目录

k8s证书说明及更新方式

本篇文章主要介绍k8s集群中证书的作用位置,并且以创建pod和exec为例说明证书调用,最后写了部署监控证书有效期的步骤。

证书概述

在 Kubernetes 中包含多个以独立进程形式运行的组件,这些组件之间通过 HTTPS/gRPC 相互通信,以协同完成集群中应用的部署和管理工作。

k8s多master架构

从图中可以看到,Kubernetes控制平面中包含了etcd,kube-apiserver,kube-scheduler,kube-controller-manager等组件,这些组件会相互进行远程调用,例如 kube-apiserver会调用etcd接口查询或数据,kube-controller-manager会调用kube-apiserver接口查询集群中的对象状态;同时kube-apiserver也会和在工作节点上的kubelet和kube-proxy进行通信,以在工作节点上部署和管理应用。

证书路径及用途

集群CA证书

签发者(CN)路径作用
kubernetes/etc/kubernetes/ssl/ca.crtKubernetes 通用 CA
etcd-ca/etc/ssl/etcd/ssl/ca.pem与 etcd 相关的所有功能
front-proxy-ca/etc/kubernetes/ssl/front-proxy-ca.crt用于前端代理证书签署

服务端证书

签发者证书路径启动命令相关参数或环境变量用途
etcd-ca/etc/ssl/etcd/ssl/member-.pem/usr/local/bin/etcdETCD_CERT_FILE提供etcd集群的加密访问
kubernetes/etc/kubernetes/ssl/apiserver.crtkube-apiserver--tls-cert-file提供kube-apiserver的加密访问
-ca@[UnixTimeStamp]/var/lib/kubelet/pki/kubelet.crt节点自签证书,提供kubelet的加密访问,过期不影响集群运行

客户端证书

签发者证书路径启动命令相关参数或环境变量用途
etcd-ca/etc/ssl/etcd/ssl/node-[NodeName].pemkube-apiserver--etcd-certfilekube-apiserver访问etcd的客户端证书
kubernetes/etc/kubernetes/ssl/apiserver-kubelet-client.crtkube-apiserver--kubelet-client-certificatekube-apiserver访问kubelet的客户端证书
front-proxy-ca/etc/kubernetes/ssl/front-proxy-client.crtkube-apiserver--proxy-client-cert-file前端代理的客户端证书,只有需要支持扩展API服务器时才需要该证书

服务账户证书(另一种形式的客户端证书)

签发者文件路径启动命令相关参数或环境变量用途
kubernetes/etc/kubernetes/admin.confkubectl提供给集群管理员操作集群时使用,一般需要复制到$HOME/.kube/config
kubernetes/etc/kubernetes/controller-manager.confkube-controller-manager--authentication-kubeconfig提供给kube-controller-manager组件访问kube-apiserver时使用
kubernetes/etc/kubernetes/scheduler.confkube-scheduler--authentication-kubeconfig提供给kube-scheduler组件访问kube-apiserver时使用
kubernetes/etc/kubenernetes/kubelet.confkubelet--kubeconfig提供给kubelet组件访问kube-apiserver时使用

注:kubelet.conf中的证书文件实际指向/var/lib/kubelet/pki/kubelet-client-current.pem,该文件是链接文件在kubelet证书滚动更新后自动指向新的文件。

其他证书

签发者文件路径启动命令相关参数或环境变量用途
etcd-ca/etc/ssl/etcd/ssl/admin-.pemetcdctl--cert提供给管理员直接访问/操作etcd的证书

证书交互过程

以创建Pod和执行kubectl exec为例说明证书交互的过程

以创建Pod为例

步骤解析:

  1. 用户通过kubectl提交资源创建请求,此时使用的集群管理证书即$HOME/.kube/config访问kube-apiserver
  2. kube-apiserver使用客户端证书保存资源到etcd中,此时使用的证书为/etc/ssl/etcd/ssl/node-.pem
  3. kube-controller-manager检查更新,此时使用kube-controller-manager的客户端证书,即/etc/kubernetes/controller-manager.conf中内嵌的证书
  4. kube-scheduler观察到需要调度新的Pod,使用客户端证书连接到kube-apiserver,证书位于/etc/kubernetes/scheduler.conf中内嵌的证书
  5. kube-scheduler通过各种算法计算出调度的节点,计算完成后提交给kube-apiserver,此时使用的证书同第4步中证书
  6. kube-apiserver保存pod与节点的映射到etcd中,此时使用的证书同第2步中的证书
  7. kubelet观察到需要在本节点创建新的Pod,证书位于/etc/kubernetes/kubelet.conf中内嵌的证书
  8. kube-apiserver绑定pod到对应节点的kubelet,此时使用的证书位于/etc/kubernetes/ssl/apiserver-kubelet-client.crt
  9. kubelet通知容器运行时创建pod
  10. 创建完成后kubelet向kube-apiserver更新状态,证书同第8步
  11. kube-apiserver保存最新的状态到etcd中,证书同第2步

