1. 程式人生 > >Kubernetes :Launcher 基於 kubeadm 的部署工具_Kubernetes中文社群

Kubernetes :Launcher 基於 kubeadm 的部署工具_Kubernetes中文社群

支援的叢集型別

單主機叢集

可增刪主節點的高可用叢集

可增刪主節點的高可用叢集

用途:建議使用者在生產環境中使用

功能:高可用的Etcd叢集;支援至少2個Master節點;支援高可用的Vespace儲存;區域網內的時間同步元件;內建的映象倉庫(Alpha);應用級別的負載均衡(Alpha)等

其實,在內部實現中,為了使整個邏輯更加的簡單,我們將主節點上的元件,只與本節點的apiserver聯絡,當然,Etcd節點為獨立的模組,我們當前的Etcd節點都執行在master節點上。

我們預設增加的服務

增加時間同步模組

  1. Ufleet內建時間同步伺服器Ufleet-ntpd,支援區域網環境
  2. 每個節點建立或者新增前,都會先與Ufleet-ntpd同步時間,同步完成後再執行安裝任務
  3. 在前期測試中發現,如果時間不同步,將導致etcd叢集極其不穩定,故建議在建立高可用叢集時,優先保證各個節點時間同步
  4. 時間同步對於之後日誌定位,監控等亦有重要的作用,不可忽視

叢集內建traefik-ingress服務

  1. 使用者建立ingress服務後,external-dns將自動獲取到相關資訊,並自動生成服務Host到IP的DNS記錄,寫入到etcd資料庫中
  2. 使用者通過ingress中指定的host,訪問服務(使用者配置:只需要將叢集的Vip新增到使用者使用的機器的DNS伺服器地址中即可)
  3. traefik將自動做負載均衡

儲存叢集

  1. 新的版本,內建Vespace儲存,即對於每個k8s叢集,同時也是一個完整的儲存叢集,包含strategy策略節點,和storage儲存節點

Launcher的架構設計

Launcher各模組簡圖及呼叫關係

流程介紹:

  1. 客戶端通過restful 介面呼叫,進入sub模組
  2. 如果是刪除,或者查詢,直接呼叫Cluster的方法執行
  3. 如果是建立或者新增任務(建立叢集,新增主節點,新增Node節點),則呼叫api模組,建立Job任務
  4. scheduler定時向api模組查詢,獲取任務和已註冊worker(Ufleet有高可用版本,高可用版本下,同時存在多個worker,可提高多人共同使用下的建立和新增任務的效率);檢查任務是否存在已過時,或者是否存在新的任務,存在則將任務分配給已註冊的worker,並呼叫api模組寫入資料庫
  5. worker定時向api模組查詢屬於自己的任務,如果存在未執行任務,則呼叫任務執行

kubeadm與launcher

kubeadm的不足和可擴充套件

kubeadm的不足:

  1. 當前kubeadm不支援高可用叢集的建立
  2. 只安裝kubernetes元件

kubeadm可擴充套件:

  1. 對證書的處理方式很好:

如果存在證書,則讀取並使用,不存在則生成,即使部分不存在也只生成對應的證書。基於此,我們生成證書時,沒有生成apiserver.crt/key,因為伺服器的證書中包含了主機IP或者域名,將導致apiserver證書不可重複使用,故儲存也沒有多大意義

  1. 可配置性好:

提供非常完整的配置項,將在下一節詳細介紹。但注意,根據我們的經驗,一般文件要晚於程式碼,對於新的特性,有時會發現文件中沒有描述,這時如果是研發人員,可參考kubeadm的程式碼進行配置

launcher建立流程介紹

  1. 建立叢集流程:

流程如右圖所示,在第7步,launcher利用kubeadm完成kubernetes元件的建立。

  1. 新增Master節點流程與建立叢集流程的差別:

新增Master節點流程與建立叢集流程基本一致,差別在於:從資料庫中獲取本叢集CA證書,叢集已有配置,生成對應主機的證書和配置檔案;往已存在etcd叢集新增節點,並等待資料同步完成後開始執行安裝任務。

  1. 新增Node節點流程:

從資料庫中獲取證書資訊,根據節點和叢集資訊生成對應的配置檔案,採用kubelet主動註冊的功能,在kubelet啟動後自動向叢集主節點註冊自己。

基於Kubeadm和我們的配置修改

Kubeadm功能介紹

kubeadm init :引導master節點的建立(to bootstrap a Kubernetes master node)

kubeadm join :新增一個worker節點到叢集中(to bootstrap a Kubernetes worker node and join it to the cluster) (注:由於我們使用kubelet主動註冊的功能,故這個功能我們沒有用)

kubeadm upgrade :將叢集升級到新的版本(to upgrade a Kubernetes cluster to a newer version)

kubeadm config :管理叢集配置檔案,可修改或者檢視(if you initialized your cluster using kubeadm v1.7.x or lower, to configure your cluster for )

kubeadm upgrade :升級kubernetes元件

kubeadm token : 管理kubeadm join 使用的token (to manage tokens for kubeadm join) (注:由於我們使用kubelet主動註冊的功能,故這個功能我們沒有用)

kubeadm reset :恢復 kubeadm init或者 kubeadm join對主機的修改(to revert any changes made to this host by kubeadm init or kubeadm join)

Kubeadm 建立叢集流程

對於每一步的詳細內容,在下面介紹

Kubeadm 建立叢集詳細介紹

  1. preflight-checks:在對系統修改前,執行一系列的檢查,可通過—skip-preflight-checks跳過這一步的檢查(注:這裡由於有對證書目錄是否為空進行檢查,而我們的證書是生成好以後再拷貝到主機上,並在執行時希望kubeadm載入我們的證書,故這裡我們跳過了這一步的檢查)
  2. generate self-signed CA: 生成一個自簽名的CA證書(或者使用一個已存在的證書),在叢集的各個元件中認證時使用.如果使用者有指定他們自己的CA證書或者key,通過—cert-dir指定(預設為/etc/kubernetes/pki目錄),則使用使用者指定的證書。(注:我們就是這樣做的,先把除了apiserver.crt/key外,其他的證書放到/etc/kubernetes/pki目錄中,並通過引數 cert-dir,對應配置檔案中的certificatesDir,指定了證書的位置,這裡利用了kubeadm自動生成沒有找到的證書的機制,生成apiserver.crt/key)
  3. generate kubeconfig files: 在/etc/kubernetes/目錄中為kubelet,controller-manager和scheduler生成kubeconfig檔案,訪問API server時使用,每個元件都有他們自己的憑證;同時,也會生成一個具有管理員許可權的admin.conf配置檔案(注:可拷貝成~/.kube/config,執行kubectl時可讀取到)
  4. dynamic kubelet config: 如果通過—feature-gates=DynamicKubeletConfig 啟動了kubelet動態配置項,它將會生成kubelet init配置檔案到 /var/lib/kubelet/config/init/kubelet檔案中.這個功能當前預設是關閉,因為這個功能的優先順序不高,但它在將來新的版本會是一個預設的選項(注:在v1.8.6版本中還不是一個預設的功能,我們當前也沒有開啟這個功能)
  5. generate manifests files and wait for control plane running: 生成API server, controller manager 和scheduler的manifest檔案.如果沒有指定etcd,則還會生成etcd的manifest檔案(注:我們指定了etcd,故我們沒有生成etcd.yaml檔案)

靜態Pod的manifests預設都要求放在/etc/kubernetes/manifests; kubelet會監視這個目錄,如果有修改,或者新建立的檔案,則會自動刪除並啟動或者建立新的靜態Pod.(注:這裡有個遲遲沒有解決的問題,如果嘗試去修改這個目錄下的檔案,就會發現,有時候修改後,Pod被刪除了,但是新的Pod沒有創建出來,這時,可以嘗試將檔案拷貝出這個目錄,等個10幾秒,然後拷貝回來,則可以正常啟動靜態Pod)

