使用 CI/CD 管道自动构建 Java 应用程序并将其部署到 Amazon EKS - AWS Prescriptive Guidance

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用 CI/CD 管道自动构建 Java 应用程序并将其部署到 Amazon EKS

创建者:MAHESH RAGHUNANDANAN(AWS)、James Radtke(AWS)和 Jomcy Pappachen(AWS)

代码存储库:aws-cicd-java-eks

环境:生产

技术:容器和微服务;; CloudNative DevOps;现代化

工作负载:所有其他工作负载

AWS 服务:AWS CloudFormation;AWS CodeCommit;AWS CodePipeline;亚马逊 EC2 容器注册表;亚马逊 EKS

Summary

此模式描述了如何创建持续集成和持续交付 (CI/CD) 管道,该管道可自动构建并部署具有推荐 DevSecOps 实践的 Java 应用程序,并将其部署到亚马逊网络服务 (AWS) 云上的亚马逊 Elastic Kubernetes Service (Amazon EKS) 集群。此模式使用采用 Spring Boot Java 框架开发的问候应用程序,该应用程序使用 Apache Maven。

您可以使用这种模式的方法为 Java 应用程序构建代码,将应用程序构件打包为 Docker 映像,对映像进行安全扫描,然后将该映像作为工作负载容器上传到 Amazon EKS 上。如果您想从紧密耦合的单片架构迁移到微服务架构,则此模式的方法非常有用。该方法还可以帮助您监控和管理 Java 应用程序的整个生命周期,从而确保更高的自动化水平并有助于避免错误或程序错误。

先决条件和限制

先决条件

  • 一个有效的 Amazon Web Services account。

  • AWS 命令行界面(AWS CLI)版本 2,已安装并配置。有关这方面的更多信息,请参阅 AWS CLI 文档中的安装、更新和卸载 AWS CLI 版本 2

  • AWS CLI 版本 2 必须使用与创建 Amazon EKS 集群相同的 IAM 角色进行配置,因为只有该角色才有权向 aws-auth ConfigMap 中添加其他 IAM 角色。有关配置 AWS CLI 的信息和步骤,请参阅 AWS CLI 文档中的配置基础知识

  • 具有 AWS 完全访问权限的 AWS Identity and Access Management (IAM) 角色和权限 CloudFormation。有关这方面的更多信息,请参阅 AWS CloudFormation 文档中的使用 IAM 控制访问权限

  • 现有的 Amazon EKS 集群,包含 EKS 集群中 Worker 节点的 IAM 角色名称和 IAM 角色 Amazon 资源名称(ARN)的详细信息。

  • Kubernetes 集群自动扩缩器,已在 Amazon EKS 集群中安装和配置。有关更多信息,请参阅 Amazon EKS 文档中的集群自动扩缩器。 

  • 访问 GitHub 存储库中的代码。

重要提示

AWS Security Hub 已作为代码中的 AWS CloudFormation 模板的一部分启用。默认情况下,启用 Security Hub 后,它会提供 30 天的免费试用,之后将收取与此 Amazon Web Services 相关的费用。有关定价的更多信息,请参阅 AWS Security Hub 定价

产品版本

  • Helm 版本 3.4.2 或更高版本

  • Apache Maven 版本 3.6.3 或更高版本

  • BridgeCrew Checkov 版本 2.2 或更高版本

  • Aqua Security Trivy 版本 0.37 或更高版本

架构

技术堆栈

  • AWS CodeBuild

  • AWS CodeCommit

  • Amazon CodeGuru

  • AWS CodePipeline

  • Amazon Elastic Container Registry

  • Amazon Elastic Kubernetes Service

  • Amazon EventBridge

  • AWS Security Hub

  • Amazon Simple Notification Service (Amazon SNS)

目标架构

""

