k8s 二进制部署 九 (kubelet)

大番茄 2019年11月23日 374次浏览

v1.16、v1.19.5

注意

关闭 swap

不关在启动 kubelet 与 kube-proxy 的时候会提示,不支持 swap 环境启动。
image-97096ba0

firewalld, selinux 也关闭。
系统时区

一、介绍

kubelet 是主要的工作节点程序,功能如下:

  • 注册节点。
  • 从 apiserver 监测已分配给节点的 pod 信息, 或者是从本地配置中获取 pod 信息, 启动 pod。
  • 执行容器健康检查。探针。
  • 挂载 pod 需要挂载的卷。
  • 下载 pod 需要的 secret, configmap, 并挂载。
  • 监控容器和节点资源。
  • 发送节点状态和 pod 状态给 apiserver。
  • 提供/metrics/cAdvisor 监控接口。

二、参数

还是单独出来了,随着学习越写越多,太占篇幅了。
https://www.yxingxing.net/archives/kubelet-20201217-parameter

三、文件

也就是目录结构还有执行文件。conf 目录下的文件一会 er 生成。

[root@k8s-node1 k8s]# tree
.
├── bin
│   ├── kubelet
│   └── kube-proxy
├── conf
├── logs
└── ssl

4 directories, 2 files

四、Unit

[Unit]
Description=kubelet
Requires=docker.service

[Service]
ExecStart=/usr/local/k8s/bin/kubelet\
--address=172.100.102.71 \
--bootstrap-kubeconfig=/usr/local/k8s/conf/bootstrp-kubeconfig \
--cert-dir=/usr/local/k8s/ssl \
--cgroup-driver=systemd \
--cluster-dns=10.0.0.2 \
--cluster-domain=cluster.local \
--kubeconfig=/usr/local/k8s/conf/kubeconfig \
--log-dir=/usr/local/k8s/logs \
--logtostderr=false \
--rotate-certificates \
--v=4 \
--root-dir=/usr/local/kubelet-data \
--pod-infra-container-image=registry.cn-beijing.aliyuncs.com/yangxingxing/pause:3.1
Restart=on-failure

[Install]
WantedBy=multi-user.target

这里的 pause 镜像是从 google 云下载并上传到阿里的,可以使用。

五、配置自动获取证书

如果不需要自动获取证书就不需要这一步
详细流程:
这个页面不要选择语言为中文, 发现页面不一样,看起来是非常老的信息,而且也是英文的。
https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/

证书轮换:
https://kubernetes.io/zh/docs/tasks/tls/certificate-rotation/

初始化流程截出来了,页面翻译的:

引导程序初始化
在引导程序初始化过程中,会发生以下情况:
kubelet开始
kubelet认为,它并没有有一个kubeconfig文件
kubelet搜索并找到bootstrap-kubeconfig文件
kubelet读取其引导程序文件,检索API服务器的URL和有限用法的“令牌”
kubelet连接到API服务器,使用令牌进行身份验证
kubelet现在具有有限的凭据来创建和检索证书签名请求(CSR)
kubelet为自己创建一个CSR,并将signerName设置为 kubernetes.io/kube-apiserver-client-kubelet
通过以下两种方式之一批准CSR:
如果已配置,则kube-controller-manager会自动批准CSR
如果进行了配置,则外部流程(可能是一个人)会使用Kubernetes API或通过以下方式批准CSR kubectl
为kubelet创建了证书
证书已颁发给kubelet
kubelet检索证书
kubeletkubeconfig使用密钥和签名证书创建一个正确的名称
kubelet开始正常运行
可选:如果已配置,则kubelet在证书即将到期时会自动请求更新证书
根据配置,自动或手动批准和颁发续签的证书。

bootstrap令牌验证:
https://kubernetes.io/zh/docs/reference/access-authn-authz/bootstrap-tokens/
这里的bootstrap是一种认证方式。非必须,也可以使用其他认证方式。


kubelect参数的bootstrip-kubeconfig是引导获取证书的意思
而bootstrap认证是一种认证方式,专门用于kubelet引导启动时认证的。


1、kube-apiserver需要做的

https://www.yxingxing.net/articles/2019/10/30/1572423121991.html

(1)需要启用enable-bootstrap-token-auth参数。只有使用bootstrap令牌验证的方式需要。如果不使用bootstrap令牌验证,就不需要enable-bootstrap-token-auth参数。
--enable-bootstrap-token-auth

如果使用token的方式就是:

--token-auth-file=FILENAME

如果使用token的方式, 官方网站显示组名是固定的system:bootstrappers。
如:
令牌, 用户名, 用户id, 组名。

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

