距離上次更新已經(jīng)有一個(gè)月了柔滔,主要是最近工作上的變動(dòng)有點(diǎn)頻繁,現(xiàn)在才暫時(shí)穩(wěn)定下來萍虽。這篇博客的本意是帶大家從零開始搭建K8S集群的睛廊。但是我后面一想,如果是我看了這篇文章杉编,會(huì)收獲什么超全?就是跟著步驟一步一走嗎?是我的話我會(huì)選擇拒絕邓馒,所以我加了關(guān)于K8S的簡(jiǎn)單介紹嘶朱,每一步的步驟都添加了解釋。由于篇幅和時(shí)間原因光酣,我只介紹了K8S中較為核心的Pod和Service疏遏。
文章前半段會(huì)簡(jiǎn)單的介紹一下K8S,后半段會(huì)介紹如何從零開始慢慢的搭建集群救军。如果想直接開始著手搭建集群改览,則可以直接從第三章開始看。
1. K8S是什么
K8S全稱kubernetes缤言,是由Google在2014年開源的生產(chǎn)級(jí)別的容器編排系統(tǒng)宝当,或者說是微服務(wù)和云原生平臺(tái)。雖說14年才開源胆萧,但實(shí)際上K8S是Google內(nèi)部的容器編排系統(tǒng)Borg的開源版本庆揩,在Google內(nèi)部已經(jīng)用了十多年了俐东。下面是一個(gè)關(guān)于K8S的Logo來源的小插曲。
Kubernetes由谷歌在2014年首次對(duì)外宣布 订晌。它的開發(fā)和設(shè)計(jì)都深受谷歌的Borg系統(tǒng)的影響虏辫,它的許多頂級(jí)貢獻(xiàn)者之前也是Borg系統(tǒng)的開發(fā)者。在谷歌內(nèi)部锈拨,Kubernetes的原始代號(hào)曾經(jīng)是Seven砌庄,即星際迷航中友好的Borg(博格人)角色。Kubernetes標(biāo)識(shí)中舵輪有七個(gè)輪輻就是對(duì)該項(xiàng)目代號(hào)的致意奕枢。
不過也有一個(gè)說法是娄昆,Docker的Logo是一個(gè)馱著集裝箱的鯨魚,也就是運(yùn)輸船缝彬,K8S的Logo是一個(gè)船舵萌焰,旨在引領(lǐng)著Docker(或者說容器技術(shù))走向遠(yuǎn)方。
2. 簡(jiǎn)單了解K8S
看了很多官方文章谷浅,是真官方扒俯。官方什么意思呢,就是有可能看完了約等于沒有看一疯,一樣的啥都不知道撼玄。
所以我想寫這樣一篇文章,給那些看完文檔仍然不太理解或者說完全沒了解過K8S的老鐵一點(diǎn)小幫助墩邀。那么讓我們回到最初對(duì)K8S的定義掌猛,它是一個(gè)微服務(wù)框架。
說到微服務(wù)框架磕蒲,我們就不得不提一下目前業(yè)界十分主流的微服務(wù)框架留潦,與這些你十分熟悉的框架進(jìn)行對(duì)比只盹,你就會(huì)很清晰的知道K8S能做什么了辣往。目前很主流的微服務(wù)框架和平臺(tái)有Spring Cloud、Dubbo和K8S殖卑。
Spring Cloud來自Netflix站削,Dubbo來自阿里,而K8S則來自Google孵稽。說的直觀一點(diǎn)许起,這三個(gè)框架都是針對(duì)微服務(wù)的解決方案∑邢剩可能有人會(huì)說园细,K8S不是一個(gè)容器編排系統(tǒng)嗎?怎么跟Spring Cloud這種軟件層面上的微服務(wù)框架做起了對(duì)比呢接校?
老鐵別慌猛频,等我們慢慢深入這個(gè)概念狮崩。
我們都知道,如果我們需要使用微服務(wù)鹿寻,那么肯定少不了一些底層的基礎(chǔ)設(shè)施的支撐睦柴,例如服務(wù)注冊(cè)與發(fā)現(xiàn)、負(fù)載均衡毡熏、日志監(jiān)控坦敌、配置管理、集群自愈和容錯(cuò)痢法、彈性伸縮...等等狱窘。我沒有列舉完,如其實(shí)這些組件都可以統(tǒng)稱為微服務(wù)的公共關(guān)注點(diǎn)疯暑。那我們是不是可以說训柴,只要能夠提供的這些功能,它就算一個(gè)微服務(wù)框架呢妇拯?
以上的大多數(shù)功能幻馁,K8S都是內(nèi)置的。故我們可以說K8S是一個(gè)與Docker Swarm相類似的容器編排系統(tǒng)越锈,但是由于K8S內(nèi)置了微服務(wù)的解決方案仗嗦,它同時(shí)也是一個(gè)功能完備的微服務(wù)框架。
2.1 Pod的概念
在Docker Swarm中甘凭,調(diào)度的最小單位是容器稀拐,而在K8S中,調(diào)度的最小是Pod丹弱,那啥是Pod呢德撬?
Pod是K8S設(shè)計(jì)的一個(gè)全新的概念,在英文中的原意是表達(dá)一群鯨魚或者是一個(gè)豌豆莢的意思躲胳。換句話說蜓洪,一個(gè)Pod中可以運(yùn)行一個(gè)或者多個(gè)容器。
在一個(gè)集群中坯苹,K8S會(huì)為每個(gè)Pod都分配一個(gè)集群內(nèi)唯一的IP地址隆檀。因?yàn)镵8S要求底層網(wǎng)絡(luò)支持集群內(nèi)的任意節(jié)點(diǎn)之間的兩個(gè)Pod能夠直接通信。這些容器共享當(dāng)前Pod的文件系統(tǒng)和網(wǎng)絡(luò)粹湃。而這些容器之所以能夠共享恐仑,是因?yàn)镻od中有一個(gè)叫Pause的根容器,其余的用戶業(yè)務(wù)容器都是共享這個(gè)根容器的IP和Volume为鳄。所以這些容器之間都可以通過localhost進(jìn)行通信裳仆。
有人可能會(huì)問,為什么要引入根容器這個(gè)概念孤钦?那是因?yàn)槿绻麤]有根容器的話歧斟,當(dāng)一個(gè)Pod中引入了多個(gè)容器的時(shí)候记某,我們應(yīng)該用哪一個(gè)容器的狀態(tài)來判斷Pod的狀態(tài)呢?所以才要引入與業(yè)務(wù)無關(guān)且不容易掛掉的Pause容器作為根容器构捡,用根容器的狀態(tài)來代表整個(gè)容器的狀態(tài)液南。
熟悉Spring Cloud或者微服務(wù)的都知道,微服務(wù)中最忌諱的就是出現(xiàn)單點(diǎn)的情況勾徽。
所以針對(duì)同一個(gè)服務(wù)我們一般會(huì)部署2個(gè)或者更多個(gè)實(shí)例滑凉。在K8S中,則是會(huì)部署多個(gè)Pod副本喘帚,組成一個(gè)Pod集群來對(duì)外提供服務(wù)畅姊。
而我們前面提過,K8S會(huì)為每一個(gè)Pod提供一個(gè)唯一的IP地址吹由,客戶端就需要通過每個(gè)Pod的唯一IP+容器端口來訪問到具體的Pod若未,這樣一來,如果客戶端把調(diào)用地址寫死倾鲫,服務(wù)器就沒有辦法做負(fù)載均衡粗合,而且,Pod重啟之后IP地址是會(huì)變的乌昔,難道每次重啟都要通知客戶端IP變更嗎隙疚?
為了解決這個(gè)問題,就要引出Service的概念了磕道。
2.2 Service
Service是K8S中最核心的資源對(duì)象之一供屉,就是用于解決上面提到的問題。我個(gè)人認(rèn)為與Swarm中的Service概念沒有太大的區(qū)別溺蕉。
一旦Service被創(chuàng)建伶丐,K8S會(huì)為其分配一個(gè)集群內(nèi)唯一的IP,叫做ClusterIP疯特,而且在Service的整個(gè)生命周期中哗魂,ClusterIP不會(huì)發(fā)生變更,這樣一來辙芍,就可以用與Docker Swarm類似的操作啡彬,建立一個(gè)ClusterIP到服務(wù)名的DNS域名映射即可羹与。
值得注意的是故硅,ClusterIP是一個(gè)虛擬的IP地址,無法被Ping纵搁,僅僅只限于在K8S的集群內(nèi)使用吃衅。
而Service對(duì)客戶端,屏蔽了底層Pod的尋址的過程腾誉。并且由kube-proxy進(jìn)程將對(duì)Service的請(qǐng)求轉(zhuǎn)發(fā)到具體的Pod上徘层,具體到哪一個(gè)峻呕,由具體的調(diào)度算法決定。這樣以來趣效,就實(shí)現(xiàn)了負(fù)載均衡瘦癌。
而Service是怎么找到Pod的呢?這就需要繼續(xù)引入另外一個(gè)核心概念Label了跷敬。
2.3 Label
Lable本質(zhì)上是一個(gè)鍵值對(duì)讯私,具體的值由用戶決定。Lable就是標(biāo)簽西傀,可以打在Pod上斤寇,也可以打到Service上∮倒樱總結(jié)來說娘锁,Label與被標(biāo)記的資源是一個(gè)一對(duì)多的關(guān)系。
例如饺鹃,我們給上面所描述的Pod打上了role=serviceA
的標(biāo)簽莫秆,那么只需要在Service中的Label Selector中加入剛剛那個(gè)標(biāo)簽,這樣一來悔详,Service就可以通過Label Selector找到打了同一Label的Pod副本集了馏锡。
接下來,再簡(jiǎn)單的介紹一下其他的K8S核心概念伟端。
2.4 Replica Set
上面提到過部署多個(gè)Pod杯道,是怎么一回事呢?K8S最開始有一個(gè)概念叫Replication Controller责蝠,不過現(xiàn)在已經(jīng)慢慢的被Replica Set所替代党巾,RS也叫下一代的RC。簡(jiǎn)單來說Replica Set定義了一種期望的場(chǎng)景霜医,即讓任何時(shí)候集群內(nèi)的Pod副本數(shù)量都符合預(yù)期的值齿拂。
一旦被創(chuàng)建,集群就會(huì)定期的檢測(cè)當(dāng)前存活的Pod數(shù)量肴敛,如果多了署海,集群就會(huì)停掉一些Pod。相反医男,如果少了就會(huì)創(chuàng)建一些Pod砸狞。這樣一來可以避免什么問題呢?假設(shè)某個(gè)服務(wù)有兩個(gè)實(shí)例在運(yùn)行镀梭,其中一個(gè)意外掛掉了刀森,如果我們?cè)O(shè)置了副本數(shù)量是2,那么集群就會(huì)自動(dòng)創(chuàng)建一個(gè)Pod报账,以保證集群內(nèi)始終有兩個(gè)Pod在運(yùn)行研底。
K8S的東西就簡(jiǎn)單的介紹這么多埠偿,接下來讓我們進(jìn)入集群的搭建環(huán)節(jié)。
3. 搭建K8S的準(zhǔn)備工作
不知道從哪篇博客開始榜晦,不是很愿意寫這種純TODO類的博文冠蒋,但是我自己躺坑之后發(fā)現(xiàn),我自己這個(gè)還真是我目前見過最簡(jiǎn)單的乾胶。
我看到的有些安裝分了很多種情況浊服,但是當(dāng)一個(gè)初學(xué)者來看的時(shí)候,可能反而會(huì)讓他看懵逼胚吁。所以接下來的安裝會(huì)有些硬核牙躺。不分情況,就只有一種情況腕扶,一把梭安裝就完事孽拷。
系統(tǒng) 版本 Ubuntu 18.04
K8S 版本 v1.16.3
Docker 版本 v19.03.5
Flannel 版本 v0.11.0
如果你問我,如果沒有機(jī)器看了你的文章也能的擁有自己的集群?jiǎn)?/em>半抱?那么請(qǐng)看下圖...
3.1 準(zhǔn)備工作
我們先假設(shè)以下的情況成立脓恕。
機(jī)器:有2-3臺(tái)物理機(jī)或虛擬機(jī)
系統(tǒng):Ubuntu 18.04 且已換好國(guó)內(nèi)的源
如果以上基本不成立,本篇文章到此結(jié)束窿侈,謝謝觀看...
3.2 安裝Docker
我也不需要介紹各種情況了炼幔,直接登上機(jī)器,創(chuàng)建一個(gè)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
然后執(zhí)行sh install_docker.sh
圆兵,等待命令跑完跺讯,驗(yàn)證docker是否安裝好即可。直接敲docker
+ 回車殉农。
3.3 安裝Kubernetes
同理刀脏,新建一個(gè)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
然后執(zhí)行sh install_k8s.sh
,等待命令跑完轮傍,驗(yàn)證k8s是否安裝好即可暂雹。直接敲kubectl
+ 回車。
3.4 關(guān)閉Swap
先給出一把梭金麸,不要耽誤了正在安裝的老鐵粥航。為什么要關(guān)閉后面再說纺裁。
- 暫時(shí)關(guān)閉 直接使用命令
sudo swapoff -a
诅病,但是重啟之后會(huì)生效讽膏。會(huì)導(dǎo)致k8s無法正常運(yùn)行。 - 永久關(guān)閉 建議一勞永逸棚瘟,
sudo vim /etc/fstab
將有swap.img那行注釋掉现斋,保存即可。
那么偎蘸,swap是啥呢庄蹋?它是系統(tǒng)的交換分區(qū),你可以理解為虛擬內(nèi)存迷雪。當(dāng)系統(tǒng)內(nèi)存不足的時(shí)候限书,會(huì)將一部分硬盤空間虛擬成內(nèi)存使用。那為什么K8S需要將其關(guān)掉呢章咧?可以從下圖看看訪問內(nèi)存和訪問硬盤速度上的差異就知道了倦西。
總的來說是為了性能考慮,所以就需要避免開啟swap交換赁严,K8S希望所有的服務(wù)都不應(yīng)該超過集群或節(jié)點(diǎn)CPU和內(nèi)存的限制扰柠。
4. 初始化Master節(jié)點(diǎn)
到這,準(zhǔn)備工作就完成了疼约,可以開始安裝K8S的master節(jié)點(diǎn)了卤档,登上要作為master節(jié)點(diǎn)的機(jī)器。
4.1 設(shè)置HostName
老規(guī)矩程剥,先上命令劝枣,再說為什么要設(shè)置。
sudo hostnamectl set-hostname master-node
自定義修改了主機(jī)名织鲸,在之后查看集群內(nèi)節(jié)點(diǎn)時(shí)哨免,每個(gè)節(jié)點(diǎn)的名字就不會(huì)顯示K8S自動(dòng)生成的名字,便于查看和記憶昙沦。例如琢唾,在其他的Node節(jié)點(diǎn)你可以將master-node
改為slave-node-1
或worker-node-2
,效果如下盾饮。
4.2 初始化集群
在機(jī)器上執(zhí)行如下命令采桃。
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
然后,抱起吉他丘损,等待命令執(zhí)行完普办。
這里需要特別注意一下。這個(gè)命令執(zhí)行完成之后徘钥,會(huì)打印一個(gè)有kubeadm join的命令衔蹲,需要保存下來。
大概長(zhǎng)這樣。
kubeadm join 你的IP地址:6443 --token 你的TOKEN --discovery-token-ca-cert-hash sha256:你的CA證書哈希
顧名思義舆驶,這個(gè)命令用于其他節(jié)點(diǎn)加入到集群中橱健,而且Token是有時(shí)效性的,過期時(shí)間一般是86400000毫秒沙廉。
如果失效拘荡,就需要重新生成。如果你真的又沒有保存撬陵,又失效了...我還是給你準(zhǔn)備了兩個(gè)補(bǔ)救措施珊皿。如果命令保存下來了,那么請(qǐng)直接跳過這兩個(gè)補(bǔ)救措施巨税。
token. 通過命令
Kubeadm token list
找回ca-cert. 執(zhí)行命令
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 普通用戶可執(zhí)行
把下面的指令一把梭即可蟋定。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
主要是,為了不那么麻煩草添,在控制節(jié)點(diǎn)上執(zhí)行kubectl
這類的命令時(shí)溢吻,不用每次都sudo。
4.4 安裝網(wǎng)絡(luò)通信插件
執(zhí)行如下命令果元,安裝網(wǎng)絡(luò)插件Flannel促王。
sudo kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
可以看到,如果不安裝Flannel而晒,我們剛剛Init好的Master節(jié)點(diǎn)會(huì)處于NOT_READY的狀態(tài)蝇狼。安裝好之后,可以通過命令kubectl get nodes
來查看所有的節(jié)點(diǎn)的狀態(tài)倡怎。也可以通過kubectl get pods --all-namespaces
來查看當(dāng)前集群中所有Pod的狀態(tài)迅耘。這里需要注意的是,只有在master節(jié)點(diǎn)是READY监署,所有Pod的狀態(tài)是RUNNING之后颤专,才可以進(jìn)行下一步。
為什么要裝網(wǎng)絡(luò)插件呢钠乏?
那是因?yàn)镵8S要求集群內(nèi)的所有節(jié)點(diǎn)之間的Pod網(wǎng)絡(luò)是互通的栖秕。換句話說,F(xiàn)lannel可以讓集群內(nèi)不同節(jié)點(diǎn)上的容器都有一個(gè)在當(dāng)前集群內(nèi)唯一的虛擬IP地址晓避。這樣以來簇捍,就可以實(shí)現(xiàn),跨節(jié)點(diǎn)的Pod與Pod直接通信俏拱。
這樣一來暑塑,將復(fù)雜的網(wǎng)絡(luò)通信,簡(jiǎn)單的變成了兩個(gè)IP地址之間的通信锅必。這主要是通過虛擬二層網(wǎng)絡(luò)實(shí)現(xiàn)的事格。看似是這個(gè)節(jié)點(diǎn)的Pod直接和另一個(gè)節(jié)點(diǎn)上的Pod進(jìn)行了通信,最終還是通過節(jié)點(diǎn)的物理網(wǎng)卡流出的驹愚。
5. Slave節(jié)點(diǎn)加入集群
到此远搪,一個(gè)單點(diǎn)的集群就已經(jīng)搭建好了。現(xiàn)在我們要做的是么鹤,登錄準(zhǔn)備好的另一臺(tái)(我只有兩臺(tái)终娃,如果你有3臺(tái)或者4天味廊,把這個(gè)章節(jié)反復(fù)走幾次就好了)服務(wù)器蒸甜。
5.1 設(shè)置HostName
執(zhí)行如下命令。
sudo hostnamectl set-hostname slave-node
因?yàn)楫?dāng)前節(jié)點(diǎn)不是master了余佛,所以主機(jī)名設(shè)置成了slave-node柠新。
5.2 加入集群
重點(diǎn)來了,執(zhí)行上一章節(jié)生成的kubeadm join命令即可辉巡。等待執(zhí)行完畢之后恨憎,就可以在master節(jié)點(diǎn)上通過命令kubectl get nodes
看到slave-node已經(jīng)加入了集群。
對(duì)于Slave節(jié)點(diǎn)的操作就沒了郊楣。
6. 感謝閱讀
關(guān)于K8S就簡(jiǎn)單的介紹到這里憔恳,由于篇幅和時(shí)間的原因,很多概念都沒有介紹净蚤,例如Deployment钥组、Volume、ConfigMap等等今瀑。僅僅只介紹了較為核心的Pod和Service程梦,以及相關(guān)的東西。畢竟橘荠,如果想要把K8S的核心理念介紹完屿附,一篇博客的篇幅是肯定不夠的,后面我再單獨(dú)詳細(xì)的介紹吧哥童。
第一次在博客里求贊啊挺份,之前完全是隨緣。不過我后來發(fā)現(xiàn)贮懈,打開博客看到大家的點(diǎn)贊和留言压恒,這對(duì)我來說是一種莫大的鼓勵(lì)。
如果你覺得這篇文章對(duì)你有幫助错邦,還麻煩點(diǎn)個(gè)贊探赫,關(guān)個(gè)注,分個(gè)享撬呢,留個(gè)言
也可以微信搜索公眾號(hào)【SH的全棧筆記】伦吠,當(dāng)然也可以直接掃描二維碼關(guān)注
image
拜了個(gè)拜