图表显示了以下工作流:

  1. 开发人员更新 CodeCommit 存储库基础分支中的 Java 应用程序代码,从而创建拉取请求 (PR)。

  2. 提交 PR 后,Amazon CodeGuru Reviewer 会自动审查代码,根据 Java 的最佳实践对其进行分析,并向开发者提供建议。

  3. PR 合并到基础分支后,将创建一个 Amazon EventBridge 事件。

  4. 该 EventBridge 事件启动 CodePipeline 管道,管道启动。

  5. CodePipeline 运行 CodeSecurity 扫描阶段(持续安全)。

  6. CodeBuild 启动安全扫描流程,在该流程中,使用 Checkov 扫描 Dockerfile 和 Kubernetes 部署 Helm 文件,并根据增量代码更改扫描应用程序源代码。应用程序源代码扫描由 CodeGuru Reviewer 命令行界面 (CLI) 包装器执行。

  7. 如果安全扫描阶段成功,则启动构建阶段(持续集成)。

  8. 在构建阶段, CodeBuild 构建工件,将构件打包到 Docker 镜像,使用 Aqua Security Trivy 扫描映像中是否存在安全漏洞,然后将映像存储在 Amazon ECR 中。

  9. 步骤 8 中检测到的漏洞将上传到 Security Hub,供开发人员或工程师进一步分析。Security Hub 提供了修复漏洞的概述和建议。

  10. CodePipeline 管道中各个阶段的电子邮件通知通过 Amazon SNS 发送。

  11. 持续集成阶段完成后, CodePipeline 进入部署阶段(持续交付)。

  12. 使用 Helm 图表将 Docker 映像作为容器工作负载(容器组(pod))部署到 Amazon EKS。

  13. 应用程序容器配置了 Amazon P CodeGuru rofiler Agent,它会将应用程序的分析数据(CPU、堆使用情况和延迟)发送到 Amazon P CodeGuru rofiler,这可以帮助开发人员了解应用程序的行为。

工具

Amazon Web Services

  • AWS CloudFormation 可帮助您设置 AWS 资源,快速一致地配置这些资源,并在 AWS 账户和区域的整个生命周期中对其进行管理。

  • AWS CodeBuild 是一项完全托管的构建服务,可帮助您编译源代码、运行单元测试和生成可随时部署的项目。

  • AWS CodeCommit 是一项版本控制服务,可帮助您私下存储和管理 Git 存储库,而无需管理自己的源代码控制系统。

  • Amazon CodeGuru Profiler 会从您的实时应用程序收集运行时性能数据,并提供建议,以帮助您微调应用程序性能。

  • Amazon CodeGuru Reviewer 使用程序分析和机器学习来检测开发人员难以发现的潜在缺陷,并提供改进您的 Java 和 Python 代码的建议。

  • AWS CodePipeline 可帮助您快速建模和配置软件发布的不同阶段,并自动执行持续发布软件变更所需的步骤。

  • Amazon Elastic Container Registry (Amazon ECR) 是一项安全、可扩展且可靠的托管容器映像注册表服务。

  • Amazon Elastic Kubernetes Service (Amazon EKS) 可帮助您在 AWS 上运行 Kubernetes,而无需安装或维护您自己的 Kubernetes 控制面板或节点。

  • Amazon EventBridge 是一项无服务器事件总线服务,可帮助您将应用程序与来自各种来源的实时数据连接起来。例如,AWS Lambda 函数、使用 API 目标的 HTTP 调用端点或其他 Amazon Web Services account 中的事件总线。

  • AWS Identity and Access Management (AWS IAM) 通过控制验证和授权使用您 AWS 资源的用户,帮助您安全地管理对您 AWS 资源的访问。

  • AWS Security Hub 向您提供 AWS 中安全状态的全面视图。Security Hub 还可以帮助您根据安全行业标准和最佳实践检查环境。

  • Amazon Simple Notification Service (Amazon SNS) 可帮助您协调和管理发布者与客户端(包括 Web 服务器和电子邮件地址)之间的消息交换。

  • Amazon Simple Storage Service (Amazon S3) 是一项基于云的对象存储服务,可帮助您存储、保护和检索任意数量的数据。

其他服务

  • Helm 是 Kubernetes 的开源软件包管理器。

  • Apache Maven 是一款软件项目管理及理解工具。

  • BridgeCrew Checkov 是一种静态代码分析工具,用于扫描基础设施即代码 (IaC) 文件,以查找可能导致安全性或合规性问题的错误配置。

  • Aqua Security Trivy 是一款全面的扫描工具,可检测容器映像、文件系统和 Git 存储库中的漏洞以及配置问题。

代码

此模式的代码可在 GitHub aws-codepipeline-devsecops-amazoneks存储库中找到。

最佳实践

  • 在本解决方案的所有阶段,IAM 实体都遵循了最低权限原则。如果您想使用其他 Amazon Web Services 或第三方工具扩展解决方案,我们建议您遵循最低权限原则。

  • 如果您有多个 Java 应用程序,我们建议为每个应用程序创建单独的 CI/CD 管线。

  • 如果您使用的是单体应用程序,我们建议尽可能将应用程序分解为微服务。微服务更加灵活,可以更轻松地将应用程序部署为容器,并且可以更好地了解应用程序的整体构建和部署。

