返回文章列表

在 K8S 中只会 CI 不会 CD ?3 种方式,让极狐GitLab 和 K8S 高效协同!

武让
极狐GitLab 高级解决方案架构师

随着国家数字化转型战略持续深入,云原生技术在各行各业中获得了更广泛的应用。其中 DevOps 和 Kubernetes 作为云原生应用的标准化平台,扮演着重要角色。

 

作为一体化 DevOps 平台,极狐GitLab 内置了开箱即用的 CI/CD 引擎,并可以与 K8S 集成,实现更快、更可靠和更高效的云原生应用程序开发、测试和部署。

 

网络上有很多关于使用极狐GitLab 在 K8S 中进行 CI 的方案,本身相对简单。而关于使用极狐GitLab 在 K8S 中进行 CD 的内容却比较少,总结的也不是很全面。所以我将这部分内容单独抽离出来,汇总成一篇文章,供大家参考。

 

在开始阅读文章或进行实操前,你需要掌握以下知识:

 

  • 掌握 K8S 的基本概念和使用方式:如 K8S 对象、对象资源 YAML、kubectl 等。
  • 掌握极狐GitLab CI 的使用方式:如 Runner、脚本语法等。
  • 掌握镜像仓库的使用方式:如 Docker Registry、Harbor、极狐GitLab 制品库、JFrog Artifactory 等。

 

基于认证的K8S集成

 

其原理是将 KubeConfig 文件作为极狐GitLab CI/CD 环境变量进行存储,在流水线脚本中使用 kubectl 通过 KubeConfig 文件连接到 K8S 集群并执行命令。

 

该方案使用简单,但在安全性较差,已被GitLab / 极狐GitLab 遗弃,详见:《Kubernetes clusters | GitLab》

 

但你依然可以根据实际情况选择使用这种方式,比如在测试环境、小型团队或者在 K8S CD 的起步阶段使用。

 

1. 获取 K8S 集群的 KubeConfig 文件,示例内容如下:

 

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: xxxxx
    server: https://xx.xx.xx.xx:443
  name: cls-2nyr3x9a
contexts:
- context:
    cluster: cls-2nyr3x9a
    user: "100023468845"
  name: cls-2nyr3x9a-100023468845-context-default
current-context: cls-2nyr3x9a-100023468845-context-default
kind: Config
preferences: {}
users:
- name: "100023468845"
  user:
    client-certificate-data: xxxxxx
    client-key-data: xxxxxx

 

2. 在实例级、群组级或项目级设置 CI/CD 环境变量,如创建名为 UAT_KUBE_CONFIG 的变量,类型为文件,内容为 KubeConfig 文件中的内容:

 

 

3. 在极狐GitLab 项目中添加 K8S Manifest,如 deploy.yaml 文件:

 

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: default
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

 

4. 在极狐GitLab 项目中添加流水线脚本,示例内容如下:

 

deploy-to-sit:
  stage: deploy
  image:
    name: bitnami/kubectl:latest
    entrypoint: ['']
  # 仅在test分支下执行
  rules:
    - if: $CI_COMMIT_BRANCH == 'test'
  # 读取 SIT_KUBE_CONFIG 环境变量作为 kubeconfig
  before_script:
    - export KUBECONFIG=$SIT_KUBE_CONFIG
  # 执行kubectl命令
  script:
    - kubectl get pods
    - kubectl apply -f deploy.yaml

deploy-to-uat:
  stage: deploy
  image:
    name: bitnami/kubectl:latest
    entrypoint: ['']
  # 仅在main分支下执行
  rules:
    - if: $CI_COMMIT_BRANCH == 'main'
  # 读取 UAT_KUBE_CONFIG 环境变量作为 kubeconfig
  before_script:
    - export KUBECONFIG=$UAT_KUBE_CONFIG
  # 执行kubectl命令
  script:
    - kubectl get pods
    - kubectl apply -f deploy.yaml

 

该方案操作简单,容易实现,但在流水线脚本中可以通过 cat $KUBECONFIG 命令读取 KubeConfig 文件内容,存在安全风险,对此可参考《如何安全使用 GitLab CICD SSH 部署》文章中的内容,对 KubeConfig 的部分内容进行隐藏,可在一定程度上提高安全性。

 

 

基于Agent的K8S集成

 

