kubeadm 的工做原理

kubeadm 的工做原理

做者:張首富
時間:2020-06-04
w x:y18163201

相信使用二進制部署過 k8s 集羣的同窗們都知道,二進制部署集羣太困難了,有點基礎的人部署起來還有成功的但願,要否則只能跟着別人的教程一步一步的去部署,部署的時候徹底不知道這樣操做的意義是啥?出問題了無從下手解決。對於初學者來講真的是浪費生命,那有沒有什麼簡單的方式來部署集羣呢?這個問題在前幾年可能沒有很好的答案,可是在如今,答案簡直太多了,好比 kubeadm,rke 等方式,咱們今天就來介紹下 kubeadm 部署集羣的工做原理。html

這裏默認你有點 k8s 基礎,知道他們都是有哪些組件構成的。 node

在集羣部署的時候,他的每個組件都是一個須要被執行的,單獨的二進制文件,在如今容器化那麼發達的時期,咱們確定來用 docker 來簡化部署。可是容器化部署的時候會有一個很大的問題,如何容器化 kubeletgit

咱們知道 kubelet 是 kubernetes 項目用來操做 Docker 等容器運行時的核心組件,在每一個 節點上都存在,能夠除了跟容器運行時打交道外,kubelet 在配置容器網絡、管理容器數據卷事 時,他都須要直接操做宿主機。github

若是如今 kubelet 自己就運行在一個容器裏,那麼直接操做宿主機就會變得很麻煩。對於網絡配置來講還好,kubelet 容器能夠經過不開啓 Network Namespace(--net host)的方式,直接共享宿主機的網絡棧。但是,要讓 kubelet 隔着容器的 Mount Namespace 和文件系統,操做宿主機的文件系統,就有點兒困難了。docker

好比,若是用戶想要使用 NFS 作容器的持久化數據卷,那麼 kubelet 就須要在容器進行綁定掛載前,在宿主機的指定目錄上,先掛載 NFS 的遠程目錄。bootstrap

但是,這時候問題來了。因爲如今 kubelet 是運行在容器裏的,這就意味着它要作的這個「mount -F nfs」命令,被隔離在了一個單獨的 Mount Namespace 中。即,kubelet 作的掛載操做,不能被「傳播」到宿主機上。centos

對於這個問題,有人說,可使用 setns() 系統調用,在宿主機的 Mount Namespace 中執行這些掛載操做;也有人說,應該讓 Docker 支持一個–mnt=host 的參數。可是,到目前爲止,在容器裏運行 kubelet,依然沒有很好的解決辦法,我也不推薦你用容器去部署 Kubernetes 項目。api

所以爲了解決上面這個問題,kubeadm 選擇了一種方案:安全

  • 把 kubelet 直接部署在宿主機上,而後使用容器部署其餘的 kubernetes組件

因此,咱們使用 kubeadm 安裝集羣的第一步 就是在全部的機器上手動安裝 kubeadm、kubelet 和 kubectl 這三個二進制文件。bash

centos/Redhat 安裝:

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

yum -y install kubectl-1.14.0 
yum -y install kubelet-1.14.0 
yum -y install kubeadm-1.14.0
systemctl enable kubelet  #必需要設置,

注意: 若是你這個時候啓動 kubelet 確定會發現一個報錯,提示缺乏文件,這個時候不用管它,咱們一會使用 kubeadm init 以後初始化集羣就正常了

而後咱們須要建立 kubeadm 的配置文件,指定咱們集羣信息。舉個例子

cat > kubeadm-config.yaml <<-'EOF'

apiVersion: kubeadm.k8s.io/v1alpha2
kind: MasterConfiguration
kubernetesVersion: v1.16.0
api:
  advertiseAddress: 192.168.0.102
  bindPort: 6443
  ...
etcd:
  local:
    dataDir: /var/lib/etcd
    image: ""
imageRepository: k8s.gcr.io
kubeProxy:
  config:
    bindAddress: 0.0.0.0
    ...
