用 edgeadm 一鍵安裝邊緣 K8s 叢集和原生 K8s 叢集

騰訊雲原生發表於2021-05-18

背景

目前,很多邊緣計算容器開源專案在使用上均存在一個預設的前提:使用者需要提前準備一個標準的或者特定工具搭建的 Kubernetes 叢集,然後再通過特定工具或者其他方式在叢集中部署相應元件來體驗邊緣能力。這無疑提高了使用者體驗邊緣能力的門檻,而且使用上有眾多的限制,讓使用者很難上手。 簡單整理,大概會有如下問題:

門檻太高

  • 使用者需要提前準備一個 Kubernetes 叢集,對於很多使用者來說門檻太高,搭建的流程比較複雜,容易失敗,把很多想使用邊緣能力的人群拒之門外;

限制性太大

  • 往往要求特定工具搭建的特定版本的 Kubernetes 叢集,通用性太差,使用者在想在實際生產環境上使用限制性太大;

新增邊緣節點比較麻煩

  • 新增邊緣節點需要依靠搭建 Kubernetes 叢集本身的工具新增 Kubernetes 原生的節點再進行轉化,對第三方工具依賴性較強,並且操作流程比較麻煩,容易出錯;

自動化能力較差

  • 無論 Kubernetes 叢集的搭建,還是新增邊緣節點都很難在生產環境自動化起來,相關流程還需要自己的團隊進行二次開發,整合難度較大;

為了降低使用者體驗邊緣能力的門檻,雲原生社群的同學打算開發一個可以一鍵部署邊緣 Kubernetes 叢集的方法,讓使用者可以更容易、更簡單的體驗邊緣 Kubernetes 叢集。

架構設計

針對上述問題,為了降低使用者使用邊緣 Kubernetes 叢集的門檻,讓邊緣 Kubernetes 叢集具備生產能力,我們設計了一鍵就可以部署出來一個邊緣 Kubernetes 叢集的方案,完全遮蔽安裝細節,讓使用者可以零門檻的體驗邊緣能力。

初衷

  • 讓使用者很簡單、無門檻的使用邊緣 Kubernetes 叢集,並能在生產環境真正把邊緣能力用起來;

目標

一鍵化使用

  • 能夠一鍵搭建起一個邊緣 Kubernetes 叢集;
  • 能夠一鍵很簡單、很靈活的新增邊緣節點;

兩種安裝創景

  • 支援線上安裝;
  • 支援離線安裝,讓私有化環境也能很簡單;

可生產使用

  • 不要封裝太多,可以讓想使用邊緣 Kubernetes 叢集的團隊能在內部系統進行簡單的整合,就生產可用;

零學習成本

  • 儘可能的和 kubeadm 的使用方式保持一致,讓使用者無額外的學習成本,會用 kubeadm 就會用 edgeadm;

原則

  • 不修改 kubeadm 原始碼
    • 儘量引用和複用 kubeadm 的原始碼,儘量不修改 kubeadm 的原始碼,避免後面升級的隱患;
    • 基於 kubeadm 但又高於 kubeadm,不必被 kubeadm 的設計所侷限,只要能讓使用者使用起來更簡單就可以被允許;
  • 允許使用者選擇是否部署邊緣能力元件;
  • 允許使用者自定義邊緣能力元件的配置;

設計與實現

我們研究了 kubeadm 的原始碼,發現可以借用 kubeadm 建立原生 Kubernetes叢集、join 節點、workflow 思想來一鍵部署邊緣 Kubernetes 叢集,並且可以分步去執行安裝步驟。這正是我們想要的簡單、靈活、低學習成本的部署方案。於是我們站在巨人的肩膀上,利用 Kubedam 的思想,複用 kubeadm 的原始碼,設計出瞭如下的解決方案。

其中 kubeadm init cluster/join node部分完全複用了 kubadm 的原始碼,所有邏輯和 kubeadm 完全相同。

這個方案有如下幾個優點:

完全相容 kubeadm

我們只是站在 kubeadm 的肩膀上,在 kubeadm init/join 之前設定了一些邊緣叢集需要的配置引數,將初始化 Master 或 Node 節點自動化,安裝了容器執行時。在 kubeadm init/join 完成之後,安裝了 CNI 網路外掛和部署了相應的邊緣能力元件。

我們以 Go Mod 方式引用了 kubeadm 原始碼,整個過程中並未對 kubeadm 的原始碼修改過一行,完全的原生,為後面升級更高版本的 kubeadm 做好了準備。

