亚马逊AWS官方博客

在 Amazon EKS 上使用 Jenkins 和 HashiCorp Terraform 实现持续集成

这篇博客文章是 Amazon Web Services 与 HashiCorp 合作的成果。HashiCorpAWS 合作伙伴网络 (APN) 的高级技术合作伙伴,在开发运营容器方面均具有 AWS 能力。

简介

有些客户在 Amazon Elastic Kubernetes Service (Amazon EKS) 上运行基于微服务的应用程序,他们需要使用 Jenkins 和 Spinnaker 构建完整的端到端持续集成 (CI) 和持续部署/交付 (CD) 管道方面的指导。Jenkins 是非常流行的 CI 服务器,具有强大的社区支持和许多插件 (Slack、GitHub、Docker、Build Pipeline) 可用。Spinnaker 提供自动发布和内置部署功能,并支持即开即用的蓝/绿部署。

这篇文章是在 Amazon EKS 上使用 Spinnaker 实现持续交付的姊妹篇,重点关注持续集成,并将讨论使用 Hashicorp TerraformAmazon EC2 上安装和配置 Jenkins。我们还将讨论 Spinnaker 管道的创建,此过程是实现强大的协调和分支的各个阶段的组合。这些管道可以手动启动,也可以由事件自动触发,例如 Docker 注册表中出现的新 Docker 映像。这篇文章中使用的其他服务和技术包括 Amazon EC2AWS Cloud9Docker HubAmazon EKS

概念概述

Terraform

Terraform 是用于安全高效地构建、更改和版本控制基础设施的工具。它通过易于使用的命令行界面 (CLI) 以及免费使用的名为 Terraform Cloud 的 SaaS 产品和用于企业的专用设备进行控制。Terraform 可以管理现有和流行的服务提供商以及定制的内部解决方案。配置文件向 Terraform 描述了运行单个应用程序或整个数据中心所需的组件。Terraform 生成执行计划,以描述达到预期状态所需执行的操作,然后执行该计划以构建所描述的基础设施。配置更改时,Terraform 能够确定更改的内容并创建可以应用的增量执行计划。Terraform 的主要功能包括:基础设施即代码、执行计划、资源图和变更自动化。

Jenkins

Jenkins 是一个自包含的开源自动化服务器,可用于自动化与构建、测试以及交付或部署软件有关的各种任务。它可以通过本机系统软件包 Docker 安装,甚至可以由安装有 Java Runtime Environment (JRE) 的任何计算机独立运行。

先决条件

为了实现本文中的说明,您需要以下资源:

架构

本文中,我们将讨论下列适用于持续集成的架构:

持续集成架构

图 1.持续集成架构

步骤概述:

  • 使用 Terraform 创建 Jenkins CI 服务器。
  • 配置 Jenkins。
  • 配置 Jenkins 作业和管道。
  • 创建和配置 Spinnaker 管道。
  • 手动运行 Spinnaker 管道。
  • 使用 AWS Cloud9 修改代码并推送代码更改。
  • 清理。

使用 Terraform 创建 Jenkins CI 服务器

手动预置 Jenkins CI 服务器可能容易出错且耗时,因此我将使用“基础设施即代码 (IaC)”方式配置 Jenkins Continuous Server (CI)。在本博文论述中我将使用 Terraform。登录到 AWS 管理控制台并创建一个 EC2 密钥对(在我的示例中,密钥对的名称为 ibuchh-key)。使用您的 GitHub 账户,派生 https://github.com/aws-samples/amazon-eks-jenkins-terraform.git 上的代码示例存储库

在 AWS Cloud9 IDE 中,打开一个 shell 终端并执行以下操作(用您的 GitHub 账户替换 aws-samples):

git clone https://github.com/aws-samples/amazon-eks-jenkins-terraform.git

cd amazon-eks-jenkins-terraform/terraform/

terraform init

terraform plan

terraform apply -auto-approve

Terraform apply

图 2.Terraform apply 的输出

Terraform apply 还将输出 Jenkins CI 服务器的 IP 地址,如上所示。

Terraform 将预置一个 AWS EC2 实例,并如 install_jenkins.sh 文件所示安装 git、Apache Maven、Docker、Java 8 和 Jenkins:

#!/bin/bash
sudo yum -y update

echo "Install Java JDK 8"
sudo yum remove -y java
sudo yum install -y java-1.8.0-openjdk

echo "Install Maven"
sudo yum install -y maven 

echo "Install git"
sudo yum install -y git

echo "Install Docker engine"
sudo yum update -y
sudo yum install docker -y
sudo sudo chkconfig docker on

echo "Install Jenkins"
sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat-stable/jenkins.repo
sudo rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key
sudo yum install -y jenkins
sudo usermod -a -G docker jenkins
sudo chkconfig jenkins on

echo "Start Docker & Jenkins services"
sudo service docker start
sudo service jenkins start

使用浏览器,打开页面 http://jenkins_ip_address:8080,这将显示 Jenkins 管理员页面:

