kubernetes证书过期处理

目录:
1、证书过期时间查询
2、证书过期处理
2.1、客户端kubelet证书自动续期
2.2、重新生成默认一年时长证书
2.3、编译kubeadm延长证书时长


简介:

k8s集群分为两种证书:

  • 用于集群 Master、Etcd等通信的证书;
  • 用于集群中客户端 Kubelet组件和api通信的证书;

我们在搭建 Kubernetes 集群时,一般只声明用于集群 Master、Etcd等通信的证书有效期为10年或者更久,但未声明集群 Kubelet 组件证书 ,Kubelet组件证书默认有效期为1年。集群运行1年以后就会导致报 certificate has expired or is not yet valid 错误,导致集群 Node不能于集群 Master正常通信。
1.14后的版本可以使用这个命令查看过期时间,如下:
$kubeadm alpha certs check-expiration​

kubeadm初始化配置文件:
kubeadm.yaml是一个kubeadm用于集群初始化时候的一个配置文件,这个配置文件主要用于集群初始化的时候指定一些自定义的参数和配置信息。我们在使用kubeadm更新k8s集群证书的时候会使用到这个配置文件。

  • 获取一个创建好的ha k8s集群的初始化配置文件
    $kubeadm config view > kubeadm.yaml
apiVersion: kubeadm.k8s.io/v1alpha1
kind: MasterConfiguration
etcd:
  endpoints:
  - https://10.10.8.141:2379
  - https://10.10.8.142:2379
  - https://10.10.8.143:2379
  caFile: /etc/etcd/ssl/ca.pem
  certFile: /etc/etcd/ssl/etcd.pem
  keyFile: /etc/etcd/ssl/etcd-key.pem
  dataDir: /var/lib/etcd
networking:
  podSubnet: 10.244.0.0/16
kubernetesVersion: 1.10.0
api:
  advertiseAddress: "10.10.8.140"
token: "b99a00.a144ef80536d4344"
tokenTTL: "0s"
apiServerCertSANs:
- k8s-master1
- k8s-master2
- k8s-master3
- 10.10.8.141
- 10.10.8.142
- 10.10.8.143
- 10.10.8.144
- 10.10.8.140
featureGates:
  CoreDNS: true
imageRepository: "k8s.gcr.io"

注意:若我们集群的证书已经过期了不能使用kubeadm获取到集群的初始化配置文件,那么我们可以手写一个简单的配置文件,写这个文件是因为获取不到集群的基本配置文件的时候kubeadm会去k8s官网找一个stable-1.txt的文件(这个文件的内容就是关于k8s的版本信息)。

  • 创建一个简单的kubeadm的配置文件
    $vi kubeadm.yaml
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: v1.13.5 #--------这里改成你集群对应的版本
imageRepository: k8s.gcr.io #-------k8s官方的镜像仓库

上面文件主要作用是告诉kubeadm中Kubernetes集群的版本,以防止它去网上查找,因为被墙,会报错如下:

could not fetch a Kubernetes version from the internet: unable to get URL "https://dl.k8s.io/release/stable-1.txt"

1、证书过期时间查询:

  • 查看k8s集群中各个组件证书过期时间1.14版本后有下面这个命令:
$kubeadm alpha certs check-expiration​
  • 查看etcd证书过期时间:
$cfssl-certinfo -cert /etc/kubernetes/pki/etcd/server.crt | grep not
$openssl x509 -in etcd.pem -noout -text |grep ' Not '
  • 查看集群证书过期时间:
$openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text |grep ' Not '
$for i in `ls /etc/kubernetes/pki/*.crt`; do echo $i ; openssl x509 -in $i -noout -dates | grep notAfter; done

2、证书过期处理:

2.1、客户端kubelet证书轮换自动续期:

kubectl证书轮换是在当前证书即将过期时,将自动生成新的密钥,并从k8s api申请新的证书。

kubelet 进程接收 --rotate-certificates 参数,该参数决定 kubelet 在当前使用的证书即将到期时,是否会自动申请新的证书。 由于证书轮换是 beta 特性,必须通过参数 --feature-gates=RotateKubeletClientCertificate=true 进行启用。

kube-controller-manager 进程接收 --experimental-cluster-signing-duration 参数,该参数控制证书签发的有效期限。
当 kubelet 启动时,如被配置为自举(使用--bootstrap-kubeconfig 参数),kubelet 会使用其初始证书连接到 Kubernetes API ,并发送证书签名的请求。 可以通过以下方式查看证书签名请求的状态:

$kubectl get csr

