如何用脚本自动更新Kubernetes配置?

wen 实用脚本 1

本文目录导读:

如何用脚本自动更新Kubernetes配置?

  1. 使用 kubectl apply 脚本
  2. 使用脚本更新特定资源
  3. 使用Python脚本更新
  4. 使用Helm的脚本
  5. 完整的自动化脚本示例
  6. 与CI/CD集成(GitLab CI示例)
  7. 最佳实践建议

我来详细讲解如何用脚本自动更新Kubernetes配置的几种常用方法:

使用 kubectl apply 脚本

#!/bin/bash
# 自动更新K8s配置脚本
set -e
# 配置变量
NAMESPACE="default"
CONFIG_DIR="./k8s-configs"
BACKUP_DIR="./backups/$(date +%Y%m%d_%H%M%S)"
# 创建备份目录
mkdir -p $BACKUP_DIR
# 备份现有配置
echo "备份现有配置..."
kubectl get all -n $NAMESPACE -o yaml > $BACKUP_DIR/current-state.yaml
# 更新配置
echo "应用新配置..."
for file in $CONFIG_DIR/*.yaml; do
    echo "应用: $file"
    kubectl apply -f $file --namespace $NAMESPACE
done
# 验证配置
echo "验证配置状态..."
kubectl rollout status deployment -n $NAMESPACE --timeout=120s

使用脚本更新特定资源

#!/bin/bash
# 更新Deployment镜像版本
update_deployment() {
    local deployment=$1
    local image=$2
    local namespace=${3:-default}
    echo "更新deployment: $deployment 使用镜像: $image"
    # 记录当前版本
    CURRENT_IMAGE=$(kubectl get deployment $deployment -n $namespace -o jsonpath='{.spec.template.spec.containers[0].image}')
    echo "当前镜像: $CURRENT_IMAGE"
    # 更新镜像
    kubectl set image deployment/$deployment container=$image -n $namespace
    # 检查更新状态
    kubectl rollout status deployment/$deployment -n $namespace
}
# 更新ConfigMap
update_configmap() {
    local configmap=$1
    local config_file=$2
    local namespace=${3:-default}
    echo "更新ConfigMap: $configmap"
    # 备份现有ConfigMap
    kubectl get configmap $configmap -n $namespace -o yaml > "${configmap}_backup.yaml"
    # 更新ConfigMap
    kubectl create configmap $configmap --from-file=$config_file -n $namespace --dry-run=client -o yaml | kubectl apply -f -
    # 重启相关Pod以应用新配置
    kubectl rollout restart deployment -n $namespace -l "app=$configmap"
}
# 使用示例
update_deployment "my-app" "myregistry/myapp:v2.0"
update_configmap "app-config" "config/app.properties"

使用Python脚本更新

#!/usr/bin/env python3
import subprocess
import json
import yaml
import os
from datetime import datetime
class K8sConfigUpdater:
    def __init__(self, namespace="default"):
        self.namespace = namespace
        self.backup_dir = f"backups/{datetime.now().strftime('%Y%m%d_%H%M%S')}"
        os.makedirs(self.backup_dir, exist_ok=True)
    def run_kubectl(self, cmd):
        """执行kubectl命令"""
        try:
            result = subprocess.run(
                cmd.split(),
                capture_output=True,
                text=True,
                check=True
            )
            return result.stdout
        except subprocess.CalledProcessError as e:
            print(f"命令执行失败: {e.stderr}")
            raise
    def backup_current_state(self):
        """备份当前状态"""
        output_file = f"{self.backup_dir}/current_state.yaml"
        cmd = f"kubectl get all -n {self.namespace} -o yaml"
        with open(output_file, 'w') as f:
            f.write(self.run_kubectl(cmd))
        print(f"备份保存到: {output_file}")
    def update_deployment_image(self, deployment, new_image):
        """更新Deployment镜像"""
        cmd = f"kubectl set image deployment/{deployment} *= {new_image} -n {self.namespace}"
        self.run_kubectl(cmd)
        # 等待滚动更新完成
        cmd = f"kubectl rollout status deployment/{deployment} -n {self.namespace}"
        self.run_kubectl(cmd)
        print(f"Deployment {deployment} 更新完成")
    def update_configmap_from_file(self, configmap_name, config_file):
        """从文件更新ConfigMap"""
        cmd = f"kubectl create configmap {configmap_name} --from-file={config_file} -n {self.namespace} --dry-run=client -o yaml"
        new_config = self.run_kubectl(cmd)
        # 应用新的ConfigMap
        apply_cmd = f"kubectl apply -f -"
        result = subprocess.run(
            apply_cmd.split(),
            input=new_config,
            capture_output=True,
            text=True,
            check=True
        )
        print(f"ConfigMap {configmap_name} 更新完成")
        # 重启相关Pod
        self.restart_pods_by_label(f"app={configmap_name}")
    def restart_pods_by_label(self, label):
        """根据标签重启Pod"""
        cmd = f"kubectl rollout restart deployment -n {self.namespace} -l {label}"
        self.run_kubectl(cmd)
        print(f"已重启标签为 {label} 的Pod")
# 使用示例
if __name__ == "__main__":
    updater = K8sConfigUpdater(namespace="production")
    # 备份当前状态
    updater.backup_current_state()
    # 更新Deployment
    updater.update_deployment_image("my-app", "myregistry/myapp:v3.0")
    # 更新ConfigMap
    updater.update_configmap_from_file("app-config", "config/app.properties")

使用Helm的脚本

#!/bin/bash
# 使用Helm更新配置
RELEASE_NAME="my-app"
CHART_PATH="./charts/my-app"
NAMESPACE="default"
# 更新Helm release
helm upgrade $RELEASE_NAME $CHART_PATH \
    --namespace $NAMESPACE \
    --set image.tag=v2.0 \
    --set replicaCount=3 \
    --values ./values/production.yaml \
    --atomic \
    --timeout 10m
# 验证更新状态
helm status $RELEASE_NAME -n $NAMESPACE

完整的自动化脚本示例

#!/bin/bash
# 完整自动化更新脚本
set -e
# 配置变量
NAMESPACE="default"
CONFIG_REPO="/path/to/config-repo"
BACKUP_DIR="/tmp/k8s-backups/$(date +%Y%m%d_%H%M%S)"
# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}
# 错误处理
error_handler() {
    log "ERROR: 脚本执行失败,行号: $1"
    log "执行回滚操作..."
    ./rollback.sh
    exit 1
}
trap 'error_handler $LINENO' ERR
# 主要更新流程
main() {
    log "开始K8s配置更新流程..."
    # 1. 备份当前状态
    log "备份当前配置..."
    mkdir -p $BACKUP_DIR
    # 备份所有资源
    kubectl get all -n $NAMESPACE -o yaml > $BACKUP_DIR/all-resources.yaml
    kubectl get configmap -n $NAMESPACE -o yaml > $BACKUP_DIR/configmaps.yaml
    kubectl get secret -n $NAMESPACE -o yaml > $BACKUP_DIR/secrets.yaml
    # 2. 拉取最新配置
    log "拉取最新配置..."
    cd $CONFIG_REPO
    git pull origin main
    # 3. 应用配置更新
    log "应用配置更新..."
    # 3.1 更新ConfigMaps
    for config_file in configs/*.properties; do
        name=$(basename $config_file .properties)
        kubectl create configmap $name \
            --from-file=$config_file \
            -n $NAMESPACE \
            --dry-run=client -o yaml | kubectl apply -f -
    done
    # 3.2 更新Deployments
    kubectl apply -f deployments/ -n $NAMESPACE
    # 3.3 更新Services
    kubectl apply -f services/ -n $NAMESPACE
    # 4. 灰度发布策略
    log "执行灰度发布..."
    # 创建新版本的Deployment
    kubectl apply -f canary-deployment.yaml
    # 等待新的Pod就绪
    sleep 30
    # 验证新版本
    if kubectl rollout status deployment/my-app-canary -n $NAMESPACE; then
        log "更新验证成功,继续完整部署..."
        # 更新主Deployment
        kubectl set image deployment/my-app my-app=myapp:new-version \
            -n $NAMESPACE
        # 删除canary Deployment
        kubectl delete deployment my-app-canary -n $NAMESPACE
    else
        log "更新验证失败,执行回滚..."
        kubectl delete deployment my-app-canary -n $NAMESPACE
        exit 1
    fi
    log "配置更新完成!"
}
# 回滚函数
rollback() {
    log "执行回滚..."
    kubectl apply -f $BACKUP_DIR/all-resources.yaml
    kubectl apply -f $BACKUP_DIR/configmaps.yaml
    kubectl apply -f $BACKUP_DIR/secrets.yaml
}
# 执行更新
main

与CI/CD集成(GitLab CI示例)

# .gitlab-ci.yml
stages:
  - deploy
variables:
  NAMESPACE: "production"
  DEPLOYMENT_NAME: "my-app"
deploy-to-k8s:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl config set-cluster k8s --server="$KUBE_URL"
    - kubectl config set credentials gitlab --token="$KUBE_TOKEN"
    - kubectl config set-context default --cluster=k8s --user=gitlab --namespace=$NAMESPACE
    - kubectl config use-context default
    # 更新配置
    - kubectl apply -f k8s/deployment.yaml
    - kubectl apply -f k8s/service.yaml
    # 滚动更新
    - kubectl set image deployment/$DEPLOYMENT_NAME \
      $DEPLOYMENT_NAME=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    # 监控部署状态
    - kubectl rollout status deployment/$DEPLOYMENT_NAME --timeout=300s

最佳实践建议

  1. 始终创建备份:在更新前备份当前配置
  2. 使用版本控制:配置脚本应纳入Git版本管理
  3. 实现回滚机制:准备回滚脚本应对失败情况
  4. 灰度发布:对重要服务使用灰度发布策略
  5. 监控和告警:监控更新过程中的异常状态
  6. 权限控制:使用最小权限原则运行更新脚本
  7. 测试环境:先在测试环境验证更新脚本

这些脚本可以根据你的具体需求进行修改和扩展,记得在实际使用前在测试环境中充分测试。

抱歉,评论功能暂时关闭!