k8s 核心概念NameSpace、Labels、Pods
簡單瞭解下k8s 中一些核心的概念以及其作用。
1. namespace
namespace 可以用來做資源隔離,Namespace為名稱提供了一個範圍。資源的Names在Namespace中具有唯一性。Namespace是一種將叢集資源劃分為多個用途(通過 resource quota)的方法。
1. 建立
(1) 命令列建立
[root@k8smaster1 ~]# kubectl create namespace new-namespace
namespace/new-namespace created
(2) yaml 建立
[root@k8smaster1 ~]# catnew-namespace2.yaml apiVersion: v1 kind: Namespace metadata: name: new-namespace2
執行建立命令:
[root@k8smaster1 ~]# kubectl create -f new-namespace2.yaml
namespace/new-namespace2 created
2. 刪除
[root@k8smaster1 ~]# kubectl delete namespaces new-namespace namespace "new-namespace" deleted
刪除一個namespace會自動刪除所有屬於該namespace的資源; default和kube-system名稱空間不可刪除; PersistentVolumes是不屬於任何namespace的,但PersistentVolumeClaim是屬於某個特定namespace的; Events是否屬於namespace取決於產生events的物件。
3. 檢視namespace
[root@k8smaster1 ~]# kubectl get namespace NAME STATUS AGE default Active 3d2h kube-node-lease Active 3d2h kube-public Active 3d2h kube-system Active 3d2h kubernetes-dashboard Active 3d new-namespace2 Active 6m41s [root@k8smaster1~]# kubectl get namespaces NAME STATUS AGE default Active 3d2h kube-node-lease Active 3d2h kube-public Active 3d2h kube-system Active 3d2h kubernetes-dashboard Active 3d new-namespace2 Active 6m46s
4. 根據namespace 檢視資源
[root@k8smaster1 ~]# kubectl get deployments -o wide --namespace=default NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR nginx 1/1 1 1 3d nginx nginx app=nginx [root@k8smaster1 ~]# kubectl get deployments -o wide --all-namespaces NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR default nginx 1/1 1 1 3d nginx nginx app=nginx kube-system coredns 2/2 2 2 3d2h coredns registry.aliyuncs.com/google_containers/coredns:1.6.7 k8s-app=kube-dns kubernetes-dashboard dashboard-metrics-scraper 1/1 1 1 3d dashboard-metrics-scraper kubernetesui/metrics-scraper:v1.0.6 k8s-app=dashboard-metrics-scraper kubernetes-dashboard kubernetes-dashboard 1/1 1 1 3d kubernetes-dashboard kubernetesui/dashboard:v2.2.0 k8s-app=kubernetes-dashboard
5. 所有物件都在namespace ?
大多數Kubernetes資源(例如pod、services、replication controllers或其他)都在某些Namespace中,但Namespace資源本身並不在Namespace中。而低級別資源(如Node和persistentVolumes)不在任何Namespace中。Events是一個例外:它們可能有也可能沒有Namespace,具體取決於Events的物件。
2. label
1. 概述
一個label 是一個key = value 的鍵值對。 label 可以附加到各種資源物件上, 如Node、pod、RC。一個物件可以有任意數量的label, 一個label 也可以被新增到任意物件。
Label 常見的用法是使用metadata.labels 欄位為物件新增label, 通過spec.selector 引用物件。 也可以在物件建立後動態的建立、編輯、刪除標籤。
2. 使用
1. 動態新增、檢視、刪除標籤
[root@k8smaster1 ~]# kubectl label node k8snode1 env_role=dev # 新增標籤 node/k8snode1 labeled [root@k8smaster1 ~]# kubectl get node k8snode1 --show-labels # 檢視標籤 NAME STATUS ROLES AGE VERSION LABELS k8snode1 Ready <none> 5d2h v1.18.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,env_role=dev,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8snode1,kubernetes.io/os=linux [root@k8smaster1 ~]# kubectl label node k8snode1 env_role- # 刪除標籤 node/k8snode1 labeled [root@k8smaster1 ~]# kubectl get node k8snode1 --show-labels # 再次檢視標籤 NAME STATUS ROLES AGE VERSION LABELS k8snode1 Ready <none> 5d2h v1.18.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8snode1,kubernetes.io/os=linux
2. 建立資源的時候設定標籤
(1) 建立labeltest.yml 檔案
apiVersion: v1 kind: ReplicationController metadata: name: nginx spec: replicas: 3 selector: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx spec: type: NodePort ports: - port: 80 selector: app: nginx
(2) 建立資源
kubectl apply -f labeltest.yml
(3) 檢視pod 資訊
[root@k8smaster1 ~]# kubectl get pods --show-labels NAME READY STATUS RESTARTS AGE LABELS nginx-86jgk 1/1 Running 0 6m46s app=nginx nginx-fbqgg 1/1 Running 0 6m46s app=nginx nginx-vq54h 1/1 Running 0 6m46s app=nginx nodeaffinity 1/1 Running 0 3h <none>
3. pod
1. pod 概述
Pod是Kubernetes建立或部署的最小/最簡單的基本單位,一個Pod代表叢集上正在執行的一個程序。
一個Pod封裝一個應用容器(也可以有多個容器),儲存資源、一個獨立的網路IP以及管理控制容器執行方式的策略選項。Pod代表部署的一個單位:Kubernetes中單個應用的例項,它可能由單個容器或多個容器共享組成的資源。每個pod 都有一個特殊的被稱為"根容器" 的pause容器。 pause 容器對應的映象屬於kubernetes 平臺的一部分,除了pause 容器,每個pod 還包含一個或多個緊密相關的使用者業務容器。
其建立流程如下:
master節點: create pod - apiserver - etcd; scheduler --apiserver --etcd -- 排程演算法,把pod 排程到某個節點 (關於其排程演算法後面介紹)
node 節點: kubelet -- apiserver -- 讀取etcd 拿到分配給當前節點的pod -- docker 建立容器
pod 關係:
(1) pod vs 應用
每個pod 都是應用的一個例項,有專用的IP
(2) pod vs 容器
一個pod 可以有多個容器,彼此間共享網路和儲存資源,每個pod 有一個pause 容器儲存所有容器的狀態,通過管理pause 容器,達到管理pod 中所有容器的效果
(3) pod VS 節點
同一個pod 中的容器總被排程到相同node 節點,不同節點間pod 的通訊基於虛擬二層網路技術實現。
(4) pod VS pod
普通的pod 和靜態的pod
2. Kubernetes中的Pod使用可分兩種主要方式
(1) Pod中執行一個容器。“one-container-per-Pod”模式是Kubernetes最常見的用法; 在這種情況下,你可以將Pod視為單個封裝的容器,但是Kubernetes是直接管理Pod而不是容器。
(2) Pods中執行多個需要一起工作的容器。Pod可以封裝緊密耦合的應用,它們需要由多個容器組成,它們之間能夠共享資源,這些容器可以形成一個單一的內部service單位 - 一個容器共享檔案,另一個“sidecar”容器來更新這些檔案。Pod將這些容器的儲存資源作為一個實體來管理。
每個Pod都是執行應用的單個例項,如果需要水平擴充套件應用(例如,執行多個例項),則應該使用多個Pods,每個例項一個Pod。在Kubernetes中,這樣通常稱為Replication。Replication的Pod通常由Controller建立和管理。
3. Pods如何管理多個容器
Pods的設計可用於支援多程序的協同工作(作為容器),形成一個cohesive的Service單位。Pod中的容器在叢集中Node上被自動分配,容器之間可以共享資源、網路和相互依賴關係,並同時被排程使用。
4. pods 特性
(1) Pods提供兩種共享資源:網路和儲存
網路: 每個Pod被分配一個獨立的IP地址,Pod中的每個容器共享網路名稱空間,包括IP地址和網路埠。Pod內的容器可以使用localhost相互通訊。當Pod中的容器與Pod 外部通訊時,他們必須協調如何使用共享網路資源(如埠)。
儲存: Pod可以指定一組共享儲存volumes。Pod中的所有容器都可以訪問共享volumes,允許這些容器共享資料。volumes 還用於Pod中的資料持久化,以防其中一個容器需要重新啟動而丟失資料。
(2) 生命週期短暫:
使用Pod: 你很少會直接在kubernetes中建立單個Pod。因為Pod的生命週期是短暫的,用後即焚的實體。當Pod被建立後(不論是由你直接建立還是被其他Controller),都會被Kuberentes排程到叢集的Node上。直到Pod的程序終止、被刪掉、因為缺少資源而被驅逐、或者Node故障之前這個Pod都會一直保持在那個Node上。
注意:重啟Pod中的容器跟重啟Pod不是一回事。Pod只提供容器的執行環境並保持容器的執行狀態,重啟容器不會造成Pod重啟。
(3) 平坦的網路
K8s 叢集中的所有 Pod 都在同一個共享網路地址空間中,也就是說每個 Pod 都可以通過其 他 Pod 的 IP 地址來實現訪問。
5. Pod和Controller
Controller可以建立和管理多個Pod,提供副本管理、滾動升級和叢集級別的自愈能力。例如,如果一個Node故障,Controller就能自動將該節點上的Pod排程到其他健康的Node上。
Pod不會自愈。如果Pod執行的Node故障,或者是排程器本身故障,這個Pod就會被刪除。同樣的,如果Pod所在Node缺少資源或者Pod處於維護狀態,Pod也會被驅逐。Kubernetes使用更高階的稱為Controller的抽象層,來管理Pod例項。雖然可以直接使用Pod,但是在Kubernetes中通常是使用Controller來管理Pod的。
6. pod 使用
1.一個容器組成的pod
(1) 建立one_pod.yml
# 一個容器組成的 Pod apiVersion: v1 kind: Pod metadata: name: mytomcat labels: name: mytomcat spec: containers: - name: mytomcat image: tomcat:8.0.15-jre8 ports: - containerPort: 8080
(2) 建立pod
kubectl create -f one_pod.yml
(3) 暴露埠
kubectl expose pods mytomcat --port=8080 --type=NodePort
(4) 檢視暴露的埠資訊
[root@k8smaster1 ~]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d4h mytomcat NodePort 10.98.168.125 <none> 8080:31159/TCP 111m
(5) 接下來從其他機器訪問31159 埠即可訪問到tomcat 的主頁
(6) 刪除掉相關資源
[root@k8smaster1 ~]# kubectl delete -f one_pod.yml pod "mytomcat" deleted [root@k8smaster1 ~]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d4h mytomcat NodePort 10.98.168.125 <none> 8080:31159/TCP 121m [root@k8smaster1 ~]# kubectl delete svc mytomcat service "mytomcat" deleted [root@k8smaster1 ~]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d4h [root@k8smaster1 ~]# kubectl get pods No resources found in default namespace.
2. 兩個容器組成的pod
(1) 建立two_pod.yml
apiVersion: v1 kind: Pod metadata: name: tomcat-redis labels: name: tomcat-redis spec: containers: - name: tomcat image: tomcat:8.0.15-jre8 ports: - containerPort: 8080 - name: redis image: redis ports: - containerPort: 6379
(2) 執行建立
[root@k8smaster1 ~]# kubectl apply -f two_pod.yml pod/tomcat-redis created [root@k8smaster1 ~]# kubectl get pods NAME READY STATUS RESTARTS AGE tomcat-redis 0/2 ContainerCreating 0 13s [root@k8smaster1 ~]# kubectl get pods NAME READY STATUS RESTARTS AGE tomcat-redis 2/2 Running 0 29s
(3) 檢視相關資訊
[root@k8smaster1 ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES tomcat-redis 2/2 Running 0 3m32s 10.244.1.8 k8snode1 <none> <none> [root@k8smaster1 ~]# curl 10.244.1.8:8080 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Apache Tomcat/8.0.15</title> <link href="favicon.ico" rel="icon" type="image/x-icon" /> <link href="favicon.ico" rel="shortcut icon" type="image/x-icon" /> <link href="tomcat.css" rel="stylesheet" type="text/css" /> </head> <body> <div id="wrapper"> <div id="navigation" class="curved container"> <span id="nav-home"><a href="http://tomcat.apache.org/">Home</a></span> ....
(4) 進入容器
1》 有多個容器的情況下預設執行exec 進入的是第一個容器
[root@k8smaster1 ~]# kubectl exec -it tomcat-redis -- bash Defaulting container name to tomcat. Use 'kubectl describe pod/tomcat-redis -n default' to see all of the containers in this pod. root@tomcat-redis:/usr/local/tomcat# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 06:55 ? 00:00:18 /usr/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.l root 84 0 0 07:36 pts/0 00:00:00 bash root 91 84 0 07:37 pts/0 00:00:00 ps -ef root@tomcat-redis:/usr/local/tomcat#
可以看到我們直接進入pod 的時候預設進入的是pod 的一個container
2》 指定容器名稱進入pod 的指定容器
檢視kubectl exec 命令解釋如下:
[root@k8smaster1 ~]# kubectl exec --help Execute a command in a container. Examples: # Get output from running 'date' command from pod mypod, using the first container by default kubectl exec mypod -- date # Get output from running 'date' command in ruby-container from pod mypod kubectl exec mypod -c ruby-container -- date # Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod mypod # and sends stdout/stderr from 'bash' back to the client kubectl exec mypod -c ruby-container -i -t -- bash -il # List contents of /usr from the first container of pod mypod and sort by modification time. # If the command you want to execute in the pod has any flags in common (e.g. -i), # you must use two dashes (--) to separate your command's flags/arguments. # Also note, do not surround your command and its flags/arguments with quotes # unless that is how you would execute it normally (i.e., do ls -t /usr, not "ls -t /usr"). kubectl exec mypod -i -t -- ls -t /usr # Get output from running 'date' command from the first pod of the deployment mydeployment, using the first container by default kubectl exec deploy/mydeployment -- date # Get output from running 'date' command from the first pod of the service myservice, using the first container by default kubectl exec svc/myservice -- date Options: -c, --container='': Container name. If omitted, the first container in the pod will be chosen -f, --filename=[]: to use to exec into the resource --pod-running-timeout=1m0s: The length of time (like 5s, 2m, or 3h, higher than zero) to wait until at least one pod is running -i, --stdin=false: Pass stdin to the container -t, --tty=false: Stdin is a TTY Usage: kubectl exec (POD | TYPE/NAME) [-c CONTAINER] [flags] -- COMMAND [args...] [options] Use "kubectl options" for a list of global command-line options (applies to all commands).
可以看到-c 可以指定container 的name, 如果省略的話預設會進入第一個容器。
檢視pod 資訊: 可以看到容器名稱、id 等資訊
[root@k8smaster1 ~]# kubectl describe pod/tomcat-redis Name: tomcat-redis Namespace: default Priority: 0 Node: k8snode1/192.168.13.104 Start Time: Thu, 13 Jan 2022 01:55:52 -0500 Labels: name=tomcat-redis Annotations: Status: Running IP: 10.244.1.8 IPs: IP: 10.244.1.8 Containers: tomcat: Container ID: docker://1ec1f327b0f15c7109901c500e72c5ea193f0283d2d32c502aea5f831aea5608 Image: tomcat:8.0.15-jre8 Image ID: docker-pullable://tomcat@sha256:6d85afe09c49b633035ba33281b3b50ae5a613cd71ef583d2adc56a9bd5b88b6 Port: 8080/TCP Host Port: 0/TCP State: Running Started: Thu, 13 Jan 2022 01:55:53 -0500 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-5r9hq (ro) redis: Container ID: docker://29a717c7ccb0cd54b8b211cc2722c3fc183bb5a0af79e9c3c358449a13d84cf0 Image: redis Image ID: docker-pullable://redis@sha256:db485f2e245b5b3329fdc7eff4eb00f913e09d8feb9ca720788059fdc2ed8339 Port: 6379/TCP Host Port: 0/TCP State: Running Started: Thu, 13 Jan 2022 01:56:16 -0500 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-5r9hq (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: default-token-5r9hq: Type: Secret (a volume populated by a Secret) SecretName: default-token-5r9hq Optional: false QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 55m default-scheduler Successfully assigned default/tomcat-redis to k8snode1 Normal Pulled 55m kubelet, k8snode1 Container image "tomcat:8.0.15-jre8" already present on machine Normal Created 55m kubelet, k8snode1 Created container tomcat Normal Started 55m kubelet, k8snode1 Started container tomcat Normal Pulling 55m kubelet, k8snode1 Pulling image "redis" Normal Pulled 54m kubelet, k8snode1 Successfully pulled image "redis" Normal Created 54m kubelet, k8snode1 Created container redis Normal Started 54m kubelet, k8snode1 Started container redis
進入指定容器:(-c 指定容器名稱)
[root@k8smaster1 ~]# kubectl exec -c redis -it tomcat-redis -- bash root@tomcat-redis:/data# redis-cli -v redis-cli 6.2.6 root@tomcat-redis:/data# redis-cli 127.0.0.1:6379> keys * 1) "key1" 127.0.0.1:6379>
7. pod 分類:
(1) 普通pod
pod 建立後會被儲存到etcd, 隨後被k8s master 排程到某個node 節點,當節點發生故障後,則會將pod 重新排程到其他節點。
(2) 靜態pod
該pod 由kubelet 進行管理且存在於特定的node 上,它們不能通過api server 進行管理,無法與ReplicationController、Deployment、DaemonSet 那些關聯,並且kubelet 無法對其健康檢查。
8. pod 狀態、生命週期、重啟策略、映象拉取策略
1. 狀態:
Pod 的 status 定義在 PodStatus 物件中,其中有一個 phase 欄位。可能的值如下
- 掛起(Pending):Pod 已被 Kubernetes 系統接受,但有一個或者多個容器映象尚未建立。等待時間包括排程 Pod 的時間和通過網路下載映象的時間,這可能需要花點時間。
- 執行中(Running):該 Pod 已經繫結到了一個節點上,Pod 中所有的容器都已被建立。至少有一個容器正在執行,或者正處於啟動或重啟狀態。
- 成功(Succeeded):Pod 中的所有容器都被成功終止,並且不會再重啟。
- 失敗(Failed):Pod 中的所有容器都已終止了,並且至少有一個容器是因為失敗終止。也就是說,容器以非0狀態退出或者被系統終止。
- 未知(Unknown):因為某些原因無法取得 Pod 的狀態,通常是因為與 Pod 所在主機通訊失敗
2. 重啟策略:restartPolicy
3. 狀態轉換
4. 映象拉取策略
spec: #specification of the resource content 指定該資源的內容 restartPolicy: Always #表明該容器一直執行,預設k8s的策略,在此容器退出後,會立即建立一個相同的容器 nodeSelector: #節點選擇,先給主機打標籤kubectl label nodes kube-node1 zone=node1 zone: node1 containers: - name: web04-pod #容器的名字 image: web:apache #容器使用的映象地址 imagePullPolicy: Never #三個選擇Always、Never、IfNotPresent,每次啟動時檢查和更新(從registery)images的策略, # Always,每次都檢查 # Never,每次都不檢查(不管本地是否有) # IfNotPresent,如果本地有就不檢查,如果沒有就拉取(預設)
9. pod 健康檢查
有兩種型別:
livenessProbe(存活檢查): 如果檢查失敗,將殺死容器,根據pod 的restartPolicy 來操作
readinessProbe(就緒檢查):如果檢查失敗,k8s 會把pod 從service endpoint是 中剔除。
檢查方式有三種:
httpGet: 傳送http 請求,返回200 -400 範圍狀態碼即為成功
exec: 執行shell 命令, 返回狀態碼是0 表示成功
tcpSocket: 發起TcpSocket 建立成功
例如:
1. 新建livess_test.yml, 內容如下: 使用exec 執行命令, 相當於執行bash 命令執行
apiVersion: v1 kind: Pod metadata: name: liveness-exec labels: test: liveness spec: containers: - name: liveness image: busybox args: - /bin/sh - -c - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy livenessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5 periodSeconds: 5
2. 建立pod
kubectl apply -f livess_test.yml
3. 檢視pod 狀態:(一直在重啟)
[root@k8smaster1 ~]# kubectl get pods NAME READY STATUS RESTARTS AGE liveness-exec 0/1 CrashLoopBackOff 10 37m
10. pod 資源限制
可以對pod 能使用的伺服器上的資源進行限制,包括cpu 和 memory,其中CPU的資源單位為CPU數量,memory 的值是記憶體位元組數。設定可以用requests 和 limits 限定最小值和最大值。
記憶體資源是以位元組為單位的,可以表示為純整數或者固定的十進位制數字,字尾可以是E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki.比如,下面幾種寫法表示相同的數值:alue:
128974848, 129e6, 129M , 123Mi
CPU資源是以CPU單位來計算的,一個容器申請0.5個CPU,就相當於其他容器申請1個CPU的一半,你也可以加個字尾m 表示千分之一的概念。比如說100m的CPU,100豪的CPU和0.1個CPU都是一樣的。但是不支援精度超過1M的。
例如:
1. 建立namespace
kubectl create namespace mem-example
2. 建立 mytomcat.yml
# 一個容器組成的 Pod apiVersion: v1 kind: Pod metadata: name: mytomcat labels: name: mytomcat spec: containers: - name: mytomcat image: tomcat:8.0.15-jre8 ports: - containerPort: 8080 resources: requests: memory: "50Mi" cpu: "125m" limits: memory: "100Mi" cpu: "250m"
上面表示容器啟動過程中最少申請0.125 個cpu, 50M 記憶體; 最多0.25 個cpu, 100m 記憶體。
3. 建立pod
kubectl apply -f pod_resource.yml --namespace=mem-example
4. 檢視pod 狀態
[root@k8smaster1 ~]# kubectl get pod --namespace=mem-example -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES mytomcat 1/1 Running 0 5m16s 10.244.1.11 k8snode1 <none> <none>
5. 以yaml 輸出檢視詳細資訊
kubectl get pods mytomcat --output=yaml --namespace=mem-example
輸出詳細資訊包含資源資訊如下:
apiVersion: v1 kind: Pod metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"name":"mytomcat"},"name":"mytomcat","namespace":"mem-example"},"spec":{"containers":[{"image":"tomcat:8.0.15-jre8","name":"mytomcat","ports":[{"containerPort":8080}],"resources":{"limits":{"cpu":"250m","memory":"100Mi"},"requests":{"cpu":"125m","memory":"50Mi"}}}]}} creationTimestamp: "2022-01-13T11:16:47Z" labels: name: mytomcat managedFields: - apiVersion: v1 fieldsType: FieldsV1 fieldsV1: f:metadata: f:annotations: .: {} f:kubectl.kubernetes.io/last-applied-configuration: {} f:labels: .: {} f:name: {} f:spec: f:containers: k:{"name":"mytomcat"}: .: {} f:image: {} f:imagePullPolicy: {} f:name: {} f:ports: .: {} k:{"containerPort":8080,"protocol":"TCP"}: .: {} f:containerPort: {} f:protocol: {} f:resources: .: {} f:limits: .: {} f:cpu: {} f:memory: {} f:requests: .: {} f:cpu: {} f:memory: {} f:terminationMessagePath: {} f:terminationMessagePolicy: {} f:dnsPolicy: {} f:enableServiceLinks: {} f:restartPolicy: {} f:schedulerName: {} f:securityContext: {} f:terminationGracePeriodSeconds: {} manager: kubectl operation: Update time: "2022-01-13T11:16:47Z" - apiVersion: v1 fieldsType: FieldsV1 fieldsV1: f:status: f:conditions: k:{"type":"ContainersReady"}: .: {} f:lastProbeTime: {} f:lastTransitionTime: {} f:status: {} f:type: {} k:{"type":"Initialized"}: .: {} f:lastProbeTime: {} f:lastTransitionTime: {} f:status: {} f:type: {} k:{"type":"Ready"}: .: {} f:lastProbeTime: {} f:lastTransitionTime: {} f:status: {} f:type: {} f:containerStatuses: {} f:hostIP: {} f:phase: {} f:podIP: {} f:podIPs: .: {} k:{"ip":"10.244.1.11"}: .: {} f:ip: {} f:startTime: {} manager: kubelet operation: Update time: "2022-01-13T11:16:49Z" name: mytomcat namespace: mem-example resourceVersion: "777204" selfLink: /api/v1/namespaces/mem-example/pods/mytomcat uid: dcbba6ba-b959-46b2-8882-960dc223cc45 spec: containers: - image: tomcat:8.0.15-jre8 imagePullPolicy: IfNotPresent name: mytomcat ports: - containerPort: 8080 protocol: TCP resources: limits: cpu: 250m memory: 100Mi requests: cpu: 125m memory: 50Mi terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /var/run/secrets/kubernetes.io/serviceaccount name: default-token-q7fc5 readOnly: true dnsPolicy: ClusterFirst enableServiceLinks: true nodeName: k8snode1 priority: 0 restartPolicy: Always schedulerName: default-scheduler securityContext: {} serviceAccount: default serviceAccountName: default terminationGracePeriodSeconds: 30 tolerations: - effect: NoExecute key: node.kubernetes.io/not-ready operator: Exists tolerationSeconds: 300 - effect: NoExecute key: node.kubernetes.io/unreachable operator: Exists tolerationSeconds: 300 volumes: - name: default-token-q7fc5 secret: defaultMode: 420 secretName: default-token-q7fc5 status: conditions: - lastProbeTime: null lastTransitionTime: "2022-01-13T11:16:47Z" status: "True" type: Initialized - lastProbeTime: null lastTransitionTime: "2022-01-13T11:16:49Z" status: "True" type: Ready - lastProbeTime: null lastTransitionTime: "2022-01-13T11:16:49Z" status: "True" type: ContainersReady - lastProbeTime: null lastTransitionTime: "2022-01-13T11:16:47Z" status: "True" type: PodScheduled containerStatuses: - containerID: docker://61f02b9ff8009948fc6fe5d43f7296e18796de68b3641b3a5333e8bcd0e73749 image: tomcat:8.0.15-jre8 imageID: docker-pullable://tomcat@sha256:6d85afe09c49b633035ba33281b3b50ae5a613cd71ef583d2adc56a9bd5b88b6 lastState: {} name: mytomcat ready: true restartCount: 0 started: true state: running: startedAt: "2022-01-13T11:16:48Z" hostIP: 192.168.13.104 phase: Running podIP: 10.244.1.11 podIPs: - ip: 10.244.1.11 qosClass: Burstable startTime: "2022-01-13T11:16:47Z"View Code
可以看到有容器申請資源的資訊。
6. 從k8snode1 用docker 檢視容器資源資訊
(1) 檢視docker cid
[root@k8snode1 ~]# docker ps -a | grep tomcat 61f02b9ff800 5b52d00c82ff "catalina.sh run" 18 minutes ago Up 18 minutes k8s_mytomcat_mytomcat_mem-example_dcbba6ba-b959-46b2-8882-960dc223cc45_0 7f8e6c9f80cd registry.aliyuncs.com/google_containers/pause:3.2 "/pause" 18 minutes ago Up 18 minutes k8s_POD_mytomcat_mem-example_dcbba6ba-b959-46b2-8882-960dc223cc45_0
(2) 檢視容器資源資訊
docker stats 61f02b9ff800
結果:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 61b1c87ab3c5 k8s_mytomcat_mytomcat_mem-example_dcbba6ba-b959-46b2-8882-960dc223cc45_2 0.17% 87.82MiB / 100MiB 87.82% 0B / 0B 0B / 0B 2
11. 節點排程
(1) 親和性
節點親和性分為硬親和性和軟親和性,硬親和性表示必須滿足,軟親和性表示嘗試滿足,但不必須。支援的常有操作符有: In NotIn Exists Gt Lt DoesNotExists
例如一個模板:
apiVersion: v1 kind: Pod metadata: name: nodeaffinity spec: containers: - name: nodeaffinity image: nginx affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: # 硬親和性 nodeSelectorTerms: - matchExpressions: - key: env_role operator: In values: - dev - test preferredDuringSchedulingIgnoredDuringExecution: # 軟親和性 - weight: 1 preference: matchExpressions: - key: group operator: In values: otherprod
測試如下:
1》新建nodeaffinity.yml
apiVersion: v1 kind: Pod metadata: name: nodeaffinity spec: containers: - name: nodeaffinity image: nginx affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: # 硬親和性 nodeSelectorTerms: - matchExpressions: - key: env_role operator: In values: - dev - test
2》 建立資源
[root@k8smaster1 ~]# kubectl apply -f nodeaffinity.yml pod/nodeaffinity created [root@k8smaster1 ~]# kubectl get pods NAME READY STATUS RESTARTS AGE nodeaffinity 0/1 Pending 0 4m4s [root@k8smaster1 ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nodeaffinity 0/1 Pending 0 4m8s <none> <none> <none> <none>
可以看到pod 沒有被排程
3》 給node 打標籤,然後再次檢視
[root@k8smaster1 ~]# kubectl label node k8snode1 env_role=dev node/k8snode1 labeled [root@k8smaster1 ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nodeaffinity 1/1 Running 0 11m 10.244.1.15 k8snode1 <none> <none>
(2) 節點選擇器
[root@k8smaster1 ~]# cat labelaffinity.yml apiVersion: v1 kind: Pod metadata: name: labelaffinity spec: containers: - name: labelaffinity image: nginx nodeSelector: env_role: dev
相當於根據node的label 標籤進行排程。
(3) 汙點和汙點容忍
nodeSelector 和 nodeAffinity: pod 排程到某些節點時,通過pod 的屬性影響其排程
Taint 汙點: 節點不做普通分配排程,是節點屬性。
場景: 專用節點、配置特點硬體節點、基於Taint 驅逐
測試:
1》 檢視節點汙點情況
[root@k8smaster1 ~]# kubectl describe node k8smaster1 | grep Taint Taints: node-role.kubernetes.io/master:NoSchedule
汙點值有三個:
NoSchedule 從來不被排程
PreferNoSchedule: 儘量不被排程
NoExecute: 不會排程,並且還會驅逐Node 已有pod
2》 為節點新增汙點值
[root@k8smaster1 ~]# kubectl taint node k8snode1 env_role:NoSchedule node/k8snode1 tainted [root@k8smaster1 ~]# kubectl describe node k8snode1 | grep Taint Taints: env_role:NoSchedule
3》測試: 可以看到擴充套件也是一直在k8snode2 節點
[root@k8smaster1 ~]# kubectl create deployment web --image=nginx deployment.apps/web created [root@k8smaster1 ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES web-5dcb957ccc-vk822 0/1 ContainerCreating 0 7s <none> k8snode2 <none> <none> [root@k8smaster1 ~]# kubectl scale deployment web --replicas=5 deployment.apps/web scaled [root@k8smaster1 ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES web-5dcb957ccc-2s4gx 0/1 ContainerCreating 0 3s <none> k8snode2 <none> <none> web-5dcb957ccc-642rk 0/1 ContainerCreating 0 3s <none> k8snode2 <none> <none> web-5dcb957ccc-vk822 1/1 Running 0 37s 10.244.2.10 k8snode2 <none> <none> web-5dcb957ccc-w6cm4 0/1 ContainerCreating 0 3s <none> k8snode2 <none> <none> web-5dcb957ccc-x8hdg 0/1 ContainerCreating 0 3s <none> k8snode2 <none> <none>
4》 刪除汙點
[root@k8smaster1 ~]# kubectl taint node k8snode1 env_role:NoSchedule- node/k8snode1 untainted [root@k8smaster1 ~]# kubectl describe node k8snode1 | grep Taint Taints: <none>
5》 汙點容忍
汙點容忍是說配置了NoSchedule,但是如果配置了容忍還是可以分配的。
首先給節點配置汙點: (配置汙點節點進行排程)
[root@k8smaster1 ~]# kubectl taint node k8snode1 env_role=dev:NoSchedule node/k8snode1 tainted [root@k8smaster1 ~]# kubectl describe node k8snode1 | grep Taint Taints: env_role=dev:NoSchedule
配置汙點容忍標識可以進行分配:tolerations.yml
apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: web name: web spec: replicas: 2 selector: matchLabels: app: web strategy: {} template: metadata: creationTimestamp: null labels: app: web spec: containers: - image: nginx:1.14 name: nginx resources: {} tolerations: - key: "env_role" operator: "Equal" value: "dev" effect: "NoSchedule" status: {}
對於 tolerations 屬性的寫法,其中pod的 key、value、effect 與 Node 的 Taint 設定需保持一致, 還有以下幾點說明:
如果 operator 的值是 Exists,則 value 屬性可省略
如果 operator 的值是 Equal,則表示其 key 與 value 之間的關係是 equal(等於)
如果不指定 operator 屬性,則預設值為 Equal
部署檢視結果:
[root@k8smaster1 ~]# kubectl apply -f tolerations.yml deployment.apps/web created [root@k8smaster1 ~]# kubectl get deployments -o wide NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR web 2/2 2 2 5s nginx nginx:1.14 app=web [root@k8smaster1 ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES web-644647f57f-fj7xk 1/1 Running 0 9s 10.244.2.15 k8snode2 <none> <none> web-644647f57f-x62cz 1/1 Running 0 9s 10.244.1.19 k8snode1 <none> <none>
我們刪除掉上面yml 容忍配置重新部署,檢視結果:(可以看到只部署在節點2)
[root@k8smaster1 ~]# kubectl apply -f tolerations.yml deployment.apps/web created [root@k8smaster1 ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES web-65b7447c7-7s44v 1/1 Running 0 2s 10.244.2.16 k8snode2 <none> <none> web-65b7447c7-ch4f6 1/1 Running 0 2s 10.244.2.17 k8snode2 <none> <none>
補充: kubectl create 和 kubectl apply 區別
kubectl create命令可建立新資源。 因此,如果再次執行該命令,則會丟擲錯誤,因為資源名稱在名稱空間中應該是唯一的。
kubectl apply命令將配置應用於資源。 如果資源不在那裡,那麼它將被建立。 kubectl apply命令可以第二次執行,因為它只是應用如下所示的配置。 在這種情況下,配置沒有改變。 所以,pod沒有改變。
從執行的角度來看,在kubectl create和kubectl apply之間第一次建立資源時沒有區別。 但是,第二次kubectl create會丟擲錯誤。
例如: 使用yaml 建立一個namespace, create 多次執行報錯,apply 沒報錯
[root@k8smaster1 ~]# kubectl create -f new-namespace2.yaml namespace/new-namespace2 created [root@k8smaster1 ~]# kubectl create -f new-namespace2.yaml Error from server (AlreadyExists): error when creating "new-namespace2.yaml": namespaces "new-namespace2" already exists [root@k8smaster1 ~]# kubectl apply -f new-namespace2.yaml Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply namespace/new-namespace2 configured【當你用心寫完每一篇部落格之後,你會發現它比你用程式碼實現功能更有成就感!】