015.Kubernetes二进制部署所有节点kubelet

一部署 kubelet

kubelet 运行在每个 worker 节点上,接收 kube-apiserver 发送的请求,管理 Pod 容器,执行交互式命令,如 exec、run、logs 等。
kubelet 启动时自动向 kube-apiserver 注册节点信息,内置的 cadvisor 统计和监控节点的资源使用情况。
为确保安全,部署时关闭了 kubelet 的非安全 http 端口,对请求进行认证和授权,拒绝未授权的访问(如 apiserver、heapster 的请求)。

1.1安装kubelet

提示:k8smaster01节点已下载相应二进制,可直接分发至node节点。

1.2分发kubelet

1 [root@k8smaster01 ~]# cd /opt/k8s/work  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh  3 [root@k8smaster01 work]# for all_ip in ${ALL_IPS[@]}  4   do  5     echo ">>> ${all_ip}"  6     scp kubernetes/server/bin/kubelet root@${all_ip}:/opt/k8s/bin/  7     ssh root@${all_ip} "chmod +x /opt/k8s/bin/*"  8   done

1.3分发kubeconfig

1 [root@k8smaster01 ~]# cd /opt/k8s/work  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh  3 [root@k8smaster01 work]# for all_name in ${ALL_NAMES[@]}  4   do  5     echo ">>> ${all_name}"  6   7     # 创建 token  8     export BOOTSTRAP_TOKEN=$(kubeadm token create   9       --description kubelet-bootstrap-token  10       --groups system:bootstrappers:${all_name}  11       --kubeconfig ~/.kube/config) 12  13     # 设置集群参数 14     kubectl config set-cluster kubernetes  15       --certificate-authority=/etc/kubernetes/cert/ca.pem  16       --embed-certs=true  17       --server=${KUBE_APISERVER}  18       --kubeconfig=kubelet-bootstrap-${all_name}.kubeconfig 19  20     # 设置客户端认证参数 21     kubectl config set-credentials kubelet-bootstrap  22       --token=${BOOTSTRAP_TOKEN}  23       --kubeconfig=kubelet-bootstrap-${all_name}.kubeconfig 24  25     # 设置上下文参数 26     kubectl config set-context default  27       --cluster=kubernetes  28       --user=kubelet-bootstrap  29       --kubeconfig=kubelet-bootstrap-${all_name}.kubeconfig 30  31     # 设置默认上下文 32     kubectl config use-context default --kubeconfig=kubelet-bootstrap-${all_name}.kubeconfig 33   done
解释:
向 kubeconfig 写入的是 token,bootstrap 结束后 kube-controller-manager 为 kubelet 创建 client 和 server 证书。
token 有效期为 1 天,超期后将不能再被用来 boostrap kubelet,且会被 kube-controller-manager 的 tokencleaner 清理;
kube-apiserver 接收 kubelet 的 bootstrap token 后,将请求的 user 设置为 system:bootstrap:<Token ID>,group 设置为 system:bootstrappers,后续将为这个 group 设置 ClusterRoleBinding。
1 [root@k8smaster01 work]# kubeadm token list --kubeconfig ~/.kube/config#查看 kubeadm 为各节点创建的 token  2 [root@k8smaster01 work]# kubectl get secrets  -n kube-system|grep bootstrap-token#查看各 token 关联的 Secret

1.5分发bootstrap kubeconfig

1 [root@k8smaster01 ~]# cd /opt/k8s/work  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh  3 [root@k8smaster01 work]# for all_name in ${ALL_NAMES[@]}  4   do  5     echo ">>> ${all_name}"  6     scp kubelet-bootstrap-${all_name}.kubeconfig root@${all_name}:/etc/kubernetes/kubelet-bootstrap.kubeconfig  7   done

1.6创建kubelet 参数配置文件

