主题
安全加固
业务场景
云咖啡公司的业务发展迅速,系统已经稳定运行了一段时间。随着公司规模扩大,安全团队提出了以下要求:
- 不同部门的员工需要不同的操作权限
- 各个服务之间需要网络隔离
- 容器运行需要遵循安全规范
- 敏感数据需要加密存储
作为运维工程师,你需要为云咖啡的 K8S 集群实施安全加固。
学习目标
完成本阶段后,你将掌握:
- RBAC 权限管理:控制谁可以对哪些资源执行什么操作
- NetworkPolicy:限制 Pod 之间的网络通信
- Pod 安全标准:确保容器以安全的方式运行
- Secret 加密:保护敏感数据的安全
前置知识
本阶段需要以下基础知识:
- Kubernetes 核心概念(Pod、Deployment、Service)
- 基本的 K8S 操作经验
- 了解认证和授权的基本概念
提示:如果你已经掌握这些知识,可以直接开始实战。
第一部分:RBAC 权限管理
什么是 RBAC
RBAC(Role-Based Access Control,基于角色的访问控制)是 K8S 中控制权限的核心机制。它通过以下概念实现权限管理:
- Role/ClusterRole:定义权限规则(能做什么)
- ServiceAccount:代表一个身份(是谁)
- RoleBinding/ClusterRoleBinding:将角色绑定到身份(谁能做什么)
场景:为开发团队创建只读权限
云咖啡公司的开发团队需要查看生产环境的资源状态,但不能修改。
步骤1:创建命名空间和测试资源
首先,创建 rbac-namespace.yaml 文件:
bash
cat > rbac-namespace.yaml << 'EOF'
# RBAC 演示:命名空间和测试资源
# 用途:创建 cloud-coffee-prod 命名空间和示例 Deployment
apiVersion: v1
kind: Namespace
metadata:
name: cloud-coffee-prod
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: coffee-shop
namespace: cloud-coffee-prod
spec:
replicas: 2
selector:
matchLabels:
app: coffee-shop
template:
metadata:
labels:
app: coffee-shop
spec:
containers:
- name: coffee-shop
image: nginx:alpine
ports:
- containerPort: 80
EOF应用配置:
bash
kubectl apply -f rbac-namespace.yaml步骤2:创建 ServiceAccount
创建 rbac-serviceaccount.yaml 文件:
bash
cat > rbac-serviceaccount.yaml << 'EOF'
# RBAC 演示:ServiceAccount
# 用途:创建 developer 服务账号
apiVersion: v1
kind: ServiceAccount
metadata:
name: developer
namespace: cloud-coffee-prod
EOF应用配置:
bash
kubectl apply -f rbac-serviceaccount.yaml步骤3:创建 Role(命名空间级别权限)
创建 rbac-role.yaml 文件:
bash
cat > rbac-role.yaml << 'EOF'
# RBAC 演示:Role(命名空间级别权限)
# 用途:定义 developer 的只读权限
# 权限说明:
# - apiGroups:资源所属的 API 组
# - resources:资源类型
# - verbs:允许的操作(get 获取单个资源,list 列出资源,watch 监听变化)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: developer-read-only
namespace: cloud-coffee-prod
rules:
- apiGroups: [""]
resources: ["pods", "deployments", "services", "configmaps", "secrets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch"]
EOF应用配置:
bash
kubectl apply -f rbac-role.yaml步骤4:创建 RoleBinding
创建 rbac-rolebinding.yaml 文件:
bash
cat > rbac-rolebinding.yaml << 'EOF'
# RBAC 演示:RoleBinding
# 用途:将 developer-read-only 角色绑定到 developer 服务账号
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: developer-read-only-binding
namespace: cloud-coffee-prod
subjects:
- kind: ServiceAccount
name: developer
namespace: cloud-coffee-prod
roleRef:
kind: Role
name: developer-read-only
apiGroup: rbac.authorization.k8s.io
EOF应用配置:
bash
kubectl apply -f rbac-rolebinding.yaml步骤5:验证权限
bash
# 使用 developer 身份测试
kubectl auth can-i list pods -n cloud-coffee-prod --as=system:serviceaccount:cloud-coffee-prod:developer
# 输出: yes
kubectl auth can-i delete pods -n cloud-coffee-prod --as=system:serviceaccount:cloud-coffee-prod:developer
# 输出: no📌 关于
--as参数的解释
--as用于模拟指定用户或服务账号执行命令,常用于 RBAC 权限测试。语法:
--as=<用户名或服务账号>使用场景:
- 测试 RBAC 规则是否正确配置
- 验证用户是否有指定权限
- 排查权限问题
常用命令:
bash# 检查当前用户权限 kubectl auth can-i list pods # 模拟服务账号检查权限 kubectl auth can-i create deployments \ --as=system:serviceaccount:myns:mysa \ -n myns # 模拟用户获取资源 kubectl get pods --as=developer -n myns提示:需要有
impersonate权限才能使用--as
常用角色模板
只读权限:
yaml
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps"]
verbs: ["get", "list", "watch"]开发权限(可部署应用):
yaml
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "update", "delete"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "delete"]管理员权限:
yaml
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]第二部分:NetworkPolicy 网络策略
什么是 NetworkPolicy
NetworkPolicy 是 K8S 中控制 Pod 之间网络通信的机制。默认情况下,所有 Pod 可以相互通信,NetworkPolicy 可以限制这种通信。
注意:NetworkPolicy 需要网络插件支持(如 Calico、Cilium、Weave),Flannel 默认不支持。
场景:隔离云咖啡各服务
云咖啡系统包含:
- 前端服务(coffee-frontend)
- 后端 API(coffee-api)
- 数据库(coffee-db)
安全要求:
- 前端只能访问 API
- API 只能访问数据库
- 数据库只能被 API 访问
步骤1:部署测试应用
创建 networkpolicy-apps.yaml 文件:
bash
cat > networkpolicy-apps.yaml << 'EOF'
# NetworkPolicy 演示:测试应用部署
# 用途:部署前端、后端和数据库三个服务用于测试网络隔离
# 架构:frontend -> api -> db
apiVersion: v1
kind: Namespace
metadata:
name: cloud-coffee
labels:
name: cloud-coffee
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: coffee-frontend
namespace: cloud-coffee
spec:
replicas: 2
selector:
matchLabels:
app: coffee-frontend
template:
metadata:
labels:
app: coffee-frontend
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: coffee-api
namespace: cloud-coffee
spec:
replicas: 2
selector:
matchLabels:
app: coffee-api
template:
metadata:
labels:
app: coffee-api
spec:
containers:
- name: api
image: nginx:alpine
ports:
- containerPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: coffee-db
namespace: cloud-coffee
spec:
replicas: 1
selector:
matchLabels:
app: coffee-db
template:
metadata:
labels:
app: coffee-db
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "root123"
ports:
- containerPort: 3306
EOF应用配置:
bash
kubectl apply -f networkpolicy-apps.yaml步骤2:创建默认拒绝策略
创建 networkpolicy-default-deny.yaml 文件:
bash
cat > networkpolicy-default-deny.yaml << 'EOF'
# NetworkPolicy 演示:默认拒绝策略
# 用途:拒绝所有入站和出站流量,作为安全基线
# 注意:此策略会阻断所有 Pod 的通信,需要配合其他策略使用
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: cloud-coffee
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
EOF应用配置:
bash
kubectl apply -f networkpolicy-default-deny.yaml说明:此策略拒绝所有入站和出站流量,作为安全基线。
步骤3:允许前端访问 API
创建 networkpolicy-api.yaml 文件:
bash
cat > networkpolicy-api.yaml << 'EOF'
# NetworkPolicy 演示:API 服务策略
# 用途:
# - 允许前端服务访问 API(入站)
# - 允许 API 访问数据库(出站)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: coffee-api-policy
namespace: cloud-coffee
spec:
podSelector:
matchLabels:
app: coffee-api
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: coffee-frontend
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: coffee-db
ports:
- protocol: TCP
port: 3306
EOF应用配置:
bash
kubectl apply -f networkpolicy-api.yaml步骤4:允许 API 访问数据库
创建 networkpolicy-db.yaml 文件:
bash
cat > networkpolicy-db.yaml << 'EOF'
# NetworkPolicy 演示:数据库策略
# 用途:只允许 API 服务访问数据库
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: coffee-db-policy
namespace: cloud-coffee
spec:
podSelector:
matchLabels:
app: coffee-db
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: coffee-api
ports:
- protocol: TCP
port: 3306
EOF应用配置:
bash
kubectl apply -f networkpolicy-db.yaml步骤5:允许前端接受外部流量
创建 networkpolicy-frontend.yaml 文件:
bash
cat > networkpolicy-frontend.yaml << 'EOF'
# NetworkPolicy 演示:前端服务策略
# 用途:
# - 允许所有外部流量访问前端(入站)
# - 允许前端访问 API(出站)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: coffee-frontend-policy
namespace: cloud-coffee
spec:
podSelector:
matchLabels:
app: coffee-frontend
policyTypes:
- Ingress
- Egress
ingress:
- from: [] # 允许所有入站流量
ports:
- protocol: TCP
port: 80
egress:
- to:
- podSelector:
matchLabels:
app: coffee-api
ports:
- protocol: TCP
port: 8080
EOF应用配置:
bash
kubectl apply -f networkpolicy-frontend.yaml网络策略验证
bash
# 测试连接(使用临时 Pod)
# 测试前端是否可以访问 API(应该成功)
kubectl run test --image=busybox -n cloud-coffee --rm -it -- wget -qO- coffee-api:8080
# 测试前端是否可以直接访问数据库(应该失败)
kubectl run test --image=busybox -n cloud-coffee --rm -it -- wget -qO- coffee-db:3306第三部分:Pod 安全标准
什么是 Pod 安全标准
Pod 安全标准定义了不同安全级别的容器运行要求:
- Privileged(特权):不受限制,可能存在安全风险
- Baseline(基线):禁止明显的特权提升
- Restricted(受限):严格限制,遵循最佳实践
场景:为云咖啡配置安全策略
首先,创建启用 Pod 安全标准的命名空间:
bash
cat > pod-security-namespace.yaml << 'EOF'
# Pod 安全标准演示:安全命名空间
# 用途:创建启用 Restricted 安全策略的命名空间
# 标签说明:
# - enforce:强制执行,违反策略的 Pod 会被拒绝
# - audit:记录审计日志,不阻止
# - warn:发出警告,不阻止
apiVersion: v1
kind: Namespace
metadata:
name: cloud-coffee-secure
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
EOF应用配置:
bash
kubectl apply -f pod-security-namespace.yaml安全的 Pod 配置示例
创建符合 Restricted 标准的 Deployment:
bash
cat > pod-security-deployment.yaml << 'EOF'
# Pod 安全标准演示:安全 Deployment 配置
# 用途:展示符合 Restricted 标准的 Pod 安全配置
# 安全特性:
# - 非 root 用户运行
# - 只读根文件系统
# - 禁止权限提升
# - 移除所有 Linux capabilities
# - 使用默认 seccomp 配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
namespace: cloud-coffee-secure
spec:
replicas: 1
selector:
matchLabels:
app: secure-app
template:
metadata:
labels:
app: secure-app
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: nginx:alpine
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
ports:
- containerPort: 80
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /var/cache/nginx
- name: run
mountPath: /var/run
volumes:
- name: tmp
emptyDir: {}
- name: cache
emptyDir: {}
- name: run
emptyDir: {}
EOF应用配置:
bash
kubectl apply -f pod-security-deployment.yaml安全配置说明:
| 配置项 | 作用 |
|---|---|
runAsNonRoot: true | 禁止以 root 用户运行 |
runAsUser: 1000 | 指定非特权用户 ID |
readOnlyRootFilesystem: true | 根文件系统只读,防止篡改 |
allowPrivilegeEscalation: false | 禁止权限提升 |
capabilities.drop: ALL | 移除所有 Linux 能力 |
seccompProfile.type: RuntimeDefault | 使用默认的系统调用过滤 |
第四部分:Secret 加密存储
为什么需要加密 Secret
默认情况下,Secret 存储在 etcd 中是明文的。攻击者如果获得 etcd 访问权限,可以读取所有敏感数据。
⚠️ K3s 环境说明
K3s 使用 SQLite 而不是 etcd 作为默认存储后端,且已经内置了加密功能。本部分的 etcd 加密配置主要适用于标准 Kubernetes 集群(使用 kubeadm 部署)。
K3s 用户:可以了解加密原理,但不需要执行以下配置步骤。
场景:启用 Secret 加密(标准 K8s 集群)
步骤1:创建加密配置
创建 encryption-config.yaml 文件:
bash
# 生成 32 字节随机密钥
ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)
# 创建加密配置文件
cat > encryption-config.yaml << EOF
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: ${ENCRYPTION_KEY}
- identity: {}
EOF步骤2:配置 kube-apiserver
⚠️ 生产环境注意事项
- 此操作需要访问控制平面节点
- 修改 kube-apiserver 配置需要重启服务
- 建议在维护窗口执行
- 执行前请备份现有配置
将 encryption-config.yaml 复制到控制平面节点:
bash
# 复制到 API Server 配置目录(在所有控制平面节点执行)
sudo cp encryption-config.yaml /etc/kubernetes/encryption-config.yaml
sudo chmod 600 /etc/kubernetes/encryption-config.yaml编辑 kube-apiserver 静态 Pod 配置:
bash
# 编辑 kube-apiserver 配置
sudo vim /etc/kubernetes/manifests/kube-apiserver.yaml在 command 部分添加以下参数:
yaml
- --encryption-provider-config=/etc/kubernetes/encryption-config.yaml添加卷挂载:
yaml
volumeMounts:
- name: encryption-config
mountPath: /etc/kubernetes/encryption-config.yaml
readOnly: true添加卷定义:
yaml
volumes:
- name: encryption-config
hostPath:
path: /etc/kubernetes/encryption-config.yaml
type: File保存后,kube-apiserver 会自动重启。
步骤3:加密现有 Secret
bash
# 创建测试 Secret
kubectl create secret generic db-password --from-literal=password=secret123 -n cloud-coffee
# 加密所有 Secret(重新写入触发加密)
kubectl get secrets --all-namespaces -o json | kubectl replace -f -步骤4:验证加密
bash
# 直接读取 etcd(应该看到加密数据)
ETCDCTL_API=3 etcdctl get /registry/secrets/cloud-coffee/db-password \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key实战任务
完成以下任务巩固所学知识:
创建开发人员角色
- 创建一个 ServiceAccount
dev-user - 创建 Role 允许查看和创建 Deployment、Pod、Service
- 验证权限是否正确
- 创建一个 ServiceAccount
配置网络隔离
- 部署三个应用:web、api、db
- 配置 NetworkPolicy 实现:web->api->db 的单向访问
- 验证隔离效果
安全加固 Pod
- 创建一个符合 Restricted 标准的 Pod
- 验证安全配置是否生效
课程总结
本阶段学习了 K8S 安全加固的核心技能:
| 内容 | 作用 | 生产环境重要性 |
|---|---|---|
| RBAC | 控制访问权限 | 高 |
| NetworkPolicy | 网络隔离 | 中高 |
| Pod 安全标准 | 容器安全 | 高 |
| Secret 加密 | 数据保护 | 高 |
下一步学习:第九阶段:生产运维