无论是引导令牌认证,还是token认证,授权都一样。

(2)授权kubelet创建CSR证书签名请求。

image-676780fd
直接把创建clusterrolebinding的内容直接复制下来并应用就可以。

[root@k8s-master init]# cat kubelet-csr.yaml 
# enable bootstrapping nodes to create CSR
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

[root@k8s-master init]# kubectl apply -f kubelet-csr.yaml
clusterrolebinding.rbac.authorization.k8s.io/create-csrs-for-bootstrapping created
[root@k8s-master init]# 
(3)授权可以签发证书。

其中又有两种方式:


1、节点还没有证书,只能使用bootstrip令牌认证,这就需要跟上面一样给system:bootstrappers组授权。

页面翻译的,能理解就行。创建一个clusterrolebinding。
image-cbd746c4

[root@k8s-master init]# cat kubelet-new-crt.yaml
# Approve all CSRs for the group "system:bootstrappers"
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

[root@k8s-master init]# kubectl apply -f kubelet-new-crt.yaml
clusterrolebinding.rbac.authorization.k8s.io/auto-approve-csrs-for-group created
[root@k8s-master init]# 

2、节点有证书,需要续订证书,就给system:nodes组,赋予可以续订证书的权限。
因为自动签署的证书里的组就是system:nodes, 可以通过一条命令查看:

[root@k8snode1 cert]# openssl x509 -in  kubelet-client-2020-12-16-09-08-23.pem -noout -subject
subject= /O=system:nodes/CN=system:node:k8snode1
[root@k8snode1 cert]# 

system:nodes组续订证书的权限。
image-d5acc8d0

[root@k8s-master init]# cat kubelet-renew-crt.yaml
# Approve renewal CSRs for the group "system:nodes"
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

[root@k8s-master init]# kubectl apply -f kubelet-renew-crt.yaml
clusterrolebinding.rbac.authorization.k8s.io/auto-approve-renewals-for-nodes created
[root@k8s-master init]# 

权限创建完了。


2、controller-manager需要做的

其实就是启动的时候加上三个参数以及开启bootstrap控制器。

--cluster-signing-cert-file=
--cluster-signing-cert-file
--experimental-cluster-signing-duration

controller-manager 需要启动bootstrapsigner控制器。默认是启动的。
--experimental-cluster-signing-duration 这个参数在v1.19.5变成了--cluster-signing-duration

3、kubelet

  • 存储生成的密钥和证书的路径(可选,可以使用默认值)
  • kubeconfig尚不存在的文件的路径;它将引导文件放在这里
  • bootstrap-kubeconfig文件的路径,用于提供服务器和引导程序凭据的URL,例如引导程序令牌。
  • 续订证书的配置,一个参数:--rotate-certificates。 官方网站说明还有一个功能标记RotateKubeletClientCertificate,默认就是启用的,而且我也没找到。

在上面的启动参数里都已经加上了。
现在就剩创建bootstrap-kubeconfig文件了。


4、配置bootstrap-kubeconfig文件

这个文件与一般的kubeconfig文件格式一样, 只是 user 部分使用 bootstrap-token。 所以主要是创建bootstrap-token。

说明bootstrap-token格式

https://kubernetes.io/zh/docs/reference/access-authn-authz/bootstrap-tokens/
image-07342065
就是这个格式,如果能打开上面的网址, 里面都有介绍。 要求大致如下:


  • token必须类似 abcdef.0123456789abcdef 这种格式,必须匹配正则表达式[a-z0-9]{6}\.[a-z0-9]{16},令牌的第一部分是“token-id”,后面部分是tokne-secret。

  • type 必须为bootstrap.kubernetes.io/token

  • name 必须为bootstrap-token-<token id>,

  • 必须在 kube-system namespace 中。


其他说明:

  • expiration字段控制令牌的到期时间。过期的令牌在用于身份验证时将被拒绝,并在ConfigMap签名期间被忽略。到期值使用RFC3339编码为绝对UTC时间。

  • controller-manager启用 tokencleaner控制器 能够自动删除过期的令牌。

  • usage-bootstrap-*表示这是用于什么。必须将值设置为true启用。有下面两个。

  • usage-bootstrap-authentication 表示令牌可以用作承载令牌向API服务器进行身份验证。

  • usage-bootstrap-signing指示令牌可用于签署 cluster-infoConfigMap。

  • auth-extra-groups: 令牌默认的组是system:bootstrappers, 如果需要设置额外的组,就在这里添加,组名必须以 "system:bootstrappers:" 开头。


创建bootstrip-token

生成一些随机值:

[root@k8s-master init]# openssl rand -base64 20
yiCm94HtA5vm1Y6Nt1oWcN3wfRE=