Jenkins 管理员页面

图 3.Jenkins 管理员页面

使用 AWS Cloud9 shell 终端,登录到 Jenkins CI 服务器,通过运行以下命令找到管理员密码:

sudo cat /var/lib/jenkins/secrets/initialAdminPassword

将其粘贴到输入框中,从而在 Jenkins 控制台上输入管理员密码,然后单击下一步 单击安装建议的插件

配置 Jenkins

1.插件

登录 Jenkins 控制台,单击管理 Jenkins → 管理 Plugins → 可用。选择并安装 Docker 插件GitHub 集成插件,然后通过单击“重启 Jenkins”复选框重新启动 Jenkins,如下所示:

Jenkins 插件

图 4.Jenkins 插件

2.凭据

Docker Hub:单击凭据 → 全局 → 添加凭据,在具有密码的用户名选择种类,输入 Docker Hub 用户名和密码并使用 dockerHubCredentials 作为 ID。

GitHub:单击凭据 → 全局 → 添加凭据,在具有密码的用户名选择种类,输入 GitHub 用户名和密码并使用 gitHubCredentials 作为 ID。

配置 Jenkins 作业和管道

在 Jenkins 控制台中,单击新建项目。选择多分支管道,将其命名为 petclinic 然后单击确定

Jenkins 多分支管道
 图 5.Jenkins 多分支管道

选择 GitHub,然后从下拉列表中选择 GitHub 凭据。输入如下所示的 GitHub URL,然后单击保存以保存 Jenkins 作业。

Jenkins 作业详细信息

图 6.Jenkins 作业详细信息

Jenkins 构建执行器将检出并扫描 GitHub 存储库,并按照下面显示的 Jenkins 文件中的规定执行管道中的阶段。确保将注册表替换为构建阶段中 Docker 注册表 URL。

pipeline {
    agent any
       triggers {
        pollSCM "* * * * *"
       }
    stages {
        stage('Build Application') { 
            steps {
                echo '=== Building Petclinic Application ==='
                sh 'mvn -B -DskipTests clean package' 
            }
        }
        stage('Test Application') {
            steps {
                echo '=== Testing Petclinic Application ==='
                sh 'mvn test'
            }
            post {
                always {
                    junit 'target/surefire-reports/*.xml'
                }
            }
        }
        stage('Build Docker Image') {
            when {
                branch 'master'
            }
            steps {
                echo '=== Building Petclinic Docker Image ==='
                script {
                    app = docker.build("ibuchh/petclinic-spinnaker-jenkins")
                }
            }
        }
        stage('Push Docker Image') {
            when {
                branch 'master'
            }
            steps {
                echo '=== Pushing Petclinic Docker Image ==='
                script {
                    GIT_COMMIT_HASH = sh (script: "git log -n 1 --pretty=format:'%H'", returnStdout: true)
                    SHORT_COMMIT = "${GIT_COMMIT_HASH[0..7]}"
                    docker.withRegistry('https://registry.hub.docker.com', 'dockerHubCredentials') {
                        app.push("$SHORT_COMMIT")
                        app.push("latest")
                    }
                }
            }
        }
        stage('Remove local images') {
            steps {
                echo '=== Delete the local docker images ==='
                sh("docker rmi -f ibuchh/petclinic-spinnaker-jenkins:latest || :")
                sh("docker rmi -f ibuchh/petclinic-spinnaker-jenkins:$SHORT_COMMIT || :")
            }
        }
    }
}

下面是最终运行的屏幕截图;如果一切顺利,您将看到一个新的 Docker 映像推送到您的 Docker 注册表中。

管道阶段

图 7.管道阶段

创建和配置 Spinnaker 管道

管道是指 Spinnaker 提供的一定顺序的阶段,从操作基础设施的功能(部署、调整、禁用),到支持功能(手动判断、等待、运行 Jenkins 作业),这些功能共同精确定义了管理您部署的操作手册。管道可帮助您一致、可重复且安全地管理部署。

1. 登录到 AWS Cloud9 IDE 环境,然后打开一个新终端。运行以下命令:

kubectl get svc -n spinnaker

Spinnaker UI 终端节点

 图 8.Spinnaker UI 终端节点

2. 打开浏览器,使用 spin-deck-public services 终端节点登录 Spinnaker UI,如上面的输出所示。

选择应用程序选项卡,然后选择操作 → 创建应用程序。 输入 petclinic 作为名称,然后输入有效的电子邮件地址,其余字段留为空白。

Spinnaker 应用程序

图 9.Spinnaker 应用程序

3. 在管道选项卡上,单击配置新管道,输入 DeployToUAT 作为管道名称,然后单击创建

Spinnaker DeployToUAT 管道

图 10.Spinnaker DeployToUAT 管道

4. 单击添加构件并选择 GitHub → 种类,文件路径 → kubernetes/petclinic.yaml,显示名称 → Petclinic-Manifest,内容 URL https://api.github.com/repos/aws-samples/amazon-eks-jenkins-terraform/contents/kubernetes/petclinic.yaml