操作说明

任务描述所需技能

克隆 GitHub 存储库。

要克隆存储库,请运行以下命令。

git clone https://github.com/aws-samples/aws-codepipeline-devsecops-amazoneks
应用程序开发者、 DevOps 工程师

创建 S3 存储桶并上传代码。

  1. 登录 AWS 管理控制台,打开 Amazon S3 控制台,然后在计划部署此解决方案的 AWS 区域 创建 S3 存储桶。有关更多信息,请参阅 Amazon S3 文档中的创建存储桶

  2. 在 S3 存储桶中,创建一个名为 code 的文件夹。

  3. 导航到您克隆存储库的位置。要创建扩展名为 .zip(cicdstack.zip)的整个代码的压缩版本并验证 .zip 文件,请按顺序运行以下命令。

    注意:如果 python 命令失败并显示未找到 Python,请改用 python3

    cd aws-codepipeline-devsecops-amazoneks python -m zipfile -c cicdstack.zip * python -m zipfile -t cicdstack.zip
  4. cicdstack.zip 文件上传到您在上一步的 S3 存储桶中创建的代码文件夹。

AWS DevOps, DevOps 工程师,云管理员, DevOps

创建 AWS CloudFormation 堆栈。

  1. 打开 AWS CloudFormation 控制台并选择创建堆栈

  2. 指定模板中,选择上传模板文件,上传 cf_templates/codecommit_ecr.yaml 文件,然后选择下一步

  3. 指定堆栈详细信息中,输入堆栈名称,然后提供以下输入参数值:

    • CodeCommitRepositoryBranchName: 您的代码将驻留的分支名称(默认为 main)

    • CodeCommitRepositoryName: 要创建的 CodeCommit 存储库的名称。

    • CodeCommitRepositoryS3Bucket:您在其中创建代码文件夹的 S3 存储桶的名称

    • CodeCommitRepositoryS3 BucketObjKeycode/cicdstack.zip

    • ECR RepositoryName:要创建的 Amazon ECR 存储库的名称

  4. 选择下一步,使用配置堆栈选项的默认设置,然后选择下一步

  5. 查看部分中,验证模板和堆栈的详细信息,然后选择创建堆栈。然后创建堆栈,包括 CodeCommit 和 Amazon ECR 存储库。

  6. 记下 CodeCommit 和 Amazon ECR 存储库的名称,这是 Java CI/CD 管道设置所必需的。

AWS DevOps, DevOps

验证 CloudFormation 堆栈部署。

  1. 在 CloudFormation 控制台的 “堆栈” 下,验证您部署的 CloudFormation 堆栈的状态。堆栈的状态应为创建完成

  2. 此外,在控制台中进行验证, CodeCommit Amazon ECR 已配置完毕并准备就绪。

DevOps 工程师

删除 S3 存储桶。

清空并删除您之前创建的 S3 存储桶。有关更多信息,请参阅 Amazon S3 文档中的删除存储桶

AWS DevOps, DevOps
任务描述所需技能

配置 Java 应用程序的 Helm 图表。

  1. 在您克隆 GitHub 存储库的位置,导航到该文件夹helm_charts/aws-proserve-java-greeting。在此文件夹中,该 values.dev.yaml 文件包含有关 Kubernetes 资源配置的信息,您可以针对将容器部署到 Amazon EKS 来修改这些配置。通过提供 Amazon Web Services account ID、AWS 区域 和 Amazon ECR 存储库名称来更新 Docker 存储库参数。

    image: repository: <account-id>.dkr.ecr.<region>.amazonaws.com/<app-ecr-repo-name>
  2. Java 容器组(pod)的服务类型设置为 LoadBalancer

    service: type: LoadBalancer port: 80 targetPort: 8080 path: /hello initialDelaySeconds: 60 periodSeconds: 30

    要使用其他服务(例如 NodePort),可以更改参数。有关更多信息,请参阅 Kubernetes 文档

  3. 您可以通过将参数 autoscaling 更改为 enabled: true 来激活 Kubernetes 水平容器组(pod)自动扩缩器

    autoscaling: enabled: true minReplicas: 1 maxReplicas: 100 targetCPUUtilizationPercentage: 80 # targetMemoryUtilizationPercentage: 80

您可以通过更改values.<ENV>.yaml文件中的值为 Kubernetes 工作负载启用不同的功能,您的开发、生产、UAT 或 QA 环境<ENV>位于何处。

DevOps

