目录
- 前言
- 创建 kubelet bootstrap kubeconfig 文件
- 查看kubeadm为各个节点创建的token
- 查看各 token 关联的 Secret
- 创建和分发kubelet参数配置
- 创建和分发kubelet启动文件
- 创建user和group的CSR权限,不创建kubelet会启动失败
- 启动 kubelet 服务
- 查看kubelet
- 手动approve server cert csr
前言
kubelet运行在每个worker节点上,接收kube-apiserver发送的请求,管理Pod容器,执行交互命令
kubelet启动时自动向kube-apiserver注册节点信息,内置的cAdivsor统计和监控节点的资源使用资源情况。为确保安全,部署时关闭了kubelet的非安全http端口,对请求进行认证和授权,拒绝未授权的访问
创建 kubelet bootstrap kubeconfig 文件
cd /opt/k8s/work
source /opt/k8s/bin/environment.sh
for node_name in ${NODE_NAMES[@]}
do
echo ">>> ${node_name}"
# 创建 token
export BOOTSTRAP_TOKEN=$(kubeadm token create \
--description kubelet-bootstrap-token \
--groups system:bootstrappers:${node_name} \
--kubeconfig ~/.kube/config)
# 设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/cert/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=kubelet-bootstrap-${node_name}.kubeconfig
# 设置客户端认证参数
kubectl config set-credentials kubelet-bootstrap \
--token=${BOOTSTRAP_TOKEN} \
--kubeconfig=kubelet-bootstrap-${node_name}.kubeconfig
# 设置上下文参数
kubectl config set-context default \
--cluster=kubernetes \
--user=kubelet-bootstrap \
--kubeconfig=kubelet-bootstrap-${node_name}.kubeconfig
# 设置默认上下文
kubectl config use-context default --kubeconfig=kubelet-bootstrap-${node_name}.kubeconfig
done
分发 bootstrap kubeconfig 文件到所有 worker 节点
cd /opt/k8s/work
source /opt/k8s/bin/environment.sh
for node_name in ${NODE_NAMES[@]}
do
echo ">>> ${node_name}"
scp kubelet-bootstrap-${node_name}.kubeconfig root@${node_name}:/etc/kubernetes/kubelet-bootstrap.kubeconfig
done
- 向kubeconfig写入的是token,bootstrap结束后kube-controller-manager为kubelet创建client和server证书
查看kubeadm为各个节点创建的token
[root@node01 work]# kubeadm token list --kubeconfig ~/.kube/config
TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS
cu4q2e.ogvim78s3p252ysg 23h 2019-12-06T17:44:24+08:00 authentication,signing kubelet-bootstrap-token system:bootstrappers:node03
nrypmb.35fyygbwr9failr5 23h 2019-12-06T17:44:23+08:00 authentication,signing kubelet-bootstrap-token system:bootstrappers:node01
r5luwb.6x6c5lnit5utyotz 23h 2019-12-06T17:44:23+08:00 authentication,signing kubelet-bootstrap-token system:bootstrappers:node02
sx8n4m.vlltkkv8m23ogxg9 23h 2019-12-06T17:44:24+08:00 authentication,signing kubelet-bootstrap-token system:bootstrappers:node04
- token有效期为1天,超期后将不能被用来bootstrap kubelet,且会被kube-controller-manager的token cleaner清理
- kube-apiserver接收kubelet的bootstrap token后,将请求的user设置为system:bootstrap; group设置为system:bootstrappers,后续将为这个group设置ClusterRoleBinding
查看各 token 关联的 Secret
[root@node01 work]# kubectl get secrets -n kube-system|grep bootstrap-token
bootstrap-token-cu4q2e bootstrap.kubernetes.io/token 7 33s
bootstrap-token-nrypmb bootstrap.kubernetes.io/token 7 34s
bootstrap-token-r5luwb bootstrap.kubernetes.io/token 7 34s
bootstrap-token-sx8n4m bootstrap.kubernetes.io/token 7 33s
创建和分发kubelet参数配置
cd /opt/k8s/work
source /opt/k8s/bin/environment.sh
cat > kubelet-config.yaml.template <
- address:kubelet 安全端口(https,10250)监听的地址,不能为 127.0.0.1,否则 kube-apiserver、heapster 等不能调用 kubelet 的 API;
- readOnlyPort=0:关闭只读端口(默认 10255),等效为未指定;
- authentication.anonymous.enabled:设置为 false,不允许匿名访问 10250 端口;
- authentication.x509.clientCAFile:指定签名客户端证书的 CA 证书,开启 HTTP 证书认证;
- authentication.webhook.enabled=true:开启 HTTPs bearer token 认证;
- 对于未通过 x509 证书和 webhook 认证的请求(kube-apiserver 或其他客户端),将被拒绝,提示 Unauthorized;
- authroization.mode=Webhook:kubelet 使用 SubjectAccessReview API 查询 kube-apiserver 某 user、group 是否具有操作资源的权限(RBAC);
- featureGates.RotateKubeletClientCertificate、featureGates.RotateKubeletServerCertificate:自动 rotate 证书,证书的有效期取决于 kube-controller-manager 的 –experimental-cluster-signing-duration 参数;
- 需要 root 账户运行;
为各个节点创建和分发kubelet配置文件
cd /opt/k8s/work
source /opt/k8s/bin/environment.sh
for node_ip in ${NODE_IPS[@]}
do
echo ">>> ${node_ip}"
sed -e "s/##NODE_IP##/${node_ip}/" kubelet-config.yaml.template > kubelet-config-${node_ip}.yaml.template
scp kubelet-config-${node_ip}.yaml.template root@${node_ip}:/etc/kubernetes/kubelet-config.yaml
done
创建和分发kubelet启动文件
cd /opt/k8s/work
source /opt/k8s/bin/environment.sh
cat > kubelet.service.template <
- 如果设置了 –hostname-override 选项,则 kube-proxy 也需要设置该选项,否则会出现找不到 Node 的情况;
- –bootstrap-kubeconfig:指向 bootstrap kubeconfig 文件,kubelet 使用该文件中的用户名和 token 向 kube-apiserver 发送 TLS Bootstrapping 请求;
- K8S approve kubelet 的 csr 请求后,在 –cert-dir 目录创建证书和私钥文件,然后写入 –kubeconfig 文件;
- –pod-infra-container-image 不使用 redhat 的 pod-infrastructure:latest 镜像,它不能回收容器的僵尸;
分发启动文件
d /opt/k8s/work
source /opt/k8s/bin/environment.sh
for node_name in ${NODE_NAMES[@]}
do
echo ">>> ${node_name}"
sed -e "s/##NODE_NAME##/${node_name}/" kubelet.service.template > kubelet-${node_name}.service
scp kubelet-${node_name}.service root@${node_name}:/etc/systemd/system/kubelet.service
done
Bootstrap Token Auth 和授予权限 kubelet 启动时查找 --kubeletconfig
参数对应的文件是否存在,如果不存在则使用 --bootstrap-kubeconfig 指定的 kubeconfig 文件向
kube-apiserver 发送证书签名请求 (CSR)。 kube-apiserver 收到 CSR 请求后,对其中的 Token
进行认证,认证通过后将请求的 user 设置为 system:bootstrap:,group 设置为
system:bootstrappers,这一过程称为 Bootstrap Token Auth。
创建user和group的CSR权限,不创建kubelet会启动失败
kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --group=system:bootstrappers
启动 kubelet 服务
source /opt/k8s/bin/environment.sh
for node_ip in ${NODE_IPS[@]}
do
echo ">>> ${node_ip}"
ssh root@${node_ip} "mkdir -p ${K8S_DIR}/kubelet/kubelet-plugins/volume/exec/"
ssh root@${node_ip} "/usr/sbin/swapoff -a"
ssh root@${node_ip} "systemctl daemon-reload && systemctl enable kubelet && systemctl restart kubelet"
done
关闭 swap 分区,否则 kubelet 会启动失败;
kubelet 启动后使用 –bootstrap-kubeconfig 向 kube-apiserver 发送 CSR 请求,当这个
CSR 被 approve 后,kube-controller-manager 为 kubelet 创建 TLS 客户端证书、私钥和
–kubeletconfig 文件。 注意:kube-controller-manager 需要配置 –cluster-signing-cert-file 和 –cluster-signing-key-file 参数,才会为 TLS Bootstrap 创建证书和私钥。
[root@node01 work]# kubectl get csr
NAME AGE REQUESTOR CONDITION
csr-5ttvq 2m6s system:bootstrap:r5luwb Pending
csr-gmt4v 2m5s system:bootstrap:cu4q2e Pending
csr-hhfw4 2m6s system:bootstrap:nrypmb Pending
csr-qpfp8 11s system:bootstrap:sx8n4m Pending
这里4个节点均处于pending(等待)状态
自动approve CSR请求
创建三个ClusterRoleBinding,分别用于自动approve client、renew client、renew server证书
cd /opt/k8s/work
cat > csr-crb.yaml <
- auto-approve-csrs-for-group 自动approve node的第一次CSR,注意第一次CSR时,请求的Group为system:bootstrappers
- node-client-cert-renewal 自动approve node后续过期的client证书,自动生成的证书Group为system:nodes
- node-server-cert-renewal 自动approve node后续过期的server证书,自动生成的证书Group
查看kubelet
等待1-10分钟,3个节点的CSR都会自动approved
[root@node01 work]# kubectl get csr
NAME AGE REQUESTOR CONDITION
csr-5ttvq 3m33s system:bootstrap:r5luwb Approved,Issued
csr-gmt4v 3m32s system:bootstrap:cu4q2e Approved,Issued
csr-hhfw4 3m33s system:bootstrap:nrypmb Approved,Issued
csr-lktrc 1s system:node:node01 Pending
csr-qpfp8 98s system:bootstrap:sx8n4m Approved,Issued
csr-s4q5h 102s system:bootstrap:sx8n4m Approved,Issued
csr-s7fds 1s system:node:node02 Pending
csr-wszxt 34s system:node:node04 Pending
Pending的CSR用于创建kubelet serve证书,需要手动approve (后面步骤)
目前所有节点均为ready状态
[root@node01 work]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
node01 Ready 26s v1.15.6
node02 Ready 26s v1.15.6
node03 Ready 25s v1.15.6
node04 Ready 59s v1.15.6
手动approve server cert csr
基于安全考虑,CSR approving controllers不会自动approve kubelet server证书签名请求,需要手动approve
kubectl get csr | grep Pending | awk '{print $1}' | xargs kubectl certificate approve
kubelet启动后监听多个端口,用于接受kube-apiserver或其他客户端发送的请求
[root@node01 work]# netstat -lntup|grep kubelet
tcp 0 0 127.0.0.1:36615 0.0.0.0:* LISTEN 10549/kubelet
tcp 0 0 10.0.20.11:10248 0.0.0.0:* LISTEN 10549/kubelet
tcp 0 0 10.0.20.11:10250 0.0.0.0:* LISTEN 10549/kubelet
- 10248: healthz http 服务;
- 10250: https 服务,访问该端口时需要认证和授权(即使访问 /healthz 也需要);
- 未开启只读端口 10255;
- 从 K8S v1.10 开始,去除了 –cadvisor-port 参数(默认 4194 端口),不支持访问 cAdvisor UI & API