K8S集群tls证书管理

在前文介绍的k8s master高可用实践方案中,需要对kube-apiserver的证书进行更新,加入VIP和从节点的IP,然后重新下发证书。回顾K8S集群整个搭建过程中,最容易让人懵圈的也就是配置证书环节,因此本文对K8S集群所用到的证书进行梳理一下。

一、根证书

ca.pem 根证书公钥文件
ca-key.pem 根证书私钥文件
ca.csr 证书签名请求,用于交叉签名或重新签名
ca-config.json 使用cfssl工具生成其他类型证书需要引用的配置文件
ca.pem用于签发后续其他的证书文件,因此ca.pem文件需要分发到集群中的每台服务器上去。

证书生成命令,默认生成的证书有效期5年

# echo ‘{"CN":"CA","key":{"algo":"rsa","size":2048}}‘ | cfssl gencert -initca - | cfssljson -bare ca -
# echo ‘{"signing":{"default":{"expiry":"43800h","usages":["signing","key encipherment","server auth","client auth"]}}}‘ > ca-config.json

二、flannel证书

证书生成命令,默认生成的证书有效期5年

# cfssl gencert -ca=/etc/ssl/etcd/ca.pem   -ca-key=/etc/ssl/etcd/ca-key.pem   -config=/etc/ssl/etcd/ca-config.json   -profile=kubernetes flanneld-csr.json | cfssljson -bare flanneld


这里生成证书需要flanneld-csr.json文件

# cat flanneld-csr.json
{
  "CN": "flanneld",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "FuZhou",
      "L": "FuZhou",
      "O": "k8s",
      "OU": "System"
    }
  ]
}

flannel启动文件配置

# cat /usr/lib/systemd/system/flanneld.service
[Unit]
Description=Flanneld overlay address etcd agent
After=network.target
After=network-online.target
Wants=network-online.target
After=etcd.service
Before=docker.service

[Service]
Type=notify
ExecStart=/usr/local/bin/flanneld   -etcd-cafile=/etc/ssl/etcd/ca.pem   -etcd-certfile=/etc/ssl/flanneld/flanneld.pem   -etcd-keyfile=/etc/ssl/flanneld/flanneld-key.pem   -etcd-endpoints=https://192.168.115.5,https://192.168.115.6:2379,https://192.168.115.7:2379   -etcd-prefix=/kubernetes/network
ExecStartPost=/usr/local/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker
Restart=on-failure

[Install]
WantedBy=multi-user.target
RequiredBy=docker.service

三、etcd证书

1、服务端证书

server.pem etcd服务端证书公钥文件
server-key.pem etcd服务端证书私钥文件
server.csr 证书签名请求

证书生成命令,默认生成的证书有效期5年

# export ADDRESS=192.168.115.5,192.168.115.6,192.168.115.7,vm1,vm2,vm3
# export NAME=server
# echo ‘{"CN":"‘$NAME‘","hosts":[""],"key":{"algo":"rsa","size":2048}}‘ |  cfssl gencert -config=ca-config.json -ca=ca.pem -ca-key=ca-key.pem -hostname="$ADDRESS" - | cfssljson -bare $NAME


server.pem、server-key.pem文件用来etcd集群间通信加解密,因此所有的etcd服务器都需要有这两个文件

# tail -15 /usr/lib/systemd/system/etcd.service
--initial-cluster-token=etcd-cluster-token --initial-cluster-state=new --cert-file=/etc/ssl/etcd/server.pem --key-file=/etc/ssl/etcd/server-key.pem --peer-cert-file=/etc/ssl/etcd/server.pem --peer-key-file=/etc/ssl/etcd/server-key.pem --trusted-ca-file=/etc/ssl/etcd/ca.pem --peer-trusted-ca-file=/etc/ssl/etcd/ca.pem --peer-client-cert-auth=true --client-cert-auth=true"
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

2、客户端证书

