使用AWS App2Container将现有应用程序转化为容器化应用程序

首先

2020年7月1日,AWS发布了一款名为App2Container的工具,用于将现有的.NET和Java应用程序容器化。

AWS App2Container 是一项新发布的服务,它可以将应用程序容器化并迁移到 AWS 云上。

AWS App2Container将启动后的应用程序及其依赖关系打包成容器映像,生成ECS任务和Kubernetes Pod定义。同时,还可以创建用于在AWS上部署这些资源的CloudFormation模板以及用于CI/CD流水线的模板。

AWS App2Container可以免费使用,但对部署在AWS上的资源会产生常规费用。我分别将Java应用程序容器化,并在ECS on Fargate和EKS上进行了部署。

前提条件 (Qian2 ti2 tiao2 jian4)

以下是Java应用程序的环境前提条件。

受支持的Java应用框架

    • Tomcat

 

    • Spring Boot

 

    • JBoss (standalone mode)

 

    • Weblogic (standalone mode)

 

    Websphere (standalone mode)

支持的Linux发行版。

    • Ubuntu

 

    • CentOS

 

    • RHEL

 

    Amazon Linux

工作环境必须满足以下条件。关于这些安装和设置步骤,将不再详述。

    • AWS CLI がインストール済みであること

 

    • Docker Engine のインストール済みであること

 

    • サーバーの root アクセス権があること

 

    • tar コマンドが利用可能であること

 

    ストレージに 20GB 以上の空き容量があること

IAM用户需要的权限在以下文件中有所记录。在部署容器化应用程序时,看起来需要先具备AdministratorAccess权限。

使用 App2Container 进行身份验证和访问管理
https://docs.aws.amazon.com/app2container/latest/UserGuide/iam-a2c.html

本次在Amazon Linux 2上启动并验证了一个Spring Boot应用程序。

应用准备完成

使用Spring Boot CLI准备Hello World应用程序。
步骤如下所述。
https://spring.pleiades.io/spring-boot/docs/current/reference/html/spring-boot-cli.html

@RestController
class WebApplication {

    @RequestMapping("/")
    String home() {
        "Hello World!"
    }

}

打开应用程序

$ spring run hello.groovy

我会确保能够正常响应。

$ curl localhost:8080
Hello World!

安装 App2Container

安裝

下载并解压安装包。

$ 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
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  104M  100  104M    0     0  8360k      0  0:00:12  0:00:12 --:--:-- 9605k

$ sudo tar xvf AWSApp2Container-installer-linux.tar.gz
install.sh
README
termsandconditions.txt
security/
security/app2container.sig
security/app2container.cert
AWSApp2Container.tar.gz

请运行 install.sh 脚本。
需要您同意使用条款。

$ sudo ./install.sh

Determining user ...
Determining Installer Path ...
The AWS App2Container tool is licensed as "AWS Content" under the terms and conditions of the AWS Customer Agreement, located at https://aws.amazon.com/agreement and the Service Terms, located at https://aws.amazon.com/service-terms. By installing, using or accessing the AWS App2Container tool, you agree to such terms and conditions. The term "AWS Content" does not include software and assets distributed under separate license terms (such as code licensed under an open source license).
Do you accept the terms and conditions above? (y/n): y
Installing AWS App2Container ...
~~以降省略~~
Installation of AWS App2Container completed successfully!
You are currently running version 1.0.0.
To get started, run 'sudo app2container init'
AWS App2Container was installed under /usr/local/app2container/AWSApp2Container.

确认安装正常。

$ sudo app2container --version
app2container version 1.0.0

最初的设定

使用 init 命令进行初始化设置。
内容如所述,但可以指定与容器化相关的存储目录以及要使用的 AWS CLI 配置文件。
如果要将艺术品存储在 S3 存储桶中(可选),则在使用 App2Container 进行 AWS 环境部署时需要指定。