管道构件

图 11.管道构件

5. 单击添加触发器并选择类型 → Docker 注册表,注册表名称 → Spinnaker 中配置的 Docker 注册表,组织 → 您的 Docker 注册表名称,映像 → Jenkins 创建的 Docker 映像。

管道触发器

图 12.管道触发器

6. 单击添加阶段,选择阶段类型 → 部署(清单),账户 → eks-uat应用程序 → petclinic,清单源 → 构件,清单构件 → Petclinic-Manifest构件账户 → spinnaker-github

部署清单阶段

图 13.部署清单阶段

7. 单击保存将更改保存到 DeployToUAT 管道。

8. 在管道选项卡下,单击创建,输入 ManualApproval 作为管道名称,然后单击“创建”。单击添加触发器并选择类型 → 管道,应用程序 → petclinic,管道 → DeployToUAT

ManualApproval 管道
 图 14.ManualApproval 管道

9. 单击添加阶段,选择阶段名称 → 手动判断,判断输入下添加两个选项批准拒绝,如下所示:

手动判断阶段

图 15.手动判断阶段

10. 单击保存将更改保存到 ManualApproval 管道。

11. 在管道选项卡下,单击创建,输入 DeployToProd 作为管道名称,然后单击创建。单击添加触发器并选择类型 → 管道,应用程序 → petclinic,管道 → DeployToProd

12. 单击添加构件并选择 GitHub → 种类,文件路径 → kubernetes/petclinic.yaml显示名称 → Petclinic-Manifest,内容 URL https://api.github.com/repos/aws-samples/amazon-eks-jenkins-terraform/contents/kubernetes/petclinic.yaml

管道构件
 图 16.管道构件

13. 单击添加触发器并选择类型 → Docker 注册表,注册表名称 → Spinnaker 中配置的 Docker 注册表,组织 → 您的 Docker 注册表名称,映像 → Jenkins 创建的 Docker 映像。

图 17.管道触发器

14. 单击添加阶段,选择阶段类型 → 部署(清单),账户 → eks-prod,应用程序 → petclinic清单源 → 构件,清单构件 → Petclinic-Manifest构件账户 → spinnaker-github

部署清单阶段

图 18.部署清单阶段

15. 单击保存将更改保存到 DeployToProd 管道。

手动运行 Spinnaker 管道

现在手动运行三个管道。单击开始手动执行,选择管道 → DeployToUAT,类型 → 标记,标记 → 输入有效的标记号。单击运行并观察管道执行。

管道执行

图 19.管道执行

使用 AWS Cloud9 修改代码并推送代码更改

让我们使用 AWS Cloud9 推送代码更改,并观察 Jenkins 和 Spinnaker 中端到端的持续集成和持续部署管道的执行情况。打开 AWS Cloud9 并在 messages.properties 文件中将 welcome 更改为 Welcome CI/CD,然后保存文件。

推送代码更改

图 20.推送代码更改

在 AWS Cloud9 中打开 shell 终端并运行以下命令:

cd environment/amazon-eks-jenkins-terraform
git status
git commit  -am "change messages.properties"
git push

这会将代码更改推送到 GitHub 存储库,从而触发 Jenkins 管道。Jenkins 管道将运行各个阶段,并将 Docker 映像推送到 Docker Hub 注册表。新 Docker 映像的创建将触发 Spinnaker DeployToUAT 管道,这继而会触发 Manual Approval 管道,如下所示。此时,新的代码更改已交付给 Amazon EKS UAT 集群:即实现了持续交付。

Spinnaker 管道

图 21.Spinnaker 管道

选择批准作为判断输入,然后单击继续以批准将触发 DeployToProd Spinnaker 管道的代码更改。然后,新的代码更改将部署到 Amazon EKS 生产集群:即实现了持续部署。

打开 Amazon EKS 生产集群的负载均衡器终端节点,您将看到新的代码更改:

应用程序代码更改

图 22.应用程序代码更改

清理

要删除 Jenkins 实例,请在 AWS Cloud9 IDE 内运行以下命令:

cd environment/amazon-eks-jenkins-terraform/terraform
terraform destroy -auto-approve

terraform destroy

图 23.Terraform destroy

结论

在本文中,我们概述了在 Amazon EKS 上使用 Terraform 和 Jenkins 配置持续集成平台所需的详细说明。Jenkins 可以与 Spinnaker 集成以构建完整的 CI/CD 管道。在 Spinnaker 中将 Jenkins 设置为持续集成 (CI) 系统,您将可以使用 Jenkins 触发管道、在管道中添加 Jenkins 阶段或在管道中添加脚本阶段。要了解有关 Terraform 的更多信息,请参阅 terraform.io 或 Terraform 文档

 

Meghan Liese

Meghan Liese

Meghan Liese 是总部位于加利福尼亚州旧金山的 HashiCorp 的 Terraform 产品营销总监。

本博文中的内容和意见属于第三方作者,AWS 不对本博文的内容或准确性负责。