client.pem etcd客户端证书公钥文件
client-key.pem etcd客户端证书私钥文件
client.csr 证书签名请求

证书生成命令,默认生成的证书有效期5年

# export ADDRESS=
# export NAME=client
# echo ‘{"CN":"‘$NAME‘","hosts":[""],"key":{"algo":"rsa","size":2048}}‘ |  cfssl gencert -config=ca-config.json -ca=ca.pem -ca-key=ca-key.pem -hostname="$ADDRESS" - | cfssljson -bare $NAME


client.pem、client-key.pem文件给etcdctl客户端用来和etcd服务器进行通信,可根据实际需要进行配置。

# export ETCDCTL_API=3
# etcdctl --write-out=table  --cert=/etc/ssl/etcd/client.pem --key=/etc/ssl/etcd/client-key.pem --cacert=/etc/ssl/etcd/ca.pem --endpoints=https://192.168.115.5:2379,https://192.168.115.6:2379,https://192.168.115.7:2379 member list

四、Master节点证书

Kube-apiserver证书
Kubernetes.pem kube-apiserver证书公钥文件
Kubernetes-key.pem kube-apiserver证书私钥文件
kuberentes.csr kube-apiserver证书签名请求

证书生成命令,默认生成的证书有效期5年

# cfssl gencert -ca=/etc/ssl/etcd/ca.pem   -ca-key=/etc/ssl/etcd/ca-key.pem   -config=/etc/ssl/etcd/ca-config.json   -profile=kubernetes k8s-csr.json | cfssljson -bare kubernetes


这里生成证书需要k8s-csr.json文件,其中定义了master节点的IP列表等信息

# cat k8s-csr.json
{
  "CN": "kubernetes",
  "hosts": [
    "127.0.0.1",
    "192.168.115.4",
    "192.168.115.5",
    "192.168.115.6",
    "192.168.115.7",
    "10.254.0.1",
    "kubernetes",
    "kubernetes.default",
    "kubernetes.default.svc",
    "kubernetes.default.svc.cluster",
    "kubernetes.default.svc.cluster.local"
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "FuZhou",
      "L": "FuZhou",
      "O": "k8s",
      "OU": "System"
    }
  ]
}

五、Node节点证书

1、kube-proxy证书

Kube-proxy.pem kube-proxy证书公钥文件
Kube-proxy-key.pem kube-proxy证书私钥文件
Kube-proxy.csr kube-proxy证书签名请求

证书生成命令,默认生成的证书有效期5年

# cfssl gencert -ca=/etc/ssl/etcd/ca.pem   -ca-key=/etc/ssl/etcd/ca-key.pem   -config=/etc/ssl/etcd/ca-config.json   -profile=kubernetes  kube-proxy-csr.json | cfssljson -bare kube-proxy


这里生成证书需要kube-proxy-csr.json文件

# cat kube-proxy-csr.json
{
  "CN": "system:kube-proxy",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "FuZhou",
      "L": "FuZhou",
      "O": "k8s",
      "OU": "System"
    }
  ]
}

2、Kubelet证书

Kubelet-client.crt: kubectl客户端证书公钥文件
Kubelet-client.key: kubectl客户端私钥文件
Kubelet.crt:kubelet服务端证书公钥文件
Kubelet.key:kubelet服务端证书私钥文件

> kubelet-client.crt 文件在 kubelet 完成 TLS bootstrapping 后生成,有效期为 1 年。此证书是由 controller manager 签署的,此后 kubelet 将会加载该证书,用于与 apiserver 建立 TLS 通讯,同时使用该证书的 CN 字段作为用户名,O 字段作为用户组向 apiserver 发起其他请求。
kubelet.crt 文件在 kubelet 完成 TLS bootstrapping 后且没有配置 --feature-gates=RotateKubeletServerCertificate=true 时才会生成;该文件为一个独立于 apiserver CA 的自签 CA 证书,有效期为 1 年;被用作 kubelet 10250 api 端口


