歡迎光臨
每天分享高質量文章

VPS 單節點部署 Kubernetes 的方法與對比

Docker 在生產環境的部署方案,目前的最優解顯然是 Kubernetes 了,Kubernetes 提供了非常完備的功能,幾乎能改寫所有能想到的運維場景,這點無需多言。
唯獨對於流量不大,對於機器資源要求比較嚴苛的小專案,Kubernetes 就顯得不那麼友好了:一套高可用的 Kubernetes 集群,至少需要 3 個 Master 節點,Worker 節點雖然沒有明確要求,但至少 2 個 Worker 節點顯然是比較恰當的。也就是說哪怕只是一個靜態的 html 頁面,Kubernetes 也至少需要 4-5 台主機。
而在實際專案中,往往有一些新想法要試水,或者臨時上線一些非常簡單的頁面,為此單獨部署一套 Kubernetes 高可用 5 節點集群顯然是浪費的。將其隨便塞進一個已經在運行的不相干的集群,也是對運維秩序的擾亂。所以比較折中的做法是犧牲高可用性,基於 1 台低配置的 VPS 或虛擬主機,部署一套 Kubernetes 單節點環境。
當然也可以不用 Kubernetes,直接通過命令列或 docker-compose 操作 Docker 也能實現同樣目的。這裡非要死磕 Kubernetes 主要基於 3 個原因:
  • 其一是統一運維的基礎設施,如果同一個運維團隊里,同時存在 Kubernetes、Docker Swarm、Shell 腳本等多種運維工具,維護起來難免顧此失彼,容易產生問題,也不利於技術積累。

  • 其二是基於 Kubernetes 可以快速水平擴展,特別是一個新想法上線如果短期內獲得了不錯的反應,流量會有快速的增長,基於 Kubernetes 的配置可以在數分鐘內從單機擴展到上百台機器的集群。

  • 其三是可以使用成熟的 Kubernetes 部署策略,即便是單節點,仍然可以通過簡單配置就實現滾動更新(RollingUpdate)、回滾等。同時還可以有 Kubernetes Dashboard 這樣好用的 UI 界面,而其他方案則要自己實現這些,並不划算。

 

當然單節點部署 Kubernetes 也需要付出代價,由於單節點既充當了 Master 節點,又是 Worker 節點,會有額外的 CPU 和記憶體消耗。實測 2 核 4G 的機器,裸 Kubernetes 會額外占用掉 0.2~0.5 核左右的 CPU 資源和 600MB 左右記憶體資源,建議單節點機器至少也應該有 2 核 4G 及以上規格。
以下以 Linode 4GB Plan 為例,記錄單節點 Kubernetes 的部署過程。
基於 Minikube 在 VPS 快速部署單節點 Kubernetes

 

Minikube 原本是用於在開發環境快速安裝 Kubernetes 的工具,由於 Docker 需要系統為 Linux 且內核支持 LXC,因此在 Windows、macOS 下目前都是通過虛擬機來實現 Docker 的安裝及運行的。而 Minikube 支持 Windows、macOS、Linux 三種 OS,會根據平臺不同,下載對應的虛擬機鏡像,併在鏡像內安裝 Kubernetes。
目前的虛擬機技術都是基於 Hypervisor來實現的,Hypervisor 規定了統一的虛擬層接口,由此 Minikube 就可以無縫切換不同的虛擬機實現,如 macOS 可以切換 Hyperkit 或 VirtualBox, Windows 下可以切換 Hyper-V 或 VirtualBox 等。虛擬機的切換可以通過 –vm-driver 實現,如:
  1. minikube start --vm-driver hyperkit
  2. minikube start --vm-driver hyperv
如果 Minikube 安裝在內核原生就支持 LXC 的 OS 內,如 Ubuntu 等,再安裝一次虛擬機顯然就是對資源的浪費了,Minikube 提供了直接對接 OS 底層的方式:
  1. minikube start --vm-driver=none
