Amazon Web Services ブログ

AWS App2Container を利用して Java および .NET アプリケーションをリモートでモダナイズする

この記事は、Modernize Java and .NET applications remotely using AWS App2Container を翻訳したものです。

本投稿は、Senior Technical Account Manager の Suresh Pathakamuri と Vijay K Sikha により寄稿されました。

AWS App2Container の公開以来、お客様からは Windows や Linux ホスト上で動作する Java や .NET アプリケーションの移行をリモートで管理できる機能を求める声が寄せられてきました。App2Container (A2C) のバージョン 1.2 からは、アプリケーションサーバーに A2C ソフトウェアをインストールすることなく、ワークロードのコンテナ化を実現できるようになりました。また、リモート実行機能により、オンプレミスのデータセンターで稼働するアプリケーションのコンテナ化が可能になります。ユーザーは、アプリケーションサーバーに対して中央管理された Windows または Linux ホスト上で App2Container を実行してコンテナ化し、Amazon Elastic Container Service (Amazon ECS) または Amazon Elastic Kubernetes Service (Amazon EKS) にデプロイできるようになりました。

このブログでは、Cloud9 環境にインストールされた App2Container を使って EC2 インスタンス上で動作する Java Spring Boot アプリケーションをコンテナ化し、コンテナ化されたアプリケーションを Amazon EKS クラスタにデプロイします。まず AWS Cloud9 環境に A2C をインストールし、Java Spring Boot アプリケーションを実行している EC2 インスタンスを設定します。EC2 インスタンスは、A2C のリモートサーバー (Cloud9 環境) からネットワーク接続された、オンプレミスのデータセンターで稼働するアプリケーションサーバーと想定できます。A2C は、アプリケーションサーバーを解析し、アプリケーションのモダナイゼーションに必要な成果物を生成します。その後、コンテナ化された Spring Boot アプリケーションのバージョンが、新しい Amazon EKS クラスタにデプロイされます。

App2Container をリモートで実行するための設定

開始するには、Amazon Linux 2 オペレーティングシステムで Cloud9 環境を作成します。AdministratorAccess ポリシーを持つ新しい IAM ロールを作成し、それを Cloud9 インスタンスにアタッチして、この環境の AWS マネージドな認証情報を無効にします。ここにリストされている最初のステップは、Cloud9 環境の作成と IAM ロールの設定に使用できます。このブログの残りの部分では、App2Container のリモートサーバーとして機能する Cloud9 環境で実行するコマンドがあります。Cloud9 を使用しない場合は、独自の EC2 またはオンプレミス Linux 環境を使用できます。
App2Container を使用する際の細かい権限のオプションについては、「Identity and access management in App2Container」を参照してください。

Cloud9 ホストにログインし、App2Container を Cloud9 環境にインストールして初期化します。Docker サービスをインストールし、アーティファクトを保存するための S3 バケットを作成します。今回のデモでは us-east-1 リージョンを使用していますが、AWS_DEFAULT_REGION の値をお好みのリージョンに変更してください。

$ export AWS_DEFAULT_REGION=us-east-1

$ cd /tmp
$ curl -o AWSApp2Container-installer-linux.tar.gz https://app2container-release-us-east-1.s3.us-east-1.amazonaws.com/latest/linux/AWSApp2Container-installer-linux.tar.gz
$ tar xvf AWSApp2Container-installer-linux.tar.gz
$ echo y |sudo ./install.sh

以下を実行して、App2Container のインストールを検証します。なお、App2Container のコマンドは、root 権限を持つユーザーで実行する必要があります。

$ sudo app2container --version

コンテナ化したいアプリケーションが格納されているサーバー上で App2Container ツールを使用するには、同サーバーに Docker Engine がインストールされている必要があります。以下のコマンドに従って Docker Engine をインストールし、サービスを開始・有効化してください。
注: Cloud9 を使用している場合は、以下の手順をスキップできます。Cloud9 環境では Docker Engine がデフォルトでインストールされています。

