Repository Reading Site
安全、CRD 与高级运维
| 级别 | 含义 | 允许什么 | |------|------|---------| | **Privileged** | 完全不限制 | 一切 | | **Baseline** | 最低限度安全 | 禁止特权容器、hostNetwork 等 | | **Restricted** | 最严格 | 必须 runAsNonRoot、drop ALL capa
安全、CRD 与高级运维
Pod Security Standards — 集群级安全准入
三个安全级别
| 级别 | 含义 | 允许什么 |
|---|---|---|
| Privileged | 完全不限制 | 一切 |
| Baseline | 最低限度安全 | 禁止特权容器、hostNetwork 等 |
| Restricted | 最严格 | 必须 runAsNonRoot、drop ALL capabilities、seccomp |
三种执行模式
| 模式 | 效果 |
|---|---|
enforce |
违规的 Pod 直接拒绝创建 |
warn |
允许创建,但在 kubectl 输出警告 |
audit |
允许创建,记录到审计日志 |
实验验证
# 给 prod 空间设置 restricted 级别
kubectl label namespace prod \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/warn=restricted \
pod-security.kubernetes.io/audit=restricted
测试特权容器:
spec:
containers:
- name: hacker
securityContext:
privileged: true # ← 这就足以被拒绝
结果:
Error from server (Forbidden): violates PodSecurity "restricted:latest":
- privileged (must not set privileged=true)
- allowPrivilegeEscalation != false
- unrestricted capabilities (must drop=["ALL"])
- runAsNonRoot != true
- seccompProfile (must set RuntimeDefault or Localhost)
合规容器模板:
spec:
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: app
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsUser: 1000
→ 创建成功,Running
面试重点
Q: PSS 和已废弃的 PodSecurityPolicy (PSP) 的区别?
- PSP 是独立资源,配置复杂,需要 RBAC 绑定,K8s 1.25 已删除
- PSS 通过 namespace label 配置,简单直观
- PSS 是 K8s 内置的准入控制器(PodSecurity Admission)
CRD — 扩展 K8s API
什么是 CRD?
K8s 内置了 Pod、Deployment、Service 等资源类型。CRD 让你定义自己的资源类型,像内置资源一样用 kubectl 管理。
实验:创建 Database 资源
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: databases.lab.example.com
spec:
group: lab.example.com # API 组
versions:
- name: v1
served: true # 是否通过 API 提供
storage: true # 是否用于存储
schema:
openAPIV3Schema: # 字段校验
type: object
properties:
spec:
type: object
properties:
engine:
type: string
enum: ["postgres", "mysql", "redis"]
replicas:
type: integer
minimum: 1
maximum: 5
storage:
type: string
additionalPrinterColumns: # kubectl get 时显示的列
- name: Engine
type: string
jsonPath: .spec.engine
- name: Replicas
type: integer
jsonPath: .spec.replicas
scope: Namespaced
names:
plural: databases
singular: database
kind: Database
shortNames: ["db"] # kubectl get db
创建和使用
apiVersion: lab.example.com/v1
kind: Database
metadata:
name: my-postgres
namespace: dev
spec:
engine: postgres
replicas: 3
storage: 10Gi
$ kubectl -n dev get db
NAME ENGINE REPLICAS STORAGE
my-postgres postgres 3 10Gi
my-redis redis 1 1Gi
CRD 只是"数据存储"
CRD 本身只是把自定义数据存在 etcd 中。要让它产生实际效果(比如真的创建 PostgreSQL 实例),需要写 Controller(控制器),也就是 Operator 模式。
Operator 模式
CRD(定义资源类型)+ Controller(监听并响应资源变化)= Operator
用户创建 Database CR
→ Controller Watch 到
→ Controller 创建 StatefulSet + Service + PVC
→ Controller 持续监控,确保数据库健康
→ 用户修改 replicas: 5
→ Controller 自动扩容
知名 Operator 举例:
cert-manager— 自动申请/续期 TLS 证书prometheus-operator— 管理 Prometheus 实例(我们已经在用)external-secrets— 从 Vault/AWS 同步 Secretstrimzi— 管理 Kafka 集群
面试题
Q: 什么时候用 Operator vs Helm?
- Helm:安装时配置一次,之后基本不变的应用
- Operator:需要运行时管理的有状态应用(备份恢复、自动修复、滚动升级)
Q: 如何开发自己的 Operator?
- kubebuilder — Go 语言框架,CNCF 推荐
- Operator SDK — Red Hat 的框架,支持 Go/Ansible/Helm
- Metacontroller — 用 Webhook 实现,任何语言
etcd 备份与恢复
备份
ETCDCTL_API=3 etcdctl snapshot save /tmp/etcd-backup.db \
--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
验证结果:
+----------+----------+------------+------------+
| HASH | REVISION | TOTAL KEYS | TOTAL SIZE |
+----------+----------+------------+------------+
| 2a14d6e3 | 16251 | 3087 | 31 MB |
+----------+----------+------------+------------+
恢复流程(灾难恢复)
# 1. 停止 API Server
mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/
# 2. 恢复 etcd 数据
ETCDCTL_API=3 etcdctl snapshot restore /tmp/etcd-backup.db \
--data-dir=/var/lib/etcd-restored
# 3. 修改 etcd static pod 使用新数据目录
# 编辑 /etc/kubernetes/manifests/etcd.yaml 中的 --data-dir
# 4. 重启 API Server
mv /tmp/kube-apiserver.yaml /etc/kubernetes/manifests/
生产建议:自动备份 CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: etcd-backup
namespace: kube-system
spec:
schedule: "0 */6 * * *" # 每 6 小时
jobTemplate:
spec:
template:
spec:
hostNetwork: true
nodeSelector:
node-role.kubernetes.io/control-plane: ""
tolerations:
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
containers:
- name: backup
image: bitnami/etcd:latest
command: ["/bin/sh", "-c"]
args:
- etcdctl snapshot save /backup/etcd-$(date +%Y%m%d-%H%M).db
--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
volumeMounts:
- name: etcd-certs
mountPath: /etc/kubernetes/pki/etcd
readOnly: true
- name: backup
mountPath: /backup
volumes:
- name: etcd-certs
hostPath:
path: /etc/kubernetes/pki/etcd
- name: backup
persistentVolumeClaim:
claimName: etcd-backup-pvc
restartPolicy: OnFailure
当前集群安全状态总结
| 安全层面 | 状态 | 备注 |
|---|---|---|
| TLS 通信 | ✅ | API Server、etcd、kubelet 全程 TLS |
| RBAC | ✅ | 已创建 ServiceAccount + Role 实验 |
| PSS | ✅ | prod namespace 设置 restricted |
| NetworkPolicy | ✅ | prod 设置 default-deny + 白名单 |
| etcd 备份 | ✅ | 手动备份完成,31MB |
| etcd 加密 | ❌ | 待配置 EncryptionConfiguration |
| 审计日志 | ❌ | 待配置 audit-policy.yaml |
| 镜像扫描 | ✅ | Harbor 内置 Trivy |