kubeletConfiguration:
  baseConfig:
    address: 0.0.0.0
    ...
networking:
  dnsDomain: cluster.local
  podSubnet: ""
  serviceSubnet: 10.96.0.0/12
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  ...
EOF

具體能夠參考:https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-init/

接下來咱們就可使用kubeadm init來部署 Master 節點了。

kubeadm init 的工做流程

1,Prefligth Checks 檢查

kubeadm 首先要作的,是一系列的檢查工做,以肯定這臺機器能夠用來部署 Kubernetes。這一步檢查,咱們稱爲「Preflight Checks」,它能夠爲你省掉不少後續的麻煩。

其實,Preflight Checks 包括了不少方面,好比:

  • Linux 內核的版本必須是不是 3.10以上?
  • Linux Cgroups 模塊是否可用
  • 機器的 hostname 是否標準?在 Kubernetes 項目裏,機器的名字以及一切存儲在 Etcd 中的 API 對象,都必須使用標準的 DNS 命名(RFC 1123)。
  • 用戶安裝的 kubeadm 和 kubelet 的版本是否匹配?
  • 機器上是否是已經安裝了 Kubernetes 的二進制文件?
  • Kubernetes 的工做端口 10250/10251/10252 端口是否是已經被佔用?
  • ip、mount 等 Linux 指令是否存在?
  • Docker 是否已經安裝?
  • Docker 和 kubelet 使用的驅動程序是否相同?
  • 。。。。

上面這些檢查中,一些檢查項目僅僅觸發警告,其它的則會被視爲錯誤而且退出 kubeadm,除非問題獲得解決或者用戶指定了 --ignore-preflight-errors=&lt;list-of-errors&gt; 參數。

2,生成自簽證書

在檢查經過以後,kubeadm 會爲你生成 kubernetes對外提供服務所需的各類證書和對應的目錄。

若是用戶已經經過 --cert-dir 配置的證書目錄(默認爲 /etc/kubernetes/pki)提供了他們本身的 CA 證書以及/或者密鑰, 那麼將會跳過這個步驟。

kubernetes 對外提供服務時,除非專門開啓「不安全模式」,不然都要經過 HTTPS 才能訪問 Kube-apiserver。這就須要爲 Kubernetes 集羣配置好證書文件。

kubeadm 爲 Kubernetes 項目生成的證書文件都放在 Master 節點的 /etc/kubernetes/pki 目錄下。在這個目錄下,最主要的證書文件是 ca.crt 和對應的私鑰 ca.key。

此外,用戶使用 kubectl 獲取容器日誌等 streaming 操做時,須要經過 kube-apiserver 向 kubelet 發起請求,這個鏈接也必須是安全的。kubeadm 爲 這一步生成的事 apiserver-kubelet-client.out 文件,對應的私鑰是 apiserver-kubelet-client.key。

除此以外,Kubernetes 集羣中還有 Aggregate APIServer 等特性,也須要用到專門的證書,這裏我就再也不一一列舉了。能夠參考這個文件:http://www.javashuo.com/article/p-bdgutsqg-nx.html 須要指出的是,你能夠選擇不讓 kubeadm 爲你生成這些證書,而是拷貝現有的證書到以下證書的目錄裏:

/etc/kubernetes/pki/ca.{crt,key}
[root@zsf-test pki]# tree
.
├── apiserver.crt
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
├── apiserver.key
├── apiserver-kubelet-client.crt
├── apiserver-kubelet-client.key
├── ca.crt
├── ca.key
├── etcd
│   ├── ca.crt
│   ├── ca.key
│   ├── healthcheck-client.crt
│   ├── healthcheck-client.key
│   ├── peer.crt
│   ├── peer.key
│   ├── server.crt
│   └── server.key
├── front-proxy-ca.crt
├── front-proxy-ca.key
├── front-proxy-client.crt
├── front-proxy-client.key
├── sa.key
└── sa.pub

3, 生成其餘組件訪問 kube-apiserver 所須要的配置文件

這些文件的路徑是:/etc/kubernetes/xxx.conf

