K8s Lab 把当前仓库文档整理成一个可阅读的网页站点

Repository Reading Site

安全、CRD 与高级运维

| 级别 | 含义 | 允许什么 | |------|------|---------| | **Privileged** | 完全不限制 | 一切 | | **Baseline** | 最低限度安全 | 禁止特权容器、hostNetwork 等 | | **Restricted** | 最严格 | 必须 runAsNonRoot、drop ALL capa

Markdownphase-3/03-security-crd-advanced.md2026年4月9日 13:30

安全、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 同步 Secret
  • strimzi — 管理 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