第十一章:自动化部署到 Kubernetes:Helm 与 kubectl 集成

CI 流水线构建出 Docker 镜像后,下一步就是将其部署到 Kubernetes 集群。这是 CD(持续部署)的核心环节。本章介绍两种主流的自动化部署方式:直接式部署(CI 调用 kubectl/Helm 命令)和 声明式部署(GitOps) (CI 更新 Git 仓库,由 ArgoCD 同步集群)。你将学会如何安全地将 CI 与 K8s 集群集成,并实现多环境部署和自动回滚。

一、Kubernetes 部署的两种模式

在 CI/CD 体系中,部署到 Kubernetes 有两种主流模式:

GitOps 的核心原则是:Git 仓库是集群期望状态的唯一事实源,集群中的实际状态会持续与 Git 中的声明式配置进行比对和同步。这种方式已成为云原生环境下的部署标准。

二、直接式部署:CI 调用 kubectl / Helm

2.1 前置条件:CI 与 K8s 集群的认证

要让 CI 流水线操作 K8s 集群,需要建立认证通道。主要有两种方式:

方式一:Kubeconfig 注入(简单但不推荐生产)

将集群的 kubeconfig 文件内容存储在 CI/CD 变量中,在流水线中写入 ~/.kube/config。

yaml 复制代码
# GitLab CI 示例
deploy:
  stage: deploy
  image: bitnami/kubectl:latest
  before_script:
    - mkdir -p $HOME/.kube
    - echo "$KUBECONFIG" | base64 -d > $HOME/.kube/config
  script:
    - kubectl set image deployment/myapp myapp=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA -n production
    - kubectl rollout status deployment/myapp -n production

⚠️ 风险:kubeconfig 包含集群管理员凭证,存储在 CI 变量中存在泄露风险。生产环境建议使用更安全的方式。

方式二:GitLab Kubernetes Agent(推荐 GitLab 用户)

GitLab 提供了 Kubernetes Agent,可在不暴露集群凭证的情况下,通过代理安全地执行 kubectl 和 helm 命令。

yaml 复制代码
# .gitlab-ci.yml
stages:
  - setup
  - deploy

create-registry-secret:
  stage: setup
  image: "portainer/kubectl-shell:latest"
  variables:
    AGENT_KUBECONTEXT: my-group/my-project:production
  script:
    - kubectl config use-context $AGENT_KUBECONTEXT
    - kubectl create secret docker-registry gitlab-registry-auth
      --docker-server="${CI_REGISTRY}"
      --docker-username="${CONTAINER_REGISTRY_ACCESS_USERNAME}"
      --docker-password="${CONTAINER_REGISTRY_ACCESS_TOKEN}"
      -n production

Agent 会自动注入到 Runner 环境中,无需在 CI 中存储 kubeconfig。

方式三:GitHub Actions + OIDC(推荐 GitHub 用户)

使用 OpenID Connect 实现无长期凭证的认证:

yaml 复制代码
- name: Configure kubectl
  uses: azure/setup-kubectl@v4
- name: Set up kubeconfig
  run: |
    mkdir -p $HOME/.kube
    echo "${{ secrets.KUBECONFIG }}" > $HOME/.kube/config

更安全的做法是使用 OIDC 联邦认证,由云平台(AWS/Azure/GCP)动态颁发短期凭证。

2.2 使用 kubectl 直接部署

基础部署:更新镜像并等待状态

yaml 复制代码
deploy:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl set image deployment/myapp myapp=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA -n production
    - kubectl rollout status deployment/myapp -n production

预校验:在正式部署前检查配置是否正确

yaml

  • kubectl apply -f k8s/ --dry-run=client -o yaml
    多环境部署:通过不同命名空间和环境变量区分
yaml 复制代码
deploy-staging:
  stage: deploy
  script:
    - kubectl set image deployment/myapp myapp=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA -n staging
    - kubectl rollout status deployment/myapp -n staging
  only:
    - develop

deploy-production:
  stage: deploy
  script:
    - kubectl set image deployment/myapp myapp=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA -n production
    - kubectl rollout status deployment/myapp -n production
  only:
    - main
  when: manual

2.3 使用 Helm 进行更灵活的部署

Helm 是 Kubernetes 的包管理工具,通过 Chart 将多个 K8s 资源打包管理。在 CI 中使用 Helm 部署是更推荐的方式。

在 CI 中安装 Helm 并执行部署:

yaml 复制代码
deploy-helm:
  stage: deploy
  image: alpine/helm:3.14
  before_script:
    - mkdir -p $HOME/.kube
    - echo "$KUBECONFIG" | base64 -d > $HOME/.kube/config
  script:
    # 更新 Chart 依赖
    - helm dependency build ./chart
    # 语法检查
    - helm lint ./chart
    # 预渲染验证(干跑)
    - helm upgrade --install myapp ./chart -f values/production.yaml --dry-run
    # 正式部署
    - helm upgrade --install myapp ./chart -f values/production.yaml \
        --set image.tag=$CI_COMMIT_SHORT_SHA \
        --namespace production \
        --atomic

关键参数说明:

--install:如果 Release 不存在则创建,存在则升级

--atomic:如果升级失败,自动回滚到上一个版本

--dry-run:预览将要生成的 K8s 资源,不实际部署