ls /etc/kubernetes/*.conf
/etc/kubernetes/admin.conf  /etc/kubernetes/controller-manager.conf  /etc/kubernetes/kubelet.conf  /etc/kubernetes/scheduler.conf

這些文件裏面記錄的是,當前這個 Master 節點的服務器地址、監聽端口。證書目錄等信息。這樣,對應的客戶端(好比 scheduler,kubelet 等),能夠直接加載相應的文件,使用裏面的信息與 kube-apiserver創建安全鏈接。

4, 爲 Master 組件生成 Pod 配置文件

在 Kubernetes 中,有一種特殊的容器啓動方法叫作「Static Pod」。它容許你把要部署的 Pod 的 YAML 文件放在一個指定的目錄裏。這樣,當這臺機器上的 kubelet 啓動時,它會自動檢查這個目錄,加載全部的 Pod YAML 文件,而後在這臺機器上啓動它們。

從這一點也能夠看出,kubelet 在 Kubernetes 項目中的地位很是高,在設計上它就是一個徹底獨立的組件,而其餘 Master 組件,則更像是輔助性的系統容器。

cd /etc/kubernetes/manifests
├── etcd.yaml
├── kube-apiserver.yaml
├── kube-controller-manager.yaml
└── kube-scheduler.yaml

而後 kubeadm 會調用 kubelet 運行這個 yml 文件,等到 Master 容器啓動後,kubeadm 會經過檢查localhost:6443/healthz 這個 Master 組件的健康檢查 url,等待 Master 組件徹底運行起來。

而後,kubeadm 就會爲集羣生成一個 bootstrap token。在後面,只要持有這個 token,任何一個安裝了 kubelet 和 kubadm 的節點,均可以經過 kubeadm join 加入到這個集羣當中。

這個 token 的值和使用方法,會在 kubeadm init 結束後被打印出來。

在 token 生成以後,kubeadm 會將 ca.crt 等 Master 節點的重要信息,經過 ConfigMap 的方式保存在 Etcd 當中,供後續部署 Node 節點使用。這個 ConfigMap 的名字是 cluster-info。

kubeadm init 的最後一步,就是安裝默認插件。Kubernetes 默認 kube-proxy 和 DNS 這兩個插件是必須安裝的。它們分別用來提供整個集羣的服務發現和 DNS 功能。其實,這兩個插件也只是兩個容器鏡像而已,因此 kubeadm 只要用 Kubernetes 客戶端建立兩個 Pod 就能夠了。

kubeadm join 的工做流程

這個流程其實很是簡單,kubeadm init 生成 bootstrap token 以後,你就能夠在任意一臺安裝了 kubelet 和 kubeadm 的機器上執行 kubeadm join 了。

但是,爲何執行 kubeadm join 須要這樣一個 token 呢?

由於,任何一臺機器想要成爲 Kubernetes 集羣中的一個節點,就必須在集羣的 kube-apiserver 上註冊。但是,要想跟 apiserver 打交道,這臺機器就必需要獲取到相應的證書文件(CA 文件)。但是,爲了可以一鍵安裝,咱們就不能讓用戶去 Master 節點上手動拷貝這些文件。

因此,kubeadm 至少須要發起一次「不安全模式」的訪問到 kube-apiserver,從而拿到保存在 ConfigMap 中的 cluster-info(它保存了 APIServer 的受權信息)。而 bootstrap token,扮演的就是這個過程當中的安全驗證的角色。

只要有了 cluster-info 裏的 kube-apiserver 的地址、端口、證書,kubelet 就能夠以「安全模式」鏈接到 apiserver 上,這樣一個新的節點就部署完成了。

接下來,你只要在其餘節點上重複這個指令就能夠了。

具體安裝能夠查看文章:

https://zhangguanzhang.github.io/2019/11/24/kubeadm-base-use/#kubeadm%E9%83%A8%E7%BD%B2

參考:極客時間 張磊的 kubernetes 專欄

相關文章
相關標籤/搜索