《Kubernetes 资源配额、健康检查与安全访问控制实战精要》

本总结覆盖 ResourceQuota(资源配额)、LimitRange(限制范围)、Pod 资源请求与限制、容器健康检查(Liveness/Readiness/Startup 探针)、Kubernetes 认证与鉴权(RBAC) 以及 服务账户(ServiceAccount) 的完整原理、配置与实战代码,所有核心知识点均配有详细注释,可直接用于生产环境。


一、资源配额(ResourceQuota)

1.1 为什么需要 ResourceQuota

  • 多团队共享集群时,防止某一命名空间耗尽集群资源。
  • 通过 ResourceQuota 对象限制 计算资源(CPU/内存) 和 对象数量(Pod/Service/Secret 等) 的总用量。

1.2 配额类型

  • 计算资源:requests.cpu、requests.memory、limits.cpu、limits.memory、requests.storage 等。
  • 对象数量:pods、services、secrets、configmaps、persistentvolumeclaims、deployments.apps 等。

若命名空间启用了计算资源配额,则创建 Pod 时 必须指定 requests 和 limits,否则 API 服务器拒绝创建。

1.3 ResourceQuota YAML(带注释)

apiVersion: v1
kind: ResourceQuota
metadata:
  name: myquota
  namespace: quota                        # 作用域
spec:
  hard:
    persistentvolumeclaims: "10"          # PVC 数量上限
    pods: "2"                             # Pod 总数上限
    secrets: "5"                          # Secret 数量上限
    services: "3"                         # Service 数量上限
    requests.cpu: "1000m"                 # 所有 Pod 的 CPU 请求总和上限(1核)
    requests.memory: "2048Mi"             # 所有 Pod 的内存请求总和上限
    limits.cpu: "1000m"                   # 所有 Pod 的 CPU 限制总和上限
    limits.memory: "2048Mi"               # 所有 Pod 的内存限制总和上限

1.4 命令行创建与测试

# 创建配额(限制 Pod 数量为 2)
kubectl create quota myquota --hard=pods=2

# 查看配额使用情况
kubectl describe resourcequota myquota

# 尝试创建 3 个副本的 Deployment,第三个 Pod 会被拒绝(超出配额)
kubectl create deployment web --image=nginx --replicas=3
# 事件报错:exceeded quota: myquota, requested: pods=1, used: pods=2, limited: pods=2

# 动态调整配额(增加 Pod 上限至 10)
kubectl patch resourcequota myquota -p '{"spec":{"hard":{"pods":10}}}'

二、Pod 资源请求(requests)与限制(limits)

2.1 概念

  • requests:调度器依据此值选择有足够资源的节点,保证 Pod 运行所需的最小资源。
  • limits:cgroups 强制限制 Pod 能使用的最大资源,防止“吵闹邻居”问题。

2.2 资源单位

  • CPU:1 = 1000m(毫核)。
  • 内存:支持二进制单位(Ki/Mi/Gi)和十进制单位(k/M/G),默认 Gi。

2.3 仅配置 requests(带注释)

apiVersion: v1
kind: Pod
metadata:
  name: web
spec:
  containers:
  - name: nginx
    image: nginx
    resources:
      requests:
        cpu: 200m          # 请求 0.2 核
        memory: 256Mi      # 请求 256 MiB
    # 未指定 limits,则 limits 默认为 requests 值(若 LimitRange 未设置默认值)

2.4 仅配置 limits

resources:
  limits:
    cpu: 500m
    memory: 512Mi
# requests 未指定,则 requests 默认等于 limits 值

2.5 同时配置(最佳实践)

resources:
  requests:
    cpu: 200m
    memory: 256Mi
  limits:
    cpu: 500m
    memory: 512Mi

2.6 使用 stress 镜像测试 CPU 限制

apiVersion: v1
kind: Pod
metadata:
  name: stress-cpu
