1. 程式人生 > 其它 >k8s——汙點、容忍+3個儲存卷(emptyDir、hostpath和nfs)

k8s——汙點、容忍+3個儲存卷(emptyDir、hostpath和nfs)

目錄

一、汙點(Taint)和容忍(Tolerations)

1.1 汙點(Taint)

1.1.1 概念

1.節點親和性,是Pod的一種屬性(偏好或硬性要求),它使Pod被吸引到一類特定的節點。Taint則相反,它使節點能夠排斥一類特定的Pod
2.Taint和Toleration相互配合,可以用來避免Pod被分配到不合適的節點上。每個節點上都可以應用一個或多個taint ,這表示對於那些不能容忍這些taint的Pod,是不會被該節點接受的。如果將toleration應用於Pod上,則表示這些 Pod 可以(但不一定)被排程到具有匹配taint的節點上
3.使用kubectl taint命令可以給某個Node節點設定汙點,Node被設定上汙點之後就和 Pod 之間存在了一種相斥的關係,可以讓Node拒絕 Pod 的排程執行,甚至將Node已經存在的Pod驅逐出去

1.1.2 汙點的組成格式

key=value:effect

每個汙點有一個key和value作為汙點的標籤,其中value可以為空,effect描述汙點的作用

1.1.3 effect支援如下三個選項

●NoSchedule:表示 k8s 將不會將 Pod 排程到具有該汙點的 Node 上
●PreferNoSchedule:表示 k8s 將盡量避免將 Pod 排程到具有該汙點的 Node 上
●NoExecute:表示 k8s 將不會將 Pod 排程到具有該汙點的 Node 上,同時會將 Node 上已經存在的 Pod 驅逐出去

1.1.4 master上的NoSchedule汙點

master 就是因為有 NoSchedule 汙點,k8s 才不會將 Pod 排程到 master 節點上
kubectl describe node master01

1.1.5 node上設定汙點

#設定汙點
kubectl taint nodes node01 key1=value1:NoSchedule

#節點說明中,查詢 Taints 欄位
kubectl describe node node01


1.1.6 去除汙點

#去除汙點
kubectl taint nodes node01 key1:NoSchedule-

#節點說明中,查詢 Taints 欄位
kubectl describe node node01


1.1.7 汙點例項測試

1.先建立兩個pod資源分別在兩個node節點上
kubectl get pods -o wide

2.在node02上建立汙點
kubectl taint nodes node02 check=mycheck:NoExecute

