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 ~]# cat new-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. 節點調度

  kube-scheduler 是kubernetes 提供的調度器,它的主要作用是根據特定的調度算法和調度策略將pod 調度到合適的Node 節點上,是一個獨立的二進制程序,啟動之后會一直監聽API Server, 獲取到PodSpec.NodeName 為空的pod,對每個pod 都會創建一個binding。

調度主要分為以下幾個過程:

- 預選過程,過濾掉不滿足條件的節點,這個過程成為Predicates。 遍歷全部節點,過濾掉不滿足條件的節點,如果所有節點都不滿足,pod 出於pending 狀態,直到有節點滿足。

- 優選過程,對通過的節點按照優先級排序,稱之為 Priorities。 對節點再次篩選,如果有多個節點都滿足條件的話,按照節點的優先級 priorities 大小對節點進行排序,最后選擇優先級最高的節點來部署pod 應用。

(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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM