securityContext、资源、配额、QoS
目标
能够通过清单规定 Pod 在节点上可以做什么(securityContext、ServiceAccount)以及可以使用多少资源(resources、LimitRange、ResourceQuota),并确认由此如何决定 QoS 类别。
为什么重要
容器默认以 root 身份运行,这是由镜像的构建方式决定的。只要存在一个容器逃逸漏洞,该 root 就可能进一步成为节点上的 root。runAsNonRoot: true 会直接阻止试图以 UID 0 启动的容器,capabilities.drop: ["ALL"] 则会移除内核授予的全部特权。如果 Web 服务器必须监听 80 端口,只需重新添加 NET_BIND_SERVICE。这就是最小权限原则的具体实现。
资源方面应分两层理解。requests 是调度器的语言。只有节点剩余可分配量大于 requests 总和时,Pod 才能调度到该节点,这与实际使用量无关。limits 是节点的语言。CPU 会通过 cgroup 配额节流,内存一旦超出就会 OOMKilled。因此,如果内存 limits 低于实际峰值,Pod 会悄无声息地反复重启。
LimitRange 和 ResourceQuota 必须配套理解。在设置了配额的命名空间中,创建没有 requests/limits 的 Pod 时,创建操作本身会被拒绝。如果只给团队命名空间设置配额,可能导致任何应用都无法启动,因此使用 LimitRange 填充默认值实际上必不可少。
步骤
- 创建命名空间
ckad-secure,并在其中创建 ServiceAccountapp-sa。 - 创建 Pod
sa-pod。镜像nginx:1.27,serviceAccountName: app-sa,automountServiceAccountToken: false。 - 创建 Pod
nonroot。镜像nginx:1.27,在 Pod 层级securityContext中设置runAsNonRoot: true、runAsUser: 1000、fsGroup: 2000。 - 创建 Pod
hardened。镜像nginx:1.27,容器名称app;在容器层级securityContext中设置allowPrivilegeEscalation: false、readOnlyRootFilesystem: true、capabilities.drop: ["ALL"]、capabilities.add: ["NET_BIND_SERVICE"]。 - 创建 Deployment
api。副本数 2,标签app=api,镜像nginx:1.27;容器的resources.requests为cpu: 100m/memory: 128Mi,resources.limits为cpu: 500m/memory: 512Mi。 - 创建 LimitRange
defaults。type: Container,default(limits)为cpu: 200m/memory: 256Mi,defaultRequest为cpu: 100m/memory: 128Mi,max为cpu: "1"/memory: 1Gi,min为cpu: 50m/memory: 64Mi。 - 创建 ResourceQuota
team-quota。requests.cpu: "2"、requests.memory: 4Gi、limits.cpu: "4"、limits.memory: 8Gi、pods: "10"。 - 再创建两个 Pod。
qos-guaranteed的 requests 与 limits 均必须为cpu: 250m/memory: 256Mi;qos-burstable只设置 requests,值为cpu: 100m/memory: 128Mi。两者均使用镜像nginx:1.27。
参考
- 可使用
kubectl create deployment api --image=nginx:1.27 --replicas=2 -n ckad-secure --dry-run=client -o yaml生成骨架并手动填写resources,也可以创建后使用kubectl set resources deployment api -n ckad-secure --requests=... --limits=...。 - 完成第 7 步后,无法在该命名空间中创建没有 requests/limits 的 Pod。如需重新创建前面步骤的 Pod,请确认 LimitRange 会填充默认值。
- 常见错误 1:把
fsGroup或runAsNonRoot写在容器下。fsGroup只存在于 Pod 层级。 - 常见错误 2:把
capabilities写在 Pod 层级。它只存在于容器层级。 - 验证:
kubectl get pod qos-guaranteed -n ckad-secure -o jsonpath='{.status.qosClass}'
命名空间与 ServiceAccount
创建命名空间 ckad-secure,并在其中创建 ServiceAccount app-sa。
使用 kubectl create serviceaccount 创建。先创建命名空间,再在其中创建 ServiceAccount。
为 Pod 指定 ServiceAccount 并关闭令牌自动挂载
创建 Pod sa-pod。镜像 nginx:1.27,serviceAccountName: app-sa,automountServiceAccountToken: false。
字段名称是 spec.serviceAccountName(serviceAccount 是旧别名)。关闭令牌自动挂载的布尔字段也位于 Pod 规范顶层。
Pod 层级 securityContext
创建 Pod nonroot。镜像 nginx:1.27,在 Pod 层级 securityContext 中设置 runAsNonRoot: true、runAsUser: 1000、fsGroup: 2000。
spec.securityContext 中的值会应用于整个 Pod。指定卷所有者组的字段只存在于 Pod 层级。
容器层级 securityContext 与 capabilities
创建 Pod hardened。镜像 nginx:1.27,容器名称 app;在容器层级 securityContext 中设置 allowPrivilegeEscalation: false、readOnlyRootFilesystem: true、capabilities.drop: ["ALL"]、capabilities.add: ["NET_BIND_SERVICE"]。
capabilities 只存在于容器层级。先全部移除,再仅添加所需能力,就是最小权限原则。drop 和 add 均为字符串数组。
为 Deployment 指定 requests 与 limits
创建 Deployment api。副本数 2,标签 app=api,镜像 nginx:1.27;容器的 resources.requests 为 cpu: 100m / memory: 128Mi,resources.limits 为 cpu: 500m / memory: 512Mi。
resources 位于容器下。requests 是调度器使用的值,limits 是运行时强制执行的值。CPU 单位 m 表示 1/1000 核。
使用 LimitRange 设置默认值及上下限
创建 LimitRange defaults。type: Container,default(limits)为 cpu: 200m / memory: 256Mi,defaultRequest 为 cpu: 100m / memory: 128Mi,max 为 cpu: "1" / memory: 1Gi,min 为 cpu: 50m / memory: 64Mi。
spec.limits 是数组,每个元素都含有 type。默认 limits 和默认 requests 使用不同的键名,请用 kubectl explain limitrange.spec.limits 确认。
使用 ResourceQuota 限制命名空间总量
创建 ResourceQuota team-quota。requests.cpu: "2"、requests.memory: 4Gi、limits.cpu: "4"、limits.memory: 8Gi、pods: "10"。
spec.hard 是映射,键名包含点,例如 requests.cpu、limits.memory。数量限制应像 pods 一样使用字符串值。
综合:按预期创建 QoS 类别
再创建两个 Pod。qos-guaranteed 的 requests 与 limits 均必须为 cpu: 250m / memory: 256Mi;qos-burstable 只设置 requests,值为 cpu: 100m / memory: 128Mi。两者均使用镜像 nginx:1.27。
QoS 不是可直接指定的字段,而是由 requests/limits 组合决定的结果。所有容器的 CPU 和内存 requests 与 limits 都必须相等,才能获得最高等级。使用 kubectl get pod -o jsonpath='{.status.qosClass}' 检查。