k8s各證書生成相關內容

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的認證;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章