k8s實踐(8)--ssl安全認證配置

一.基於CA簽名的雙向數字證書認證方式


在一個安全的內網環境中, Kubernetes的各個組件與Master之間可以通過apiserver的非安全端口http://apiserver:8080進行訪問。但如果apiserver需要對外提供服務,或者集羣中的某些容器也需要訪問apiserver以獲取集羣中的某些信息,則更安全的做法是啓用HTTPS安全機制。Kubernetes提供了基於CA簽名的雙向數字證書認證方式和簡單的基於HTTP BASE或TOKEN的認證方式,其中CA證書方式的安全性最高。本節先介紹以CA證書的方式配置Kubernetes集羣,要求Master上的kube-apiserver.kube-controller-manager. kube-scheduler進程及各Node上的kubelet, kube-proxy進程進行CA簽名雙向數字證書安全設置

k8s中哪些組件需要進行tls證書認證,哪些不需要?

kube-scheduler、kube-controller-manager 一般和 kube-apiserver 部署在同一臺機器上,它們使用非安全端口和 kube-apiserver通信,非安全端口默認爲http的8080,可以使用--insecure-port指定,監聽非安全端口的地址默認爲127.0.0.1,可以使用--insecure-bind-address指定;

kubelet、kube-proxy、kubectl 部署在其它 Node 節點上,如果通過安全端口訪問 kube-apiserver,則必須先通過 TLS 證書認證,再通過 RBAC 授權。安全端口默認爲https的6443,可以使用--secure-port指定,監聽安全端口的地址默認爲0.0.0.0(監聽所有接口),可以使用--bind-address指定。

 

1、基於CA簽名的雙向數字證書的生成過程如下:

(1)爲kube-apiserver生成一個數字證書,並用CA證書進行簽名。

(2)爲kube-apiserver進程配置證書相關的啓動參數,包括CA證書(用於驗證客戶端證書的簽名真僞)、自己的經過CA簽名後的證書及私鑰,

(3)爲每個訪問Kubernetes API Server的客戶端(如kube-controller-manager.kube-scheduler,kubelet, kube-proxy及調用API Server的客戶端程序kubectl等)進程生成自己的數字證書,也都用CA證書進行簽名,在相關程序的啓動參數裏增加CA證書、自己的證書等相關參數。1)設置kube-apiserver的CA證書相關的文件和啓動參數

 

生成如下證書:

根證書公鑰與私鑰:ca-public.pem ca-private.pem

API Server公鑰與私鑰:apiserver-public.pemapiserver-private.pem

從節點公鑰與私鑰kubelet-publi.pemkubelet-private.pem

集羣管理員公鑰與私鑰:admin.pem與admin-key.pem

 

二、根證書生成


我們需要一個證書來爲自己頒發的證書籤名,這個證書可從其他CA獲取,或者是自簽名的根證書。這裏我們生成一個自簽名的根證書。

1、CA根證書 ca-private.pem

       生成一個2048位的密鑰:

# openssl genrsa -out ca-private.pem 2048

2、生成CA私鑰

    我們自己做測試,那麼證書的申請機構和頒發機構都是自己。直接生成證書私鑰,-day指定證書有效期

    # openssl req -x509 -new -nodes -key ca-private.pem -days 3650 -out ca-public.pem -subj "/CN=kube-ca"

     注意:生成ca-private.pem時, -subi參數中"CN"的值通常爲域名。

 

 

三、生成apiserver服務端證書


1、apiserver證書使用說明

kube-apiserver

使用的證書 證書作用
ca-public.pem CA根證書
ca-private.pem CA端私鑰
apiserver-public.pem kube-apiserver的tls認證證書
apiserver-private.pem kube-apiserver的tls認證私鑰

--token-auth-file指定了token.csv的位置,用於kubelet 組件 第一次啓動時沒有證書如何連接 apiserver 。 Token 和 apiserver 的 CA 證書被寫入了 kubelet 所使用的 bootstrap.kubeconfig 配置文件中;這樣在首次請求時,kubelet 使用 bootstrap.kubeconfig 中的 apiserver CA 證書來與 apiserver 建立 TLS 通訊,使用 bootstrap.kubeconfig 中的用戶 Token 來向 apiserver 聲明自己的 RBAC 授權身份