$ sudo yum install docker -y
$ sudo systemctl start docker
$ sudo systemctl enable docker

App2Container で生成したアーティファクトや AWS CloudFormation テンプレートを保存するためには、S3 バケットが必要です。以下のように S3 バケットを作成します。Amazon S3 バケット名はグローバルに一意である必要があります。もし「Bucket name already exists」または「BucketAlreadyExists」というエラーが出た場合は、別のバケット名を使ってバケットを作成する必要がありますので、次に示すようにバケット名に日付を追加して、一意の名前にします。


$ aws s3 mb s3://a2c-remote-`date +%s`
make_bucket: a2c-remote-1617832770

$ aws s3 ls |grep a2c-remote
2021-04-07 21:59:31 a2c-remote-1617832770

Cloud9 インスタンスにアタッチされている EBS ボリュームのサイズを 20 GB に変更します。これは、後のステップで生成されるアーティファクトのための十分なストレージを確保するためです。aws configure コマンドを実行してデフォルトのリージョン名を設定し、このステップではリージョンのみを指定し、他の入力は省略します。

App2Container CLI の初期化を一度だけ実行するために init コマンドを実行します。前のステップで作成した S3 バケット名が入力されていることを確認してください。これは、次のステップでのアプリケーションアーティファクトはそのバケットに保存されるためです。

$ sudo app2container init
Workspace directory path for artifacts[default: /root/app2container]: 
Use AWS EC2 Instance profile 'arn:aws:iam::<Account ID>:instance-profile/<Role Name>' configured with this instance? (Y/N)[default: y]:  
Which AWS Region to use?[default: us-east-1]: 
Optional S3 bucket for application artifacts: a2c-remote-1617832770
Report usage metrics to AWS? (Y/N)[default: y]: 
Automatically upload logs and App2Container generated artifacts on crashes and internal errors? (Y/N)[default: y]: 
Require images to be signed using Docker Content Trust (DCT)? (Y/N)[default: n]: 
Configuration saved
$

Java Spring Boot アプリケーションを実行するアプリケーションサーバーの設定

次のセクションでは、AWS CLI を使用して EC2 インスタンス上で Java Spring Boot アプリケーションを設定および実行します。

以下のコマンドを実行して SSH キーを作成し、AWS アカウントの Secrets Manager にインポートしてください。このキーは、A2C ツールがリモートサーバーからアプリケーションサーバーへの認証に使用します。詳細は、A2C ドキュメントの「Manage secrets for AWS App2Container」を参照してください。

$ ssh-keygen -t rsa -f ~/.ssh/a2crsakey -q -P ""
$ aws ec2 import-key-pair --key-name "A2CKEY" \
--public-key-material fileb://~/.ssh/a2crsakey.pub
$ B64KEY=$(base64 ~/.ssh/a2crsakey)
$ echo -e $'{\n "username": "ec2-user",\n "key": "'$B64KEY'"\n}' >> a2ckey.json
$ aws secretsmanager create-secret --name a2ckey --description "A2C secrets" --secret-string file://a2ckey.json

以下のコマンドは、Spring Boot アプリケーションをインストールするためのユーザーデータのシェルスクリプト、アプリケーションホストにアクセスするためのセキュリティグループ、およびユーザーデータのシェルスクリプトを使用してサンプルの Java アプリケーションを実行する EC2 インスタンスを作成します。この例のセキュリティグループでは、ポート 22 と 8080 が全世界に公開されていますが、アプリケーション環境では特定の IP に制限することをお勧めします。


$ echo "User Data creation to install springboot application"
$ cat <<EOF >appuserdata.sh
#!/bin/bash
yum -y install git maven
git clone https://github.com/aws-samples/kubernetes-for-java-developers.git
cd kubernetes-for-java-developers/app
mvn spring-boot:run &
EOF

