K8s 学习:常用命令 100 条(三)- CI/CD 集成实战

K8s 学习:常用命令 100 条(三)- CI/CD 集成实战

CI/CD

系列文章: K8s 命令实战指南
适用人群: DevOps 工程师、开发人员、运维工程师
阅读时间: 15 分钟


前言

将 Kubernetes 集成到 CI/CD 流水线中,可以实现自动化部署、滚动更新和快速回滚。本文介绍如何在常见的 CI/CD 工具中使用 kubectl 命令。


一、CI/CD 基础配置

1.1 配置 kubeconfig

# 方式1:使用 Service Account(推荐)
kubectl create serviceaccount gitlab-deployer -n default
kubectl create clusterrolebinding gitlab-deployer-binding --clusterrole=cluster-admin --serviceaccount=default:gitlab-deployer

# 获取 Service Account Token
kubectl get secret $(kubectl get serviceaccount gitlab-deployer -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 --decode

# 获取 CA 证书
kubectl get secret $(kubectl get serviceaccount gitlab-deployer -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.ca\.crt}'

# 方式2:使用 kubeconfig 文件
cat ~/.kube/config

# 方式3:在 CI/CD 中设置环境变量
export KUBECONFIG=/path/to/kubeconfig

使用场景:

  • GitLab CI 连接集群
  • Jenkins 连接集群
  • GitHub Actions 连接集群
  • 自动化脚本认证

1.2 验证连接

# 在 CI/CD 中测试连接
kubectl cluster-info

# 验证权限
kubectl auth can-i create deployments
kubectl auth can-i delete pods

# 查看当前上下文
kubectl config current-context

# 查看可用命名空间
kubectl get namespaces

使用场景:

  • CI/CD 配置验证
  • 权限检查
  • 环境确认

二、GitLab CI 集成

2.1 基础配置

# .gitlab-ci.yml
stages:
  - build
  - deploy

variables:
  IMAGE_NAME: registry.example.com/myapp
  IMAGE_TAG: $CI_COMMIT_SHA

build:
  stage: build
  script:
    - docker build -t $IMAGE_NAME:$IMAGE_TAG .
    - docker push $IMAGE_NAME:$IMAGE_TAG

deploy:
  stage: deploy
  script:
    - kubectl set image deployment/myapp myapp=$IMAGE_NAME:$IMAGE_TAG
    - kubectl rollout status deployment/myapp --timeout=300s
  only:
    - master

使用场景:

  • 代码提交自动构建
  • 自动更新镜像版本
  • 滚动更新应用
  • 生产环境部署

2.2 高级配置

# .gitlab-ci.yml(高级)
stages:
  - test
  - build
  - deploy-staging
  - deploy-production

variables:
  IMAGE_NAME: registry.example.com/myapp
  STAGING_NAMESPACE: staging
  PRODUCTION_NAMESPACE: production

test:
  stage: test
  script:
    - npm test
    - npm run lint

build:
  stage: build
  script:
    - docker build -t $IMAGE_NAME:$CI_COMMIT_SHA .
    - docker tag $IMAGE_NAME:$CI_COMMIT_SHA $IMAGE_NAME:latest
    - docker push $IMAGE_NAME:$CI_COMMIT_SHA
    - docker push $IMAGE_NAME:latest

deploy-staging:
  stage: deploy-staging
  script:
    - kubectl config set-context --current --namespace=$STAGING_NAMESPACE
    - kubectl apply -f k8s/staging/
    - kubectl set image deployment/myapp myapp=$IMAGE_NAME:$CI_COMMIT_SHA
    - kubectl rollout status deployment/myapp --timeout=300s
  environment:
    name: staging
    url: https://staging.example.com
  only:
    - develop

deploy-production:
  stage: deploy-production
  script:
    - kubectl config set-context --current --namespace=$PRODUCTION_NAMESPACE
    - kubectl apply -f k8s/production/
    - kubectl set image deployment/myapp myapp=$IMAGE_NAME:$CI_COMMIT_SHA
    - kubectl rollout status deployment/myapp --timeout=300s
  environment:
    name: production
    url: https://www.example.com
  when: manual
  only:
    - master

使用场景:

  • 多环境部署(staging/production)
  • 手动审批部署
  • 自动化测试
  • 环境隔离

2.3 回滚配置

# .gitlab-ci.yml(回滚)
rollback:
  stage: rollback
  script:
    - kubectl rollout undo deployment/myapp
    - kubectl rollout status deployment/myapp --timeout=300s
  when: manual
  only:
    - master

rollback-to-revision:
  stage: rollback
  script:
    - kubectl rollout history deployment/myapp
    - kubectl rollout undo deployment/myapp --to-revision=$REVISION
  when: manual
  only:
    - master

使用场景:

  • 快速回滚到上一个版本
  • 回滚到指定版本
  • 手动触发回滚
  • 紧急修复

三、Jenkins 集成

3.1 声明式 Pipeline

// Jenkinsfile
pipeline {
    agent any

    environment {
        IMAGE_NAME = 'registry.example.com/myapp'
        IMAGE_TAG = "${env.BUILD_NUMBER}"
        KUBECONFIG = credentials('kubeconfig')
    }

    stages {
        stage('Build') {
            steps {
                sh 'docker build -t ${IMAGE_NAME}:${IMAGE_TAG} .'
                sh 'docker push ${IMAGE_NAME}:${IMAGE_TAG}'
            }
        }

        stage('Deploy to Staging') {
            steps {
                sh 'kubectl config set-context --current --namespace=staging'
                sh 'kubectl set image deployment/myapp myapp=${IMAGE_NAME}:${IMAGE_TAG}'
                sh 'kubectl rollout status deployment/myapp --timeout=300s'
            }
        }

        stage('Deploy to Production') {
            steps {
                input 'Deploy to Production?'
                sh 'kubectl config set-context --current --namespace=production'
                sh 'kubectl set image deployment/myapp myapp=${IMAGE_NAME}:${IMAGE_TAG}'
                sh 'kubectl rollout status deployment/myapp --timeout=300s'
            }
        }
    }

    post {
        failure {
            sh 'kubectl rollout undo deployment/myapp'
        }
    }
}

使用场景:

  • Jenkins 流水线集成
  • 自动化构建和部署
  • 失败自动回滚
  • 手动审批部署

3.2 脚本式 Pipeline

// Jenkinsfile(脚本式)
node {
    def imageName = 'registry.example.com/myapp'
    def imageTag = env.BUILD_NUMBER

    try {
        stage('Build') {
            sh "docker build -t ${imageName}:${imageTag} ."
            sh "docker push ${imageName}:${imageTag}"
        }

        stage('Deploy') {
            sh "kubectl set image deployment/myapp myapp=${imageName}:${imageTag}"
            sh "kubectl rollout status deployment/myapp --timeout=300s"
        }

    } catch (Exception e) {
        // 失败时回滚
        sh 'kubectl rollout undo deployment/myapp'
        throw e
    }
}

使用场景:

  • 复杂流水线逻辑
  • 条件判断
  • 异常处理
  • 自定义流程

四、GitHub Actions 集成

4.1 基础配置

# .github/workflows/deploy.yml
name: Deploy to Kubernetes

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Set up kubectl
      uses: azure/setup-kubectl@v3

    - name: Configure kubectl
      run: |
        mkdir -p ~/.kube
        echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > ~/.kube/config

    - name: Build and push Docker image
      run: |
        docker build -t registry.example.com/myapp:${{ github.sha }} .
        docker push registry.example.com/myapp:${{ github.sha }}

    - name: Deploy to Kubernetes
      run: |
        kubectl set image deployment/myapp myapp=registry.example.com/myapp:${{ github.sha }}
        kubectl rollout status deployment/myapp --timeout=300s

使用场景:

  • GitHub 仓库自动化部署
  • 代码推送触发部署
  • 自动更新镜像版本
  • 滚动更新应用

4.2 多环境部署

# .github/workflows/deploy.yml(多环境)
name: Deploy to Kubernetes

on:
  push:
    branches: [ main, develop ]

jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/develop'

    steps:
    - uses: actions/checkout@v3

    - name: Deploy to Staging
      run: |
        kubectl config set-context --current --namespace=staging
        kubectl apply -f k8s/staging/
        kubectl set image deployment/myapp myapp=registry.example.com/myapp:${{ github.sha }}
        kubectl rollout status deployment/myapp --timeout=300s

  deploy-production:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
    - uses: actions/checkout@v3

    - name: Deploy to Production
      run: |
        kubectl config set-context --current --namespace=production
        kubectl apply -f k8s/production/
        kubectl set image deployment/myapp myapp=registry.example.com/myapp:${{ github.sha }}
        kubectl rollout status deployment/myapp --timeout=300s

使用场景:

  • 分支对应环境
  • 自动化多环境部署
  • 环境隔离
  • 条件触发

五、蓝绿部署

5.1 蓝绿部署流程

# 1. 部署绿色版本
kubectl apply -f deployment-green.yaml

# 2. 等待绿色版本就绪
kubectl rollout status deployment/myapp-green --timeout=300s

# 3. 切换流量到绿色版本
kubectl patch service myapp -p '{"spec":{"selector":{"version":"green"}}}'

# 4. 验证绿色版本
curl http://myapp-service/

# 5. 如果有问题,回滚到蓝色版本
kubectl patch service myapp -p '{"spec":{"selector":{"version":"blue"}}}'

# 6. 确认无误后,删除蓝色版本
kubectl delete deployment myapp-blue

使用场景:

  • 零停机部署
  • 快速回滚
  • 生产环境验证
  • 版本切换

5.2 自动化蓝绿部署脚本

#!/bin/bash
# blue-green-deploy.sh

IMAGE_TAG=$1
NAMESPACE=${2:-default}

echo "开始蓝绿部署..."

# 获取当前活跃版本
CURRENT_VERSION=$(kubectl get service myapp -n $NAMESPACE -o jsonpath='{.spec.selector.version}')

if [ "$CURRENT_VERSION" == "blue" ]; then
    NEW_VERSION="green"
else
    NEW_VERSION="blue"
fi

echo "当前版本: $CURRENT_VERSION"
echo "新版本: $NEW_VERSION"

# 部署新版本
cat deployment-template.yaml | \
    sed "s/{{VERSION}}/$NEW_VERSION/g" | \
    sed "s/{{IMAGE_TAG}}/$IMAGE_TAG/g" | \
    kubectl apply -n $NAMESPACE -f -

# 等待新版本就绪
kubectl rollout status deployment/myapp-$NEW_VERSION -n $NAMESPACE --timeout=300s

# 切换流量
kubectl patch service myapp -n $NAMESPACE -p "{\"spec\":{\"selector\":{\"version\":\"$NEW_VERSION\"}}}"

echo "蓝绿部署完成!当前版本: $NEW_VERSION"

使用场景:

  • 自动化蓝绿部署
  • 版本切换
  • 零停机更新
  • 生产环境验证

六、金丝雀发布

6.1 金丝雀发布流程

# 1. 部署金丝雀版本(10% 流量)
kubectl apply -f deployment-canary.yaml

# 2. 配置 Service 流量分割
kubectl apply -f service-canary.yaml

# 3. 监控金丝雀版本
kubectl logs -l version=canary -f

# 4. 逐步增加流量(20% -> 50% -> 100%)
kubectl patch service myapp -p '{"spec":{"selector":{"version":"canary"}}}'

# 5. 如果正常,完全切换到新版本
kubectl scale deployment myapp-stable --replicas=0
kubectl scale deployment myapp-canary --replicas=3

# 6. 如果有问题,回滚
kubectl scale deployment myapp-canary --replicas=0
kubectl scale deployment myapp-stable --replicas=3

使用场景:

  • 渐进式发布
  • 风险控制
  • 小流量验证
  • 灰度发布

6.2 自动化金丝雀发布脚本

#!/bin/bash
# canary-deploy.sh

IMAGE_TAG=$1
NAMESPACE=${2:-default}
CANARY_REPLICAS=${3:-1}
STABLE_REPLICAS=${4:-9}

echo "开始金丝雀发布..."

# 部署金丝雀版本
cat deployment-canary.yaml | \
    sed "s/{{IMAGE_TAG}}/$IMAGE_TAG/g" | \
    sed "s/{{REPLICAS}}/$CANARY_REPLICAS/g" | \
    kubectl apply -n $NAMESPACE -f -

# 等待金丝雀版本就绪
kubectl rollout status deployment/myapp-canary -n $NAMESPACE --timeout=300s

echo "金丝雀版本已部署($CANARY_REPLICAS 个副本)"
echo "监控命令: kubectl logs -l version=canary -n $NAMESPACE -f"

# 监控 5 分钟
echo "监控 5 分钟..."
sleep 300

# 检查错误率
ERROR_RATE=$(kubectl logs -l version=canary -n $NAMESPACE | grep -c "ERROR")

if [ $ERROR_RATE -gt 10 ]; then
    echo "错误率过高,回滚金丝雀版本..."
    kubectl scale deployment myapp-canary -n $NAMESPACE --replicas=0
    exit 1
fi

# 逐步增加金丝雀副本
echo "增加金丝雀副本到 $((CANARY_REPLICAS * 2))..."
kubectl scale deployment myapp-canary -n $NAMESPACE --replicas=$((CANARY_REPLICAS * 2))
kubectl scale deployment myapp-stable -n $NAMESPACE --replicas=$((STABLE_REPLICAS - CANARY_REPLICAS))

echo "金丝雀发布完成!"

使用场景:

  • 自动化金丝雀发布
  • 错误率监控
  • 渐进式流量切换
  • 自动回滚

七、配置管理

7.1 ConfigMap 更新

# 更新 ConfigMap(不重启 Pod)
kubectl create configmap app-config --from-file=config.yaml --dry-run=client -o yaml | kubectl apply -f -

# 触发 Pod 滚动更新(让 Pod 重新加载配置)
kubectl rollout restart deployment/myapp

# 查看 ConfigMap 变更历史
kubectl describe configmap app-config

# 比较 ConfigMap 差异
kubectl get configmap app-config -o yaml > current-config.yaml
diff config.yaml current-config.yaml

使用场景:

  • 应用配置更新
  • 配置热更新
  • 配置版本控制
  • 配置回滚

7.2 Secret 更新

# 更新 Secret(不重启 Pod)
kubectl create secret generic app-secret --from-literal=password=newpass --dry-run=client -o yaml | kubectl apply -f -

# 触发 Pod 滚动更新
kubectl rollout restart deployment/myapp

# 查看 Secret 变更历史
kubectl describe secret app-secret

# 解码 Secret 内容
kubectl get secret app-secret -o jsonpath='{.data.password}' | base64 --decode

使用场景:

  • 密码更新
  • 密钥轮换
  • 证书更新
  • 安全配置

八、监控与告警

8.1 部署状态监控

# 监控部署状态
kubectl rollout status deployment/myapp --timeout=300s

# 查看部署历史
kubectl rollout history deployment/myapp

# 查看 Pod 状态
kubectl get pods -l app=myapp -w

# 查看事件
kubectl get events --field-selector involvedObject.name=myapp

# 监控资源使用
kubectl top pod -l app=myapp

使用场景:

  • 部署进度监控
  • 异常检测
  • 性能监控
  • 事件追踪

8.2 自动化健康检查

#!/bin/bash
# health-check.sh

DEPLOYMENT_NAME=$1
NAMESPACE=${2:-default}

echo "开始健康检查..."

# 等待部署完成
kubectl rollout status deployment/$DEPLOYMENT_NAME -n $NAMESPACE --timeout=300s

# 检查 Pod 状态
READY_PODS=$(kubectl get deployment $DEPLOYMENT_NAME -n $NAMESPACE -o jsonpath='{.status.readyReplicas}')
DESIRED_PODS=$(kubectl get deployment $DEPLOYMENT_NAME -n $NAMESPACE -o jsonpath='{.status.replicas}')

if [ "$READY_PODS" != "$DESIRED_PODS" ]; then
    echo "健康检查失败:就绪副本数不匹配"
    exit 1
fi

# 检查容器重启次数
RESTART_COUNT=$(kubectl get pods -l app=$DEPLOYMENT_NAME -n $NAMESPACE -o jsonpath='{.items[0].status.containerStatuses[0].restartCount}')

if [ "$RESTART_COUNT" -gt 3 ]; then
    echo "健康检查失败:容器重启次数过多"
    exit 1
fi

# 测试服务连通性
SERVICE_IP=$(kubectl get service $DEPLOYMENT_NAME -n $NAMESPACE -o jsonpath='{.spec.clusterIP}')
if ! kubectl run -it --rm --restart=Never busybox --image=busybox:1.28 -- wget -qO- http://$SERVICE_IP:80 > /dev/null 2>&1; then
    echo "健康检查失败:服务不可访问"
    exit 1
fi

echo "健康检查通过!"

使用场景:

  • 部署后自动验证
  • 服务可用性检查
  • 自动化测试
  • CI/CD 集成

九、总结

9.1 CI/CD 集成最佳实践

  1. 安全性

    • 使用 Service Account 认证
    • 限制权限范围
    • 保护敏感信息
  2. 可靠性

    • 滚动更新策略
    • 健康检查
    • 自动回滚
  3. 可追溯性

    • 版本标签
    • 部署历史
    • 审计日志
  4. 效率

    • 并行构建
    • 缓存优化
    • 增量部署

9.2 常用命令速查

场景 命令
更新镜像 kubectl set image deployment/<name> <container>=<image>
查看部署状态 kubectl rollout status deployment/<name>
查看历史 kubectl rollout history deployment/<name>
回滚 kubectl rollout undo deployment/<name>
重启 kubectl rollout restart deployment/<name>
应用配置 kubectl apply -f <yaml-file>

参考资料


作者: PaPaBot
发布时间: 2026-03-07
标签: #Kubernetes #K8s #DevOps #CI/CD #自动化部署


本文属于《K8s 命令实战指南》系列文章第三篇

Views: 0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Index