--tls-cert-file=apiserver-public.pem指定kube-apiserver證書地址

--tls-private-key-file=apiserver-private.pem指定kube-apiserver私鑰地址

--client-ca-file=ca-public.pem 指定根證書地址

--service-account-key-file=ca-private.pem/apiserver-private.pem包含PEM-encoded x509 RSA公鑰和私鑰的文件路徑,用於驗證Service Account的token,如果不指定,則使用--tls-private-key-file指定的文件

--etcd-cafile=ca-private.pem 到etcd安全連接使用的SSL CA文件

--etcd-certfile=apiserver-public.pem 到etcd安全連接使用的SSL 證書文件

--etcd-keyfile=apiserver-private.pem到etcd安全連接使用的SSL 私鑰文件

基於masterssl.cnf創建apiserver-public.pemapiserver-private.pem文件。

在生成apiserver.csr時,  -subi參數中"/CN"指定的名字需爲Master所在的主機名。

2、證書生成

1)證書配置

創建用於生成證書籤名請求(CSR)的配置文件masterssl.cnf,該文件用於x509 v3版本的證書。

在該文件中主要需要設置:

 (1)、Master服務器的hostname (k8s-master)、IP地址${MASTER_IPV4}(192.168.10.50),

  (2)、Kubernetes Master Service的虛擬服務名稱(kubernetes.default等)和使用自己規劃作爲kubernetes service IP端的首IP替換${K8S_SERVICE_IP}

即apiserver參數的--service-cluster-ip-range的首IP,

若--service-cluster-ip-range=192.168.10.0/16,則${K8S_SERVICE_IP}爲192.168.0.1

若--service-cluster-ip-range=10.0.0.0/16,則${K8S_SERVICE_IP}爲10.0.0.1

masterssl.cnf文件的示例如下:

[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster.local
IP.1 = ${K8S_SERVICE_IP}
IP.2 = ${MASTER_IPV4}

1)alt_names指的是最終可以訪問的域名或者IP,所以,其實一個證書是可以多個網站同時使用的。被訪問域名只要滿足DNS和IP中的一個,其證書就是合法的。
SubjectAltName是X509 Version 3 (RFC 2459)的擴展,允許ssl證書指定多個可以匹配的名稱。SubjectAltName 可以包含email 地址,ip地址,正則匹配DNS主機名,等等。

SAN(Subject Alternative Name)是 SSL 標準 x509 中定義的一個擴展。使用了 SAN 字段的 SSL 證書,可以擴展此證書支持的域名,使得一個證書可以支持多個不同域名的解析。


 

 

2)、生成apiserver服務端私鑰:

openssl genrsa -out apiserver-private.pem 2048

3)、生成服務端證書籤名請求文件(CSR):

         和CA證書的生成不同的是,我們需要先生成一個csr證書請求文件文件(CSR,Cerificate Signing Request),有了這個文件之後再利用CA根證書生成最終的證書。

         基於配置文件masterssl.cnf生成證書籤名請求文件(CSR):

openssl req -new -key apiserver-private.pem  -out apiserver.csr -subj "/CN=k8s-master" -config masterssl.cnf

(這個是 NO SAN 命令openssl req -new -key apiserver-private.pem  -out apiserver.csr 只執行 NO SAN 命令也可以簽發證書,不過卻不能夠添加多個域名。)

4)、生成apiserver服務端認證公鑰

         使用ca-private.pem、 ca-public.pem 和apiserver.csr 生成apiservertls認證公鑰

openssl x509 -req -in apiserver.csr  -CA ca-public.pem  -CAkey ca-private.pem -CAcreateserial -out apiserver-public.pem  -days 3650 -extensions v3_req -extfile masterssl.cnf

全部執行完後會生成6個文件:

apiserver-private.csr
apiserver-private.pem
apiserver-public.pem
ca-private.pem
ca-public.pem
ca-public.srl

查看證書:

openssl x509  -noout -text -in ./apiserver-public.pem

