亚马逊AWS官方博客
在 Kubernetes 上使用 Spinnaker 构建部署管道
Spinnaker 是一种持续交付平台,最初由 Netflix 开发,用于快速、可靠地发布软件更改。Spinnaker 使开发人员可以更轻松地专注于编写代码,而无需担心底层的云基础设施。它与 Jenkins 以及其他流行的构建工具无缝集成。
在本博文中,我们将讨论如何安装 Spinnaker 以及如何为在 Kubernetes 上运行的工作负载构建持续交付管道。我们的工作流与以下类似:
图中包含了下列步骤:
- 开发人员将代码推送到 GitHub。
- GitHub 触发 Jenkins。
- Jenkins 构建一个 Docker 映像,然后为它添加标签并推送到 Amazon Elastic Container Registry (Amazon ECR)。
- Spinnaker 管道将在 Amazon ECR 收到此新 Docker 映像时触发。
- 然后 Spinnaker 将执行如下操作:
- 使用 Helm 生成 (Bake) Kubernetes 部署文件(开发和生产)。
- 将 Kubernetes 部署到开发环境。
- 人工判断:我们的管道配置需要人工手动确认,然后才能将应用程序部署到生产环境。它会等待此步骤完成,然后才会继续执行管道。
- 将代码部署到生产环境。
先决条件
- 一个正在运行的 Kubernetes 集群。如果您还没有运行这样的集群,请使用 eksctl 以通过一个命令启动并运行 EKS 集群。
- Kubernetes 集群中至少需要有 8GB 可用内存和 2 个 vCPU 以支持 Spinnaker 微服务。一个 m5.large 实例应该足够满足此要求。
- 已在您的计算机上安装、配置和运行 kubectl。
- 已安装 Helm。如要安装,请遵循 Kubernetes Helm 说明。
- 已安装 Jenkins。如要安装,请遵循 AWS 上的 Jenkins 文档中的说明。
- 已为 Jenkins 安装 Docker 和 Amazon ECR 插件并且正确配置。
- 一个 Docker 注册表账户。如果您还没有这样的账户,您可以使用 Amazon ECR,因为我们在本博文中也将这样做。您还可以使用 Docker Hub。
- 一个身份提供商 (LDAP/SAML/Oauth2)。在本博文中,我们将使用 Active Directory (LDAP) 身份认证机制。如果您还没有身份提供商,请遵循 AWS 托管 Microsoft AD 文档中的说明。
步骤
当所有的先决条件都具备后,您就可以开始设置管道的实际步骤。我们将详细讲解每个步骤,下面概括了我们将要执行的步骤:
- 构建一个示例应用程序:Hello world 示例微服务。
- 使用 Helm 在 EKS 上安装 Spinnaker。
- 设置 LDAP/AD 身份验证。
- 通过设置入站控制器来暴露 Spinnaker。
- 将一个 GitHub 账户添加到 Spinnaker。
- 在您的 AWS 账户中配置 Amazon ECR,以便存储 Jenkins 推送的 Docker 映像。
- 为 Docker 映像编译和 ECR 推送配置 Jenkins。
- 在 Spinnaker 中构建 CI/CD 管道 — 私用来自 GitHub 的 Web-hook 自动化编译,手动批准生产环境部署。
- 运行管道并部署应用程序。
- 测试。
- 清除。
第 1 步:构建示例应用程序
为便于本博文的演示,我们将使用我们的管道将会构建和部署的示例应用程序。请对示例应用程序进行分叉以继续下一步。
此存储库包含一个 Helm 图表,该图表将在 Spinnaker 进行部署时使用。本节剩余部分提到的项目已经为此存储库完成,因此您可以直接使用。如果您使用示例应用程序,则可跳过第 2 步! 否则,如果您使用自己的应用程序:
如果您使用自己的应用程序
如果您倾向于使用自己的应用程序,您将需要创建自己的 Helm 图表并进行封装。请按照以下步骤为您的应用程序创建和封装一个 Helm 图表。
helm 创建示例微服务
打开 sample-microservice/templates/deployment.yaml,然后进行如下更改:
1.1 添加命名空间
将 namespace: {{ .Release.Namespace}}
添加到 Helm 模板部署中。这将帮助 Spinnaker 在部署阶段提到的特定命名空间中部署 Kubernetes 部署包
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ include "sample-microservice.fullname" . }}
namespace: {{ .Release.Namespace}}
1.2 更改映像
将 Helm 模板的 deployment.yaml 文件中的 "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
更改为 {{ .Values.image.repository }}
(这将让 Spinnaker 替换部署的标签),即从:
spec:
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image.repository }}
imagePullPolicy: "{{ .Values.image.pullPolicy }}:{{ .Values.image.tag}}"
更改为:
spec:
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image.repository }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
通过运行以下命令封装 Helm 图表:
helm package sample-microservice
此命令将创建 Spinnaker 会用到的 sample-microservice-0.1.0.tgz 文件。
第 2 步:使用 Helm 安装 Spinnaker
要使用默认配置安装 Spinnaker,请运行如下命令:
helm install stable/spinnaker --name=spinnaker --namespace=spinnaker
如需了解更多信息,请参阅适用于 GitHub 上的 Spinnaker 的 Helm 图表。
在安装过程中,我们来谈谈我们将在本博文中用到的一些 Spinnaker 组件。有关 Spinnaker 的详细架构和组件,请参阅 Spinnaker 参考架构。
- Deck — 这是用于提供基于浏览器的 UI 的 Spinnaker 前端组件。
- Gate — 此服务提供了 Spinnaker REST API,负责服务脚本处理客户端以及来自 Deck 的所有操作。
- Halyard — 用于配置、安装和更新 Spinnaker 的 CLI。
Spinnaker 将 Redis 作为缓存基础设施,用于存储与实时执行有关的信息;有关此功能的更多信息请参阅 Spinnaker Redis 配置页面。我们将使用 Helm 图表依赖并且安装在 Kubernetes 集群内部的一个 Redis 安装。对于 Spinnaker 的生产设置,您将需要将 Redis 外部化。您还将需要参阅 Spinnaker 生产化文档。
Spinnaker 还需要一个数据存储(S3、Minio 或其他对象存储)。默认安装会使用 Minio。对于生产环境,您将需要通过在 values.yaml 中启用 S3 来使用 S3,而不是 Minio。
要验证您的 Spinnaker 安装:
kubectl -n spinnaker get pods:
与以下类似的输出可确认 Spinnaker 已成功安装:
NAME READY STATUS RESTARTS AGE spin-clouddriver-945c95564-8wl52 1/1 Running 0 2h spin-deck-6c4bf6c4f6-wqgmk 1/1 Running 0 2h spin-echo-646f6c4b76-p29tl 1/1 Running 0 2h spin-front50-7cc5575457-qcvtd 1/1 Running 1 2h spin-gate-84dc696d7c-zqctg 1/1 Running 0 2h spin-igor-885f8bf5c-xprkc 1/1 Running 0 2h spin-orca-7bfd8fd4d6-28dks 1/1 Running 0 2h spin-rosco-844b85888-sggkk 1/1 Running 0 2h spinnaker-install-using-hal-qlvfj 0/1 Completed 0 2h spinnaker-Minio-df54fb68d-h4ld9 1/1 Running 0 2h spinnaker-Redis-master-0 1/1 Running 0 2h spinnaker-spinnaker-halyard-0 1/1 Running 0 2h
要列出服务,请运行以下命令:
kubectl -n spinnaker get services
输出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE spin-clouddriver ClusterIP 172.20.135.53 <none> 7002/TCP 2h spin-deck ClusterIP 172.20.167.104 <none> 9000/TCP 2h spin-echo ClusterIP 172.20.46.99 <none> 8089/TCP 2h spin-front50 ClusterIP 172.20.234.34 <none> 8080/TCP 2h spin-gate ClusterIP 172.20.132.82 <none> 8084/TCP 2h spin-igor ClusterIP 172.20.87.99 <none> 8088/TCP 2h spin-orca ClusterIP 172.20.241.201 <none> 8083/TCP 2h spin-rosco ClusterIP 172.20.136.62 <none> 8087/TCP 2h spinnaker-Minio ClusterIP None <none> 9000/TCP 2h spinnaker-Redis-master ClusterIP 172.20.80.211 <none> 6379/TCP 2h spinnaker-spinnaker-halyard ClusterIP None <none> 8064/TCP 2h
要启动 Spinnaker UI,请运行命令:
kubectl -n spinnaker port-forward svc/spin-deck 9000:9000
在浏览器中导航至 http://localhost:9000。这时您应会看到:
第 2.1 步:设置 LDAP/AD 身份验证。
获取您的 Active Directory 服务器的 URL。在我的 AWS 账户中,有一个 AD 服务器与我的 Kubernetes 集群在同一个 VPC 中运行。如果您还没有这样的服务器,请转至 AWS 托管 AD 并自行获取一个服务器。
如下所示创建一个名为 gate-local.yaml
的文件。此文件将用于放置 Spinnaker 的 Active Directory 配置。
ldap:
enabled: true
url: ldap://10.0.157.236:389/dc=ad,dc=prabhatsharma,dc=com
userSearchBase: OU=users,OU=ad
userSearchFilter: (sAMAccountName={0})
managerDn: CN=prabhat,OU=users,OU=ad,dc=ad,dc=prabhatsharma,dc=com
managerPassword: MySuper#StrongPassword
将 gate-local.yaml
复制到 Halyard:
kubectl cp gate-local.yaml spinnaker-spinnaker-halyard-0:/home/spinnaker/.hal/default/profiles/
应用 Halyard 配置:
kubectl exec spinnaker-spinnaker-halyard-0 -- bash hal deploy apply
第 3 步:暴露 Spinnaker — 设置入站控制器
这是一个可选步骤,仅在您需要在 Kubernetes 集群外部暴露 Spinnaker 时使用。您必须安装了 NGINX 入站控制器才能成功完成此步骤。
我在 Route53 中配置了一个公有的万用域,它指向我的 NGINX 入站 ELB。您需要使用自己的域,为此请将 yourcustomdomain.com 替换为您自己的域。
创建文件 spinnaker-ingress.yaml
:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: spinnaker
annotations:
kubernetes.io/ingress.class: nginx
spec:
tls:
- hosts:
- spinnaker.yourcustomdomain.com
- spin-gate.yourcustomdomain.com
rules:
- host: spinnaker.yourcustomdomain.com
http:
paths:
- path: /
backend:
serviceName: spin-deck
servicePort: 9000
- host: spin-gate.yourcustomdomain.com
http:
paths:
- path: /
backend:
serviceName: spin-gate
servicePort: 8084
部署入站控制器:
kubectl -n spinnaker apply -f spinnaker-ingress.yaml
这时,您已经暴露了甲板(Spinnaker UI 终端节点)和闸门(Spinnaker API 终端节点)。
您需要告诉 Spinnaker 使用我们刚刚创建的新 Spinnaker 终端节点。为此我们将使用 Halyard。要运行 Halyard,请登录到 Halyard Pod:
kubectl -n spinnaker exec -it spinnaker-spinnaker-halyard-0 bash
这将会进入容器中的壳程序。
spinnaker@spinnaker-spinnaker-halyard-0:/workdir$
运行以下命令以将 Spinnaker 配置为使用新的终端节点。如果需要任何其他的配置,您始终可以参考完整的 Halyard 命令列表。
hal config security api edit --override-base-url https://spin-gate.yourcustomdomain.com
hal config security ui edit --override-base-url https://spinnaker.yourcustomdomain.com
hal deploy apply
此后您将能够通过 https://spinnaker.yourcustomdomain.com 访问 Spinnaker。
第 4 步:将一个 GitHub 账户添加到 Spinnaker
我们将使用 Halyard 来添加 GitHub 账户
要访问 Halyard Pod:
kubectl -n spinnaker exec -it spinnaker-spinnaker-halyard-0 bash
hal config artifact github account add aws-samples
hal deploy apply
注意:请将 aws-samples 更改为您自己的 Github 账户名。
以上命令将允许 Spinnaker 访问 GitHub。
第 5 步:为 Jenkins 映像推送配置 Amazon ECR 存储库
您需要一个 Docker 存储库来存储您的微服务 Docker 映像。为此我们将创建一个 Amazon ECR 存储库。
导航至 AWS 控制台 > 计算 > ECR。
单击创建存储库。
键入存储库的名称 (sample-microservice),然后单击创建存储库。
此存储库将存储 Jenkins 推送的我们的微服务的 Docker 映像。
第 6 步:为 Docker 映像编译和 ECR 推送配置 Jenkins
注意:您必须已经安装并配置好 Amazon ECR 插件才能执行此操作。您可以前往 Jenkins > Plugin Manager(插件管理器)> Installed(已安装)并搜索 Amazon ECR,从而验证该插件已安装。
我们将配置一个 Jenkins 作业,此作业将通过向 GitHub 推送代码的方式触发。此作业将会构建一个 Docker 映像并将该映像推送到 Amazon ECR。
现在登录到您的 Jenkins 安装,并且:
6.1 创建一个新的任意风格项目
6.2 配置源代码管理
更改分叉后的 GitHub 存储库路径,然后将 aws-samples 替换为您自己的用户名,例如将 https://github.com/aws-samples/sample-microservice-with-spinnaker 替换为 https://github.com/[您的 GitHub 句柄]/sample-microservice-with-spinnaker。
6.3 配置编译触发器
您可以使用 Webhook 或轮询。在本博文中我们使用 Webhook。GitHub 的 Jenkins Webhook 配置不属于本博文的范围。
6.4 配置编译阶段
我们将 Jenkins 编译号作为 Docker 映像标签使用:
Jenkins 变量 BUILD_NUMBER 将作为新创建映像的标签使用。
第 7 步:为 Spinnaker 配置 Amazon ECR
注意:要完成此项操作,您的 Kubernetes 节点必须分配了恰当的 IAM 角色以允许访问 ECR。您可以在文档中找到可以分配到您的 Kubernetes 工作线程节点 IAM 角色的示例 IAM 策略。
此配置将允许您配置将容器推送到 ECR 时将会触发的 Spinnaker 管道。
ADDRESS=123456789123.dkr.ecr.us-west-2.amazonaws.com
REGION=us-west-2
hal config provider docker-registry account add my-ecr-registry \
--address $ADDRESS \
--username AWS \
--password-command "aws --region $REGION ecr get-authorization-token --output text --query 'authorizationData[].authorizationToken' | base64 -d | sed 's/^AWS://'"
hal deploy apply
有关管理 Docker 注册表的更多信息,请参阅 Spinnaker 的 Docker 注册表文档。
第 8 步:在 Spinnaker 中构建 CI/CD 管道
在开始构建此管道前,您需要了解一些 Spinnaker 概念:
应用 — 应用是指您将使用 Spinnaker 部署的服务、该服务的所有配置以及它运行所需的所有基础实施。您一般会为每个服务创建不同的应用,但这并非 Spinnaker 的强制要求。
管道 — 管道是指 Spinnaker 提供的一定顺序的阶段,从操作基础设施的功能(部署、调整、禁用),到支持功能(人工判断、等待、运行 Jenkins 作业)等等。所有这些阶段一起准确定义了管理您的部署的操作手册。
阶段 — Spinnaker 中的阶段是管道的基本构建块,它描述了该管道将执行的操作。您可以按任何顺序排列 Spinnaker 中的阶段,但一些阶段顺序要比其他顺序更常见。Spinnaker 提供了多个阶段,例如部署、调整、禁用、人工判断等等。
构件 — 在 Spinnaker 中,构件是指引用任何外部资源的对象。该资源可以是:
- Docker 映像
- 存储在 GitHub 中的文件
- Amazon 系统映像 (AMI)
- S3、GCS 等中的二进制大对象
Spinnaker 使用 Helm v2 来管理向 Kubernetes 推送的部署。您必须为您计划推送部署的每个环境指定一个基本 Helm 模板和一个覆盖文档。
下面我们执行设置管道的必要步骤:
- 创建应用
- 创建管道
- 设置配置
- 设置构件
- Helm 模板 — sample-microservice-0.1.0.tgz
- Helm 开发环境覆盖 — values/dev.yaml
- Helm 生产环境覆盖 — values/dev.yaml
- Docker 映像 — 123456789123.dkr.ecr.us-west-2.amazonaws.com/sample-microservice
- 设置管道触发器
- 设置构件
- 创建阶段
- Bake 开发
- Bake 生产
- 部署到开发
- 人工判断
- 部署到生产
8.1 创建应用
我们的应用将是 Spinnaker 中的一个占位符,代替我们将为其构建管道的服务。
登录到 Spinnaker 后,从 Applications > Create Application 创建一个新的应用。
单击 Create;您将会看到应用基础设施页面:
8.2 创建管道
转至“Pipelines”,然后单击 Configure a new pipeline。
8.3 设置管道配置
现在您将进入:
现在我们将配置 Expected Artifacts:
Helm 模板构件
单击 Add Artifact。
注意:在下面的步骤中,请将 aws-samples 替换为您的 GitHub 句柄。
将默认内容 URL 设置为 https://api.gitgub.com/repos/aws-samples/sample-microservice-with-spinnaker/contents/sample-microservice-0.1.0.tgz
触发器每次触碰 Webhook 时,会将构件传输至 Spinnaker。如果您的管道需要特定的构件来执行尚未通过触发器收到的管道,您可以指定要使用的默认构件。在此例中,我们将指定默认构件,因为我们的管道未被 GitHub 触发,因此不会在我们需要执行时传输该构件。
对其他构件进行类似配置:
开发环境覆盖构件
构件类型 — GitHub
文件路径 — values/dev.yaml
默认构件内容 URL – https://api.github.com/repos/aws-samples/sample-microservice-with-spinnaker/contents/values/dev.yaml
生产环境覆盖构件
构件类型 — GitHub
文件路径 — values/prod.yaml
默认构件内容 URL – https://api.github.com/repos/aws-samples/sample-microservice-with-spinnaker/contents/values/prod.yaml
Docker 映像构件
构件类型 — Docker
Docker 映像 — 123456789123.dkr.ecr.us-west-2.amazonaws.com/sample-microservice
默认构件 Docker 映像 — 123456789123.dkr.ecr.us-west-2.amazonaws.com/sample-microservice:latest
现在我们将配置 Automated Triggers:
自动化触发器可以在每次发生特定事件时(例如,Docker 映像推送到注册表、代码推送到 GitHub 等)启动某个管道。我们需要在我们的 ECR 存储库中有新的 Docker 映像可用时启动管道。
配置方式是从 Automated Triggers 的下拉列表中选择注册表名称和映像:
然后单击右下角的 Save Changes 以保存更改。
8.4 添加 Bake 阶段
现在我们的管道配置已经完成,可以添加新的阶段
Bake dev — 此阶段将使用 dev.yaml 中的覆盖值,通过 Helm v2 来渲染部署模板。
跳转至管道顶部,单击 Add stage。
提供名称和将会进行部署的 Kubernetes 命名空间。命名空间必须已经存在,否则管道执行时将会失败。
这还将创建一个叫做 Produces Artifacts 的部分,您可以下翻看到:
此生成的构件是一个 base64 编码的 Kubernetes 部署文件(含服务、入口等)。
安装与上述 Bake dev类似的操作,创建一个 Bake prod 阶段。
这时您的管道应会与以下类似:
8.5 添加部署到生产阶段
在完成“Bake dev”和“Bake prod”阶段后,我们的 Kubernetes 部署文件已经准备就绪,可以用于部署。现在创建一个 Deploy dev 阶段,这将会部署到开发环境。选中 Bake dev 阶段后,单击 Add stage。将“Bake prod”作为一个依赖项与 Bake dev 一起添加。
8.6 添加人工判断阶段
许多团队希望有人来人工审批,然后再将部署推送到生成环境。如果您的团队属于这种情况,您可以添加一个“Manual Judgement”阶段。
单击 Add stage,然后从下拉列表中选择 Manual Judgement:
8.7 添加部署到生产阶段
这是我们的最后一个阶段,如果一切进展顺利,我们会将部署文件推送到生产环境。单击 Add stage 并选择预期构件 sample-microservice-prod, type: embedded/base64,从而创建此阶段。它应当拥有一个依赖项 Manual Judgement。
9.测试
在您的 Kubernetes 集群中创建两个命名空间:
kubectl create namespace sample-microservice-dev
kubectl create namespace sample-microservice-prod
现在您可以通过修改 main.go 并推送提交至 GitHub,从而对整个管道进行测试。您将一次看到以下事件:
- Jenkins 编译被触发。
- 新的 Docker 映像被发布到 Amazon ECR。
- Spinnaker 管道被触发。
您可以在管道屏幕上看到进度。在人工判断阶段,它将与以下类似:
单击 Continue,管道将继续将部署推送到生产环境。
祝贺您! 您已经启动并运行了您的 Spinnaker 管道。如需了解更多信息,请参阅官方的 Spinnaker 指南。
10.清除
完成测试后,您可以按照下列步骤执行清理:
10.1 删除 Helm 图表
helm delete spinnaker --purge
这将会删除与 Spinnaker Helm 部署关联的所有资源。
10.2 删除入站控制器
kubectl -n spinnaker delete ingress spinnaker
这将删除 Spinnaker 入站控制器。
小结
在本博文中,我们向大家演示了如何安装 Spinnaker 和创建持续交付管道。此外,我们还介绍了一些 Spinnaker 概念合同可以在构建管道时使用的不同类型的阶段。虽然此管道十分简单,Spinnaker 也支持多种其他功能,例如回滚和金雀花部署。它可以与 Jenkins 和 Travis CI 等 CI 工具集成。它还可以与 Prometheus 和 SignalFx 等集成以进行金雀花分析。要了解有关 Spinnaker 功能的更多信息,请参阅精彩的 Spinnaker 文档。
祝大家部署快乐!