窮人也能用得起 K8s - VPS 單節點部署 Kubernetes 的方法與對比
更好的程式碼高亮可以參看原文
Docker 在生產環境的部署方案,目前的最優解顯然是 Kubernetes 了,Kubernetes (下稱 K8s)提供了非常完備的功能,幾乎能覆蓋所有能想到的運維場景,這點無需多言。
唯獨對於流量不大,對於機器資源要求比較嚴苛的小專案,K8s 就顯得不那麼友好了: 一套高可用的 K8s 叢集,至少需要 3 個 Master 節點,Worker 節點雖然沒有明確要求,但至少 2 個 Worker 節點顯然是比較恰當的。也就是說哪怕只是一個靜態的 html 頁面,K8s 也至少需要 4-5 臺主機。
而在實際專案中,往往有一些新想法要試水,或者臨時上線一些非常簡單的頁面,為此單獨部署一套 K8s 高可用 5 節點叢集顯然是浪費的。將其隨便塞進一個已經在執行的不相干的叢集,也是對運維秩序的擾亂。所以比較折中的做法是犧牲高可用性,基於 1 臺低配置的 VPS 或虛擬主機,部署一套 K8s 單節點環境。
當然也可以不用 K8s,直接通過命令列或 docker-compose 操作 Docker 也能實現同樣目的。這裡非要死磕 K8s 主要基於 3 個原因:
- 其一是統一運維的基礎設施,如果同一個運維團隊裡,同時存在 K8s、Docker Swarm、Shell 指令碼等多種運維工具,維護起來難免顧此失彼,容易產生問題,也不利於技術積累。
- 其二是基於 K8s 可以快速水平擴充套件,特別是一個新想法上線如果短期內獲得了不錯的反應,流量會有快速的增長,基於 K8s 的配置可以在數分鐘內從單機擴充套件到上百臺機器的叢集。
- 其三是可以使用成熟的 K8s 部署策略,即便是單節點,仍然可以通過簡單配置就實現滾動更新(RollingUpdate)、回滾等。同時還可以有 K8s dashboard 這樣好用的 UI 介面,而其他方案則要自己實現這些,並不划算。
當然單節點部署 K8s 也需要付出代價,由於單節點既充當了 Master 節點,又是 Worker 節點,會有額外的 CPU 和記憶體消耗。實測 2 核 4G 的機器,裸 K8s 會額外佔用掉 0.2~0.5 核左右的 CPU 資源和 600 MB 左右記憶體資源,建議單節點機器至少也應該有 2 核 4G 及以上規格。
以下以 Linode 4GB Plan 為例,記錄單節點 K8s 的部署過程。
基於 minikube 在 VPS 快速部署單節點 Kubernetes
minikube 原本是用於在開發環境快速安裝 K8s 的工具,由於 Docker 需要系統為 Linux 且核心支援 LXC,因此在 Windows、macOS 下目前都是通過虛擬機器來實現 Docker 的安裝及執行的。而 Minikube 支援 Windows、macOS、Linux 三種 OS,會根據平臺不同,下載對應的虛擬機器映象,並在映象內安裝 k8s。
目前的虛擬機器技術都是基於 Hypervisor 來實現的,Hypervisor 規定了統一的虛擬層介面,由此 Minikube 就可以無縫切換不同的虛擬機器實現,如 macOS 可以切換 hyperkit 或 VirtualBox, Windows 下可以切換 Hyper-V 或 VirtualBox 等。虛擬機器的切換可以通過 --vm-driver
實現,如
bash
minikube start --vm-driver hyperkit
minikube start --vm-driver hyperv
如果 Minikube 安裝在核心原生就支援 LXC 的 OS 內,如 Ubuntu 等,再安裝一次虛擬機器顯然就是對資源的浪費了,Minikube 提供了直接對接 OS 底層的方式
bash
minikube start --vm-driver=none
因此在 VPS 上,可以藉助 Minikube,快速安裝 K8s 環境,同時又最大限度的使用 OS 系統資源。
OS 以 Ubuntu 18.04 為例
1. 安裝 Docker Engine
由於 minikube 限制,必須安裝版本不高於 v18.09 的 Docker (截止 2019 年 2 月 19 日)
可以用 apt-cache policy docker-ce
檢視可以安裝的 Docker 版本, 這裡我們選擇 18.06.2
bash
apt-get install -y apt-transport-https ca-certificates curl software-properties-common && \
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" && \
apt-get update && apt-get install docker-ce=18.06.2~ce~3-0~ubuntu
2. 安裝 minikube
```bash curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube && sudo cp minikube /usr/local/bin/ && rm minikube
export MINIKUBE_WANTUPDATENOTIFICATION=false export MINIKUBE_WANTREPORTERRORPROMPT=false export MINIKUBE_HOME=$HOME export CHANGE_MINIKUBE_NONE_USER=true mkdir -p $HOME/.minikube ```
3. 啟動 minikube
bash
minikube start --vm-driver=none
如果一切順利,可以看到 minikube 將下載並安裝 kubeadm kubelet 等必要元件,最後按照 minikube 的提示,安裝 kubectl
bash
sudo apt-get update && sudo apt-get install -y apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubectl
之後就可以通過 kubectl get pods -n kube-system
檢視容器的執行情況了
為了方便操作,建議配置 kubectl 的指令補全, 並將名稱空間切換至 kube-system, 後文指令都將忽略名稱空間 kube-system
。
bash
kubectl completion bash >> ~/.bashrc
source ~/.bashrc
kubectl config set-context minikube --namespace=kube-system
解決 CoreDNS Forwarding loop 問題
在我的 VPS 上完成上述安裝後, 可以看到 CoreDNS 服務並沒有完成啟動
```plain
kubectl get pods
NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-86c58d9df4-jjhwl 0/1 CrashLoopBackOff 5 3m59s kube-system coredns-86c58d9df4-zzj4m 0/1 CrashLoopBackOff 5 3m59s ```
通過檢視日誌可以看到 CoreDNS 服務檢測到了迴圈 DNS 查詢
```plain
kubectl logs coredns-86c58d9df4-jjhwl
[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
檔案位置, 如
bash
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
不是軟連結後,就不會再覆蓋這個檔案。
bash
rm /etc/resolv.conf && echo "nameserver 114.114.114.114 > /etc/resolv.conf"
kubectl delete pods -n kube-system --selector k8s-app=kube-dns
也可以將 /etc/resolv.conf
指向主機商提供的 DNS 解析檔案。
bash
rm /etc/resolv.conf && cp /run/systemd/resolve/resolv.conf /etc/resolv.conf
kubectl delete pods -n kube-system --selector k8s-app=kube-dns
minikube 不使用虛擬機器的注意點
由於 minikube 主要設計是基於虛擬機器安裝的,vm-driver=none
也會帶來一些影響, 主要包括
- minikube 在安裝時將覆蓋主機原有的
/usr/local/bin/kubeadm
,/usr/local/bin/kubectl
,/etc/kubernetes
等目錄 - 無法在一臺主機上使用
vm-driver=none
安裝 2 個 minikube minikube dashboard
,minikube mount
,minikube ssh
等基於虛擬機器的指令均無法使用minikube delete
將刪除/etc/kubernetes
目錄
為了避免問題,建議使用全新的主機安裝,使用完後直接回收主機即可。
基於 microk8s 在 VPS 快速部署單節點 Kubernetes
minikube 雖然是官方出品,但主要還是基於虛擬機器做的設計。在 Linux 生產環境下,microk8s 可能是一個更合適的選擇。
microk8s 基於 snap 進行安裝,ubuntu 16.04 及之後的版本都已經預裝了 snap,如果是其他發行版的 Linux 需要先安裝 snap。 安裝前 microk8s 可以通過
plain
snap info microk8s
瞭解可安裝版本和操作指令等資訊。
microk8s 的獨特之處在於直接包含了 Kubernetes 單節點必須的如 kubectl
, kubelet
等所有工具,甚至直接包含了 docker。因此在一臺裸機上執行
plain
snap install microk8s --classic
之後,就可以在程式裡看到 /snap/microk8s
為字首的一系列熟悉的程式, 並且這些程式直接執行在主機,並未使用容器,k8s 也沒有使用預設的埠 6443
,而改用8080
。這樣做帶來的一個好處是即便系統之前已經安裝了kubectl
, docker
等,也可以進行安裝,不會衝突;不過就不能用 kubectl
、 docker
直接進行操作, 而需要使用 microk8s.docker
, microk8s.kubectl
等, 與原來的指令是完全一樣的。
安裝完成後可以通過 microk8s.status
檢視執行狀態及外掛的開啟情況。也可以用 microk8s.inspect
檢視已經安裝的服務。
通常來說安裝了 microk8s 後,我們也不會再次安裝 kubectl
, 為了操作方面,可以為 microk8s.kubectl
開啟設定kubectl
為別名, 並開啟輸入補全。
plain
snap alias microk8s.kubectl kubectl
source <(microk8s.kubectl completion bash)
也可以隨時取消別名。
plain
snap unalias kubectl
和 minikube 相同,microk8s 預設只安裝最核心的功能,可以通過 microk8s.enable dns dashboard
等開啟附加的外掛。
使用 kubeadm 部署單節點 Kubernetes
通過 minikube 或 microk8s 安裝 K8s 雖然方便,但是由於很多安裝細節被遮蔽,直接用在生產環境也難免讓人心存疑慮,那麼也可以使用 kubeadm 部署單節點 kubernetes。
同樣以 Ubuntu18.04 為例, 首先安裝 Docker v18.06.2 後 (K8s 同樣對 Docker 版本有要求),參考官方文件, 可以使用 apt-get
直接安裝 kubelet
,kubeadm
, kubectl
, 並且限制這些服務不能自動升級。
bash
apt-get update && apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl
接下來關閉 swap,這應該是為了避免 swap 對 CPU 和記憶體的 limit 造成意外影響。
bash
swapoff -a
然後執行
bash
kubeadm init --pod-network-cidr=10.244.0.0/16
就會開始 Kubernetes master 節點的安裝。安裝完成後 CoreDNS 是處於 Pending
狀態的,這是由於網路外掛尚未安裝,Kubernetes 使用 CNI 作為容器網路的介面,因此可以根據主機實際情況選擇不同的 CNI 實現,這裡以比較流行的 flannel 為例。
bash
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml
之後可以看到 CoreDNS 的狀態從 Pending
變為 Running
。至此 K8s 的 master 節點所需服務就已經安裝完畢。可以參考安裝後的提示,配置 kubectl
bash
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
現在嘗試部署一個 pod
bash
kubectl run --rm --restart=Never -it --image=hello-world test-pod
發現 pod 狀態卡在 Pending
,檢視 pod 資訊看到如下報錯
bash
$ kubectl describe pod test-pod
0/1 nodes are available: 1 node(s) had taints that the pod didn't tolerate.
這是由於 K8s 預設禁止在 master 節點部署 pod,可以使用以下指令取消這一限制。
bash
kubectl taint nodes --all node-role.kubernetes.io/master-
之後可以看到 pod 狀態已經變為 Completed
Kubernetes 單節點部署方式對比
至此我們分別用 minikube、microk8s、kubeadm 3 種方式完成了單節點 k8s 的部署。從安裝的服務來看,k8s 單節點必要的服務包括:
- 容器執行時: 預設是 Docker
- etcd: key-value 儲存服務,用於儲存叢集的狀態
- kube-apiserver: 叢集資源操作的唯一入口,並提供認證、授權、訪問控制、API 註冊和發現等機制
- kube-controller-manager: 維護叢集的狀態,比如故障檢測、自動擴充套件、滾動更新等
- kube-scheduler: 負責資源的排程,按照預定的排程策略將 Pod 排程到相應的機器上
- kubelet: 負責維持容器的生命週期,同時也負責 Volume(CVI)和網路(CNI)的管理
- kube-proxy: 負責為 Service 提供 cluster 內部的服務發現和負載均衡
三者差異之處在於:
- microk8s 部署 k8s 是直接安裝到主機而不是以容器方式安裝
- microk8s 雖然預設沒有安裝 DNS 服務,但通常情況下為了使用服務發現,還是需要安裝的,microk8s 預設的 DNS 服務是 kube-dns,而不是目前官方推薦的 CoreDNS 。
- 網路外掛 kubeadm 需要自己選擇, microk8s 和 minikube 都會自己安裝
- minikube 預設額外安裝了
storage-provisioner
用於虛擬機器掛載磁碟
從易用角度來看,microk8s 是安裝最簡單,門檻最低的;minikube 適合對 minikube 比較熟悉的使用者。
無論以何種方式安裝 k8s, 都需要注意安全問題, 因為在 k8s 的設計中, Master 節點是不會暴露到外網的,使用者服務都會安裝到 Worker 節點,但是在單節點的情況下,k8s 所監聽的埠都沒有設防,容器的許可權也有可能過大,這些安全問題在 minikube 的文件中也有提到, 需要對網路埠設定 iptables 限制可訪問的 IP 等方式來提升安全性,如果是安全性敏感的專案,建議放棄單節點 k8s 的方案。
References:
相關文章
- 窮人版生產力工具,好用得飛起 「GitHub 熱點速覽」Github
- kubernetes環境部署單節點redisRedis
- MongoDB單節點部署與基本操作MongoDB
- 極簡的配置單節點Kubernetes(k8s)叢集K8S
- 第七節 無窮小的比較
- PinPoint單節點部署及客戶端配置方法客戶端
- kubernetes——二進位制多節點部署
- Kubernetes-高可用k8s叢集部署(多Master節點二進位制方式)K8SAST
- k8s系列--node(k8s節點介紹,新增節點,移除節點)K8S
- Redis3.2.5部署(單節點)RedisS3
- Kubernetes – 節點
- K8s kubernetes安裝部署K8S
- 【K8S】基於單Master節點安裝K8S叢集K8SAST
- ElasticSearch 7.6.2 單機部署三個節點 報錯Elasticsearch
- Linux下NiFi 1.9.2部署(單節點)LinuxNifi
- ListView 與 RecyclerView 簡單對比View
- 使用Kubeadm建立k8s叢集之節點部署(三十一)K8S
- 貴點也值奈何搶不到 小米5與小米4S對比評測
- 基於minikube快速搭建kubernetes單節點環境
- Kubernetes(k8s)部署安全最佳實踐K8S
- k8s~pod單副本的平滑部署K8S
- 如果使用得當,MySQL 也可以化身 NoSQLMySql
- rancher新增k8s節點時顯示節點已新增K8S
- 二進位制部署1.23.4版本k8s叢集-5-部署Master節點服務K8SAST
- 二進位制部署1.23.4版本k8s叢集-6-部署Node節點服務K8S
- [譯]單應用跨多k8s叢集的部署與管理K8S
- RAC 雙節點 轉單節點流程
- k8s 節點打標籤K8S
- K8s(Kubernetes)簡介及安裝部署K8S
- Kubernetes(k8s)部署redis-cluster叢集K8SRedis
- 簡單對比MySQL和Oracle中的一個sql解析細節MySqlOracle
- 使用kubeadm搭建一單節點k8s測試叢集K8S
- DMO節點內部插入的常用方法與區別
- k8s多節點儀表盤(web介面)部署與谷歌瀏覽器訪問k8s儀表盤問題解決!K8SWeb谷歌瀏覽器
- 哈哈,如果使用得當,MySQL也可以化身NoSQLMySql
- 單機版搭建kubernetes(K8s)K8S
- dom4j 根據xml節點路徑查詢節點,找到對應的目標節點下的子節點,對節點Text值進行修改XML
- k8s單master叢集部署K8SAST