k8s集群证书管理

k8s内的主节点与工作节点组件通信依赖ssl证书进行加密通信,而证书是会过期的

1、手动续签证书:https://egonlin.com/?p=11593

 

2、自动续签证书:需针对不同组件采用不同策略

主节点(控制平面)证书自动更新:推荐使用 Cert-Manager + 自签名 CA

工作节点(kubelet)证书自动更新:工作节点证书通过 Kubernetes 原生 TLS Bootstrapping 机制实现全自动轮换(已默认开启),无需外部工具。

kubeadm部署会自动创建自签名CA,默认 默认有效期 10 年,需手动更新(高风险操作)

 针对用户的环境(Kubernetes 1.22.2),我自动化方案:
 一、控制平面证书自动化续期(使用cert-manager)
 步骤:
 1. 安装cert-manager(使用Helm或YAML)
 2. 创建自签名CA(或使用现有CA)并存储为Secret
 3. 创建ClusterIssuer引用该CA
 4. 为每个控制平面组件(apiserver, etcd, controller-manager, scheduler等)创建Certificate资源
 5. 修改控制平面组件的静态Pod定义,使其使用cert-manager管理的证书(从Secret挂载),并启用证书热加载(如果组件支持)
 6. 重启控制平面组件(一次性的,之后由cert-manager自动续期)
 二、工作节点证书自动化续期
 工作节点的kubelet证书通过TLS Bootstrapping自动轮换,但需要确保:
 1. kubelet配置了`--rotate-certificates=true`(默认开启)详解工作节点的/var/lib/kubelet/config.yaml中的配置项rotateCertificates为true
 2. controller-manager配置了自动批准CSR(默认开启)
 3. 确保RBAC授权正确(默认已设置)
 三、CA根证书的考虑
 控制平面组件的根证书(ca.crt)默认10年,但若需要更新,则需要手动操作(风险高)。建议在初始化集群时使用长期有效的CA,或者定期(比如每8年)更新CA并重新签所有证书,不过有几个人能在一家公司干满10年呢,或者说同一个项目谁能维护10年呢哈哈哈。
 四、监控与告警
 部署监控,对证书过期时间进行告警(如使用Prometheus监控cert-manager的指标,或定期检查证书过期时间)。
 具体操作步骤(针对控制平面):
 1. 安装cert-manager
   由于是离线环境?这里假设有网络(如果没有,需要先下载镜像)
   使用Helm安装:
   ```
   helm repo add jetstack https://charts.jetstack.io
   helm repo update
   helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --version v1.13.1 --set installCRDs=true
   ```
 2. 创建自签名CA(如果集群现有的CA可以继续使用,则跳过创建,直接创建Secret)
   生成CA(在master节点上):
   ```
   openssl genrsa -out ca.key 2048
   openssl req -x509 -new -nodes -key ca.key -subj "/CN=Kubernetes" -days 3650 -out ca.crt

   查看
   openssl x509 -in /etc/kubernets/pki/ca.crt -noout -text |grep Not
   ```
   创建Secret(在kube-system命名空间):
   ```
   kubectl create secret tls k8s-root-ca --cert=ca.crt --key=ca.key -n kube-system
   ```
 3. 创建ClusterIssuer
   ```yaml
   apiVersion: cert-manager.io/v1
   kind: ClusterIssuer
   metadata:
     name: k8s-root-issuer
     namespace: kube-system
   spec:
     ca:
       secretName: k8s-root-ca
   ```
 4. 为每个组件创建Certificate资源(以apiserver为例)
   ```yaml
   apiVersion: cert-manager.io/v1
   kind: Certificate
   metadata:
     name: kube-apiserver
     namespace: kube-system
   spec:
     secretName: kube-apiserver-tls   # 这个Secret名称需要与apiserver启动参数中指定的证书一致
     duration: 8760h   # 1年
     renewBefore: 720h  # 提前30天续期
     issuerRef:
       name: k8s-root-issuer
       kind: ClusterIssuer
     commonName: kube-apiserver
     usages:
       - server auth
       - client auth
     dnsNames:
       - kubernetes
       - kubernetes.default
       - kubernetes.default.svc
       - kubernetes.default.svc.cluster.local
       - localhost
       # 添加其他DNS名称(如master节点的主机名、负载均衡器的域名等)
     ipAddresses:
       - 127.0.0.1
       - 10.96.0.1   # ClusterIP of kubernetes service
       # 添加master节点的IP地址
       - 192.168.110.128
   ```
   注意:需要为etcd、controller-manager、scheduler等创建类似的Certificate资源。
 5. 修改控制平面组件的静态Pod定义(以apiserver为例)
   文件位置:/etc/kubernetes/manifests/kube-apiserver.yaml
   修改内容:
   - 将`--tls-cert-file`和`--tls-private-key-file`指向新证书(从Secret挂载的路径)
   - 添加volume挂载(将Secret挂载到容器内)
   示例:
   ```yaml
   spec:
     containers:
     - command:
       - kube-apiserver
       - --tls-cert-file=/etc/kubernetes/secrets/kube-apiserver-tls/tls.crt
       - --tls-private-key-file=/etc/kubernetes/secrets/kube-apiserver-tls/tls.key
       # ... 其他参数保持不变
       volumeMounts:
       - name: apiserver-tls
         mountPath: /etc/kubernetes/secrets/kube-apiserver-tls
         readOnly: true
     volumes:
     - name: apiserver-tls
       secret:
         secretName: kube-apiserver-tls
   ```
   注意:修改后,kubelet会自动重启apiserver的Pod。
 6. 重启控制平面组件(如果不确定是否支持热加载,可以重启)
   实际上,修改静态Pod定义后,kubelet会自动重启对应的Pod。
 7. 注意:其他组件(etcd, controller-manager, scheduler)也需要做类似的修改。
 8. 对于kubelet.conf等kubeconfig文件,不需要再手动更新,因为控制平面组件已经使用了新证书,且kubeconfig中的证书是由同一个CA签发的,所以信任链一致。
 五、工作节点:
   无需额外操作,只要确保kubelet的配置正确(自动轮换开启),并且controller-manager能够自动批准CSR。
 六、监控:
   使用cert-manager自带的Prometheus指标进行监控,并设置告警规则,例如:
   ```
   # 证书在30天内过期
   certmanager_certificate_expiration_timestamp_seconds - time() < 86400 * 30
   ```
 七、注意事项:
   - 在迁移过程中,需要确保集群处于可维护状态(可能短暂不可用)。
   - 备份原有的证书和配置文件。
   - 由于用户集群版本为1.22.2,注意cert-manager的版本兼容性(cert-manager v1.13.1支持Kubernetes 1.22+)。
 八、关于CA根证书的长期管理:
   - 如果使用自签名CA,建议设置较长的有效期(例如10年),并定期检查CA的过期时间。
   - 更新CA根证书是一个复杂且危险的操作,需要谨慎。
 总结:通过上述步骤,控制平面证书将由cert-manager自动续期,工作节点证书由Kubernetes原生机制自动续期,从而实现全集群证书的自动化管理。

 