为解决基于认证的 K8S 集成所带来的安全性问题,提高效率和性能,以及实现更多的功能,GitLab 设计了 GitLab Agent for K8S 来作为 K8S 和 GitLab / 极狐GitLab 沟通的桥梁,详见:《GitLab Agent for Kubernetes | GitLab》

 

GitLab Agent for K8S 在 GitLab / 极狐GitLab 14.5 版本之后,已从专业版下放到标准版(社区版)。GitLab Agent for K8S 同时支持 Push 模型和 Pull 模型,关于这两者的介绍和区别可参考文章《云原生时代,你还不懂 GitOps》。

 

在极狐GitLab 中,基于传统 Push 模型的 CD 方式称之为“极狐GitLab CI/CD Workflow”,而基于 Pull 模型的 CD 方式称之为“GitOps Workflow”,接下来将分别说明这两种方式如何实现。

 

安装Agent

 

不论是极狐GitLab CI/CD Workflow 还是 GitOps Workflow,都需要安装 GitLab Agent for K8S,目前 GitLab Agent for K8S 支持的 K8S 版本如下:

 

  • 1.26 (support ends on March 22, 2024 or when 1.29 becomes supported);
  • 1.25 (support ends on October 22, 2023 or when 1.28 becomes supported);
  • 1.24 (support ends on July 22, 2023 or when 1.27 becomes supported)。

 

此外需要在本地电脑安装 helmkubectl 用于链接 K8S 集群并安装 Agent。安装方式详见文档:《Installing the agent for Kubernetes | GitLab》

 

以下是安装 Agent 的主要步骤:

 

1. 创建一个根群组,如 ci → 在根群组 ci 下创建子群组,如 agents → 在子群组 agents 下创建一个项目,如 agent1 → 在该项目下创建文件,路径为 .gitlab/agents//config.yaml,内容留空,用于作为 Agent 的配置文件。

2. 在 agent1 项目左侧的菜单栏中,选择“基础设置→ Kubernetes 集群”,新建一个集群,如 my-agent,需注意集群名称需与上一步文件路径中的 <agent-name> 一致。

 

 

3. 使用 kubectl 连接到 K8S 集群,根据指引使用 helm 命令安装 Agent.

 

 

4. 安装完成后检查 Agent 的连接状态。

 

 

 

极狐GitLab CI/CD Workflow

 

需注意极狐GitLab Agent for K8S 只能安装在指定的项目中,不能安装在实例或群组中。如果有很多项目都需要用到 Agent,虽然可以给每个项目创建 Agent,但管理比较复杂,而且一点也不优雅,所以我们希望尽可能的去复用同一个 Agent。

 

Agent 支持给其他项目或者群组复用,但这些项目或群组需要与 Agent 这个项目本身处于同一个根群组下,不能跨根群组复用 Agent,详见:《Using GitLab CI/CD with a Kubernetes cluster | GitLab》

 

所以基于极狐GitLab CI/CD Workflow 的群组划分方式一般建议如下:

 

基于 2.1 中配置的 Agent,实现极狐GitLab CI/CD Workflow 的主要步骤如下:

 

1. 在 agent1 项目中,修改 .gitlab/agents//config.yaml 文件,增加以下内容:

 

ci_access:
  projects:
    - id: <其他需要复用该agent的项目的相对路径,最多100个,需与agent项目处于相同的父群组。>
  groups:
    - id: ci/gitlab-cicd-workflow
    - id: <其他需要复用该agent的群组的相对路径,最多100个,需与agent项目处于相同的父群组。>

 

2. 在根群组 ci 下创建子群组,如 gitlab-cicd-workflow。在子群组 gitlab-cicd-workflow 中创建项目,如 push-model-demo,该项目的相对路径是 ci/gitlab-cicd-workflow/push-model-demo

 

3. 在 push-model-demo 项目中添加 K8S Manifest,如一个 deploy.yaml 文件。

 

4. 在 push-model-demo 项目中添加流水线脚本,示例内容如下:

 

deploy:
  image:
    name: bitnami/kubectl:latest
    entrypoint: ['']
  script:
    - kubectl config get-contexts
    # kubectl config use-context path/to/agent/repository:agent-name
    - kubectl config use-context ci/agents/agent1:my-agent
    - kubectl get pods
    - kubectl apply -f deploy.yaml

 

