[关闭]
@zhangsiming65965 2020-09-22T02:36:43.000000Z 字数 12434 阅读 164

K8s certificate authentication

Kubernetes

---Author:张思明 ZhangSiming

---Mail:1030728296@qq.com

---QQ:1030728296

=============================

一、数字证书原理

1.1 传统非对称加密

message --> (公钥加密) --> || 传输 || --> (私钥解密) --> message

注意:
1.这里与数字证书认证相反,是公钥加密私钥解密
2.公钥私钥需要是一个秘钥对

1.2 哈希函数

message --> H(message) --> Hash message

处理加入一个随机数,然后得出结果(加盐); 可以有效缓解在输入值是一个有效的集合,哈希值也是固定长度被别人‘试’出来的几率

message --> H(R|message) --> Hash message 

1.3 数字证书

1.3.1 数字签名

数字签名;把数据根据私钥/哈希进行加密,然后必须要对应的公钥来进行解密认证才能确保数据安全。前半句的加密过程就叫做 '数字签名'

1.3.2 数字证书认证过程

Alice想要通过证书加密让Bob安全读到自己的信息流程如下:

  1. Alice在本地生成Private Key和CSR(Certificate Signing Request)。CSR中包含了Alice的公钥和姓名,机构、地址等身份信息。
  2. Alice使用该CSR向证书机构发起数字证书申请。
  3. 证书机构验证Alice的身份后,使用CSR中的信息生成数字证书,并使用自己的CA根证书对应的私钥对该证书签名。
  4. Alice使用自己的Private Key对合同进行签名,然后将签名后的合同和自己的证书一起并发送给Bob。
  5. Bob使用操作系统中自带的证书机构根证书中的公钥来验证Alice证书中的签名,以确认Alice的身份和公钥。(使用内置根证书确认身份并获取Alice证书)
  6. Alice的证书验证成功后,Bob使用Alice证书中的公钥来验证合同中数字签名。(使用刚刚获取的Alice证书(公钥)解析Alice发送的内容)
  7. 合同数字签名通过验证,可以证明该合同为Alice本人发送,并且中间未被第三方篡改过。

注意:
1.自签发证书:证书签发商和证书持有者是同一个人,缺点是没有人能告诉你"这个人就是这个人(我就是我)"; 所以需要上面的信任证书机构的介入,多一环进行认证证明
2.证书链:但是信任的证书机构的根证书是很机密的,一旦被盗取可能会导致很多人都无法证明"我就是我", 所以一般会引入一些中间证书商,多一层上面的解析循环;这样也保证了万一中间商证书泄露,不至于全部使用证书机构的人都陷于危险之中
3.证书签发一般都是有一定时期的, 过期了就如同废纸

参考链接:https://zhaohuabing.com/post/2020-03-19-pki/

二、双向 TLS 认证原理

  1. 双向 TLS 认证需要的场景是,服务端和客户端都需要确认,这样就是正反都走一遍上面的流程,来完成双向的数据加密,保证双向的数据安全

参考链接:https://medium.com/sitewards/the-magic-of-tls-x509-and-mutual-authentication-explained-b2162dec4401

三、Kubernetes 中的证书工作机制

cert-picture

3.1 Kubernetes 中使用到的主要证书

注意:
1. 只有当你运行 kube-proxy 并要支持 扩展 API 服务器 时,才需要 front-proxy 证书

