Kubernetes 之 二進制安裝(二) 證書詳解

前言
node

在進行二進制搭建K8S集羣前,咱們須要梳理通最磨人的一個點,就是各類各樣的證書機制。這一步是在安裝配置kubernetes的全部步驟中最容易出錯也是最難排查問題的一步,而這卻恰好是第一步,萬事開頭難,不要由於這點困難就望而卻步。linux

一共有多少證書?json

官方文檔參考https://kubernetes.io/docs/setup/certificates/bootstrap

先從Etcd算起:
vim

一、Etcd對外提供服務,要有一套etcd server證書api

二、Etcd各節點之間進行通訊,要有一套etcd peer證書瀏覽器

三、Kube-APIserver訪問Etcd,要有一套etcd client證書安全

再算kubernetes:bash

四、Kube-APIserver對外提供服務,要有一套kube-apiserver server證書服務器

五、kube-scheduler、kube-controller-manager、kube-proxy、kubelet和其餘可能用到的組件,須要訪問kube-APIserver,要有一套kube-APIserver client證書

六、kube-controller-manager要生成服務的service account,要有一對用來簽署service account的證書(CA證書)

七、kubelet對外提供服務,要有一套kubelet server證書

八、kube-APIserver須要訪問kubelet,要有一套kubelet client證書

加起來共8套,可是這裏的「套」的含義咱們須要理解。

同一個套內的證書必須是用同一個CA籤署的簽署不一樣套裏的證書的CA能夠相同,也能夠不一樣。例如,全部etcd server證書須要是同一個CA簽署的,全部的etcd peer證書也須要是同一個CA簽署的,而一個etcd server證書和一個etcd peer證書,徹底能夠是兩個CA機構簽署的,彼此沒有任何關係。這算兩套證書。

爲何同一個「套」內的證書必須是同一個CA簽署的

緣由在驗證這些證書的一端。由於在要驗證這些證書的一端,一般只能指定一個Root CA。這樣一來,被驗證的證書天然都須要是被這同一個Root CA對應的私鑰簽署,否則不能經過認證。

其實實際上,使用一套證書(都使用一套CA來簽署)同樣能夠搭建出K8S,同樣能夠上生產,可是理清這些證書的關係,在遇到由於證書錯誤,請求被拒絕的現象的時候,不至於無從下手,並且若是沒有搞清證書之間的關係,在維護或者解決問題的時候,貿然更換了證書,弄很差會把整個系統搞癱。

TLS bootstrapping 簡化kubelet證書製做

Kubernetes1.4版本引入了一組簽署證書用的API。這組API的引入,使咱們能夠不用提早準備kubelet用到的證書。

每一個kubelet用到的證書都是獨一無二的,由於它要綁定各自的IP地址,因而須要給每一個kubelet單獨製做證書,若是業務量很大的狀況下,node節點會不少,這樣一來kubelet的數量也隨之增長,並且還會常常變更(增減Node)kubelet的證書製做就成爲一件很麻煩的事情。使用TLS bootstrapping就能夠省事兒不少。

工做原理:Kubelet第一次啓動的時候,先用同一個bootstrap token做爲憑證。這個token已經被提早設置爲隸屬於用戶組system:bootstrappers,而且這個用戶組的權限也被限定爲只能用來申請證書。 用這個bootstrap token經過認證後,kubelet申請到屬於本身的兩套證書(kubelet server、kube-apiserver client for kubelet),申請成功後,再用屬於本身的證書作認證,從而擁有了kubelet應有的權限。這樣一來,就去掉了手動爲每一個kubelet準備證書的過程,而且kubelet的證書還能夠自動輪替更新

官方文檔參考https://kubernetes.io/docs/tasks/tls/certificate-rotation/

kubelet證書爲什麼不一樣

這樣作是一個爲了審計,另外一個爲了安全。 每一個kubelet既是服務端(kube-apiserver須要訪問kubelet),也是客戶端(kubelet須要訪問kube-apiserver),因此要有服務端和客戶端兩組證書。

服務端證書須要與服務器地址綁定,每一個kubelet的地址都不相同,即便綁定域名也是綁定不一樣的域名,故服務端地址不一樣

客戶端證書也不該相同,每一個kubelet的認證證書與所在機器的IP綁定後,能夠防止一個kubelet的認證證書泄露之後,使從另外的機器上僞造的請求經過驗證。

