Amazon Correttoを使用してみた

概要

こんにちは。

Amazon Correttoと呼ばれる、Javaの開発キットおよび実行環境を提供し、AWSから提供されております、マルチプラットフォームで本番環境に対応しています。

パフォーマンスの向上および長期サポートがされている点などの利点があります。

Javaの開発にVS CODEを使い、Extension Pack for Javaの拡張機能でJDK(Java11)以上を求められるため、Amazon Corretto 11を使用します。

Amazon Correttoでは、Java8, 11, 17が提供されております。

Amazon Corretto 11のドキュメントは以下となります。
Amazon Corretto 11 – Amazon Corretto

プロジェクト準備

Amazon CorrettoはDockerイメージが提供されておりますが、今回は、カスタムビルドし、Kubernetes環境にデプロイし、VS CODEからリモート接続で開発していきますのでプロジェクトをまず作成します。

最終的なプロジェクト構成は下記のようになります。

それでは順を追って作成していきましょう。

まずは、カスタムビルドするため、Dockerファイル等を作成していきます。

tree java

java
├── create-persistent-volume.yaml
├── create-persitent-claim.yaml
├── docker-compose
│   ├── Dockerfile
│   ├── docker-compose.yml
│   ├── id_rsa
│   └── make.sh
└── java.yaml

Dockerビルドに必要なファイル作成

まず、 docker-compose ディレクトリを作成します。

この直下に、Dockerfileを作成します。

Dockerfileでは、almalinuxをベースとして、管理者ユーザの秘密鍵を作成し、Amazon Corretto 11をダウンロードしインストールするものとなります。

この秘密鍵は、VS CODEから、コンテナに対してリモートSSH接続する際に必要になるものです。

vi Dockerfile