3.2 etcd证书

  1. $ ssh 10.20.11.120
  2. $ sudo systemctl status etcd
  3. etcd.service - etcd docker wrapper
  4. Loaded: loaded (/etc/systemd/system/etcd.service; enabled; vendor preset: enabled)
  5. Active: active (running) since Mon 2020-08-03 15:42:36 CST; 1 months 18 days ago
  6. $ cat /etc/etcd.env | tail -13
  7. # TLS settings
  8. ETCD_TRUSTED_CA_FILE=/etc/ssl/etcd/ssl/ca.pem # etcd验证访问 etcd 服务器的客户端证书的 CA 根证书, 服务端签名证书和服务端私钥
  9. ETCD_CERT_FILE=/etc/ssl/etcd/ssl/member-ip-10-20-11-120.pem
  10. ETCD_KEY_FILE=/etc/ssl/etcd/ssl/member-ip-10-20-11-120-key.pem
  11. ETCD_CLIENT_CERT_AUTH=true
  12. ETCD_PEER_TRUSTED_CA_FILE=/etc/ssl/etcd/ssl/ca.pem # etcd peer之间验证访问 etcd 服务器的客户端证书的 CA 根证书, 服务端签名证书和服务端私钥
  13. ETCD_PEER_CERT_FILE=/etc/ssl/etcd/ssl/member-ip-10-20-11-120.pem
  14. ETCD_PEER_KEY_FILE=/etc/ssl/etcd/ssl/member-ip-10-20-11-120-key.pem
  15. ETCD_PEER_CLIENT_CERT_AUTH=True
  16. # 验证etcd证书过期时间
  17. $ sudo openssl x509 -in /etc/ssl/etcd/ssl/ca.pem -noout -dates
  18. notBefore=Aug 6 05:07:43 2019 GMT
  19. notAfter=Jul 13 05:07:43 2119 GMT

3.3 kube-apiserver证书

  1. $ ssh 10.20.11.120
  2. $ cd /etc/kubernetes
  3. $ cat manifests/kube-apiserver.yaml
  4. apiVersion: v1
  5. kind: Pod
  6. metadata:
  7. creationTimestamp: null
  8. labels:
  9. component: kube-apiserver
  10. tier: control-plane
  11. name: kube-apiserver
  12. namespace: kube-system
  13. spec:
  14. containers:
  15. - command:
  16. - kube-apiserver
  17. - --advertise-address=10.20.11.120
  18. - --etcd-cafile=/etc/ssl/etcd/ssl/ca.pem # 用于验证 etcd 客户端证书的 CA 根证书, 用于访问 etcd 的客户端证书和私钥
  19. - --etcd-certfile=/etc/ssl/etcd/ssl/node-ip-10-20-11-120.pem
  20. - --etcd-keyfile=/etc/ssl/etcd/ssl/node-ip-10-20-11-120-key.pem
  21. - --kubelet-client-certificate=/etc/kubernetes/ssl/apiserver-kubelet-client.crt # 用于访问 kubelet 的客户端证书和私钥
  22. - --kubelet-client-key=/etc/kubernetes/ssl/apiserver-kubelet-client.key
  23. - --proxy-client-cert-file=/etc/kubernetes/ssl/front-proxy-client.crt # 只有当你运行 kube-proxy 并要支持 扩展 API 服务器 时,才需要 front-proxy 证书
  24. - --proxy-client-key-file=/etc/kubernetes/ssl/front-proxy-client.key
  25. - --client-ca-file=/etc/kubernetes/ssl/ca.crt # 用于验证访问 kube-apiserver 的客户端的证书的 CA 根证书
  26. - --service-account-key-file=/etc/kubernetes/ssl/sa.pub # 用于验证 service account token 的公钥
  27. - --tls-cert-file=/etc/kubernetes/ssl/apiserver.crt # 用于对外提供服务的服务器证书和私钥
  28. - --tls-private-key-file=/etc/kubernetes/ssl/apiserver.key
  29. ...

3.4 controller-manager, kubelet, scheduler证书