一鍵化,用起來簡單、靈活、自動化

edgeadm init 叢集和 join 節點完全保留了 kubeadm init/join 原有的引數和流程,只是自動了初始化節點和安裝容器執行時,可以用edgeadm --enable-edge=fasle引數來一鍵化安裝原生 Kubernetes 叢集, 也可以用edgeadm --enable-edge=true引數一鍵化來安裝邊緣 Kubernetes 叢集。

可以 Join 任何只要能夠訪問到 Kube-apiserver 位於任何位置的節點, 也可以 join master。join master 也延續了 kubeadm 的的方式,搭建高可用的節點可以在需要的時候,直接用 join master 去擴容 Master 節點,實現高可用。

無學習成本,和 kubeadm 的使用完全相同

因為kubeadm init cluster/join node部分完全複用了 kubadm 的原始碼,所有邏輯和 kubeadm 完全相同,完全保留了 kubeadm 的使用習慣和所有 flag 引數,用法和 kubeadm 使用完全一樣,沒有任何新的學習成本,使用者可以按 kubeadm 的引數或者使用 kubeadm.config 去自定義邊緣 Kubernetes 叢集。

邊緣節點安全增強

藉助 Kubernetes Node鑑權機制,我們預設開啟了NodeRestriction准入外掛,確保每個節點身份都唯一,只具有最小許可權集,即使某個邊緣節點被攻破也無法操作其他邊緣節點。

Kubelet 我們也預設開啟了Kubelet配置證照輪換機制,在 Kubelet 證照即將過期時, 將自動生成新的祕鑰,並從 Kubernetes API 申請新的證照。 一旦新的證照可用,它將被用於與 Kubernetes API 間的連線認證。

用 edgeadm 安裝邊緣 Kubernetes 叢集

以下流程社群已經錄製了詳細教程視訊,可結合文件進行安裝:

視訊資源連結:用edgeadm一鍵安裝邊緣Kubernetes 叢集和原生Kubernetes 叢集

安裝條件

  • 遵循 kubeadm 的最低要求 ,Master && Node 最低2C2G,磁碟空間不小於1G;

  • 目前支援 amd64、arm64 兩個體系;

    其他體系可自行編譯 edgeadm 和製作相應體系安裝包,可參考 5. 自定義Kubernetes靜態安裝包

  • 支援的 Kubernetes 版本:大於等於v1.18,提供的安裝包僅提供 Kubernetes v1.18.2 版本;

    其他 Kubernetes 版本可參考 5. 自定義 Kubernetes 靜態安裝包,自行製作。

下載 edgeadm 靜態安裝包

下載 edgeadm 靜態安裝包,並拷貝到所有 Master 和 Node 節點。

注意修改"arch=amd64"引數,目前支援[amd64, amd64], 下載自己機器對應的體系結構,其他引數不變

arch=amd64 version=v0.3.0-beta.0 && rm -rf edgeadm-linux-* && wget https://superedge-1253687700.cos.ap-guangzhou.myqcloud.com/$version/$arch/edgeadm-linux-$arch-$version.tgz && tar -xzvf edgeadm-linux-* && cd edgeadm-linux-$arch-$version && ./edgeadm

安裝包大約200M,關於安裝包的詳細資訊可檢視 5. 自定義Kubernetes靜態安裝包

如果下載安裝包比較慢,可直接檢視相應SuperEdge相應版本, 下載edgeadm-linux-amd64/arm64-*.0.tgz,並解壓也是一樣的。

一鍵安裝邊緣獨立 Kubernetes 叢集功能從 SuperEdge-v0.3.0-beta.0開始支援,注意下載 v0.3.0-beta.0 及以後版本。

安裝邊緣 Kubernetes Master 節點

./edgeadm init --kubernetes-version=1.18.2 --image-repository superedge.tencentcloudcr.com/superedge --service-cidr=10.96.0.0/12 --pod-network-cidr=192.168.0.0/16 --install-pkg-path ./kube-linux-*.tar.gz --apiserver-cert-extra-sans=<Master節點外網IP> --apiserver-advertise-address=<Master節點內網IP> --enable-edge=true -v=6

其中:

  • --enable-edge=true: 是否部署邊緣能力元件,預設 true

--enable-edge=false 表示安裝原生 Kubernetes 叢集,和 kubeadm 搭建的叢集完全一樣;

  • --install-pkg-path: Kubernetes 靜態安裝包的地址

