文章

k8s特殊用法

kubectl -n prod get deployments.apps 获取 副本数为1个的用户名

1
kubectl -n prod get deployments.apps -o jsonpath='{range .items[?(@.spec.replicas==1)]}{.metadata.name}{"\n"}{end}'
1
2
3
4
5
6
7
8
9
apiVersion: apps/v1
kind: Deployment
metadata:
  name: xxx
spec:
  template:
    spec:
      enableServiceLinks: false

设置 污点和容忍度

基本参数解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
taint           污点
tolerations     容忍度

给节点设置污点
kubectl taint nodes nodename key=value:effect

去除污点
kubectl taint nodes nodename key:effect-

key: type
value: mlflow
effect:
    NoSchedule      新的pod将不会调度到该节点
    NoExecute       新的pod将不会调度到该节点,已经在该节点上运行的pod将会被驱逐
    PreSchedule     尽量不会将新的pod调度到该节点

=====================================================
希望将某些pod调度到设置有污点的节点上,则需要在pod的Spec中设置容忍度
tolerations:
- key: "type"
  operator: "Equal"
  value: "mlflow"
  effect: "NoSchedule"
容忍度: 污点的标签: type=mlflow, 会执行 NoSchedule
当pod的容忍度和节点的污点相匹配的时候,pod调度的时候便会忽略节点的污点

tolerations:
- key: "key"
  operator: "Exists"
  effect: "NoSchedule"


operator:
    Equal   默认,value的值需要和taint设置的value值相等。
    Exists  表示可以不指定具体的value

注意:
如果只设置了Exists,则表示该Pod会匹配任意的key,value,effect,会容忍任意的taint。
如果effect为空,则可以与所有键名为key的污点相匹配。


=====================================================
特殊情况:
tolerations:
- key: "key"
  operator: "Equal"
  value: "value"
  effect: "NoExecute"
  tolerationSeconds: 3600

effect为NoExecute
表示已经在该节点上运行的pod的不会被立刻驱逐,还可以运行3600秒。 如果在此之前上述污点被删除了,则 pod 不会被驱逐




使Pod终端能控制当前宿主机的网络

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: v1
kind: Deployment
metadata:
  name: network-tools
spec:
  containers:
  - name: network-tools-container
    image: YOUR_IMAGE
    command: ["/bin/sh", "-c", "sleep 3600"]
    securityContext:
      capabilities:
        add:
          - NET_ADMIN


# 主要配置
securityContext:
      capabilities:
        add:
          - NET_ADMIN

加载configMap 和 Secret 作为环境变量使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
spec:
  template:
    spec:
      containers:
        - envFrom:
            - secretRef:
                name: ***-secret
            - configMapRef:
                name: ***-cm
或者
spec:
  template:
    spec:
      containers:
        - image: ***
          envFrom:
            - secretRef:
                name: ***-secret
            - configMapRef:
                name: ***-cm

为 Pod 自动注入 当前namespace 下的其他服务的环境变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
是否为 Pod 自动注入环境变量,这些环境变量指向同一命名空间中的服务。
默认情况下,这个特性是开启的,但你可以将其设置为 false 来禁用它

1.集群层,不可做

2. namespace层,可做
kubectl edit namespace <namespace-name>
spec:
  enableServiceLinks: false
或者
kubectl patch namespace <namespace-name> -p '{"spec":{"enableServiceLinks":false}}'

3. deployment 可做
kubectl -n <namespace-name> edit deployment ***
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
spec:
  template:
    spec:
      enableServiceLinks: false

挂载 configmap 和 secret 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
## 创建例子 ConfigMap、Secret
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
data:
  mykey: myvalue
  anotherkey: anothervalue

apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  username: YWRtaW4=  # Base64 编码的 "admin"
  password: cGFzc3dvcmQ=  # Base64 编码的 "password"
###################################################################

spec:
  containers:
  - name: my-container
    image: busybox
    command: ["/bin/sh", "-c", "sleep 3600"]
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
    - name: secret-volume
      mountPath: /etc/secret
      readOnly: true
  volumes:
  - name: config-volume
    configMap:
      name: my-config
  - name: secret-volume
    secret:
      secretName: my-secret


## 挂载加 子目录
spec:
  containers:
  - name: my-container
    image: busybox
    command: ["/bin/sh", "-c", "sleep 3600"]
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config/mykey
      subPath: mykey
    - name: config-volume
      mountPath: /etc/config/anotherkey
      subPath: anotherkey
    - name: secret-volume
      mountPath: /etc/secret/username
      subPath: username
      readOnly: true
    - name: secret-volume
      mountPath: /etc/secret/password
      subPath: password
      readOnly: true
  volumes:
  - name: config-volume
    configMap:
      name: my-config
  - name: secret-volume
    secret:
      secretName: my-secret


创建 Headless Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: Service
metadata:
  name: apollo-configservice-hl
  namespace: md
spec:
  type: ClusterIP
  clusterIP: None  # 无头生效位置
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: apollo-configservice