从 v1.10 开始,部分 kubelet 参数需在配置文件中配置,建议创建kubelet配置文件。
1 [root@k8smaster01 ~]# cd /opt/k8s/work  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh  3 [root@k8smaster01 work]# cat > kubelet-config.yaml.template <<EOF  4 kind: KubeletConfiguration  5 apiVersion: kubelet.config.k8s.io/v1beta1  6 address: "##ALL_IP##"  7 staticPodPath: ""  8 syncFrequency: 1m  9 fileCheckFrequency: 20s 10 httpCheckFrequency: 20s 11 staticPodURL: "" 12 port: 10250 13 readOnlyPort: 0 14 rotateCertificates: true 15 serverTLSBootstrap: true 16 authentication: 17   anonymous: 18     enabled: false 19   webhook: 20     enabled: true 21   x509: 22     clientCAFile: "/etc/kubernetes/cert/ca.pem" 23 authorization: 24   mode: Webhook 25 registryPullQPS: 0 26 registryBurst: 20 27 eventRecordQPS: 0 28 eventBurst: 20 29 enableDebuggingHandlers: true 30 enableContentionProfiling: true 31 healthzPort: 10248 32 healthzBindAddress: "##ALL_IP##" 33 clusterDomain: "${CLUSTER_DNS_DOMAIN}" 34 clusterDNS: 35   - "${CLUSTER_DNS_SVC_IP}" 36 nodeStatusUpdateFrequency: 10s 37 nodeStatusReportFrequency: 1m 38 imageMinimumGCAge: 2m 39 imageGCHighThresholdPercent: 85 40 imageGCLowThresholdPercent: 80 41 volumeStatsAggPeriod: 1m 42 kubeletCgroups: "" 43 systemCgroups: "" 44 cgroupRoot: "" 45 cgroupsPerQOS: true 46 cgroupDriver: cgroupfs 47 runtimeRequestTimeout: 10m 48 hairpinMode: promiscuous-bridge 49 maxPods: 220 50 podCIDR: "${CLUSTER_CIDR}" 51 podPidsLimit: -1 52 resolvConf: /etc/resolv.conf 53 maxOpenFiles: 1000000 54 kubeAPIQPS: 1000 55 kubeAPIBurst: 2000 56 serializeImagePulls: false 57 evictionHard: 58   memory.available:  "100Mi" 59 nodefs.available:  "10%" 60 nodefs.inodesFree: "5%" 61 imagefs.available: "15%" 62 evictionSoft: {} 63 enableControllerAttachDetach: true 64 failSwapOn: true 65 containerLogMaxSize: 20Mi 66 containerLogMaxFiles: 10 67 systemReserved: {} 68 kubeReserved: {} 69 systemReservedCgroup: "" 70 kubeReservedCgroup: "" 71 enforceNodeAllocatable: ["pods"] 72 EOF

1.7分发kubelet 参数配置文件

1 [root@k8smaster01 ~]# cd /opt/k8s/work  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh  3 [root@k8smaster01 work]# for all_ip in ${ALL_IPS[@]}  4   do  5     echo ">>> ${all_ip}"  6     sed -e "s/##ALL_IP##/${all_ip}/" kubelet-config.yaml.template > kubelet-config-${all_ip}.yaml.template  7     scp kubelet-config-${all_ip}.yaml.template root@${all_ip}:/etc/kubernetes/kubelet-config.yaml  8   done

1.8创建kubelet systemd

1 [root@k8smaster01 ~]# cd /opt/k8s/work  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh  3 [root@k8smaster01 work]# cat > kubelet.service.template <<EOF  4 [Unit]  5 Description=Kubernetes Kubelet  6 Documentation=https://github.com/GoogleCloudPlatform/kubernetes  7 After=docker.service  8 Requires=docker.service  9  10 [Service] 11 WorkingDirectory=${K8S_DIR}/kubelet 12 ExecStart=/opt/k8s/bin/kubelet \ 13   --allow-privileged=true \ 14   --bootstrap-kubeconfig=/etc/kubernetes/kubelet-bootstrap.kubeconfig \ 15   --cert-dir=/etc/kubernetes/cert \ 16   --cni-conf-dir=/etc/cni/net.d \ 17   --container-runtime=docker \ 18   --container-runtime-endpoint=unix:///var/run/dockershim.sock \\ 19   --root-dir=${K8S_DIR}/kubelet \ 20   --kubeconfig=/etc/kubernetes/kubelet.kubeconfig \ 21   --config=/etc/kubernetes/kubelet-config.yaml \ 22   --hostname-override=##ALL_NAME## \ 23   --pod-infra-container-image=registry.cn-beijing.aliyuncs.com/k8s_images/pause-amd64:3.1 \ 24   --image-pull-progress-deadline=15m \ 25   --volume-plugin-dir=${K8S_DIR}/kubelet/kubelet-plugins/volume/exec/ \ 26   --logtostderr=true \ 27   --v=2 28 Restart=always 29 RestartSec=5 30 StartLimitInterval=0 31  32 [Install] 33 WantedBy=multi-user.target 34 EOF
解释:
  • 如果设置了 --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 镜像,它不能回收容器的僵尸。

1.9分发kubelet systemd

1 [root@k8smaster01 ~]# cd /opt/k8s/work  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh  3 [root@k8smaster01 work]# for all_name in ${ALL_NAMES[@]}  4   do  5     echo ">>> ${all_name}"  6     sed -e "s/##ALL_NAME##/${all_name}/" kubelet.service.template > kubelet-${all_name}.service  7     scp kubelet-${all_name}.service root@${all_name}:/etc/systemd/system/kubelet.service  8   done

二启动验证

2.1授权

