发布于 2026-01-06 3 阅读
0

10 分钟速成 Google Cloud Kubernetes:使用 Node.js 和 Kubernetes 的 Semaphore CI/CD 流水线演示

十分钟速成谷歌云 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 并:

  1. 创建一个项目。默认情况下,Google 会分配一个随机名称,但您可以使用“编辑”按钮更改它。我更喜欢使用更具描述性的名称,例如semaphore-demo-nodejs-k8s……
  2. 请前往 IAM 并创建一个服务账号。该账号应为项目所有者。创建完成后,请创建并下载JSON 格式的密钥文件。
  3. Kubernetes Engine中,创建一个名为 `<cluster_name>` 的集群semaphore-demo-nodejs-k8s-server。您可以选择节点数量以及每台机器的配置。三个节点足以让您体验 Kubernetes 的基本功能。本次演示将使用配置最低的机器。
  4. 前往SQL控制台,在与集群相同的区域中创建一个 PostgreSQL 数据库。启用私有 IP网络。您也可以启用公共 IP 并将自己添加到白名单以便远程连接。记下 Google 分配给您的数据库的 IP 地址。
  5. 创建一个名为“数据库”的数据库demo和一个名为“用户名”的用户名demouser

我知道这很费工夫。好消息是你只需要做一次。

最后,fork演示版本

GitHub 标志 semaphoreci-demos / semaphore-demo-nodejs-k8s

使用 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

  1. Fork 此仓库并使用它来创建一个项目

  2. 在 Google Cloud 上创建项目:semaphore-demo-nodejs-k8s

  3. 在 Google Cloud 上创建 Kubernetes 集群:semaphore-demo-nodejs-k8s-server

  4. 在 Google Cloud 上创建 PostgreSQL 数据库。

  5. 创建数据库demo和用户demouser

  6. 复制环境文件并编辑数据库主机名和数据库密码:

    $ cp ormconfig.sample.json /tmp/ormconfig.production.json
    $ cp sample.env /tmp/production.env
    Enter fullscreen mode Exit fullscreen mode
  7. 将环境文件作为密钥上传:

    $ 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
  8. 在 IAM 中创建服务帐户:

    • 角色:项目负责人
    • 创建并下载访问密钥JSON文件。
  9. 将访问密钥作为密钥上传到 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 的私有容器注册表中。

推广和 Docker 构建

我们来看看它是如何运作的?打开.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

密钥和环境文件

我们需要将数据库用户名和密码传递给服务器。为此,我们将使用两个文件,这两个文件包含的变量基本相同:

  • 环境:一个包含环境变量的普通 bash 文件。
  • ormconfig: TypeORM的配置文件,TypeORM 是我们项目的数据库 ORM。

由于这些文件包含敏感信息,我们不应该将它们提交到 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>` 值替换hostpassword您的数据库 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_HOSTDB_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