執行到這一步,回阻塞,但一旦控制組件起來並且正常執行,kubeadm init就會繼續執行(注:這裡要注意,由於google的映象,在國內下載不了,早前的版本會一直等待,後來的版本會失敗結束.如果有其他的映象倉庫,則可以通過配置項imageRepository指定為自己的映象倉庫)

  1. add labels and taints: 如果通過—feature-gates=DynamicKubeletConfig 啟動了kubelet動態配置,它將會通過建立一個ConfigMap和一些RBAC規則來保證kubelet能夠正常的訪問,修改通過Node.spec.configSource指定的node,新建立的ConfigMap,這個功能預設關閉.(注:我們沒有啟用這個功能)
  2. generate bootstrap token: 新增一些標籤和taints在主節點上,這樣就沒有額外的工作負載在這上面(注:我們當前在單主機和高可用叢集中都刪除了這個taint,並新增新的標籤,以標記這個節點既是Master節點,又是Node節點)
  3. make node join works via join token: 生成token,使其他的Node節點可以註冊到這個Master節點。可選,也可以通過—token指定(注:我們早先的版本,有使用kubeadm join的功能,這個token我們是自己生成後,通過這個配置指定,以保證多Master叢集情況下,使用的是同一個token)
  4. make node join works via join token: 為了允許Node通過kubeadm join token 加入到叢集,以及啟動TLS,需要做的必要的配置:

1.加入所需要的全部的ConfigMap,啟動相關的RBAC訪問規則

2.使Bootstrap Token可以訪問CSR的API

3.設定新的CSR請求自動批准

  1. install dns: 通過API server安裝內部的DNS伺服器(kube-dns)和kube-proxy.如果kubeadm通過–feature-gates=CoreDNS=true配置了使用CoreDNS,則CoreDNS會替代kube-dns作為預設的DNS服務安裝到叢集中.注意到,如果DNS伺服器被部署,就不會執行排程任務直到CNI外掛被安裝.(注:這個特性在v1.9版本之後支援,當前我們使用的是v1.8的版本,並且由於當前我們提供的應用級別的負載均衡,通過DNS可直接訪問應用的功能還處於測試階段,我們採用kube-dns作為預設DNS,而CoreDNS作為額外的DNS伺服器。這裡的CNI即Container Network Interface,是指實現了CNI介面的網路外掛,我們當前使用calico)
  2. change control plane if set self-hosting: 如果kubeadm init通過 alpha self-hosting功能啟動了單主機的特性,(—feature-gates=SelfHosting=true),則靜態Pod的控制器就會轉成self-host模式,與沒有指定的區別是,控制組件會有對應的leader(注:這裡主要是指 kube-controller-manager和schduler,我們在單主機叢集中沒有啟動這個選項)

Kubeadm 提供的引數

apiVersion: kubeadm.k8s.io/v1alpha1
kind: MasterConfiguration
api:
  advertiseAddress: <address|string>
  bindPort: <int>
etcd:
  endpoints:
  - <endpoint1|string>
  - <endpoint2|string>
  caFile: <path|string>
  certFile: <path|string>
  keyFile: <path|string>
  dataDir: <path|string>
  extraArgs:
    <argument>: <value|string>
    <argument>: <value|string>
  image: <string>
kubeProxy:
  config:
    mode: <value|string>
networking:
  dnsDomain: <string>
  serviceSubnet: <cidr>
  podSubnet: <cidr>
kubernetesVersion: <string>
cloudProvider: <string>
nodeName: <string>
authorizationModes:
- <authorizationMode1|string>
- <authorizationMode2|string>
token: <string>
tokenTTL: <time duration>
selfHosted: <bool>
apiServerExtraArgs:
  <argument>: <value|string>
  <argument>: <value|string>
controllerManagerExtraArgs:
  <argument>: <value|string>
  <argument>: <value|string>
schedulerExtraArgs:
  <argument>: <value|string>
  <argument>: <value|string>
apiServerExtraVolumes:
- name: <value|string>
  hostPath: <value|string>
  mountPath: <value|string>
controllerManagerExtraVolumes:
- name: <value|string>
  hostPath: <value|string>
  mountPath: <value|string>
schedulerExtraVolumes:
- name: <value|string>
  hostPath: <value|string>
  mountPath: <value|string>
apiServerCertSANs:
- <name1|string>
- <name2|string>
certificatesDir: <string>
imageRepository: <string>
unifiedControlPlaneImage: <string>
featureGates:
  <feature>: <bool>
  <feature>: <bool>