上面三个apiserver的客户端组件的证书都写在了对应的KUBECONFIG中,名为controller-manager.conf, kubelet.conf, scheduler.conf, 就不一一展示, 随便列举一个如下:

  1. # 包含验证apiserver证书的ca证书, 还有请求时候的看客户端证书和私钥
  2. root@ip-10-20-11-120:/etc/kubernetes# cat scheduler.conf
  3. apiVersion: v1
  4. clusters:
  5. - cluster:
  6. certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRFNU1EZ3dOakExTURrek1Gb1hEVEk1TURnd016QTFNRGt6TUZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTWg2Ck5JOEJBUzVGUUlORUlwalNIQjN6V2lPdGNpUDU5NDNEMTU4Q0hIMmNhVitYalQxS2RsQ1pNRys0bVNRd3dmSE8KNEtINjdnWGF0RDBoRVBlYjVlZm4zYUQvTkRxME1FWWRBRUNEWDAvdmxUWUtjS1l4bHcwTXorbUlhK00vWE5aUgozaE5aejBwbEVDS2F4c2ZXSVVaSUNJb1VFOFA5ZHBqemdOck5WdTV6WHR3T3crOVhFUVp1aHlwVzlvTWFneEN1ClpWcUJJUURzZHFrejdoZEVVOWh5TGJLVXQrbnZlTGNETHJHV2dVSFBJTjBycmE1NXRQYTR1RTN3MXpvZWRGa0QKeFF6ZzZFSTZJRmNCMFM0d2ttU2cxNkV2N0JUajZpUzNTNHd2d0pwd3RCVWY5bVc1Sm1zYnZkckFlL1pOMldNKwo3aUZkTFFpMzRlKzg1eUFJOHM4Q0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFFVFBLNDZHV0dMMVpmSHFWT3pzengzL0lab04KRnErOUxXejJIdTRHaWlmUmdJakJUODVOc1J1VDJUQlNCSVRXZzlNUUM1ZFRpSTVzWnh0MENsV29XaFRML2E1MwprbzBXa1VWVVY5SjhmZDZ0RHdZNXNMTmdZeHliM2VZblEzTXU4QVMrZ2NSZWVtVjFCMFc0T0JkSW52eTFkdVhICndVMmM3WmhwYzFpdkNUVmowcXBkVFhRTmw2bGlNUWpQWXY4eTdyblFCMTZ0K0VTRXZPRzFCeHRWVUFJdXFET0oKeHNaY2MvdmJCZjBjbDBiMk9iQmIwSG4rbEVxb25TcnJlZnlncXZtYTNwbVNaMDIzTG5aMXkzdjFSMEkzVjlVZApoOTJRb2t6K2x0QUNQU3UzTHVJSXBpR3VxbVZNeTNtL21YamU2L0d0eDJYbWtxTUtITmNuNlBTSWU4UT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
  7. server: https://10.20.11.120:6443
  8. name: kubernetes
  9. contexts:
  10. - context:
  11. cluster: kubernetes
  12. user: system:kube-scheduler
  13. name: system:kube-scheduler@kubernetes
  14. current-context: system:kube-scheduler@kubernetes
  15. kind: Config
  16. preferences: {}
  17. users:
  18. - name: system:kube-scheduler
  19. user:
  20. client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMzakNDQWNhZ0F3SUJBZ0lJSEdKbkpVMUtvcE13RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB4T1RBNE1EWXdOVEE1TXpCYUZ3MHlNVEE0TURNd056TTRNalphTUNBeApIakFjQmdOVkJBTVRGWE41YzNSbGJUcHJkV0psTFhOamFHVmtkV3hsY2pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCCkJRQURnZ0VQQURDQ0FRb0NnZ0VCQU1VOEFPY245OFdtZlVJOEc4VEdsN0Vaa09oeFY3eVpETXo5cDNIbWIyWnEKOVljTFRDdDd4OUswVG9yZW1CMG4vdG5qTmkrbFo3eXJsdGFHaXpjeVZ5Q0ZQWmQyUit0ZjlVNWcwNU5yTUxJcApZOHJjL3pOS0FMQSs3dk5FL0RxRDQya1pBMnpKUXMxU0RNUkFKZ3FaWmVXLzJIQmRPVS9xc0xrRkVVbGVZYmQ3CnhlczRHeWFLMUVrYXVvU2ptdlM2ODR1cnpaU1o5TzFLQnFVN2dicDVzandBZzl2WVVCVU5vSGw0alNQYU1sQ2EKYWVEZG1CRmtNVm5rWk9vR3haeUZ2WHVjcTVzdnJ4b1JsUElXOUVwS1hORFpaOVAyaTJNZitZWlRocDEzTFFKTwp0Q2dWd0lFVXo3S1ZBMDROTjA3L2J6RkcxeWxLUHVlMVluTWNjc2t4dkw4Q0F3RUFBYU1uTUNVd0RnWURWUjBQCkFRSC9CQVFEQWdXZ01CTUdBMVVkSlFRTU1Bb0dDQ3NHQVFVRkJ3TUNNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUIKQVFDYmx2RzlUTno0eThTNFFoNU5WZUhudjhPeG96VkRHa09IOHIvRzVEU2ZUazVCTFhmQjgvRU9mbzNnLytnZwpRNDZtMTVIdnFTYVhtYU5iKys1Mlg4N3BtLzFWZmgycVduUW9XVmdmQkdGL0FuMWN1TW1Ra0hWTlB4bEVoeHZuCjhEb1k2SEMwdy9LUW1OTGRuOEI5bys3UEJGRlhmaE9KY2RkMkc1SWNpS0Y2ZEk3UkJHVFBIZGE1TzJJb0Y4OEsKLzY3MnN5UGFIYXJENFFQWkZEYUVLRGNwa0w0UEpQYlM4QTlweTM3dVJuZVQ1dkp3MjFnVXY4RlFveWtnWkQwZAo0QkozL05Ld0dEZUQ5aFE2amhXM01SYjNGTkVjU00vNGc2NXh4VmpiNlRJM0tlenpkdFRZTnQwUm5IVkdXNk0zCmNPVjI5MzgzR1FWUkZWT3NVK2JQQ2JycgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
  21. client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBeFR3QTV5ZjN4YVo5UWp3YnhNYVhzUm1RNkhGWHZKa016UDJuY2VadlptcjFod3RNCkszdkgwclJPaXQ2WUhTZisyZU0yTDZWbnZLdVcxb2FMTnpKWElJVTlsM1pINjEvMVRtRFRrMnN3c2lsanl0ei8KTTBvQXNEN3U4MFQ4T29QamFSa0RiTWxDelZJTXhFQW1DcGxsNWIvWWNGMDVUK3F3dVFVUlNWNWh0M3ZGNnpnYgpKb3JVU1JxNmhLT2E5THJ6aTZ2TmxKbjA3VW9HcFR1QnVubXlQQUNEMjloUUZRMmdlWGlOSTlveVVKcHA0TjJZCkVXUXhXZVJrNmdiRm5JVzllNXlybXkrdkdoR1U4aGIwU2twYzBObG4wL2FMWXgvNWhsT0duWGN0QWs2MEtCWEEKZ1JUUHNwVURUZzAzVHY5dk1VYlhLVW8rNTdWaWN4eHl5VEc4dndJREFRQUJBb0lCQUd6KzJOemxhSGFRcUI0SApTNjAxdGpTSGxWM3U3UFpyZWZoNm9LTkFIZ1h5UzljaU5paTlrZEx1RTQySXIzVkZXZ0FkSVIrNWY1ZHpGN3RiCnhPbHU1MWt3YUxZZ0JtU2J0ZHRuaE9TdDBzNVNNelN6WmxCNHIrSzJGS1RaVmE0Y25uckErUFNRVUZ0WTRYYysKb0FjeGVHODcwcWRkelVOTnhmV3BTRUZNYUNIVnlYeW1RQ1lRNXdBVDR0am1tNHZGNm9LbktHeldIRWZSWEQ4OAo3YUYrVmcyMzlVNHhzQWpRUHFsMFc1M3FyUFB1R0pjMXhJWUJ5RzVuQ2pRa0tPVlEzRUt1NVNPTUdlSFhsRmpvCnUraStkN3NDaDBvWStlUTRyREJXNFYwdGFCczAxM2VjTDUrNHRDRjhuQW1mZzBoQ0RVSkY4QnJpM1ZCeWoyTWUKNmhCelhMa0NnWUVBeHdCbWRIRlVZVTNEMU9sRGFnd2sxN1p5TUtjbG1DWmlxSWwvOHdaZ3ZMb0puaVlCUS9QUApZVFdObXNpMnd3bWpMcFhaT2lLcDVnRldheWxMYnRKekVXRnpnbEtPYnM4WnB4eEtEMTAvdlhmK0ZFRXJnMkd0Cmd2UEw1YjBtdERWNTB5aGt4TDE4U2MyNWJGd3NRSTVISzdtaisyM1k4WEFpeGxQcno2Snl6QzBDZ1lFQS9ib0cKNUlGcjRTYlJrSEoxeEozS2orVEswRXRldGZRbTNRKytRLzVXbGQ3VWtvNHI4RUZWQ2lscEpiTWVOa1AwUjhZYQovcjRaNzJYREpjMXdPcFVvNjN0TGlXSkxQdUVwOGNhalNsSDc4QlNHRUdXaGEwZ0pTYnJPUHEvdW16OW53ZlV5CmN0SExTa0Z6THlLWkd5dmViZ2dVWTlTVjRYVklqQmU4MXZ0cmhCc0NnWUVBbzQzQnB2d3AxSnNjVTFXdjBXM1AKcmZiR0hSU1RBbHl5QTBDWEJ6NzdyTURkL0x2Um1HNit4MjlEUmE2bS90OWgzWHpNLzBuVUJ6U2NPUkRFYlgzTAprc0pjTkFUMENVQnZIZmhUS2hPQ3VvN3ZKT2gzQWRENjBVRGNHS0tBTitZbmpST0sxbVBCemNxbUZkZ2ZpcU1rCi9WdmkyVmRyME90UHVWN3AxVW4zUGJVQ2dZRUFtUlpDem1CZ0xNcjFLb2hGRWtwNlMzT3FBeDlXbDhZbUpMODQKOTJGZjhMRXY1UFV2QVprSnJFWHNFVGtQZzRKZ3cyVitLREdmQ0ZpSDlDa09DK3F2YzlWQ2NEUUVYbjRRaHJacApFNUIveUEwNkRtNmpoRTFFZlYzZXp1ZnJ1WFA2TUlhMjE1eEpZaFkzWHpzcTBjQVlScDlOWGlhSUFDNTVoVDFWClRRa0poLzBDZ1lFQXJKdnZiSWxIdWV5VU5ScitqM3FQejFIS3RtQmhZc0dEN3QrU2FEeDJlaVBSdzNsL1g0MEQKVFFFYVBNY291dXgrZkN3SmtzTnFqcGZ6Sjk5M1RacHYxL0owR01rUXhKZVdvOGN0bGdEVVBIMjlsOW9FUVlWegpralJ4ZCt6Q0tiUnhyTDVkaDRpMmlDeUNSSkdYNSt2Rm83QjlYaEdCVDRiZkNFYk1iSWRyam9FPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=