5. 运行 push-model-demo 项目的流水线,验证结果。

 

 

使用极狐GitLab CI/CD Workflow 基于 Agent 的 K8S 集成比基于认证的 K8S 集成略显复杂,但它不会泄露 KubeConfig 文件,也不直接操作 K8S API,此外在 agent 项目中可修改配置文件实现对指定项目的 CD 授权,也从多方面增加了系统的安全性。

 

但是由于 Push 模型本身在设计上就会出现“配置漂移”和安全合规问题,所以极狐GitLab CI/CD Workflow 依然被认为是一种“不安全”的 CD 模式。

 

GitOps Workflow

 

基于 GitLab Agent for K8S 的 GitOps Workflow 如下图所示:

 

 

开发人员使用极狐GitLab CI 对代码进行自动构建,将打包的镜像存放到制品库,将配置清单存放到配置库。部署在 K8S 集群上的 GitLab Agent 监听配置库,当发现配置库有变化时,基于配置库中配置清单自动执行部署任务。

 

需要注意的是目前基于 GitLab Agent for K8S 的 GitOps Workflow 存在一些缺陷:

 

如果要复用 Agent,则配置清单项目需设置可见性为公开(Public)。而一个项目的可见性要设置为公开(Public),则它的群组、父群组的可见性也需要设置为公开(Public)。这增加了管理上的风险。

 

或者在每个配置清单项目里设置单独的 Agent,这样这些项目的可见性就可设置为私有(Private)。但这又增加了管理的复杂度。

 

GitLab 官方目前正在解决这个问题,详见:https://gitlab.com/groups/gitlab-org/-/epics/7704

 

基于 2.1 中配置的 Agent,实现极狐GitLab CI/CD Workflow 的主要步骤如下:

 

1. 在根群组 ci 下创建子群组,如 gitops-workflow。在子群组 gitops-workflow 中创建公开(Public)项目,如 pull-model-demo,该项目的相对路径是 ci/gitops-workflow/pull-model-demo

 

2. 在 pull-model-demo 项目中添加 K8S Manifest,如一个 deploy.yaml 文件。

 

3. 在 agent1 项目中,修改 .gitlab/agents//config.yaml 文件,增加以下内容:

 

gitops:
  manifest_projects:
  - id: ci/gitops-workflow/pull-model-demo
    ref: # either `branch`, `tag` or `commit` can be specified
      branch: main
      # commit: <mysha>
      # tag: v1.0
    paths:
      # Read all YAML files from this directory.
    - glob: '*.yaml'
      # Read all .yaml files from team2/apps and all subdirectories.
      # - glob: '/team2/apps/**/*.yaml'
      # If 'paths' is not specified or is an empty list, the configuration below is used.
      # - glob: '/**/*.{yaml,yml,json}'
    reconcile_timeout: 3600s
    dry_run_strategy: none
    prune: true
    prune_timeout: 3600s
    prune_propagation_policy: foreground
    inventory_policy: must_match

 

4. 等待片刻后使用 kubectl get pod -A 查看部署情况。

 

 

5. 可使用以下命令查看 Agent 日志或进行调试:

 

# 查询所有GitLab Agent的命名空间
kubectl get ns | grep gitlab-agent
# 查询指定命名空间下的GitLab Agent Pod
kubectl get pod -n gitlab-agent-my-agent
# 查询指定GitLab Agent Pod的日志
kubectl logs my-agent-gitlab-agent-88b4c67db-5nhz9 -n gitlab-agent-my-agent

 

 

正如上文所述,基于极狐GitLab Agent for K8S 的 GitOps Workflow 实现了 GitOps,但它目前还存在一些问题,在这些问题得到解决之前,建议你充分考虑使用这种方式的利弊,或者考虑使用第三方的 GitOps 工具,如 Flux、ArgoCD 等。

 

关于 GitOps Workflow 的更多内容可以参考:《Using GitOps with a Kubernetes cluster | GitLab》

 

第三方GitOps工具与GitLab集成

 

Flux

 

Flux 是一个 GitOps 工具,用于自动化地管理 Kubernetes 应用程序的部署和更新。它的主要思想是将 Kubernetes 集群配置文件存储在 Git 存储库中,并使用 Git 的工作流来管理应用程序的生命周期,包括部署、升级和回滚。

 

