安全架构深度剖析

概述

Kubernetes 安全架构涵盖身份认证(Authentication)、授权(Authorization)、准入控制(Admission Control)、网络策略(NetworkPolicy)等多个层次。本文深入剖析 Kubernetes 安全机制的工作原理。

安全分层架构

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
┌──────────────────────────────────────────────────────────────────────────────┐
│ Kubernetes 安全分层 │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 7. 网络安全层 │ │
│ │ NetworkPolicy / CNI │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 6. 运行时安全 │ │
│ │ PodSecurityPolicy / PSA │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 5. 资源安全层 │ │
│ │ ResourceQuota / LimitRange │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 4. 准入控制层 │ │
│ │ Mutating + Validating Webhook │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 3. 授权层 │ │
│ │ RBAC / ABAC / Node / Webhook │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 2. 认证层 │ │
│ │ X509 / Token / OIDC / Webhook │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 1. API 安全层 │ │
│ │ TLS / 审计日志 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘

认证 (Authentication)

认证方式

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
┌──────────────────────────────────────────────────────────────────────────────┐
│ 认证方式概览 │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ X509 客户端证书 │ │
│ │ - kubeconfig 中的 client-certificate-data │ │
│ │ - kubelet 使用的 Kubelet Certificate Rotation │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Bearer Token │ │
│ │ - ServiceAccount Token │ │
│ │ - Bootstrap Token │ │
│ │ - 静态 Token 文件 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ OIDC (OpenID Connect) │ │
│ │ - 第三方身份提供商集成 │ │
│ │ - dex, Keycloak, Auth0 等 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Webhook Token Authentication │ │
│ │ - 外部认证服务验证 Token │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Anonymous Auth (匿名) │ │
│ │ - 启用: --anonymous-auth=true (默认) │ │
│ │ - 禁用: --anonymous-auth=false │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘

ServiceAccount Token

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 自动创建 ServiceAccount 时会创建对应的 Token Secret
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-sa
namespace: default
---
apiVersion: v1
kind: Secret
metadata:
name: my-sa-token-xxxxx
annotations:
kubernetes.io/service-account.name: my-sa
type: kubernetes.io/service-account-token
data:
# JWT Token 内容 (base64 编码)
token: <base64 encoded JWT>
# CA 证书
ca.crt: <base64 encoded CA>

Token 格式

1
2
3
4
5
6
7
8
9
{
"iss": "kubernetes/serviceaccount",
"kubernetes.io/serviceaccount/namespace": "default",
"kubernetes.io/serviceaccount/secret.name": "my-sa-token-xxxxx",
"kubernetes.io/serviceaccount/service-account.name": "my-sa",
"kubernetes.io/serviceaccount/service-account.uid": "<uid>",
"sub": "system:serviceaccount:default:my-sa",
"aud": "https://kubernetes.default.svc"
}

授权 (Authorization)

授权模式

1
2
# kube-apiserver 启动参数
--authorization-mode=Node,RBAC
模式 说明
AlwaysAllow 允许所有请求(默认)
AlwaysDeny 拒绝所有请求(测试用)
RBAC 基于角色的访问控制(推荐)
ABAC 基于属性的访问控制
Node Node 授权器,kubelet 专用
Webhook 外部授权服务

RBAC 核心概念

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
┌──────────────────────────────────────────────────────────────────────────────┐
│ RBAC 核心概念 │
│ │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ Role │ │ RoleBinding │ │ Subject │ │
│ │ (角色) │────>│ (绑定) │<────│ (主体) │ │
│ │ │ │ │ │ │ │
│ │ rules: │ │ subjects: │ │ - User │ │
│ │ - verbs: │ │ - kind: │ │ - Group │ │
│ │ get,list │ │ ServiceAccount│ │ - ServiceAccount│ │
│ │ - resources: │ │ name: my-sa │ │ │ │
│ │ pods │ │ │ │ │ │
│ │ - apiGroups:│ │ roleRef: │ │ │ │
│ │ "" │ │ kind: Role │ │ │ │
│ └───────────────┘ │ name: pod-reader│ └───────────────┘ │
│ │ └───────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ ClusterRole │ │
│ │ (集群角色) │ │
│ │ │ │
│ │ 区别: │ │
│ │ - 作用于集群 │ │
│ │ - 可绑定任意命名空间│ │
│ └───────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘

PolicyRule 详解

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
# Role 示例
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: default
rules:
# 规则1: 读取 pods
- apiGroups: [""] # 核心 API 组
resources: ["pods"] # 资源类型
verbs: ["get", "list", "watch"] # 操作

# 规则2: 读取 pods/logs (子资源)
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get", "list"]

# 规则3: 读取特定名称的 pod
- apiGroups: [""]
resources: ["pods"]
resourceNames: ["my-pod"] # 限制名称
verbs: ["get"]

# 规则4: 非资源 URL
- nonResourceURLs: ["/healthz", "/metrics"]
verbs: ["get"]

准入控制 (Admission Control)