安全方面,若是每一個node上保留了用於簽署證書的bootstrap token,那麼bootstrap token泄漏之後,是否是能夠隨意簽署證書了?安全隱患很是大。因此,kubelet啓動成功之後,本地的bootstrap token須要被刪除。

正式製做證書

雖然能夠用多套證書,可是維護多套CA實在過於繁雜,這裏仍是用一個CA簽署全部證書。

須要準備的證書:

  • admin-key.pem

  • admin.pem

  • ca-key.pem

  • ca.pem

  • kube-proxy-key.pem

  • kube-proxy.pem

  • kubernetes-key.pem

  • kubernetes.pem

使用證書的組件以下:

  • etcd:使用 ca.pem、kubernetes-key.pem、kubernetes.pem

  • kube-apiserver:使用 ca.pem、kubernetes-key.pem、kubernetes.pem

  • kubelet:使用 ca.pem

  • kube-proxy:使用 ca.pem、kube-proxy-key.pem、kube-proxy.pem

  • kubectl:使用 ca.pem、admin-key.pem、admin.pem

  • kube-controller-manager:使用 ca-key.pem、ca.pem

咱們使用CFSSL來製做證書,它是cloudflare開發的一個開源的PKI工具,是一個完備的CA服務系統,能夠簽署、撤銷證書等,覆蓋了一個證書的整個生命週期,後面只用到了它的命令行工具。

注:通常狀況下,K8S中證書只須要建立一次,之後在向集羣中添加新節點時只要將/etc/kubernetes/ssl目錄下的證書拷貝到新節點上便可。

下載安裝cfssl命令行工具

[root@dong bin]# mkdir -p /usr/local/bin/cfssl
[root@dong bin]# wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 
[root@dong bin]# wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 
[root@dong bin]# wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 
[root@dong bin]# chmod +x cfssl*
[root@dong bin]# mv cfssl_linux-amd64 /usr/local/bin/cfssl
[root@dong bin]# mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
[root@dong bin]# mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo
[root@dong bin]# export PATH=/usr/local/bin:$PATH

建立CA證書

建立存放證書目錄

[root@dong bin]# mkdir -p /opt/kubernetes/ssl/
[root@dong bin]# cd /opt/kubernetes/ssl/

建立證書配置文件

[root@dong ssl]# vim ca-config.json
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "87600h"
      }
    }
  }
}

字段說明:

ca-config.json:能夠定義多個 profiles,分別指定不一樣的過時時間、使用場景等參數;後續在簽名證書時使用某個 profile;

signing:表示該證書能夠簽名其餘證書;生成的ca.pem證書中 CA=TRUE;

server auth:表示client能夠用該 CA 對server提供的證書進行驗證;

client auth:表示server能夠用該CA對client提供的證書進行驗證

expiry:過時時間

建立CA證書籤名請求文件

[root@dong ssl]# vim ca-csr.json
{
  "CN": "kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ],
    "ca": {
       "expiry": "87600h"
    }
}

字段說明:

「CN」:Common Name,kube-apiserver 從證書中提取該字段做爲請求的用戶名 (User Name);瀏覽器使用該字段驗證網站是否合法;

「O」:Organization,kube-apiserver 從證書中提取該字段做爲請求用戶所屬的組 (Group);

生成CA證書和私鑰

[root@dong ssl]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca
[root@dong ssl]# ls | grep ca
ca-config.json
ca.csr
ca-csr.json
ca-key.pem
ca.pem

其中ca-key.pem是ca的私鑰,ca.csr是一個簽署請求,ca.pem是CA證書,是後面kubernetes組件會用到的RootCA。

建立kubernetes證書

建立kubernetes證書籤名請求文件 kubernetes-csr.json

[root@dong ssl]# vim kubernetes-csr.json
{
    "CN": "kubernetes",
    "hosts": [
      "127.0.0.1",
      "192.168.214.88",
      "192.168.214.89",
      "192.168.214.90",
      "192.168.214.200",
      "192.168.214.201",
      "192.168.214.202",
      "10.254.0.1",
      "192.168.214.210",
      "192.168.214.1/24",
      "kubernetes",
      "kube-api.wangdong.com",
      "kubernetes.default",
      "kubernetes.default.svc",
      "kubernetes.default.svc.cluster",
      "kubernetes.default.svc.cluster.local"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "ST": "BeiJing",
            "L": "BeiJing",
            "O": "k8s",
            "OU": "System"
        }
    ]
}

