1. Kubernetes脚本化运维的核心价值
在云原生时代,Kubernetes已经成为容器编排的事实标准。但很多运维人员在日常工作中,仍然会陷入重复性的手动操作陷阱。我经历过一个典型场景:某次凌晨3点处理集群节点异常时,发现需要连续执行17个kubectl命令才能完成故障转移。这种经历让我深刻意识到——脚本化才是Kubernetes运维的终极解决方案。
Kubernetes脚本主要解决三类问题:
- 批量操作:比如同时给100个Pod打标签
- 条件逻辑:根据节点资源使用率自动扩容
- 流程封装:将复杂的部署流程固化为可重复执行的脚本
最常用的脚本语言是Bash Shell和Python。根据2023年CNCF的调查报告,68%的Kubernetes运维人员会使用Shell脚本处理基础操作,而Python则在复杂场景中占比达52%。这两种语言各有优势:
| 语言 | 适用场景 | 典型用例 | 学习曲线 |
|---|---|---|---|
| Bash | 简单命令组合 | 批量删除Evicted状态的Pod | 低 |
| Python | 复杂逻辑处理 | 根据Prometheus指标自动HPA | 中 |
提示:选择脚本语言时,建议从Shell开始入门,等遇到需要处理JSON输出或复杂判断时再切换到Python
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Shell脚本实战:从入门到精通
2.1 基础命令组合技巧
一个高效的Kubernetes Shell脚本往往从合理的命令组合开始。以下是经过实战检验的模板:
bash复制#!/bin/bash
# 获取所有命名空间下CrashLoopBackOff的Pod
kubectl get pods --all-namespaces -o json | \
jq -r '.items[] | select(.status.containerStatuses[]?.state.waiting.reason=="CrashLoopBackOff") | .metadata.namespace + "/" + .metadata.name'
这个脚本展示了Shell脚本的黄金搭档:
kubectl:基础查询命令jq:JSON处理神器- 管道(
|):组合多个工具
我常用的几个进阶技巧:
- 使用
--field-selector替代grep过滤资源,性能提升10倍 - 通过
-o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'直接提取关键字段 - 在循环中使用
--chunk-size=50避免大列表内存溢出
2.2 典型运维场景脚本示例
案例:自动清理失败的Job
bash复制#!/bin/bash
# 清理超过1天的失败Job
CUTOFF_TIME=$(date -d '1 day ago' -u +'%Y-%m-%dT%H:%M:%SZ')
kubectl get jobs --all-namespaces -o json | \
jq -r --arg cutoff "$CUTOFF_TIME" '
.items[] |
select(.status.failed > 0) |
select(.status.completionTime < $cutoff) |
.metadata.namespace + "/" + .metadata.name' | \
while read -r job; do
ns=${job%/*}
name=${job#*/}
echo "Deleting failed job: $ns/$name"
kubectl delete job -n "$ns" "$name"
done
这个脚本解决了运维中的痛点:
- 通过jq的
--arg参数实现时间比对 - 使用字符串处理提取namespace和name
- 添加了执行日志输出
注意:生产环境建议先注释delete命令,确认输出符合预期后再执行
3. Python脚本进阶:Kubernetes API深度集成
3.1 官方客户端库最佳实践
Python的kubernetes-client比Shell更适合复杂场景。安装时要注意版本匹配:
bash复制pip install kubernetes==24.2.0 # 匹配K8s 1.24版本
一个安全的客户端初始化方案:
python复制from kubernetes import client, config
try:
config.load_kube_config() # 本地开发环境
except:
config.load_incluster_config() # 容器内运行
v1 = client.CoreV1Api()
我总结的API调用规范:
- 总是设置
_preload_content=False提升大列表查询性能 - 使用
timeout_seconds参数避免挂起 - 通过
watch接口监听资源变更
3.2 实战:智能节点排水脚本
python复制import kubernetes
from datetime import datetime, timedelta
def drain_node(node_name):
v1 = kubernetes.client.CoreV1Api()
# 检查节点是否已经标记为不可调度
node = v1.read_node(node_name)
if not node.spec.unschedulable:
patch = {"spec": {"unschedulable": True}}
v1.patch_node(node_name, patch)
# 获取该节点上所有Pod
pods = v1.list_pod_for_all_namespaces(
field_selector=f"spec.nodeName={node_name}"
).items
# 迁移策略:先迁移非控制器Pod,再处理控制器管理的Pod
for pod in sorted(pods, key=lambda x: x.metadata.owner_references is None, reverse=True):
print(f"Evicting {pod.metadata.namespace}/{pod.metadata.name}")
try:
v1.create_namespaced_pod_eviction(
name=pod.metadata.name,
namespace=pod.metadata.namespace,
body=kubernetes.client.V1Eviction(
metadata=kubernetes.client.V1ObjectMeta(
name=pod.metadata.name,
namespace=pod.metadata.namespace
)
)
)
except kubernetes.client.ApiException as e:
print(f"Failed to evict {pod.metadata.name}: {e}")
这个脚本包含多个高级技巧:
- 使用patch而非update修改节点状态
- 通过owner_references区分Pod类型
- 实现优雅驱逐(eviction)而非强制删除
4. 生产环境脚本安全规范
4.1 权限控制黄金法则
我经历过因脚本权限过大导致的事故,总结出三条铁律:
- 最小权限原则:为脚本创建专属ServiceAccount
yaml复制apiVersion: v1
kind: ServiceAccount
metadata:
name: script-runner
automountServiceAccountToken: false
- RBAC精准授权:
yaml复制apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- 审计日志必开:
bash复制# 在kube-apiserver启动参数中添加
--audit-log-path=/var/log/k8s-audit.log
--audit-log-maxage=30
4.2 脚本安全检查清单
每个脚本上线前必须完成:
- [ ] 使用
--dry-run=client测试写操作 - [ ] 设置
set -o errexit -o nounset -o pipefail - [ ] 对删除操作添加二次确认
- [ ] 限制并发操作数量
- [ ] 添加资源操作速率限制
一个安全的删除模板:
bash复制#!/bin/bash
set -euo pipefail
RESOURCES=$(kubectl get pods -l app=canary --no-headers | wc -l)
if (( RESOURCES > 5 )); then
echo "WARNING: Attempting to delete $RESOURCES resources" >&2
read -rp "Confirm deletion? (y/n) " choice
case "$choice" in
y|Y ) kubectl delete pods -l app=canary ;;
* ) exit 1 ;;
esac
fi
5. 调试与性能优化实战
5.1 常见错误排查指南
问题:脚本执行卡住无响应
- 检查kubectl版本是否匹配集群(
kubectl version --short) - 添加
--v=6参数查看详细API调用 - 设置全局超时:
KUBECLIENT_TIMEOUT=30
问题:jq处理JSON报错
- 使用
-r参数输出原始字符串 - 对可能为null的字段添加
?:.status?.containerStatuses?[]? - 先输出完整JSON检查数据结构
5.2 性能优化技巧
- 并发控制:使用xargs并行处理
bash复制kubectl get pods -l app=web -o name | \
xargs -P 4 -I {} kubectl exec {} -- /app/health-check
- 缓存机制:减少API调用
python复制from functools import lru_cache
@lru_cache(maxsize=100)
def get_node_info(node_name):
return v1.read_node(node_name)
- 批量操作:使用
kubectl apply -f -替代循环
bash复制kubectl get ns -o json | jq -r '.items[].metadata.name' | \
while read ns; do
echo "apiVersion: v1
kind: ConfigMap
metadata:
name: script-config
namespace: $ns
data:
timestamp: $(date +%s)" | kubectl apply -f -
done
6. 脚本开发环境配置
6.1 IDE推荐配置
VS Code最佳插件组合:
- Kubernetes:IntelliSense支持
- ShellCheck:Shell脚本静态检查
- Python:Pylance语言服务
- YAML:CRD模板支持
我的settings.json关键配置:
json复制{
"kubernetes.snippets.enable": true,
"shellcheck.exclude": ["SC1091", "SC2155"],
"python.analysis.typeCheckingMode": "basic",
"yaml.schemas": {
"kubernetes": "/*.yaml"
}
}
6.2 本地测试环境搭建
使用kind快速创建测试集群:
bash复制# 创建带Metrics Server的集群
cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 8080
protocol: TCP
EOF
# 安装常用组件
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
7. 复杂场景:自定义指标自动伸缩
结合Prometheus实现智能伸缩的Python示例:
python复制from kubernetes import client, config
from prometheus_api_client import PrometheusConnect
prom = PrometheusConnect(url="http://prometheus:9090")
def check_cpu_pressure():
query = 'sum(rate(container_cpu_usage_seconds_total[1m])) by (node) / sum(kube_node_status_capacity_cpu_cores) by (node)'
result = prom.custom_query(query)
return {item['metric']['node']: float(item['value'][1]) for item in result}
def scale_deployment(namespace, name, replicas):
apps_v1 = client.AppsV1Api()
patch = {"spec": {"replicas": replicas}}
apps_v1.patch_namespaced_deployment_scale(
name=name,
namespace=namespace,
body=patch
)
def auto_scaler():
cpu_usage = check_cpu_pressure()
for node, usage in cpu_usage.items():
if usage > 0.8: # 扩容阈值
scale_deployment("app", "frontend", 10)
elif usage < 0.3: # 缩容阈值
scale_deployment("app", "frontend", 3)
这个方案的优势:
- 直接使用原始指标而非HPA预定义指标
- 可以实现跨部署的联动伸缩
- 支持自定义算法处理指标
8. 脚本生命周期管理
8.1 版本控制策略
我推荐的Git仓库结构:
code复制/k8s-scripts
├── /bin # 可执行脚本
├── /lib # 公共函数库
├── /docs # 使用文档
├── /tests # 测试用例
└── Makefile # 构建入口
关键Makefile规则:
makefile复制test:
docker run --rm -v $(PWD):/scripts koalaman/shellcheck:v0.8.0 /scripts/bin/*.sh
deploy:
kubectl create configmap scripts --from-file=bin/ -o yaml --dry-run=client | \
kubectl apply -f -
8.2 持续集成方案
GitLab CI示例:
yaml复制stages:
- test
- deploy
shellcheck:
stage: test
image: koalaman/shellcheck:v0.8.0
script:
- shellcheck bin/*.sh
k8s-apply:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl apply -f <(kubectl create configmap scripts --from-file=bin/ -o yaml --dry-run=client)
only:
- master
9. 新兴趋势:AI辅助脚本生成
最新实践表明,LLM可以辅助生成Kubernetes脚本框架。我的工作流程:
-
需求分解:用自然语言描述任务
code复制我需要一个能自动清理超过7天的Completed状态Pod的脚本,要排除特定命名空间kube-system -
生成初稿:通过AI工具生成框架代码
-
安全加固:人工添加:
- 权限检查
- 速率限制
- 审计日志
-
测试验证:在kind集群中实际运行
典型改进点:
- 添加jq查询的超时处理
- 对大规模集群分页处理
- 增加Prometheus指标暴露
10. 终极方案:脚本即CRD
对于企业级环境,我推荐将脚本转化为Kubernetes原生资源:
yaml复制apiVersion: script.operator/v1
kind: MaintenanceScript
metadata:
name: cleanup-jobs
spec:
schedule: "0 3 * * *" # 每天凌晨3点执行
script: |
#!/bin/bash
kubectl get jobs --all-namespaces --field-selector=status.successful=1
serviceAccount: script-runner
alertRules:
- alert: ScriptFailed
expr: script_execution_status{script="cleanup-jobs"} == 1
for: 5m
这种方案的优点:
- 享受Kubernetes的原生调度能力
- 与现有监控告警体系集成
- 支持GitOps工作流
实现方法:
- 使用Kubebuilder开发Operator
- 通过CronJob资源触发执行
- 使用ConfigMap存储脚本内容