准入流程

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
┌──────────────────────────────────────────────────────────────────────────────┐
│ 准入控制流程 │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Mutating 阶段 (修改) │ │
│ │ │ │
│ │ 1. NamespaceLifecycle - 检查命名空间存在 │ │
│ │ 2. LimitRanger - 设置默认值/限制 │ │
│ │ 3. ServiceAccount - 设置 SA │ │
│ │ 4. DefaultStorageClass - 添加默认存储类 │ │
│ │ 5. DefaultTolerationSeconds - 默认容忍时间 │ │
│ │ 6. MutatingWebhook - 调用自定义变异 webhook │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Validating 阶段 (验证) │ │
│ │ │ │
│ │ 1. ResourceQuota - 验证资源配额 │ │
│ │ 2. PodSecurity - 验证 Pod 安全标准 │ │
│ │ 3. LimitRanger - 验证资源限制 │ │
│ │ 4. ValidatingWebhook - 调用自定义验证 webhook │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 请求被持久化到 etcd │
└──────────────────────────────────────────────────────────────────────────────┘

常用准入插件

插件 类型 说明
NamespaceLifecycle Validating 防止创建已终止的命名空间
LimitRanger Mutating 设置默认值/资源限制
ServiceAccount Mutating 自动配置 ServiceAccount
DefaultStorageClass Mutating 添加默认存储类
ResourceQuota Validating 验证资源配额
PodSecurity Validating 验证 Pod 安全标准
NodeRestriction Validating 限制 kubelet 的权限

AdmissionReview 请求格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// admission.k8s.io/v1
type AdmissionReview struct {
TypeMeta
Request *AdmissionRequest
Response *AdmissionResponse
}

type AdmissionRequest struct {
UID types.UID
Kind GroupVersionKind
Resource GroupVersionResource
Subresource string
RequestKind *GroupVersionKind
Name string
Namespace string
Operation Operation
UserInfo authenticationv1.UserInfo
Object runtime.Object
OldObject runtime.Object
DryRun *bool
}

网络策略 (NetworkPolicy)

策略类型

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
# 入口策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress
spec:
podSelector:
matchLabels:
app: my-app
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 80

# 出口策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-egress
spec:
podSelector:
matchLabels:
app: my-app
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
name: database
ports:
- protocol: TCP
port: 5432
- to: # 允许 DNS
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53

Pod 隔离模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌──────────────────────────────────────────────────────────────────────────────┐
│ Pod 隔离模式 │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 无 NetworkPolicy │ │
│ │ │ │
│ │ Pod 可以接收/发送任意流量 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 有 Ingress NetworkPolicy │ │
│ │ │ │
│ │ 仅允许符合策略的入站流量 │ │
│ │ 默认拒绝其他入站流量 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 有 Egress NetworkPolicy │ │
│ │ │ │
│ │ 仅允许符合策略的出站流量 │ │
│ │ 默认拒绝其他出站流量 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘

Pod 安全

PodSecurityContext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
kind: Pod
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
supplementalGroups: [1000]
containers:
- name: app
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE

SecurityContext 字段

字段 说明
runAsUser 运行用户 ID
runAsGroup 运行组 ID
runAsNonRoot 必须以非 root 运行
fsGroup 文件系统组
supplementalGroups 补充组
allowPrivilegeEscalation 禁止权限提升
readOnlyRootFilesystem 只读根文件系统
capabilities Linux 能力

Secret 管理

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
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque # 通用类型
data:
username: <base64>
password: <base64>
---
# TLS 证书
apiVersion: v1
kind: Secret
metadata:
name: my-tls-secret
type: kubernetes.io/tls
data:
tls.crt: <base64>
tls.key: <base64>
---
# Docker 配置
apiVersion: v1
kind: Secret
metadata:
name: my-registry-secret
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: <base64>

外部 Secret 管理

方案 说明
HashiCorp Vault 通过 CSI Provider 集成
AWS Secrets Manager 通过 External Secrets Operator
GCP Secret Manager 通过 External Secrets Operator
Azure Key Vault 通过 CSI Provider

审计日志 (Audit)

审计策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# 1. 不记录只读请求
- level: None
verbs: ["get", "list", "watch"]
resources:
- group: ""
resources: ["pods"]

# 2. 记录元数据级别的请求
- level: Metadata
resources:
- group: ""
resources: ["secrets", "configmaps"]

# 3. 记录请求和响应体
- level: RequestResponse
resources:
- group: "networking.k8s.io"
resources: ["ingresses"]

# 4. 记录所有其他请求
- level: Request

审计阶段

阶段 说明
RequestReceived 收到请求时
ResponseStarted 响应开始发送时
ResponseComplete 响应发送完成
Panic 发生 panic 时

关键代码路径

文件 说明
staging/src/k8s.io/apiserver/pkg/authentication/ 认证
staging/src/k8s.io/apiserver/pkg/authorization/ 授权
staging/src/k8s.io/apiserver/pkg/admission/ 准入控制
plugin/pkg/auth/authorizer/rbac/ RBAC 授权器
pkg/kubelet/certificate/ Kubelet 证书轮换
pkg/api/podsecurity/ Pod 安全策略

面试题

基础题

1. Kubernetes 有哪些认证方式?