以执行kubectl exec为例

步骤解析:

  1. 用户执行kubectl exec子命令请求进入容器中执行指令,此时使用的集群管理证书即$HOME/.kube/config访问kube-apiserver
  2. kube-apiserver使用客户端证书访问kubelet,证书位于/etc/kubernetes/ssl/apiserver-kubelet-client.crt
  3. kubelet通过gRPC接口访问容器运行时,无需证书
  4. 容器运行时返回执行结果给kubelet
  5. kubelet返回执行结果给kube-apiserver,此时使用kubelet客户端证书访问kube-apiserver,证书位于/etc/kubernetes/kubelet.conf中内嵌的证书
  6. 呈现执行的结果

证书有效期监控

为防止证书过期造成集群不可用,可部署exporter采集各个证书的有效期并且对小于7天的证书进行告警及时通知集群管理员更新证书。

部署ssl_exporter

部署类型为daemonset

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app: ssl-exporter
  name: ssl-exporter
spec:
  selector:
    matchLabels:
      app: ssl-exporter
  template:
    metadata:
      labels:
        app: ssl-exporter
    spec:
      containers:
      - image: reg.kolla.org/library/ssl-exporter:2.4.2
        imagePullPolicy: IfNotPresent
        name: ssl-exporter
        resources: 
          limits:
            cpu: 250m
            memory: 256Mi
          requests:
            cpu: 100m
            memory: 128Mi
        volumeMounts:
        - mountPath: /host/etc/kubernetes
          name: k8s-certs
          readOnly: true
        - mountPath: /host/var/lib/kubelet/pki
          name: kubelet-certs
          readOnly: true
      hostNetwork: true
      volumes:
      - hostPath:
          path: /etc/kubernetes
          type: ""
        name: k8s-certs
      - hostPath:
          path: /var/lib/kubelet/pki
          type: ""
        name: kubelet-certs

配置Prometheus抓取规则

由于服务证书暂不能使用通配符,各个服务账户证书需手动配置策略。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
scrape_configs:
- job_name: "ssl-k8s-file"
  metrics_path: /probe
  params:
    module: ["file"]
    target: ["/host/etc/kubernetes/ssl/*.crt"]
  kubernetes_sd_configs:
  - role: node
  relabel_configs:
  - source_labels: [__address__]
    regex: ^(.*):(.*)$
    target_label: __address__
    replacement: ${1}:9219

- job_name: "ssl-kubelet-file"
  metrics_path: /probe
  params:
    module: ["file"]
    target: 
      - "/host/var/lib/kubelet/pki/*.crt"
  kubernetes_sd_configs:
  - role: node
  relabel_configs:
  - source_labels: [__address__]
    regex: ^(.*):(.*)$
    target_label: __address__
    replacement: ${1}:9219

- job_name: "kubeconfig-admin"
  metrics_path: /probe
  params:
    module: ["kubeconfig"]
    target: ["/host/etc/kubernetes/admin.conf"]
  kubernetes_sd_configs:
  - role: node
  relabel_configs:
  - source_labels: [__address__]
    regex: ^(.*):(.*)$
    target_label: __address__
    replacement: ${1}:9219

- job_name: "kubeconfig-controller-manager"
  metrics_path: /probe
  params:
    module: ["kubeconfig"]
    target: ["/host/etc/kubernetes/controller-manager.conf"]
  kubernetes_sd_configs:
  - role: node
  relabel_configs:
  - source_labels: [__address__]
    regex: ^(.*):(.*)$
    target_label: __address__
    replacement: ${1}:9219

- job_name: "kubeconfig-kubelet"
  metrics_path: /probe
  params:
    module: ["kubeconfig"]
    target: ["/host/etc/kubernetes/kubelet.conf"]
  kubernetes_sd_configs:
  - role: node
  relabel_configs:
  - source_labels: [__address__]
    regex: ^(.*):(.*)$
    target_label: __address__
    replacement: ${1}:9219

- job_name: "kubeconfig-scheduler"
  metrics_path: /probe
  params:
    module: ["kubeconfig"]
    target: ["/host/etc/kubernetes/scheduler.conf"]
  kubernetes_sd_configs:
  - role: node
  relabel_configs:
  - source_labels: [__address__]
    regex: ^(.*):(.*)$
    target_label: __address__
    replacement: ${1}:9219

配置Prometheus告警策略

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
groups:
- name: check_ssl_validity
  rules:
  - alert: "K8S集群证书在7天后过期"
    expr: (ssl_file_cert_not_after - time()) / 86400 < 7
    for: 1h
    labels:
      severity: critical
    annotations:
      description: 'K8S集群的证书还有{{ printf "%.1f" $value }}天就过期了,请尽快更新证书'
      summary: "K8S集群证书证书过期警告"

配置Grafana面板

服务账户证书展示

../../images/kubernetes/image-20230508111309091.png

ssl证书展示

../../images/kubernetes/image-20230508111341724.png