以下是完整的自动化解决方案,可避免未来证书过期导致的服务中断:

自动化证书管理方案(基于 Kubernetes 1.22.2)

一、控制平面证书自动化(Master 节点)

核心工具:cert-manager + 自签名 CA

# 1. 安装 cert-manager(v1.13.1 兼容 Kubernetes 1.22)
helm repo add jetstack https://charts.jetstack.io
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.13.1 \
  --set installCRDs=true

# 2. 创建长期有效的根 CA(10年有效期)
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -key ca.key \
  -subj "/CN=Kubernetes Internal CA" \
  -days 3650 -out ca.crt

# 3. 创建 CA Secret
kubectl create secret tls k8s-root-ca \
  --namespace=kube-system \
  --cert=ca.crt \
  --key=ca.key

# 4. 创建 ClusterIssuer
cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: k8s-root-issuer
  namespace: kube-system
spec:
  ca:
    secretName: k8s-root-ca
EOF

二、为控制平面组件配置自动续期

# 5. API Server 证书配置(示例)
cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: kube-apiserver
  namespace: kube-system
spec:
  secretName: kube-apiserver-tls
  duration: 8760h  # 1年
  renewBefore: 720h # 提前30天续期
  issuerRef:
    name: k8s-root-issuer
    kind: ClusterIssuer
  commonName: kube-apiserver
  dnsNames:
    - kubernetes
    - kubernetes.default
    - kubernetes.default.svc
    - kubernetes.default.svc.cluster.local
    - localhost
  ipAddresses:
    - 127.0.0.1
    - 10.96.0.1
    - 192.168.110.128  # Master IP
  organization:
    - system:masters
  usages:
    - server auth
    - client auth
EOF

三、修改控制平面组件配置

# 6. 修改 API Server 配置
sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml

添加以下配置:

spec:
  containers:
  - command:
    - kube-apiserver
    - --tls-cert-file=/etc/kubernetes/secrets/kube-apiserver-tls/tls.crt
    - --tls-private-key-file=/etc/kubernetes/secrets/kube-apiserver-tls/tls.key
    - --feature-gates=APIServerIdentity=true
    - --tls-cert-file-watch=true  # 启用证书监控
  volumeMounts:
    - name: apiserver-tls
      mountPath: /etc/kubernetes/secrets/kube-apiserver-tls
  volumes:
    - name: apiserver-tls
      secret:
        secretName: kube-apiserver-tls

四、工作节点自动化(Worker 节点)

