• kubernetes 管理Pod 资源对象


    想学习更多相关知识请看博主的个人博客地址:https://blog.huli.com/

    https://blog.huli.com/

    管理 Pod 资源对象

    Pod 是 Kubernetes 系统的基础单元,是资源对象模型中可由用户创建或部署的最小组件,也是在 kubernetes 系统上运行容器化应用的资源对象。其他的大多数资源对象都是用于支撑和扩展Pod对象功能的,例如,用于管控Pod运行的StatefulSet和Deployment等控制器对象,用于暴露Pod应用的Service和Ingress对象,为Pod提供存储的PersistentVolume存储资源对象等。这些资源对象大体可分为有限的几个类别,并且可基于资源清单作为资源配置文件进行陈述式或声明式管理。本章将描述这些类别,并详细介绍Pod资源的基础应用。

    1. 容器与 Pod 资源对象

    现代的容器技术被设计用来运行单个进程(包括子进程)时,该进程在容器中PID名称空间中的进程号为1,可直接接受并处理信号,于是,在此类进程终止时,容器即终止退出。若要在一个容器内运行多个进程,则需要为这些进程提供一个类似与Linux操作系统init进程的管控类进程,以树状结构完成多进程的生命周期管理,例如,崩溃后回收相应的系统资源等。单容器运行多进程时,通常还需要日志进程来管理这些进程的日志,例如,将它们分别保存于不同的目标日志文件等,否则用户就不得不手动来分拣日志信息。因此,绝大多数场景中都应该于一个容器中仅运行一个进程,它将日志信息直接输出至容器的标准输出,支持用户直接使用命令(kubectl logs)进程获取,这也是Docker 或 Kubernetes 使用容器的标准方式。

    不过,分别运行与各自容器的进程之间无法实现基于IPC的通信机制,此时,容器间的隔离机制对于依赖于此类通信方式的进程来说却又成为了障碍。Pod 资源抽象正是用来解决此类问题的组件,前文已然多次提到,Pod对象是一组容器的集合,这些容器共享 Network、UTS 及 IPC 名称空间,因此具有相同的域名、主机名和网络接口,并可通过IPC直接通信。为一个POD对象中的各容器提供网络名称空间等共享机制的是底层基础容器pause,图4-1所示为一个有三个容器组成的Pod资源,各容器共享Network、IPC和UTS名称空间,但分别拥有各自的MNT、USR和PID名称空间。需要特别强调的是,一个Pod对象中的多个容器必须运行于同一工作节点之上。

    尽管可以将Pod类比为物理机或VM,但一个Pod内通常仅应该运行一个应用,除非多个进程之间具有密切的关系。这也意味着,实践中应该将多个应用分别构建到多个而非单个Pod中,这样也更能符合容器的轻量化设计、运行之目的。

    例如,一个有着前端(application server)和后端(database server)的应用,其前、后端应该分别组织与各自的Pod中,而非同一个Pod的不同容器中。这样做的好处在于,多个Pod可被调度至多个不同的主机运行,提高了资源的利用率。另外,Pod也是Kubernetes进行系统规模伸缩的基础单元,分别运行与不同Pod的多个应用可独立按需求进行规模的变动,这就增强了系统架构的灵活性。事实上,前、后端应用的规模需求通常不会相同,而且无状态应用(application server)的规模变动也比有状态应用(database server)容易的多,将它们组织于同一个Pod中时将无法享受这种便利。

    不过,这些场景要求必须与同一Pod中同时运行多个容器。此时,这些分布式应用(尤其是微服务架构中的多个服务)必须遵守某些最佳实践机制或基本准则。事实上,Kubernetes 并非期望成为一个管理系统,而是一个支持这些最佳实践的向开发人员或管理人员提供更高级别服务的系统。分布式系统设计通常包含以下几种模型:

    1)Sidecar pattern(边车模型或跨斗模型):即为 Pod 的主应用容器提供协同的辅助应用容器,每个应用独立运行,最为典型的代表是将主应用容器中的日志使用agent收集至日志服务器中时,可以将 agent 运行为辅助应用容器,即 sidecar。另一个典型的应用是为主应用容器中的 database server 启用本地缓存,如图
    file

    2)Ambassador pattern(大使模型):即为远程服务创建一个本地代理,代理应用运行与容器中,主容器中的应用通过代理容器访问远程服务,如图4-3所示。一个典型的使用示例是主应用程序中的进程访问“一主多从”模型的远程Redis应用时,可在当前Pod容器中为Redis服务创建一个 Ambassador conteriner,主应用容器中的进程直接通过 localhost 接口访问 Ambassador container即可。即便是Redis主从集群架构发生变动时,也仅需要将 Ambassador container 加以修改即可,主应用容器无须对此做出任何反映。
    file

    3)Adapter pattern:(适配器模型):此种模型一般用于将主应容器中的内容进行标准化输出,例如,日志数据或指标数据的输出,这有助于调用者统一接收数据的接口,如果图 4-4 所示。另外,某应用滚动升级后的版本不兼容旧的版本时,其报告信息的格式也存在不兼容的可能性,使用 Adapter container 有助于避免那些调用此报告数据的应用发生错误。

    file

    Kubernetes 系统的Pod资源对象用于运行单个容器化应用,此应用称为Pod对象的主容器(main container),同时Pod也能够容纳多个容器,不过额外的容器一般工作为 Sidecar 模型,用于辅助主容器完成工作职能。

    2 . 管理 Pod 对象的容器

    一个Pod对象中至少要存在一个容器,因此,containers 字段是定义 Pod 时其嵌套字段 Spec 中的必选项,用于为 Pod 指定要创建的容器列表。进行容器配置时,name为必选字段,用于指定容器名称,image字段是为可选,以方便更高级别的管理类资源(如Deployment)等能覆盖此字段,于是自主式的Pod并不可省略此字段。因此,定义一个容器的基础框架如下:

    name: CONTAINER_NAME
    image: IMAGE_FILE_NAME
    

    此外,定义容器时还有一些其他常用的字段,例如,定义要暴露的端口、改变镜像运行的默认程序、传递环境变量、定义可用的系统资源配额等。

    2.1 镜像及其获取策略

    各工作节点负责运行Pod对象,而Pod的核心功用在于运行容器,因此工作节点上必须配置容器运行引擎,如Docker等。启动容器时,容器引擎将首先于本地查找指定的镜像文件,不存在的镜像则需要从指定的镜像仓库(Registry)下载至本地,如图
    file

    Kubernetes 系统支持用户自定义镜像文件的获取策略,例如在网络资源较为紧张的情况下可以禁止从仓库中获取镜像文件等。容器的“imagePullPolicy”字段用于为其指定镜像获取策略,它的可用值包括如下几个。

    • Always:镜像标签为“latest”或镜像不存在时总是从指定的仓库中获取镜像。
    • ifNotPresent:仅当本地镜像缺失时方才从目标仓库下载镜像。
    • Never:禁止从仓库下载镜像,仅使用本地镜像。

    下面的资源清单中的容器定义了如何使用 nginx:latest 镜像,其获取策略为 Always,这意味着每次启动容器时,他都会到镜像仓库中获取最新版本的镜像文件:

    apiVersion: v1
    kind: Pod
    metadata:
        name: nginx-pod
    spec:
        containers:
        - name: nginx
          image: nginx:latest
          imagePullPolicy: Always
    

    对于标签为“latest”的镜像文件,其默认的镜像策略即为“always”,而对于其他标签的镜像,其默认策略则为“IfNotPresent”。需要注意的是,使用私有仓库中的镜像时通常需要由 Registry 服务器完成认证后才能进行。认证过程要么需要在相关节点上交互式执行 docker login 命令来进行,要么就是将认证信息定义为专有的 Secret 资源,并配置 Pod 通过“imagePullSecrets”字段调用此认证信息完成。

    2.2 暴露端口

    Docker 的网络模型中,使用默认网络的容器化应用需要通过NAT机制将其“暴露”(expose)到外部网络中才能被其他节点之上的容器客户端所访问。然而,Kubernetes 系统的网络模型中,各 Pod 的 IP 地址处于同一网络平面,无论是否为容器指定了要暴露的端口,都不会影响集群中其他节点之上的Pod客户端对其进行访问,这就意味着,任何监听在非lo接口上的端口都可以通过Pod网络直接被请求。从这个角度来说,容器端口只是信息性数据,它只是为集群用户提供了一个快速了解相关Pod对象的可访问端口的途径,而且显式指定容器端口,还能为其赋予一个名称以方便调用。

    容器的 ports 字段的值是一个列表,由一到多个端口对象组成,它的常用嵌套字段包括如下几个。

    • containerPort <intrger>:必选字段,指定在Pod对象的IP地址上暴露的容器端口,有效范围为(0, 65536);使用时,应该总是指定容器应用正常监听着的端口。
    • name <string>:当前端口的名称,必须符合 IANA_SVC_NAME 规范且在当前 Pod 内必须是唯一的;此端口名可被 Service 资源调用。
    • protocol:端口相关的协议,其值仅可为TCP或UDP,默认为TCP。

    下面的资源配置清单示例(pod-example-with-port.yaml)中定义的 pod-example 指定了要暴露容器上 TCP 的 80 端口,并将之命令为 http:

    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-example
    spec:
        containers:
        - name: myapp
          image: ikubernetes/myapp:v1
          ports:
          - name: http
            containerPort: 80
            protocol: TCP
    

    然而,Pod 对象的IP地址仅在当前集群内可达,它们无法直接接收来自集群外部客户端的请求流量,尽管它们的服务可达性不受工作节点边界的约束,但依然受制于集群边界。一个简单的解决方案是通过其所在的工作节点的IP地址和端口将其暴露到集群外部,如图
    file

    • hostPort <integer>:主机端口,它将接收到的请求通过NAT机制转发至由 containerPort 字段指定的容器接口。
    • hostIP <string>:主机端口要绑定的主机IP,默认为 0.0.0.0,即主机之上所有可用的IP地址;考虑到托管的Pod对象是由调度器调度运行的,工作节点的IP地址难以明确指定,因此此字段通常使用默认值。

    需要注意的是,hostPort 和 NodePort 类型的 Service 对象暴露端口的方式不同,NodePort 是通过所有节点暴露容器服务,而 hostPort 则是经由 Pod 对象所在的节点的IP地址来进行。

    2.3 自定义运行的容器化应用

    由 Docker 镜像启动容器时运行的应用程序在相应的 Dockerfile 中由 ENTRYPOINT 指令进行定义,传递给程序的参数则通过 CMD 指令指定,ENTRYPOINT 指令不存在时,CMD 可用于同时指定程序及其参数。容器的 command 字段能够指定不同于镜像默认运行的应用程序,并且可以同时使用 args 字段进行参数传递,它们将覆盖镜像中定义的程序及参数,并以无参数方式运行应用程序。例如下面的资源清单文件将镜像 ikubernetes/myapp:v1 的默认应用程序修改为了 “/bin/sh”,传递应用的参数修改为了 “-c while true; do sleep 30; done”:

    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-with-custom-command
    spec:
        containers:
        - name: myapp
          image: alpine:latest
          command: ["/bin/sh"]
          args: ["-c", "while true; do sleep 30; done"]
    

    自定义args,也是向容器中的应用程序传递配置信息的常用方式之一,对于非云原生(cloud native)的应用程序,这几乎也是最简单的配置方式。另一个常用的方式是使用环境变量。

    2.4 环境变量

    非容器化的传统管理方式中,复杂应用程序的配置信息多数由配置文件进行指定,用户可借助于简单的文本编辑器完成配置管理。然而,对于容器隔离出的环境中的应用程序,用户就不得不穿透容器边界在容器内进行配置编辑并进行重载,这种方式复杂且低效。于是,有环境变量在容器启动时传递配置信息就成为一种备受青睐的方式。

    这种方式依赖于应用程序支持通过环境变量进行配置的能力,否则,用户在制作 Docker 镜像时需要通过 entrypoint 脚本完成环境变量到程序配置文件的同步。

    向 Pod 对象中的容器环境变量传递数据的方法有两种:env 和 envFrom,这里重点介绍第一种方式,第二种方式将在介绍ConfigMap 和 Sescrt 资源时进行说明。

    通过环境变量配置容器化应用时,需要在容器配置段中嵌套使用 env 字段,他的值是一个由环境变量构成的列表。环境变量通常由 name 和 value 字段构成。

    • name <string>:环境变量的名称,必选字段。
    • value <string>:传递给环境变量的值,通过$(VAR_NAME)引用,逃逸格式为“$$(VAR_NAME)”,默认值为空。

    下面配置清单中定义的Pod对象为其容器 filebeat 传递了两个环境变量,REDIS_HOST 定义了 filebeat 收集的日志信息要发往的 Redis 主机地址,LOG_LEVEL 则定义了 filebeat 的日志级别:

    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-with-env
    spec:
        containers:
        - name: filebeat
          image: filebeat:5.6.5-alpine
          env:
          - name: REDIS_HOST
            value: db.ilinux.io:6379
          - name: LOG_LEVEL
            value: info
    

    这些环境变量可直接注入容器的 shell 环境中,无论它们是否真正被用到,使用 printenv 一类的命令都能在容器中获取到所有环境变量的列表。

    2.5 共享节点的网络名称空间

    同一个 Pod 对象的各容器均运行于一个独立的、隔离的 Network 名称空间中,共享同一个网络协议栈及相关的网络设备

    通常,以Kubeadm 部署的 Kubernetes 集群中的 kube-apiserver、kube-controller-manager、kube-scheduler,以及 kube-proxy 和 kube-flannel 等通常都是第二种类型的Pod对象。事实上,仅需要设置 spec.hostNetwork 的属性为 true 即可创建共享节点网络名称空间的 Pod 对象,如下面的配置清单所示:

    apiVersion: v1
    kind: Pod
    metadata: 
        name: pod-use-hostnetwork
    spec:
        containers:
        - name: myapp
          image: ikubernetes/myapp:v1
        hostNetwork: true
    

    将上面的配置清单保存与配置文件中,如 pod-use-hostnetwork.yaml,将其创建与集群上,并查看其网络接口的相关属性信息以验证它是否能共享使用工作节点的网络名称空间:

    $ kubectl apply -f pod-use-hostnetwork.yaml
    pod/pod-use-hostnetwork created
    $ kubectl exec -it pod-use-hostnetwork -- sh
    / # ifconfig 
    cni0      Link encap:Ethernet  HWaddr 72:C6:CF:37:34:8C  
              inet addr:10.244.3.1  Bcast:0.0.0.0  Mask:255.255.255.0
              inet6 addr: fe80::70c6:cfff:fe37:348c/64 Scope:Link
              UP BROADCAST MULTICAST  MTU:1500  Metric:1
              RX packets:276 errors:0 dropped:0 overruns:0 frame:0
              TX packets:286 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000 
              RX bytes:19983 (19.5 KiB)  TX bytes:35428 (34.5 KiB)
    
    docker0   Link encap:Ethernet  HWaddr 02:42:5C:E0:08:C5  
              inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
              UP BROADCAST MULTICAST  MTU:1500  Metric:1
              RX packets:0 errors:0 dropped:0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
    
    ens192    Link encap:Ethernet  HWaddr 00:0C:29:AD:A8:D2  
              inet addr:192.168.0.183  Bcast:192.168.0.255  Mask:255.255.255.0
              inet6 addr: fe80::20c:29ff:fead:a8d2/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:3235233 errors:0 dropped:1 overruns:0 frame:0
              TX packets:2402001 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000 
              RX bytes:1594050628 (1.4 GiB)  TX bytes:237476297 (226.4 MiB)
    
    flannel.1 Link encap:Ethernet  HWaddr 36:4D:70:4C:69:47  
              inet addr:10.244.3.0  Bcast:0.0.0.0  Mask:255.255.255.255
              inet6 addr: fe80::344d:70ff:fe4c:6947/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
              RX packets:237 errors:0 dropped:0 overruns:0 frame:0
              TX packets:232 errors:0 dropped:8 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:28098 (27.4 KiB)  TX bytes:17586 (17.1 KiB)
    
    lo        Link encap:Local Loopback  
              inet addr:127.0.0.1  Mask:255.0.0.0
              inet6 addr: ::1/128 Scope:Host
              inet6 addr: ::1/128 Scope:Host
              UP LOOPBACK RUNNING  MTU:65536  Metric:1
              RX packets:1338 errors:0 dropped:0 overruns:0 frame:0
              TX packets:1338 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000 
              RX bytes:81611 (79.6 KiB)  TX bytes:81611 (79.6 KiB)
    

    如上述命令的结果显示所示,它打印出的工作节点的网络设备及其相关的接口信息。这就意味着,Pod 对象中运行的容器化应用也将监听与其所在的工作节点的IP地址之上,这可以通过直接向 kube-node-2.localdomain 节点发起请求来验证:

    curl kube-node-2.localdomain
    

    另外,在 Pod 对象中时还可以分别使用 spec.hostPID 和 spec.hostIPC 来共享工作节点的PID和IPC名称空间。

    2.6 设置 Pod 对象的安全上下文

    Pod 对象的安全上下文用于设定 Pod 或容器的权限和访问控制功能,其支持设置的常用属性包括以下几个方面:

    • 基于用户ID(UID)和组ID(GID)控制访问对象(如文件)时的权限。
    • 以特权或非特权的方式运行。
    • 通过Linux Capabilities为其提供部分特征。
    • 基于 Seccomp 过滤进程的系统调用。
    • 基于 SELinux 的安全标签。
    • 是否能够进行权限升级。

    Pod 对象的安全上下文定义在 spec.securityContext 字段中,而容器的安全上下文则定义在 spec.containers[].securityContext 字段中,且二者可嵌套使用的字段还有所不同。下面的配置清单示例为 busybox 容器定义了安全上下文,它以 uid 为 1000 的非特权用户运行容器,并禁止权限升级:

    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-with-securitycontext
    spec:
        containers:
        - name: busybox
          image: busybox
          command: ["/bin/sh", "-c", "sleep 86400"]
          securityContext:
            runAsNonRoot: true
            runAsUser: 1000
            allowPrivilegeEscalation: false
    

    将上面的配置清单保存与配置文件(如 pod-with-securitycontext.yaml 文件)中,而后创建于集群中即可验证容器进程的运行者身份:

    (base) [root@liuxinyuan-master ~]$ kubectl apply -f pod-with-securitycontext.yaml
    (base) [root@liuxinyuan-master ~]$ exec pod-with-securitycontext -- ps aux
    PID   USER     TIME  COMMAND
        1 1000      0:00 sleep 86400
        6 1000      0:00 ps aux
    

    另外,可设置的安全上下文属性还有 fsGroup、seLinuxOptions、supplementalGroups、sysctls、capabilities 和 privileged 等,且 Pod 和容器各自支持的字段也有所不同,感兴趣的读者可按需对各属性进行测试。

    3. 标签与标签选择器

    实践中,随着同类资源对象的数量越来越多,分类管理也变得越来越有必要:基于简单且直接的标准将资源对象划分为多个比较小的分组,无论是对开发人员还是对系统工程师来说,都能提升管理效率,这也正是 Kubernetes 标签(Label)的核心功能之一。对于附带标签的资源对象,可使用标签选择器(Label Selector)挑选出符合过滤条件的资源以完成所需要的操作,如关联、查看和删除等。

    3.1 标签概述

    标签是 kubernetes 极具特色的功能之一,它能够附加于 Kubernetes 的任何资源对象之上。简单来说,标签就是“键值”类型的数据,它们可于资源创建时直接指定,也可随时按需添加于活动对象之中,而后即可由标签选择器进行匹配检查从而完成资源挑选。一个对象可拥有不止一个标签,而同一个标签也可以被添加至多个资源之上。

    实践中,可以为资源附加多个不同维度的标签以实现灵活的资源分组管理功能,例如,版本标签、环境标签、分层架构标签等,用于交叉标示同一个资源所属的不同版本、环境及架构层级等,如图 4-8 所示。下面是较为常用的标签。

    • 版本标签:"release": "stable", "release": "canary", "release": "beta"
    • 环境标签:"envionmrnt": "dev", "environment": "qa", "environment": "production"
    • 应用标签:"app": "ui", "app": "as", "app": "pc", "app": "sc"
    • 架构层级标签:"tier": "frontend", "tier": "backend", "tier": "cache"
    • 分区标签:"partition": "customerA", "partition": "customerB"
    • 品控级别标签:"track": "daily", "track": “weekly”

    标签中的键名称通常由键前缀和和键名组成,其中键前缀可选,其格式形如“KEY_PREFIX/KEY_NAME”。键名至多只能使用63个字符,可使用字母、数字、连接号(-)、下划线(_)、点号(.)等字符,并且只能以字母或数字开头。键前缀必须为DNS子域名格式,且不能超过 253 个字符。省略键前缀时,键将被视为用户的私有数据,不过由 Kubernetes 系统组件或第三方组件自动为用户资源添加的键必须使用键前缀,而“kubernetes.io”前缀则预留给 Kubernetes 的核心组件使用。

    标签中的键值必须不能多于 63 个字符,它要么为空,要么是以字母或数字开头及结尾,且中间仅使用字母、数字、连接号(-)、下划线(_)或点号(.)等字符的数据。

    实践中,建议键名及键值能做到“见名知义”,且尽可能保持简单。

    3.2 管理资源标签

    创建资源时,可直接在其 metadata 中嵌套使用 “labels” 字段以定义要附加的标签项。例如,下面的 Pod 资源清单文件示例 pod-with-labels.yaml 中使用了两个标签 env=qa 和 tier=frontend:

    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-with-labels
        labels:
            env: qa
            tier: frontend
    spec:
        containers:
        - name: myapp
          image: ikubernetes/myapp:v1
    

    基于此资源清单创建出定义的Pod对象之后,即可在“kubectl get pods”命令中使用“--show-labels”选项,以额外显示对象的标签信息:

    (base) [root@liuxinyuan-master ~]$ kubectl apply -f pod-with-labels.yaml
    pod/pod-with-labels created
    (base) [root@liuxinyuan-master ~]$ kubectl get pods --show-labels
    NAME                       READY   STATUS    RESTARTS   AGE    LABELS
    pod-example                1/1     Running   1          2d4h   <none>
    pod-with-labels            1/1     Running   0          32s    env=qa,tier=frontend
    

    “kubectl label” 命令可以直接管理活动对象的标签,以按需进行添加或修改等操作

    kubectl label pods/pod-example env=production
    

    不过,对于已经附带了指定键名的标签,使用“kubectl label” 为其设定新的键值时需要为命令同时使用 “--overwrite” 命令以强制覆盖原有的键值。例如,将 pod-with-labels 的 env 的值修改为 “testing”:

     (base) [root@liuxinyuan-master ~]kubectl label pods/pod-with-labels env=testing --overwrite
    pod/pod-with-labels labeled
    

    用户若期望某标签之下的资源集合执行某类操作,例如,查看或删除等,则需要先使用“标签选择器”挑选出满足条件的资源对象。

    3.3 标签选择器

    标签选择器用于表达标签的查询条件或选择标准,Kubernetes API 目前支持两个选择器:基于等值关系(equality-based)以及基于集合关系(set-based)。例如,env=production 和 env!=qa 是基于等值关系的选择器,而 tier in (frontend, backend)则是基于集合关系的选择器。另外,使用标签选择器时还将遵循以下逻辑。

    1. 同时指定的多个选择器之间的逻辑关系为“与”操作。
      2)使用空值的标签选择器意味着每个资源对象都将被选中。
      3)空的标签选择器将无法选出任何资源。

    基于等值关系的标签选择器的可用操作符有“=”“==”和“!=”三种,其中前两个意义相同,都表示“等值”关系,最后一个表示“不等”关系。“kubectl get”命令的“-l”选项能够指定使用标签选择器,例如,显示键名 env 的值不为qa的所有Pod对象:

    kubectl get pods -l "env!=qa" -L env
    NAME                       READY   STATUS    RESTARTS   AGE     ENV
    pod-example                1/1     Running   1          2d19h   production
    pod-with-labels            1/1     Running   0          15h     testing
    

    再例如,显示标签键名 env 的值不为 qa,且标签键名 tier 的职为 frontend 的所有 Pod 对象:

    kubectl get pods -l "env!=qa,tier=frontend" -L env,tier
    NAME              READY   STATUS    RESTARTS   AGE   ENV       TIER
    pod-with-labels   1/1     Running   0          15h   testing   frontend
    

    基于集合关系的标签选择器支持 in、notin 和 exists 三种操作符,它们的使用格式及意义具体如下。

    • KEY in (VALUE1, VALUE2, ...):指定的键名的值存在于给定的列表中即满足条件。
    • KEY notin (VALUE1, VALUE2, ...):指定的键名的值不存在与给定的列表中即满足条件。
    • KEY:所有存在此键名标签的资源。
    • !KEY:所有不存在此键名标签的资源。

    例如,显示标签键名 env 的值为 production 或 env 的所有 Pod 对象:

    $ kubectl get pods -l "env in (production,dev)" -L env
    NAME          READY   STATUS    RESTARTS   AGE     ENV
    pod-example   1/1     Running   1          2d19h   production
    

    再如,列出标签键名 env 的值为 production 或 dev,且不存在键名为 tier 的标签的所有 Pod 对象:

    $ kubectl get pods -l 'env in (production,dev),!tier' -L env,tier
    NAME          READY   STATUS    RESTARTS   AGE     ENV          TIER
    pod-example   1/1     Running   1          2d19h   production
    

    为了避免shell解释器解析惊叹号(!),必须要为此类表达式使用单引号。

    此外,Kubernetes 的诸多资源对象必须以标签选择器的方式关联到Pod资源对象,例如 Service、Deployment 和 ReplicaSet 类型的资源等,它们在 spec 字段中嵌套使用嵌套的 “selector” 字段,通过“matchLabels”来指定标签选择器,有的甚至还支持使用“matchExperssions”构造复杂的标签选择机制。

    • matchLabels:通过直接给定键值对来指定标签选择器。
    • matchExpressions:基于表达式指定的标签选择器列表,每个选择器都形如 “{key:KEY_NAME, operator: OPERATOR, values: [VALUE1, VALUE2, ...]}”,选择器列表间为“逻辑与”关系;使用 In 或 NotIn 操作符时,其 values 不强制要求为非空的字符串列表,而使用 Exists 或 DostNotExist 时,其 values 必须为空。

    下面所示的资源清单片段是一个示例,它同时定义了两类标签选择器:

    selector:
      matchLabels:
        component: redis
      matchExpressions:
        - {key: tier, operator: In, values: [cache]}
        - {key: environment, operator: Exists, values:}
    

    标签赋予了 Kubernetes 灵活操作资源对象的能力,它也是 Service 和 Deployment 等核心资源类型得以实现的基本前提。

    3.4 Pod 节点选择器 nodeSelector

    Pod 节点选择器是标签及标签选择器的一种应用,它能够让 Pod 对象基于集群中工作节点的标签来挑选倾向运行的目标节点。

    Kubernetes 的 kube-scheduler 守护进程负责在各工作节点中基于系统资源的可用性等标签挑选一个来运行创建的 Pod 对象,默认的调度器是 default-scheduler。Kubernetes 可将所有工作节点上的各系统资源抽象成资源池统一分配使用,因此用户无须关心Pod对象的具体运行位置也能良好工作。不过,事情总有例外,比如仅有部分节点拥有Pod对象依赖到的特殊硬件设备的情况,如GPU和SSD等。即便如此,用户也不应该静态指定Pod对象的运行位置,而是让 scheduler 基于标签和标签选择器为 Pod 用户挑选匹配的工作节点。

    Pod 对象的 spec.nodeSelector 可用于定义节点标签选择器,用户事先为特定部分的 Node 资源对象设定好标签,而后配置 Pod 对象通过节点标签选择器进行匹配检测,从而完成节点亲和性调度。

    如果某 Pod 资源需要调度至这些具有 SSD 设备的节点之上,那么只需要为其使用 spec.nodeSelector 标签选择器即可,例如下面的资源清单文件 pod-with-nodeselector.yaml 示例:

    apiVersion: v1
    kind: Pod
    metadata:
        name: pod-with-nodeselector
        lables:
            env: testing
    spec:
        containers:
        - name: myapp
          image: ikubernetes/myapp:v1
        nodeSelector:
            disktype: ssd
    

    将如上资源清单中定义的 Pod 资源创建于集群中,通过检查其运行的节点即可判定调度效果

    另外,手动测试和查看节点标签的读者或许已经注意到了,集群中的每个节点默认已经附带了多个标签,如 kubernetes.io/hostname、beta.kubernetes.io/os 和 beta.kubernetes.io/arch 等,这些标签也可以直接由 nodeSelector 使用,尤其是希望将 Pod 调度至某特定节点时,可以使用 kubernetes.io/hostname 直接绑定至相应的主机即可。不过,这种绑定至特定主机的需求还有一种更为简单的实现方式,即使用 spec.nodeName 字段直接指定目标节点。

  • 相关阅读:
    (OK) 编译cBPM-android—CentOS 7—NDK8—androideabi-4.7— API14
    (OK) 编译xerces-c-3.1.2(动态库)—CentOS 7— android-ndk
    (OK) 编译libiconv-1.14(静态库)—CentOS 7— android-ndk
    (OK) 编译xerces-c-3.1.2(静态库)—CentOS 7— android-ndk
    (OK) 在Android系统上运行C/C++程序
    (OK—C++程序) CodeBlocks — CentOS 7 + android-ndk
    (OK) CentOS7 安装 Codeblocks
    (OK—C++程序) Eclipse C/C++ — CentOS 7 + android-ndk + eclipse-cpp-mars-R
    (OK) CentOS 7 + android-ndk-r10d-linux-x86_64 + Android (ARM)—ndk-build
    (OK—C程序) Eclipse C/C++ — CentOS 7 + android-ndk + eclipse-cpp-mars-R
  • 原文地址:https://www.cnblogs.com/precipitation/p/15980975.html
Copyright © 2020-2023  润新知