Flux 可以通过轮询 Git 存储库或使用 Webhooks 自动同步 Kubernetes 应用程序的部署状态。当 Git 存储库中的配置文件发生更改时,Flux 会自动检测并将更改推送到 Kubernetes 集群中,从而实现自动部署和更新应用程序的能力。

 

 

2023年2月,GitLab 官方也宣布了未来将会与 Flux 深度集成,计划将 Flux 作为 GitLab GitOps 解决方案的一部分来替代 GitLab Agent for K8S。详见:《GitOps with GitLab: What you need to know about the Flux CD integration | GitLab》

 

目前GitLab / 极狐GitLab 与 Flux 的集成还是依靠 Flux 原生的能力,后续会在极狐GitLab 上开发相关的 UI 界面以增强用户体验,预计 2024 年会发布 GA 版本。

 

使用 Flux 与 GitLab / 极狐GitLab 集成实现 GitOps 可参考官方文档:《Tutorial: Set up Flux for GitOps | GitLab》

 

主要步骤如下:

 

1. 创建空项目,如 flux-config,作为 Flux 的配置数据源。并为该项目创建访问令牌,角色为 Maintainer,范围是 api

 

 

2. 在本地电脑安装 kubectl,配置上下文以访问 K8S 集群,用于安装 Flux。

 

3. 在本地电脑安装 Flux CLI,Flux CLI 的安装方式可参考《Install the Flux CLI》,以 Mac 和 Linux 为例,可执行以下命令安装:

 

curl -s https://fluxcd.io/install.sh | sudo bash

 

4. 在本地电脑通过 Flux CLI 在 K8S 集群中安装 Flux:

 

# 第1步中获取的访问令牌
export GITLAB_TOKEN=xxxxx

flux bootstrap gitlab \
  # GitLab实例地址
  --hostname=jhgitlab.com \
  # Flux配置仓库所在的群组 
  --owner=mycompany/ci/flux-gitops \
  # Flux配置仓库名称
  --repository=flux-config \
  # Flux配置仓库的默认分支
  --branch=main \
  # Flux配置存储路径
  --path=clusters/my-cluster \
  # 验证方式
  --token-auth 

 

安装成功后显示内容如下:

 

 

执行 kubectl get pod -n flux-system 查看 Flux 的部署情况。

 

 

5. 创建项目,如 web-app-manifests,用于托管某项目的 K8S Manifest,如 nginx-deployment.yaml

 

apiVersion: apps/v1

kind: Deployment

metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

 

6. 创建该项目的部署令牌,设置名称,如 flux_deploy_token,范围是 read_repository

 

 

 

为了避免每个项目都要创建部署令牌,也可使用群组访问令牌或者个人访问令牌,范围同样也是 read_repository

 

 

7. 在本地电脑通过 Flux CLI 在 K8S 集群中生成该部署令牌的 Secret:

 

# flux-deploy-authentication 是Secret名称
flux create secret git flux-deploy-authentication \
     # web-app-manifests项目的路径
     --url=https://jhgitlab.com/mycompany/ci/flux-gitops/web-app-manifests \
     # Secret的命名空间
     --namespace=default \
     --bearer-token=glpat-EkAVMryjoxBVqgH1EDKq
     # 部署令牌/访问令牌名称
     --username=flux_deploy_token \
     # 部署令牌密码/访问令牌
     --password=rLbLreiR2jeUWrD_W7vH

 

使用命令 kubectl -n default get secrets flux-deploy-authentication -o yaml 验证 Secret 是否生成成功。

 

 

8. 在 Flux 配置项目 flux-config 中添加文件 clusters/my-cluster/web-app/web-app-manifests-source.yaml,内容如下:

 

---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
  name: web-app-manifests
  namespace: default
spec:
  # 同步时间间隔
  interval: 1m0s
  # 同步manifest项目的分支
  ref:
    branch: main
  # 使用secret的名称
  secretRef:
    name: flux-deploy-authentication
  # 同步manifest项目的地址
  url: https://jhgitlab.com/mycompany/ci/flux-gitops/web-app-manifests

 

该文件用于将 web-app-manifests 项目以 GitRepository 类型同步到 K8S 集群中。

 

 

9. 在 Flux 配置项目 flux-config 中添加文件 clusters/my-cluster/web-app/clusters/my-cluster/web-app/web-app-manifests-kustomization.yaml,内容如下:

 

