YAML是專門用來配置文件的語言,很是簡潔和強大。與瞭解的properties、XML、json等數據格式,習慣以後就會發現愈來愈好用。其實YAML就是結合了大部分的標記語言的特性,整合新開發的。html
YAML文件的特色:node
井井有條、結構清晰; 使用簡單、上手容易; 功能強大、語義豐富; 須要特別注意的是: 大小寫敏感; 嚴格要求縮進;
1)YAML文件的組成linux
**Kubernetes中的YAML文件主要由五個一級字段組成,分別是:** * apiVersion:api版本信息; * kind:指定建立資源對象的類型; * metadata:元數據內部的嵌套字段,定義了資源對象的名稱、名稱空間等; * spec:規範定義資源應該擁有什麼樣的特性,依靠控制器確保性能能夠知足,知足用戶指望的狀態。 * status:顯示資源的當前狀態,K8s就是確保當前狀態向目標狀態無限靠近從而知足用戶指望。表明資源當前的狀態;
2)獲取編寫YAML文件的幫助
雖然知道了YAML文件中的一級字段都是什麼,可是仍是不知道應該怎麼寫。能夠藉助如下命令來獲取一些幫助信息。nginx
[root@master ~]# kubectl api-versions //獲取當前集羣支持的 apiserver版本 [root@master ~]# kubectl api-resources //獲取所有的api資源對象 [root@master ~]# kubectl explain deployment //查看k8s某個對象的配置清單格式,應該包含哪些字段及使用方法 [root@master ~]# kubectl explain deployment.spec //這個命令是很是重要的,它能夠一級一級來獲取幫助
3)YAML文件的基本格式web
[root@master ~]# cat web.yaml kind: Deployment //指定要建立的資源對象 apiVersion: extensions/v1beta1 //指定deployment所對應的API版本信息 metadata: name: web //定義deployment的名稱 spec: replicas: 2 //指定副本數量 template: metadata: labels: //指定pod的標籤 app: web_server spec: containers: - name: nginx //指定pod運行的容器的名稱 image: nginx //指定運行容器所需的鏡像
4)生成資源(容器)驗證並查看:docker
[root@master yaml]# kubectl apply -f web.yaml [root@master yaml]# kubectl create -f web.yaml //以上兩條命令都是用於生成資源的二選一 //apply能夠指定屢次,若是發現文件不一樣,則更新 //使用「-f」來指定yaml文件,根據yaml文件中定義的內容生成所需的資源 [root@master ~]# kubectl delete -f web.yaml //若是想快速的刪除定義的資源能夠用此命令 //刪除yaml文件中定義的資源 [root@master yaml]# kubectl get deployments. web //查看web控制器所產生的pod NAME READY UP-TO-DATE AVAILABLE AGE web 2/2 2 2 30s //能夠看見已經生成了兩臺容器 [root@master ~]# kubectl describe deployments. web //用於查看web控制器的詳細信息的
注:Kubernetes已經根據YAML文件生成了咱們所需的pod資源,這裏資源指的就是容器!json
[root@master yaml]# kubectl get pod -o wide //此命令用於查詢生成的資源及IP NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES web-d6ff6c799-c7625 1/1 Running 0 4m2s 10.244.2.3 node01 <none> <none> web-d6ff6c799-sgjc9 1/1 Running 0 4m2s 10.244.1.3 node02 <none> <none> [root@master yaml]# curl -I 10.244.2.3 HTTP/1.1 200 OK Server: nginx/1.19.1 Date: Thu, 13 Aug 2020 09:45:14 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Tue, 07 Jul 2020 15:52:25 GMT Connection: keep-alive ETag: "5f049a39-264" Accept-Ranges: bytes //k8s集羣內部訪問表示是沒有問題的 //咱們需解決一個問題pod的服務可以被外部訪問到
[root@master ~]# cat web-svc.yaml kind: Service apiVersion: v1 metadata: name: web-svc spec: type: NodePort //指定類型爲NodePort,可讓外部訪問,不然默認狀況下是cluster IP,僅限集羣內部訪問 selector: app: web_server //必須與deployment資源對象的標籤進行關聯 ports: - protocol: TCP port: 80 //指定要映射到的Cluster IP的端口 targetPort: 80 //指定的是要映射pod中的端口 nodePort: 31000 //指定映射到宿主機的端口,範圍是30000~32767 [root@master ~]# kubectl apply -f web-svc.yaml //生成service的控制文件(yaml中已經定義其名稱爲web-svc) [root@master ~]# kubectl get svc web-svc //查看service控制器 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE web-svc NodePort 10.100.154.1 <none> 80:31000/TCP 35s //TYPE:爲NodePort,可使外部訪問; //PORT:映射出的端口與咱們定義的同樣
訪問瀏覽器測試:vim
# [root@master ~]# kubectl describe svc web-svc //查看service的詳細信息
返回的信息以下:後端
[root@master ~]# kubectl get pod -o wide | awk '{print $6}' //提取後端pod的IP地址 IP 10.244.2.3 10.244.1.3 //與上述查詢的結果同樣!
咱們知道service是有負載均衡的能力,那麼是怎麼實現的?api
其實,背後的原理並無那麼高大上,kube-proxy經過iptables的轉發機制來實現負載均衡的效果的,先定義目標IP是service提供的羣集IP,而後使用「-j」選項轉發到其餘iptables規則,接下來驗證一下:
[root@master ~]# kubectl get svc web-svc | awk '{print $3}' CLUSTER-IP 10.100.154.1 [root@master ~]# iptables-save | grep 10.100.154.1 -A KUBE-SERVICES ! -s 10.244.0.0/16 -d 10.100.154.1/32 -p tcp -m comment --comment "default/web-svc: cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ -A KUBE-SERVICES -d 10.100.154.1/32 -p tcp -m comment --comment "default/web-svc: cluster IP" -m tcp --dport 80 -j KUBE-SVC-3RBUQ3B6P3MTQ3S7 //從上述結果中能夠看出,當目標地址是羣集IP時,就會轉發到KUBE-SVC-3RBUQ3B6P3MTQ3S7規則中
[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.100.154.1/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-YZTKOTIFXSS7FVXI -A KUBE-SVC-3RBUQ3B6P3MTQ3S7 -j KUBE-SEP-MP33GWHNEEMYWCYU //從查詢結果中能夠看出其負載均衡的效果,由於後端只建立了兩個pod,因此其機率爲0.5
由此能夠看出service實現負載均衡的效果:默認狀況下使用iptables規則,固然還可使用其餘的方法,這裏就不介紹了!
查看負載均衡的詳細信息需根據cluster ip爲切入口!
實現負載均衡最根本的原理就是i:iptables規則根據random(隨機數)實現的負載均衡!
注:此實驗須要搭建私有倉庫,關於搭建私有倉庫registry請參考博客:Docker搭建私有倉庫之registry
[root@master ~]# docker pull httpd [root@master ~]# docker tag httpd 192.168.45.129:5000/httpd:v1 [root@master ~]# docker tag httpd 192.168.45.129:5000/httpd:v2 [root@master ~]# docker tag httpd 192.168.45.129:5000/httpd:v3 //將下載的httpd鏡像更改一下名稱 [root@master ~]# vim /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd --insecure-registry 192.168.45.129:5000 [root@master ~]# systemctl daemon-reload [root@master ~]# systemctl restart docker.service //重啓docker服務 [root@master ~]# docker push 192.168.45.129:5000/httpd:v1 [root@master ~]# docker push 192.168.45.129:5000/httpd:v2 [root@master ~]# docker push 192.168.45.129:5000/httpd:v3 //將定義成不一樣版本鏡像上傳到私有庫 [root@master yaml]# cat httpd01.deployment.yaml kind: Deployment apiVersion: extensions/v1beta1 metadata: name: httpd spec: revisionHistoryLimit: 10 //記錄歷史版本信息爲10個 replicas: 3 template: metadata: labels: app: httpd-server spec: containers: - name: httpd image: 192.168.45.129:5000/httpd:v1 //三個版本根據鏡像進行區分 ports: //這個只是一個聲名沒有任何做用 - 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.45.129:5000/httpd:v2 //三個版本根據鏡像進行區分 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.45.129:5000/httpd:v3 //三個版本根據鏡像進行區分 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,表示版本對應的編號,也能夠看出其對應的yaml [root@master yaml]# kubectl apply -f httpd02.deployment.yaml --record [root@master yaml]# kubectl apply -f httpd03.deployment.yaml --record //根據yaml文件進行兩次升級 [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 //確認升級的版本信息已經記錄 [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 //建立一個svc便於訪問測試 [root@master yaml]# curl 127.0.0.1:31000 <h1>hello bjq:v3</h1> //訪問測試頁面效果 [root@master yaml]# kubectl rollout undo deployment httpd --to-revision=1 //回滾到版本1,使用--to-revision=1表示,1表示查看歷史版本的第一列編號 [root@master yaml]# curl 127.0.0.1:31000 //測試訪問 <h1>hello bjq:v1</h1>
[root@master yaml]# kubectl apply -f httpd03.deployment.yaml --record [root@master yaml]# kubectl get deployments. httpd pod -o wide //能夠看出當前的httpd服務版本是v3 NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR httpd 3/3 3 3 54m httpd 192.168.45.129:5000/httpd:v3 app=httpd-server Error from server (NotFound): deployments.extensions "pod" not found
若是不指定pod的位置的話,默認狀況下,是由K8s中scheduler這個組件來完成的,不能人爲的干預。若是是業務須要手動指定的話,那麼就須要如下方法:
[root@master yaml]# kubectl label nodes node02 disk=ssd //手動給node02打上一個 disk=ssd的標籤 [root@master yaml]# kubectl get nodes --show-labels | grep disk=ssd //查看集羣中各個節點的標籤(包含disk=ssd) node02 Ready <none> 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 //從結果中能夠可看出只有node02包含這個標籤 [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.45.129:5000/httpd:v1 ports: - containerPort: 80 nodeSelector: //指定標籤選擇器 disk: ssd [root@master yaml]# kubectl apply -f httpd.yaml //根據yaml文件生成所需的pod資源 [root@master yaml]# kubectl get pod NAME READY STATUS RESTARTS AGE httpd-7df55ff7b5-p8ll2 1/1 Running 0 23s httpd-7df55ff7b5-tdh6w 1/1 Running 0 23s httpd-7df55ff7b5-vjbn8 1/1 Running 0 23s //從查詢結果中能夠看出三個pod資源都運行在node02節點上
注:上述需求已經實現,可是隻要有人爲干預的地方就會錯誤的產生,不得不考慮如下這種狀況!假若將node02的標籤進行刪除的話,看一下會發生什麼狀況!
[root@master yaml]# kubectl label nodes node02 disk- //將node02的disk=ssd的標籤進行刪除 [root@master yaml]# kubectl get nodes --show-labels | grep disk=ssd //驗證,標籤已經被刪除 [root@master yaml]# kubectl delete -f httpd.yaml //將本來的pod資源進行刪除 [root@master yaml]# kubectl apply -f httpd.yaml //從新生成pod資源(yaml文件中依然指定了標籤) [root@master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES httpd-7df55ff7b5-d2s4s 0/1 Pending 0 12s <none> <none> <none> <none> httpd-7df55ff7b5-h66tj 0/1 Pending 0 12s <none> <none> <none> <none> httpd-7df55ff7b5-rz67j 0/1 Pending 0 12s <none> <none> <none> <none> //可是查看pod的狀態爲Pending,顯然這種狀態的pod是不正常的
即便標籤的不存在的,yaml文件中也指定了標籤,建立pod資源時,不會出現錯誤,可是pod的狀態爲Pending(等待的狀態),解決方法以下:
[root@master yaml]# kubectl describe pod httpd-7df55ff7b5-d2s4s
注:從結果中就已經看出了是由於標籤選擇器與集羣中node的標籤不匹配致使的!
若是以上沒有發現錯誤的信息,還需進行如下操做:
[root@master yaml]# kubectl logs -n kube-system kube-scheduler-master //查看Scheduler組件所產生的日誌信息 [root@master yaml]# less /var/log/messages | grep kubelet //查看系統日誌中包含kubelet組件的信息 //由於kubelet是負責管理pod的