系统环境

  • 操作系统: CentOS 7.9

  • Golang 版本: 1.17.3

  • Docker 版本: 20.10.8

  • Kubeadm 版本: 1.23.0

  • Kubernetes 版本: 1.23.0

Kubernetes 官方提供了 kubeadm 工具安装 kubernetes 集群,使用这个工具安装集群非常便捷,使部署和升级 Kubernetes 变得简单起来,默认情况下,kubeadm 会生成一个集群所需的全部证书,而由于 kubeadm 生成的 CA 根证书有效期为10年,客户端证书有效期只有1年,因此在一年之内就需要对所有的客户端证书进行续签。所有证书都存放在 /etc/kubernetes/pki 目录下

查看证书过期时间

[root@saas-k8s-master-01 ~]# kubeadm certs check-expiration      

CERTIFICATE                EXPIRES                  RESIDUAL TIME   CERTIFICATE AUTHORITY   EXTERNALLY MANAGED
admin.conf                 Apr 09, 2024 06:49 UTC   9d                                     no      
apiserver                  Apr 09, 2024 06:49 UTC   9d             ca                      no      
apiserver-etcd-client      Apr 09, 2024 06:49 UTC   9d             etcd-ca                 no      
apiserver-kubelet-client   Apr 09, 2024 06:49 UTC   9d             ca                      no      
controller-manager.conf    Apr 09, 2024 06:49 UTC   9d                                     no      
etcd-healthcheck-client    Apr 09, 2024 06:49 UTC   9d             etcd-ca                 no      
etcd-peer                  Apr 09, 2024 06:49 UTC   9d             etcd-ca                 no      
etcd-server                Apr 09, 2024 06:49 UTC   9d             etcd-ca                 no      
front-proxy-client         Apr 09, 2024 06:49 UTC   9d             front-proxy-ca          no      
scheduler.conf             Apr 09, 2024 06:49 UTC   9d                                     no      

CERTIFICATE AUTHORITY   EXPIRES                  RESIDUAL TIME   EXTERNALLY MANAGED
ca                      May 02, 2033 07:46 UTC   9y              no      
etcd-ca                 May 02, 2033 07:46 UTC   9y              no      
front-proxy-ca          May 02, 2033 07:46 UTC   9y              no  

证书类别

集群根证书

[root@saas-k8s-master-01 ~]# ll /etc/kubernetes/pki/ca* -rw-r--r-- 1 root root 1066 Aug 7 03:03 /etc/kubernetes/pki/ca.crt -rw------- 1 root root 1675 Aug 7 03:03 /etc/kubernetes/pki/ca.key

由此集群根证书签发的证书有:

  1. kube-apiserver 组件持有的服务端证书

[root@saas-k8s-master-01 ~]# ll /etc/kubernetes/pki/apiserver.*
-rw-r--r-- 1 root root 1277 Aug  7 03:03 /etc/kubernetes/pki/apiserver.crt
-rw------- 1 root root 1675 Aug  7 03:03 /etc/kubernetes/pki/apiserver.key
  1. kubelet 组件持有的客户端证书

[root@saas-k8s-master-01 ~]# ll /etc/kubernetes/pki/apiserver-kubelet-client.*
-rw-r--r-- 1 root root 1143 Aug  7 03:03 /etc/kubernetes/pki/apiserver-kubelet-client.crt
-rw------- 1 root root 1679 Aug  7 03:03 /etc/kubernetes/pki/apiserver-kubelet-client.key

说明:kubelet的/var/lib/kubelet/config.yaml 配置文件中一般不会明确指定服务端证书,而是只指定ca根证书,让kubelet根据本地主机信息自动生成服务端证书并保存到配置的cert-dir文件夹中

汇聚层根证书

[root@saas-k8s-master-01 ~]# ll /etc/kubernetes/pki/front-proxy-ca.*
-rw-r--r-- 1 root root 1078 Aug  7 03:03 /etc/kubernetes/pki/front-proxy-ca.crt
-rw------- 1 root root 1675 Aug  7 03:03 /etc/kubernetes/pki/front-proxy-ca.key

由此汇聚层根证书签发的证书有:

  1. 代理端使用的客户端证书,用作代用户与 kube-apiserver 认证

[root@saas-k8s-master-01 ~]# ll /etc/kubernetes/pki/front-proxy-client.*
-rw-r--r-- 1 root root 1103 Aug  7 03:03 /etc/kubernetes/pki/front-proxy-client.crt
-rw------- 1 root root 1675 Aug  7 03:03 /etc/kubernetes/pki/front-proxy-client.key