--install-pkg-path的值可以為機器上的路徑,也可以為網路地址(比如:http://xxx/xxx/kube-linux-arm64/amd64-*.tar.gz, 能免密wget到就可以),注意用和機器體系匹配的Kubernetes靜態安裝包;

  • --apiserver-cert-extra-sans: kube-apiserver的證照擴充套件地址
    • 推薦簽訂Master節點外網IP或者域名,只要簽訂的Master節點的IP或者域名能被邊緣節點訪問到就可以,當然內網IP也被允許,前提是邊緣節點可以通過此IP訪問 Kube-apiserver。自定義域名的話可自行在所有 Matser和Node節點配置 hosts;
    • 簽訂外網IP和域名,是因為邊緣節點一般和 Master 節點不在同一區域網,需要通過外網來加入和訪問Master;
  • --image-repository:映象倉庫地址

要是 superedge.tencentcloudcr.com/superedge 比較慢,可換成其他加速映象倉庫,只要能 Pull 下來 kube-apiserver,kube-controller-manager,kube-scheduler,kube-proxy,etcd, pause……映象就可以。

其他引數和 kubeadm 含義完全相同,可按 kubeadm 的要求進行配置。

也可用 kubeadm.config 配置 kubeadm 的原引數,通過edgeadm init --config kubeadm.config --install-pkg-path ./kube-linux-*.tar.gz 來建立邊緣 Kubernetes 叢集。

要是執行過程中沒有問題,叢集成功初始化,會輸出如下內容:

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config
  
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/
  
Then you can join any number of worker nodes by running the following on each as root:

edgeadm join xxx.xxx.xxx.xxx:xxx --token xxxx \
    --discovery-token-ca-cert-hash sha256:xxxxxxxxxx
    --install-pkg-path <Path of edgeadm kube-* install package>

執行過程中如果出現問題會直接返回相應的錯誤資訊,並中斷叢集的初始化,可使用./edgeadm reset命令回滾叢集的初始化操作。

設定Master kube-config 檔案

要使非 root 使用者可以執行 kubectl,請執行以下命令,它們也是 edgeadm init 輸出的一部分:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

或者,如果你是 root 使用者,則可以執行:

export KUBECONFIG=/etc/kubernetes/admin.conf

注意儲存./edgeadm init輸出的./edgeadm join命令,後面新增Node節點時會用到。

其中token的有效期和kubeadm一樣24h,過期之後可以用./edgeadm token create建立新的token。

--discovery-token-ca-cert-hash 的值生成也同 kubeadm,可在 Master 節點執行下面命令生成。

openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

Join 邊緣節點

在邊緣節點上執行 <2>.下載edgeadm靜態安裝包,或者通過其他方式把 edgeadm 靜態安裝包上傳到邊緣節點,然後執行如下命令:

./edgeadm join <Master節點外網IP/Master節點內網IP/域名>:Port --token xxxx \
     --discovery-token-ca-cert-hash sha256:xxxxxxxxxx 
     --install-pkg-path <edgeadm Kube-*靜態安裝包地址/FTP路徑> --enable-edge=true

其中:

  • <Master 節點外網 IP/Master 節點內網IP/域名>:Port 是節點訪問 Kube-apiserver 服務的地址

可以把edgeadm init加入節點提示的 Kube-apiserver 服務的地址視情況換成Master節點外網IP/Master節點內網IP/域名,主要取決於想讓節點通過外網還是內網訪問 Kube-apiserver 服務。

  • --enable-edge=true: 加入的節點是否作為邊緣節點(是否部署邊緣能力元件),預設 true

--enable-edge=false 表示 join 原生 Kubernetes 叢集節點,和 kubeadm join 的節點完全一樣;

如果執行過程中沒有問題,新的 Node 成功加入叢集,會輸出如下內容:

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

執行過程中如果出現問題會直接返回相應的錯誤資訊,並中斷節點的新增,可使用./edgeadm reset命令回滾加入節點的操作,重新 join。

提示:如果邊緣節點 join 成功後都會給邊緣節點打一個label: superedge.io/edge-node=enable,方便後續應用用 nodeSelector 選擇應用排程到邊緣節點;

原生 Kubernetes 節點和 kubeadm 的 join 一樣,不會做任何操作。

用 edgeadm 安裝邊緣高可用 Kubernetes 叢集

安裝前提

安裝 Haproxy

在 Master 上安裝 Haproxy 作為叢集總入口

注意:替換配置檔案中的 < Master VIP >

# yum install -y haproxy# cat << EOF >/etc/haproxy/haproxy.cfgglobal    log         127.0.0.1 local2    chroot      /var/lib/haproxy    pidfile     /var/run/haproxy.pid    maxconn     4000    user        haproxy    group       haproxy    daemon    stats socket /var/lib/haproxy/statsdefaults    mode                    http    log                     global    option                  httplog    option                  dontlognull    option http-server-close    option forwardfor       except 127.0.0.0/8    option                  redispatch    retries                 3    timeout http-request    10s    timeout queue           1m    timeout connect         10s    timeout client          1m    timeout server          1m    timeout http-keep-alive 10s    timeout check           10s    maxconn                 3000frontend  main *:5000    acl url_static       path_beg       -i /static /images /javascript /stylesheets    acl url_static       path_end       -i .jpg .gif .png .css .js    use_backend static          if url_static    default_backend             appfrontend kubernetes-apiserver    mode                 tcp    bind                 *:16443    option               tcplog    default_backend      kubernetes-apiserverbackend kubernetes-apiserver    mode        tcp    balance     roundrobin    server  master-0  <Master VIP>:6443 check # 這裡替換 Master VIP 為使用者自己的 VIPbackend static    balance     roundrobin    server      static 127.0.0.1:4331 checkbackend app    balance     roundrobin    server  app1 127.0.0.1:5001 check    server  app2 127.0.0.1:5002 check    server  app3 127.0.0.1:5003 check    server  app4 127.0.0.1:5004 checkEOF

安裝 Keepalived

在所有 Master 安裝 Keepalived,執行同樣操作:
注意:

  • 替換配置檔案中的 < Master VIP >

  • 下面的 keepalived.conf 配置檔案中 < Master 本機外網 IP > 和 < 其他 Master 外網 IP > 在不同 Master 的配置需要調換位置,不要填錯。

  ## 安裝keepalived  yum install -y keepalived  cat << EOF >/etc/keepalived/keepalived.conf   ! Configuration File for keepalived  global_defs {     smtp_connect_timeout 30     router_id LVS_DEVEL_EDGE_1  }  vrrp_script checkhaproxy{  script "/etc/keepalived/do_sth.sh"  interval 5  }  vrrp_instance VI_1 {      state BACKUP      interface eth0      nopreempt      virtual_router_id 51      priority 100      advert_int 1      authentication {          auth_type PASS          auth_pass aaa      }      virtual_ipaddress {          <master VIP> # 這裡替換 Master VIP 為使用者自己的 VIP      }      unicast_src_ip <Master 本機外網 IP>      unicast_peer {        <其他 Master 外網 IP>        <其他 Master 外網 IP>      }  notify_master "/etc/keepalived/notify_action.sh master"  notify_backup "/etc/keepalived/notify_action.sh BACKUP"  notify_fault "/etc/keepalived/notify_action.sh FAULT"  notify_stop "/etc/keepalived/notify_action.sh STOP"  garp_master_delay 1  garp_master_refresh 5     track_interface {       eth0     }     track_script {       checkhaproxy      }  }  EOF

安裝高可用邊緣 Kubernetes Master

在其中一臺 Master 中執行叢集初始化操作

./edgeadm init --control-plane-endpoint <Master VIP> --upload-certs --kubernetes-version=1.18.2 --image-repository superedge.tencentcloudcr.com/superedge --service-cidr=10.96.0.0/12 --pod-network-cidr=192.168.0.0/16 --apiserver-cert-extra-sans=<Master節點外網IP/Master節點內網IP/域名/> --install-pkg-path <edegadm Kube-*靜態安裝包地址> -v=6

引數含義同 3. 用 edgeadm 安裝邊緣 Kubernetes 叢集,其他和 kubeadm 一致,這裡不在解釋;

要是執行過程中沒有問題,叢集成功初始化,會輸出如下內容:

Your Kubernetes control-plane has initialized successfully!To start using your cluster, you need to run the following as a regular user:  mkdir -p $HOME/.kube  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config  sudo chown $(id -u):$(id -g) $HOME/.kube/config  You should now deploy a pod network to the cluster.Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:  https://kubernetes.io/docs/concepts/cluster-administration/addons/  You can now join any number of the control-plane node running the following command on each as root:  edgeadm join xxx.xxx.xxx.xxx:xxx --token xxxx \    --discovery-token-ca-cert-hash sha256:xxxxxxxxxx \    --control-plane --certificate-key xxxxxxxxxx    --install-pkg-path <Path of edgeadm kube-* install package>    Please note that the certificate-key gives access to cluster sensitive data, keep it secret!As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use"edgeadm init phase upload-certs --upload-certs" to reload certs afterward.Then you can join any number of worker nodes by running the following on each as root:edgeadm join xxx.xxx.xxx.xxx:xxxx --token xxxx \    --discovery-token-ca-cert-hash sha256:xxxxxxxxxx      --install-pkg-path <Path of edgeadm kube-* install package>

執行過程中如果出現問題會直接返回相應的錯誤資訊,並中斷叢集的初始化,使用./edgeadm reset命令回滾叢集的初始化操作。

要使非 root 使用者可以執行 kubectl,請執行以下命令,它們也是 edgeadm init 輸出的一部分:

mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config

或者,如果你是 root 使用者,則可以執行:

export KUBECONFIG=/etc/kubernetes/admin.conf

注意儲存./edgeadm init輸出的./edgeadm join命令,後面新增Master節點和邊緣節點需要用到。

Join Master 節點

在另一臺 Master 執行./edgeadm join命令

./edgeadm join xxx.xxx.xxx.xxx:xxx --token xxxx    \    --discovery-token-ca-cert-hash sha256:xxxxxxxxxx \    --control-plane --certificate-key xxxxxxxxxx     \    --install-pkg-path <edgeadm Kube-*靜態安裝包地址 

要是執行過程中沒有問題,新的 Master 成功加入叢集,會輸出如下內容:

This node has joined the cluster and a new control plane instance was created:* Certificate signing request was sent to apiserver and approval was received.* The Kubelet was informed of the new secure connection details.* Control plane (master) label and taint were applied to the new node.* The Kubernetes control plane instances scaled up.* A new etcd member was added to the local/stacked etcd cluster.To start administering your cluster from this node, you need to run the following as a regular user:        mkdir -p $HOME/.kube        sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config        sudo chown $(id -u):$(id -g) $HOME/.kube/config        Run 'kubectl get nodes' to see this node join the cluster.

執行過程中如果出現問題會直接返回相應的錯誤資訊,並中斷節點的新增,使用./edgeadm reset命令回滾叢集的初始化操作。

Join node 邊緣節點

./edgeadm join xxx.xxx.xxx.xxx:xxxx --token xxxx \    --discovery-token-ca-cert-hash sha256:xxxxxxxxxx     --install-pkg-path <edgeadm Kube-*靜態安裝包地址/FTP路徑>

要是執行過程中沒有問題,新的 node 成功加入叢集,會輸出如下內容:

This node has joined the cluster:* Certificate signing request was sent to apiserver and a response was received.* The Kubelet was informed of the new secure connection details.Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

執行過程中如果出現問題會直接返回相應的錯誤資訊,並中斷節點的新增,使用./edgeadm reset命令回滾叢集的初始化操作。

自定義 Kubernetes 靜態安裝包

Kubernetes 靜態安裝包的目錄結構如下:

kube-linux-arm64-v1.18.2.tar.gz ## kube-v1.18.2 arm64的Kubernetes靜態安裝包├── bin                         ## 二進位制目錄│   ├── conntrack               ## 連線跟蹤的二進位制檔案│   ├── kubectl                 ## kube-v1.18.2的kubectl│   ├── kubelet                 ## kube-v1.18.2的kubelet│   └── lite-apiserver          ## 相應版本的lite-apiserver,可編譯SuperEdge的lite-apiserver生成├── cni                         ## cin的配置│   └── cni-plugins-linux-v0.8.3.tar.gz ## v0.8.3的CNI外掛二進位制壓縮包└── container                   ## 容器執行時目錄    └── docker-19.03-linux-arm64.tar.gz ## docker 19.03 arm64體系的安裝指令碼和安裝包

自定義其他 Kubernetes 版本

自定義其他 Kubernetes 版本需要做的有兩件事:

  • 替換二進位制目錄中的 kubectl 和 kubelet 檔案,版本需要大於等於 Kubernetes v1.18.0;
  • 確保 init 使用的映象倉庫中有相應 Kubernetes 版本的基礎映象;

自定義其他體系 Kubernetes 靜態安裝包

自定義 Kubernetes 靜態安裝包其他體系需要做三件事:

  • 將 Kubernetes 靜態安裝包的所有二進位制換成目標體系,包括 cni 和 container 相應安裝包中的二進位制;
  • 確保 init 使用的映象倉庫中有相應體系的 Kubernetes 版本的基礎映象,推薦使用多體系映象
  • 充分測試,確保沒有什麼相容問題。要有相關問題,也可以在 SuperEdge 社群提 Issues 一塊來修復。

相關文章