---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: nginx-source-kustomization
  namespace: default
spec:
  interval: 1m0s
  path: ./
  prune: true
  sourceRef:
    kind: GitRepository
    name: web-app-manifests
    namespace: default
  targetNamespace: default

 

该文件用于监听 K8S 中的 GitRepository 资源,当资源发生变化时,使用 kustomize 来运行这些 Manifest。

 

10.使用 kubectl get pods -n default 命令,可以看到 Flux 根据 web-app-manifests 项目中的 nginx-deployment.yaml 部署了 3 个 nginx-deployment

 

 

11. 修改 web-app-manifests 项目中的 nginx-deployment.yaml,如将 replicas 修改为 2,等待片刻,再次使用 kubectl 命令查看,Flux 自动将 nginx-deployment 的副本数量调整为 2

 

 

12. 如果想划分部署环境,可参考以下方式:

 

  • 相同集群,不同命名空间:无需修改 Flux 配置库,只需用不同名称的配置清单或配置清单库的不同分支来区分 Manifest 和 Namespace 即可。

 

├── Group: A
|   ├── Project:flux-config
|       ├── Folder: clusters/my-cluster
|   ├── SubGroup:web-app-manifest
|       ├── Project: staging
|       └── Project: production
|   ├── Project:server-manifest
|       ├── Branch: staging
|       └── Branch: production

 

  • 不同集群:需修改 Flux 配置库,用 Flux 配置库中的不同目录区分不同的 K8S 环境,用不同名称的配置清单或配置清单库的不同分支来区分 Manifest 和 Namespace。

 

export GITLAB_TOKEN=xxxxx
     
export KUBECONFIG=$HOME/.kube/config-cluster-staging
flux bootstrap gitlab \
  --hostname=jhgitlab.com \
  --owner=mycompany/ci/flux-gitops \
  --repository=flux-config \
  --branch=main \
  --path=clusters/cluster-staging \
  --token-auth 
     
export KUBECONFIG=$HOME/.kube/config-cluster-production
flux bootstrap gitlab \
  --hostname=jhgitlab.com \
  --owner=mycompany/ci/flux-gitops \
  --repository=flux-config \
  --branch=main \
  --path=clusters/cluster-production \
  --token-auth  

 

├── Group: A
|   ├── Project:flux-config
|       ├── Folder: clusters/staging
|       └── Folder: clusters/production
|   ├── SubGroup:web-app-manifest
|       ├── Project: staging
|       └── Project: production
|   ├── Project:server-manifest
|       ├── Branch: staging
|       └── Branch: production

 

使用 Flux 与极狐GitLab 集成,开发人员只需通过 CI 将应用打包成镜像存放在镜像库,开发人员或运维人员维护该应用对应的配置清单库如 web-app-manifests,运维人员维护 Flux 配置库如 flux-config,即可实现 GitOps。

 

ArgoCD

 

ArgoCD 是一款开源且主要针对 Kubernetes 来做 GitOps 的持续交付工具,是 CNCF 的孵化项目。

 

相较于 Flux,ArgoCD 提供了更完整的 GitOps 解决方案,包括多集群支持、应用程序版本控制、可视化部署状态等功能。

 

 

 

ArgoCD 作为目前使用最为广泛的 GitOps 工具,亦提供与极狐GitLab 集成,将极狐GitLab 作为单一可信源,从而实现 GitOps。

 

网络上关于 ArgoCD+GitLab 的相关文章和介绍很多,也可直接参考极狐GitLab 官方内容:《极狐GitLab 和 ArgoCD 的集成实践-极狐GitLab》

 

作为诞生于社区的开源产品,极狐GitLab 在 CI/CD 方面大部分的功能是免费的,基于极狐GitLab 和这篇文章,你可以实现在 K8S 中进行 CD 的基础功能。如果要做的更深、更好,肯定需要花费更多的时间来实践、打磨。

 

当然如果你的团队和企业需要一些技术支持和一些最佳实践的经验指导,少踩坑、快上线、有兜底,也可以使用极狐GitLab 企业版,在拥有更多企业级功能、性能的基础上,获得更全面、更可靠的服务。

极狐GitLab 一体化DevOps平台 专为中国用户研发,免费试用60天专业版高级功能
售前咨询
联系电话
在线支持
预约演示