摘出来几个做token-id, 和 token-secret, 大写变成小写就可以。

[root@k8s-master init]# cat bootstrip-token.yaml
apiVersion: v1
kind: Secret
metadata:
  # Name MUST be of form "bootstrap-token-<token id>"
  name: bootstrap-token-yicm94
  namespace: kube-system

# Type MUST be 'bootstrap.kubernetes.io/token'
type: bootstrap.kubernetes.io/token
stringData:

  # Token ID and secret. Required.
  token-id: yicm94
  token-secret: hta5vm1y6nt1owcn

  # Expiration. Optional.
  expiration: 2019-11-28T03:22:11Z

  # Allowed usages.
  usage-bootstrap-authentication: "true"
  usage-bootstrap-signing: "true"

[root@k8s-master init]# kubectl apply -f bootstrip-token.yaml
secret/bootstrap-token-yicm94 created
[root@k8s-master init]# 

注意过期时间。

接下来直接把kubectl使用的config文件或者自己新创建一个文件, 放到kubelect启动参数bootstrap-kubeconfig所指定的文件。
删除原来文件user部分的证书认证,把token放进去。

image-e366b2aa

成了这个样子就可以了。接下来就可以启动kubelet了。


另外: 上面的server 我这里没有连接vip, 因为还要安装hasproxy 或 nginx做负载均衡代理到后面的apiserver。 这里只是说明kubelet, 就不折腾了。

五、启动kubelet。

[root@k8s-node1 k8s]# tree
.
├── bin
│   ├── kubelet
│   └── kube-proxy
├── conf
│   └── bootstrp-kubeconfig
├── logs
└── ssl

4 directories, 3 files
[root@k8s-node1 conf]# systemctl start kubelet

[root@k8s-node1 k8s]# tree
.
├── bin
│   ├── kubelet
│   └── kube-proxy
├── conf
│   ├── bootstrp-kubeconfig
│   └── kubeconfig
├── logs
│   ├── kubelet.ERROR -> kubelet.k8s-node1.root.log.ERROR.20191124-020405.7817
│   ├── kubelet.INFO -> kubelet.k8s-node1.root.log.INFO.20191124-020344.7817
│   ├── kubelet.k8s-node1.root.log.ERROR.20191124-020405.7817
│   ├── kubelet.k8s-node1.root.log.INFO.20191124-020344.7817
│   ├── kubelet.k8s-node1.root.log.WARNING.20191124-020345.7817
│   └── kubelet.WARNING -> kubelet.k8s-node1.root.log.WARNING.20191124-020345.7817
└── ssl
    ├── kubelet-client-2019-11-24-02-03-44.pem
    ├── kubelet-client-current.pem -> /usr/local/k8s/ssl/kubelet-client-2019-11-24-02-03-44.pem
    ├── kubelet.crt
    └── kubelet.key

4 directories, 14 files

在master节点查看一下:

[root@k8s-master logs]# kubectl get nodes
NAME        STATUS   ROLES    AGE   VERSION
k8s-node1   Ready    <none>   52s   v1.16.2

另外: 上面是通过bootstrap-token的方式认证的,不清楚其他的认证方式,如:
证书的方式, 是不是需要固定组为system:bootstrappers, 然后也是按上面的方式给这个组授权。

六、一些额外的东西

1、证书的组与用户

因为要给kubelet使用Node鉴权模式,需要system:ndoes组以及system:node:<nodeName>用户,所以就算不使用自动颁发的证书,自己手动给kubelet创建证书的时候。也需要指定组名system:ndoes和用户名system:node:<nodeName>。 如果不使用Node鉴权,比如要使用RBAC,那就无所谓了。
Node鉴权:
https://kubernetes.io/zh/docs/reference/access-authn-authz/node/

2、续订证书时的用户

测试发现在bootstrip-token可以使用的情况下,续订证书中的csr请求用户是bootstrap-token, 而在token过期或者删除的情况下就是node了。

[root@k8smaster1 bootstrip]# kubectl get csr
NAME        AGE   SIGNERNAME                                    REQUESTOR                 CONDITION
csr-6hzp8   45m   kubernetes.io/kube-apiserver-client-kubelet   system:node:k8snode1      Approved,Issued
csr-d5jwf   25s   kubernetes.io/kube-apiserver-client-kubelet   system:node:k8snode1      Approved,Issued
csr-lj4nz   89m   kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:h9qwkh   Approved,Issued

可能会有疑问,之前授权的是system:nodes组,这里显示的请求是system:node:k8snode1用户。

csr请求里面是有组的,只是没有显示出来而已,详细信息就可以看到了。