参考答案:

  • X509 客户端证书:最常用
  • Bearer Token:ServiceAccount JWT
  • Bootstrap Token:集群引导
  • OIDC:OpenID Connect
  • Webhook:外部认证服务
  • Anonymous:匿名访问

2. ServiceAccount 的工作原理是什么?

参考答案:

  1. 创建 ServiceAccount 时自动创建对应的 Token Secret
  2. Token 是一个 JWT,包含 namespace、name 等信息
  3. Pod 启动时 Token 自动挂载到 /var/run/secrets/kubernetes.io/serviceaccount/
  4. kubelet 通过 ServiceAccount 访问 API Server

3. RBAC 的核心概念有哪些?

参考答案:

  • Role:命名空间级别的权限
  • ClusterRole:集群级别的权限
  • RoleBinding:将 Role 绑定到主体
  • ClusterRoleBinding:将 ClusterRole 绑定到主体
  • Subject:User、Group、ServiceAccount

中级题

4. 准入控制的两个阶段是什么?顺序如何?

参考答案:

阶段 顺序 作用
Mutating 修改请求内容
Validating 验证请求有效性

5. 如何限制 Pod 的权限?

参考答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 1. SecurityContext
spec:
securityContext:
runAsNonRoot: true
readOnlyRootFilesystem: true

# 2. PodSecurity (PSP 替代)
spec:
securityContext:
seccompProfile:
type: RuntimeDefault

# 3. NetworkPolicy
spec:
policyTypes:
- Ingress
- Egress

6. Secret 如何保证安全?

参考答案:

  1. 静态加密:etcd 存储加密
  2. RBAC:限制 Secret 访问权限
  3. Secret 轮换:定期更新
  4. 外部密钥管理:Vault、AWS Secrets Manager
  5. 禁止明文:使用 sealed-secrets

7. 如何配置审计日志?

参考答案:

1
2
3
4
5
6
# kube-apiserver 配置
--audit-policy-file=/etc/kubernetes/audit-policy.yaml
--audit-log-path=/var/log/kubernetes/audit.log
--audit-log-maxage=30
--audit-log-maxbackup=10
--audit-log-maxsize=100

高级题

8. AdmissionWebhook 的工作原理是什么?

参考答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 1. kube-apiserver 调用 webhook
admissionReview := &admission.AdmissionReview{
Request: &admission.AdmissionRequest{
UID: types.UID(uuid.NewUUID()),
Kind: gvk,
Resource: gvr,
Operation: admission.Operation(op),
Object: runtime.RawExtension{Raw: body},
},
}

// 2. Webhook 服务返回修改后的对象
admissionReview.Response = &admission.AdmissionResponse{
UID: admissionReview.Request.UID,
Allowed: true,
Patch: patchBytes, // JSON Patch
}

9. 如何实现基于角色的权限委托?

参考答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# ClusterRole 定义权限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: namespace-reader
rules:
- apiGroups: [""]
resources: ["*"]
verbs: ["get", "list", "watch"]

---
# RoleBinding 委托给其他用户
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: delegate-to-user
namespace: target-ns
subjects:
- kind: User
name: other-user
roleRef:
kind: ClusterRole
name: namespace-reader

10. Kubelet 证书轮换是如何工作的?

参考答案:

  1. kubelet 启动时检查证书是否即将过期
  2. 如果即将过期,向 API Server 请求新证书
  3. API Server 使用 CSR (CertificateSigningRequest) 审批
  4. kubelet 获取签名后的证书
  5. 证书保存到本地,更新 kubeconfig

场景题

11. 如何实现多租户隔离?

参考答案:

  1. 命名空间隔离
  2. RBAC 权限控制
  3. ResourceQuota/LimitRange
  4. NetworkPolicy 网络隔离
  5. PodSecurity 安全策略
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
# 完整的多租户配置
---
apiVersion: v1
kind: Namespace
metadata:
name: tenant-a
labels:
tenant: a
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: tenant-a
spec:
podSelector: {}
policyTypes: [Ingress, Egress]
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: tenant-a-quota
namespace: tenant-a
spec:
hard:
requests.cpu: "10"
requests.memory: 20Gi
persistentvolumeclaims: "10"

12. 如何排查 RBAC 权限问题?

参考答案:

1
2
3
4
5
6
7
8
9
10
11
12
# 1. 检查用户身份
kubectl auth whoami

# 2. 检查权限
kubectl auth can-i get pods --as=<user>

# 3. 查看绑定的角色
kubectl get rolebinding -A | grep <user>
kubectl get clusterrolebinding | grep <user>

# 4. 查看详细绑定
kubectl describe rolebinding <name> -n <ns>

13. 如何保护集群安全?

参考答案:

  1. API Server 安全

    • 启用 RBAC
    • 禁用匿名访问
    • 启用审计日志
  2. 传输加密

    • TLS 证书轮换
    • etcd 加密
  3. 网络安全

    • 网络策略隔离
    • kubeconfig 权限控制
  4. 运行时安全

    • Pod 安全策略
    • 限制容器权限
  5. 密钥管理

    • 使用 Vault 等外部密钥管理
    • 定期轮换密钥