一般生成的根證書(ca-private.pem, ca-public.pem)與apiserver證書(apiserver-private.pem,apiserver-public.pem)放置在Master節點的某個目錄(例如/mnt/app/kubernetes/ssl)

 

apiserver的配置中需要指定如下參數:

--service-account-key-file=/mnt/app/kubernetes/ssl/apiserver-private.pem \
--tls-private-key-file=/mnt/app/kubernetes/ssl/apiserver-private.pem \
--tls-cert-file=/mnt/app/kubernetes/ssl/apiserver-public.pem \
--client-ca-file=/mnt/app/kubernetes/ssl/ca-public.pem  \
同時,可以關掉非安全端口8080,設置安全端口爲443 (默認爲6443):

最後重啓kube-apiserver服務。

 

3. kube-controller-manager客戶端雙向認證證書

kubelet 發起的 CSR 請求都是由 kube-controller-manager 來做實際簽署的,所有使用的證書都是根證書的密鑰對 。由於kube-controller-manager是和kube-apiserver部署在同一節點上,且使用非安全端口通信,故不需要證書。

使用的證書 證書作用
ca.pem CA根證書
ca-key.pem kube-apiserver的tls認證私鑰

--cluster-signing-cert-file:指定簽名的CA機構根證書,用來簽名爲 TLS BootStrap 創建的證書和私鑰

--cluster-signing-key-file:指定簽名的CA機構私鑰,用來簽名爲 TLS BootStrap 創建的證書和私鑰

--service-account-private-key-file: 同上

--root-ca-file=: 根CA證書文件路徑 ,用來對 kube-apiserver 證書進行校驗,指定該參數後,纔會在Pod 容器的 ServiceAccount 中放置該 CA 證書文件

--kubeconfig :kubeconfig配置文件路徑,在配置文件中包括Master的地址信息及必要認證信息

apiversion: v1
kind: Config
users:
- name: controllermanager
  user:
    client-certificate:
    client-key: /mnt/app/kubernetes/ssl/manager-client-private.pem
clusters:
- name: local
  cluster:
    certificate-authority: /var/run/kubernetes/ca.crt
contexts:
  context:
    cluster: local
    user: controllermanager
    name: my-context
current-context: my-context

controller-manager的配置中需要指定如下參數:
--service-account-private-key-file=/mnt/app/kubernetes/ssl/apiserver-private.pem
--root-ca-file=/mnt/app/kubernetes/ssl/ca-public.pem
--cluster-signing-cert-file=/mnt/app/kubernetes/ssl/ca-public.pem
--cluster-signing-key-file=/mnt/app/kubernetes/ssl/ca-private.pem

 

當然也可以爲controller-manager創建證書,controller-manager相對於apiserver是客戶端:

2)、設置kube-controller-manager的客戶端證書、私鑰和啓動參數

$ openssl genrsa -out manager-client-private.pem  2048

$ openssl req -new -key  manager-client-private.pem  -subj "/CN=k8s-master"  -out  manager-client.csr

$ openssl x509 -req  -in  manager-client.csr  -CA ca-public.pem  -CAkey ca-private.pem  -CAcreateserial -out  manager-client-public.pem  -days 5000 

然後可以通過curl測試:

 curl  --cacert /mnt/app/kubernetes/ssl/ca-public.pem --key /mnt/app/kubernetes/ssl/manager-client-private.pem --cert /mnt/app/kubernetes/ssl/manager-client-public.pem  https://k8s-master:6443

如果看到下面錯誤,說明認證有問題。
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "Unauthorized",
  "reason": "Unauthorized",
  "code": 401
}

/mnt/app/kubernetes/ssl/kubeconfig.yaml

apiVersion: v1
kind: Config
users:
- name: controllermanager
  user:
    client-certificate:/mnt/app/kubernetes/ssl/manager-client-public.pem
    client-key:/mnt/app/kubernetes/ssl/manager-client-private.pem
clusters:
- name: local
  cluster:
    certificate-authority: /mnt/app/kubernetes/ssl/ca-public.pem
contexts:
- context:
    cluster: local
    user: controllermanager
  name: my-context
current-context: my-context

 

5、刪除相關serviceAccount的token

