Kubernetes是Google開源的一個(gè)容器編排引擎,它支持自動(dòng)化部署、大規(guī)??缮炜s、應(yīng)用容器化管理。在生產(chǎn)環(huán)境中部署一個(gè)應(yīng)用程序時(shí),通常要部署該應(yīng)用的多個(gè)實(shí)例以便對(duì)應(yīng)用請(qǐng)求進(jìn)行負(fù)載均衡。
創(chuàng)新互聯(lián)建站長期為成百上千客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺(tái),與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為柏鄉(xiāng)企業(yè)提供專業(yè)的做網(wǎng)站、成都做網(wǎng)站,柏鄉(xiāng)網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。在Kubernetes中,我們可以創(chuàng)建多個(gè)容器,每個(gè)容器里面運(yùn)行一個(gè)應(yīng)用實(shí)例,然后通過內(nèi)置的負(fù)載均衡策略,實(shí)現(xiàn)對(duì)這一組應(yīng)用實(shí)例的管理、發(fā)現(xiàn)、訪問,而這些細(xì)節(jié)都不需要運(yùn)維人員去進(jìn)行復(fù)雜的手工配置和處理。
可移植: 支持公有云,私有云,混合云,多重云(multi-cloud)
可擴(kuò)展: 模塊化,插件化,可掛載,可組合
自動(dòng)化: 自動(dòng)部署,自動(dòng)重啟,自動(dòng)復(fù)制,自動(dòng)伸縮/擴(kuò)展
在K8s中創(chuàng)建資源的方式有兩種:命令行和YAML文件,本次博文主要介紹使用YAML文件的方式,如需使用命令行創(chuàng)建資源請(qǐng)參考K8s資源對(duì)象的基本管理
Kubernetes中的YAML文件與配置清單是一樣的,根據(jù)個(gè)人習(xí)慣。本次博文統(tǒng)稱為YAML文件!
YAML是專門用來配置文件的語言,非常簡(jiǎn)潔和強(qiáng)大。與了解的properties、XML、json等數(shù)據(jù)格式,習(xí)慣之后就會(huì)發(fā)現(xiàn)越來越好用。其實(shí)YAML就是結(jié)合了大部分的標(biāo)記語言的特性,整合新開發(fā)的。
YAML文件的特點(diǎn):
- 層次分明、結(jié)構(gòu)清晰;
- 使用簡(jiǎn)單、上手容易;
- 功能強(qiáng)大、語義豐富;
需要特別注意的是:- 大小寫敏感;
- 嚴(yán)格要求縮進(jìn);
Kubernetes中的YAML文件主要由五個(gè)一級(jí)字段組成,分別是:
- apiVersion:api版本信息;
- kind:指定創(chuàng)建資源對(duì)象的類型;
- metadata:元數(shù)據(jù)內(nèi)部的嵌套字段,定義了資源對(duì)象的名稱、名稱空間等;
- spec:規(guī)范定義資源應(yīng)該擁有什么樣的特性,依靠控制器確保性能可以滿足,滿足用戶期望的狀態(tài)。
- status:顯示資源的當(dāng)前狀態(tài),K8s就是確保當(dāng)前狀態(tài)向目標(biāo)狀態(tài)無限靠近從而滿足用戶期望。代表資源當(dāng)前的狀態(tài);
雖然知道了YAML文件中的一級(jí)字段都是什么,但是還是不知道應(yīng)該怎么寫。可以借助以下命令來獲取一些幫助信息。
[root@master ~]# kubectl api-versions
//獲取當(dāng)前集群支持的 apiserver版本
[root@master ~]# kubectl api-resources
//獲取全部的api資源對(duì)象
[root@master ~]# kubectl explain deployment
//查看k8s某個(gè)對(duì)象的配置清單格式,應(yīng)該包含哪些字段及使用方法
[root@master ~]# kubectl explain deployment.spec
//這個(gè)命令是非常重要的,它可以一級(jí)一級(jí)來獲取幫助
[root@master ~]# cat web.yaml
kind: Deployment //指定要?jiǎng)?chuàng)建的資源對(duì)象
apiVersion: extensions/v1beta1 //指定deployment所對(duì)應(yīng)的API版本信息
metadata:
name: web //定義deployment的名稱
spec:
replicas: 2 //指定副本數(shù)量
template:
metadata:
labels: //指定pod的標(biāo)簽
app: web_server
spec:
containers:
- name: nginx //指定pod運(yùn)行的容器的名稱
image: nginx //指定運(yùn)行容器所需的鏡像
[root@master ~]# kubectl apply -f web.yaml
//使用“-f”來指定yaml文件,根據(jù)yaml文件中定義的內(nèi)容生成所需的資源
apply可以指定多次,如果發(fā)現(xiàn)文件不同,則更新
[root@master ~]# kubectl delete -f web.yaml
//刪除yaml文件中定義的資源
[root@master ~]# kubectl get deployments. web
//查看web控制器所產(chǎn)生的pod
NAME READY UP-TO-DATE AVAILABLE AGE
web 2/2 2 2 5m50s
[root@master ~]# kubectl describe deployments. web
//查看web控制器的詳細(xì)信息
返回的結(jié)果如下:
這樣一來,Kubernetes已經(jīng)根據(jù)YAML文件生成了我們所需的pod資源!
[root@master ~]# kubectl get pod -o wide //查看pod的詳細(xì)信息
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-d6ff6c799-7jtvd 1/1 Running 0 17m 10.244.2.2 node02
web-d6ff6c799-7tpdc 1/1 Running 0 17m 10.244.1.2 node01
K8s集群內(nèi)部測(cè)試訪問:
[root@master ~]# cat web-svc.yaml
kind: Service
apiVersion: v1
metadata:
name: web-svc
spec:
type: NodePort //指定類型為NodePort,可以讓外部訪問,否則默認(rèn)情況下是cluster IP,僅限集群內(nèi)部訪問
selector:
app: web_server //必須與deployment資源對(duì)象的標(biāo)簽進(jìn)行關(guān)聯(lián)
ports:
- protocol: TCP
port: 80 //指定要映射到的Cluster IP的端口
targetPort: 80 //指定的是要映射pod中的端口
nodePort: 31000 //指定映射到宿主機(jī)的端口,范圍是30000~32767
[root@master ~]# kubectl apply -f web-svc.yaml
//生成service的控制文件(yaml中已經(jīng)定義其名稱為web-svc)
[root@master ~]# kubectl get svc web-svc //查看service控制器
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web-svc NodePort 10.99.32.22 80:31000/TCP 12m
//TYPE:為NodePort,可以使外部訪問;
//PORT:映射出的端口與我們定義的一樣
測(cè)試訪問:
注意:是訪問群集中任意節(jié)點(diǎn)都可以訪問k8s集群中pod所提供的服務(wù)!
[root@master ~]# kubectl describe svc web-svc
//查看service的詳細(xì)信息
返回的信息如下:
既然說到,Endpoints指定的是后端pod的IP地址,那么下面進(jìn)行驗(yàn)證:
[root@master ~]# kubectl get pod -o wide | awk '{print $6}'
//提取后端pod的IP地址
IP
10.244.2.2
10.244.1.2
//與上述查詢的結(jié)果一樣!
我們知道service是有負(fù)載均衡的能力,那么是怎么實(shí)現(xiàn)的?
其實(shí),背后的原理并沒有那么高大上,kube-proxy通過iptables的轉(zhuǎn)發(fā)機(jī)制來實(shí)現(xiàn)負(fù)載均衡的效果的,先定義目標(biāo)IP是service提供的群集IP,然后使用“-j”選項(xiàng)轉(zhuǎn)發(fā)到其他iptables規(guī)則,接下來驗(yàn)證一下:
[root@master ~]# kubectl get svc web-svc | awk '{print $3}'
//首先查看service的群集IP地址
CLUSTER-IP
10.99.32.22
[root@master ~]# iptables-save | grep 10.99.32.22
//查看iptables規(guī)則中與群集IP地址相關(guān)的內(nèi)容
-A KUBE-SERVICES ! -s 10.244.0.0/16 -d 10.99.32.22/32 -p tcp -m comment --comment "default/web-svc: cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ
-A KUBE-SERVICES -d 10.99.32.22/32 -p tcp -m comment --comment "default/web-svc: cluster IP" -m tcp --dport 80 -j KUBE-SVC-3RBUQ3B6P3MTQ3S7
從上述結(jié)果中可以看出,當(dāng)目標(biāo)地址是群集IP時(shí),就會(huì)轉(zhuǎn)發(fā)到KUBE-SVC-3RBUQ3B6P3MTQ3S7規(guī)則中
[root@master ~]# iptables-save | grep KUBE-SVC-3RBUQ3B6P3MTQ3S7
:KUBE-SVC-3RBUQ3B6P3MTQ3S7 - [0:0]
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/web-svc:" -m tcp --dport 31000 -j KUBE-SVC-3RBUQ3B6P3MTQ3S7
-A KUBE-SERVICES -d 10.99.32.22/32 -p tcp -m comment --comment "default/web-svc: cluster IP" -m tcp --dport 80 -j KUBE-SVC-3RBUQ3B6P3MTQ3S7
-A KUBE-SVC-3RBUQ3B6P3MTQ3S7 -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-E3SP5QDRAUFB55IC
-A KUBE-SVC-3RBUQ3B6P3MTQ3S7 -j KUBE-SEP-3T3LUFAKMOTS5BKN
//從查詢結(jié)果中可以看出其負(fù)載均衡的效果,因?yàn)楹蠖酥粍?chuàng)建了兩個(gè)pod,所以其概率為0.5
由此可以看出service實(shí)現(xiàn)負(fù)載均衡的效果:默認(rèn)情況下使用iptables規(guī)則,當(dāng)然還可以使用其他的方法,這里就不介紹了!
查看負(fù)載均衡的詳細(xì)信息需根據(jù)cluster ip為切入口!
實(shí)現(xiàn)負(fù)載均衡最根本的原理就是:iptables規(guī)則根據(jù)random(隨機(jī)數(shù))實(shí)現(xiàn)的負(fù)載均衡!
通過K8s資源對(duì)象的基本管理之使用命令行的方式可以了解到kubernetes版本升級(jí)、回滾的操作與docker swarm幾乎是一樣的?;貪L操作只能回滾到上一個(gè)版本。
搭建私有倉庫,使用鏡像制作自定義鏡像(三個(gè)版本),根據(jù)主頁內(nèi)容進(jìn)行區(qū)分,將自定義鏡像上傳到私有倉庫中,由于過于簡(jiǎn)單,過程略……
kubernetes還可以回滾到指定的版本,方法如下:
[root@master yaml]# cat httpd01.deployment.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: httpd
spec:
revisionHistoryLimit: 10 //記錄歷史版本信息為10個(gè)
replicas: 3
template:
metadata:
labels:
app: httpd-server
spec:
containers:
- name: httpd
image: 192.168.1.1:5000/httpd:v1 //三個(gè)版本根據(jù)鏡像進(jìn)行區(qū)分
ports: //這個(gè)只是一個(gè)聲名沒有任何作用
- containerPort: 80
[root@master yaml]# cat httpd02.deployment.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: httpd
spec:
revisionHistoryLimit: 10
replicas: 3
template:
metadata:
labels:
app: httpd-server
spec:
containers:
- name: httpd
image: 192.168.1.1:5000/httpd:v2 //三個(gè)版本根據(jù)鏡像進(jìn)行區(qū)分
ports:
- containerPort: 80
[root@master yaml]# cat httpd03.deployment.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: httpd
spec:
revisionHistoryLimit: 10
replicas: 3
template:
metadata:
labels:
app: httpd-server
spec:
containers:
- name: httpd
image: 192.168.1.1:5000/httpd:v3 //三個(gè)版本根據(jù)鏡像進(jìn)行區(qū)分
ports:
- containerPort: 80
[root@master yaml]# kubectl apply -f httpd01.deployment.yaml --record
//--record的作用就是記錄歷史版本信息
[root@master yaml]# kubectl rollout history deployment httpd
//查看歷史的版本信息
deployment.extensions/httpd
REVISION CHANGE-CAUSE
1 kubectl apply --filename=httpd01.deployment.yaml --record=true
//1,表示版本對(duì)應(yīng)的編號(hào),也可以看出其對(duì)應(yīng)的yaml
[root@master yaml]# kubectl apply -f httpd02.deployment.yaml --record
[root@master yaml]# kubectl apply -f httpd03.deployment.yaml --record
//根據(jù)yaml文件進(jìn)行兩次升級(jí)
[root@master yaml]# kubectl rollout history deployment httpd
deployment.extensions/httpd
REVISION CHANGE-CAUSE
1 kubectl apply --filename=httpd01.deployment.yaml --record=true
2 kubectl apply --filename=httpd02.deployment.yaml --record=true
3 kubectl apply --filename=httpd03.deployment.yaml --record=true
//確認(rèn)升級(jí)的版本信息已經(jīng)記錄
[root@master yaml]# vim httpd-svc.yaml
kind: Service
apiVersion: v1
metadata:
name: httpd-svc
spec:
type: NodePort
selector:
app: httpd-server
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 31000
[root@master yaml]# kubectl apply -f httpd-svc.yaml
//創(chuàng)建一個(gè)svc便于訪問測(cè)試
[root@master yaml]# curl 127.0.0.1:31000
hello lvzhenjiang:v3
//訪問測(cè)試頁面效果
[root@master yaml]# kubectl rollout undo deployment httpd --to-revision=1
//回滾到版本1,使用--to-revision=1表示,1表示查看歷史版本的第一列編號(hào)
[root@master yaml]# curl 127.0.0.1:31000 //測(cè)試訪問
hello lvzhenjiang:v1
如果不指定pod的位置的話,默認(rèn)情況下,是由K8s中scheduler這個(gè)組件來完成的,不能人為的干預(yù)。如果是業(yè)務(wù)需要手動(dòng)指定的話,那么就需要以下方法:
[root@master yaml]# kubectl label nodes node02 disk=ssd
//手動(dòng)給node02打上一個(gè) disk=ssd的標(biāo)簽
[root@master yaml]# kubectl get nodes --show-labels | grep disk=ssd
//查看集群中各個(gè)節(jié)點(diǎn)的標(biāo)簽(包含disk=ssd)
node02 Ready 5d22h v1.15.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disk=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=node02,kubernetes.io/os=linux
//從結(jié)果中可以可看出只有node02包含這個(gè)標(biāo)簽
[root@master yaml]# vim httpd.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: httpd
spec:
revisionHistoryLimit: 10
replicas: 3
template:
metadata:
labels:
app: httpd-server
spec:
containers:
- name: httpd
image: 192.168.1.1:5000/httpd:v1
ports:
- containerPort: 80
nodeSelector: //指定標(biāo)簽選擇器
disk: ssd
[root@master yaml]# kubectl apply -f httpd.yaml
//根據(jù)yaml文件生成所需的pod資源
[root@master yaml]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
httpd-5895f5548b-6lb97 1/1 Running 0 12s 10.244.2.8 node02
httpd-5895f5548b-gh8br 1/1 Running 0 10s 10.244.2.10 node02
httpd-5895f5548b-llxh7 1/1 Running 0 12s 10.244.2.9 node02
//從查詢結(jié)果中可以看出三個(gè)pod資源都運(yùn)行在node02節(jié)點(diǎn)上
上述需求已經(jīng)實(shí)現(xiàn),但是只要有人為干預(yù)的地方就會(huì)錯(cuò)誤的產(chǎn)生,不得不考慮以下這種情況!倘若將node02的標(biāo)簽進(jìn)行刪除的話,看一下會(huì)發(fā)生什么情況!
[root@master yaml]# kubectl label nodes node02 disk-
//將node02的disk=ssd的標(biāo)簽進(jìn)行刪除
[root@master yaml]# kubectl get nodes --show-labels | grep disk=ssd
//驗(yàn)證,標(biāo)簽已經(jīng)被刪除
[root@master yaml]# kubectl delete -f httpd.yaml
//將原本的pod資源進(jìn)行刪除
[root@master yaml]# kubectl apply -f httpd.yaml
//重新生成pod資源(yaml文件中依然指定了標(biāo)簽)
[root@master yaml]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
httpd-5895f5548b-7w26q 0/1 Pending 0 65s
httpd-5895f5548b-c6p6s 0/1 Pending 0 65s
httpd-5895f5548b-v4s5c 0/1 Pending 0 65s
//但是查看pod的狀態(tài)為Pending,顯然這種狀態(tài)的pod是不正常的
即使標(biāo)簽的不存在的,yaml文件中也指定了標(biāo)簽,創(chuàng)建pod資源時(shí),不會(huì)出現(xiàn)錯(cuò)誤,但是pod的狀態(tài)為Pending(等待的狀態(tài)),解決方法如下:
[root@master yaml]# kubectl describe pod httpd-5895f5548b-7w26q
//查看pod的詳細(xì)信息
返回的結(jié)果如下:
從結(jié)果中就已經(jīng)看出了是因?yàn)闃?biāo)簽選擇器與集群中node的標(biāo)簽不匹配導(dǎo)致的!
如果以上沒有發(fā)現(xiàn)錯(cuò)誤的信息,還需進(jìn)行以下操作:
[root@master yaml]# kubectl logs -n kube-system kube-scheduler-master
//查看Scheduler組件所產(chǎn)生的日志信息
[root@master yaml]# less /var/log/messages | grep kubelet
//查看系統(tǒng)日志中包含kubelet組件的信息
//因?yàn)閗ubelet是負(fù)責(zé)管理pod的
有關(guān)K8s的詳細(xì)介紹還是建議參考K8s中文文檔
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。