etcd 集群根证书

[root@saas-k8s-master-01 ~]# ll /etc/kubernetes/pki/etcd/ca.*
-rw-r--r-- 1 root root 1058 Aug  7 03:03 /etc/kubernetes/pki/etcd/ca.crt
-rw------- 1 root root 1679 Aug  7 03:03 /etc/kubernetes/pki/etcd/ca.key

由此 etcd 根证书签发的证书有:

  1. etcd server 服务端证书

[root@saas-k8s-master-01 ~]# ll /etc/kubernetes/pki/etcd/server.*
-rw-r--r-- 1 root root 1188 Aug  7 03:03 /etc/kubernetes/pki/etcd/server.crt
-rw------- 1 root root 1679 Aug  7 03:03 /etc/kubernetes/pki/etcd/server.key
  1. etcd 集群中 peer 节点互相通信使用的客户端证书

[root@saas-k8s-master-01 ~]# ll /etc/kubernetes/pki/etcd/peer.*
-rw-r--r-- 1 root root 1188 Aug  7 03:03 /etc/kubernetes/pki/etcd/peer.crt
-rw------- 1 root root 1675 Aug  7 03:03 /etc/kubernetes/pki/etcd/peer.key
  1. Pod 中定义 Liveness 探针使用的客户端证书

[root@saas-k8s-master-01 ~]# ll /etc/kubernetes/pki/etcd/healthcheck-client.*
-rw-r--r-- 1 root root 1139 Aug  7 03:03 /etc/kubernetes/pki/etcd/healthcheck-client.crt
-rw------- 1 root root 1675 Aug  7 03:03 /etc/kubernetes/pki/etcd/healthcheck-client.key
  1. 配置在 kube-apiserver 中用来与 etcd server 做双向认证的客户端证书

[root@saas-k8s-master-01 ~]# ll /etc/kubernetes/pki/apiserver-etcd-client.*
-rw-r--r-- 1 root root 1135 Aug  7 03:03 /etc/kubernetes/pki/apiserver-etcd-client.crt
-rw------- 1 root root 1679 Aug  7 03:03 /etc/kubernetes/pki/apiserver-etcd-client.key

Serveice Account 密钥

[root@saas-k8s-master-01 ~]# ll /etc/kubernetes/pki/sa.*
-rw------- 1 root root 1675 Aug  7 03:03 /etc/kubernetes/pki/sa.key
-rw------- 1 root root  451 Aug  7 03:03 /etc/kubernetes/pki/sa.pub

说明:Serveice Account密钥对仅提供给kube-controller-manager使用,kube-controller-manager通过sa.key对token进行签名,Master节点通过公钥sa.pub进行签名的验证

API Server身份验证过程

API Server 的 Authentication 环节支持多种身份校验方式:Client Cert、Bearer Token、Static Password Auth 等,这些方式中只要有一种方式通过 Authentication(Kubernetes API Server 会逐个方式尝试),那么身份校验就会通过

一旦 API Server 发现 Client 发起的 Request 使用的是 Service Account Token 的方式,API Server 就会自动采用 Signed Bearer Token 方式进行身份校验。而 Request 就会使用携带的 Service Account Token 参与验证。该 Token 是 API Server 在创建 Service Account 时用 kube-controller-manager 启动参数 --service-account-private-key-file 指定的私钥签署 (sign) 的,同时必须指定 kube-apiserver 参数 --service-account-key-file(如果没指定的话,会使用 --tls-private-key-file 替代)为该私钥对应的公钥,用来在认证阶段验证 Token,也就是说该证书对通过 CN 和 O 指定了 ServiceAccount 的授权权限

通过 Authentication 后,API Server 将根据 Pod 所属 ServiceAccount 的用户名(以 system:serviceaccount: 为前缀)和组(以 system:serviceaccounts: 前缀)的权限对其进行 Authorization 和 Admission Control 两个环节的处理

不管是自动生成的 Token 还是手动创建的 Token 的值都是一样的,因为进行签署 Token 的 -–service-account-key-file 是同一个

ServiceAccount 中的 Token 是 API server 私钥签署的,Pod 在对 API Server 发起请求的时候会带上该 Token,以确保能够通过 API Server 的认证。对 ServiceAccount 的授权通过对 ServiceAccount 对应的用户或组进行 RBAC 控制即可

更新证书

从上面可以了解到,默认情况下 ETCD 证书有效期是 10 年时间,其它证书有效期为 1 年时间,所以如果我们安装集群时没有修改证书过期时间,那么默认 1 年后可能会出现证书过期集群不可用的问题,所以接下来我们进入修改 kubeadm 源码过程

