TLS Bootstrapping 的作用就是自动创建 kubelet 和 kube-proxy 的证书的。手动创建证书也行,但是集群规模大了手动创建比较麻烦,TLS Bootstrapping 的作用就是为了省点事。

官方文档:

https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/


Bootstrap启动过程:

1、kubelet 启动。

2、kubelet 未发现 kubeconfig文件。

3、kubelet 寻找 bootstrap-kubeconfig文件。

4、kubelet 读取 bootstrap-kubeconfig 内容,从中知道 apiserver地址 和 token。

5、kubelet 连接到 apiserver,使用token进行身份验证。

6、kubelet 现在具有向 apiserver发起证书签名请求(CSR)的权限了。

7、kubelet 为自己创建CSR请求。

8、批准CSR有以下两种方式:

        (一)、配置controller-manager自动批准CSR,(controller-manager负责证书的签署)。

        (二)、手动批准CSR(批准命令:kubectl certificate approve csr-msxdh)。

9、apiserver为kubelet创建证书。

10、apiserver给kubelet颁发证书。

11、kubelet 把证书拿回来(这个证书是一个文件中包含私钥和证书)。

12、kubelet 使用 证书和私钥创建kubeconfig(正式的配置文件)。

13、kubelet 开始其他工作。

14、可选:如果kubelet配置了自动更新证书,kubelet会在证书快到期时自动更新证书。

15、如果配置了CSR自动批准则自动批准,否则手动批准,同第8步。


要配置的几个组件:

        kube-apiserver

        kube-controller-manager

        kubelet

        集群内资源:ClusterRoleBinding 和 ClusterRole(1.8之前)。

        Kubernetes证书颁发机构(这里指x509的CA)。


x509证书:


        全局的ca证书,也就是master节点使用的那个自签证书,用来给其他证书签证的证书,ca.crt 和 ca.key。如果集群已近存在目前只是增加节点这个证书就不用创建了。



apiserver的配置


apiserver的工作主要有以下几点:

        1、识别客户证书(kubelet将ca证书发给apiserver进行认证)

        2、验证 kubelet。

        3、授权kubelet创建CSR。

识别客户证书:

        第一步只要在kubelet中将ca.crt配置好即可,在kubelet配置中会提到。

验证kubelet:

        验证kubelet的方式有多种,推荐的有两种。

        (一)、Bootstrap Tokens(Beta)

        (二)、Token 认证文件

        这里使用第二种认证方式,认证原理就是对比token是否相同,步骤如下。

生成token:

head -c 16 /dev/urandom | od -An -t x | tr -d ' '

token认证文件:

02b50b05283e98dd0fd71db496ef01e8,kubelet-bootstrap,10001,"system:bootstrappers"

授权kubelet创建CSR:enable bootstrapping nodes to create CSR

cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: create-csrs-for-bootstrapping
subjects:
- kind: Group
  name: system:bootstrappers
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: system:node-bootstrapper
  apiGroup: rbac.authorization.k8s.io
EOF



controller-manager的配置


controller-manager的功能:

        1、查看证书

        2、签署证书

        因为controller-manager要签署证书,所以要将用于签证的秘钥和证书提供给controller-manager。

在kube-controller-manager.service中要添加的配置项:

--cluster-signing-cert-file="/etc/path/to/kubernetes/ca/ca.crt"
--cluster-signing-key-file="/etc/path/to/kubernetes/ca/ca.key"

签证时间:如果要设置签证的时间则添加如下参数,默认为一年8760h0m0s。

--experimental-cluster-signing-duration=8760h0m0s

        下面是设置controller-manager批准bootstrapping的CSR请求,和批准证书自动更新的CSR请求,主要设置一些权限绑定。低于1.8版本的要加上两个ClusterRoles,详见官方文档

批准bootstrapping的CSR请求:Approve all CSRs for the group "system:bootstrappers"

cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: auto-approve-csrs-for-group
subjects:
- kind: Group
  name: system:bootstrappers
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: system:certificates.k8s.io:certificatesigningrequests:nodeclient
  apiGroup: rbac.authorization.k8s.io
EOF

批准自动更新的CSR请求:Approve renewal CSRs for the group "system:nodes"

cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: auto-approve-renewals-for-nodes
subjects:
- kind: Group
  name: system:nodes
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: system:certificates.k8s.io:certificatesigningrequests:selfnodeclient
  apiGroup: rbac.authorization.k8s.io
EOF

或者使用如下命令:

自动Approve CSR请求:

kubectl create clusterrolebinding auto-approve-csrs-for-group --group=system:bootstrappers --clusterrole=system:certificates.k8s.io:certificatesigningrequests:nodeclient

自动批准更新CSR请求:

kubectl create clusterrolebinding auto-approve-renewals-for-nodes --group=system:nodes --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeclient


kubelet的配置


kubelet的相关功能配置:

        1、设置签发过来的证书存储目录,不设置则使用默认目录。

        2、设置生成的配置文件 kubeconfig 的文件路径。

        3、设置 bootstrap-kubeconfig 文件的路径,文件中包含 apiserver 地址和 token。

        4、配置证书轮询,包括客户端和服务端证书。


