Kubelet Bootstrap 机制 APIServer基于引导token认证

众所周知 TLS 的作用就是对通讯加密,防止中间人窃听;同时如果证书不信任的话根本就无法与 apiserver建立连接,更不用提有没有权限向 apiserver 请求指定内容。在开启了 TLS 的集群中,每当与集群交互的时候少不了的是身份认证,使用 kubeconfig(即证书) 和 token 两种认证方式是最简单也最通用的认证方式。
 

当集群开启了 TLS 认证后,每个节点的 kubelet 组件都要使用由 apiserver 使用的 CA 签发的有效证书才能与 apiserver 通讯。
 

此时如果节点多起来,为每个节点单独签署证书将是一件非常繁琐的事情;TLS bootstrapping 功能就是让 kubelet 先使用一个预定的低权限用户连接到 apiserver,然后向 apiserver 申请证书,kubelet 的证书由 apiserver 动态签署。
 

TLS Bootstrapping ,使用 Token 时整个启动引导过程:
1、在集群内创建特定的 Bootstrap Token Secret ,该 Secret 将替代以前的 token.csv 内置用户声明文件
2、在集群内创建首次 TLS Bootstrap 申请证书的 ClusterRole、后续 renew Kubelet client/server 的 ClusterRole,以及其相关对应的 ClusterRoleBinding;并绑定到对应的组或用户
3、调整 Controller Manager 配置,以使其能自动签署相关证书和自动清理过期的 TLS Bootstrapping Token
4、生成特定的包含 TLS Bootstrapping Token 的 bootstrap.kubeconfig 以供 kubelet 启动时使用
5、调整 Kubelet 配置,使其首次启动加载 bootstrap.kubeconfig 并使用其中的 TLS Bootstrapping Token 完成首次证书申请
6、证书被 Controller Manager 签署,成功下发,Kubelet 自动重载完成引导流程
7、后续 Kubelet 自动 renew 相关证书

kubeadm部署的如下所示:

--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.2

启用 TLS Bootstrapping 机制
TLS Bootstraping:Master apiserver启用TLS认证后,Node节点kubelet和kube-proxy要与kube-apiserver进行通信,必须使用CA签发的有效证书才可以当Node节点很多时,这种客户端证书颁发需要大量工作,同样也会增加集群扩展复杂度。

为了简化流程,Kubernetes引入了TLS bootstraping机制来自动颁发客户端证书,kubelet会以一个低权限用户自动向apiserver申请证书,kubelet的证书由apiserver动态签署。

所以强烈建议在Node上使用这种方式,目前主要用于kubelet,kube-proxy还是由我们统一颁发一个证书。(当机器越来越多的时候,手动的为kubelet颁发证书,还是比较麻烦的,应用这个机制就是为自动的为kubelet颁发证书)

TLS bootstraping 工作流程:

 创建上述配置文件中token文件:

cat > /opt/kubernetes/cfg/token.csv << EOF
c47ffb939f5ca36231d9e3121a252940,kubelet-bootstrap,10001,"system:node-bootstrapper"
EOF

格式:token,用户名,UID,用户组   这个是系统自带的用户组,主要就是让node使用strap颁发证书,低权限用户。

node上拿着这个token c47ffb939f5ca36231d9e3121a252940 请求过来,就会以最低权限颁发证书。

token也可自行生成替换:

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

授权kubelet-bootstrap用户允许请求证书 

要给这个用户授予权限 

[root@k8s-master logs]# kubectl get clusterrole
NAME                                                                   CREATED AT
 
system:node-bootstrapper                                               2022-03-25T12:33:52Z
kubectl create clusterrolebinding kubelet-bootstrap \
--clusterrole=system:node-bootstrapper \
--user=kubelet-bootstrap

部署kubelet
1. 创建配置文件

cat > /opt/kubernetes/cfg/kubelet.conf << EOF
KUBELET_OPTS="--logtostderr=false \\
--v=2 \\
--log-dir=/opt/kubernetes/logs \\
--hostname-override=k8s-master \\
--network-plugin=cni \\
--kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig \\
--bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig \\
--config=/opt/kubernetes/cfg/kubelet-config.yml \\
--cert-dir=/opt/kubernetes/ssl \\
--pod-infra-container-image=lizhenliang/pause-amd64:3.0"
EOF
  • –hostname-override:显示名称,集群中唯一
  • –network-plugin:启用CNI
  • –kubeconfig:空路径,会自动生成,后面用于连接apiserver
  • –bootstrap-kubeconfig:首次启动向apiserver申请证书
  • –config:配置参数文件
  • –cert-dir:kubelet证书生成目录
  • –pod-infra-container-image:管理Pod网络容器的镜像