spec:
  containers:
  - name: stress
    image: progrium/stress
    args: ['-c', '1']                  # 启动 1 个 CPU 密集工作线程
    resources:
      limits:
        cpu: 200m                      # 限制 CPU 为 0.2 核
        memory: 256Mi
  • 通过 kubectl top pod 观察,CPU 使用率将被压制在 200m 左右。

2.7 使用 stress 测试内存限制(OOM)

args: ['-m', '1', '--vm-bytes', '512M']   # 申请 512MB 内存
resources:
  limits:
    memory: 256Mi                         # 限制为 256Mi,将触发 OOMKill
  • Pod 状态变为 OOMKilled,反复重启。

2.8 重要结论

  • CPU 是可压缩资源,超限时会被节流(throttle),Pod 不会被杀。
  • 内存是不可压缩资源,超限时触发 OOMKilled,容器被杀死并重启。

三、LimitRange(限制范围)

3.1 为什么需要 LimitRange

  • 当命名空间启用了 ResourceQuota 后,若 Pod 未指定 resources,则无法创建。
  • LimitRange 可为未指定资源的 Pod 设置默认 requests 和 limits,也可限制最小/最大值。

3.2 LimitRange YAML(带详细注释)

apiVersion: v1
kind: LimitRange
metadata:
  name: mylimit
  namespace: quota
spec:
  limits:
  - type: Container                     # 可选项:Container / Pod / PersistentVolumeClaim
    max:
      cpu: "1"                          # 单个容器 CPU 最大值(1核)
      memory: 1024Mi                    # 单个容器内存最大值
    min:
      cpu: 100m                         # 单个容器 CPU 最小值
      memory: 128Mi
    default:                            # 未指定 limits 时的默认值
      cpu: 500m
      memory: 512Mi
    defaultRequest:                     # 未指定 requests 时的默认值
      cpu: 200m
      memory: 256Mi

约束关系:min <= defaultRequest <= default <= max

3.3 验证默认值行为

  • 创建无 resources 的 Pod,其 requests 和 limits 会被自动填充为 defaultRequest 和 default。
  • 若仅指定 limits 而未指定 requests,则 requests 自动等于 limits(非 defaultRequest)。
  • 若仅指定 requests 而未指定 limits,则 limits 自动等于 default。
  • 若请求的值超出 max 或低于 min,API 服务器拒绝创建。

四、健康检查(Health Check / Probes)

4.1 探针类型

  • LivenessProbe:检测容器是否存活,失败则重启容器。
  • ReadinessProbe:检测容器是否就绪可接收流量,失败则从 Service Endpoints 中移除。
  • StartupProbe:用于慢启动容器,成功前不会执行 Liveness/Readiness。

4.2 探测方法

  • httpGet:发送 HTTP GET 请求,状态码 200-399 为成功。
  • exec:在容器内执行命令,退出码 0 为成功。
  • tcpSocket:尝试建立 TCP 连接,成功打开端口为成功。
  • grpc:调用 gRPC 健康检查接口。

4.3 通用探针参数(带注释)

livenessProbe:
  initialDelaySeconds: 5      # 容器启动后延迟多少秒开始探测
  periodSeconds: 5            # 探测间隔(秒)
  timeoutSeconds: 10          # 探测超时时间
  successThreshold: 1         # 连续成功多少次才算成功(默认 1)
  failureThreshold: 3         # 连续失败多少次才算失败(默认 3)

4.4 LivenessProbe – httpGet 示例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: httpd
        image: httpd
        livenessProbe:
          httpGet:
            path: /index.html
            port: 80
            scheme: HTTP
          initialDelaySeconds: 5
          periodSeconds: 5
  • 若删除 /usr/local/apache2/htdocs/index.html,探测失败,容器会自动重启。

4.5 ReadinessProbe – httpGet 示例

readinessProbe:
  httpGet:
    path: /index.html
    port: 80
  initialDelaySeconds: 5
  periodSeconds: 5
  • 若某 Pod 的 index.html 被删除,该 Pod 的 IP 会从 Service Endpoints 中移除,不再接收流量。