FROM almalinux:latest
CMD ["/sbin/init"]
RUN dnf -y install openssh-server
RUN mkdir -p ~/.ssh
RUN chmod 700 ~/.ssh
RUN ssh-keygen -t rsa -m PEM -N "" -f ~/.ssh/id_rsa
RUN mv ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys
RUN chmod 600 ~/.ssh/authorized_keys
RUN dnf -y install wget
RUN wget https://corretto.aws/downloads/latest/amazon-corretto-11-$(uname -m)-linux-jdk.rpm
RUN rpm -Uvh amazon-corretto-11-$(uname -m)-linux-jdk.rpm
RUN java -version
RUN rm -fv amazon-corretto-11-$(uname -m)-linux-jdk.rpm
RUN rm -fr /var/cache/dnf/*
RUN dnf clean all

次に、 docker-compose.yml を作成します。

vi docker-compose.yml

version: "3.5"
services:
  dev:
    image: almalinux:latest
    build: .
    container_name: amazoncorretto.dev
    hostname: amazoncorretto.dev.image
    privileged: true
    ports:
      - "2022:22"
    restart: always

次に、ビルドする為、 make.sh ファイルを作成します。

docker-compose でビルドし、タグを付与し、ビルドしたイメージを任意場所に保存後、後片付けをおこなうものとなります。

docker save 箇所で標準出力している、 /var/nfs/docker-images/almalinux-amazoncorretto.tar.gz は各自環境に置き換えてください。(ビルドしたイメージを保存する場所)

vi make.sh

#!/usr/bin/env bash
docker-compose build
#docker-compose up -d
#docker cp amazoncorretto.dev:/root/.ssh/id_rsa .
docker tag $(docker images | grep almalinux | grep latest | awk '{ print $3 }') almalinux/amazoncorretto:latest
docker save $(docker images | grep almalinux/amazoncorretto | grep latest | awk '{ printf "%s:%s", $1, $2 }') > /var/nfs/docker-images/almalinux-amazoncorretto.tar.gz
# https://qiita.com/suin/items/19d65e191b96a0079417
docker-compose down --rmi all --volumes --remove-orphans
docker rmi -f $(docker images | grep almalinux | grep latest | awk '{ print $3 }') almalinux/amazoncorretto:latest
docker rmi -f $(docker images | grep almalinux | grep none | awk '{ print $3 }')

Dockerビルド

それでは、実際に実行してみましょう。

docker-compose ディレクトリに移動し、 chmod 700 make.sh とし、実行権限を付与後、 ./make.sh とし実行します。

ビルドには書き出しも含めるのでマシンのスペック環境にも寄りますが、数分程度かかりますので気長に待ちましょう。

./make.sh 
Sending build context to Docker daemon  2.803kB
Step 1/15 : FROM almalinux:latest
latest: Pulling from library/almalinux
75898fabccbe: Pull complete 
Digest: sha256:08042694fffd61e6a0b3a22dadba207c8937977915ff6b1879ad744fd6638837
Status: Downloaded newer image for almalinux:latest
 ---> f5e7328a3824
Step 2/15 : CMD ["/sbin/init"]
 ---> Running in 367882d22c5d
Removing intermediate container 367882d22c5d
 ---> b8cdf07048f4
Step 3/15 : RUN dnf -y install openssh-server
・
・[中略]
・

無事にビルドが完了すると almalinux-amazoncorretto.tar.gz の圧縮ファイルが生成されます。

du -sh /var/nfs/docker-images/almalinux-amazoncorretto.tar.gz

802M    /var/nfs/docker-images/almalinux-amazoncorretto.tar.gz

ビルドイメージのLoad

docker load コマンドを使用し、ビルドしたイメージを読み込みます。

こちらもの数分程度かかります。

docker load --input /var/nfs/docker-images/almalinux-amazoncorretto.tar.gz

5d508b5d614b: Loading layer [==================================================>]  241.4MB/241.4MB
0e59499aa093: Loading layer [==================================================>]  41.42MB/41.42MB
5f16be9f23fe: Loading layer [==================================================>]   2.56kB/2.56kB
e23d7b61a3bd: Loading layer [==================================================>]  2.048kB/2.048kB
591d8d6f7630: Loading layer [==================================================>]  6.656kB/6.656kB
7ef56cfcea14: Loading layer [==================================================>]  4.096kB/4.096kB
f09bd89316dc: Loading layer [==================================================>]  3.584kB/3.584kB
492cebb1a935: Loading layer [==================================================>]  27.08MB/27.08MB
0c5065956e8e: Loading layer [==================================================>]  191.2MB/191.2MB
465b53674a6c: Loading layer [==================================================>]  336.1MB/336.1MB
86efcdcdc593: Loading layer [==================================================>]   2.56kB/2.56kB
177c14109b04: Loading layer [==================================================>]  1.536kB/1.536kB
df661e9fc5d9: Loading layer [==================================================>]  8.192kB/8.192kB
4fa21646a3c1: Loading layer [==================================================>]  2.711MB/2.711MB

docker images コマンドでイメージがLoadされたか確認します。

almalinux/amazoncorretto のイメージで833MB程度になっていれば問題ありません。

docker images | grep alma

almalinux/amazoncorretto                   latest     a3beaca8277b   41 minutes ago   833MB

Kubernetesマニフェスト作成

プロジェクト直下に移動し、 create-persistent-volume.yaml を作成します。

PVおよびPVCについて、以下で解説していますので、合わせてごらんください。
nfsサーバを構築しKubernetesからストレージとして利用してみた

javaのプロジェクトファイルなどは、外部NFSサーバに保存する想定です。

vi create-persistent-volume.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001
  annotations:
    volume.beta.kubernetes.io/storage-class: "slow"
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    server: 192.168.1.110
    path: /export/nfs/pv0001

次に、 create-persitent-claim.yaml を作成します。

vi create-persitent-claim.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: amazoncorretto-pv-claim
  labels:
    app: amazoncorretto-pv-vol
  annotations:
    "volume.beta.kubernetes.io/storage-class": "slow"
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

serviceとして、sshポート22番を2022番でマッピングしています。

VS CODEから接続するときは、2022番を指定し接続するようにします。

次に、先ほどビルドしたイメージを利用するマニフェストを作成します。

vi java.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: amazoncorretto-almalinux
  labels:
    app: amazoncorretto
spec:
  selector:
    matchLabels:
      app: amazoncorretto
      tier: almalinux
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: amazoncorretto
        tier: almalinux
    spec:
      containers:
      - image: almalinux/amazoncorretto:latest
        imagePullPolicy: IfNotPresent
        name: almalinux
        command:
          - "/sbin/init"
        volumeMounts:
        - name: almalinux-persistent-storage
          mountPath: /opt/nfs
        securityContext:
          allowPrivilegeEscalation: true
          capabilities: {}
          privileged: true
          readOnlyRootFilesystem: false
          seLinuxOptions: {}
      volumes:
      - name: almalinux-persistent-storage
        persistentVolumeClaim:
          claimName: amazoncorretto-pv-claim
---
apiVersion: v1
kind: Service
metadata:
  name: amazoncorretto-service
spec:
  selector:
    app: amazoncorretto
    tier: almalinux
  ports:
  - protocol: TCP
    port: 2022
    targetPort: 22

デプロイ

PV, PVC, POD, serviceを作成します。

kubectl apply -f ../java/

persistentvolume/pv0001 created
persistentvolumeclaim/amazoncorretto-pv-claim created
deployment.apps/amazoncorretto-almalinux created
service/amazoncorretto-service created

podがRunning状態、serviceが2022、pv、pvcがあることが確認できます。

service ClusterIP 10.103.23.102 に対して、2022番ポートで接続となります。

kubectl get po,pv,pvc,svc

NAME                                            READY   STATUS    RESTARTS   AGE
pod/amazoncorretto-almalinux-55b5cc8c68-gqppt   1/1     Running   0          92s

NAME                      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                             STORAGECLASS   REASON   AGE
persistentvolume/pv0001   5Gi        RWO            Recycle          Bound    default/amazoncorretto-pv-claim   slow                    92s

NAME                                            STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/amazoncorretto-pv-claim   Bound    pv0001   5Gi        RWO            slow           92s

NAME                             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/amazoncorretto-service   ClusterIP   10.103.23.102   <none>        2022/TCP   92s

POD動作確認

kubectl exec コマンドでPOD内部に入ります。

kubectl exec -it amazoncorretto-almalinux-55b5cc8c68-gqppt --tty -- bash

VS CODEで接続する際に名前解決できる必要があるのでcurlで名前解決できるか確認します。

301 Movedになれば問題ありません。

[root@amazoncorretto-almalinux-55b5cc8c68-gqppt /]# curl google.com

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>

Amazon Corretto 11がインストールされていることを確認します。

[root@amazoncorretto-almalinux-55b5cc8c68-gqppt /]# java --version

openjdk 11.0.14.1 2022-02-08 LTS
OpenJDK Runtime Environment Corretto-11.0.14.10.1 (build 11.0.14.1+10-LTS)
OpenJDK 64-Bit Server VM Corretto-11.0.14.10.1 (build 11.0.14.1+10-LTS, mixed mode)

秘密鍵が存在することを確認します。

[root@amazoncorretto-almalinux-55b5cc8c68-gqppt /]# ls -la /root/.ssh/

total 16
drwx------ 1 root root 4096 Feb 24 19:59 .
dr-xr-x--- 1 root root 4096 Feb 24 20:02 ..
-rw------- 1 root root  571 Feb 24 19:59 authorized_keys
-rw------- 1 root root 2455 Feb 24 19:59 id_rsa

秘密鍵をホストへコピー

podからログアウトし、ホストに戻ります。

docker cp コマンドでホストに秘密鍵をコピーします。

今回、対象のコンテナは k8s_almalinux_amazoncorretto-almalinux-55b5cc8c68-gqppt_default_a6c4b3e2-d2d9-4863-96ed-7e856dfa6523_0 となります。

docker ps | grep alma

11f1d7e44c5b   a3beaca8277b             "/bin/bash -c 'sleep…"   17 minutes ago      Up 17 minutes                k8s_almalinux_amazoncorretto-almalinux-55b5cc8c68-gqppt_default_a6c4b3e2-d2d9-4863-96ed-7e856dfa6523_0
5d4afa706952   k8s.gcr.io/pause:3.2     "/pause"                 17 minutes ago      Up 17 minutes                k8s_POD_amazoncorretto-almalinux-55b5cc8c68-gqppt_default_a6c4b3e2-d2d9-4863-96ed-7e856dfa6523_0

docker cp k8s_almalinux_amazoncorretto-almalinux-55b5cc8c68-gqppt_default_a6c4b3e2-d2d9-4863-96ed-7e856dfa6523_0:/root/.ssh/id_rsa ./

ホストに秘密鍵がコピーできました。

こちらの秘密鍵は、VS CODEからpodにssh接続する際に必要となります。

筆者はwindowsからpodに多段ssh接続します。

多段SSHについては以下をご参照ください。
vscodeの多段sshについて

ls -la id_rsa

-rw------- 1 dev_user dev_user 2455  2月 25 04:59 id_rsa

windowsのvs codeからpodへリモート接続

多段SSHでは、Kubernetesにまずsshし、そこから、podのseviceに対してsshします。

筆者の場合、 CLUSTER-IP 10.103.23.102 の 2022ポートなので、VS CODEの拡張機能、 Remote - SSH で使用する config の Hostnameに 10.103.23.102、Portに 2022 とします。

kubectl get svc

NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
amazoncorretto-service   ClusterIP   10.103.23.102   <none>        2022/TCP   44m

java開発環境構築

amazoncorretto-almalinux-55b5cc8c68-gqppt のPODにVS CODEから接続が完了していることを確認します。

VS CODEのターミナルから uname -n コマンドで amazoncorretto-almalinux-55b5cc8c68-gqppt になっていれば問題ありません。

VS CODEの拡張機能 Extension Pack for Java をインストールします。

その後、再度、リモートSSH接続しなおします。

nfsをマウントしている /opt/nfs ディレクトリに移動します。

その後、VS CODEのコマンドパレットにjavaと入力し、一覧に java: Create Java Project と出てくるので、クリックし、No build toolsを選択後、 /opt/nfs/ とでるので、OKを押し、HelloJavaと入力し、Enterをおします。

その後、プロジェクトが作成され、自動的にプロジェクトフォルダが開かれます。

開かれたプロジェクトで src/App.java を開き、VS CODEの実行とデバックより実行とデバックをクリックし、実行します。(javaを選択します。)

実行後、下記のように、 Hello, World! とでれば開発環境のできあがりです。

cd /opt/nfs/HelloJava ; /usr/bin/env /usr/lib/jvm/java-11-amazon-corretto/bin/java -agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=localhost:45735 -cp /opt/nfs/HelloJava/bin App 
Hello, World!

まとめ

どうでしたでしょうか。

カスタムビルドしたイメージにはjava開発環境が入っているので、他環境で動かした時にすぐに開発することができます。

次回は、本記事で作成した環境からAWSリソースを操作してみたいと思います。