Kubeadm 我們當前使用的引數模板

apiVersion: kubeadm.k8s.io/v1alpha1
kind: MasterConfiguration
api:
  advertiseAddress: {{HOSTIP}}
  bindPort: 6443
etcd:
  endpoints:
  {{ETCD_ENDPOINTS}}
kubernetesVersion: {{KUBERNETES_VERISON}}
networking:
  dnsDomain: cluster.local
  serviceSubnet: {{SERVICE_SUBNET}}
  podSubnet: {{POD_SUBNET}}
token: {{JOIN_TOKEN}}
nodeName: {{HOSTNAME}}
certificatesDir: /etc/kubernetes/pki
imageRepository: ufleet.io/google_containers

與Kops和Kubespray的比較

Kops和Launcher的比較

  1. 對於k8s元件,kops需預安裝kubectl;launcher都自帶有對應版本的kubectl,所以不需要預先安裝(但由於部署儲存節點時需要等包,故還需要安裝)
  2. kops負責基礎設施流程和kubernetes的建立流程;launcher只能在已執行的linux主機上執行
  3. kops以普通服務的方式執行kubernetes;launcher以容器化方式執行kubernetes服務
  4. kops與AWS和GCP等公有云關係密切,不能在裸機上執行;launcher針對裸主機設計,對公有云環境沒有要求
  5. kops通過命令列執行,同步方式;launcher是獨立的服務,通過restful api互動,傳送請求後立即返回,非同步執行
  6. kops高可用叢集中的etcd節點,允許執行在node節點上;launcher高可用叢集,etcd節點都執行在master節點上
  7. kops當前已經支援升級kubernetes,可指定版本安裝,可指定網路外掛;launcher當前不支援升級kubernetes版本,並且不能指定版本安裝,預設使用calico外掛,不可配置

Kubespray和Launcher的比較

  1. kubespray屬於kubernetes孵化器中的專案,通過ansible playbook來定義系統和執行kubernetes叢集安裝任務的流程;launcher沒有依賴其他的自動化運維工具,定義自己的安裝流程,只支援安裝部署kubernetes叢集,但針對性更強,使用也更加簡單
  2. kubespray需要先配置節點名到主機IP的DNS對映;launcher支援自動按照規則修改主機名,不需額外配置
  3. kubespray以普通服務的方式執行kubernetes;launcher以容器化方式執行kubernetes服務
  4. kubespray通過命令列執行,同步方式;launcher是獨立的服務,通過restful api互動,傳送請求後立即返回,非同步執行
  5. kubespray高可用叢集中的etcd節點,允許執行在node節點上;launcher高可用叢集,etcd節點都執行在master節點上
  6. kubespray當前已經支援升級kubernetes,可指定版本安裝,可指定網路外掛;launcher當前不支援升級kubernetes版本,並且不能指定版本安裝,預設使用calico外掛,不可配置

支援多版本以及自動升級的思考

支援指定k8s版本安裝

歷史原因:在老的版本,我們為了支援在無法連線外網的區域網內執行安裝任務,內建了特定版本的kubernetes檔案和映象,支援多個版本也沒有特定的需求。

目標:考慮到將來的發展,在新的launcher版本中,會將與映象和二進位制檔案等部分抽離,launcher將作為類似於框架程式碼,在kubeadm支援下,完成對指定版本的kubernetes執行安裝部署任務。

方案:當前Ufleet已經內建映象倉庫,並且我們已經實現了kubelet等元件的容器化,對於kubectl、kuberadm等,將按版本存放到某一個特定的倉庫容器映象中。launcher將定時查詢並更新支援的kubernetes版本。在安裝過程中,自動更新配置檔案,並通過映象倉庫獲取到指定版本的kubernetes元件,執行安裝任務。

支援k8s版本升級

目標:我們考慮在高可用叢集,支援k8s版本升級,並最小化對使用者的影響。

方案:其實對我們來說,在不影響使用者的正常使用情況下升級,並不是很難。我們當前已經支援主節點的增加和刪除,就是考慮到將來升級的。針對主節點,將按照如下流程:主節點切換為不可排程模式->遷移執行的Pod->刪除主節點->使用新版本新增主節點->切換為正常可排程模式。