4.6 LivenessProbe – exec 示例(检测文件是否存在)

livenessProbe:
  exec:
    command:
    - cat
    - /tmp/healthy
  initialDelaySeconds: 5
  periodSeconds: 5

4.7 LivenessProbe – tcpSocket 示例

livenessProbe:
  tcpSocket:
    port: 80

4.8 StartupProbe 典型用法(慢启动应用)

startupProbe:
  httpGet:
    path: /health
    port: 8080
  failureThreshold: 30        # 允许 30 次失败(每次 10s = 300s 启动时间)
  periodSeconds: 10
  • 在 StartupProbe 成功之前,Liveness 和 Readiness 不会执行。

五、认证(Authentication)

5.1 Kubernetes API 访问控制流程

  1. 传输安全(TLS)
  2. 认证(Authentication):验证客户端身份。
  3. 鉴权(Authorization):判断是否有权执行操作。
  4. 准入控制(Admission Control):可修改或拒绝请求。
  5. 审计(Audit):记录操作日志。

5.2 用户类型

  • 普通用户(User):由外部认证系统(如 X509 证书)管理,Kubernetes 没有对应的 User 资源。
  • 服务账户(ServiceAccount):由 Kubernetes API 管理,属于命名空间级别。

5.3 使用 X509 客户端证书创建用户(完整流程)

① 客户端生成私钥和证书签名请求(CSR)
# 客户端(如 client 节点)操作
openssl genrsa -out laoma.key 2048
openssl req -new -key laoma.key -out laoma.csr -subj "/CN=laoma/O=kubernets"
# CN 为用户名,O 为用户组(可选)
② 管理员使用集群 CA 签发证书
# 管理员(master)操作
openssl x509 -req -in laoma.csr -CA /etc/kubernetes/pki/ca.crt \
  -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out laoma.crt -days 1095
③ 创建 kubeconfig(方法一:使用 kubectl config 命令)
# 将 CA 证书、用户证书和私钥拷贝到客户端,然后执行:
kubectl config set-cluster kubernetes --kubeconfig=config \
  --server=https://10.1.8.30:6443 \
  --certificate-authority=ca.crt --embed-certs

kubectl config set-credentials laoma --kubeconfig=config \
  --client-key=laoma.key --client-certificate=laoma.crt --embed-certs

kubectl config set-context laoma@kubernetes --kubeconfig=config \
  --cluster=kubernetes --user=laoma --namespace=default

kubectl config use-context laoma@kubernetes --kubeconfig=config
④ 授权用户(后续 RBAC 章节)
kubectl create clusterrolebinding laoma-admin --clusterrole=cluster-admin --user=laoma

5.4 删除用户权限(非删除用户本身)

kubectl delete clusterrolebinding laoma-admin   # 回收权限
# 客户端重新请求会被拒绝(403)

六、授权(Authorization)与 RBAC

6.1 RBAC 核心资源

  • Role:命名空间级别的权限集合。
  • ClusterRole:集群级别的权限集合。
  • RoleBinding:将 Role 绑定到用户/组/服务账户(指定命名空间)。
  • ClusterRoleBinding:将 ClusterRole 绑定到用户/组/服务账户(集群范围)。

6.2 权限规则(PolicyRule)构成

  • apiGroups:资源所属的 API 组(如 ""、apps、batch)。
  • resources:资源类型(如 pods、deployments、deployments/scale)。
  • verbs:操作动词(get、list、watch、create、update、patch、delete、deletecollection、exec 等)。
  • resourceNames:可选,限定特定资源名称。

6.3 创建 Role 并绑定(带注释)

# role.yaml - 允许 get/list/watch pods
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: default
rules:
- apiGroups: [""]                # 核心 API 组(空字符串)
  resources: ["pods"]            # 资源类型
  verbs: ["get", "list", "watch"] # 操作权限
# rolebinding.yaml - 将 role 绑定给用户 laoma
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: laoma-pod-reader
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pod-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: laoma
# 创建
kubectl apply -f role.yaml
kubectl apply -f rolebinding.yaml