字段說明:

若是 hosts 字段不爲空則須要指定受權使用該證書的 IP 或域名列表。

因爲該證書後續被 etcd 集羣和 kubernetes master使用,將etcd、master節點的IP都填上,同時還有service網絡的首IP。(通常是 kube-apiserver 指定的 service-cluster-ip-range 網段的第一個IP,如 10.254.0.1)

我這裏的設置包括一個私有鏡像倉庫,三個etcd,三個master,以上物理節點的IP也能夠更換爲主機名。

生成kubernetes證書和私鑰

[root@dong ssl]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
[root@dong ssl]# ls |grep kubernetes
kubernetes.csr
kubernetes-csr.json
kubernetes-key.pem
kubernetes.pem

建立admin證書

建立admin證書籤名請求文件admin-csr.json

[root@dong ssl]# admin-csr.json
{
  "CN": "admin",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "system:masters",
      "OU": "System"
    }
  ]
}

說明:

後續 kube-apiserver 使用 RBAC 對客戶端(如 kubelet、kube-proxy、Pod)請求進行受權;

kube-apiserver 預約義了一些 RBAC 使用的 RoleBindings,如 cluster-admin 將 Group system:masters 與 Role cluster-admin 綁定,該 Role 授予了調用kube-apiserver 的全部 API的權限;

O指定該證書的 Group 爲 system:masters,kubelet 使用該證書訪問 kube-apiserver 時 ,因爲證書被 CA 簽名,因此認證經過,同時因爲證書用戶組爲通過預受權的 system:masters,因此被授予訪問全部 API 的權限;

注:這個admin 證書,是未來生成管理員用的kube config 配置文件用的,如今咱們通常建議使用RBAC 來對kubernetes 進行角色權限控制, kubernetes 將證書中的CN 字段 做爲User, O 字段做爲 Group

生成admin證書和私鑰

[root@dong ssl]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
[root@dong ssl]# ls | grep admin
admin.csr
admin-csr.json
admin-key.pem
admin.pem

建立kube-proxy證書

建立 kube-proxy 證書籤名請求文件 kube-proxy-csr.json

[root@dong ssl]# vim kube-proxy-csr.json
{
  "CN": "system:kube-proxy",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}

說明:

CN 指定該證書的 User 爲 system:kube-proxy;

kube-apiserver 預約義的 RoleBinding system:node-proxier 將User system:kube-proxy 與 Role system:node-proxier 綁定,該 Role 授予了調用 kube-apiserver Proxy 相關 API 的權限;

生成kube-proxy證書和私鑰

[root@dong ssl]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes  kube-proxy-csr.json | cfssljson -bare kube-proxy
[root@dong ssl]# ls |grep kube-proxy
kube-proxy.csr
kube-proxy-csr.json
kube-proxy-key.pem
kube-proxy.pem

通過上述操做,咱們會用到以下文件:

[root@dong ssl]# ls | grep pem
admin-key.pem
admin.pem
ca-key.pem
ca.pem
kube-proxy-key.pem
kube-proxy.pem
kubernetes-key.pem
kubernetes.pem

查看證書信息