因此在 VPS 上,可以借助 Minikube,快速安裝 Kubernetes 環境,同時又最大限度的使用 OS 系統資源。
OS 以 Ubuntu 18.04 為例。
1、安裝 Docker Engine
由於 Minikube 限制,必須安裝版本不高於 v18.09 的 Docker (截止 2019 年 2 月 19 日)。
可以用 apt-cache policy docker-ce 查看可以安裝的 Docker 版本, 這裡我們選擇 18.06.2。
  1. apt-get install -y apt-transport-https ca-certificates curl software-properties-common && \
  2. curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \
  3. add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" && \
  4. apt-get update && apt-get install docker-ce=18.06.2~ce~3-0~ubuntu
2、安裝 Minikube
  1. curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube && sudo cp minikube /usr/local/bin/ && rm minikube
  2. export MINIKUBE_WANTUPDATENOTIFICATION=false
  3. export MINIKUBE_WANTREPORTERRORPROMPT=false
  4. export MINIKUBE_HOME=$HOME
  5. export CHANGE_MINIKUBE_NONE_USER=true
  6. mkdir -p $HOME/.minikube
3、啟動 Minikube
  1. minikube start --vm-driver=none
如果一切順利,可以看到 Minikube 將下載並安裝 kubeadm kubelet 等必要組件,最後按照 Minikube 的提示,安裝 kubectl:
  1. sudo apt-get update && sudo apt-get install -y apt-transport-https
  2. curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
  3. echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
  4. sudo apt-get update
  5. sudo apt-get install -y kubectl
之後就可以通過 kubectlgetpods-n kube-system 查看容器的運行情況了。
為了方便操作,建議配置 kubectl 的指令補全, 並將命名空間切換至 kube-system, 後文指令都將忽略命名空間 kube-system。
  1. kubectl completion bash >> ~/.bashrc
  2. source ~/.bashrc
  3. kubectl config set-context minikube --namespace=kube-system
解決 CoreDNS Forwarding loop 問題
在我的 VPS 上完成上述安裝後, 可以看到 CoreDNS 服務並沒有完成啟動:
  1. # kubectl get pods
  2. NAMESPACE NAME READY STATUS RESTARTS AGE
  3. kube-system coredns-86c58d9df4-jjhwl 0/1 CrashLoopBackOff 5 3m59s
  4. kube-system coredns-86c58d9df4-zzj4m 0/1 CrashLoopBackOff 5 3m59s
通過查看日誌可以看到 CoreDNS 服務檢測到了迴圈 DNS 查詢
  1. # kubectl logs coredns-86c58d9df4-jjhwl
  2. [FATAL] plugin/loop: Forwarding loop detected in "." zone. Exiting. See https://coredns.io/plugins/loop#troubleshooting. Probe query: "HINFO 6451342721392587444.9147583119172762210.".
這一問題在 Ubuntu 上非常容易遭遇,是因為 Ubuntu 使用 systemd-resolved 作為 DNS 解析器,當網絡狀態變化時,systemd-resolved 有可能將 127.0.0.53 作為域名服務器寫入 /etc/resolv.conf,而 CoreDNS 預設又會讀取宿主機上 systemd-resolved 所使用的檔案,造成死迴圈。
解決這個問題的一種方法是在啟動 Minikube 時直接指定 resolv.conf 檔案位置, 如:
  1. minikube --vm-driver=none start --extra-config=kubelet.resolv-conf=/run/systemd/resolve/resolv.conf
如果啟動 Minikube 後產生了這個問題,則可以刪除resolv.conf軟鏈接, 自己生成一個resolv.conf,當 systemd-resolved 檢測到 /etc/resolv.conf 不是軟鏈接後,就不會再改寫這個檔案。
  1. rm /etc/resolv.conf && echo "nameserver 114.114.114.114 > /etc/resolv.conf"
  2. kubectl delete pods -n kube-system --selector k8s-app=kube-dns
