K8S - kubectl patch 实现非交互式修改 yaml 文件完成 pod 变动


使用 kubectl patch 更新 API 对象

前言:

假如我们部署了几个 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

posted @ 2022-06-21 14:41  公博义  阅读(5193)  评论(0编辑  收藏  举报