[root@master1 ssl]# cfssl-certinfo -cert kubernetes.pem
{
  "subject": {
    "common_name": "kubernetes",
    "country": "CN",
    "organization": "k8s",
    "organizational_unit": "System",
    "locality": "BeiJing",
    "province": "BeiJing",
    "names": [
      "CN",
      "BeiJing",
      "BeiJing",
      "k8s",
      "System",
      "kubernetes"
    ]
  },
  "issuer": {
    "common_name": "kubernetes",
    "country": "CN",
    "organization": "k8s",
    "organizational_unit": "System",
    "locality": "BeiJing",
    "province": "BeiJing",
    "names": [
      "CN",
      "BeiJing",
      "BeiJing",
      "k8s",
      "System",
      "kubernetes"
    ]
  },
  "serial_number": "321233745860282370502438768971300435157761820875",
  "sans": [
    "192.168.214.1/24",
    "kubernetes",
    "kube-api.wangdong.com",
    "kubernetes.default",
    "kubernetes.default.svc",
    "kubernetes.default.svc.cluster",
    "kubernetes.default.svc.cluster.local",
    "127.0.0.1",
    "192.168.214.88",
    "192.168.214.89",
    "192.168.214.90",
    "192.168.214.200",
    "192.168.214.201",
    "192.168.214.202",
    "10.254.0.1",
    "192.168.214.210"
  ],
  "not_before": "2019-03-12T11:26:00Z",
  "not_after": "2029-03-09T11:26:00Z",
  "sigalg": "SHA256WithRSA",
  "authority_key_id": "CB:34:54:33:1F:F4:37:E:E5:94:B7:F5:8A:3D:F4:A4:43:43:E2:7F",
  "subject_key_id": "EC:31:D8:5F:4:E3:6F:C2:7F:DA:A8:F0:BD:A:B9:1F:56:7B:9A:DF",
  "pem": "-----BEGIN CERTIFICATE-----\nMIIExjCCA66gAwIBAgIUOESejeFvtUe1qwPcXOQdC9a6iMswDQYJKoZIhvcNAQEL\nBQAwZTELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaUppbmcxEDAOBgNVBAcTB0Jl\naUppbmcxDDAKBgNVBAoTA2s4czEPMA0GA1UECxMGU3lzdGVtMRMwEQYDVQQDEwpr\ndWJlcm5ldGVzMB4XDTE5MDMxMjExMjYwMFoXDTI5MDMwOTExMjYwMFowZTELMAkG\nA1UEBhMCQ04xEDAOBgNVBAgTB0JlaUppbmcxEDAOBgNVBAcTB0JlaUppbmcxDDAK\nBgNVBAoTA2s4czEPMA0GA1UECxMGU3lzdGVtMRMwEQYDVQQDEwprdWJlcm5ldGVz\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAteZIJbL5G2ZHEKajyVe7\nv4E1F9K9RzLTxghStRo808QOpVclOkFRHCi2qplrFrQmW4d/5AhJmofdoBuwIe/T\n3UgrhlPj1rWC5DhaG8J7+wOIp62yURslnXE+A+EsXQLXxeKxrbrodNwTmGJHXdGl\nv2pi0lyAgewdnhJHcYTvQbrDvbxpqYOHqKzJ3sqm1TSjnWSI9C1Hk/iF9xmjA4CG\nLDHocnxzNv+T/qSofv0yyGgA/HovlNxP+jSIwaWJu3QHhOxV3k2Bj7i0jSJoq3n9\nDl4co22Ge4SLiI2zPZayt9whzSyUoc5eloYJ1w7INcmfz2gOYl7L3godLg/gI5Eh\nNQIDAQABo4IBbDCCAWgwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUF\nBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTsMdhfBONvwn/a\nqPC9CrkfVnua3zAfBgNVHSMEGDAWgBTLNFQzH/Q3DuWUt/WKPfSkQ0PifzCB6AYD\nVR0RBIHgMIHdghAxOTIuMTY4LjIxNC4xLzI0ggprdWJlcm5ldGVzghVrdWJlLWFw\naS53YW5nZG9uZy5jb22CEmt1YmVybmV0ZXMuZGVmYXVsdIIWa3ViZXJuZXRlcy5k\nZWZhdWx0LnN2Y4Iea3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVygiRrdWJl\ncm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWyHBH8AAAGHBMCo1liHBMCo\n1lmHBMCo1lqHBMCo1siHBMCo1smHBMCo1sqHBAr+AAGHBMCo1tIwDQYJKoZIhvcN\nAQELBQADggEBADtxejgpSQy913K9YyVLcS2k9bs41mZZbuokyrZiJeJ/CKZKzCo+\ngnF7P9/35IjkNlnYhlpUTTIJbnlQY8mDyKx1AaZOkzr+2djYRpg2vL3E7+CdRldQ\nUpNANSITolInKqboXev8SlLF9Mc/dWqgZzoifezuEkZ+c5KM6MY6MpMDVjVKNBxy\nJTd3bZNaPopop8IWxLAel5IQbzUhooswtzUxUslwKnYYC9tsKc5AgiXdehCnbGNf\nIr6wkK2OJBJStNPqarnpH6FZ6JxJ+qt59SdNhLixOT84HBR7ews/ZCYhQuPaJTy2\nwIb0XOtxILF3JMBNW/n21IyhF0vXsMdLg+o=\n-----END CERTIFICATE-----\n"
}

在搭建k8s集羣的時候,將這些文件分發到至此集羣中其餘節點機器中便可。至此,TLS證書建立完畢

相關文章
相關標籤/搜索