$ echo "Below commands creates security group and ingress rules"
$ aws ec2 create-security-group --group-name A2CSecurityGroup --description "A2C security group"
$ aws ec2 authorize-security-group-ingress --group-name A2CSecurityGroup \
--protocol tcp --port 22 --cidr 0.0.0.0/0
$ aws ec2 authorize-security-group-ingress --group-name A2CSecurityGroup \
--protocol tcp --port 8080 --cidr 0.0.0.0/0

$ echo "Below commands creates ec2 host with springboot application installed"
$ aws ec2 run-instances \
--image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 \
--count 1 --instance-type t2.medium --key-name A2CKEY \
--block-device-mapping "[ { \"DeviceName\": \"/dev/xvda\", \"Ebs\": { \"VolumeSize\": 32 } } ]" \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=APPHost}]' \
--security-groups A2CSecurityGroup \
--user-data file://appuserdata.sh

Spring Boot アプリケーションを検証するには、AWS CLI または AWS マネジメントコンソールからアプリケーションサーバーの IP アドレスを取得します。以下のコマンドを実行して、ホストの IP アドレスを取得し、アプリケーションサーバーをテストします。curl コマンドを実行すると、「Hello」というレスポンスが返ってくるはずです。curl コマンドに応答するまで、インスタンスが実行状態になるのに数分かかる場合があります。

$ aws ec2 describe-instances --filter "Name=tag:Name,Values=APPHost" \
--query "Reservations[*].Instances[*].[PublicIpAddress, Tags[?Key=='Name'].Value|[0]]" \
--output text
$ curl http://<IP Address>:8080/hello - Note: IP address is masked in command for security reasons.
Hello

App2Container リモート機能を使用してアプリケーションをコンテナ化する

以下のコマンドを実行して、Cloud9 からのアプリケーションサーバー接続を設定します。アプリケーションサーバーの IP または FQDN と、SSH キーを保存するためのシークレットの ARN が必要になります。Secrets Manager から SSH キーの ARN を取得するコマンドを以下に示します。2 つ目のコマンドは、Java アプリケーションが実行されている EC2 インスタンスを取得します。

$ aws secretsmanager list-secrets --query "SecretList[?Name=='a2ckey']"
$ aws ec2 describe-instances --filter "Name=tag:Name,Values=APPHost" \
--query "Reservations[*].Instances[*].[PublicIpAddress, Tags[?Key=='Name'].Value|[0]]" \
--output text
$ sudo app2container remote configure
Server IP address: <AppServerIP>
Server FQDN (Fully Qualified Domain Name): 
Authentication method to be used (key/cert)[default: key]: 
Secret ARN for remote connection credentials: arn:aws:secretsmanager:us-east-1:xxxxxxxxxxxx:secret:a2c-remote-1-ezY0tZ
Continue to configure another server? (y/N)[default: n]: 
? Configure successful, you can view hosts config file at: /root/.app2container-config/remote_hosts.conf

remote inventory コマンドを実行すると、ホスト上で動作している Java アプリケーションを確認することができます。各アプリケーションは、一意のアプリケーション ID で識別されます。インベントリファイルに記載されているアプリケーション ID を書き留め、アプリケーション ID が使用される以降の手順にて置き換えます。

$ sudo app2container remote inventory --target <AppServerIP>
✔ Server inventory has been stored under /root/app2container/remote/<AppServerIP>/inventory.json
? Remote inventory retrieved successfully

remote analyze コマンドは、ホスト上で実行されているアプリケーションのレポートを生成します。analysis.json を確認し、アプリケーションの要件に応じて編集することができます。コンテナのパラメータや解析情報は必要に応じて更新することができます。このデモでは、analyze コマンドで作成されたデフォルトの設定を使用します。

$ sudo app2container remote analyze --application-id  java-generic-dc310dd41a0a --target <AppServerIP>
? Analysis successful for application java-generic-dc310dd41a0a