查看当前版本

[root@k8s-master-01 ~]# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.0", GitCommit:"ab69524f795c42094a6630298ff53f3c3ebab7f4", GitTreeState:"clean", BuildDate:"2021-12-07T18:15:11Z", GoVersion:"go1.17.3", Compiler:"gc", Platform:"linux/amd64"}

获取源码

获取源码,以 v1.230 为例,Kubernetes v1.23.0使用的Golang版本为 1.17.3,各个Kubernetes版本使用的Golang版本是不一样的,编译时安装的Golang版本要严格按照文件中的指定版本

[root@k8s-master-01 ~]# yum install git wget -y
[root@k8s-master-01 ~]# cd /root/
[root@k8s-master-01 ~]# git clone --branch v1.23.0 --single-branch --depth 1 https://github.com/kubernetes/kubernetes

安装Golang

在 https://golang.org/dl/ 下载对应版本的Golang

[root@k8s-master-01 ~]# yum install -y gcc make rsync jq
#下载 golang 1.17.3
[root@k8s-master-01 ~]# wget https://dl.google.com/go/go1.17.3.linux-amd64.tar.gz

#解压并放置在一个目录中
[root@k8s-master-01 ~]# tar zxvf go1.17.3.linux-amd64.tar.gz  -C /usr/local

[root@k8s-master-01 ~]#  vi /etc/profile

export GOROOT=/usr/local/go
export GOPATH=/usr/local/gopath
export PATH=$PATH:$GOROOT/bin

#使配置生效
[root@k8s-master-01 ~]# source /etc/profile

[root@k8s-master-01 ~]# go version

go version go1.17.3 linux/amd64

修改源码CA证书时间

[root@k8s-master-01 ~]# cd kubernetes
[root@k8s-master-01 kubernetes]# vim staging/src/k8s.io/client-go/util/cert/cert.go
...
########### 修改10年为100年(注掉部分为源代码,后面跟着的是修改后的代码)
#NotAfter:             now.Add(duration365d * 10).UTC(),
NotAfter:              now.Add(duration365d * 100).UTC(),
KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
BasicConstraintsValid: true,
IsCA:                  true,
...

修改源码其它证书时间

[root@k8s-master-01 kubernetes]# vim cmd/kubeadm/app/constants/constants.go
...
########### 后面追加个 * 100 (注掉部分为源代码,后面跟着的是修改后的代码)
#const duration365d = time.Hour * 24 * 365
const duration365d = time.Hour * 24 * 365 * 100

// Config contains the basic fields required for creating a certificate
type Config struct {
        CommonName   string
        Organization []string
        AltNames     AltNames
        Usages       []x509.ExtKeyUsage
}
...

编译kubeadm

使用 make 命令编译 kubeadm, 执行的命令如下

[root@k8s-master-01 kubernetes]# make all WHAT=cmd/kubeadm GOFLAGS=-v

编译成功后 kubeadm会放到当前目录中的 ./_output/local/bin/linux/amd64/ 目录中

[root@k8s-master-01 kubernetes]# cd ./_output/local/bin/linux/amd64/
[root@k8s-master-01 amd64]# ll

-rwxr-xr-x 1 root root  6270976 5月   3 14:39 conversion-gen
-rwxr-xr-x 1 root root  5996544 5月   3 14:38 deepcopy-gen
-rwxr-xr-x 1 root root  6000640 5月   3 14:38 defaulter-gen
-rwxr-xr-x 1 root root  3376679 5月   3 14:38 go2make
-rwxr-xr-x 1 root root 45170688 5月   3 14:40 kubeadm
-rwxr-xr-x 1 root root  8114176 5月   3 14:39 openapi-gen
-rwxr-xr-x 1 root root  5971968 5月   3 14:38 prerelease-lifecycle-gen

替换kubeadm

将编译好的kubeadm二进制文件拷贝到所有节点下并进行替换

[root@k8s-master-01 ~]# mv /usr/bin/kubeadm  /usr/bin/kubeadm.bak
[root@k8s-master-01 ~]# mv kubeadm /usr/bin/kubeadm

验证kubeadm版本与原来是否保持一致,确认BuildDate为重新编译的时间

[root@k8s-master-01 ~]# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.0", GitCommit:"ab69524f795c42094a6630298ff53f3c3ebab7f4", GitTreeState:"archive", BuildDate:"2024-05-03T06:39:41Z", GoVersion:"go1.17.3", Compiler:"gc", Platform:"linux/amd64"}

备份集群文件