最初,来自节点上 kubelet 的证书签名请求处于 Pending 状态。 如果证书签名请求满足特定条件, 控制管理器会自动批准,此时请求会处于 Approved 状态。 接下来,控制器管理器会签署证书, 证书的有效期限由 --experimental-cluster-signing-duration 参数指定,签署的证书会被附加到证书签名请求中。

Kubelet 会从 Kubernetes API 取回签署的证书,并将其写入磁盘,存储位置通过 --cert-dir 参数指定。 然后 kubelet 会使用新的证书连接到 Kubernetes API。

当签署的证书即将到期时,kubelet 会使用 Kubernetes API,发起新的证书签名请求。 同样地,控制管理器会自动批准证书请求,并将签署的证书附加到证书签名请求中。 Kubelet 会从 Kubernetes API 取回签署的证书,并将其写入磁盘。 然后它会更新与 Kubernetes API 的连接,使用新的证书重新连接到 Kubernetes API。

1)、开启证书轮换:

  • 修改kubelet启动配置文件增加如下参数
    在/etc/systemd/system/kubelet.service.d/10-kubeadm.conf 增加如下参数:
Environment="KUBELET_EXTRA_ARGS=--feature-gates=RotateKubeletServerCertificate=true --feature-gates=RotateKubeletClientCertificate=true"
  • 修改kube-controller-manager.yaml配置文件
    在/etc/kubernetes/manifests/kube-controller-manager.yaml 添加如下参数:
  - command:
    - kube-controller-manager
    - --experimental-cluster-signing-duration=87600h0m0s #10年
    - --feature-gates=RotateKubeletServerCertificate=true
    - ....
  • 创建 rbac 对象
    创建rbac对象,允许节点轮换kubelet server证书:
    $vi kubelet-ca-update.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver
rules:
- apiGroups:
  - certificates.k8s.io
  resources:
  - certificatesigningrequests/selfnodeserver
  verbs:
  - create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubeadm:node-autoapprove-certificate-server
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:nodes
$kubectl create -f kubelet-ca-update.yaml
2.2、重新生成默认一年时长证书

在集群已经部署好的情况下集群的证书过期,可以选择对证书进行重新生成。
单master或多master集群(etcd在集群内)处理:
1)、备份原先的证书文件和配置文件:

$cp -rp /etc/kubernetes /etc/kubernetes.bak

2)、删除过期的证书文件:
(注意:1.13.0以下的版本需要删除旧的证书,不然不会重新生成,1.13.5以上的就不用操作了会自动更新的。ca.cer\ca.key\sa的这些证书不要删除ca默认就是10年没必要重新生成,同时kubeadm在重新生成apiserver这些组件的证书的时候需要使用ca证书来进行签发)

$ rm -f /etc/kubernetes/pki/apiserver*
$ rm -f /etc/kubernetes/pki/front-proxy-client.*
$ rm -rf /etc/kubernetes/pki/etcd/healthcheck-client.*
$ rm -rf /etc/kubernetes/pki/etcd/server.*
$ rm -rf /etc/kubernetes/pki/etcd/peer.*

3)、获取k8s集群初始化的配置文件yaml文件:

$kubeadm config view > kubeadm.yaml

4)、生成新的证书文件
生成证书有两种方式一种是重新生成私钥和公钥,一种是使用存在的私钥重新签发。

  • 生成相应组件的证书(此格式会使用相应组件的原来的key重新签发证书):
$kubeadm alpha phase certs renew etcd-healthcheck-client --config kubeadm.yaml
$kubeadm alpha phase certs renew etcd-peer --config kubeadm.yaml
$kubeadm alpha phase certs renew etcd-server --config kubeadm.yaml
$kubeadm alpha phase certs renew front-proxy-client--config kubeadm.yaml
$kubeadm alpha phase certs renew apiserver-etcd-client --config kubeadm.yaml
$kubeadm alpha phase certs renew apiserver-kubelet-client --config kubeadm.yaml
$kubeadm alpha phase certs renew apiserver --config kubeadm.yaml
##或者重新签发全部组件的证书
$kubeadm alpha phase certs renew all --config kubeadm.yaml

或如下格式(这种格式需要删除原来存在的相应证书和key,此格式会重新创建相应组件的私钥和公钥):
$kubeadm init phase certs apiserver --config kubeadm.yaml
  • 生成新的配置文件(admin.conf、controller-manager.conf、kubelet.conf、scheduler.conf):
$rm -f admin.conf kubelet.conf controller-manager.conf scheduler.conf
$kubeadm alpha phase kubeconfig all --config kubeadm.yaml
或如下格式重新生成相关组件的配置文件:
$kubeadm init phase kubeconfig all --config ./kubeadm.yaml
  • 将新生成的admin.conf文件覆盖掉.kube/config文件:
$mv $HOME/.kube/config $HOME/.kube/config.old
$cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$chown $(id -u):$(id -g) $HOME/.kube/config
$sudo chmod 644 $HOME/.kube/config

5)、各节点重启kubelet或相关组件:

$ systemctl restart kubelet
或重新启动docker容器中的kube-apiserver,kube-controller,kube-scheduler,etcd

注意:若集群式采用高可用ha方式安装的话有所区别,etd的相关证书需要另外签发操作,要是之前搭建集群的时候已经使用了长时间的则仅仅需要处理k8s其它组件的证书即可。

k8s cluster ha多master集群(etcd在集群外)处理:
1)、备份证书和配置:

$cp -rp /etc/kubernetes /etc/kubernetes.bak
$cp -rm /etc/etcd/ssl /etc/etcd/ssl.bak

2)、删除过期的证书文件:
(注意:1.13.0以下的版本需要删除旧的证书,不然不会重新生成,1.13.5以上的就不用操作了会自动更新的;ca.cer\ca.key\sa的这些证书不要删除ca默认就是10年没必要重新生成,同时kubeadm在重新生成apiserver这些组件的证书的时候需要使用ca证书来进行签发)

$ rm -f /etc/kubernetes/pki/apiserver*
$ rm -f /etc/kubernetes/pki/front-proxy-client.*
$ rm -rf /etc/kubernetes/pki/etcd/healthcheck-client.*
$ rm -rf /etc/kubernetes/pki/etcd/server.*
$ rm -rf /etc/kubernetes/pki/etcd/peer.*

3)、获取k8s集群初始化的配置文件yaml文件:

$kubeadm config view > kubeadm.yaml

4)、etcd证书续期(重新创建,etcd要是没有过期不用管这步):
以下这三个证书文件是之前高可用集群创建的时候用于解决etcd证书问题,现在要依据下面三个文件重新创建etcd证书。

  • 创建etcd的根证书配置:
$cat >  ca-config.json <<EOF
{
"signing": {
"default": {
  "expiry": "876000h"
},
"profiles": {
  "kubernetes-Soulmate": {
    "usages": [
        "signing",
        "key encipherment",
        "server auth",
        "client auth"
    ],
    "expiry": "876000h"
  }
}
}
}
EOF
  • 创建etcd的根证书签发配置:
$cat >  ca-csr.json <<EOF
{
"CN": "kubernetes-Soulmate",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
  "C": "CN",
  "ST": "hangzhou",
  "L": "hangzhou",
  "O": "k8s",
  "OU": "System"
}
]
}
EOF
  • 创建etcd的证书签发列表配置:
$cat > etcd-csr.json <<EOF
{
  "CN": "etcd",
  "hosts": [
    "127.0.0.1",
    "10.10.8.141",
    "10.10.8.142",
    "10.10.8.143"
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "hangzhou",
      "L": "hangzhou",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF
  • 生成etcd的证书:
$cfssl gencert -initca ca-csr.json | cfssljson -bare ca
$cfssl gencert -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -profile=kubernetes-Soulmate etcd-csr.json | cfssljson -bare etcd
  • 将新生成的etcd证书拷贝到本节点上:
$cp -rp ca.pem  etcd-key.pem  etcd.pem /etc/etcd/ssl/
  • 将新生成的etcd证书拷贝到各个etcd节点上:
$scp -r /etc/etcd/ssl root@${other_node}:/etc/etcd/

注意:重启etcd服务(记住,要3个节点一起重启,不然会hang住)

5)、重新生成k8s其它组件证书和admin.conf配置文件

  • 重新生成处etcd组件外的其它组件证书(不需要生成etcd相关的证书):
$kubeadm alpha certs renew front-proxy-client --config kubeadm.yaml
$kubeadm alpha certs renew apiserver-kubelet-client --config kubeadm.yaml
$kubeadm alpha certs renew apiserver --config kubeadm.yaml
  • 重新生成配置文件(admin.conf、controller-manager.conf、kubelet.conf、scheduler.conf):
$kubeadm alpha phase kubeconfig all --config kubeadm.yaml 
或版本不一样可能kubeadm命令不一样可以用下面这个命令:
$kubeadm init phase kubeconfig all --config ./kubeadm.yaml

6)、将新生成的admin配置文件覆盖掉原本的admin文件(非root用户处理):

$mv $HOME/.kube/config $HOME/.kube/config.old
$cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$chown $(id -u):$(id -g) $HOME/.kube/config
$sudo chmod 777 $HOME/.kube/config

7)、将新生成的pki目录下的证书文件和配置文件拷贝到其他master节点上:

$scp pki/* root@${other_master}:/etc/kubernetes/pki/
$scp *.conf root@${other_master}:/etc/kubernetes/

8)、各节点重启kubelet:

  • 重启节点上的kubelet
$ systemctl restart kubelet
或者重启api、scheduler、controller三个容器

注意:查看kube-controller-manager容器是否还有报"Unauthorized",若有则重启docker。

2.3、编译kubeadm延长证书时长:

1.14后的通过NewSelfSignedCACert这个方法签发的证书都默认为10年有效期了,但这个只影响部分证书,但这样还没满足我们的需求,部分证书是通过NewSignedCert这个方法签发,而这个方法签发的证书默认只有一年有效期。

1)、下载k8s源代码修改相关证书时长:

$vi staging/src/k8s.io/client-go/util/cert/cert.go

func NewSelfSignedCACert(cfg Config, key crypto.Signer) (*x509.Certificate, error) {
    now := time.Now()
    tmpl := x509.Certificate{
        SerialNumber: new(big.Int).SetInt64(0),
        Subject: pkix.Name{
            CommonName:   cfg.CommonName,
            Organization: cfg.Organization,
        },
        NotBefore:             now.UTC(),
        //这里已经调整为10年有效期
        NotAfter:              now.Add(duration365d * 10).UTC(),
        KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
        BasicConstraintsValid: true,
        IsCA:                  true,
    }

    certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &tmpl, &tmpl, key.Public(), key)
    if err != nil {
        return nil, err
    }
    return x509.ParseCertificate(certDERBytes)
}

$vi cmd/kubeadm/app/util/pkiutil/pki_helpers.go

func NewSignedCert(cfg *certutil.Config, key crypto.Signer, caCert *x509.Certificate, caKey crypto.Signer) (*x509.Certificate, error) {
    serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64))
    if err != nil {
        return nil, err
    }
    if len(cfg.CommonName) == 0 {
        return nil, errors.New("must specify a CommonName")
    }
    if len(cfg.Usages) == 0 {
        return nil, errors.New("must specify at least one ExtKeyUsage")
    }

    certTmpl := x509.Certificate{
        Subject: pkix.Name{
            CommonName:   cfg.CommonName,
            Organization: cfg.Organization,
        },
        DNSNames:     cfg.AltNames.DNSNames,
        IPAddresses:  cfg.AltNames.IPs,
        SerialNumber: serial,
        NotBefore:    caCert.NotBefore,
        // 默认只有一年有效期,改为10年
        NotAfter:     time.Now().Add(kubeadmconstants.CertificateValidity).UTC(),​
        KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
        ExtKeyUsage:  cfg.Usages,
    }
    certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &certTmpl, caCert, key.Public(), caKey)
    if err != nil {
        return nil, err
    }
    return x509.ParseCertificate(certDERBytes)
}

##根据import 找到相关文件并修改
vim cmd/kubeadm/app/constants/constants.go​
将CertificateValidity = time.Hour * 24 * 365 改为 time.Hour * 24 * 365 * 10

2)、编译:

docker run --rm -v 你修改后的代码目录:/go/src/k8s.io/kubernetes -it icyboy/k8s_build:v1.11.5 bash

$cd /go/src/k8s.io/kubernetes

## 编译kubeadm, 这里主要编译kubeadm 即可
make all WHAT=cmd/kubeadm GOFLAGS=-v

## 编译kubelet
$make all WHAT=cmd/kubelet GOFLAGS=-v

## 编译kubectl
$make all WHAT=cmd/kubectl GOFLAGS=-v

编译完产物在 _output/bin/kubeadm 目录下将kubeadm 文件拷贝出来,替换系统中的kubeadm

3)、替换本地kubeadm:

$chmod +x kubeadm && cp -f kubeadm /usr/bin

4)、备份原有的证书和conf文件:

## 备份本地旧的证书
$cp -rp /etc/kubernetes /etc/kubernetes.bak

5)、重新生成10年的证书和新的conf文件:

## 获取k8s集群初始化的配置文件yaml文件
$kubeadm config view > kubeadm.yaml

## 生成新的证书
$kubeadm alpha phase certs renew all --config  ~/kubeadm.yaml

## 根据新证书重新生成新的配置文件
$kubeadm alpha phase kubeconfig all --config ~/kubeadm.yaml
或版本不一样可能kubeadm命令不一样可以用下面这个命令:
$kubeadm init phase kubeconfig all --config ./kubeadm.yaml

## 替换老的config文件
$cp -f /etc/kubernetes/admin.conf ~/.kube/config

6)、重启个节点kubelet:

$systemctl restart kubelet

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350