1、证书存储目录:

--cert-dir=/etc/kubernetes/cert/

2、kubeconfig:

--kubeconfig=/etc/kubernetes/kubeconfig

3、bootstrap-kubeconfig:

--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubeconfig

4、证书轮询:

现有证书快到期时创建CSR请求来轮询客户端证书。

--rotate-certificates=true

客户端证书轮询后再进行服务端的证书轮询:

--rotate-server-certificates=true


具体的配置过程如下:

使用命令创建bootstrap-kubeconfig文件:

kubectl config --kubeconfig=/etc/kubernetes/bootstrap-kubeconfig set-cluster bootstrap --server='https://192.168.1.133:6443' --certificate-authority=/etc/kubernetes/cert/ca.crt
kubectl config --kubeconfig=/etc/kubernetes/bootstrap-kubeconfig set-credentials kubelet-bootstrap --token=5e9e293d3b14c995bd7c1415c5e0c6c0
kubectl config --kubeconfig=/etc/kubernetes/bootstrap-kubeconfig set-context bootstrap --user=kubelet-bootstrap --cluster=bootstrap
kubectl config --kubeconfig=/etc/kubernetes/bootstrap-kubeconfig use-context bootstrap

安装并运行docker等:

wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

kubelet.service

[Unit]
Description=Kubernetes kubelet Server
After=docker.service
Requires=docker.service

[Service]
WorkingDirectory=/var/lib/kubelet
ExecStart=/usr/bin/kubelet \
--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubeconfig \
--kubeconfig=/etc/kubernetes/kubeconfig \
--cert-dir=/etc/kubernetes/cert/ \
--rotate-certificates=true \
--rotate-server-certificates=true

Restart=on-failure
[Install]
WantedBy=multi-user.target

查看和批准CSR请求:

[root@k8s-01 kubernetes]# kubectl get csr
NAME        AGE   REQUESTOR            CONDITION
csr-msxdh   64s   system:node:k8s-05   Pending
csr-nxh65   78s   kubelet-bootstrap    Approved,Issued
[root@k8s-01 kubernetes]# kubectl certificate approve csr-msxdh
certificatesigningrequest.certificates.k8s.io/csr-msxdh approved
[root@k8s-01 kubernetes]# 
[root@k8s-01 kubernetes]# kubectl get csr
NAME        AGE     REQUESTOR            CONDITION
csr-msxdh   2m31s   system:node:k8s-05   Approved,Issued
csr-nxh65   2m45s   kubelet-bootstrap    Approved,Issued


其他需要认证的组件:

        如kube-proxy、监控、网络等其他组件也需要向apiserver获得身份验证,有两种方法,第一种是同kubelet。第二种是Daemonset方式。



操作示例


        以下实验环境为二进制安装的k8s 1.14.2,如果是kubeadm安装的话实际操作有区别。

设置主机名:

hostnamectl set-hostname k8s-06

配置DNS:

cat >> /etc/hosts <<EOF
192.168.1.133 k8s-01
192.168.1.134 k8s-02
192.168.1.135 k8s-03
192.168.1.136 k8s-04
192.168.1.137 k8s-05
192.168.1.138 k8s-06
EOF

关闭swap:

swapoff -a

注释swap:

vim /etc/fstab

配置docker yum源:

wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

安装docker:

yum install docker-ce -y

启动docker:

systemctl start docker
systemctl status docker

从其他节点拷贝或下载 kubelet kubectl和 kube-proxy:

scp /usr/bin/kubelet root@192.168.1.138:/usr/bin/
scp /usr/bin/kube-proxy root@192.168.1.138:/usr/bin/
scp /usr/bin/kubectl root@192.168.1.138:/usr/bin/


apiserver上的配置:在master节点上

生成token:

head -c 16 /dev/urandom | od -An -t x | tr -d ' '

设置token文件:这个token下面还要用

cat > /etc/kubernetes/token.csv <<EOF
5e9e293d3b14c995bd7c1415c5e0c6c0,kubelet-bootstrap,10001,"system:bootstrappers"
EOF

打开kube-apiserver.service:

vim /usr/lib/systemd/system/kube-apiserver.service

添加如下选项:

--token-auth-file=/etc/kubernetes/token.csv


controller-manager的配置:

vim /usr/lib/systemd/system/kube-controller-manager.service

添加如下两个选项:

--cluster-signing-cert-file=/etc/kubernetes/cert/ca.crt \
--cluster-signing-key-file=/etc/kubernetes/cert/ca.key \

创建ClusterRoleBinding:

1、批准CSR

cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: create-csrs-for-bootstrapping
subjects:
- kind: Group
  name: system:bootstrappers
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: system:node-bootstrapper
  apiGroup: rbac.authorization.k8s.io
EOF

2、client rotate

cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: auto-approve-csrs-for-group
subjects:
- kind: Group
  name: system:bootstrappers
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: system:certificates.k8s.io:certificatesigningrequests:nodeclient
  apiGroup: rbac.authorization.k8s.io