3.kubectl get pods -o wide
檢視 Pod 狀態,會發現 node02 上的 Pod 已經被全部驅逐(注:如果是 Deployment 或者 StatefulSet 資源型別,為了維持副本數量則會在別的 Node 上再建立新的 Pod

1.2、容忍(Tolerations)

1.2.1 概念

設定了汙點的 Node 將根據 taint 的 effect:NoSchedule、PreferNoSchedule、NoExecute 和 Pod 之間產生互斥的關係,Pod 將在一定程度上不會被排程到 Node 上。但我們可以在 Pod 上設定容忍(Tolerations),意思是設定了容忍的 Pod 將可以容忍汙點的存在,可以被排程到存在汙點的Node上

1.2.2 測試汙點

1.在node02設定汙點的基礎上,再在node01上設定汙點
kubectl taint nodes node01 check=mycheck:NoExecute

2.vim demo1.yaml
==========================================================
apiVersion: v1
kind: Pod
metadata:
  name: myapp03
  labels:
    app: myapp03
spec:
  containers:
  - name: myapp01
    image: nginx
==========================================================
3.kubectl apply -f demo1.yaml

4.kubectl get pods -o wide

1.2.3 在設定汙點的基礎上設定容忍

vim demo2.yaml
==========================================================
apiVersion: v1
kind: Pod
metadata:
  name: myapp04
  labels:
    app: myapp04
spec:
  containers:
  - name: myapp01
    image: nginx
  tolerations:
  - key: "check"
    operator: "Equal"
    value: "mycheck"
    effect: "NoExecute"
    tolerationSeconds: 15
==========================================================
#其中的 key、vaule、effect 都要與 Node 上設定的 taint 保持一致
#operator 的值為 Exists 將會忽略 value 值,即存在即可
#tolerationSeconds 用於描述當 Pod 需要被驅逐時可以在 Pod 上繼續保留執行的時間
==========================================================
kubectl apply -f demo2.yaml

kubectl get pods -o wide -w

1.2.4 容忍的其他注意事項

1.當不指定 key 值時,表示容忍所有的汙點 key
  tolerations:
  - operator: "Exists"  
2.當不指定 effect 值時,表示容忍所有的汙點作用
  tolerations:
  - key: "key"
    operator: "Exists"
3.有多個 Master 存在時,防止資源浪費,可以如下設定
kubectl taint nodes Master-Name node-role.kubernetes.io/master=:PreferNoSchedule

1.2.5 node升級時,設定汙點的流程

//如果某個 Node 更新升級系統元件,為了防止業務長時間中斷,可以先在該 Node 設定 NoExecute 汙點,把該 Node 上的 Pod 都驅逐出去
kubectl taint nodes node01 check=mycheck:NoExecute

//此時如果別的 Node 資源不夠用,可臨時給 Master 設定 PreferNoSchedule 汙點,讓 Pod 可在 Master 上臨時建立
kubectl taint nodes master node-role.kubernetes.io/master=:PreferNoSchedule

//待所有 Node 的更新操作都完成後,再去除汙點
kubectl taint nodes node01 check=mycheck:NoExecute-

二、Pod啟動階段(相位 phase)

2.1 pod啟動過程

1.排程到某臺 node 上。kubernetes 根據一定的優先順序演算法選擇一臺 node 節點將其作為 Pod 執行的 node
2.拉取映象
3.掛載儲存配置等
4.執行起來。如果有健康檢查,會根據檢查的結果來設定其狀態

2.2 phase的狀態

●Pending:表示APIServer建立了Pod資源物件並已經存入了etcd中,但是它並未被排程完成(比如還沒有排程到某臺node上),或者仍然處於從倉庫下載映象的過程中。

●Running:Pod已經被排程到某節點之上,並且Pod中所有容器都已經被kubelet建立。至少有一個容器正在執行,或者正處於啟動或者重啟狀態(也就是說Running狀態下的Pod不一定能被正常訪問)。

●Succeeded:有些pod不是長久執行的,比如job、cronjob,一段時間後Pod中的所有容器都被成功終止,並且不會再重啟。需要反饋任務執行的結果。

●Failed:Pod中的所有容器都已終止了,並且至少有一個容器是因為失敗終止。也就是說,容器以非0狀態退出或者被系統終止,比如 command 寫的有問題。

●Unknown:因為某些原因無法取得 Pod 的狀態,通常是因為與 Pod 所在主機通訊失敗

2.3 故障排除步驟

//檢視Pod事件
kubectl describe TYPE NAME_PREFIX  

//檢視Pod日誌(Failed狀態下)
kubectl logs <POD_NAME> [-c Container_NAME]

//進入Pod(狀態為running,但是服務沒有提供)
kubectl exec –it <POD_NAME> bash

//檢視叢集資訊
kubectl get nodes

//發現叢集狀態正常
kubectl cluster-info

//檢視kubelet日誌發現
journalctl -xefu kubelet

2.4 對節點執行維護操作:刪除節點上的pod資料

2.4.1 將Node標記為不可排程的狀態

kubectl get nodes

//將 Node 標記為不可排程的狀態,這樣就不會讓新建立的 Pod 在此 Node 上執行
kubectl cordon <NODE_NAME> 		 #該node將會變為SchedulingDisabled狀態

kubectl cordon node01

kubectl get nodes

2.4.2 用drain刪除pod資料

//kubectl drain 可以讓 Node 節點開始釋放所有 pod,並且不接收新的 pod 程序。drain 本意排水,意思是將出問題的 Node 下的 Pod 轉移到其它 Node 下執行
==========================================================
kubectl drain node01 --ignore-daemonsets --delete-local-data --force
==========================================================
--ignore-daemonsets:無視 DaemonSet 管理下的 Pod。
--delete-local-data:如果有 mount local volume 的 pod,會強制殺掉該 pod。
--force:強制釋放不是控制器管理的 Pod,例如 kube-proxy。

注:執行 drain 命令,會自動做了兩件事情:
(1)設定此 node 為不可排程狀態(cordon)
(2)evict(驅逐)了 Pod

2.4.3 將Node標記為可排程的狀態

//kubectl uncordon 將 Node 標記為可排程的狀態
kubectl uncordon <NODE_NAME>

kubectl uncordon node01

kubectl get nodes

三、儲存卷

3.1 emptyDir儲存卷

當pod被分配給節點時,首先建立emptyDir卷,並且只要該Pod在該節點上執行,該卷就會存在。正如卷的名字所述,它最初是空的。Pod中的容器可以讀取和寫入emptyDir卷中的相同檔案,儘管該卷可以掛載到每個容器中的相同或不同路徑上。當出於任何原因從節點中刪除 pod時,emptyDir中的資料將被永久刪除
vim demo3.yaml
==========================================================
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx1
    image: nginx
    ports:
    - name: http
      containerPort: 80
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html/
  - name: nginx2
    image: nginx
    volumeMounts:
    - name: html
      mountPath: /data/
    command: ['/bin/bash','-c','while true;do echo $(date) >> /data/index.html;sleep 10;done']
  volumes:
  - name: html
    emptyDir: {}
==========================================================
kubectl apply -f demo3.yaml

kubectl get pods -o wide

kubectl exec -it nginx -c nginx2 sh  #進去nginx2容器
cat /data/index.html

kubectl exec -it nginx -c nginx1 sh  #進去nginx1容器
cat /usr/share/nginx/html/index.html


3.2 hostPath儲存卷

hostpath卷將 node節點的檔案系統中的檔案或目錄掛載到叢集中。hostPath可以實現持久儲存,但是在node節點故障時,也會導致資料的丟失
1.vim demo4.yaml
==========================================================
apiVersion: v1
kind: Pod
metadata:
  name: nginx222
  labels:
    app: nginx222
spec:
  containers:
  - name: nginx1
    image: nginx
    ports:
    - name: http
      containerPort: 80
    volumeMounts:        
    - name: html    ##使用的儲存卷名稱,如果跟下面volume欄位name值相同,則表示使用volume的這個儲存卷
      mountPath: /usr/share/nginx/html/   ##掛載至容器中哪個目錄
      readOnly: false     #讀寫掛載方式,預設為讀寫模式false
  volumes: 
  - name: html     #儲存卷名稱
    hostPath:      
      path: /data/pod/volume   #在宿主機上目錄的路徑
      type: DirectoryOrCreate  #定義型別,這表示如果宿主機沒有此目錄則會自動建立
==========================================================
2.kubectl apply -f demo4.yaml

3.檢視pod在哪個node節點建立,可以用ip訪問測試
kubectl get pods -o wide 

4.在node節點上自動建立的目錄中寫入內容
echo 'woshiwuyifan' > /data/pod/volume/index.html

5.訪問測試
curl http://10.244.2.70

6.主節點寫入內容測試共享
kubectl exec -it nginx222 -c nginx1 sh #進入容器
echo 'woshigutianle' >> /usr/share/nginx/html/index.html
再退出容器測試node02節點:curl http://10.244.2.70




3.3 nfs共享儲存卷

3.3.1 另起伺服器nfs01節點

1.設定主機名
hostnamectl set-hostname nfs01
su

2.關閉防火牆和安全功能
systemctl stop firewalld
setenforce 0

3.建立共享目錄並給許可權
mkdir -p /data/volume
chmod 777 /data/volume

4.安裝nfs,並配置nfs服務
yum install -y rpcbind nfs-utils

vim /etc/exports
/data/volume 192.168.80.0/24(rw,sync,no_root_squash)

5.啟動nfs服務並檢視本機共享目錄
systemctl start rpcbind
systemctl start nfs

showmount -e

6.在共享目錄寫入網頁檔案
echo 'woshizhangjiahui' > /data/volume/index.html


3.3.2 在master節點和node節點配置對映

echo '192.168.80.14 nfs01' >> /etc/hosts

3.3.3 主節點操作

vim demo5.yaml
==========================================================
apiVersion: v1
kind: Pod
metadata:
  name: nginx333
  labels:
    app: nginx222
spec:
  containers:
  - name: nginx1
    image: nginx
    ports:
    - name: http
      containerPort: 80
    volumeMounts:        
    - name: html    ##使用的儲存卷名稱,如果跟下面volume欄位name值相同,則表示使用volume的這個儲存卷
      mountPath: /usr/share/nginx/html/   ##掛載至容器中哪個目錄
      readOnly: false     #讀寫掛載方式,預設為讀寫模式false
  volumes: 
  - name: html     #儲存卷名稱
    nfs:      
      path: /data/volume   #在宿主機上目錄的路徑
      server: nfs01
==========================================================
kubectl apply -f demo5.yaml

kubectl get pods -o wide

curl http://10.244.2.71  #排程的node節點的ip

3.3.4 在nfs伺服器額外寫網頁檔案

nfs伺服器:echo 'woshi111' >> /data/volume/index.html
主伺服器:curl http://10.244.2.71
kubectl exec -it nginx333 -c nginx1 sh