本教程介绍如何使用 Jenkins 和 Google Kubernetes Engine (GKE) 设置持续交付流水线,如下图所示。
目标
- 了解示例应用。
- 将应用部署到 GKE。
- 将代码上传到 Cloud Source Repositories。
- 在 Jenkins 中创建部署流水线。
- 部署开发环境。
- 部署 Canary 版本。
- 部署生产环境。
费用
本教程使用 Google Cloud 的以下收费组件:
- Compute Engine
- Google Kubernetes Engine
- Cloud Build
准备工作
-
登录您的 Google 帐号。
如果您还没有 Google 帐号,请注册新帐号。
-
在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。
-
确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能。
- 启用 Compute Engine, GKE, and Cloud Build API。
准备环境
完成在 GKE 上设置 Jenkins 教程。 确保您在 GKE 中安装的 Jenkins 是在安装运行。
在 Cloud Shell 中,克隆示例代码:
git clone https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes cd continuous-deployment-on-kubernetes/sample-app
将
cluster-admin
角色应用于 Jenkins 服务帐号:kubectl create clusterrolebinding jenkins-deploy \ --clusterrole=cluster-admin --serviceaccount=default:cd-jenkins
在本教程中,Jenkins 服务帐号需要
cluster-admin
权限才能创建应用所需的 Kubernetes 命名空间和任何其他资源。对于生产用途,您应该为必要的各项权限编目,并将其分别应用于服务帐号。
了解应用
您将在持续部署流水线中部署示例应用 gceme
。该应用使用 Go 语言编写,位于代码库的 sample-app
目录中。当您在 Compute Engine 实例上运行 gceme
二进制文件时,应用会在信息卡片中显示实例的元数据。
该应用通过支持两种操作模式来模拟微服务:
在后端模式下,
gceme
侦听端口 8080 并以 JSON 格式返回 Compute Engine 实例元数据。在前端模式下,
gceme
查询后端gceme
服务,并在用户界面中显示 JSON 格式的查询结果。
前端模式和后端模式支持两个额外的网址:
/version
打印正在运行的版本。/healthz
报告应用的运行状况。在前端模式下,如果后端可以访问,则运行状况会显示为OK
。
将示例应用部署到 Kubernetes
使用描述部署环境的清单文件将 gceme
前端和后端部署到 Kubernetes。这些文件使用的是本教程后面更新的默认映像。
将应用部署到两个环境中。
生产环境。您的用户访问的实际网站。
Canary 环境。容量较小的网站,可接收一定比例的用户流量。使用此环境可以在将软件发布到实际环境之前通过实时流量对软件进行健全性检查。
首先,将您的应用部署到生产环境中,以使用工作代码为流水线设定种子。
创建 Kubernetes 命名空间以从逻辑上隔离生产部署:
kubectl create ns production
创建 Canary 和生产部署和服务:
kubectl --namespace=production apply -f k8s/production kubectl --namespace=production apply -f k8s/canary kubectl --namespace=production apply -f k8s/services
对生产环境前端进行纵向扩容:
kubectl --namespace=production scale deployment gceme-frontend-production --replicas=4
检索生产服务的外部 IP。您可能需要几分钟才能看到负载平衡器的 IP 地址。
kubectl --namespace=production get service gceme-frontend
该过程完成后,IP 地址将显示在
EXTERNAL-IP
列中。NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gceme-frontend LoadBalancer 10.35.254.91 35.196.48.78 80:31088/TCP 1m
将前端服务负载平衡器的 IP 存储在环境变量中:
export FRONTEND_SERVICE_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}" --namespace=production services gceme-frontend)
通过在浏览器中打开前端外部 IP 地址,确认两个服务都正常运行。
打开一个单独的终端并轮询生产端点的
/version
网址,以便在下一部分中观察滚动更新。while true; do curl http://$FRONTEND_SERVICE_IP/version; sleep 1; done
创建代码库以托管示例应用源代码
接下来,创建 gceme
示例应用的副本并将其推送到 Cloud Source Repositories。
运行以下命令在 Cloud Source Repositories 中创建代码库:
gcloud source repos create gceme
初始化本地 Git 代码库:
git init git config credential.helper gcloud.sh export PROJECT_ID=$(gcloud config get-value project) git remote add origin https://source.developers.google.com/p/$PROJECT_ID/r/gceme
为代码库中的 Git 提交设置用户名和电子邮件地址。 将
[EMAIL_ADDRESS]
替换为您的 Git 电子邮件地址,并将[USERNAME]
替换为您的 Git 用户名。git config --global user.email "[EMAIL_ADDRESS]" git config --global user.name "[USERNAME]"
添加、提交和推送文件:
git add . git commit -m "Initial commit" git push origin master
创建流水线
使用 Jenkins 定义和运行流水线,以便对您的 gceme
副本进行测试、构建,并将其部署到 Kubernetes 集群。
添加服务帐号凭据
配置凭据以允许 Jenkins 访问代码库。
- 在 Jenkins 用户界面中,点击左侧导航中的凭据。
点击凭据表中的 Jenkins 链接。
点击全局凭据。
点击左侧导航中的添加凭据。
从种类下拉列表中选择元数据中的 Google 服务帐号。
点击确定。
现在有两个全局凭据。记下第二个凭据的名称,以便稍后在本教程中使用。
创建 Jenkins 作业
接下来,使用 Jenkins 流水线功能配置构建流水线。Jenkins 流水线文件使用类 Groovy 的语法编写。
导航到 Jenkins 用户界面并按照以下步骤配置流水线作业。
- 点击界面左上角的 Jenkins 链接。
- 点击左侧导航中的新建内容链接。
- 将项目命名为 sample-app,选择多分支流水线选项,然后点击确定。
- 在下一页上,点击添加源并选择 git。
将 Cloud Source Repositories 中
sample-app
代码库的 HTTPS 克隆网址粘贴到项目代码库字段中。将[PROJECT_ID]
替换为您的项目 ID。https://source.developers.google.com/p/[PROJECT_ID]/r/gceme
从凭据下拉列表中,选择添加服务帐号时创建的凭据的名称。
在扫描多分支流水线部分中,选择如果不运行则定期扫描框。将间隔值设置为“1分钟”。
点击保存。
完成这些步骤后,系统将运行名为“Branch indexing”的作业。此元作业标识代码库中的分支,并确保现有分支中未发生更改。如果刷新 Jenkins,master
分支将显示此作业。
第一次运行此作业会失败,直到您在下一步中进行一些代码更改。
修改流水线定义
为 Canary 环境创建一个名为 canary
的分支。
git checkout -b canary
定义该流水线的 Jenkinsfile 容器使用 Jenkins Pipeline Groovy 语法编写。 使用 Jenkinsfile 可以将整个构建流水线表示在与源代码共存的单个文件中。流水线支持强大的功能(如并行化)且需要手动用户批准。
修改 Jenkinsfile,使其包含第 1 行的项目 ID。
部署 Canary 版本
现在您的流水线已配置正确,您可以对 gceme
应用进行更改,并用流水线对其进行测试、打包和部署。
Canary 环境被设置为 Canary 版本。
因此,您的更改将发布到生产负载平衡器后面的一小部分 pod 中。您可以通过维护共享相同标签的多个部署,在 Kubernetes 中实现此目的。对于此应用,gceme-frontend
服务在具有标签 app: gceme
和 role: frontend
的所有 pod 中实现负载平衡。k8s/frontend-canary.yaml
Canary 清单文件将副本设置为 1
并包含 gceme-frontend
服务所需的标签。
目前,您有五分之一的前端 pod 运行 Canary 代码,其他五分之四运行生产代码。这有助于确保在发布至所有 pod 之前,Canary 代码不会对用户产生负面影响。
- 打开
html.go
并将blue
的两个实例替换为orange
。 打开
main.go
并将版本号从1.0.0
更改为2.0.0
:const version string = "2.0.0"
接下来,添加这些文件并将其提交到本地代码库:
git add Jenkinsfile html.go main.go git commit -m "Version 2"
最后,将您的更改推送到远程 Git 服务器:
git push origin canary
将更改推送到 Git 代码库后,导航到 Jenkins 界面,您可以在其中看到您的构建已启动。
构建运行后,点击左侧导航窗格中构建旁边的向下箭头,然后选择控制台输出。
跟踪构建的输出几分钟,并观察
kubectl --namespace=production apply...
消息是否开始。开始后,请检查正在轮询生产/version
网址的终端,并观察某些请求是否开始更改。现在,您已将该更改发布至一部分用户。将更改部署到 Canary 环境后,您可以通过将代码与
master
分支合并并将其推送到 Git 服务器,继续将更改发布至其他用户。git checkout master git merge canary git push origin master
大约 1 分钟后,
sample-app
文件夹中的master
作业开始运行。点击
master
链接可显示流水线的各个阶段,以及通过/失败信息和时序特征。轮询生产网址以验证新版本 2.0.0 是否已发布,以及是否正在处理来自所有用户的请求。
export FRONTEND_SERVICE_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}" --namespace=production services gceme-frontend) while true; do curl http://$FRONTEND_SERVICE_IP/version; sleep 1; done
您可以查看项目中的 Jenkinsfile 以查看工作流。
部署开发分支
有时您需要处理无法直接推送到 Canary 环境的重大更改,因而催生了开发分支,这是开发者在提交代码更改以将其集成到实际网站之前对其进行测试的一组环境。这些环境是应用的缩小版本,但使用与实际环境相同的机制进行部署。
如需从功能分支创建开发环境,可以将该分支推送到 Git 服务器,通过 Jenkins 部署您的环境。在开发场景中,您不应使用公开的负载平衡器。为了帮助保护您的应用,您可以使用 kubectl 代理。此代理使用 Kubernetes API 对自身进行身份验证,并将来自本地机器的请求代理到集群中的服务,而不会将您的服务暴露给互联网。
创建另一个分支并将其推送到 Git 服务器。
git checkout -b new-feature git push origin new-feature
系统将创建一个新作业,并且您的开发环境正在创建中。作业的控制台输出的底部是访问环境的说明。
在后台启动代理。
kubectl proxy &
使用 localhost 验证您的应用是否可供访问:
curl http://localhost:8001/api/v1/namespaces/new-feature/services/gceme-frontend:80/proxy/
您现在可以将代码推送到此分支以更新您的开发环境。完成后,将您的分支合并回
canary
,以将该代码部署到 Canary 环境中。git checkout canary git merge new-feature git push origin canary
如果您确信您的代码不会在生产环境中产生问题,请从
canary
分支合并到master
分支以启动部署:git checkout master git merge canary git push origin master
用完开发分支后,将其从服务器中删除并从 Kubernetes 集群中删除该环境:
git push origin :new-feature kubectl delete ns new-feature
清理
为避免因本教程中使用的资源导致您的 Google Cloud 帐号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。
删除项目
为了避免产生费用,最简单的方法是删除您为本教程创建的项目。
如需删除项目,请执行以下操作:
- 在 Cloud Console 中,转到管理资源页面。
- 在项目列表中,选择要删除的项目,然后点击删除。
- 在对话框中输入项目 ID,然后点击关闭以删除项目。
后续步骤
- 详细了解 GKE 上的 Jenkins 的最佳做法。
- 参阅在 GKE 上设置 Jenkins 教程。
- 了解如何为 GKE 配置 Jenkins。
- 试用其他 Google Cloud 功能。查阅我们的教程。