EOF

3、server rotate

cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: auto-approve-renewals-for-nodes
subjects:
- kind: Group
  name: system:nodes
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: system:certificates.k8s.io:certificatesigningrequests:selfnodeclient
  apiGroup: rbac.authorization.k8s.io
EOF


kubelet的配置:在node节点上

创建目录:

mkdir /etc/kubernetes/cert -pv
mkdir /var/lib/kubelet -pv

从主节点拷贝ca证书到node节点:

scp /etc/kubernetes/cert/ca.crt root@192.168.1.138:/etc/kubernetes/cert/

创建bootstrap-kubeconfig文件:

kubectl config --kubeconfig=/etc/kubernetes/bootstrap-kubeconfig set-cluster bootstrap --server='https://192.168.1.133:6443' --certificate-authority=/etc/kubernetes/cert/ca.crt
kubectl config --kubeconfig=/etc/kubernetes/bootstrap-kubeconfig set-credentials kubelet-bootstrap --token=5e9e293d3b14c995bd7c1415c5e0c6c0
kubectl config --kubeconfig=/etc/kubernetes/bootstrap-kubeconfig set-context bootstrap --user=kubelet-bootstrap --cluster=bootstrap
kubectl config --kubeconfig=/etc/kubernetes/bootstrap-kubeconfig use-context bootstrap

创建 kubelet.service文件:

cat > /usr/lib/systemd/system/kubelet.service <<EOF
[Unit]
Description=Kubernetes kubelet Server
After=docker.service
Requires=docker.service

[Service]
WorkingDirectory=/var/lib/kubelet
ExecStart=/usr/bin/kubelet \\
--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubeconfig \\
--kubeconfig=/etc/kubernetes/kubeconfig \\
--cert-dir=/etc/kubernetes/cert/ \\
--rotate-certificates=true \\
--rotate-server-certificates=true

Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF

启动kubelet:

systemctl start kubelet.service

查看状态:

systemctl status kubelet.service

查看日志:

tail -f /var/log/messages

到主节点查看CSR请求:

[root@k8s-01 ~]# kubectl get csr
NAME        AGE     REQUESTOR            CONDITION
csr-dgftc   2m21s   kubelet-bootstrap    Approved,Issued
csr-gvj2j   22s     system:node:k8s-06   Pending

批准CSR请求:

[root@k8s-01 ~]# kubectl certificate approve csr-gvj2j
certificatesigningrequest.certificates.k8s.io/csr-gvj2j approved
[root@k8s-01 ~]# kubectl get csr
NAME        AGE    REQUESTOR            CONDITION
csr-dgftc   6m5s   kubelet-bootstrap    Approved,Issued
csr-gvj2j   4m6s   system:node:k8s-06   Approved,Issued

查看签署过来的证书:

[root@k8s-06 ~]# ll /etc/kubernetes/cert/
total 12
-rw-r--r-- 1 root root 1086 Oct 26 05:13 ca.crt
-rw------- 1 root root 1151 Oct 26 05:28 kubelet-client-2019-10-26-05-28-37.pem
lrwxrwxrwx 1 root root   59 Oct 26 05:28 kubelet-client-current.pem -> /etc/kubernetes/cert/kubelet-client-2019-10-26-05-28-37.pem
-rw------- 1 root root 1187 Oct 26 05:34 kubelet-server-2019-10-26-05-34-40.pem
lrwxrwxrwx 1 root root   59 Oct 26 05:34 kubelet-server-current.pem -> /etc/kubernetes/cert/kubelet-server-2019-10-26-05-34-40.pem

查看生成的配置文件:

[root@k8s-06 ~]# cat /etc/kubernetes/kubeconfig
apiVersion: v1
clusters:
- cluster:
    certificate-authority: /etc/kubernetes/cert/ca.crt
    server: https://192.168.1.133:6443
  name: default-cluster
contexts:
- context:
    cluster: default-cluster
    namespace: default
    user: default-auth
  name: default-context
current-context: default-context
kind: Config
preferences: {}
users:
- name: default-auth
  user:
    client-certificate: /etc/kubernetes/cert/kubelet-client-current.pem
    client-key: /etc/kubernetes/cert/kubelet-client-current.pem


配置kube-proxy:只需要配置--kubeconfig选项即可。

cat < /usr/lib/systemd/system/kube-proxy.service <<EOF
[Unit]
Description=Kubernetes Kube-Proxy Server
After=network.target
Requires=network.service

[Service]
WorkingDirectory=/var/lib/kubelet
ExecStart=/usr/bin/kube-proxy \\
--kubeconfig=/etc/kubernetes/kubeconfig

Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

启动kube-proxy:

systemctl start kube-proxy.service

查看状态:

systemctl status kube-proxy.service

查看新加进来的节点:

[root@k8s-01 ~]# kubectl get nodes
NAME     STATUS   ROLES    AGE    VERSION
k8s-02   Ready    <none>   141d   v1.14.2
k8s-03   Ready    <none>   141d   v1.14.2
k8s-06   Ready    <none>   14m    v1.14.2