这个文件也是生成的,并且将CA证书加载进来,主要用来连接apiserver。 

[root@k8s-master cfg]# pwd
/opt/kubernetes/cfg
[root@k8s-master cfg]# ls kubelet.kubeconfig 
kubelet.kubeconfig

以kubelet开头的都是自动生成的,主要使用  kubelet-client-current.pem  kubelet.crt  kubelet.key这三个证书

[root@k8s-master ssl]# ls kubelet*
kubelet-client-2022-03-25-21-23-51.pem  kubelet-client-current.pem  kubelet.crt  kubelet.key
[root@k8s-master ssl]# pwd
/opt/kubernetes/ssl

2. 配置参数文件 

cat > /opt/kubernetes/cfg/kubelet-config.yml << EOF
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: 0.0.0.0
port: 10250
readOnlyPort: 10255
cgroupDriver: cgroupfs
clusterDNS:
- 10.0.0.2
clusterDomain: cluster.local 
failSwapOn: false
authentication:
  anonymous:
    enabled: false
  webhook:
    cacheTTL: 2m0s
    enabled: true
  x509:
    clientCAFile: /opt/kubernetes/ssl/ca.pem 
authorization:
  mode: Webhook
  webhook:
    cacheAuthorizedTTL: 5m0s
    cacheUnauthorizedTTL: 30s
evictionHard:
  imagefs.available: 15%
  memory.available: 100Mi
  nodefs.available: 10%
  nodefs.inodesFree: 5%
maxOpenFiles: 1000000
maxPods: 110
EOF

 cgroupDriver: cgroupfs 要和docker info里面显示的驱动保持一致。

 3. 生成bootstrap.kubeconfig文件(为了解决,当kubelet很多的时候,为了避免手动颁发证书,引入tls机制,能够自动的为将要加入集群的node颁发证书。所有kubelet要链接apiserver都需要证书,要不然使用手签,要不然使用tls,这里使用tls,使用这个文件去连接apiserver,然后颁发证书,加入集群。)

KUBE_APISERVER="https://192.168.159.3:6443" # apiserver IP:PORT
TOKEN="c47ffb939f5ca36231d9e3121a252940" # 与token.csv里保持一致
 
# 生成 kubelet bootstrap kubeconfig 配置文件
kubectl config set-cluster kubernetes \
  --certificate-authority=/opt/kubernetes/ssl/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=bootstrap.kubeconfig
 
kubectl config set-credentials "kubelet-bootstrap" \
  --token=${TOKEN} \
  --kubeconfig=bootstrap.kubeconfig
 
kubectl config set-context default \
  --cluster=kubernetes \
  --user="kubelet-bootstrap" \
  --kubeconfig=bootstrap.kubeconfig
 