kubelet 启动时查找 --kubeletconfig 参数对应的文件是否存在,如果不存在则使用 --bootstrap-kubeconfig 指定的 kubeconfig 文件向 kube-apiserver 发送证书签名请求 (CSR)。
kube-apiserver 收到 CSR 请求后,对其中的 Token 进行认证,认证通过后将请求的 user 设置为 system:bootstrap:<Token ID>,group 设置为 system:bootstrappers,这一过程称为 Bootstrap Token Auth。
默认情况下,这个 user 和 group 没有创建 CSR 的权限,因此kubelet 会启动失败,可通过如下方式创建一个 clusterrolebinding,将 group system:bootstrappers 和 clusterrole system:node-bootstrapper 绑定。
1 [root@k8smaster01 ~]#  kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --group=system:bootstrappers

2.2启动kubelet

1 [root@k8smaster01 ~]# source /opt/k8s/bin/environment.sh  2 [root@k8smaster01 ~]# for all_name in ${ALL_NAMES[@]}  3   do  4     echo ">>> ${all_name}"  5     ssh root@${all_name} "mkdir -p ${K8S_DIR}/kubelet/kubelet-plugins/volume/exec/"  6     ssh root@${all_name} "/usr/sbin/swapoff -a"  7     ssh root@${all_name} "systemctl daemon-reload && systemctl enable kubelet && systemctl restart kubelet"  8   done
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 创建证书和私钥。
提示:
启动服务前必须先创建工作目录;
关闭 swap 分区,否则 kubelet 会启动失败。

2.3查看kubelet服务

1 [root@k8smaster01 ~]# source /opt/k8s/bin/environment.sh  2 [root@k8smaster01 ~]# for all_name in ${ALL_NAMES[@]}  3   do  4     echo ">>> ${all_name}"  5     ssh root@${all_name} "systemctl status kubelet"  6   done  7 [root@k8snode01 ~]# kubectl get csr  8 [root@k8snode01 ~]# kubectl get nodes

三approve CSR 请求

3.1自动 approve CSR 请求

创建三个 ClusterRoleBinding,分别用于自动 approve client、renew client、renew server 证书。
1 [root@k8snode01 ~]# cd /opt/k8s/work  2 [root@k8snode01 work]# cat > csr-crb.yaml <<EOF  3  # Approve all CSRs for the group "system:bootstrappers"  4  kind: ClusterRoleBinding  5  apiVersion: rbac.authorization.k8s.io/v1  6  metadata:  7    name: auto-approve-csrs-for-group  8  subjects:  9  - kind: Group 10    name: system:bootstrappers 11    apiGroup: rbac.authorization.k8s.io 12  roleRef: 13    kind: ClusterRole 14    name: system:certificates.k8s.io:certificatesigningrequests:nodeclient 15    apiGroup: rbac.authorization.k8s.io 16 --- 17  # To let a node of the group "system:nodes" renew its own credentials 18  kind: ClusterRoleBinding 19  apiVersion: rbac.authorization.k8s.io/v1 20  metadata: 21    name: node-client-cert-renewal 22  subjects: 23  - kind: Group 24    name: system:nodes 25    apiGroup: rbac.authorization.k8s.io 26  roleRef: 27    kind: ClusterRole 28    name: system:certificates.k8s.io:certificatesigningrequests:selfnodeclient 29    apiGroup: rbac.authorization.k8s.io 30 --- 31 # A ClusterRole which instructs the CSR approver to approve a node requesting a 32 # serving cert matching its client cert. 33 kind: ClusterRole 34 apiVersion: rbac.authorization.k8s.io/v1 35 metadata: 36   name: approve-node-server-renewal-csr 37 rules: 38 - apiGroups: ["certificates.k8s.io"] 39   resources: ["certificatesigningrequests/selfnodeserver"] 40   verbs: ["create"] 41 --- 42  # To let a node of the group "system:nodes" renew its own server credentials 43  kind: ClusterRoleBinding 44  apiVersion: rbac.authorization.k8s.io/v1 45  metadata: 46    name: node-server-cert-renewal 47  subjects: 48  - kind: Group 49    name: system:nodes 50    apiGroup: rbac.authorization.k8s.io 51  roleRef: 52    kind: ClusterRole 53    name: approve-node-server-renewal-csr 54    apiGroup: rbac.authorization.k8s.io 55 EOF 56 [root@k8snode01 work]# kubectl apply -f 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 为 system:nodes。

3.2查看 kubelet 的情况

1 [root@k8snode01 ~]# kubectl get csr | grep boot#等待一段时间(1-10 分钟),三个节点的 CSR 都被自动 approved  2 [root@k8snode01 ~]# kubectl get nodes#所有节点均 ready  3 [root@k8snode01 ~]# ls -l /etc/kubernetes/kubelet.kubeconfig  4 [root@k8snode01 ~]# ls -l /etc/kubernetes/cert/|grep kubelet