关于kubelet首次启动 TLS bootstrapping的介绍(先有鸡还是先有蛋问题的解决方案)可参考文档,https://mritd.me/2018/01/07/kubernetes-tls-bootstrapping-note/

六、配置证书自动续期

默认签署kubectl客户端和kubelet服务端证书只有 1 年有效期,如果想要调整证书有效期可以通过设置 kube-controller-manager 的?--experimental-cluster-signing-duration?参数实现,该参数默认值为?8760h0m0s。下面我们来介绍一下如何实现证书到期的自动续签。这个问题如果处理不当,证书过期之后会出现所有的node节点连接不上的情况。

1、kcm服务,这里为了方便测试,过期时间修改为30分钟

# egrep ‘feature|experimental‘ /usr/lib/systemd/system/kube-controller-manager.service
  --feature-gates=RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true   --experimental-cluster-signing-duration=30m0s # systemctl  daemon-reload
# systemctl restart kube-controller-manager

2、kubelet服务
配置完成删掉Kubelet-client.crt、Kubelet-client.key、Kubelet.crt、Kubelet.key四个文件后重启kubelet服务。

# egrep ‘feature|rotate‘ /usr/lib/systemd/system/kubelet.service
  --feature-gates=RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true   --rotate-certificates=true # systemctl  daemon-reload
# systemctl restart kubelet

3、手工签发证书

# kubectl create clusterrolebinding kubelet-clinet --clusterrole=system:node  --user=system:anonymous

如果缺少对system:anonymous用户的授权,kubelet启动的时候会报错如下:
error: failed to run Kubelet: cannot create certificate signing request: certificatesigningrequests.certificates.k8s.io is forbidden: User "system:anonymous" cannot create certificatesigningrequests.certificates.k8s.io at the cluster scope

# kubectl get csr
# kubectl certificate approve csr-fn946
# kubectl certificate approve csr-kwvg9 

node节点将会重新生成kubectl客户端和kubelet服务端证书

4、配置自动签发证书,在大规模集群下,这个配置是必须的

# cat rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver
rules:
- apiGroups:
  - certificates.k8s.io
  resources:
  - certificatesigningrequests/selfnodeserver
  verbs:
  - create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubeadm:node-autoapprove-certificate-server
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:nodes

# kubectl create -f  rbac.yaml
# kubectl create clusterrolebinding node-client-auto-approve-csr  --clusterrole=system:certificates.k8s.io:certificatesigningrequests:nodeclient  --group=system:bootstrappers
# kubectl create clusterrolebinding node-client-auto-renew-crt --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeclient --group=system:nodes
# kubectl create clusterrolebinding node-server-auto-renew-crt  --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeserver  --group=system:nodes

这里需要注意的是删除掉Kubelet-client.crt、Kubelet-client.key两个文件之后,启动kubelet服务,首先会生成一个Kubelet-client.key文件,我们需要对这个证书的crs请求进行approve,否则node节点无法正常启动。
其次,如果kubelet.kubeconfig文件中配置的client-certificate、client-key目录位置和kubelet的启动参数--cert-dir不一致,则kubelet.kubeconfig文件中的配置文件会被自动更新。

原文地址:http://blog.51cto.com/ylw6006/2167592

时间: 2024-08-29 17:44:51

K8S集群tls证书管理的相关文章

使用kubeadm部署k8s集群03-扩容kube-apiserver到3节点

使用kubeadm部署k8s集群03-扩容kube-apiserver到3节点 2018/1/3 扩容 kube-apiserver 到 3 节点 配置 kube-apiserver.yaml 分析 kube-apiserver 依赖的证书 为新节点生成专属证书 下发证书到对应的节点 确认每个节点的 apiserver 是否处于 Running 状态 配置 kube-apiserver.yaml ### 拷贝原 master 上的配置: [[email protected] ~]# mkdir

再探使用kubeadm部署高可用的k8s集群-01引言