kubectl config use-context default --kubeconfig=bootstrap.kubeconfig
[root@k8s-master cfg]# cat bootstrap.kubeconfig 
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR2akNDQXFhZ0F3SUJBZ0lVY0tqQnBLWnBOWDBvd1FMZlZYYUhHMmlaYXJrd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1pURUxNQWtHQTFVRUJoTUNRMDR4RURBT0JnTlZCQWdUQjBKbGFXcHBibWN4RURBT0JnTlZCQWNUQjBKbAphV3BwYm1jeEREQUtCZ05WQkFvVEEyczRjekVQTUEwR0ExVUVDeE1HVTNsemRHVnRNUk13RVFZRFZRUURFd3ByCmRXSmxjbTVsZEdWek1CNFhEVEl5TURNeU5URXhOVGd3TUZvWERUSTNNRE15TkRFeE5UZ3dNRm93WlRFTE1Ba0cKQTFVRUJoTUNRMDR4RURBT0JnTlZCQWdUQjBKbGFXcHBibWN4RURBT0JnTlZCQWNUQjBKbGFXcHBibWN4RERBSwpCZ05WQkFvVEEyczRjekVQTUEwR0ExVUVDeE1HVTNsemRHVnRNUk13RVFZRFZRUURFd3ByZFdKbGNtNWxkR1Z6Ck1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBeUNRUlZTWmhHUnJaNEV6TjZVbGQKNE9nVFRGVDhjNU95MW1ka24wbVgxYmxDdFRGckNBZ0VQOGdyRTZGVWI1T0k5SU1na3JlUVVvSlVoTGtrVVBIaApURnBzcXA0cmgyVUlKVjJFZ3FPKzNpbUc4NWJtdjBPNE5hb3B2cThCQXZVREZKdWcxOHJYK2ZYeEx5VFE5V0tRCkpmUWNhVmQ4V2FYbWFrMHJhU0JEeDhtNUZpdjEvekV1YmlEZmVCUTJ0NFRvQllkd1k0MmpyN1k3VW95ZVExZlgKTndxUUpjTVFsS1h0c0ZwZGE5T2pycE5PcWkrZHBISXJXYkVBZGhYTkNJZy9odzBuNFJ4OTRFSU0yUVhTWUJOZApMZHpqamU4UFZPenAyVXpnYTZJZ294L3JXRVcvVnA5MTM0YlZGcU0veTJjajB6TnZzS2xJUEVnbENMUE92cUh5ClB3SURBUUFCbzJZd1pEQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0VnWURWUjBUQVFIL0JBZ3dCZ0VCL3dJQkFqQWQKQmdOVkhRNEVGZ1FVSjYzTXZVSlNPbzNDendOSWdsa3dIL2ozTnM0d0h3WURWUjBqQkJnd0ZvQVVKNjNNdlVKUwpPbzNDendOSWdsa3dIL2ozTnM0d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFJdG1ha3M4cy9hYnhSc1Z5NHhmClhEVzlaeHNObFp2dzc2YnhxeTYvem56RW5UV0JyMHdpV0tmRXFtbk5xNE8rdnZxT1hVQklSMVBaamVYY3FYNlIKN2dlMWRmRGE3dVNqNFdYU2tONS9xbG5xMkNKVGxteVFKQUdHcTZpdnIzQ2ppQ0FKWlU4Z0FRTkg0Q2hJc0NlcwpXMy9HQjZ4a2xFdkkydm5pS2w4MEFxK0tXcXg2c0xCbmIrTlFiOW1zOStRN250ZDBveFBOK04wcnpOZ0JVUUwvCldsUUw0b1ZLWDN2VElqVzlEVkRrdVh0YjdzbzJkZ2JXM3FxRy9scUhDb1NYZ3c5bjdab2c0MmNqS0VOSUc5R1AKMnlWUmlMUHRjRVlOYStybXJ2SytncTZ0WWc2MTM4OXpIbXBxY0FvQW1kYVZQUTlsQzlSK1IweVNGNkZmenJmaQpJWG89Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
    server: https://192.168.111.3:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubelet-bootstrap
  name: default
current-context: default
kind: Config
preferences: {}
users:
- name: kubelet-bootstrap
  user:
    token: c47ffb939f5ca36231d9e3121a252940
users:
- name: kubelet-bootstrap
  user:
    token: c47ffb939f5ca36231d9e3121a252940

上面这个就是通过kubectl config生成的文件,指定了CA的证书,token要保持一致,因为是用token来请求的。

拷贝到配置文件路径:

cp bootstrap.kubeconfig /opt/kubernetes/cfg

当你启动kubelet,它就会拿着bootstrap.kubeconfig向apiserver发起请求,apiserver会去验证这个token是不是可信任的,是否有权限,ca证书是不是正确的,通过之后才会为其颁发证书,最后kubelet就启动成功了。

4. systemd管理kubelet

cat > /usr/lib/systemd/system/kubelet.service << EOF
[Unit]
Description=Kubernetes Kubelet
After=docker.service
 
[Service]
EnvironmentFile=/opt/kubernetes/cfg/kubelet.conf
ExecStart=/opt/kubernetes/bin/kubelet \$KUBELET_OPTS
Restart=on-failure
LimitNOFILE=65536
 
[Install]
WantedBy=multi-user.target
EOF

5. 启动并设置开机启动

systemctl daemon-reload
systemctl start kubelet
systemctl enable kubelet

