文章

k8s - k8s使用gvisor

k8s - k8s使用gvisor

k8s使用gvisor部署单一的pod方式

https://github.com/google/gvisor https://gvisor.dev/

跟着官方文档走一圈。

背景

  1. 要安全隔离运行pod内的程序;
  2. 要有且只有一个pod来提供某一个服务,例如one for one claw;
  3. pod异常时能自动恢复。

使用deployment

gVisor

前一篇文章已经提到过安装gvisor。

1
2
root@wfy-0002:~# which runsc
/usr/local/bin/runsc

为什么用deployment

控制平面(API Server + etcd)完全可以支撑一万个 Deployment,许多大型集群甚至运行着数十万个 Deployment。真正的资源挑战在节点层面——你需要有足够的 CPU/内存来运行一万个 Pod。

无Deployment控制的pod:

  1. pod被误删除,无法自动创建。
  2. 节点宕机,其他节点更不会重建。
  3. 手动创建同名pod会因名字冲突而失败,确实能保证唯一。

如果你确实需要自动恢复并保证唯一性,就必须使用 控制器(Deployment、ReplicationController、StatefulSet)。即使是最轻量的 kubectl run --restart=Always 命令,其背后也会创建一个 Deployment 或 ReplicationController。

deployment.yaml

1
2
3
4
5
6
7
#gvisor-runtimeclass.yaml

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: gvisor
handler: runsc

当前目录的 deployment.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
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
#
# kubectl apply -f deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: unique-claw-001 # Deployment 自身标识:名称 + 命名空间唯一(与 Pod 类似)。
  namespace: default
spec:
  replicas: 1  #  永远只运行一个实例
  strategy:
    type: Recreate  # 默认 RollingUpdate 策略,绝对不能容忍双 Pod 同时存在,可以把 strategy.type 改为 Recreate
  revisionHistoryLimit: 2   # 减少历史版本
  selector:
    matchLabels:
      app: unique-claw-001   # 用来匹配 Pod 的标签
  template:
    metadata:
      labels:
        app: unique-claw-001
    spec:
      restartPolicy: Always    # Pod 异常退出后自动重启(默认就是 Always,可省略)
      runtimeClassName: gvisor  # 关键:指定使用 gvisor 运行时
      containers:
      - name: app
        image: redis:7.2.5
        ports:
          - containerPort: 6379
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"
        # 1. 启动探针:仅在 Pod 启动期间执行,成功后不再介入
        startupProbe:
          exec:
            command:
            - sh
            - -c
            - |
              # 使用 timeout 防止 redis-cli 卡死
              timeout 3 redis-cli -h 127.0.0.1 -p 6379  --no-auth-warning PING | grep  PONG
          initialDelaySeconds: 10      # 容器启动后等10秒才开始探测
          periodSeconds: 5             # 每5秒探测一次
          timeoutSeconds: 3            # 探测超时时间3秒
          failureThreshold: 30         # 允许失败30次,启动慢时可适当放宽
          successThreshold: 1          # 成功1次即认为探针成功
    # 2. 存活探针:Pod 稳定运行后,持续检查 Redis 状态
        livenessProbe:
          exec:
            command:
            - sh
            - -c
            - |
              timeout 3 redis-cli -h 127.0.0.1 -p 6379 --no-auth-warning PING | grep  PONG
          initialDelaySeconds: 0       # 从 startup 结束后开始
          periodSeconds: 15            # 每15秒探测一次
          timeoutSeconds: 3            # 超时时间3秒
          failureThreshold: 3          # 连续失败3次才重启容器
          successThreshold: 1          # 成功1次即恢复健康

观察对应的进程和pod状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 未使用runsc
root@raha-0002:~# ps axu|grep redis
dnsmasq  2401711  0.9  0.3  55600 14752 ?        Ssl  17:51   0:00 redis-server *:6379
root     2401779  0.0  0.0   6336  2176 pts/0    S+   17:51   0:00 grep redis

# 使用runsc以后
root@raha-0002:~# ps axu|grep redis
root     2403160  0.0  0.0   6336  2176 pts/0    S+   17:53   0:00 grep redis
root@raha-0002:~# ps axu|grep redis

# pod删除后,可以自动拉起
root@raha-0001:/data/tmp# kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
openclaw-deployment-77785d7699-2pw5z   1/1     Running   0          24d
unique-claw-001-ddcdd6b9c-8867z        1/1     Running   0          16m
本文由作者按照 CC BY 4.0 进行授权