yaml文件特殊值解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
例子1:
volumeMounts:
  - mountPath: /var/www/html
	name: site-data
	subPath: html
  - mountPath: /var/lib/mysql
	name: site-data
	subPath: mysql

subPath: 引用的卷内的子路径,而不是其根路径

============================================
例子2:
volumes:
  - name: git-config
    hostPath:
      path: /root/.ssh
      type: Directory
  - hostPath:
    name: docker
      path: /var/run/docker.sock
      type: Socket
  - name: k8s-config
    secret:
      defaultMode: 420
      secretName: mlflow-kubeconfig
      
type Directory  挂载目录
type: Socket    挂载socket文件    

=================================================


特殊挂载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1. ssh 密钥挂载的时候只需要挂载 私钥即可

secrets.yml
=============================================
apiVersion: v1
kind: Secret
data:
  id_rsa: ******
metadata:
  name: mlflow-ssh-key
  namespace: dev8
type: Opaque

deployment.yml
===============================================
... ...
volumeMounts:
  - mountPath: /root/.ssh/id_rsa
    name: git-config
    subPath: id_rsa
volumes:
  - name: git-config
    secret:
      defaultMode: 0400
      secretName: mlflow-ssh-key

设置共享内存

作用及注意事项

kubernetes 不允许直接修改 Docker 中设置的 shim memory 默认为 64M

实现

1
2
3
4
5
6
7
8
9
10
11
# kubernetes 提供了一种 emptyDir 的方式,可以将 emptyDir.medium 字段设置为 "Memory" 挂载到 /dev/shm,一定要设置 emptyDir.medium 参数,如果不设置,宿主机的内存有可能会被耗尽

#=================================================
    volumeMounts:
      - mountPath: /dev/shm
        name: cache-volume
volumes:
  - emptyDir:
    medium: Memory
    sizeLimit: 170Gi
    name: cache-volume

缺点

1.不能及时禁止用户使用内存。虽然过 1~2 分钟 Kubelet 会将 Pod 挤出,但是这个时间内,其实对 Node 还是有风险的。

2.影响 Kubernetes 调度,因为 emptyDir 并不涉及 Node 的 Resources,这样会造成 Pod “偷偷”使用了 Node 的内存,但是调度器并不知晓。

3.用户不能及时感知到内存不可用。

设置容器生命周期管理

生命周期钩子(Lifecycle Hooks)

在容器生命周期的特定阶段触发自定义操作,例如:

  • postStart:容器启动后立即执行(与主进程并行,不阻塞容器启动)。
  • preStop:容器终止前执行(用于优雅关闭,例如清理资源、通知其他服务)。
1
2
3
4
5
6
7
8
9
10
containers:
- name: myapp
 image: myapp:latest
 lifecycle:
   postStart:
     exec:
       command: ["/bin/sh", "-c", "echo '容器已启动' > /tmp/start.log"]
   preStop:
     exec:
       command: ["/bin/sh", "-c", "supervisorctl stop all"]

注意事项:

  • postStart:不保证在容器 ENTRYPOINT 之前完成。
  • preStop:是优雅终止的关键步骤,Kubernetes 会等待其执行完成(默认最多 terminationGracePeriodSeconds 时间)。

lifecycle.preStop

容器停止前的优雅终止

1
2
3
4
5
6
7
lifecycle:
 preStop:
   exec:
     command:
       - supervisorctl
       - stop
       - all

作用

  • 在 Kubernetes 终止容器 之前,先执行 supervisorctl stop all 命令,优雅停止由 supervisor 管理的所有进程。
  • 避免强制终止导致数据丢失或请求中断(例如:完成正在处理的请求、关闭数据库连接等)。

用 Pod 字段作为环境变量的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
apiVersion: v1
kind: Pod
metadata:
  name: dapi-envars-fieldref
spec:
  containers:
    - name: test-container
      image: registry.k8s.io/busybox
      command: [ "sh", "-c"]
      args:
      - while true; do
          echo -en '\n';
          printenv MY_NODE_NAME MY_POD_NAME MY_POD_NAMESPACE;
          printenv MY_POD_IP MY_POD_SERVICE_ACCOUNT;
          sleep 10;
        done;
      env:
        - name: MY_NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        - name: MY_POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: MY_POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: MY_POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: MY_POD_SERVICE_ACCOUNT
          valueFrom:
            fieldRef:
              fieldPath: spec.serviceAccountName
  restartPolicy: Never

配置外部服务通过Ingress转发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
--- Endpoints
apiVersion: v1
kind: Endpoints
metadata:
  name: xx-xx-svc
  namespace: kmr
subsets:
  - addresses:
      - ip: 10.xx.9.xx
    ports:
      - port: 3000

--- Service
apiVersion: v1
kind: Service
metadata:
  name: xx-xx-svc
  namespace: kmr
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: 3000
      protocol: TCP

--- Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: xx-xx-ingress
  namespace: kmr
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
  ingressClassName: ingress-nginx
  rules:
    - host: xx-xx.hannto.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: xx-xx-svc
                port:
                  number: 80
  tls:
  - secretName: xx-xx
本文由作者按照 CC BY 4.0 进行授权