3.3手动 approve server cert csr

基于安全性考虑,CSR approving controllers 不会自动 approve kubelet server 证书签名请求,需要手动 approve。
1 [root@k8smaster01 ~]# kubectl get csr  2 [root@k8smaster01 ~]# kubectl certificate approve csr-2kmtj  3
1 [root@k8smaster01 ~]# ls -l /etc/kubernetes/cert/kubelet-*

四kubelet API 接口

4.1kubelet 提供的 API 接口

1 [root@k8smaster01 ~]# sudo netstat -lnpt|grep kubelet#查看kubelet监听端口
解释:
  • 10248: healthz http 服务;
  • 10250: https 服务,访问该端口时需要认证和授权(即使访问 /healthz 也需要);
  • 未开启只读端口 10255;
  • 从 K8S v1.10 开始,去除了 --cadvisor-port 参数(默认 4194 端口),不支持访问 cAdvisor UI & API。

4.2kubelet api 认证和授权

kubelet 配置了如下认证参数:
  • authentication.anonymous.enabled:设置为 false,不允许匿名�访问 10250 端口;
  • authentication.x509.clientCAFile:指定签名客户端证书的 CA 证书,开启 HTTPs 证书认证;
  • authentication.webhook.enabled=true:开启 HTTPs bearer token 认证。
同时配置了如下授权参数:
authroization.mode=Webhook:开启 RBAC 授权。
kubelet 收到请求后,使用 clientCAFile 对证书签名进行认证,或者查询 bearer token 是否有效。如果两者都没通过,则拒绝请求,提示 Unauthorized。
1 [root@k8smaster01 ~]# curl -s --cacert /etc/kubernetes/cert/ca.pem https://172.24.8.71:10250/metrics     2 Unauthorized[root@k8smaster01 ~]#  3 [root@k8smaster01 ~]# curl -s --cacert /etc/kubernetes/cert/ca.pem -H "Authorization: Bearer 123456" https://172.24.8.71:10250/metrics     4 Unauthorized
若通过认证后,kubelet 使用 SubjectAccessReview API 向 kube-apiserver 发送请求,查询证书或 token 对应的 user、group 是否有操作资源的权限(RBAC)。

4.3证书认证和授权

1 [root@k8smaster01 ~]# curl -s --cacert /etc/kubernetes/cert/ca.pem --cert /etc/kubernetes/cert/kube-controller-manager.pem --key /etc/kubernetes/cert/kube-controller-manager-key.pem https://172.24.8.71:10250/metrics#默认权限不足  2 Forbidden (user=system:kube-controller-manager, verb=get, resource=nodes, subresource=metrics)  3 curl -s --cacert /etc/kubernetes/cert/ca.pem --cert /opt/k8s/work/admin.pem --key /opt/k8s/work/admin-key.pem https://172.24.8.71:10250/metrics|head#使用最高权限的admin
解释:
--cacert、--cert、--key 的参数值必须是文件路径,如上面的 ./admin.pem 不能省略 ./,否则返回 401 Unauthorized。

4.4创建bear token 认证和授权

1 [root@k8smaster01 ~]# kubectl create sa kubelet-api-test  2 [root@k8smaster01 ~]# kubectl create clusterrolebinding kubelet-api-test --clusterrole=system:kubelet-api-admin --serviceaccount=default:kubelet-api-test  3 [root@k8smaster01 ~]# SECRET=$(kubectl get secrets | grep kubelet-api-test | awk '{print $1}')  4 [root@k8smaster01 ~]# TOKEN=$(kubectl describe secret ${SECRET} | grep -E '^token' | awk '{print $2}')  5 [root@k8smaster01 ~]# echo ${TOKEN}
1 [root@k8smaster01 ~]# curl -s --cacert /etc/kubernetes/cert/ca.pem -H "Authorization: Bearer ${TOKEN}" https://172.24.8.71:10250/metrics|head

4.5cadvisor 和 metrics

cadvisor 是内嵌在 kubelet 二进制中的,统计所在节点各容器的资源(CPU、内存、磁盘、网卡)使用情况的服务。
浏览器访问 https://172.24.8.71:10250/metrics 和 https://172.24.8.71:10250/metrics/cadvisor 分别返回 kubelet 和 cadvisor 的 metrics。
注意:
kubelet.config.json 设置 authentication.anonymous.enabled 为 false,不允许匿名证书访问 10250 的 https 服务;
参考https://github.com/opsnull/follow-me-install-kubernetes-cluster/blob/master/A.%E6%B5%8F%E8%A7%88%E5%99%A8%E8%AE%BF%E9%97%AEkube-apiserver%E5%AE%89%E5%85%A8%E7%AB%AF%E5%8F%A3.md,创建和导入相关证书,然后访问上面的 10250 端口。
(0)

相关推荐