也可以將 /etc/resolv.conf 指向主機商提供的 DNS 解析檔案。
  1. rm /etc/resolv.conf && cp /run/systemd/resolve/resolv.conf /etc/resolv.conf
  2. kubectl delete pods -n kube-system --selector k8s-app=kube-dns
Minikube 不使用虛擬機的註意點
由於 Minikube 主要設計是基於虛擬機安裝的,vm-driver=none 也會帶來一些影響,主要包括:
  1. Minikube 在安裝時將改寫主機原有的 /usr/local/bin/kubeadm,/usr/local/bin/kubectl,/etc/kubernetes 等目錄

  2. 無法在一臺主機上使用 vm-driver=none 安裝 2 個 minikube

  3. minikube dashboard,minikube mount,minikube ssh 等基於虛擬機的指令均無法使用

  4. minikube delete 將刪除 /etc/kubernetes 目錄

     

為了避免問題,建議使用全新的主機安裝,使用完後直接回收主機即可。
基於 MicroK8s 在 VPS 快速部署單節點 Kubernetes

 

Minikube 雖然是官方出品,但主要還是基於虛擬機做的設計。在 Linux 生產環境下,MicroK8s 可能是一個更合適的選擇。
MicroK8s 基於 Snap 進行安裝,Ubuntu 16.04 及之後的版本都已經預裝了 Snap,如果是其他發行版的 Linux 需要先安裝 Snap。 安裝前 MicroK8s 可以通過:
  1. snap info microk8s
瞭解可安裝版本和操作指令等信息。
MicroK8s 的獨特之處在於直接包含了 Kubernetes 單節點必須的如 kubectl,kubelet 等所有工具,甚至直接包含了 Docker。因此在一臺裸機上運行:
  1. snap install microk8s --classic
之後,就可以在行程里看到 /snap/microk8s 為前綴的一系列熟悉的行程, 並且這些行程直接運行在主機,並未使用容器,Kubernetes 也沒有使用預設的端口 6443,而改用 8080。這樣做帶來的一個好處是即便系統之前已經安裝了kubectl,Docker 等,也可以進行安裝,不會衝突;不過就不能用 kubectl、 Docker直接進行操作, 而需要使用 microk8s.docker,microk8s.kubectl 等, 與原來的指令是完全一樣的。
安裝完成後可以通過 microk8s.status 查看運行狀態及插件的開啟情況。也可以用 microk8s.inspect 查看已經安裝的服務。
通常來說安裝了 MicroK8s 後,我們也不會再次安裝 kubectl, 為了操作方面,可以為 microk8s.kubectl 開啟設置 kubectl 為別名, 並開啟輸入補全。
  1. snap alias microk8s.kubectl kubectl
  2. source microk8s.kubectl completion bash)
也可以隨時取消別名。
  1. snap unalias kubectl
和 Minikube 相同,MicroK8s 預設只安裝最核心的功能,可以通過 microk8s.enable dns dashboard 等開啟附加的插件。
使用 Kubeadm 部署單節點 Kubernetes

 

通過 Minikube 或 MicroK8s 安裝 Kubernetes 雖然方便,但是由於很多安裝細節被屏蔽,直接用在生產環境也難免讓人心存疑慮,那麼也可以使用 Kubeadm 部署單節點 Kubernetes。
同樣以 Ubuntu18.04 為例, 首先安裝 Docker v18.06.2 後 (Kubernetes 同樣對 Docker 版本有要求),參考官方文件, 可以使用 apt-get 直接安裝 kubelet,kubeadm,kubectl,並且限制這些服務不能自動升級。
  1. apt-get update && apt-get install -y apt-transport-https curl
  2. curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
  3. cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
  4. deb https://apt.kubernetes.io/ kubernetes-xenial main
  5. EOF
  6. apt-get update
  7. apt-get install -y kubelet kubeadm kubectl
  8. apt-mark hold kubelet kubeadm kubectl