核心机制:原生 TLS Bootstrapping

# 1. 确保所有节点 kubelet 配置
sudo vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

添加参数:

ini
Environment="KUBELET_EXTRA_ARGS=--rotate-certificates=true --cert-dir=/var/lib/kubelet/pki"
# 2. 配置 Controller Manager 自动审批
sudo vi /etc/kubernetes/manifests/kube-controller-manager.yaml

添加参数:

spec:
  containers:
  - command:
    - kube-controller-manager
    - --cluster-signing-duration=87600h  # 10年有效期
    - --controllers=*,csrapprover
    - --feature-gates=RotateKubeletServerCertificate=true

五、监控与告警系统

# 1. 创建证书过期告警(Prometheus)
cat <<EOF | kubectl apply -f -
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: cert-expiry-alert
  namespace: kube-system
spec:
  groups:
  - name: cert-expiry
    rules:
    - alert: CertificateExpiringSoon
      expr: (certmanager_certificate_expiration_timestamp_seconds - time()) / 86400 < 30
      for: 5m
      labels:
        severity: critical
      annotations:
        summary: "证书即将过期 ({{ $labels.name }})"
        description: "证书 {{ $labels.name }} 将在 {{ printf \"%.0f\" ( (certmanager_certificate_expiration_timestamp_seconds - time()) / 86400 ) }} 天后过期"
EOF

# 2. 定期检查脚本
sudo tee /usr/local/bin/check-certs.sh <<'EOF'
#!/bin/bash
kubeadm certs check-expiration
find /etc/kubernetes/pki -type f -name "*.crt" -print0 | 
  xargs -0 openssl x509 -noout -dates |
  awk -F= '/notAfter/{print "证书过期时间:", $2}'
EOF
sudo chmod +x /usr/local/bin/check-certs.sh

# 3. 添加到 cronjob(每月检查)
(crontab -l ; echo "0 0 1 * * /usr/local/bin/check-certs.sh | mail -s 'K8s证书检查' admin@example.com") | crontab -

六、灾备与恢复方案

# 1. 自动备份证书
sudo tee /usr/local/bin/backup-certs.sh <<'EOF'
#!/bin/bash
BACKUP_DIR="/backup/certs/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR
cp -a /etc/kubernetes $BACKUP_DIR
cp -a /var/lib/kubelet/pki $BACKUP_DIR/kubelet-certs
tar -czf $BACKUP_DIR.tar.gz $BACKUP_DIR
find /backup -type f -mtime +30 -delete
EOF
sudo chmod +x /usr/local/bin/backup-certs.sh

# 2. 添加到 cronjob(每周备份)
(crontab -l ; echo "0 3 * * 0 /usr/local/bin/backup-certs.sh") | crontab -

# 3. Velero 备份关键 Secrets
velero backup create certs-backup --include-resources secrets --selector cert-manager.io/certificate-name

方案验证流程

# 1. 强制触发续期测试
kubectl patch certificate kube-apiserver -n kube-system \
  --type='json' -p='[{"op": "replace", "path": "/spec/renewBefore", "value": "5m"}]'

# 2. 观察续期过程
kubectl get certificates -n kube-system -w
kubectl logs -f -n cert-manager deploy/cert-manager

# 3. 验证新证书加载
openssl s_client -connect 127.0.0.1:6443 -showcerts 2>/dev/null | 
  openssl x509 -noout -dates

关键注意事项

  1. 版本兼容性

    • cert-manager v1.13.x 完美兼容 Kubernetes 1.22

    • 确保所有节点时间同步(NTP 服务)

  2. 多主节点部署

    # 在所有 Master 节点执行相同配置
    for node in k8scludes1 k8scludes2 k8scludes3; do
      scp /etc/kubernetes/manifests/*.yaml ${node}:/etc/kubernetes/manifests/
      ssh ${node} "systemctl restart kubelet"
    done
  3. 证书迁移策略

    • 首次配置在维护窗口进行

    • 使用 kubeadm certs renew all 生成新证书

    • 逐步替换为 cert-manager 管理

  4. 安全加固

    # 限制 CA Secret 访问
    kubectl create rolebinding cert-manager-ca \
      --role=cert-manager-ca-role \
      --serviceaccount=kube-system:cert-manager \
      --namespace=kube-system

方案优势

  • 控制平面证书全自动续期(cert-manager)

  • 工作节点证书自动轮换(原生 TLS Bootstrapping)

  • 过期前主动告警(Prometheus)

  • 灾难恢复保障(自动备份 + Velero)

  • 零手动干预,彻底避免证书过期导致的集群故障

 

 

 

上一篇
下一篇
Copyright © 2022 Egon的技术星球 egonlin.com 版权所有 沪ICP备2022009235号 沪公网安备31011802005110号 青浦区尚茂路798弄 联系方式-13697081366