背景
目前,很多邊緣計算容器開源項目在使用上均存在一個默認的前提:用戶需要提前准備一個標准的或者特定工具搭建的 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 集群
安裝前提
- 准備一個Master VIP,做為可用負載均衡統一入口;
- 3台滿足 kubeadm 的最低要求 的機器作為Master節點;
- 3台滿足 kubeadm 的最低要求 的機器做worker節點;
安裝 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 一塊來修復。