如果运行了一个HA集群,以下命令需要在所有Master节点上执行

[root@k8s-master-01 ~]# cp -a /etc/kubernetes/ /etc/kubernetes-`date +%Y%m%d`
[root@k8s-master-01 ~]# kubectl get cm kubeadm-config -n kube-system -o yaml > /root/kubeadm-config.yaml

更新证书

执行如下命令更新所有证书

[root@k8s-master-01 ~]# kubeadm certs renew all
[renew] Reading configuration from the cluster...
[renew] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'

certificate embedded in the kubeconfig file for the admin to use and for kubeadm itself renewed
certificate for serving the Kubernetes API renewed
certificate the apiserver uses to access etcd renewed
certificate for the API server to connect to kubelet renewed
certificate embedded in the kubeconfig file for the controller manager to use renewed
certificate for liveness probes to healthcheck etcd renewed
certificate for etcd nodes to communicate with each other renewed
certificate for serving etcd renewed
certificate for the front proxy client renewed
certificate embedded in the kubeconfig file for the scheduler manager to use renewed

Done renewing certificates. You must restart the kube-apiserver, kube-controller-manager, kube-scheduler and etcd, so that they can use the new certificates.

确认证书是否续期成功

[root@k8s-master-01 ~]# kubeadm certs check-expiration

CERTIFICATE                EXPIRES                  RESIDUAL TIME   CERTIFICATE AUTHORITY   EXTERNALLY MANAGED
admin.conf                 Apr 09, 2124 06:49 UTC   99y                                     no      
apiserver                  Apr 09, 2124 06:49 UTC   99y             ca                      no      
apiserver-etcd-client      Apr 09, 2124 06:49 UTC   99y             etcd-ca                 no      
apiserver-kubelet-client   Apr 09, 2124 06:49 UTC   99y             ca                      no      
controller-manager.conf    Apr 09, 2124 06:49 UTC   99y                                     no      
etcd-healthcheck-client    Apr 09, 2124 06:49 UTC   99y             etcd-ca                 no      
etcd-peer                  Apr 09, 2124 06:49 UTC   99y             etcd-ca                 no      
etcd-server                Apr 09, 2124 06:49 UTC   99y             etcd-ca                 no      
front-proxy-client         Apr 09, 2124 06:49 UTC   99y             front-proxy-ca          no      
scheduler.conf             Apr 09, 2124 06:49 UTC   99y                                     no      

CERTIFICATE AUTHORITY   EXPIRES                  RESIDUAL TIME   EXTERNALLY MANAGED
ca                      May 02, 2033 07:46 UTC   9y              no      
etcd-ca                 May 02, 2033 07:46 UTC   9y              no      
front-proxy-ca          May 02, 2033 07:46 UTC   9y              no   

可以看到所有客户端证书的到期时间均从执行renew成功的时间开始续签了100年,所有根证书ca、etcd-ca、front-proxy-ca只有在init初始化的时候才会更新时间,因此建议对于kubeadm部署 Kubernetes,可以在初始化之前使用编译的方式将证书设置为更长时间,如100年

注意: 如果使用编译后的kubeadm执行 upgrade 命令,更新原有的证书有效期为1年的Kubernetes集群,证书更新也是有效果的,不过kubeadm更新操作并不会更新ETCD证书,所以ETCD证书有效期还是默认的10年,需要手动更新

启用证书

依次在所有 Master 节点上执行如下命令重启 kube-apiserver、kube-controller-manager、kube-scheduler 和etcd使其启用新证书,以下两种命令选一即可

[root@k8s-master-01 ~]# docker ps |egrep "k8s_kube-apiserver|k8s_kube-scheduler|k8s_kube-controller|k8s_etcd_etcd"|awk '{print $1}'|xargs docker restart
或者
[root@k8s-master-01 ~]# mv /etc/kubernetes/manifests/ /etc/kubernetes/manifests.bak && sleep 30 && mv /etc/kubernetes/manifests.bak /etc/kubernetes/manifests/

执行完一台后请务必确认对应Master节点上的kube-apiserver、kube-controller-manager、kube-scheduler和etcd服务Pod均处于Running状态并就绪后再开始操作下一台

替换config文件

执行如下命令替换 config 文件

[root@k8s-master-01 ~]# sudo cp -a /etc/kubernetes/admin.conf $HOME/.kube/config
[root@k8s-master-01 ~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config

文章作者: 鲜花的主人
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 爱吃可爱多
Kubernetes Kubernetes
喜欢就支持一下吧
打赏
微信 微信
支付宝 支付宝