簡單瞭解一下K8S,並搭建自己的叢集
距離上次更新已經有一個月了,主要是最近工作上的變動有點頻繁,現在才暫時穩定下來。這篇部落格的本意是帶大家從零開始搭建K8S叢集的。但是我後面一想,如果是我看了這篇文章,會收穫什麼?就是跟著步驟一步一走嗎?是我的話我會選擇拒絕,所以我加了關於K8S的簡單介紹,每一步的步驟都添加了解釋。由於篇幅和時間原因,我只介紹了K8S中較為核心的Pod和Service。
文章前半段會簡單的介紹一下K8S,後半段會介紹如何從零開始慢慢的搭建叢集。如果想直接開始著手搭建叢集,則可以直接從第三章開始看。
1. K8S是什麼
K8S全稱kubernetes,是由Google在2014年開源的生產級別的容器編排系統,或者說是微服務和雲原生平臺。雖說14年才開源,但實際上K8S是Google內部的容器編排系統Borg的開源版本,在Google內部已經用了十多年了。下面是一個關於K8S的Logo來源的小插曲。
Kubernetes由谷歌在2014年首次對外宣佈 。它的開發和設計都深受谷歌的Borg系統的影響,它的許多頂級貢獻者之前也是Borg系統的開發者。在谷歌內部,Kubernetes的原始代號曾經是Seven,即星際迷航中友好的Borg(博格人)角色。Kubernetes標識中舵輪有七個輪輻就是對該專案代號的致意。
不過也有一個說法是,Docker的Logo是一個馱著集裝箱的鯨魚,也就是運輸船,K8S的Logo是一個船舵,旨在引領著Docker(或者說容器技術)走向遠方。
2. 簡單瞭解K8S
看了很多官方文章,是真官方。官方什麼意思呢,就是有可能看完了約等於沒有看,一樣的啥都不知道。
所以我想寫這樣一篇文章,給那些看完文件仍然不太理解或者說完全沒了解過K8S的老鐵一點小幫助。那麼讓我們回到最初對K8S的定義,它是一個微服務框架。
說到微服務框架,我們就不得不提一下目前業界十分主流的微服務框架,與這些你十分熟悉的框架進行對比,你就會很清晰的知道K8S能做什麼了。目前很主流的微服務框架和平臺有Spring Cloud、Dubbo和K8S。
Spring Cloud來自Netflix,Dubbo來自阿里,而K8S則來自Google。說的直觀一點,這三個框架都是針對微服務的解決方案。可能有人會說,K8S不是一個容器編排系統嗎?怎麼跟Spring Cloud這種軟體層面上的微服務框架做起了對比呢?
老鐵別慌,等我們慢慢深入這個概念。
我們都知道,如果我們需要使用微服務,那麼肯定少不了一些底層的基礎設施的支撐,例如服務註冊與發現、負載均衡、日誌監控、配置管理、叢集自愈和容錯、彈性伸縮…等等。我沒有列舉完,如其實這些元件都可以統稱為微服務的公共關注點。那我們是不是可以說,只要能夠提供的這些功能,它就算一個微服務框架呢?
以上的大多數功能,K8S都是內建的。故我們可以說K8S是一個與Docker Swarm相類似的容器編排系統,但是由於K8S內建了微服務的解決方案,它同時也是一個功能完備的微服務框架。
2.1 Pod的概念
在Docker Swarm中,排程的最小單位是容器,而在K8S中,排程的最小是Pod,那啥是Pod呢?
Pod是K8S設計的一個全新的概念,在英文中的原意是表達一群鯨魚或者是一個豌豆莢的意思。換句話說,一個Pod中可以執行一個或者多個容器。
在一個叢集中,K8S會為每個Pod都分配一個叢集內唯一的IP地址。因為K8S要求底層網路支援叢集內的任意節點之間的兩個Pod能夠直接通訊。這些容器共享當前Pod的檔案系統和網路。而這些容器之所以能夠共享,是因為Pod中有一個叫Pause的根容器,其餘的使用者業務容器都是共享這個根容器的IP和Volume。所以這些容器之間都可以通過localhost進行通訊。
有人可能會問,為什麼要引入根容器這個概念?那是因為如果沒有根容器的話,當一個Pod中引入了多個容器的時候,我們應該用哪一個容器的狀態來判斷Pod的狀態呢?所以才要引入與業務無關且不容易掛掉的Pause容器作為根容器,用根容器的狀態來代表整個容器的狀態。
熟悉Spring Cloud或者微服務的都知道,微服務中最忌諱的就是出現單點的情況。
所以針對同一個服務我們一般會部署2個或者更多個例項。在K8S中,則是會部署多個Pod副本,組成一個Pod叢集來對外提供服務。
而我們前面提過,K8S會為每一個Pod提供一個唯一的IP地址,客戶端就需要通過每個Pod的唯一IP+容器埠來訪問到具體的Pod,這樣一來,如果客戶端把呼叫地址寫死,伺服器就沒有辦法做負載均衡,而且,Pod重啟之後IP地址是會變的,難道每次重啟都要通知客戶端IP變更嗎?
為了解決這個問題,就要引出Service的概念了。
2.2 Service
Service是K8S中最核心的資源物件之一,就是用於解決上面提到的問題。我個人認為與Swarm中的Service概念沒有太大的區別。
一旦Service被建立,K8S會為其分配一個叢集內唯一的IP,叫做ClusterIP,而且在Service的整個生命週期中,ClusterIP不會發生變更,這樣一來,就可以用與Docker Swarm類似的操作,建立一個ClusterIP到服務名的DNS域名對映即可。
值得注意的是,ClusterIP是一個虛擬的IP地址,無法被Ping,僅僅只限於在K8S的叢集內使用。
而Service對客戶端,遮蔽了底層Pod的定址的過程。並且由kube-proxy程序將對Service的請求轉發到具體的Pod上,具體到哪一個,由具體的排程演算法決定。這樣以來,就實現了負載均衡。
而Service是怎麼找到Pod的呢?這就需要繼續引入另外一個核心概念Label了。
2.3 Label
Lable本質上是一個鍵值對,具體的值由使用者決定。Lable就是標籤,可以打在Pod上,也可以打到Service上。總結來說,Label與被標記的資源是一個一對多的關係。
例如,我們給上面所描述的Pod打上了role=serviceA
的標籤,那麼只需要在Service中的Label Selector中加入剛剛那個標籤,這樣一來,Service就可以通過Label Selector找到打了同一Label的Pod副本集了。
接下來,再簡單的介紹一下其他的K8S核心概念。
2.4 Replica Set
上面提到過部署多個Pod,是怎麼一回事呢?K8S最開始有一個概念叫Replication Controller,不過現在已經慢慢的被Replica Set所替代,RS也叫下一代的RC。簡單來說Replica Set定義了一種期望的場景,即讓任何時候叢集內的Pod副本數量都符合預期的值。
一旦被建立,叢集就會定期的檢測當前存活的Pod數量,如果多了,叢集就會停掉一些Pod。相反,如果少了就會建立一些Pod。這樣一來可以避免什麼問題呢?假設某個服務有兩個例項在執行,其中一個意外掛掉了,如果我們設定了副本數量是2,那麼叢集就會自動建立一個Pod,以保證叢集內始終有兩個Pod在執行。
K8S的東西就簡單的介紹這麼多,接下來讓我們進入叢集的搭建環節。
3. 搭建K8S的準備工作
不知道從哪篇部落格開始,不是很願意寫這種純TODO類的博文,但是我自己躺坑之後發現,我自己這個還真是我目前見過最簡單的。
我看到的有些安裝分了很多種情況,但是當一個初學者來看的時候,可能反而會讓他看懵逼。所以接下來的安裝會有些硬核。不分情況,就只有一種情況,一把梭安裝就完事。
系統 版本 Ubuntu 18.04
K8S 版本 v1.16.3
Docker 版本 v19.03.5
Flannel 版本 v0.11.0
如果你問我,如果沒有機器看了你的文章也能的擁有自己的叢集嗎?那麼請看下圖…
3.1 準備工作
我們先假設以下的情況成立。
機器:有2-3臺物理機或虛擬機器
系統:Ubuntu 18.04 且已換好國內的源
如果以上基本不成立,本篇文章到此結束,謝謝觀看…
3.2 安裝Docker
我也不需要介紹各種情況了,直接登上機器,建立一個shell指令碼,例如叫install_docker.sh
,一把梭程式碼如下。
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates
curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get -y install docker-ce docker-ce-cli containerd.io
然後執行sh install_docker.sh
,等待命令跑完,驗證docker是否安裝好即可。直接敲docker
+ 回車。
3.3 安裝Kubernetes
同理,新建一個shell指令碼,例如install_k8s.sh
。一把梭程式碼如下。
sudo curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt-get update
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get install -y kubelet kubeadm kubectl --allow-unauthenticated
然後執行sh install_k8s.sh
,等待命令跑完,驗證k8s是否安裝好即可。直接敲kubectl
+ 回車。
3.4 關閉Swap
先給出一把梭,不要耽誤了正在安裝的老鐵。為什麼要關閉後面再說。
- 暫時關閉 直接使用命令
sudo swapoff -a
,但是重啟之後會生效。會導致k8s無法正常執行。 - 永久關閉 建議一勞永逸,
sudo vim /etc/fstab
將有swap.img那行註釋掉,儲存即可。
那麼,swap是啥呢?它是系統的交換分割槽,你可以理解為虛擬記憶體。當系統記憶體不足的時候,會將一部分硬碟空間虛擬成記憶體使用。那為什麼K8S需要將其關掉呢?可以從下圖看看訪問記憶體和訪問硬碟速度上的差異就知道了。
總的來說是為了效能考慮,所以就需要避免開啟swap交換,K8S希望所有的服務都不應該超過叢集或節點CPU和記憶體的限制。
4. 初始化Master節點
到這,準備工作就完成了,可以開始安裝K8S的master節點了,登上要作為master節點的機器。
4.1 設定HostName
老規矩,先上命令,再說為什麼要設定。
sudo hostnamectl set-hostname master-node
自定義修改了主機名,在之後檢視叢集內節點時,每個節點的名字就不會顯示K8S自動生成的名字,便於檢視和記憶。例如,在其他的Node節點你可以將master-node
改為slave-node-1
或worker-node-2
,效果如下。
4.2 初始化叢集
在機器上執行如下命令。
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
然後,抱起吉他,等待命令執行完。
這裡需要特別注意一下。這個命令執行完成之後,會列印一個有kubeadm join的命令,需要儲存下來。
大概長這樣。
kubeadm join 你的IP地址:6443 --token 你的TOKEN --discovery-token-ca-cert-hash sha256:你的CA證書雜湊
顧名思義,這個命令用於其他節點加入到叢集中,而且Token是有時效性的,過期時間一般是86400000毫秒。
如果失效,就需要重新生成。如果你真的又沒有儲存,又失效了…我還是給你準備了兩個補救措施。如果命令儲存下來了,那麼請直接跳過這兩個補救措施。
token. 通過命令
Kubeadm token list
找回ca-cert. 執行命令
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
找回
4.3 普通使用者可執行
把下面的指令一把梭即可。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
主要是,為了不那麼麻煩,在控制節點上執行kubectl
這類的命令時,不用每次都sudo。
4.4 安裝網路通訊外掛
執行如下命令,安裝網路外掛Flannel。
sudo kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
可以看到,如果不安裝Flannel,我們剛剛Init好的Master節點會處於NOT_READY的狀態。安裝好之後,可以通過命令kubectl get nodes
來檢視所有的節點的狀態。也可以通過kubectl get pods --all-namespaces
來檢視當前叢集中所有Pod的狀態。這裡需要注意的是,只有在master節點是READY,所有Pod的狀態是RUNNING之後,才可以進行下一步。
為什麼要裝網路外掛呢?
那是因為K8S要求叢集內的所有節點之間的Pod網路是互通的。換句話說,Flannel可以讓叢集內不同節點上的容器都有一個在當前叢集內唯一的虛擬IP地址。這樣以來,就可以實現,跨節點的Pod與Pod直接通訊。
這樣一來,將複雜的網路通訊,簡單的變成了兩個IP地址之間的通訊。這主要是通過虛擬二層網路實現的。看似是這個節點的Pod直接和另一個節點上的Pod進行了通訊,最終還是通過節點的物理網絡卡流出的。
5. Slave節點加入叢集
到此,一個單點的叢集就已經搭建好了。現在我們要做的是,登入準備好的另一臺(我只有兩臺,如果你有3臺或者4天,把這個章節反覆走幾次就好了)伺服器。
5.1 設定HostName
執行如下命令。
sudo hostnamectl set-hostname slave-node
因為當前節點不是master了,所以主機名設定成了slave-node。
5.2 加入叢集
重點來了,執行上一章節生成的kubeadm join命令即可。等待執行完畢之後,就可以在master節點上通過命令kubectl get nodes
看到slave-node已經加入了叢集。
對於Slave節點的操作就沒了。
6. 感謝閱讀
關於K8S就簡單的介紹到這裡,由於篇幅和時間的原因,很多概念都沒有介紹,例如Deployment、Volume、ConfigMap等等。僅僅只介紹了較為核心的Pod和Service,以及相關的東西。畢竟,如果想要把K8S的核心理念介紹完,一篇部落格的篇幅是肯定不夠的,後面我再單獨詳細的介紹吧。
第一次在部落格裡求贊啊,之前完全是隨緣。不過我後來發現,開啟部落格看到大家的點贊和留言,這對我來說是一種莫大的鼓勵。
拜了個拜如果你覺得這篇文章對你有幫助,還麻煩點個贊,關個注,分個享,留個言
也可以微信搜尋公眾號【SH的全棧筆記】,當然也可以直接掃描二維碼關注