接下來關閉 Swap,這應該是為了避免 Swap 對 CPU 和記憶體的Llimit 造成意外影響。
  1. swapoff -a
然後運行:
  1. kubeadm init --pod-network-cidr=10.244.0.0/16
就會開始 Kubernetes Master 節點的安裝。安裝完成後 CoreDNS 是處於 Pending 狀態的,這是由於網絡插件尚未安裝,Kubernetes 使用 CNI 作為容器網絡的接口,因此可以根據主機實際情況選擇不同的 CNI 實現,這裡以比較流行的 Flannel 為例。
  1. kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml
之後可以看到 CoreDNS 的狀態從 Pending 變為 Running。至此 Kubernetes 的 Master 節點所需服務就已經安裝完畢。可以參考安裝後的提示,配置 kubectl:
  1. mkdir -p $HOME/.kube
  2. sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  3. sudo chown $(id -u):$(id -g) $HOME/.kube/config
現在嘗試部署一個 Pod:
  1. kubectl run --rm --restart=Never -it --image=hello-world test-pod
發現 Pod 狀態卡在 Pending,查看 Pod 信息看到如下報錯:
  1. $ kubectl describe pod test-pod
  2. 0/1 nodes are available: 1 node(s) had taints that the pod didn't tolerate.
這是由於 Kubernetes 預設禁止在 Master 節點部署 Pod,可以使用以下指令取消這一限制。
  1. kubectl taint nodes --all node-role.kubernetes.io/master-
之後可以看到 Pod 狀態已經變為 Completed。
Kubernetes 單節點部署方式對比

 

至此我們分別用 Minikube、MicroK8s、Kubeadm 3 種方式完成了單節點 Kubernetes 的部署。從安裝的服務來看,Kubernetes 單節點必要的服務包括:
  • 容器運行時:預設是 Docker

  • etcd:key-value 儲存服務,用於儲存集群的狀態

  • kube-apiserver:集群資源操作的唯一入口,並提供認證、授權、訪問控制、API 註冊和發現等機制

  • kube-controller-manager:維護集群的狀態,比如故障檢測、自動擴展、滾動更新等

  • kube-scheduler:負責資源的調度,按照預定的調度策略將 Pod 調度到相應的機器上

  • kubelet:負責維持容器的生命周期,同時也負責 Volume(CVI)和網絡(CNI)的管理

  • kube-proxy:負責為 Service 提供 Cluster 內部的服務發現和負載均衡

 

三者差異之處在於:
  • MicroK8s 部署 Kubernetes 是直接安裝到主機而不是以容器方式安裝

  • MicroK8s 雖然預設沒有安裝 DNS 服務,但通常情況下為了使用服務發現,還是需要安裝的,MicroK8s 預設的 DNS 服務是 Kube-Dns,而不是目前官方推薦的 CoreDNS 。

  • 網絡插件 Kubeadm 需要自己選擇, MicroK8s 和 Minikube 都會自己安裝

  • Minikube 預設額外安裝了 storage-provisioner 用於虛擬機掛載磁盤 從易用角度來看,MicroK8s 是安裝最簡單,門檻最低的;Minikube 適合對 Minikube 比較熟悉的用戶。

無論以何種方式安裝 Kubernetes, 都需要註意安全問題, 因為在 Kubernetes 的設計中, Master 節點是不會暴露到外網的,用戶服務都會安裝到 Worker 節點,但是在單節點的情況下,Kubernetes 所監聽的端口都沒有設防,容器的權限也有可能過大,這些安全問題在 Minikube 的文件中也有提到, 需要對網絡端口設置 iptables 限制可訪問的 IP 等方式來提升安全性,如果是安全性敏感的專案,建議放棄單節點 Kubernetes 的方案。
原文鏈接:https://avnpc.com/pages/kubernetes-for-single-vps

赞(0)

分享創造快樂