验证 Helm 图表是否存在语法错误。

  1. 在终端上,运行以下命令,验证 Helm v3 是否已安装在本地工作站中。

    helm --version

    如果未安装 Helm v3,请安装

  2. 在终端中,导航到 Helm 图表目录(helm_charts/aws-proserve-java-greeting),然后运行以下命令。

    helm lint . -f values.dev.yaml

    这将检查 Helm 图表中是否存在任何语法错误。

DevOps 工程师
任务描述所需技能

创建 CI/CD 管线。

  1. 打开 AWS CloudFormation 控制台,然后选择创建堆栈

  2. 指定模板中,选择上传模板文件,上传 cf_templates/build_deployment.yaml 模板,然后选择下一步

  3. 指定堆栈详细信息中,指定堆栈名称,然后提供以下输入参数值:

    • CodeBranchName: CodeCommit repo 的分支名称,您的代码所在的位置

    • EKSClusterName:您的 EKS 集群的名称(不是 EKSCluster ID)

    • EKS CodeBuildAppName:应用程序的名称 Helm 图表 (aws-proserve-java-greeting)

    • EKS WorkerNodeRole ARN:亚马逊 EKS 工作节点 IAM 角色的 ARN

    • EKS WorkerNodeRoleName:分配给 Amazon EKS 工作节点的 IAM 角色的名称

    • EcrDockerRepository: 用于存储代码的 Docker 镜像的 Amazon ECR 存储库的名称

    • EmailRecipient: 需要向其中发送构建通知的电子邮件地址

    • EnvType: 环境(例如,开发、测试或生产)

    • SourceRepoName: CodeCommit 存储库的名称,您的代码所在的位置

  4. 选择下一步。使用配置堆栈选项的默认设置,然后选择下一步

  5. 查看部分,验证 AWS CloudFormation 模板和堆栈详细信息,然后选择下一步

  6. 选择创建堆栈。 

  7. 在 CloudFormation 堆栈部署期间,您在参数中提供的电子邮件地址的所有者将收到一条订阅 SNS 主题的消息。要订阅 Amazon SNS,所有者必须选择消息中的链接。

  8. 创建堆栈后,打开堆栈的输出选项卡,然后记录 EksCodeBuildkubeRoleARN 输出密钥的 ARN 值。稍后将需要此 IAM ARN 值才能 CodeBuild 向 IAM 角色提供在 Amazon EKS 集群中部署工作负载的权限。

AWS DevOps
任务描述所需技能

打开 Aqua Security 集成。

要将 Trivy 报告的 Docker 映像漏洞调查发现上传到 Security Hub,必须执行此步骤。由于 AWS CloudFormation 不支持 Security Hub 集成,因此必须手动完成此过程。

  1. 打开 AWS Security Hub 控制台,然后导航到集成

  2. 搜索 Aqua Security,然后选择 Aqua Security:Aqua Security

  3. 选择接受调查发现

AWS 管理员、 DevOps 工程师
任务描述所需技能

CodeBuild 允许在 Amazon EKS 集群中运行 Helm 或 kubectl 命令。

CodeBuild 要通过身份验证才能在 EKS 集群中使用 Helm 或kubectl命令,您必须将 IAM 角色添加到aws-authConfigMap在本例中,添加 IAM 角色的 ARNEksCodeBuildkubeRoleARN,这是为 CodeBuild 服务创建的 IAM 角色,用于访问 EKS 集群并在其上部署工作负载。这是一次性活动。

重要:必须先完成以下程序,然后才能进入部署批准阶段 CodePipeline。

  1. 在 Amazon Linux 或 macOS 环境中打开 cf_templates/kube_aws_auth_configmap_patch.sh Shell 脚本。

  2. 通过运行以下命令对 Amazon EKS 集群进行验证。

    aws eks --region <aws-region> update-kubeconfig --name <eks-cluster-name>
  3. 使用以下命令运行 Shell 脚本,将 <rolearn-eks-codebuild-kubectl> 替换为之前记录的 EksCodeBuildkubeRoleARN ARN 值。

    bash cf_templates/kube_aws_auth_configmap_patch.sh <rolearn-eks-codebuild-kubectl> 

已配置 aws_auth ConfigMap,并授予访问权限。

DevOps
任务描述所需技能