$ sudo app2container init
Workspace directory path for artifacts[default: /root/app2container]:
AWS Profile (configured using 'aws configure --profile')[default: default]:
Optional S3 bucket for application artifacts: <your_bucket_name>
Report usage metrics to AWS? (Y/N)[default: y]: N
Require images to be signed using Docker Content Trust (DCT)? (Y/N)[default: n]: N
Configuration saved

应用容器化

对现有应用程序进行分析

使用”inventory”命令可列出当前正在运行的应用程序。
在以下示例中,”java-generic-65424cc9″是应用程序ID,
在后续的命令执行中需要进行指定。

$ sudo app2container inventory
{
                "java-generic-65424cc9": {
                                "processId": 2493,
                                "cmdline": "/usr/lib/jvm/java-11-openjdk-11.0.7.10-4.amzn2.0.1.x86_64/bin/java ... /usr/local/bin:/usr/local/lib/spring-boot-cli-2.3.1.RELEASE.jar org.springframework.boot.loader.JarLauncher run ./hello.groovy ",
                                "applicationType": "java-generic"
                }
}

执行analyze命令后,analysis.json会被保存在在init时指定的artifact目录中。该文件描述了应用程序运行所需的依赖关系,并可以根据需要手动修改值。

$ sudo app2container analyze --application-id java-generic-65424cc9
✔ Created artifacts folder /root/app2container/java-generic-65424cc9
✔ Generated analysis data in /root/app2container/java-generic-65424cc9/analysis.json
? Analysis successful for application java-generic-65424cc9