? Next Steps:
1. View the application analysis file at /root/app2container/remote/<AppServerIP>/java-generic-dc310dd41a0a/analysis.json.
2. Edit the application analysis file as needed.
3. Start the extraction process using the following command: app2container remote extract --target <AppServerIP> --application-id java-generic-dc310dd41a0a

remote extract コマンドは、A2C のリモートサーバーである Cloud9 環境上の指定されたアプリケーションサーバーのアプリケーションアーカイブを生成します。このステップは完了するまでに数分かかります。

$ sudo app2container remote extract --application-id  java-generic-dc310dd41a0a --target <AppServerIP>
? Extraction successful for application java-generic-dc310dd41a0a

? Next Step:
1. Please initiate containerization using "app2container containerize --input-archive /root/app2container/remote/<AppServerIP>/java-generic-dc310dd41a0a/java-generic-dc310dd41a0a-extraction.tar"

次に containerize コマンドを使って、実行中のアプリケーションの Docker イメージを生成します。

$ sudo app2container containerize --input-archive /root/app2container/remote/<AppServerIP>/java-generic-dc310dd41a0a/java-generic-dc310dd41a0a-extraction.tar
✔ AWS prerequisite check succeeded
✔ Docker prerequisite check succeeded
✔ Extracted input archive
✔ Entry file generated
✔ Dockerfile generated under /root/app2container/java-generic-dc310dd41a0a/Artifacts
✔ Generated dockerfile.update under /root/app2container/java-generic-dc310dd41a0a/Artifacts
✔ Generated deployment file at /root/app2container/java-generic-dc310dd41a0a/deployment.json
? Containerization successful. Generated docker image java-generic-dc310dd41a0a

? You are all set to test and deploy your container image.

Next Steps:
1. View the container image with "docker images" and test the application with "docker run -it java-generic-dc310dd41a0a".
2. When you are ready to deploy to AWS, please edit the deployment file as needed at /root/app2container/java-generic-dc310dd41a0a/deployment.json.
3. Generate deployment artifacts using "app2container generate app-deployment --application-id java-generic-dc310dd41a0a".

docker images コマンドで Docker イメージが正常に作成されたことを確認します。

$ sudo docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
java-generic-dc310dd41a0a   latest              ae38e940aed9        49 seconds ago      4.27GB
amazonlinux                 2                   935e8db88df5        2 days ago     