3.5 Service Account 秘钥对

Service account 主要被 pod 用于访问 kube-apiserver。 在为一个 pod 指定了 service account 后,kubernetes 会为该 service account 生成一个 JWT token,并使用 secret 将该 service account token 挂载到 pod 上。pod 中的应用可以使用 service account token 来访问 api server。service account 证书被用于生成和验证 service account token
注意:
1. Service account加密过程是文章开头说的"非对称加密", 也就是说只是controller-manager私钥加密数据, 然后kube-apiserver的公钥进行解密而已
2. 由于是非对称加密, 也就是说没有"双向 tls 认证"
3. istio的做法就是为每个 service account 生成一个证书, 之后就可以"双向 tls 认证"

sa-key

  1. $ cat manifests/kube-controller-manager.yaml | grep service-account
  2. - --service-account-private-key-file=/etc/kubernetes/ssl/sa.key
  3. - --use-service-account-credentials=true
  4. $ cat manifests/kube-apiserver.yaml | grep service-account
  5. - --service-account-key-file=/etc/kubernetes/ssl/sa.pub

FAQ:

1. 在安装 Kubernetes 时,我们需要为每一个工作节点上的 Kubelet 分别生成一个证书。由于工作节点可能很多,手动生成 Kubelet 证书的过程会比较繁琐怎么办?
  1. Kubernetes 提供了一个 certificates.k8s.io API,可以使用配置的 CA 根证书来签发用户证书
  2. Kubernetes 提供了 TLS bootstrapping 的方式来简化 Kubelet 证书的生成过程, 过程如下:(需要apiserver启用--enable-bootstrap-token-auth)

