1 机制说明
Kubernetes 的安全机制本质是"身份认证 → 权限控制 → 资源隔离 → 网络隔离 → 数据加密"五层防护体系,保证谁能访问、能做什么、在哪访问、数据是否安全。
Kubernetes安全机制主要包括五个方面:
1️⃣ Authentication :身份认证(证书、Token、OIDC)
2️⃣ Authorization :RBAC权限控制
3️⃣ Admission Controller :准入控制
4️⃣ NetworkPolicy :Pod 网络隔离
5️⃣ Encryption:TLS通信和etcd数据加密
2 安全机制流程
2.1 流程图
bash
# 当客户端(如 kubectl)向 API Server 请求资源时
请求:连接认证 # 通过证书ca.crt连接
↓
认证:身份认证 # 解决的问题:谁可以访问 API Server
↓
鉴权:权限认证 # 解决的问题:认证通过之后,能干什么
↓
准入控制 # 解决的问题:请求是否合理
↓
资源写入 etcd
2.2 Prometheus 访问举例
无论是k8s内部的服务访问还是外部的服务访问,都需要进行以上过程
- 内部服务访问:连接认证(ca.crt)和身份认证(Token)自动生成,权限认证(RBAC)需要配置
- 外部服务访问:连接认证(ca.crt)需要复制,身份认证(Token)需要生成,权限认证(RBAC)需要配置
2.2.1 外部 Prometheus(集群外)
1️⃣ 拷贝k8s的ca.crt 到Prometheus服务器上
bash
scp /etc/kubernetes/pki/ca.crt root@master01:/etc/prometheus
2️⃣ 获取 Token
bash
SECRET_NAME=$(kubectl -n monitoring get sa/prometheus-sa -o jsonpath='{.secrets[0].name}')
TOKEN=$(kubectl -n monitoring get secret $SECRET_NAME -o jsonpath='{.data.token}' | base64 --decode)
echo $TOKEN > /etc/prometheus/k8s-token
3️⃣ Prometheus 配置使用 Token
bash
vim /etc/prometheus/prometheus.yml
-----------------------------------------------------------------------------------------
scrape_configs:
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- api_server: https://<K8S_API_SERVER>:6443
role: pod
bearer_token_file: /etc/prometheus/k8s-token # 这里引用 token 文件
tls_config:
ca_file: /etc/prometheus/ca.crt
insecure_skip_verify: false
4️⃣ 创建 ServiceAccount
bash
kubectl -n monitoring create serviceaccount prometheus-sa
5️⃣ 创建 RBAC 权限并绑定 SA(只读访问 Pods/Services/Endpoints)
bash
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus-readonly
rules:
- apiGroups: [""]
resources: ["pods","services","endpoints"]
verbs: ["get","list","watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus-sa-binding
subjects:
- kind: ServiceAccount
name: prometheus-sa
namespace: monitoring
roleRef:
kind: ClusterRole
name: prometheus-readonly
apiGroup: rbac.authorization.k8s.io
EOF
✅ 说明:Prometheus 启动后会用 Token 向 API Server 认证身份,然后 RBAC 判断权限
2.2.2 内部 Prometheus(Pod 内)
- Kubernetes 会自动挂载 Token 到 Pod:
bash
/var/run/secrets/kubernetes.io/serviceaccount/token
- Prometheus 配置使用 ConfigMap 进行管理,只需指向挂载路径:
bash
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: monitoring
data:
prometheus.yml: |
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: false
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: (.+)
replacement: $1
-----------------------------------------------------------------------------------------
# 在创建 Prometheus 的 Deployment中挂载 ConfigMap
volumeMounts:
- name: prometheus-config
mountPath: /etc/prometheus/prometheus.yml
subPath: prometheus.yml
volumes:
- name: prometheus-config
configMap:
name: prometheus-config
无需手动创建或拷贝 Token,RBAC 权限认证同上。
3 身份认证(Authentication)
🔑 解决的问题:谁可以访问 API Server
Kubernetes 所有操作都必须经过 API Server,所以第一步是确认访问者身份。
3.1 支持的认证方式
- HTTP Token 认证:在 HTTP Header 携带一个难以仿冒的长 Token;API Server 维护 Token 与用户名的映射。
- HTTP Basic 认证 :用户名:密码 使用 Base64 编码后放入 Header 的
Authorization字段。 - HTTPS 证书认证(最严格) :基于 CA 根证书签名(CA = ca.crt + ca.key)的双向 TLS 认证。
注:Token 与 Basic 仅支持服务端对客户端 的单向 认证;HTTPS 证书可实现双向认证。
3.2 ServiceAccount(SA)
用于 Pod 中容器访问 API Server 的身份。由于 Pod 动态创建/销毁,为每个 Pod 手动发证书不可行,故使用 Service Account 解决 Pod 到 API Server 的认证。
ServiceAccount 中包含三部分:
- Token:由 API Server 私钥签名的 Token,用于服务端认证来访主体;
- ca.crt:CA 根证书,供客户端验证 API Server 的证书;
- namespace:该 service-account-token 的命名空间作用域。
默认每个命名空间都有一个 SA;若创建 Pod 时未指定 SA,将使用所属命名空间的 default SA。创建 Pod 后,系统会自动将以下内容挂载到容器:
bash
/var/run/secrets/kubernetes.io/serviceaccount/
├─ ca.crt # 连接认证
├─ namespace
└─ token # 身份认证
# 查看 Service Account
kubectl get sa
4 权限控制(Authorization)
🔐 解决的问题:认证通过之后,能干什么
Kubernetes使用 RBAC权限模型。
| 资源 | 作用 |
|---|---|
| Role | namespace级权限 |
| ClusterRole | 集群级权限(跨namespace) |
| RoleBinding | 绑定Role |
| ClusterRoleBinding | 绑定ClusterRole |
4.1 什么时候需要 RBAC 认证
pod需要对其他pod进行增删改查的操作时,才需要设置权限
例如:
Prometheus 监控k8s时,需要查看权限,所以需要进行RBAC的权限认证
4.2 RBAC 认证逻辑
bash
Role/ClusterRole # 设置权限
│
├───── RoleBinding/ClusterRoleBinding # 将权限绑定到SA账户
↓
ServiceAccount # 拿到权限
↓
用户 / Pod # 用 SA 账户进行访问
↓
API Server
↓
RBAC判断
↓
允许 or 拒绝
5 准入控制(Admission Control)
🔐 解决的问题:请求是否合理
认证 + 授权之后,还会经过 Admission Controller
举个例子:
bash
# 当创建一个pod时,当返回
// 请求合理,允许创建
pod/nginx-ok created
// 请求不合理,拒绝创建
Error from server (Forbidden):
pod nginx-bad rejected: must specify resources limits
6 网络安全(Network Security)
🌐 解决的问题:Pod之间是否可以通信
默认:
bash
Pod ↔ Pod 全部互通
6.1 安全方案
NetworkPolicy------限制 Pod 网络访问。
示例逻辑:
bash
# 只允许带有t=t1 标签的pod/namespace 访问 带有t=t2 标签的pod/namespace,禁止其他的访问
t=t1 ───────▶ t=t2 ✅允许
t=t2 ───────▶ t=t1 ✅不受影响
其他 ───────▶ t=t1 ✅不受影响
t=t1 ───────▶ 其他 ✅不受影响
t=t2 ───────▶ 其他 ✅不受影响
其他 ───────▶ t=t2 ❌拒绝
必须配合网络插件:(Flannel不支持)
- Calico
6.2 实例演示
bash
# 实现结果(注:使用标签匹配,namespace也同理,标签自定义,需要以 键:值 的方式)
frontend (t=t1)
│允许
▼
backend (access=backend)
▲
│允许
prometheus (t=t1)
# 关键配置
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-monitor-and-frontend
spec:
podSelector:
matchLabels:
role: backend # 选择后端Pod
policyTypes:
- Ingress # 只是语法规则,不是Ingress,代表的是 接受来自谁的访问
# 如果是egress,代表的是 只能访问到谁
ingress:
- from:
- podSelector:
matchLabels:
t: t1 # 允许访问来源
-----------------------------------------------------------------------------------------
# 如果是 egress,代表 role: backend 只能访问到 t: t1
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-monitor-and-frontend
spec:
podSelector:
matchLabels:
role: backend # 选择后端Pod
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
t: t1
7 数据安全(Encryption)
🔒 解决的问题:数据是否加密
Kubernetes主要有两类数据加密:API 通信加密 和 etcd数据加密
7.1 API 通信加密
所有组件通信使用:
bash
TLS证书
例如:
bash
kubectl → apiserver
kubelet → apiserver
controller → apiserver
7.2 etcd数据加密
7.2.1 概念
由于 K8s 的核心存储 etcd 默认明文存储 ,会导致存储在etcd 中的 Secrets 等敏感信息可能被访问,所以需要开启 EncryptionConfiguration 对 etcd 中的 Secrets 进行加密
7.2.2 配置方式
bash
vim encryption-config.yaml
-----------------------------------------------------------------------------------------
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-key>
- identity: {}
=========================================================================================
# 修改 kube-apiserver 启动参数, kube-apiserver 会自动重启,让配置生效
--encryption-provider-config=/etc/kubernetes/encryption-config.yaml
# secret: <base64-encoded-key> 的获取方式
head -c 32 /dev/urandom | base64
// 输出: y1ZpM3+4B1C5x1j2k3l4m5n6o7p8q9r0s1t2u3v4w5x=