前言

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 <<EOF
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: "##NODE_IP##"
staticPodPath: ""
syncFrequency: 1m
fileCheckFrequency: 20s
httpCheckFrequency: 20s
staticPodURL: ""
port: 10250
readOnlyPort: 0
rotateCertificates: true
serverTLSBootstrap: true
authentication:
anonymous:
enabled: false
webhook:
enabled: true
x509:
clientCAFile: "/etc/kubernetes/cert/ca.pem"
authorization:
mode: Webhook
registryPullQPS: 0
registryBurst: 20
eventRecordQPS: 0
eventBurst: 20
enableDebuggingHandlers: true
enableContentionProfiling: true
healthzPort: 10248
healthzBindAddress: "##NODE_IP##"
clusterDomain: "${CLUSTER_DNS_DOMAIN}"
clusterDNS:
- "${CLUSTER_DNS_SVC_IP}"
nodeStatusUpdateFrequency: 10s
nodeStatusReportFrequency: 1m
imageMinimumGCAge: 2m
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
volumeStatsAggPeriod: 1m
kubeletCgroups: ""
systemCgroups: ""
cgroupRoot: ""
cgroupsPerQOS: true
cgroupDriver: systemd
runtimeRequestTimeout: 10m
hairpinMode: promiscuous-bridge
maxPods: 220
podCIDR: "${CLUSTER_CIDR}"
podPidsLimit: -1
resolvConf: /etc/resolv.conf
maxOpenFiles: 1000000
kubeAPIQPS: 1000
kubeAPIBurst: 2000
serializeImagePulls: false
evictionHard:
memory.available: "100Mi"
nodefs.available: "10%"
nodefs.inodesFree: "5%"
imagefs.available: "15%"
evictionSoft: {}
enableControllerAttachDetach: true
failSwapOn: true
containerLogMaxSize: 20Mi
containerLogMaxFiles: 10
systemReserved: {}
kubeReserved: {}
systemReservedCgroup: ""
kubeReservedCgroup: ""
enforceNodeAllocatable: ["pods"]
EOF
  • 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 <<EOF
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=docker.service
Requires=docker.service
[Service]
WorkingDirectory=${K8S_DIR}/kubelet
ExecStart=/opt/k8s/bin/kubelet \\
--bootstrap-kubeconfig=/etc/kubernetes/kubelet-bootstrap.kubeconfig \\
--cert-dir=/etc/kubernetes/cert \\
--cni-conf-dir=/etc/cni/net.d \\
--container-runtime=docker \\
--container-runtime-endpoint=unix:///var/run/dockershim.sock \\
--root-dir=${K8S_DIR}/kubelet \\
--kubeconfig=/etc/kubernetes/kubelet.kubeconfig \\
--config=/etc/kubernetes/kubelet-config.yaml \\
--hostname-override=##NODE_NAME## \\
--pod-infra-container-image=gcr.azk8s.cn/google_containers/pause-amd64:3.1 \\
--image-pull-progress-deadline=15m \\
--volume-plugin-dir=${K8S_DIR}/kubelet/kubelet-plugins/volume/exec/ \\
--logtostderr=true \\
--v=2
Restart=always
RestartSec=5
StartLimitInterval=0
[Install]
WantedBy=multi-user.target
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 镜像,它不能回收容器的僵尸;

分发启动文件

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 <<EOF
# Approve all CSRs for the group "system:bootstrappers"
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
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
---
# To let a node of the group "system:nodes" renew its own credentials
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: node-client-cert-renewal
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
---
# A ClusterRole which instructs the CSR approver to approve a node requesting a
# serving cert matching its client cert.
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: approve-node-server-renewal-csr
rules:
- apiGroups: ["certificates.k8s.io"]
resources: ["certificatesigningrequests/selfnodeserver"]
verbs: ["create"]
---
# To let a node of the group "system:nodes" renew its own server credentials
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: node-server-cert-renewal
subjects:
- kind: Group
name: system:nodes
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: approve-node-server-renewal-csr
apiGroup: rbac.authorization.k8s.io
EOF 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

查看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 <none> 26s v1.15.6
node02 Ready <none> 26s v1.15.6
node03 Ready <none> 25s v1.15.6
node04 Ready <none> 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