验证 CI/CD 管线是否自动启动。

  1. 如果 Checkov 在 Dockerfile 或 Helm 图表中检测到漏洞,则管道中的 CodeSecurity 扫描阶段通常会失败。但是,此示例的目的是建立一个识别潜在安全漏洞的过程,而不是通过 CI/CD 管道(通常是一个 DevSecOps 过程)修复漏洞。在文件 buildspec/buildspec_secscan.yaml 中,该 checkov 命令使用 --soft-fail 标志来避免管线故障。

    - echo -e "\n Running Dockerfile Scan" - checkov -f code/app/Dockerfile --framework dockerfile --soft-fail --summary-position bottom - echo -e "\n Running Scan of Helm Chart files" - cp -pv helm_charts/$EKS_CODEBUILD_APP_NAME/values.dev.yaml helm_charts/$EKS_CODEBUILD_APP_NAME/values.yaml - checkov -d helm_charts/$EKS_CODEBUILD_APP_NAME --framework helm --soft-fail --summary-position bottom - rm -rfv helm_charts/$EKS_CODEBUILD_APP_NAME/values.yaml

    要使管线在报告 Dockerfile 和 Helm 图表的漏洞时失败,必须从 checkov 命令中删除该 --soft-fail 选项。然后,开发人员或工程师可以修复漏洞并将更改提交到 CodeCommit 源代码存储库。

  2. 与 CodeSecurity 扫描类似,在将应用程序推送到 Amazon ECR 之前,构建阶段使用 Aqua Security Trivy 来识别高风险和严重 Docker 镜像漏洞。在此示例中,我们不会因为 Docker 映像漏洞而使管线失败。在文件 buildspec/buildspec.yml 中,该 trivy 命令包含带有 0值的标志 --exit-code ,这就是为什么在报告 HIGH 或 CRITICAL Docker 映像漏洞时管线不会失效的原因。

    - AWS_REGION=$AWS_DEFAULT_REGION AWS_ACCOUNT_ID=$AWS_ACCOUNT_ID trivy -d image --no-progress --ignore-unfixed --exit-code 0 --severity HIGH,CRITICAL --format template --template "@securityhub/asff.tpl" -o securityhub/report.asff $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$CODEBUILD_RESOLVED_SOURCE_VERSION

    要使管线在报告 HIGH, CRTICAL 漏洞时失败,请将 --exit-code 的值更改为 1

    然后,开发人员或工程师可以修复漏洞并将更改提交到 CodeCommit 源代码存储库。

  3. Aqua Security Trivy 报告的 Docker 映像漏洞已上传到 Security Hub。在 AWS Security Hub 控制台上,导航到调查发现。使用记录状态 = 活跃产品 = Aqua Security来筛选调查发现。这将列出 Security Hub 中的 Docker 映像漏洞。漏洞可能需要 15 分钟到 1 小时才会出现在 Security Hub 上。

有关使用启动管道的更多信息 CodePipeline,请参阅 AWS CodePipeline 文档中的在中 CodePipeline启动管道、手动启动管道和按计划启动管道。

DevOps

批准部署。

  1. 构建阶段完成后,将有一个部署批准门。审查者或发布经理应检查该构建,如果满足所有要求,则应予以批准。对于使用持续交付进行应用程序部署的团队,推荐使用这种方法。

  2. 批准后,管线将启动部署阶段。

  3. 部署阶段成功后,此阶段的 CodeBuild 日志将提供应用程序的 URL。使用 URL 验证应用程序是否准备就绪。

DevOps

验证应用程序分析。

部署完成并将应用程序容器部署在 Amazon EKS 中后,在应用程序中配置的 Amazon P CodeGuru rofiler 代理将尝试将应用程序的分析数据(CPU、堆摘要、延迟和瓶颈)发送到 Ama CodeGuru zon Profiler。

对于应用程序的初始部署,Amazon CodeGuru Profiler 大约需要 15 分钟才能对分析数据进行可视化。

AWS DevOps

相关资源

其他信息

CodeGuru 在功能方面,不应将 Profiler 与 AWS X-Ray 服务混淆。 CodeGuru Profiler 是识别可能导致瓶颈或安全问题的最昂贵代码行,并在它们成为潜在风险之前对其进行修复的首选。AWS X-Ray 服务用于监控应用程序性能。

在此模式中,事件规则与默认事件总线相关联。如果需要,您可以扩展模式以使用自定义事件总线。

此模式使用 CodeGuru Reviewer 作为应用程序代码的静态应用程序安全测试 (SAST) 工具。您也可以将此管道用于其他工具,例如 SonarQube 或 Checkmarx。可以添加其中任何工具的相应扫描设置说明buildspec/buildspec_secscan.yaml,取代的扫描指令 CodeGuru。