k8s證書概念
client certificate is used to authenticate client by server. (客戶端證書:用於被服務端認證)
server certificate is used by server and verified by client for server identity.(服務端證書:用來驗證使用證書的服務器的身份)
peer certificate is used by etcd cluster members as they communicate with each other in both ways.(對等證書:由etcd集羣成員使用,因爲它們以兩種方式相互通信;對等證書即是客戶端證書,也是服務端證書)
注:服務端證書一般要指定hosts,即允許哪些IP或者域名使用此證書,客戶端證書一般不需要指定hosts,或者指定爲[](爲空)
本文證書前提
本例中:只採用一個ca根證書;也可以採用多個不同ca分別進行驗證
ca證書:ca.pem、ca-key.pem(本例中etcd、k8s組件全使用同一個ca證書)
etcd證書:
peer.pem、peer-key.pem:etcd各節點相互通信的對等證書及私鑰(hosts指定所有etcd節點IP)
server.pem、server-key.pem:etcd各節點自己的服務器證書及私鑰(hosts指定當前etcd節點的IP)
client.pem、client-key.pem:命令行客戶端訪問etcd使用的證書私鑰(hosts可以不寫或者爲空)
apiserver-etcd-client.pem、apiserver-etcd-client-key.pem:apiserver訪問etcd的證書及私鑰;
注:其中peer.pem和server.pem可以使用一個,因爲都是服務端證書(hosts指定所有etcd節點IP)
client.pem和apiserver-etcd-client.pem可以使用一個,因爲都是客戶端證書(hosts都爲空或不寫)
k8s證書:
kube-apiserver.pem:kube-apiserver節點使用的證書(每個master生成一個,hosts爲當前master的IP)
kubelet.pem:kube-apiserver訪問kubelet時的客戶端證書(每個master一個,hosts爲當前master的IP)
aggregator-proxy.pem:kube-apiserver使用聚合時,客戶端訪問代理的證書(hosts爲空)
admin.pem:kubectl客戶端的證書(hosts爲空或者不寫)
生成ca證書、ca私鑰、簽發證書的策略
關於cfssl的用法參考我另一篇博客:https://blog.51cto.com/liuzhengwei521/2120535
生成簽發證書的策略
cat ca-config.json { "signing": { "default": { "expiry": "438000h" }, "profiles": { "kubernetes": { "usages": [ "signing", "key encipherment", "server auth", "client auth" ], "expiry": "438000h" } } } }
生成ca自簽名請求
cat ca-csr.json { "CN": "kubernetes", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "HangZhou", "L": "XS", "O": "k8s", "OU": "System" } ], "ca": { "expiry": "876000h" } }
生成ca證書及私鑰
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
生成etcd的peer(對等)證書
cat peer-csr.json { "CN": "etcd", "hosts": [ "192.168.10.110", "192.168.10.111", "192.168.10.112", "127.0.0.1" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "HangZhou", "L": "XS", "O": "k8s", "OU": "System" } ] } cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes peer-csr.json | cfssljson -bare peer 注:因爲是對等證書,需要指定hosts(即只能在指定的IP上使用);hosts指定的IP均爲etcd各節點的IP
生成etcd的server證書
cat server-csr.json { "CN": "etcd", "hosts": [ "192.168.10.110", "127.0.0.1" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "HangZhou", "L": "XS", "O": "k8s", "OU": "System" } ] } cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes server-csr.json | cfssljson -bare server 注:因爲是server證書,需要指定hosts(即只能在指定的IP上使用),hosts當前etcd節點的IP地址; 注:各節點均要生成此證書,如果羨麻煩,可以直接使用peer的證書
生成etcd的client證書
{ "CN": "etcd", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "HangZhou", "L": "XS", "O": "k8s", "OU": "System" } ] } cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes client-csr.json | cfssljson -bare client 注:因爲是client端證書,不需要指定hosts,因爲需要在任意節點使用此證書 注:因爲kube-apiserver也是作爲etcd的客戶端訪問etcd的,所以kube-apiserver也可以使用此證書; 注:kube-apiserver使用上面的證書時,hosts爲空,也可以指定hosts單獨爲apiserver生成證書 使用示例:查看集羣是否健康 etcdctl --key-file=./client-key.pem \ --cert-file=./client.pem \ --ca-file=./ca.pem --endpoints="https://192.168.10.110:2379" \ cluster-health
生成kubectl使用的證書(k8s管理員)
cat admin-csr.json { "CN": "admin", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "HangZhou", "L": "XS", "O": "system:masters", "OU": "System" } ] } cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin 注:CN相當於k8s中的User,names中的O相當於k8s的Group,在認證時會基於此進行鑑權 注:本例中O對應的值爲system:masters,在k8s中system:masters組綁定到了cluster-admin上了 注:cluster-admin的clusterrolebinding是對整個集羣具有管理權限 注:此證書也可用於kube-apiserver訪問kubelet使用的認證文件 --kubelet-https=true \ --kubelet-client-certificate=/etc/kubernetes/ssl/admin.pem \ --kubelet-client-key=/etc/kubernetes/ssl/admin-key.pem
[root@master01 ~]# kubectl describe clusterrolebinding cluster-admin Name: cluster-admin Labels: kubernetes.io/bootstrapping=rbac-defaults Annotations: rbac.authorization.kubernetes.io/autoupdate: true Role: Kind: ClusterRole Name: cluster-admin Subjects: Kind Name Namespace ---- ---- --------- Group system:masters 注:可以看到system:masters的類型爲Group,綁定在名字爲cluster-admin的clusterrolebinding上 注:由此admin.pem通過k8s的RBAC認證後,才能管理整個集羣;
#生成admin使用的kubeconfig文件,以完成對集羣的訪問 #設置集羣參數 kubectl config set-cluster myk8s \ --certificate-authority=ca.pem \ --embed-certs=true \ --server=https://192.168.10.103:6443 #設置客戶端認證參數 kubectl config set-credentials cluster-admin \ --client-certificate=admin.pem \ --client-key=admin-key.pem \ --embed-certs=true #設置上下文參數 kubectl config set-context admin --cluster=myk8s --user=cluster-admin #選擇使用的上下文 kubectl config use-context admin
生成kube-apiserver的證書
cat kube-apiserver-csr.json { "CN": "kubernetes", "hosts": [ "127.0.0.1", "192.168.10.103", "192.168.10.250", "10.68.0.1", "www.51yunv.com", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster", "kubernetes.default.svc.cluster.local" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "HangZhou", "L": "XS", "O": "k8s", "OU": "System" } ] } cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-apiserver-csr.json | cfssljson -bare kube-apiserver 注:kube-apiserver作爲所有訪問的入口,一定要把hosts的內容指全面,否則會造成無法訪問的情況; 注:在本例中的192.168.10.103,表示當前master節點的IP地址(每個master的替換IP後,都要生成此證書) 注:在本例中的192.168.10.250,表示VIP,即如果前面用keepalived+haproxy做HA時的VIP地址 注:在本例中的10.68.0.1,表示集羣中第一個service的地址,pod會通過此地址訪問kube-apiserver; 注:在本例中的www.51yunv.com,表示當kube-apiserver對外部提供訪問時使用的域名; 注:在本例中的kubernetes.default.svc.cluster.local,表示此集羣中的Pod通過dns訪問kube-apiserver使用的地址
生成aggregator的證書
cat aggregator-proxy-csr.json { "CN": "aggregator", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "HangZhou", "L": "XS", "O": "k8s", "OU": "System" } ] } cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes aggregator-proxy-csr.json | cfssljson -bare aggregator-proxy 注:aggregator證書用開啓kube-apiserver聚合時,客戶端訪問kube-aggregator使用的證書
生成kubelet訪問kube-apiserver的認證文件
kubelet訪問apiserver使用的是kubeconfig文件;需要先生成證書,然後通過證書生成kubeconfig文件
cat kubelet-csr.json { "CN": "system:node:10.10.5.218", "hosts": [ "127.0.0.1", "10.10.5.218" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "HangZhou", "L": "XS", "O": "system:nodes", "OU": "System" } ] } cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubelet-csr.json | cfssljson -bare kubelet 注:hosts中的10.10.5.218爲當前node節點的IP地址,不同的node要更換後生成當前node節點可以使用的證書; 然後在每個節點上都要生成當前節點可用的kubeconfig文件 #生成kubeconfig文件 kubectl config set-cluster k8s \ --certificate-authority=ca.pem \ --embed-certs=true \ --server=https://192.168.10.103:6443 \ --kubeconfig=kubelet.kubeconfig kubectl config set-credentials system:node:192.168.10.105 \ --client-certificate=kubelet.pem \ --embed-certs=true \ --client-key=kubelet-key.pem \ --kubeconfig=kubelet.kubeconfig kubectl config set-context default --cluster=k8s --user=system:node:192.168.10.105 --kubeconfig=kubelet.kubeconfig kubectl config use-context default --kubeconfig=kubelet.kubeconfig
生成kube-proxy訪問kube-apiserver的認證文件
kube-proxy訪問apiserver使用的是kubeconfig文件;需要先生成證書,然後通過證書生成kubeconfig文件
cat kube-proxy-csr.json { "CN": "system:kube-proxy", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "HangZhou", "L": "XS", "O": "k8s", "OU": "System" } ] } cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy 注:CN相當於k8s中的User,names中的O相當於k8s的Group,在RBAC籤權時的需要認證 注:本例中CN對應的值爲system:kube-proxy,在k8s中system:kube-proxy綁定到了system:node-proxier 注:system:node-proxier是專用於kube-proxy訪問kube-apiserver的 生成kubeconfig文件 kubectl config set-cluster k8s \ --certificate-authority=ca.pem \ --embed-certs=true \ --server=https://192.168.10.103:6443 \ --kubeconfig=kube-proxy.kubeconfig kubectl config set-credentials kube-proxy \ --client-certificate=kube-proxy.pem \ --embed-certs=true \ --client-key=kube-proxy-key.pem \ --kubeconfig=kube-proxy.kubeconfig kubectl config set-context default --cluster=k8s --user=kube-proxy --kubeconfig=kube-proxy.kubeconfig kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
[root@master01 etc]# kubectl describe clusterrolebinding system:node-proxier Name: system:node-proxier Labels: kubernetes.io/bootstrapping=rbac-defaults Annotations: rbac.authorization.kubernetes.io/autoupdate: true Role: Kind: ClusterRole Name: system:node-proxier Subjects: Kind Name Namespace ---- ---- --------- User system:kube-proxy 注:可以看到system:kube-proxy用戶綁定在system:node-proxier的clusterrolebinding上 這樣當kube-proxy訪問kube-apiserver就可以通過RBAC的認證;