由於系統重新生成證書,需要刪除相關serviceAccount的token,然後重啓apiserver,apiserver根據最新

 kubectl get secret -n kube-system                     
NAME                  TYPE                                  DATA      AGE
coredns-token-cdn9x   kubernetes.io/service-account-token   3         3d
default-token-lht2v   kubernetes.io/service-account-token   3         3d

 kubectl delete secret coredns-token-cdn9x  -n kube-system
 secret "coredns-token-cdn9x" deleted

 

 

 

四、node節點客戶端雙向證書生成


設置每臺Node上kubelet的客戶端證書、私鑰和啓動參數

1)、首先複製kube-apiserver的ca-public.pemca-private.pem文件到Node上,

2)、在生成kubelet-public.pem時-CA參數和-CAkey參數使用的是apiserver的ca-public.pemca-private.pem文件。

3)、在生成kubelet client.csr時-subj參數中的"/CN"設置爲本Node的IP地址。

-subj   指定證書申請者的個人信息

可以將節點IP放入到環境變量

# Export this worker's IP address.

export WORKER_IP=<WORKER_IPV4>


openssl genrsa -out kubelet-private.pem 2048
openssl req -new -key kubelet-private.pem   -out kubelet.csr -subj "/CN=kubelet-key" -config kubelet-openssl.cnf
openssl x509 -req -in kubelet.csr  -CA ca-public.pem  -CAkey ca-private.pem  -CAcreateserial -out kubelet-public.pem -days 3650 -extensions v3_req -extfile kubelet-openssl.cnf

openssl genrsa -out kubelet-private.pem 2048
openssl req -new -key kubelet-private.pem   -out kubelet.csr -subj "/CN=kubelet-key"
openssl x509 -req -in kubelet.csr  -CA ca-public.pem  -CAkey ca-private.pem  -CAcreateserial -out kubelet-public.pem -days 3650

curl  --cacert /mnt/app/kubernetes/ssl/ca-public.pem --key /mnt/app/kubernetes/ssl/kubelet-private.pem --cert /mnt/app/kubernetes/ssl/kubelet-public.pem  https://k8s-master:6443

 

將這些文件複製到一個目錄中(例如/etc/kubernetes/ssl/)。

其中kubelet-openssl.cnf內容如下:

[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
IP.1 = $ENV::WORKER_IP
 

從節點上配置kubelet所使用的配置文件worker-kubeconfig.yaml (kubelet和kube-proxy進程共用)指定證書:

配置客戶端證書等相關參數,內容如下:

kubelet的如下參數使用證書:

--kubeconfig=/etc/kubernetes/worker-kubeconfig.yaml
--tls-private-key-file=/etc/kubernetes/ssl/kubelet-private.pem
--tls-cert-file=/etc/kubernetes/ssl//kubelet-public.pem

重啓kubelet

 

kube-proxy複用上一步kubelet創建的客戶端證書,配置啓動參數:

--master=https://192.168.18.3:443

--kubeconfig=/etc/kubernetes/worker-kubeconfig.yaml

重啓kube-proxy服務。

至此,一個基於CA的雙向數字證書認證的Kubernetes集羣環境就搭建完成了。

 

五、集羣管理員雙向認證證書生成


此證書用於kubectl,設置方式如下:

$ openssl genrsa -out admin-key.pem 2048
$ openssl req -new -key admin-key.pem -out admin.csr -subj "/CN=kube-admin"
$ openssl x509 -req -in admin.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out admin.pem -days 365

# 配置一個名爲default的集羣,並指定服務地址與根證書
kubectl config set-cluster default --server=https://172.17.4.101:443 --certificate-authority=${PWD}/ssl/ca.pem

# 設置一個管理用戶爲admin,並配置訪問證書
kubectl config set-credentials admin --certificate-authority=${PWD}/ssl/ca.pem --client-key=${PWD}/ssl/admin-key.pem --client-certificate=${PWD}/ssl/admin.pem

# 設置一個名爲default使用default集羣與admin用戶的上下文,
kubectl config set-context default --cluster=default --user=admin

# 啓用default爲默認上下文
kubectl config use-context default
 

 

 

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