十分钟速成谷歌云 Kubernetes
使用 Node.js 和 Kubernetes 的信号量演示 CI/CD 流水线
最初,谷歌创建了 Kubernetes。“让它开源,”谷歌说,于是源代码就开源了。谷歌也看到了它的优势。不开玩笑地说,如果说谁最了解如何运行 Kubernetes,那非谷歌莫属。
在这篇实践教程中,我们将学习如何使用 Semaphore CI/CD 将演示应用程序持续交付到 Google Kubernetes Engine。读完本文后,您将对 Kubernetes 的工作原理有更深入的了解,更重要的是,您还将拥有一个可供实践的持续交付流水线。
Kubernetes 中的部署是如何工作的?
Kubernetes部署就像俄罗斯套娃一样。应用程序运行在Docker容器中,容器又位于Pod中,Pod参与部署过程。
Pod 是一组运行在同一节点上并共享资源的 Docker 容器。Pod 是短暂的,可以根据需要随时启动和停止。为了获得稳定的公网 IP 地址,Kubernetes 提供了负载均衡服务,将传入的请求转发到各个 Pod。
定义部署的最直接方法是编写一个清单,就像我下面展示的那样。
首先,我们有 部署 资源,它持有并控制 Pod。部署包含一个状态 name和一个目标状态 spec,目标状态定义了最终期望状态:
副本数:要创建的 Pod 数量。将此数字设置为与集群中的节点数相匹配。例如,我使用三个 Pod,所以我将 其 更改 replicas: 3为 3 。
spec.containers:定义 Pod 中运行的 Docker 镜像。我们将把镜像上传到 Google 私有镜像仓库,然后从那里拉取镜像。
标签:它们是附加到 Pod 上的键值映射。然后,我们可以利用它们 matchLabels将部署与 Pod 关联起来。
apiVersion : apps/v1
kind : Deployment
metadata :
name : semaphore-demo-nodejs-k8s-server
spec :
replicas : 3
selector :
matchLabels :
app : semaphore-demo-nodejs-k8s-server
template :
metadata :
labels :
app : semaphore-demo-nodejs-k8s-server
spec :
containers :
- name : semaphore-demo-nodejs-k8s-server
image : gcr.io/$GCP_PROJECT_ID/semaphore-demo-nodejs-k8s-server:$SEMAPHORE_WORKFLOW_ID
env :
- name : NODE_ENV
value : " production"
Enter fullscreen mode
Exit fullscreen mode
清单的最后一部分是 服务 。负载均衡器服务会暴露一个稳定的公网 IP 地址供用户连接。我们告诉 Kubernetes,该服务将为标记为 `<load-balancer-service-name>` 的 Pod 提供服务 app: semaphore-demo-nodejs-k8s-server。
kind : Service
metadata :
name : semaphore-demo-nodejs-k8s-lb
spec :
selector :
app : semaphore-demo-nodejs-k8s-server
type : LoadBalancer
ports :
- port : 80
targetPort : 3001
Enter fullscreen mode
Exit fullscreen mode
在使用此清单之前,我们需要两样东西:
将 Docker 镜像推送到 Google 私有仓库。
将清单文件发送到集群。
我们将在下一节中处理这两个问题。但首先,让我们在谷歌云上创建必要的服务。
CI/CD 和 Kubernetes
我们将使用 Semaphore 来运行我们的 持续集成和交付 工作流程:
持续集成:哪怕是最微小的错误都可能导致网站宕机或应用程序崩溃。我们将代码通过持续集成流水线进行测试,以便在错误渗透到部署环境之前将其清除。
Dockerize:为每次更新生成 Docker 镜像,以便我们可以跟踪生产环境中正在运行的确切版本,并且可以在几秒钟内回滚或向前更新。
部署:100% 自动化部署到 Google Kubernetes。无需人工干预,意味着更可靠、更频繁的发布。
由于我希望专注于 Kubernetes 部署,因此我将完全跳过持续集成部分。如果您感兴趣并想详细了解其工作原理,可以在 Semaphore 博客上找到 完整的演示 教程。
准备工作
您需要注册一些服务: Google Cloud Platform 将作为我们的云服务提供商; GitHub 用于存放应用程序代码; Semaphore 用于 CI/CD。我建议您安装 Semaphore CLI 以便快速完成设置。
前往您的 Google Cloud Platform 并:
创建一个项目。默认情况下,Google 会分配一个随机名称,但您可以使用 “编辑” 按钮更改它。我更喜欢使用更具描述性的名称,例如 semaphore-demo-nodejs-k8s……
请前往 IAM 并创建一个 服务账号 。该账号应为 项目 所有者 。创建完成后,请创建并下载JSON 格式的 密钥文件。
在 Kubernetes Engine 中,创建一个名为 `<cluster_name>` 的集群 semaphore-demo-nodejs-k8s-server。您可以选择节点数量以及每台机器的配置。三个节点足以让您体验 Kubernetes 的基本功能。本次演示将使用配置最低的机器。
前往 SQL 控制台,在与集群相同的区域中创建一个 PostgreSQL 数据库。启用 私有 IP 网络。您也可以启用公共 IP 并将自己添加到白名单以便远程连接。记下 Google 分配给您的数据库的 IP 地址。
创建一个名为“数据库”的数据库 demo和一个名为“用户名”的用户名 demouser。
我知道这很费工夫。好消息是你只需要做一次。
最后,fork 演示版本 。
使用 Node.js 和 Kubernetes 的 Semaphore 演示 CI/CD 流水线
使用 Node.js 和 Kubernetes 的信号量演示 CI/CD 流水线
示例应用程序和 CI/CD 管道展示了如何在 Semaphore 2.0 上运行 Node.js 项目。
该应用程序基于 Nest.js,代码使用 TypeScript 编写。
该应用程序已部署到 Google Cloud Kubernetes。
信号灯上的 CI/CD
Fork 此仓库并使用它来 创建一个项目 。
在 Google Cloud 上创建项目: semaphore-demo-nodejs-k8s
在 Google Cloud 上创建 Kubernetes 集群: semaphore-demo-nodejs-k8s-server
在 Google Cloud 上创建 PostgreSQL 数据库。
创建数据库 demo和用户 demouser。
复制环境文件并编辑数据库主机名和数据库密码:
$ cp ormconfig.sample.json /tmp/ormconfig.production.json
$ cp sample.env /tmp/production.env
Enter fullscreen mode
Exit fullscreen mode
将环境文件作为密钥上传:
$ sem create secret production-env \
-f /tmp/ormconfig.production.json:/home/semaphore/ormconfig.production.json \
-f /tmp/production.env:/home/semaphore/production.env
Enter fullscreen mode
Exit fullscreen mode
在 IAM 中创建服务帐户:
角色:项目负责人
创建并下载访问密钥JSON文件。
将访问密钥作为密钥上传到 Semaphore:
$ sem create secret gcr-secret \
-e GCP_PROJECT_ID=semaphore-demo-nodejs-k8s …
Enter fullscreen mode
Exit fullscreen mode
克隆它,并将其添加到 Semaphore:
$ cd semaphore-demo-nodejs-k8s
$ sem init
Enter fullscreen mode
Exit fullscreen mode
该应用程序实现了一个 API 接口。它使用 TypeScript 和 Nest.js 框架编写。
Dockerize Pipeline
该 流水线 准备 Docker 镜像,然后将其推送到 Google 的私有 容器注册表 中。
我们来看看它是如何运作的?打开 .semaphore/docker-build.yml。
文件开头有 name管道的配置信息 agent。代理会告诉 Semaphore 哪些可用 机器 和操作系统运行作业:
version : v1.0
name : Docker build server
agent :
machine :
type : e1-standard-2
os_image : ubuntu1804
Enter fullscreen mode
Exit fullscreen mode
代码块 和 作业 决定了 流水线的 执行顺序。代码块按顺序依次执行,而代码块内的作业则并行执行。如果作业中的任何命令失败,流水线就会停止运行。
以下是 Docker 构建模块:
blocks :
- name : Build
task :
secrets :
- name : gcr-secret
- name : production-env
prologue :
commands :
- gcloud auth activate-service-account --key-file=.secrets.gcp.json
- gcloud auth configure-docker -q
- gcloud config set project $GCP_PROJECT_ID
- gcloud config set compute/zone $GCP_PROJECT_DEFAULT_ZONE
- checkout
jobs :
- name : Docker build
commands :
- cp /home/semaphore/ormconfig.production.json ormconfig.json
- cp /home/semaphore/production.env production.env
- docker pull "gcr.io/$GCP_PROJECT_ID/semaphore-demo-nodejs-k8s-server:latest" || true
- docker build --cache-from "gcr.io/$GCP_PROJECT_ID/semaphore-demo-nodejs-k8s-server:latest" -t "gcr.io/$GCP_PROJECT_ID/semaphore-demo-nodejs-k8s-server:$SEMAPHORE_WORKFLOW_ID" .
- docker images
- docker push "gcr.io/$GCP_PROJECT_ID/semaphore-demo-nodejs-k8s-server:$SEMAPHORE_WORKFLOW_ID"
Enter fullscreen mode
Exit fullscreen mode
该命令 prologue在每个作业执行之前执行。它配置 gcloud 以使其与项目协同工作。首先,我们需要使用 `gcloud.config` 获取授权 gcloud auth。接下来,我们将 gcloud 配置为 Docker 助手,以便可以使用私有镜像仓库。最后,我们为会话设置活动项目和区域。
检出操作 会克隆存储库。
构建作业会将一些配置文件复制到 Docker 镜像中,并将其推送到镜像仓库。 为了给镜像添加标签,我们使用 `<image_tag>` 标签 $SEMAPHORE_WORKFLOW_ID,该标签保证在每个工作流中都是唯一的。
此时,您可能想知道这些配置文件和环境变量是从哪里来的。它们是通过 secrets关键字导入的。信号量 密钥 机制允许我们将敏感数据安全地存储在代码库之外。我们稍后会创建这些密钥。
读取完这条管道后,我们可以通过 推广 将其与下一条管道连接起来:
promotions :
- name : Deploy server to Kubernetes
pipeline_file : deploy-k8s.yml
auto_promote_on :
- result : passed
Enter fullscreen mode
Exit fullscreen mode
密钥和环境文件
我们需要将数据库用户名和密码传递给服务器。为此,我们将使用两个文件,这两个文件包含的变量基本相同:
由于这些文件包含敏感信息,我们不应该将它们提交到 GitHub。相反,我们应该将它们作为 Secrets 上传到 Semaphore。Semaphore中的 Secrets 会自动加密,并在您的作业请求时提供。
将提供的示例配置复制到您的代码仓库之外,例如复制到您的 /tmp目录中:
$ cp ormconfig.sample.json /tmp/ormconfig.production.json
$ cp sample.env /tmp/production.env
Enter fullscreen mode
Exit fullscreen mode
编辑 ormconfig.production.json。将 `<database_ip_address>` 和 `<password>` 值替换 host为 password您的数据库 IP 地址和密码 demouser。文件的第一部分应如下所示:
{
"type" : "postgres" ,
"host" : "YOUR_DB_IP" ,
"port" : 5432 ,
"username" : "demouser" ,
"password" : "YOUR_DB_PASSWORD" ,
"database" : "demo" ,
. . .
Enter fullscreen mode
Exit fullscreen mode
编辑 production.env。设置 NODE_ENV=production,保持不变,并 根据需要 PORT更改 DB_HOST, DB_PASSWORD和: DB_PORT
NODE_ENV = production
PORT = 3001
URL_PREFIX = v1/api
DATABASE_HOST = YOUR_DB_IP
DATABASE_USER = demouser
DATABASE_PASSWORD = YOUR_DB_PASSWORD
DATABASE_DBNAME = demo
DATABASE_PORT = 5432
Enter fullscreen mode
Exit fullscreen mode
将这两个文件作为名为“secret”的密钥上传到 Semaphore production-env:
$ sem create secret production-env \
-f /tmp/production.env:/home/semaphore/production.env \
-f /tmp/ormconfig.production.json:/home/semaphore/ormconfig.production.json
Enter fullscreen mode
Exit fullscreen mode
我们需要创建第二个密钥来存储与 Google 相关的信息和服务帐户 JSON 密钥:
$ sem create secret gcr-secret \
-e GCP_PROJECT_ID = semaphore-demo-nodejs-k8s \
-e GCP_PROJECT_DEFAULT_ZONE = YOUR_REGION \
-f YOUR_GCP_ACCESS_KEY_FILE.json:/home/semaphore/.secrets.gcp.json
Enter fullscreen mode
Exit fullscreen mode
部署管道
有了 Docker 镜像,我们就可以在我们的 Kubernetes 集群上运行它了。
请查看部署管道 .semaphore/deploy-k8s.yml。它由 2 个模块组成,每个模块包含一个作业。
gcloud序言中的 大多数命令我们都见过了,这里唯一的新命令是 gcloud container,该命令用于检索以下 kubectl命令的 Kubernetes 配置文件。
这样 envsubst我们就可以直接展开环境变量。结果会生成一个纯 YAML 文件。最后一步是使用 kubectl apply 将清单文件发送到我们的集群:
blocks :
- name : Deploy to Kubernetes
task :
secrets :
- name : gcr-secret
env_vars :
- name : CLUSTER_NAME
value : semaphore-demo-nodejs-k8s-server
prologue :
commands :
- gcloud auth activate-service-account --key-file=.secrets.gcp.json
- gcloud auth configure-docker -q
- gcloud config set project $GCP_PROJECT_ID
- gcloud config set compute/zone $GCP_PROJECT_DEFAULT_ZONE
- gcloud container clusters get-credentials $CLUSTER_NAME --zone $GCP_PROJECT_DEFAULT_ZONE --project $GCP_PROJECT_ID
- checkout
jobs :
- name : Deploy
commands :
- cat deployment.yml | envsubst | tee deployment.yml
- kubectl apply -f deployment.yml
Enter fullscreen mode
Exit fullscreen mode
至此,我们几乎完成了。为了标记此镜像正在集群上运行,我们添加了最后一个代码块,将镜像标记为 latest。以下是相关命令:
- docker pull "gcr.io/$GCP_PROJECT_ID/semaphore-demo-nodejs-k8s-server:$SEMAPHORE_WORKFLOW_ID"
- docker tag "gcr.io/$GCP_PROJECT_ID/semaphore-demo-nodejs-k8s-server:$SEMAPHORE_WORKFLOW_ID" "gcr.io/$GCP_PROJECT_ID/semaphore-demo-nodejs-k8s-server:latest"
- docker push "gcr.io/$GCP_PROJECT_ID/semaphore-demo-nodejs-k8s-server:latest"
Enter fullscreen mode
Exit fullscreen mode
准备好进行试运行了吗?推送修改,然后观察管道运行情况。
$ git add deployment.yml
$ git add .semaphore/*
$ git commit -m "first deployment”
$ git push origin master
Enter fullscreen mode
Exit fullscreen mode
您可以通过 Semaphore 帐户查看作业进度。请稍等几分钟,直到所有流水线都完成。希望一切正常,现在我们可以检查集群状态了。
以下是从 Google Cloud 控制台连接到集群的最简单方法:
Kubernetes Engine > 集群 > 选择您的集群 > 连接 按钮
您将获得一个连接到该项目的浏览器终端。
我们来检查一下集群。首先,检查一下 Pod:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
semaphore-demo-nodejs-k8s-server-6b95cf5dfd-hgrmn 1/1 Running 0 97s
semaphore-demo-nodejs-k8s-server-6b95cf5dfd-jgc9p 1/1 Running 0 112s
semaphore-demo-nodejs-k8s-server-6b95cf5dfd-r29gc 1/1 Running 0 105s
Enter fullscreen mode
Exit fullscreen mode
每个 pod 都被分配了一个不同的名称;它们都在运行我们应用程序的一个副本。
接下来,我们来检查部署情况:
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
semaphore-demo-nodejs-k8s-server 3/3 3 3 12m
Enter fullscreen mode
Exit fullscreen mode
部署正在控制这 3 个 pod。我们被告知这 3 个 pod 可用且已是最新版本。
最后,我们来检查一下服务:
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT( S) AGE
kubernetes ClusterIP 10.36.0.1 <none> 443/TCP 71m
semaphore-demo-nodejs-k8s-server-lb LoadBalancer 10.36.9.180 104.154.96.87 80:32217/TCP 12m
Enter fullscreen mode
Exit fullscreen mode
忽略 ClusterIP 服务,那是部署之前就有的服务。我们可以使用负载均衡器服务的外部 IP 地址连接到应用程序。
让我们用 curl 测试一下这个应用程序:
$ curl -w " \n " -X POST -d \
"username=jimmyh&firstName=Johnny&lastName=Hendrix&age=30&description=Burn the guitar" \
http://YOUR_EXTERNAL_IP/v1/api/users
{
"username" : "jimmyh" ,
"description" : "Burn the guitar" ,
"age" : "30" ,
"firstName" : "Johnny" ,
"lastName" : "Hendrix" ,
"id" : 1,
"createdAt" : "2019-08-05T20:45:48.287Z" ,
"updatedAt" : "2019-08-05T20:45:48.287Z"
}
Enter fullscreen mode
Exit fullscreen mode
API 端点接受 以下参数并 GET请求 : POSTDELETE
$ curl -w " \n " http://YOUR_EXTERNAL_IP/v1/api/users/1
{
"id" : 1,
"username" : "jimmyh" ,
"description" : "Burn the guitar" ,
"firstName" : "Johnny" ,
"lastName" : "Hendrix" ,
"age" : 30,
"createdAt" : "2019-08-05T20:45:48.287Z" ,
"updatedAt" : "2019-08-05T20:45:48.287Z"
}
Enter fullscreen mode
Exit fullscreen mode
结论
这段路程虽然漫长,但希望一切顺利。现在您已经知道如何为 Google Cloud Kubernetes Engine 构建 CI/CD 流水线了。
一些想法可以这样玩:
创建一个测试集群。
构建一个开发容器并在其中运行测试。
通过滚动更新 增强您的清单 。
想用AWS而不是Google?看看这篇教程:
如果您想了解更多关于 Semaphore 如何与 Kubernetes 和 Docker 协同工作的信息,请查看以下内容:
你觉得这篇文章有用吗?点赞❤️和🦄,关注我或在下方留言。
对 CI/CD 和 Kubernetes 感兴趣吗?我们正在编写一本免费电子书, 注册 即可在发布后第一时间收到。
感谢阅读!
文章来源:https://dev.to/semaphore/google-cloud-kubernetes-in-10-minutes-2enb