6. 批准kubelet证书申请并加入集群

# 查看kubelet证书请求
kubectl get csr
NAME                                                   AGE    SIGNERNAME                                    REQUESTOR           CONDITION
node-csr-uCEGPOIiDdlLODKts8J658HrFq9CZ--K6M4G7bjhk8A   6m3s   kubernetes.io/kube-apiserver-client-kubelet   kubelet-bootstrap   Pending
 
# 批准申请
kubectl certificate approve node-csr-uCEGPOIiDdlLODKts8J658HrFq9CZ--K6M4G7bjhk8A
 
# 查看节点
kubectl get node
NAME         STATUS     ROLES    AGE   VERSION
k8s-master   NotReady   <none>   7s    v1.18.3

 注:由于网络插件还没有部署,节点会没有准备就绪 NotReady

I0327 21:48:51.905063    2254 bootstrap.go:115] Kubeconfig /opt/kubernetes/cfg/kubelet.kubeconfig exists and is valid, skipping bootstrap
I0327 21:48:51.923413    2254 dynamic_cafile_content.go:129] Loaded a new CA Bundle and Verifier for "client-ca-bundle::/opt/kubernetes/ssl/ca.pem"
I0327 21:48:51.924452    2254 manager.go:146] cAdvisor running in container: "/sys/fs/cgroup/cpu,cpuacct/system.slice/kubelet.service"
I0327 21:48:52.007848    2254 fs.go:125] Filesystem UUIDs: map[23612460-2ba4-4f9b-8e6f-74e23f32fd35:/dev/dm-0 a3e099f4-0adb-49e8-9862-98593c721741:/dev/sda1 c7c91808-9ff6-49bd-bcd9-2f77af693db9:/dev/dm-1]

最后文件内容如下 

[root@k8s-master cfg]# cat kubelet.kubeconfig 
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR2akNDQXFhZ0F3SUJBZ0lVY0tqQnBLWnBOWDBvd1FMZlZYYUhHMmlaYXJrd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1pURUxNQWtHQTFVRUJoTUNRMDR4RURBT0JnTlZCQWdUQjBKbGFXcHBibWN4RURBT0JnTlZCQWNUQjBKbAphV3BwYm1jeEREQUtCZ05WQkFvVEEyczRjekVQTUEwR0ExVUVDeE1HVTNsemRHVnRNUk13RVFZRFZRUURFd3ByCmRXSmxjbTVsZEdWek1CNFhEVEl5TURNeU5URXhOVGd3TUZvWERUSTNNRE15TkRFeE5UZ3dNRm93WlRFTE1Ba0cKQTFVRUJoTUNRMDR4RURBT0JnTlZCQWdUQjBKbGFXcHBibWN4RURBT0JnTlZCQWNUQjBKbGFXcHBibWN4RERBSwpCZ05WQkFvVEEyczRjekVQTUEwR0ExVUVDeE1HVTNsemRHVnRNUk13RVFZRFZRUURFd3ByZFdKbGNtNWxkR1Z6Ck1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBeUNRUlZTWmhHUnJaNEV6TjZVbGQKNE9nVFRGVDhjNU95MW1ka24wbVgxYmxDdFRGckNBZ0VQOGdyRTZGVWI1T0k5SU1na3JlUVVvSlVoTGtrVVBIaApURnBzcXA0cmgyVUlKVjJFZ3FPKzNpbUc4NWJtdjBPNE5hb3B2cThCQXZVREZKdWcxOHJYK2ZYeEx5VFE5V0tRCkpmUWNhVmQ4V2FYbWFrMHJhU0JEeDhtNUZpdjEvekV1YmlEZmVCUTJ0NFRvQllkd1k0MmpyN1k3VW95ZVExZlgKTndxUUpjTVFsS1h0c0ZwZGE5T2pycE5PcWkrZHBISXJXYkVBZGhYTkNJZy9odzBuNFJ4OTRFSU0yUVhTWUJOZApMZHpqamU4UFZPenAyVXpnYTZJZ294L3JXRVcvVnA5MTM0YlZGcU0veTJjajB6TnZzS2xJUEVnbENMUE92cUh5ClB3SURBUUFCbzJZd1pEQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0VnWURWUjBUQVFIL0JBZ3dCZ0VCL3dJQkFqQWQKQmdOVkhRNEVGZ1FVSjYzTXZVSlNPbzNDendOSWdsa3dIL2ozTnM0d0h3WURWUjBqQkJnd0ZvQVVKNjNNdlVKUwpPbzNDendOSWdsa3dIL2ozTnM0d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFJdG1ha3M4cy9hYnhSc1Z5NHhmClhEVzlaeHNObFp2dzc2YnhxeTYvem56RW5UV0JyMHdpV0tmRXFtbk5xNE8rdnZxT1hVQklSMVBaamVYY3FYNlIKN2dlMWRmRGE3dVNqNFdYU2tONS9xbG5xMkNKVGxteVFKQUdHcTZpdnIzQ2ppQ0FKWlU4Z0FRTkg0Q2hJc0NlcwpXMy9HQjZ4a2xFdkkydm5pS2w4MEFxK0tXcXg2c0xCbmIrTlFiOW1zOStRN250ZDBveFBOK04wcnpOZ0JVUUwvCldsUUw0b1ZLWDN2VElqVzlEVkRrdVh0YjdzbzJkZ2JXM3FxRy9scUhDb1NYZ3c5bjdab2c0MmNqS0VOSUc5R1AKMnlWUmlMUHRjRVlOYStybXJ2SytncTZ0WWc2MTM4OXpIbXBxY0FvQW1kYVZQUTlsQzlSK1IweVNGNkZmenJmaQpJWG89Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
    server: https://192.168.111.3: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: /opt/kubernetes/ssl/kubelet-client-current.pem
    client-key: /opt/kubernetes/ssl/kubelet-client-current.pem

