NGINX.COM
Web Server Load Balancing with NGINX Plus

本文是“Microservices June 微服务之月 2023”系列教程之一,旨在帮助您将概念付诸实践。

7 月 1 日前免费注册线上教学项目 NGINX 微服务之月,并在 8 月 1 日前按要求完成课程,即可获得 NGINX 独家纪念礼品以及结课证书。

本文末尾包括本实验的验收标准,想要获取礼品和证书的同学,请在 8 月 1 日前随单元小测提交实验结果。

本系列教程包括:

本教程希望能够帮助您深入了解微服务架构下的自动化部署和 CI/CD 的核心原理和实现方法,以及如何应用这些知识来推动企业的数字化转型。

 

概述

自动化部署对于大多数项目的成功至关重要。然而,仅仅部署代码是不够的。您还需要确保停机时间有限(或消除),并且在失败的情况下快速回滚。将金丝雀部署蓝绿部署组合起来是确保新代码可行的常见方法。该策略包括两个步骤:

  • 步骤1:金丝雀部署以隔离测试 – 将代码部署到环境之外的独立节点、服务器或容器中,测试以确保代码按预期工作。
  • 步骤2:蓝绿部署以生产环境测试 – 假设代码在金丝雀部署中工作,将代码移植到新创建的服务器(或节点或容器)中,与当前版本的服务器并行存在于您的生产环境中。然后重定向一部分生产流量到新版本,以测试它是否在更高的负载下继续良好地工作。通常,您从将一小部分(例如 10%)流量引导到新版本开始,并逐步增加它,直到新版本接收所有流量。增量的大小取决于您对新版本是否能够处理流量的信心;您甚至可以在单个步骤中完全切换到新版本。

如果您不熟悉在应用程序或网站的不同版本之间分配流量的不同用例(流量分割),请阅读我们博客上的文章《如何使用高级流量管理提高 Kubernetes 的弹性》了解蓝绿部署、金丝雀发布、A/B 测试、速率限制、断路器等的概念。虽然博客是针对 Kubernetes 的,但这些概念广泛适用于微服务应用程序。

 

教程概述

在本教程中,我们展示如何使用 Gitlab 自动化部署的第一步。在教程的四个挑战中,您可以使用 Docker Desktop 或者其他 K8S 环境部署应用程序的新版本

  • 创建和部署 NGINX 容器应用程序
  • 使用 Gitlab CI/CD
  • 测试 Gitlab CI/CD 工作流程
  • 注意:虽然本教程使用 Docker Destop K8S 环境,但是这些概念和技术可以应用于任何被授权的 K8S 环境(例如:阿里云、腾讯云等)。

GitLab CI/CD 简介

GitLab CI/CD 是 GitLab 提供的持续集成和持续部署的解决方案。它可以帮助团队自动化构建、测试和部署应用程序,从而提高生产力并加速交付速度。使用 GitLab CI/CD,您可以将 CI/CD 管道集成到您的开发工作流中,从而自动执行以下任务:

  • 检查代码并运行测试
  • 构建和打包应用程序
  • 部署应用程序到各种环境(如开发环境、测试环境和生产环境)
  • 监控应用程序的运行状况并自动执行故障恢复操作

GitLab CI/CD 可以与各种语言和框架一起使用,并支持多种部署方式,包括 Kubernetes、AWS、GCP、Azure 等。它还提供了一个直观且易于使用的界面,使得团队可以快速上手并开始构建 CI/CD 管道。