6.4 创建 ClusterRole 并绑定(集群级别)

# clusterrole.yaml - 允许在所有命名空间 get/list/watch pods
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
# clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: laoma-cluster-pod-reader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-pod-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: laoma

6.5 常用预定义 ClusterRole

  • view:对所有资源(除 secrets 等)拥有 get/list/watch 权限。
  • edit:在 view 基础上增加 create/update/patch/delete 权限(对大多数资源)。
  • admin:命名空间内的完全控制权(但不能修改资源配额和命名空间本身)。
  • cluster-admin:集群超级管理员权限。

6.6 多规则 Role 示例(不同资源不同权限)

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: multi-role
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
  resources: ["deployments", "deployments/scale"]   # 子资源
  verbs: ["get", "list", "watch", "patch"]          # patch 用于 scale

6.7 apiGroups 速查

资源类型apiVersionapiGroups
Pod, Service, PVCv1“”
Deployment, DaemonSetapps/v1“apps”
Job, CronJobbatch/v1“batch”
Role, RoleBindingrbac.authorization.k8s.io/v1“rbac.authorization.k8s.io”
NetworkPolicynetworking.k8s.io/v1“networking.k8s.io”

七、服务账户(ServiceAccount)

7.1 服务账户 vs 用户账户

特性用户账户服务账户
使用者人Pod 中的进程
范围集群级别命名空间级别
管理方式外部认证(证书/令牌)Kubernetes API 自动管理

7.2 默认服务账户

  • 每个命名空间都有一个 default ServiceAccount。
  • 未指定 serviceAccountName 的 Pod 自动使用 default。

7.3 创建自定义 ServiceAccount 并绑定角色

# 创建服务账户
kubectl create sa sa1 -n auth

# 将集群角色 cluster-admin 绑定给 sa1(注意格式:--serviceaccount=namespace:name)
kubectl create clusterrolebinding sa1-admin \
  --clusterrole=cluster-admin \
  --serviceaccount=auth:sa1

7.4 在 Pod 中使用自定义服务账户

apiVersion: v1
kind: Pod
metadata:
  name: web
  namespace: auth
spec:
  serviceAccountName: sa1           # 使用自定义 SA
  containers:
  - name: nginx
    image: nginx
  • Pod 内的进程将拥有 sa1 被授予的权限(如管理整个集群)。

7.5 服务账户令牌(Token)

① 临时令牌(TokenRequest API,推荐)
kubectl create token sa1 -n auth
# 返回一个短期有效的 JWT 令牌
② 手动创建长期令牌(通过 Secret,不推荐)
apiVersion: v1
kind: Secret
metadata:
  name: sa1-token
  namespace: auth
  annotations:
    kubernetes.io/service-account.name: sa1   # 关键注解
type: kubernetes.io/service-account-token
  • 创建后,控制平面自动将令牌填充到 data.token 中。
  • 删除 ServiceAccount 时,关联的 Secret 会被自动清理。

7.6 Pod 内访问 API 的默认挂载(v1.22+)

  • Kubernetes 自动将 投射卷(Projected Volume) 挂载到 /var/run/secrets/kubernetes.io/serviceaccount。
  • 包含三个文件:
    • token:绑定到 Pod 的短期令牌。
    • ca.crt:集群 CA 证书。
    • namespace:Pod 所在的命名空间。
# 进入 Pod 验证
kubectl exec -it web -- cat /var/run/secrets/kubernetes.io/serviceaccount/token

八、环境清理

kubectl delete ns quota        # 配额与限制
kubectl delete ns health       # 健康检查
kubectl delete ns auth         # 认证与授权

以上内容涵盖了 资源配额与限制、健康检查探针、认证(X509 证书) 和 RBAC 授权 的全部核心知识点,所有 YAML 和命令均附带详细注释。建议在独立命名空间中逐一实践,加深对 Kubernetes 安全与资源管理机制的理解。

更多推荐