新增加Worker Node 


在master节点将Worker Node涉及文件拷贝到新节点

[root@k8s-master ~]# scp -r /opt/kubernetes root@192.168.111.6:/opt/


[root@k8s-master ~]# scp -r /usr/lib/systemd/system/{kubelet,kube-proxy}.service root@192.168.111.6:/usr/lib/systemd/system


[root@k8s-master ~]# scp -r /opt/cni/ root@192.168.111.6:/opt/

在新的worker节点上删除kubelet证书和kubeconfig文件

[root@k8s-node3 ~]#rm -rf /opt/kubernetes/cfg/kubelet.kubeconfig 

[root@k8s-node3 ~]#rm -rf /opt/kubernetes/ssl/kubelet*

 注:这几个文件是证书申请审批后自动生成的,每个Node不同,必须删除重新生成。

修改主机名

[root@k8s-node3 ~]# vim /opt/kubernetes/cfg/kubelet.conf
--hostname-override=k8s-node1

[root@k8s-node3 ~]# vim /opt/kubernetes/cfg/kube-proxy-config.yml
hostnameOverride: k8s-node3

 启动并设置开机启动

systemctl daemon-reload
systemctl start kubelet
systemctl enable kubelet
systemctl start kube-proxy
systemctl enable kube-proxy

 在Master上批准新Node kubelet证书申请

kubectl get csr
NAME                                                   AGE   SIGNERNAME                                    REQUESTOR           CONDITION
node-csr-4zTjsaVSrhuyhIGqsefxzVoZDCNKei-aE2jyTP81Uro   89s   kubernetes.io/kube-apiserver-client-kubelet   kubelet-bootstrap   Pending

kubectl certificate approve node-csr-4zTjsaVSrhuyhIGqsefxzVoZDCNKei-aE2jyTP81Uro

Node 的扩容


在实际生产系统中经常会 现服务器容址不足的情况, 这时就需要购买新的服务器, 然后将应用系统进行水平扩展来完成对系统的扩容。

在Kubern etes 集群 ,一个新 Node 入是非常简单的。在新的 Node 上安装 do cker ku be let kube -p roxy  服务,然后配置 k ubelet   kube-prox 服务的启动参数,将 Mast er URL

指定为当前 Kubernetes 集群 Maste 的地址, 最后启动这些服务。通过 kubelet 服务默认的自动注册机制,新的 Node 将自动加入现有的 Kubernetes 集群中,如图所示:

Kubernetes Master 在接受新 Node 的注册之后,会自动将其纳入当前集群的调度范围, 之后创建容器时就可以对新的 Node 进行调度了,通过这种机制, Kubernetes 实现了集群中 Node 的扩容。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值