极狐参考文档:[https://docs.gitlab.com/ee/administration/cicd.html]

 

自动化发布/部署先期准备工作

在你开始本实验之前,请做好一下准备工作

  • K8S 集群环境(GKE,EKS,AKS,AKC,笔记本 Docker Desktop with Kubernetes 均可)

    检查环境有效性:

    kubectl get all -A
    
  • Gitlab(https://gitlab.com/)账户或者极狐(https://jihulab.com)账户

  • Helm 环境

    检查 helm 命令安装成功

    helm version
    
  • Visual Studio Code

    检查 git 环境

    git -v
    
  • nodejs 19.x 运行环境

    检查 nodejs 命令安装成功

    node -v
    

Untitled

 

挑战 1 – 安装 CI/CD 环境安装

1 – 创建分支

首先 Login 到你自己的 Gitlab 中,然后在我们这个 Repository 基础上建立一个分支(branch),点击 Fork

Untitled

选择目标地。

2 – 克隆到本地

可以使用 vscode 自带的 Clone Git 能力或者 Git 命令都可以,使用 vscode 请参阅 Demo,Git 命令如下:

git clone <https://jihulab.com/f5/microservices-june-2023-automation.git>

Untitled

完成后你可以看到一个类似于这样的目录结构

☝ 至此你已经完成了你的第一个 Gitlab 项目

自我检查:
1. 确认文件夹已经完整克隆
2. 检查 git branch 的输出为 main

 

挑战 2 – 配置 Agent Config

自动化部署是现代软件开发流程中至关重要的一环。它的目的是为了让软件交付流程更快速、更可靠。在实践中,自动化部署通常包括两种方式:推送(PUSH)和拉取(PULL)。推送通常是指将代码和配置文件推送到服务器上,而拉取则是指从代码仓库中拉取代码并自动构建和部署到服务器上。这里我们使用拉的方式(Gitops)来完成 CI/CD,有兴趣的同学也可以尝试用 Git Runner 来完成。

1- 编写 Agent 配置文件

使用 Gitops 需要在 K8S 上部署一个 Agent,首先需要配置 .gitlab/agents/my-agent/config.yaml 配置文件这里已经为大家准备好,不用任何操作。

gitops:
  manifest_projects:
  - id: "F5/Microservices-June-2023-automation"
    ref: # either `branch`, `tag`, or `commit` can be specified
      branch: main
    paths:
    - glob: '/deploy/**/*.{yaml,json}'

💡 这里的 id: F5/Microservices-June-2023-automation 请改为你自己的名字,my-agent 可以改为你喜欢的任意名字

这是一个 GitOps 的配置文件示例,其中有一个 manifest_projects 的配置项,用于指定 GitOps 管理的 Kubernetes YAML 或 JSON 配置文件所在的路径。其中,id 属性用于唯一标识该项目,paths 属性用于指定该项目包含的文件路径,使用 glob 模式进行匹配。

在此示例中,idF5/Microservices-June-2023-automation,该项目包含的文件路径为 / 下所有的 YAML 或 JSON 文件。

glob 是一种文件名匹配模式,它允许您使用通配符字符(如 * 和 ?)来匹配文件或目录的名称。在 GitOps 的配置文件示例中,glob 模式用于匹配指定目录下的 YAML 或 JSON 文件。例如,’/**/*.yaml’ 可以匹配所有子目录下的 YAML 文件。

在这个示例中,glob 应该被设置为 'deploy/**/*.yaml',以匹配 F5/Microservices-June-2023-automation 项目下的 deploy 文件夹中的所有 YAML 文件。

要在 GitLab 中使用 GitOps 实现自动部署,您需要配置以下组件:

  1. GitLab CI/CD 管道:使用 CI/CD 管道从 Git 存储库的 deploy 目录中提取 YAML 文件并部署它们。
  2. GitLab Agent:在 Kubernetes 集群上运行的 GitLab Agent,用于执行 CI/CD 管道。

在我们的 Lab 中,Agent 启动后,k8s 就会部署这个 /deploy/xc-simple-login.yaml 这个配置文件

2 – 配置 Kubernetes clusters

点击左侧菜单栏中的 Infrastructure 下的 Kubernetes clusters,选择

使用以下 Helm 命令在 Kubernetes 集群中安装 GitLab Agent:

helm repo add gitlab https://charts.gitlab.io
helm repo update
helm upgrade --install my-agent gitlab/gitlab-agent \
    --namespace gitlab-agent-my-agent \
    --create-namespace \
    --set image.tag=v15.11.0-rc2 \
    --set config.token=<your key> \
    --set config.kasAddress=wss://kas.jihulab.com

在这个命令中,<your key> 应该替换为您的 GitLab key。使用极狐时创建 cluster 时,这个命令和 key 都会自动产生。

Untitled

大约 5 分钟后,my-agent 就能自动部署完成。

Untitled

💡 注意,由于 fork 操作会直接启动 CI Pipeline,因此检查 pipeline 时会发现 deploy 作业不成功,这个是正常的,后续提交 commit 会再次执行 pipeline,或者等 my-agent 部署完直接 retry。

自我检查:
1. 使用 helm list -A 检查 agent 的部署情况
2. 使用 kubectl get all -A 检查 deploy, service, pod 的启动情况

 

挑战 3 – 配置 CI

这里已经为大家准备好,不用任何操作。

stages:          # List of stages for jobs, and their order of execution
  - package
  - deploy

# Use the official docker image.

docker-build:       # This job runs in the package stage
  stage: package
  image: docker:latest
  services:
    - docker:dind
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
  # Default branch leaves tag empty (= latest tag)
  # All other branches are tagged with the escaped branch name (commit ref slug)
  script:
    - echo "Dockering application..."
    - |
      if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then
        tag=""
        echo "Running on default branch '$CI_DEFAULT_BRANCH': tag = 'latest'"
      else
        tag=":$CI_COMMIT_REF_SLUG"
        echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag"
      fi
    - docker build --pull -t "$CI_REGISTRY_IMAGE${tag}" .
    - docker push "$CI_REGISTRY_IMAGE${tag}"
  # Run this job in a branch where a Dockerfile exists
  rules:
    - if: $CI_COMMIT_BRANCH
      exists:
        - Dockerfile

deploy-job:      # This job runs in the deploy stage.
  stage: deploy  # It only runs when *both* jobs in the test stage complete successfully.
  environment: dev
  image:
    name: bitnami/kubectl:latest
    entrypoint: [""]
  script:
    - echo "Deploying application..."
    - kubectl config get-contexts
    - kubectl config use-context "$CI_PROJECT_NAMESPACE"/"$CI_PROJECT_NAME":my-agent
    - echo "kubectl set image deployment/xc-simple-login xc-simple-login=$CI_REGISTRY_IMAGE:latest"
    - kubectl set image deployment/xc-simple-login xc-simple-login=$CI_REGISTRY_IMAGE:latest
    - kubectl rollout restart deployment/xc-simple-login
    - kubectl get pod
    - echo "Application successfully deployed."
  only:
    - main

该文件定义了名为 packagedeploy 的作业,分别使用 docker 镜像和 bitnami/kubectl 来部署。第一个 package 依赖于根目录下的 Dockerfile,依据这个 Dockerfile

FROM nginx

COPY dist/ /usr/share/nginx/html/

这里表示用 nginx 做为模板,将 /dist 封装入 docker 中,从而产生 docker image 文件,$CI_REGISTRY_IMAGE${tag} 这个是 gitlab 的内置变量,是镜像仓库的位置。

效果检查- CI/CD 效果

此时你在 k8s 上已经能够看到部署完成的 pod 和 svc 了。

如果在实验过程中用的是 Docker Desktop K8S 或者你是本地部署,那么使用就可以将 port 映射到 localhost 上,那么可以直接用浏览器访问 http://localhost:30010

Untitled

然后我们修改 /src/views/Home.vue 这个文件,将 Welcome to F5 Simple Login App 修改为你喜欢的名字,例如**“这是我的第一个网页”**,然后重新编译,执行

npm run build

并提交(commit)后(可以使用 vscode,或者用 git 命令)

将更改添加到暂存区:

git add .

提交更改:

git commit -m "update"

然后你在 jihulab 上就能看到新的 pipeline 了

Untitled

在 k8s 上能够自动部署最新的镜像文件

此时,当你再次打开浏览器,就能看到最新的名字

自我检查:
1. 检查上面 pipeline 截图的 2 个 stage 都是绿色的✅状态
2. 检查本地能够打开网页

Untitled

Untitled

 

思考题

如何果大家想像 demo 中自己编译 VUE,需要执行:

npm install -D @vue/cli-service
npm run build

那如何将 npm 也封装在 CI/CD 中?这样只要改变了代码就能直接部署了。

 

最终检查

检查 1-代码库正确 Fork

LAB 的仓库代码已 Fork 至您的仓库中

并且在 CI/CD 中流水线均正常结束(✅状态)
Untitled

检查 2-deploy-job 的输出结果

Untitled

确保红框标注的内容存在于 deploy-job 的输出结果中。

 

实验验收标准:

请同学们在提交本单元的单元小测时,附上你的 gitlab/jihulab 地址,以便我们验收你的配置文件。

提交极狐或者 GitLab 的 URL,得分点情况如下:

  1. URL 提交正确(能够打开的代码仓库)
  2. my-agent 文件内容改写正确(改为自己的项目名字,参见挑战 2
  3. CI/CD 下的流水线中最后的流水线为已通过(Passed)状态(参见最终检查
  4. deploy-job 的输出结果中包含一个正在创建的 container 和一个 running 的 container(参见最终检查
  5. 附加题:流水线中包含第三个编译作业,或者 Dockerfile 包含编译作业

 

下一步

恭喜!您已经学会了如何使用 Gitops 来执行微服务应用程序的自动发布与部署。

如果您还对 Github 的 CI/CD 感兴趣,可以查看:

延伸阅读:如何使用 GitHub Action 实现微服务灰度发布自动化

Hero image
免费 O'Reilly 电子书:
《NGINX 完全指南》

更新于 2022 年,一本书了解关于 NGINX 的一切

关于作者

朱炜良

NGINX 资深架构师

关于 F5 NGINX

F5, Inc. 是备受欢迎的开源软件 NGINX 背后的商业公司。我们为现代应用的开发和交付提供一整套技术。我们的联合解决方案弥合了 NetOps 和 DevOps 之间的横沟,提供从代码到用户的多云应用服务。访问 nginx-cn.net 了解更多相关信息。