-f:指定环境对应的 values 文件

使用 values 文件管理多环境:

text

chart/

├── values.yaml # 默认配置

├── values/

│ ├── dev.yaml # 开发环境覆盖

│ ├── staging.yaml # 预发布环境覆盖

│ └── production.yaml # 生产环境覆盖

yaml 复制代码
deploy:
  script:
    - helm upgrade --install myapp ./chart \
        -f values/${ENV}.yaml \
        --set image.tag=$CI_COMMIT_SHORT_SHA

三、GitOps 模式:声明式部署与 ArgoCD

GitOps 将部署从"推"变为"拉":CI 流水线只负责构建镜像并更新 Git 仓库中的部署清单,而 ArgoCD 持续监控 Git 仓库的变化,自动将集群状态同步到期望状态。

3.1 架构对比

text

【直接式部署】

CI → kubectl/helm → K8s 集群(CI 直接操作集群)

【GitOps 部署】

CI → 更新 Git 仓库(镜像 tag)→ ArgoCD 监听 → 自动同步到 K8s 集群

3.2 在 CI 中更新 Git 仓库(触发 ArgoCD)

CI 流水线的最后一步不再是调用 kubectl,而是将新的镜像 tag 提交到 Git 仓库的部署清单中:

yaml 复制代码
# GitLab CI 示例
update-gitops:
  stage: deploy
  image: alpine/git:latest
  script:
    - git clone https://gitlab.com/team/gitops-repo.git
    - cd gitops-repo
    - sed -i "s|image: myapp:.*|image: myapp:$CI_COMMIT_SHORT_SHA|g" overlays/production/deployment.yaml
    - git config user.email "ci@gitlab.com"
    - git config user.name "GitLab CI"
    - git add .
    - git commit -m "deploy: $CI_COMMIT_SHORT_SHA [skip ci]"
    - git push https://$GITLAB_USER:$GITLAB_TOKEN@gitlab.com/team/gitops-repo.git main

💡 提示:skip ci 可避免 Git 仓库更新触发新的 CI 流水线,防止无限循环。

3.3 ArgoCD 自动同步

ArgoCD 部署在 K8s 集群中,持续监控 Git 仓库:

yaml 复制代码
# Application 定义
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://gitlab.com/team/gitops-repo.git
    targetRevision: main
    path: overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true        # 自动删除不在 Git 中的资源
      selfHeal: true     # 自动修复手动修改
    syncOptions:
      - CreateNamespace=true

开启 automated 后,ArgoCD 每隔 3 分钟(默认)检查 Git 仓库变更,自动同步到集群。

3.4 使用 Argo CD Image Updater(全自动方案)

Argo CD Image Updater 可以自动检测镜像仓库中的新版本,并更新 Git 仓库中的镜像 tag,实现从代码提交到部署的全自动闭环。

四、部署策略:滚动更新、蓝绿部署与金丝雀发布

在 CI/CD 流水线中,选择合适的部署策略至关重要。

4.1 在 CI 中实现蓝绿部署

通过 Service 的 label selector 切换流量:

yaml 复制代码
# 部署绿色版本(v2)
- kubectl apply -f deployment-green.yaml

# 验证绿色版本健康
- kubectl rollout status deployment/myapp-green -n production

# 切换流量到绿色版本(修改 Service selector)
- kubectl patch service myapp -p '{"spec":{"selector":{"version":"green"}}}' -n production

# 如需回滚,只需将 selector 改回 "blue"

4.2 使用 Argo Rollouts 实现金丝雀发布

Argo Rollouts 是 Kubernetes 的高级部署引擎,支持金丝雀和蓝绿部署:

yaml 复制代码
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: myapp
spec:
  replicas: 10
  strategy:
    canary:
      steps:
      - setWeight: 10      # 10% 流量到新版本
      - pause: {duration: 5m}
      - setWeight: 50      # 50% 流量
      - pause: {duration: 5m}
      - setWeight: 100     # 100% 流量
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: app
        image: myapp:$CI_COMMIT_SHORT_SHA

CI 只需更新镜像 tag 并提交 Git,Argo Rollouts 自动执行金丝雀步骤。

五、安全最佳实践

最小权限原则:为 CI 使用的 ServiceAccount 只授予必要的 K8s 权限(如只允许更新特定 Deployment)。

使用短期凭证:优先使用 OIDC 或 GitLab Agent,避免长期有效的 kubeconfig 泄露。

预校验配置:在 CI 中执行 kubectl apply --dry-run=client 提前发现 YAML 语法错误。

敏感信息隔离:数据库密码等敏感配置使用 Kubernetes Secret 或 Vault,不写入 values.yaml。

审计与追溯:GitOps 模式下,所有变更都有 Git 提交记录,便于审计。

六、小结

本章介绍了 Kubernetes 自动化部署的两种核心模式:

直接式部署:CI 直接调用 kubectl 或 helm 命令,简单直接,适合快速迭代

声明式部署(GitOps) :CI 只更新 Git 仓库,由 ArgoCD 同步集群,安全可控,适合生产环境

实际项目中,可根据团队规模和风险偏好选择合适的方式。对于生产环境,强烈推荐 GitOps 模式------它让 Git 成为唯一的变更入口,所有操作可追溯、可回滚。