<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          解析k8s中節(jié)點(diǎn)組件和集群通信原理

          共 9169字,需瀏覽 19分鐘

           ·

          2021-08-06 07:10

          本文會(huì)分析node節(jié)點(diǎn)的兩個(gè)組件(kube-proxy和kubelet)同集群如何建立通信的過(guò)程。這兩個(gè)組件其實(shí)已經(jīng)覆蓋了從集群外(非POD形式)和集群進(jìn)行通信的所有可能,為什么這么說(shuō),我們可以看一下這兩個(gè)組件的特點(diǎn):

          • kube-proxy:只是做client和集群進(jìn)行通信
          • kubelet:即作為客戶端去監(jiān)聽(tīng)和獲取集群中的信息,又要作為服務(wù)端讓集群獲取這個(gè)node節(jié)點(diǎn)上的pod信息

          前兩部分我們會(huì)簡(jiǎn)單的科普一下SSL的過(guò)程和k8s中通過(guò)RBAC進(jìn)行認(rèn)證的內(nèi)容,因?yàn)檫@兩部分內(nèi)容屬于看懂后續(xù)兩部分的基礎(chǔ),如果對(duì)這兩部分內(nèi)容比較熟悉的同學(xué)可以跳過(guò)。

          為了增加閱讀體驗(yàn),我把有過(guò)多代碼的放到另一個(gè)文件里面,文章中相應(yīng)的部分通過(guò)鏈接的方式。

          一、密不透風(fēng):SSL的過(guò)程

          首先如果要想有一個(gè)CA機(jī)構(gòu)簽發(fā)的證書的話,會(huì)自己生成私鑰,然后通過(guò)私鑰證書簽名請(qǐng)求(CSR)讓CA去簽名,這個(gè)證書簽名中會(huì)包含服務(wù)端的一些信息(比如common name、organization等)還有公鑰。

          CA收到證書簽名請(qǐng)求(CSR)之后,會(huì)生成一個(gè)證書,證書內(nèi)容包括申請(qǐng)者的信息,CA的信息以及申請(qǐng)者公鑰,然后會(huì)用CA的私鑰進(jìn)行加密,然后把證書給服務(wù)端。

          當(dāng)客戶端想要和服務(wù)端進(jìn)行SSL連接的時(shí)候要先要發(fā)個(gè)申請(qǐng)連接的請(qǐng)求。

          然后服務(wù)端就會(huì)把通過(guò)CA簽發(fā)的證書給客戶端。

          客戶端用CA的證書去驗(yàn)證服務(wù)端的證書是否正確(一般CA證書會(huì)內(nèi)置在操作系統(tǒng)中,這也是為什么第0步驟會(huì)用虛線表示)

          客戶端驗(yàn)證通過(guò)后會(huì)用證書中的公鑰對(duì)數(shù)據(jù)進(jìn)行加密保證安全。

          注:

          • 這里只是說(shuō)的單向SSL過(guò)程,如果是雙向的話客戶端也要有自己的證書
          • 驗(yàn)證證書通過(guò)后之后,客戶端和服務(wù)端會(huì)協(xié)商一個(gè)對(duì)稱加密進(jìn)行通信,因?yàn)榉菍?duì)稱加密太慢了。(因?yàn)閷?duì)稱加密的過(guò)程對(duì)本文沒(méi)影響,所以有興趣的讀者可以自行查找資料或者和我探討交流)
          • 這里為了照顧大多數(shù)讀者,沒(méi)有細(xì)致的深入,比如CA怎么簽發(fā)的服務(wù)端證書。考慮到本文主要講k8s的,不是講加密的,這里沒(méi)有重點(diǎn)寫出

          附加幾個(gè)生成密鑰和查看的命令:

          • 生成私鑰:openssl genrsa -out helios.key 1024
          • 通過(guò)私鑰生成公鑰:openssl rsa -in helios.key -pubout -out helios.pem
          • 生成證書簽名請(qǐng)求:openssl req -key helios.key -new -out helios.req
          • CA簽發(fā)證書:openssl x509 -req -in helios.req -CA cacertificate.pem -CAkey caprivate.key -out helioscertificate.pem
          • 查看證書簽名請(qǐng)求文件內(nèi)容:openssl req -in helios.req -noout -text

          二、各司其職:RBAC是什么

          RBAC的本質(zhì)就是給不同的用戶不同的角色,角色代表的權(quán)限,是由k8s本身定義的,用戶代表的訪問(wèn)集群的“人”。

          所以要理解RBAC就要理解k8s中有幾種用戶,角色怎么控制權(quán)限,以及用戶和角色之間如何綁定的,下面我們就來(lái)一個(gè)個(gè)的看。

          2.1 k8s中的用戶

          在k8s中,用戶從宏觀上就可以分為兩種,集群內(nèi)的用戶以及集群外的用戶:

          • 集群內(nèi)的用戶:serviceAccount
          • 集群外的用戶:User

          集群外的user就是能通過(guò)HTTP請(qǐng)求體中拿到, 對(duì)于集群內(nèi)的用戶認(rèn)證信息怎么拿到呢,我們來(lái)看個(gè)kube-system命名空間下面的coredns這個(gè)serviceAccount的定義,我們能看到它有一個(gè)secrets字段,這個(gè)字段的name字段就是指定的secrets的名字,也就是說(shuō)如果某個(gè)POD聲明使用了這個(gè)serviceAccount,就會(huì)把這個(gè)serviceAccount對(duì)應(yīng)的secrets掛載到POD里面,這個(gè)secrets對(duì)應(yīng)的定義在這里。在POD中掛載的目錄為:/var/run/secrets/kubernetes.io/serviceaccount/,我們可以使用下面命令查看這個(gè)pod有沒(méi)有訪問(wèn)某個(gè)api的權(quán)限:

          kubectl  exec -ti centosb -n helios-ns bash
          CA_CERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
          TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
          NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
          curl --cacert $CA_CERT -H "Authorization: Bearer $TOKEN" "https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/pods/"

          在k8s中為了簡(jiǎn)化一系列用戶有相同權(quán)限的操作,提出了Group的的概念,就是能給一個(gè)組的成員綁定角色,所以Group是個(gè)邏輯的概念,是對(duì)一組用戶的抽象。這里我們先有個(gè)印象后面還會(huì)提及到。

          2.2 RBAC中角色

          角色就是一組權(quán)限的集合,我們可以看一下system:coredns這個(gè)角色的例子:yaml文件地址對(duì)于system:coredns這個(gè)集群級(jí)用戶來(lái)說(shuō),有對(duì)apiGroups為""下面endpoints、services、pod、namespaces的list和watch的權(quán)限。

          2.3 RBAC的用法

          k8s通過(guò)RBAC將權(quán)限的使用者和角色分離,提供四個(gè)新的資源,分為兩組,分別為:

          • rolebindings/roles:針對(duì)單個(gè)namespace下面的資源,比如說(shuō)endpoints、services等
          • clusterrolebindings/clusterroles:除了針對(duì)rolebindings/roles的功能外,還有集群級(jí)別的資源,比如說(shuō)namespace、pvc等

          我們可以看一下system:coredns這個(gè)clusterrolebinding的yaml定義:yaml文件地址上述的ClusterRoleBinding就是將kube-system下面的coredns用戶(ServiceAccount)和system:coredns進(jìn)行綁定使之有對(duì)應(yīng)的權(quán)限。

          現(xiàn)在對(duì)于RBAC的基本概念就解釋完了,其實(shí)RBAC還是很容易理解的,這里提出兩個(gè)問(wèn)題供讀者思考:

          • rolebindings能和clusterroles綁定么
          • clusterrolebindings能和roles綁定么

          三、拋磚引玉:kube-proxy和集群通信的過(guò)程

          3.1 啟動(dòng)前需要的手動(dòng)配置

          1. 創(chuàng)建證書簽名請(qǐng)求kube-proxy-csr.json
          2. 通過(guò)ca的證書、私鑰以及上一步的證書簽名請(qǐng)求生成kube-proxy的私鑰和證書
          cfssl gencert -ca=/opt/k8s/work/ca.pem \
            -ca-key=/opt/k8s/work/ca-key.pem \
            -config=/opt/k8s/work/ca-config.json \
            -profile=kubernetes  kube-proxy-csr.json | cfssljson -bare kube-proxy
          1. 通過(guò)set-cluster設(shè)置集群信息(比如設(shè)置為kubernetes),放在kube-proxy.kubeconfig文件中(這個(gè)時(shí)候的kube-proxy.kubeconfig的內(nèi)容:kube-proxy1.kubeconfig)
          2. 設(shè)置訪問(wèn)集群的用戶為kube-proxy,放在kube-proxy.kubeconfig文件中(這個(gè)時(shí)候的kube-proxy.kubeconfig的內(nèi)容:kube-proxy2.kubeconfig)
          3. 創(chuàng)建上下文(將第4步和第5部的進(jìn)行綁定即,用kube-proxy去訪問(wèn)kubernetes集群),使用kube-proxy.kubeconfig文件中。(這個(gè)時(shí)候的kube-proxy.kubeconfig的內(nèi)容:kube-proxy3.kubeconfig)
          4. 在kube-proxy的配置文件中,配置訪問(wèn)apiserver的客戶端(clientConnection.kubeconfig)
          5. 使用第5步創(chuàng)建的上下文,這個(gè)時(shí)候的kube-proxy.kubeconfig文件內(nèi)容為最終狀態(tài)kube-proxy.kubeconfig

          在集群中針對(duì)kube-proxy會(huì)有如下的RBAC規(guī)則:通過(guò)system:node-proxier這個(gè)CRB將用戶system:kube-proxy和ClusterRole進(jìn)行綁定.

          3.2 啟動(dòng)之后

          1. kube-proxy通過(guò)啟動(dòng)前生成的kube-proxy.kubeconfig和apiserver通信
          2. apiserver通過(guò)內(nèi)置的RBAC判斷用戶權(quán)限
          3. 認(rèn)證和授權(quán)結(jié)束,可以通信

          四、千呼萬(wàn)喚始出來(lái):kubele和集群通信的過(guò)程

          kubelet和kube-proxy的區(qū)別就是,kube-proxy僅僅是作為和集群通信的庫(kù)戶端,但是kubelet既要做客戶端(和集群通信)又要做服務(wù)端(供apiserver收集pod的日志等)。

          kube-proxy生成一份客戶端證書之后在各個(gè)node上是能通用的。kubelet的服務(wù)端證書中必須能表示這個(gè)node的身份(所以在kubelet證書里面有節(jié)點(diǎn)相關(guān)的CN信息)。

          kubelet和kube-proxy有一些不相同的地方就是kubelet代表的是一個(gè)node節(jié)點(diǎn),所以他的證書要能唯一標(biāo)識(shí)(證書中的CN字段system:nodes:172.27.xxx.xxx)。

          為了避免手動(dòng)為每個(gè)節(jié)點(diǎn)手動(dòng)創(chuàng)建個(gè)證書,所以k8s的1.4版本中引入了bootstrap(Add proposal for kubelet TLS bootstrap),bootstrap的目標(biāo)就是省去上述這么多手動(dòng)搞證書的步驟,把這個(gè)過(guò)程內(nèi)置在k8s里面,基于bootstrap的過(guò)程如下:

          4.1 啟動(dòng)前的配置

          4.1.1 生成token

          因?yàn)樽铋_(kāi)始的kubelet是沒(méi)有證書的,這時(shí)候就要通過(guò)一個(gè)唯一的token的去和api-server通信,這個(gè)token的權(quán)限是比較低的。

          token的格式為*[a-z0-9]{6}.[a-z0-9]{16}*(例如abcdef.0123456789abcdef)token的格式分為兩個(gè)部分tokenID和(.)secret

          • tokenID是public信息,比如是會(huì)作為用戶名system:bootstrap:
          • secret只能給信任的第三方,作為認(rèn)證信息 可以通過(guò)kubeadm來(lái)簡(jiǎn)化這個(gè)流程
          # /opt/k8s/bin/kubeadm token create \
          > --description helios-test \
          > --groups system:bootstrappers:k8s01 \
          > --kubeconfig ~/.kube/config
          379jgz.xc7l8qnzwrw10obr

          4.1.2 創(chuàng)建secret

          secrets有下面幾種類型:

          • Opaque:?jiǎn)渭兊耐ㄟ^(guò)把base64去encode密碼,安全性不高
          • kubernetes.io/dockerconfigjson:用來(lái)存儲(chǔ)私有docker registry的認(rèn)證信息,詳情見(jiàn)registry-secret-existing-credentials。
          • kubernetes.io/service-account-token:用來(lái)存儲(chǔ)注入給pod的認(rèn)證信息
          • bootstrap.kubernetes.io/token:專門用于bootstrap的

          secret的格式:bootstrap-token-secret-format當(dāng)然這個(gè)secret有幾個(gè)要求:

          • 必須在kube-system的命名空間下
          • 比如以bootstrap-token-開(kāi)頭
          • secret的類型必須是bootstrap.kubernetes.io/token 我們來(lái)驗(yàn)證一下:
          # kubectl get secrets -n kube-system | grep bootstrap-token-
          bootstrap-token-379jgz                           bootstrap.kubernetes.io/token         7      4h12m

          bootstrap-token-379jgz這個(gè)secret的內(nèi)容為:bootstrap-token-secret其中usage-bootstrap-*用于說(shuō)明secret的目的:

          • usage-bootstrap-authentication:這個(gè)token能作為認(rèn)證token

          auth-extra-groups:為該token的擴(kuò)展認(rèn)證:

          echo -n "c3lzdGVtOmJvb3RzdHJhcHBlcnM6azhzMDE=" | base64 --decode
          system:bootstrappers:k8s01

          4.1.3 設(shè)置RBAC規(guī)則

          • 授予kubelet創(chuàng)建CSR的權(quán)限: kubelet-bootstrap-crb、kubelet-bootstrap-cr

          • 授予過(guò)期輪換client證書的權(quán)限:node-client-cert-renewal

          • 授予過(guò)期輪換server證書的權(quán)限: node-server-cert-renewal

          4.1.4 設(shè)置集群參數(shù)

          kubectl config set-cluster kubernetes \
                --certificate-authority=/etc/kubernetes/cert/ca.pem \
                --embed-certs=true \
                --server=${KUBE_APISERVER} \
                --kubeconfig=kubelet-bootstrap-${node_name}.kubeconfig

          4.1.5 根據(jù)第一步的token添加用戶

          kubectl config set-credentials kubelet-bootstrap \
                --token=${BOOTSTRAP_TOKEN} \
                --kubeconfig=kubelet-bootstrap-${node_name}.kubeconfig

          4.1.6 設(shè)置上下文參數(shù)


          kubectl config set-context default \
                --cluster=kubernetes \
                --user=kubelet-bootstrap \
                --kubeconfig=kubelet-bootstrap-${node_name}.kubeconfig

          4.1.7 設(shè)置默認(rèn)上下文

          kubectl config use-context default --kubeconfig=kubelet-bootstrap-${node_name}.kubeconfig

          4.1.8 配置各個(gè)組件參數(shù)

          設(shè)置kubelet的啟動(dòng)參數(shù):

          --bootstrap-kubeconfig=/etc/kubernetes/kubelet-bootstrap.kubeconfig
          --cert-dir=/etc/kubernetes/cert
          --kubeconfig=/etc/kubernetes/kubelet.kubeconfig

          因?yàn)閏omtroller-manager負(fù)責(zé)簽發(fā)證書,所有comtroller-manager的啟動(dòng)文件中要有CA的相關(guān)信息

          --cluster-signing-cert-file="/var/lib/kubernetes/ca.pem"
          --cluster-signing-key-file="/var/lib/kubernetes/ca-key.pem"
          --experimental-cluster-signing-duration=8760h

          4.2 啟動(dòng)過(guò)程

          其實(shí)是先去找kubeconfg文件,如果找不到就會(huì)使用bootstrap-kubeconfig去開(kāi)始bootstrsp的過(guò)程:

          4.2.1 第一次CSR的過(guò)程(申請(qǐng)client證書)

          1. kubelet在node節(jié)點(diǎn)上生成clinet.key,然后把公鑰和bootstrap-kubeconfig發(fā)送出去
          2. api-server對(duì)請(qǐng)求進(jìn)行認(rèn)證,通過(guò)后創(chuàng)建CSR
            • api-server從bootstrap-kubeconfig文件中提取出token。
            • kube-system的ns下,尋找bootstrap-token-的secret
            • 用戶為system:bootstrappers:,因?yàn)閷儆趕ystem:bootstrappers組下面,有創(chuàng)建CSR的權(quán)限
            • 創(chuàng)建CSR
          3. controller-manager監(jiān)聽(tīng)到了有CSR,并且這個(gè)用戶有自動(dòng)approve的權(quán)限,就頒發(fā)證書
          4. kubelet通過(guò)watch看到創(chuàng)建的CSR變?yōu)榱薸ssued狀態(tài),就通過(guò)拿CSR中status.certificate的字段,然后base64解碼變?yōu)楸镜匚募?/section>

          第一次CSR之后,就已經(jīng)在kubelet的啟動(dòng)參數(shù)的--kubeconfig=路徑中生成了訪問(wèn)apiserver的kube-config文件,為kube-config我們可以看看證書中,用戶的名字(CN):


          #
           cfssl certinfo -cert /etc/kubernetes/cert/kubelet-client-current.pem
          {
            "subject": {
              "common_name": "system:node:k8s01",
              "organization": "system:nodes",
              "names": [
                "system:nodes",
                "system:node:k8s01"
              ]
            },
            ...
          }

          現(xiàn)在的用戶就變?yōu)閟ystem:node:k8s01,組變?yōu)閟ystem:nodes了

          4.2.2 第二次CSR的過(guò)程(申請(qǐng)server端證書)

          1. 用上述生成的kube-config文件去訪問(wèn)apiserver
          2. apiserver通過(guò)RBAC查看該用戶是否有創(chuàng)建CSR的權(quán)限(crb為:node-client-cert-renewal, approve-node-server-renewal-csr都給綁了)
          3. 出于安全問(wèn)題,因?yàn)檫@一步就相當(dāng)于注冊(cè)node的過(guò)程,所以要手動(dòng)apporve
          4. 真正給頒發(fā)證書的還是controller-manager
          5. kubelet通過(guò)watch看到創(chuàng)建的CSR變?yōu)榱薸ssued狀態(tài),就通過(guò)拿CSR中status.certificate的字段,然后base64解碼變?yōu)楸镜匚募?/section>

          原文鏈接:https://github.com/helios741/myblog/tree/new/learn_go/src/2020/0104_k8s_component_communication



          K8S 進(jìn)階訓(xùn)練營(yíng)


           點(diǎn)擊屏末  | 即刻學(xué)習(xí)


          掃描二維碼獲取

          更多云原生知識(shí)





          k8s 技術(shù)圈

          瀏覽 70
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  无码123区 | 日韩乱论网站 | 男人天堂2024手机在线 | 在线91福利| 日本在线中文不卡 |