再探使用kubeadm部署高可用的k8s集群-01引言 2018/1/26 提示 仅供测试用途前言:高可用一直是重要的话题,需要持续研究.最近关注到 k8s 官网文档有更新,其中一篇部署高可用集群的文章思路不错,简洁给力,希望能分享给有需要的小伙伴一起研究下. 资源 k8s node master0, 10.222.0.100 master1, 10.222.0.101 master2, 10.222.0.102 LB, 10.222.0.88 master0, master1, master2

k8s集群之kubernetes-dashboard和kube-dns组件部署安装

说明 最好先部署kube-dns,有些组合服务直接主机用hostname解析,例如redis主从,heapster监控组件influxdb.grafana之间等. 参考文档 https://greatbsky.github.io/KubernetesDoc/kubernetes1.5.2/cn.html 安装集群文档见: http://jerrymin.blog.51cto.com/3002256/1898243 安装PODS文档见: http://jerrymin.blog.51cto.com

k8s集群之日志收集EFK架构

参考文档 http://tonybai.com/2017/03/03/implement-kubernetes-cluster-level-logging-with-fluentd-and-elasticsearch-stack/ https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/fluentd-elasticsearch https://t.goodrain.com/t/k8s/242 http://logz

基于prometheus监控k8s集群

本文建立在你已经会安装prometheus服务的基础之上,如果你还不会安装,请参考:prometheus多维度监控容器 如果你还没有安装库k8s集群,情参考: 从零开始搭建基于calico的kubenetes 前言 kubernetes显然已成为各大公司亲睐的容器编排工具,各种私有云公有云平台基于它构建,那么,我们怎么监控集群中的所有容器呢?目前有三套方案: heapster+influxDB heapster为k8s而生,它从apiserver获取节点信息,每个节点kubelet内含了cAdv

使用kubeadm安装k8s集群故障处理三则

最近在作安装k8s集群,测试了几种方法,最终觉得用kubeadm应该最规范. 限于公司特别的网络情况,其安装比网上不能访问google的情况还要艰难. 慢慢积累经验吧. 今天遇到的三则故障记下来作参考. 当然,所有方法都是看了log输出后,从网上搜索的方法. =============== Q,如何让kubeadm在安装过程中不联网? A:记得在kubeadm init过程中增加参数 --kubernetes-version=v1.7.0 Q,kubelet cgroup driver参数不一致

使用kubeadm部署k8s集群08-配置LB指向kube-apiserver

使用kubeadm部署k8s集群08-配置LB指向kube-apiserver 2018/1/4 配置 LB 指向 kube-apiserver 小目标:在 3 个 master 节点前,还需配置一个 LB 来作为 apiserver 的入口 LB -> master x3 直接使用阿里云内网 SLB L4 proxy 资源(本次实例是 4 层而不使用 7 层的原因是:跳过了处理证书的环节) 申请下来资源后,将得到一个 vip 指向上述 3 个 master 节点的 IP 作为后端真实服务器 注

使用kubeadm部署k8s集群05-配置kubectl访问kube-apiserver

使用kubeadm部署k8s集群05-配置kubectl访问kube-apiserver 2018/1/4 配置 kubectl 访问 kube-apiserver 切换 master 节点连接到本节点的 apiserver 确认集群信息 切换 master 节点连接到本节点的 apiserver ### 为了在这 2 个新的节点执行 kubectl 需要配置 admin.yaml [[email protected] ~]# mkdir -p ~/k8s_install/master/admi

使用kubeadm部署k8s集群01-初始化

使用kubeadm部署k8s集群01-初始化 2018/1/3 节点配置 master x3 OS version: centos7 swapoff ### 阿里云默认:off hosts ### 每个节点上配置: [[email protected] ~]# cat /etc/hosts ### k8s master @envDev 10.10.9.67 tvm-00 10.10.9.68 tvm-01 10.10.9.69 tvm-02 Docker version: latest(17.0