App2Container は、Docker イメージの作成だけでなく Amazon ECS や Amazon EKS でアプリケーションをモダナイズするために必要なアーティファクトも作成します。このデモでは、Amazon EKS を使用します。Amazon EKS の設定のために、以下のように (エディタなどを使用して) ファイルを更新します。デプロイファイルで、EKS のための createEksArtifacts を True に、ECS のための createEcsArtifacts を False に変更してください。

       "ecsParameters": {
              "createEcsArtifacts": false,
              ....
              ....
       "eksParameters": {
              "createEksArtifacts": true,
              "stackName": "a2c-java-generic-d15cb42f23d9-EKS",
              "reuseResources": {
                     "vpcId": "",
                     "reuseExistingA2cStack": {
                            "cfnStackName": ""
                     },
                     "sshKeyPairName": ""
              },
              "gMSAParameters": {
                     "domainSecretsArn": "",
                     "domainDNSName": "",
                     "domainNetBIOSName": "",
                     "createGMSA": false,
                     "gMSAName": ""
              }
       }

App2Container リモート機能を使用してアプリケーションをデプロイする

次に、--deploy フラグを付けた generate app-deployment コマンドを使用します。このコマンドは Docker イメージを格納する Amazon ECR リポジトリを作成し、CloudFormation テンプレートを S3 にアップロードして、テンプレートをデプロイします。CloudFormation スタックは、EC2 をワーカーノードとする EKS クラスターを作成し、EKS クラスターに pod/service をデプロイします。AWS マネジメントコンソールにログインして、このステップで使用した --deploy の CloudFormation サービスのステータスを追跡することができます。deploy フラグをスキップして CloudFormation テンプレートを編集することで、このアプリケーションをアカウント内の既存の EKS クラスターにデプロイすることができます。コンテナのデプロイ設定に関するこのドキュメントには、デプロイ前に必要に応じて変更できるパラメータの詳細が記載されています。

$ sudo app2container generate app-deployment  --application-id java-generic-dc310dd41a0a --deploy
✔ AWS prerequisite check succeeded
✔ Docker prerequisite check succeeded
✔ Created ECR Repository
✔ Uploaded CloudFormation resources to S3 Bucket: a2c-remote-1614362000
✔ Generated CloudFormation Master template at: /root/app2container/java-generic-dc310dd41a0a/EksDeployment/amazon-eks-entrypoint-new-vpc.yaml
✔ Initiated CloudFormation stack creation. This may take a few minutes. To track progress, open the AWS CloudFormation console.
? Deployment successful for application java-generic-dc310dd41a0a

? You're all set to use AWS CloudFormation to manage your application stack.

Successfully created EKS stack a2c-java-generic-dc310dd41a0a-EKS.  Check the  AWS CloudFormation Console for details.
We have also set up your kubectl config to access your cluster at: /root/.kube/config

Next Steps:
1. Setup a pipeline for your application stack using:

    app2container generate pipeline --application-id java-generic-dc310dd41a0a
$ 

最後に、EKS に Java アプリケーションをデプロイします。ロードバランサーエンドポイントはアプリケーションサービス用にデプロイされており、エンドポイント名は AWS マネジメントコンソールの EC2 ページで見つけるか、以下のように kubectl get services コマンドを実行することで確認できます。

$ sudo curl --silent --location -o /usr/local/bin/kubectl \
   https://amazon-eks.s3.us-west-2.amazonaws.com/1.17.11/2020-09-18/bin/linux/amd64/kubectl
$ sudo chmod +x /usr/local/bin/kubectl
$ sudo aws eks update-kubeconfig --name <EKS Clustername>

$ sudo /usr/local/bin/kubectl get pods
NAME                                                    READY   STATUS    RESTARTS   AGE
java-generic-dc310dd41a0a-deployment-867b54f57f-t6gtq   1/1     Running   0          41m

$ sudo /usr/local/bin/kubectl get services
NAME                                TYPE           CLUSTER-IP     EXTERNAL-IP                                                               PORT(S)          AGE
java-generic-dc310dd41a0a-service   LoadBalancer   172.20.14.56   <DNS Name>.<region>.elb.amazonaws.com   8080:31043/TCP   41m
kubernetes                          ClusterIP      172.20.0.1     <none>                                                                    443/TCP          57m

以下のように、curl ユーティリティーまたは Web ブラウザからテストすることができます。DNS 名とリージョンはセキュリティ上の理由でマスクされています。前のセクションの出力にある正しい値に置き換えてください。

$ curl http://*<DNS Name>**.<region>*.elb.amazonaws.com:8080/hello
Hello

App2Container のリモート実行機能を使用して、スタンドアロンホスト上で実行されている Java Spring Boot アプリケーションを Amazon EKS に正常に移植しました。同様の作業を Windows サーバー上で動作する .NET アプリケーションに対して行う場合、ログイン認証情報は Secrets Manager に保存し、残りのプロセスは同じままにします。ここでは、Linux ワーカーホストとして機能するワーカーマシンとして Cloud9 環境を使用しましたが、Windows Server 2016 または 2019 からでも同様の作業を行うことができます。

AWS App2Container は無料で提供されています。EC2、ECS、EKS、S3 などの AWS サービスの実際の使用量に対してのみお支払いいただきます。詳細については、App2Container の FAQsApp2Container のドキュメント、およびその他の AWS ブログを参照してください。App2Container ツールに関する技術的な質問や機能のリクエストがある場合は、app2container-support@amazon.com までメールでお問い合わせください。

翻訳はソリューションアーキテクト 杉本 晋吾 が担当しました。原文はこちらです。