? Next Steps:
1. View the application analysis file at /root/app2container/java-generic-65424cc9/analysis.json.
2. Edit the application analysis file as needed.
3. Start the containerization process using this command: app2container containerize --application-id java-generic-65424cc9
分析.json 的例子(点击展开)分析.json
{
“a2CTemplateVersion”: “1.0”,
“createdTime”: “2020-07-04 09:31:254”,
“containerParameters”: {
“_comment1”: “*** EDITABLE: 下面的部分可以根据应用程序要求进行编辑。请参阅下面的analysisInfo部分获取有关应用程序的详细信息。***”,
“imageRepository”: “java-generic-65424cc9”,
“imageTag”: “latest”,
“containerBaseImage”: “amazonlinux:2”,
“appExcludedFiles”: [],
“appSpecificFiles”: [],
“applicationMode”: false,
“logLocations”: [],
“enableDynamicLogging”: false,
“dependencies”: []
},
“analysisInfo”: {
“_comment2”: “*** NON-EDITABLE: 分析结果 ***”,
“processId”: 2493,
“appId”: “java-generic-65424cc9”,
“userId”: “1001”,
“groupId”: “1001”,
“cmdline”: [
“/usr/lib/jvm/java-11-openjdk-11.0.7.10-4.amzn2.0.1.x86_64/bin/java”,
“-cp”,
“/usr/local/bin:/usr/local/lib/spring-boot-cli-2.3.1.RELEASE.jar”,
“org.springframework.boot.loader.JarLauncher”,
“run”,
“./hello.groovy”
],
“osData”: {
“ANSI_COLOR”: “0;33”,
“CPE_NAME

容器化

您可以使用 containerize 命令来将应用程序容器化。
在此过程中,必须设置适当的 AWS CLI 凭据信息。
(如果使用 sudo 执行命令,则需设置为 root 用户配置的配置文件)。
目前,即使在 EC2 实例配置了实例配置文件,似乎仍不使用 IAM 角色的临时凭据,
因此我们需要单独设置访问密钥。

$ sudo app2container containerize --application-id java-generic-65424cc9
✔ AWS prerequisite check succeeded
✔ Docker prerequisite check succeeded
✔ Extracted container artifacts for application
✔ Entry file generated
✔ Dockerfile generated under /root/app2container/java-generic-65424cc9/Artifacts
✔ Generated dockerfile.update under /root/app2container/java-generic-65424cc9/Artifacts
✔ Generated deployment file at /root/app2container/java-generic-65424cc9/deployment.json
? Containerization successful. Generated docker image java-generic-65424cc9

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

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

使用containerize命令会在执行generate app-deployment命令时生成所需的deployment.json、Dockerfile和容器镜像等内容。

$ sudo tree /root/app2container/java-generic-65424cc9/
/root/app2container/java-generic-65424cc9/
├── Artifacts
│   ├── ContainerFiles.tar ★アプリケーション実行の依存関係をまとめた tar
│   ├── Dockerfile 
│   ├── Dockerfile.update ★ 作成されたイメージをベースイメージとした Dockerfile のサンプル
│   ├── entryfile ★ コンテナ起動時の CMD 
│   └── excludedFiles ★ コンテナ化時に除外されたファイルのリスト
├── analysis.json
└── deployment.json
以下是Dockerfile的示例(展开后可点击查看):从amazonlinux:2开始
维护者AWS
工作目录为/
# 复制入口文件
复制entryfile /entryfile
# 预安装软件包
RUN yum -y install tar && yum -y install gzip && yum -y install shadow-utils.x86_64
# 添加并解压Tar文件
COPY ContainerFiles.tar /
RUN tar xvfP /ContainerFiles.tar –directory / –skip-old-files –same-owner –ignore-failed-read && rm -rf /ContainerFiles.tar
# 按照下面的示例更新文件# 复制[“generic_config_file”, “/root/app2container/java-generic-65424cc9/Artifacts/generic_config_file”]# 环境变量
ENV HOME /home/ssm-user
ENV JAVA_HOME /usr/lib/jvm/java-11-openjdk-11.0.7.10-4.amzn2.0.1.x86_64
ENV PWD /home/ssm-user
ENV TERM xterm-256color
ENV LANG C.UTF-8
ENV OLDPWD /usr/local
ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
ENV SHLVL 1
ENV SPRING_HOME /usr/local
# 暴露端口
EXPOSE 8080
# 用户和用户组
RUN groupadd -f -r -g 1001 ssm-user
RUN id -u ssm-user > /dev/null 2>&1 || useradd -r -g 1001 -u 1001 ssm-user
USER ssm-user:ssm-user
工作目录为/home/ssm-user
# 镜像入口点
CMD /entryfile

deployment.json可以手动编辑。
关于ECS的参数,默认设置为cpu:2,memory:4096,并且似乎会被保留为Fargate任务执行时的资源,所以根据需要可能需要进行更改。

deployment.json 的例子 (点击展开)deployment.json
{
“a2CTemplateVersion”: “1.0”,
“applicationId”: “java-generic-65424cc9”,
“imageName”: “java-generic-65424cc9”,
“exposedPorts”: [
{
“localPort”: 8080,
“protocol”: “tcp6”
}
],
“environment”: [],
“ecrParameters”: {
“ecrRepoTag”: “latest”
},
“ecsParameters”: {
“createEcsArtifacts”: true,
“ecsFamily”: “java-generic-65424cc9”,
“cpu”: 2,
“memory”: 4096,
“dockerSecurityOption”: “”,
“enableCloudwatchLogging”: false,
“publicApp”: true,
“stackName”: “a2c-java-generic-65424cc9-ECS”,
“reuseResources”: {
“vpcId”: “”,
“cfnStackName”: “”,
“sshKeyPairName”: “”
},
“gMSAParameters”: {
“domainSecretsArn”: “”,
“domainDNSName”: “”,
“domainNetBIOSName”: “”,
“createGMSA”: false,
“gMSAName”: “”
}
},
“eksParameters”: {
“createEksArtifacts”: false,
“stackName”: “a2c-java-generic-65424cc9-EKS”,
“reuseResources”: {
“vpcId”: “”,
“cfnStackName”: “”,
“sshKeyPairName”: “”
}
}
}

在这个阶段,由于容器镜像已经创建,您也可以在本地执行并进行验证。
我认为这是为了再现当前运行中的环境,但镜像的大小相当可观。

$ sudo docker image ls
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
java-generic-65424cc9   latest              d7843b85b3b9        About an hour ago   3.95GB
amazonlinux             2                   fa0a6a710ca7        3 days ago          163MB

$ sudo docker run --rm -d -p 8080:8080 java-generic-65424cc9:latest
34e6266424e130f0b6fcb6213547cc7b744123b24805db37bea3e4da9edc094c

$ sudo docker ps
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                    NAMES
34e6266424e1        java-generic-65424cc9:latest   "/bin/sh -c /entryfi…"   6 seconds ago       Up 5 seconds        0.0.0.0:8080->8080/tcp   vigilant_lederberg

$ curl http://localhost:8080
Hello World!

应用程序的部署

创建用于部署的资源

通过使用 generate app-deployment 命令,会生成用于将应用程序部署到 AWS 的各种资源,如 CloudFormation 模板。
通过添加 –deploy 选项,可以直接执行部署,但在这里我们先只执行生成工件的步骤。

$ sudo app2container generate app-deployment --application-id java-generic-65424cc9
✔ AWS prerequisite check succeeded
✔ Docker prerequisite check succeeded
✔ Created ECR Repository
✔ Registered ECS Task Definition with ECS
✔ Uploaded CloudFormation resources to S3 Bucket: <your_bucket_name>
✔ Generated CloudFormation Master template at: /root/app2container/java-generic-65424cc9/EcsDeployment/ecs-master.yml
? ECS CloudFormation templates and additional deployment artifacts generated successfully for application java-generic-65424cc9

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

Next Steps:
1. Edit the CloudFormation template as necessary.
2. Create an application stack using the AWS CLI or the AWS Console. AWS CLI command:

        aws cloudformation deploy --template-file /root/app2container/java-generic-65424cc9/EcsDeployment/ecs-master.yml --capabilities CAPABILITY_NAMED_IAM --stack-name a2c-java-generic-65424cc9-ECS

3. Set up a pipeline for your application stack using "app2container:

        app2container generate pipeline --application-id java-generic-65424cc9"

当执行成功时,会在艺术品目录中放置用于部署ECS的任务定义、CloudFormation的主模板和管道定义文件。
默认情况下,不会创建针对EKS的资源,请参考文章的后半部分。

由于CloudFormation生成了嵌套堆栈,因此其余的模板会在初始化时上传到指定的S3存储桶中。

$ sudo tree /root/app2container/java-generic-65424cc9/
/root/app2container/java-generic-65424cc9/
├── Artifacts
│   ├── ContainerFiles.tar
│   ├── Dockerfile
│   ├── Dockerfile.update
│   ├── entryfile
│   └── excludedFiles
├── EcsDeployment
│   └── ecs-master.yml ★ CloudForamtion テンプレート
├── analysis.json
├── deployment.json
├── pipeline.json ★ パイプライン作成用定義ファイル
└── taskDef.json ★ ECS用タスク定義

$ aws s3 ls s3://<your_bucket_name>/a2c-<application-id>/ecs/subtemplates/
2020-07-04 11:58:23      12258 ecs-cluster.yml
2020-07-04 11:58:23       2327 ecs-dns.yml
2020-07-04 11:58:24      16521 ecs-gmsa-automation-doc.yml
2020-07-04 11:58:24       2545 ecs-gmsa-execute.yml
2020-07-04 11:58:24       7216 ecs-gmsa-iam-roles.yml
2020-07-04 11:58:24       6112 ecs-gmsa-lambda-functions.yml
2020-07-04 11:58:24       3713 ecs-gmsa.yml
2020-07-04 11:58:24      16909 ecs-lb-webapp.yml
2020-07-04 11:58:24      19955 ecs-master.yml
2020-07-04 11:58:24      10882 ecs-private-app.yml
2020-07-04 11:58:24       9586 ecs-public-load-balancer.yml
2020-07-04 11:58:24       3377 ecs-vpc.yml

此外,在此时,任务定义已自动注册到 ECS,并且镜像已推送到 ECR。

在Fargate上部署ECS

使用生成的 ecs-master.yml 文件来执行应用部署命令。

$ sudo aws cloudformation deploy --template-file /root/app2container/java-generic-65424cc9/EcsDeployment/ecs-master.yml --capabilities CAPABILITY_NAMED_IAM --stack-name a2c-java-generic-65424cc9-ECS

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - a2c-java-generic-65424cc9-ECS

向创建的 ELB 发送请求后,收到了一条消息。

$ aws cloudformation describe-stacks --stack-name a2c-java-generic-65424cc9-ECS --query 'Stacks[].Outputs[2]'
[
    {
        "ExportName": "a2c-java-generic-65424cc9-ECS-PublicLoadBalancerDNSForCLIOutput",
        "OutputKey": "PublicLoadBalancerDNSName",
        "OutputValue": "a2c-j-Publi-XXXXXXXXXXXX-111111111.ap-northeast-1.elb.amazonaws.com"
    }
]

$ curl http://a2c-j-Publi-XXXXXXXXXXXX-111111111.ap-northeast-1.elb.amazonaws.com
Hello World!

与为容器设计的应用程序相比,需要进行充分预先验证,并且可能存在运营等方面的挑战,但只需要几个步骤就可以完成容器化和部署到ECS on Fargate,这非常具有吸引力。

创建 CI/CD 流水线

创建用于部署的资源

使用generate pipeline,您可以在AWS CodePipeline中创建CI/CD流水线并生成所需的工件。
您也可以像使用app-deployment一样使用–deploy选项。

要执行 generate pipeline,需要在生成的 pipeline.json 的 releaseInfo 中添加部署的 ECS 集群名和服务名。

{
        "a2CTemplateVersion": "1.0",
        "sourceInfo": {
                "CodeCommit": {
                        "repositoryName": "a2c-java-generic-65424cc9-ecs",
                        "branch": "master"
                }
        },
        "imageInfo": {
                "image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/java-generic-65424cc9:latest"
        },
        "releaseInfo": {
                "ECS": {
                        "beta": {
                                "clusterName": "",
                                "serviceName": "",
                                "enabled": false
                        },
                        "prod": {
                                "clusterName": "a2c-java-generic-65424cc9-ECS-Cluster",
                                "serviceName": "a2c-java-generic-65424cc9-ECS-LBWebAppStack-XXXXXXXXXXXX-Service-YYYYYYYYYYYY",
                                "enabled": true
                        }
                }
        }
}

在这里,我们指定了刚刚部署的资源作为“prod”。
执行生成流水线时,将创建用于部署 CodePipline 的 CloudFormation 和 CodeDeploy 的 buildspec.yml 模板。

$ sudo app2container generate pipeline --application-id java-generic-65424cc9
✔ Created CodeCommit repository
✔ Generated buildspec file(s)
✔ Generated CloudFormation templates
✔ Committed files to CodeCommit repository
? Pipeline resource template generation successful for application java-generic-65424cc9

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

Next Steps:
1. Edit the CloudFormation template as necessary.
2. Create a pipeline stack using the AWS CLI or the AWS Console. AWS CLI command:

        aws cloudformation deploy --template-file /root/app2container/java-generic-65424cc9/Artifacts/Pipeline/CodePipeline/ecs-pipeline-master.yml --capabilities CAPABILITY_NAMED_IAM --stack-name a2c-java-generic-65424cc9-ecs-pipeline-stack

$ sudo tree /root/app2container/java-generic-65424cc9/
/root/app2container/java-generic-65424cc9/
├── Artifacts
│   ├── ContainerFiles.tar
│   ├── Dockerfile
│   ├── Dockerfile.update
│   ├── Pipeline
│   │   └── CodePipeline
│   │       ├── Dockerfile
│   │       ├── buildspec.yml
│   │       └── ecs-pipeline-master.yml
│   ├── entryfile
│   └── excludedFiles
├── EcsDeployment
│   └── ecs-master.yml
├── analysis.json
├── deployment.json
├── pipeline.json
└── taskDef.json

部署管道

使用 ecs-pipeline-master.yml 文件进行部署。
该文件也将作为嵌套堆栈进行部署。

$ sudo aws cloudformation deploy --template-file /root/app2container/java-generic-65424cc9/Artifacts/Pipeline/CodePipeline/ecs-pipeline-master.yml --capabilities CAPABILITY_NAMED_IAM --stack-name a2c-java-generic-65424cc9-ecs-pipeline-stack

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - a2c-java-generic-65424cc9-ecs-pipeline-stack

通过这样做,Dockerfile和buildspec.yml将在CodeCommit中进行管理,
并且当对存储库进行更改时,将检测到并启动管道。
使用CodeBuild进行容器映像的构建和推送,以及任务定义的编辑,
可以轻松创建一个进行ECS集群部署的管道。

image.png

EKS 部署

创建用于 EKS 部署的构件。

需要通过使用containerize命令创建的deployment.json来创建与EKS相关的资源,请编辑eksParameters并将createEksArtifacts更改为true。

       "eksParameters": {
              "createEksArtifacts": true,
              "stackName": "a2c-java-generic-65424cc9-EKS",
              "reuseResources": {
                     "vpcId": "",
                     "cfnStackName": "",
                     "sshKeyPairName": ""
              }
       }

请再次运行generate app-deployment命令。
请注意,pipeline.json将被覆盖。

$ sudo app2container generate app-deployment --application-id java-generic-65424cc9
✔ AWS prerequisite check succeeded
✔ Docker prerequisite check succeeded
✔ Created ECR Repository
✔ Uploaded CloudFormation resources to S3 Bucket: <your_bucket_name>
✔ Generated CloudFormation Master template at: /root/app2container/java-generic-65424cc9/EksDeployment/amazon-eks-master.template.yaml
? EKS CloudFormation templates and additional deployment artifacts generated successfully for application java-generic-65424cc9

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

Next Steps:
1. Edit the CloudFormation template as necessary.
2. Create an application stack using the AWS CLI or the AWS Console. AWS CLI command:

        aws cloudformation deploy --template-file /root/app2container/java-generic-65424cc9/EksDeployment/amazon-eks-master.template.yaml --capabilities CAPABILITY_NAMED_IAM --stack-name a2c-java-generic-65424cc9-EKS

3. Setup a pipeline for your application stack using app2container:

        app2container generate pipeline --application-id java-generic-65424cc9

创建用于部署 EKS 集群的 CloudFormation 模板,并创建部署和服务所需的清单文件。命名空间可能默认为 default,因此根据需要进行自定义。

$ sudo tree /root/app2container/java-generic-65424cc9/
/root/app2container/java-generic-65424cc9/
├── Artifacts
│   ├── ContainerFiles.tar
│   ├── Dockerfile
│   ├── Dockerfile.update
│   ├── Pipeline
│   │   └── CodePipeline
│   │       ├── Dockerfile
│   │       ├── buildspec.yml
│   │       └── ecs-pipeline-master.yml
│   ├── entryfile
│   └── excludedFiles
├── EcsDeployment
│   └── ecs-master.yml
├── EksDeployment ★
│   ├── amazon-eks-master.template.yaml
│   └── java-generic-65424cc9.pem
├── analysis.json
├── deployment.json
├── eks_deployment.yaml ★
├── eks_service.yaml ★
├── pipeline.json
└── taskDef.json

将部署至 EKS 集群。

使用 amazon-eks-master.template.yaml 文件部署 EKS 集群会花费一定时间。

$ sudo aws cloudformation deploy --template-file /root/app2container/java-generic-65424cc9/EksDeployment/amazon-eks-master.template.yaml --capabilities CAPABILITY_NAMED_IAM --stack-name a2c-java-generic-65424cc9-EKS

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - a2c-java-generic-65424cc9-EKS

也可以为 EKS 创建 CI/CD 流水线,但由于步骤与 ECS 相同,因此将不再详述。

请提供更多的上下文信息,使我能够正确地为您翻译。

App2Container文档
https://docs.aws.amazon.com/app2container/latest/UserGuide/what-is-a2c.html

希望这些内容对你有所帮助。

广告
将在 10 秒后关闭
bannerAds