kubelet组件部署的更多相关文章

  1. suse 12 二进制部署 Kubernetets 1.19.7 - 第09章 - 部署kubelet组件

    文章目录 1.9.部署kubelet 1.9.0.创建kubelet bootstrap kubeconfig文件 1.9.1.创建kubelet配置文件 1.9.2.配置kubelet为system ...

  2. IntelliJ IDEA 14.1.4导入项目启动报错:Error during artifact deployment.[组件部署期间出错]

    1.问题描述:Error during artifact deployment.[组件部署期间出错] 2.删除Artifacts 3.刷新 4.重新生成Artifacts 5.重新选择 再重新启动项目 ...

  3. Openstack组件部署 — keystone(domain, projects, users, and roles)

    目录 目录 前文列表 Create a domain projects users and roles domain projects users and roles的意义和作用 Create the ...

  4. Openstack组件部署 — Keystone Install & Create service entity and API endpoints

    目录 目录 前文列表 Install and configure Prerequisites 先决条件 Create the database for identity service 生成一个随机数 ...

  5. Openstack组件部署 — Keystone功能介绍与认证实现流程

    目录 目录 前文列表 Keystone认证服务 Keystone认证服务中的概念 Keystone的验证过程 简单来说 前文列表 Openstack组件部署 - Overview和前期环境准备 Ope ...

  6. Openstack组件部署 — Networking service_Compute Node

    目录 目录 前文列表 安装组件 配置通用组件 配置自服务网络选项 配置Linux 桥接代理 配置Nova使用网络 完成安装 验证操作Execute following commands on Cont ...

  7. Openstack组件部署 — Networking service_安装并配置Controller Node

    目录 目录 前文列表 前提条件 网络环境 完成下面的步骤以创建数据库 创建service credentials服务凭证 创建Neutron的API Endpoints 配置自服务网络 安装网络组件 ...

  8. Openstack组件部署 — Netwotking service组件介绍与网络基本概念

    目录 目录 前文列表 Openstack Networking serivce 基本的Neutron概念 Neutron的抽象对象 网络networks 子网subnets 路由器routers 端口 ...

  9. Openstack组件部署 — Nova_Install and configure a compute node

    目录 目录 前文列表 Prerequisites 先决条件 Install and configure a compute node Install the packages Edit the etc ...

随机推荐

  1. 【java基础之异常】死了都要try,不淋漓尽致地catch我不痛快!

    目录 1.异常 1.1 异常概念 1.2 异常体系 1.3 异常分类 1.4 异常的产生过程解析 2. 异常的处理 2.1 抛出异常throw 2.2 Objects非空判断 2.3 声明异常thro ...

  2. Linux Cannot allocate memory问题

    查找了一下相关文档,发现这个错误的含义其实就是像它自己说的,没法分配内存了. The problem is inherent with the way Java allocates memory wh ...

  3. 【Spdy协议简介】

    一.SPDY协议诞生记 SPDY (SPDY 是 Speedy 的昵音,意思是更快)是 Google 开发的基于传输控制协议 (TCP) 的应用层协议 ,那么为什么要搞一个SPDY出来呢?距离万维网之 ...

  4. sublime3中运行python文件

    sublime3中运行python文件 tools->build system->new build stystem 粘贴下面代码{"cmd":["pytho ...

  5. php nginx反向代理获取真实ip的教程

    php nginx反向代理获取真实ip的教程 <pre> location /getip { proxy_pass http://newmiracle.cn/ip.php; } proxy ...

  6. VS反编译查看源码时,会把类实现的所有接口都直接显示

    今天在看ArrayList,发现一个很有意思的问题.从VS里反编译看,ArrayList继承了ICollection. IEnumerable.IList和ICloneable,而IList又继承了I ...

  7. ADO.NET学习心得《一》

    大家好,我是代号六零一,很高兴又开始重启博客了,为了更好的加深自己的记忆和复习,今天开始坚持写写心得体会,刚开始学习ADO.NET的时候也是一脸懵逼的,代码只有动手敲打才会知道其实并不难,只要多敲几遍 ...

  8. MySQL系列:MySQL的基本使用

    数据库的基本操作 在MySQL数据库中,对于一个MySQL示例,是可以包含多个数据库的. 在连接MySQL后,我们可以通过 show databases; 来进行查看有那么数据库.这里已经存在一些库了 ...

  9. 关于Eratosthenes筛子算法筛选小于n的素数的理解

    今天在学习Java核心技术第九章集合框架中的BitSet时,遇到了这个算法.Eratosthenes筛子算法时一个查找素数的方法,这并不是查找素数的最好方法,但是测试编译程序性能的一种流行的基准. 一 ...

  10. CentOS 6.4 configure error的解决方法

    资料来源:http://blog.sina.com.cn/s/blog_62426dcf0100f2rz.html 虽然上面的文章是针对centOS 5写的,不过经测试也可用于centOS6.4. 自 ...