1) 调用 kube-apiserver 生成一个 bootstrap token
2) 将该 bootstrap token 写入到一个 kubeconfig 文件中,作为 kubelet 调用 kube-apiserver 的客户端验证方式
3) 通过 --bootstrap-kubeconfig 启动参数将 bootstrap token 传递给 kubelet 进程
4) Kubelet 采用bootstrap token 调用 kube-apiserver API,生成自己所需的服务器和客户端证书
5) 证书生成后,Kubelet 采用生成的证书和 kube-apiserver 进行通信,并删除本地的 kubeconfig 文件,以避免 bootstrap token 泄漏风险

参考链接:
https://zhaohuabing.com/post/2020-05-19-k8s-certificate/
https://kubernetes.io/zh/docs/tasks/tls/managing-tls-in-a-cluster/

2. 如何升级kubernetes证书但是不让serviceaccout轮换?

我们都知道 serviceaccount 的 token 是依赖于 sa.key 和 sa.pub 的,也就是说如果这俩秘钥更换了,所有的 serviceaccout 就都失效了,会重新创建(kube-system命名空间的会自动轮换,其他ns的需要手动); 但是如果只是更换证书的话,其实是不需要更换sa秘钥对的,因为sa秘钥对采用的是"非对称加密", 也就是说永不过期,除非删除秘钥对;事实上我们只要手动更换其他证书即可:

  1. $ cp -R /etc/kubernetes/ssl /etc/kubernetes/ssl.backup
  2. $ cp /etc/kubernetes/admin.conf /etc/kubernetes/admin.conf.backup
  3. $ cp /etc/kubernetes/controller-manager.conf /etc/kubernetes/controller-manager.conf.backup
  4. $ cp /etc/kubernetes/kubelet.conf /etc/kubernetes/kubelet.conf.backup
  5. $ cp /etc/kubernetes/scheduler.conf /etc/kubernetes/scheduler.conf.backup
  6. $ kubeadm alpha certs renew apiserver-kubelet-client
  7. $ kubeadm alpha certs renew apiserver
  8. $ kubeadm alpha certs renew front-proxy-client
  9. $ kubeadm alpha kubeconfig user --client-name system:kube-controller-manager > /etc/kubernetes/controller-manager.conf
  10. $ kubeadm alpha kubeconfig user --client-name system:kube-scheduler > /etc/kubernetes/scheduler.conf
  11. $ kubeadm alpha kubeconfig user --client-name system:node:{nodename} --org system:nodes > /etc/kubernetes/kubelet.conf
  12. $ kubeadm alpha kubeconfig user --client-name kubernetes-admin --org system:masters > /etc/kubernetes/admin.conf
  13. $ cp /etc/kubernetes/admin.conf ~/.kube/config

最后重启基础组件即可(嫌麻烦可以直接master节点关机重启)

参考链接:https://github.com/kubernetes-sigs/kubespray/issues/5464

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注