• 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
  • 相关阅读:
    python程序设计练习题:电子银行购物商城
    python -m参数
    Python 中的 if __name__ == 'main' 的作用和原理
    Modbus协议
    Python configparser模块
    Python logging 模块:日志处理
    python hashlib模块
    Python time模块:Python 日期和时间
    mac 使用系统的自带的quickTime录屏
    Linphone android3.2.4 采用率设置(模拟电话大网信道)
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/15792078.html
Copyright © 2020-2023  润新知