K8S - kubectl patch 实现非交互式修改 yaml 文件完成 pod 变动
目录
前言:
假如我们部署了几个 DaemonSet 控制的 Pod,如果我们想禁止其调度到某个节点,我们可以
kubectl edit DaemonSet xxx
添加一段 node 驱逐策略,edit 保存退出之后会自动完成 pod 的变动,但是这样是交互式的,如果集群机器非常多的情况下,会变得很麻烦,现在想要一条命令完成调度。spec: revisionHistoryLimit: 10 selector: matchLabels: app: nginx template: metadata: creationTimestamp: null labels: app: nginx spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: NotIn values: - node02 containers: - image: nginx:1.14.1 imagePullPolicy: IfNotPresent ..........
1. 创建 nginx-daemonset.yaml 并发布
nginx-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-daemonset
labels:
app: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.1
ports:
- containerPort: 80
发布
kubectl apply -f nginx-daemonset.yaml
查看
[root@master ~]#kubectl get pods,svc -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-daemonset-5ln28 1/1 Running 0 60s 10.244.1.3 node01 <none> <none>
pod/nginx-daemonset-z86nn 1/1 Running 0 60s 10.244.2.3 node02 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d10h <none>
[root@master ~]#kubectl get DaemonSet
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
nginx-daemonset 2 2 2 2 2 <none> 9m58s
2. edit 编辑 nginx-daemonset 完成 pod 调度
添加的 yaml 字段的含义是不允许该 pod 调度到 node02 节点。
[root@master ~]#kubectl edit DaemonSet nginx-daemonset
...
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- node02
...
查看
[root@master ~]#kubectl get pods,svc -o wide # pod 已经从 node02 驱逐
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-daemonset-xnfjq 1/1 Running 0 5m21s 10.244.1.4 node01 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d10h <none>
3. 使用 patch 非交互式修改 pod yaml 文件完成动态更新
[yaml 转 json 工具](在线YAML转JSON工具 - ToolTT在线工具箱)
3.1 将我们需要添加的 yaml 文件字段转换成 json
// 从这里开始,去掉不需要的字段
spec:
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- node02
// -------------------------- //
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- node02
json 格式
{
"spec": {
"template": {
"spec": {
"affinity": {
"nodeAffinity": {
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [
{
"matchExpressions": [
{
"key": "kubernetes.io/hostname",
"operator": "NotIn",
"values": [
"node02"
]
}
]
}
]
}
}
}
}
}
}
}
// 压缩格式
{"spec":{"template":{"spec":{"affinity":{"nodeAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":{"nodeSelectorTerms":[{"matchExpressions":[{"key": "kubernetes.io/hostname","operator": "NotIn","values": ["node02"]}]}]}}}}}}}
查看当前 pod
# 删除了先前的实验配置,重新 apply
[root@master ~]#kubectl get pods,svc -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-daemonset-6x6kw 1/1 Running 0 11s 10.244.2.6 node02 <none> <none>
pod/nginx-daemonset-j58xv 1/1 Running 0 11s 10.244.1.8 node01 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d14h <none>
3.2 使用 patch 更新 pod
[root@master ~]#kubectl patch DaemonSet nginx-daemonset --patch '{"spec":{"template":{"spec":{"affinity":{"nodeAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":{"nodeSelectorTerms":[{"matchExpressions":[{"key": "kubernetes.io/hostname","operator": "NotIn","values": ["node02"]}]}]}}}}}}}'
daemonset.apps/nginx-daemonset patched
查看结果
# 可以看到只有 node01 节点存在该 pod
[root@master ~]#kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-daemonset-d94fc 0/2 ContainerCreating 0 2s <none> node01 <none> <none>
[root@master ~]#kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-daemonset-d94fc 2/2 Running 0 42s 10.244.1.7 node01 <none> <none>
4. kubectl patch 常用命令
使用 patch 更新 Node 节点
kubectl patch node k8s-node-1 -p '{"spec":{"unschedulable":true}}'
使用 patch 更新由 node.json 文件中指定的类型和名称标识的节点
kubectl patch -f node.json -p '{"spec":{"unschedulable":true}}'
更新容器的镜像
kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve-hostname","image":"new image"}]}}'
或
kubectl patch pod valid-pod --type='json' -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"new image"}]'
设置服务对外的 IP
kubectl patch svc <svc-name> -n <namespace> -p '{"spec": {"type": "LoadBalancer", "externalIPs":["192.168.31.241"]}}'
脚本实现批量更新 deploy 添加反亲和
#!/bin/bash
DEPLOY_NAME=($(kubectl get deploy -n zcm9 | grep -v -E "NAME|mysql|redis|task|zcache|net|minio|serverless" | awk '{print $1}'))
for ((i=0;i<${#DEPLOY_NAME[@]};i++))
do
cat > ./exec_patch.sh << EOF
kubectl patch deployment NAME -n zcm9 --patch '{"spec":{"template":{"spec":{"affinity":{"podAffinity":{},"podAntiAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchExpressions":[{"key":"zcm-app","operator":"In","values":["NAME"]}]},"topologyKey":"kubernetes.io/hostname"}]}}}}}}'
EOF
sed -i "s/NAME/${DEPLOY_NAME[i]}/g" ./exec_patch.sh
sh ./exec_patch.sh
if [ $? -ne 0 ];then
echo ${DEPLOY_NAME[i]}" patch failed,please check!!!"
exit 1
fi
echo ${DEPLOY_NAME[i]}" patch success!!!"
rm -rf ./exec_patch.sh
sleep 2
done