跳转至

基础用法

标签和选择算符

标签(Labels) 是附加到 Kubernetes 对象(比如 Pod)上的键值对。 标签旨在用于指定对用户有意义且相关的对象的标识属性,但不直接对核心系统有语义含义。 标签可以用于组织和选择对象的子集。标签可以在创建时附加到对象,随后可以随时添加和修改。 每个对象都可以定义一组键/值标签。每个键对于给定对象必须是唯一的。

JSON
1
2
3
4
5
6
"metadata": {
  "labels": {
    "key1" : "value1",
    "key2" : "value2"
  }
}

标签能够支持高效的查询和监听操作,常用于Log支持

动机

标签使用户能够以 松散耦合 的方式将他们自己的组织结构映射到系统对象,而无需客户端存储这些映射。

服务部署和批处理流水线通常是多维实体(例如,多个分区或部署、多个发行序列、多个层,每层多个微服务)。 管理通常需要交叉操作,这打破了严格的层次表示的封装,特别是由基础设施而不是用户确定的严格的层次结构。

示例标签:

  • "release" : "stable""release" : "canary"
  • "environment" : "dev""environment" : "qa""environment" : "production"
  • "tier" : "frontend""tier" : "backend""tier" : "cache"
  • "partition" : "customerA""partition" : "customerB"
  • "track" : "daily""track" : "weekly"

有一些常用标签的例子;你可以任意制定自己的约定。 请记住,标签的 Key 对于给定对象必须是唯一的。

语法和字符集

标签是键值对。有效的标签键有两个段:可选的前缀和名称,用斜杠(/)分隔。

名称段是必需的,必须小于等于 63 个字符,以字母数字字符([a-z0-9A-Z])开头和结尾, 带有破折号(-),下划线(_),点( .)和之间的字母数字。

前缀是可选的。如果指定,前缀必须是 DNS 子域:由点(.)分隔的一系列 DNS 标签,总共不超过 253 个字符, 后跟斜杠(/)。

如果省略前缀,则假定标签键对用户是私有的。

向最终用户对象添加标签的 自动系统组件(例如 kube-schedulerkube-controller-manager、 kube-apiserverkubectl 或其他第三方自动化工具)必须指定前缀

例如,以下是一个清单 (manifest),适用于具有 environment: production 和 app: nginx 这两个标签的 Pod:

YAML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: v1
kind: Pod
metadata:
  name: label-demo
  labels:
    environment: production
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

标签选择算符

名称和 UID 不同, 标签不支持唯一性。通常,我们希望许多对象携带相同的标签。

通过标签选择算符,客户端/用户可以识别一组对象。标签选择算符是 Kubernetes 中的核心分组原语。API 目前支持两种类型的选择算符:基于等值的基于集合的

标签选择算符可以由逗号分隔的多个需求组成。 在多个需求的情况下,必须满足所有要求,因此逗号分隔符充当逻辑&&)运算符。

基于等值的需求

基于等值基于不等值的需求允许按标签键和值进行过滤。

匹配对象必须满足所有指定的标签约束,尽管它们也可能具有其他标签。 可接受的运算符有 === 和 != 三种。 前两个表示相等(并且是同义词),而后者表示不相等。例如:

YAML
1
2
environment = production
tier != frontend
  • 前者选择所有资源,其键名等于 environment,值等于 production
  • 后者选择所有资源,其键名等于 tier,值不同于 frontend or 所有资源都没有带有 tier 键的标签。

可以使用逗号运算符来过滤 production 环境中的非 frontend 层资源:environment=production,tier!=frontend

基于等值的标签要求的一种使用场景是 Pod 要指定节点选择标准。 例如,下面的示例 Pod 选择带有标签 "accelerator=nvidia-tesla-p100"。

YAML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: v1
kind: Pod
metadata:
  name: cuda-test
spec:
  containers:
    - name: cuda-test
      image: "registry.k8s.io/cuda-vector-add:v0.1"
      resources:
        limits:
          nvidia.com/gpu: 1
  nodeSelector:
    accelerator: nvidia-tesla-p100

基于集合的需求

基于集合的标签需求允许你通过一组值来过滤键。 支持三种操作符:innotin 和 exists(只可以用在键标识符上)。例如:

Text Only
1
2
3
4
environment in (production, qa)
tier notin (frontend, backend)
partition
!partition
  • 第一个示例选择了所有键等于 environment 并且值等于 production 或者 qa 的资源。
  • 第二个示例选择了所有键等于 tier 并且值不等于 frontend 或者 backend 的资源,以及所有没有 tier 键标签的资源。
  • 第三个示例选择了所有包含了有 partition 标签的资源;没有校验它的值。
  • 第四个示例选择了所有没有 partition 标签的资源;没有校验它的值。

类似地,逗号分隔符充当 运算符。

因此,使用 partition 键(无论为何值)和 environment 不同于 qa 来过滤资源可以使用 partition, environment notin (qa) 来实现。

有效地使用标签

到目前为止我们使用的示例中的资源最多使用了一个标签。 在许多情况下,应使用多个标签来区分不同集合。

例如,不同的应用可能会为 app 标签设置不同的值。 但是,类似 guestbook 示例 这样的多层应用,还需要区分每一层。前端可能会带有以下标签:

YAML
1
2
3
labels:
  app: guestbook
  tier: frontend

Redis 的主从节点会有不同的 tier 标签,甚至还有一个额外的 role 标签:

YAML
1
2
3
4
labels:
  app: guestbook
  tier: backend
  role: master

以及

YAML
1
2
3
4
labels:
  app: guestbook
  tier: backend
  role: replica

标签使得我们能够按照所指定的任何维度对我们的资源进行切片和切块:

Bash
1
2
kubectl apply -f examples/guestbook/all-in-one/guestbook-all-in-one.yaml
kubectl get pods -Lapp -Ltier -Lrole
Text Only
1
2
3
4
5
6
7
8
9
NAME                           READY  STATUS    RESTARTS   AGE   APP         TIER       ROLE
guestbook-fe-4nlpb             1/1    Running   0          1m    guestbook   frontend   <none>
guestbook-fe-ght6d             1/1    Running   0          1m    guestbook   frontend   <none>
guestbook-fe-jpy62             1/1    Running   0          1m    guestbook   frontend   <none>
guestbook-redis-master-5pg3b   1/1    Running   0          1m    guestbook   backend    master
guestbook-redis-replica-2q2yf  1/1    Running   0          1m    guestbook   backend    replica
guestbook-redis-replica-qgazl  1/1    Running   0          1m    guestbook   backend    replica
my-nginx-divi2                 1/1    Running   0          29m   nginx       <none>     <none>
my-nginx-o0ef1                 1/1    Running   0          29m   nginx       <none>     <none>
Bash
1
kubectl get pods -lapp=guestbook,role=replica
Text Only
1
2
3
NAME                           READY  STATUS   RESTARTS  AGE
guestbook-redis-replica-2q2yf  1/1    Running  0         3m
guestbook-redis-replica-qgazl  1/1    Running  0         3m

更新标签

有时需要要在创建新资源之前对现有的 Pod 和其它资源重新打标签。 这可以用 kubectl label 完成。 例如,如果想要将所有 NGINX Pod 标记为前端层,运行:

Bash
1
kubectl label pods -l app=nginx tier=fe
Text Only
1
2
3
pod/my-nginx-2035384211-j5fhi labeled
pod/my-nginx-2035384211-u2c7e labeled
pod/my-nginx-2035384211-u3t6x labeled

首先用标签 "app=nginx" 过滤所有的 Pod,然后用 "tier=fe" 标记它们。 想要查看你刚设置了标签的 Pod,请运行:

Bash
1
kubectl get pods -l app=nginx -L tier
Text Only
1
2
3
4
NAME                        READY     STATUS    RESTARTS   AGE       TIER
my-nginx-2035384211-j5fhi   1/1       Running   0          23m       fe
my-nginx-2035384211-u2c7e   1/1       Running   0          23m       fe
my-nginx-2035384211-u3t6x   1/1       Running   0          23m       fe

此命令将输出所有 "app=nginx" 的 Pod,并有一个额外的描述 Pod 所在分层的标签列 (用参数 -L 或者 --label-columns 标明)。

将 Pod 分配给节点

如何将 Kubernetes Pod 指派给 Kubernetes 集群中的特定节

你必须拥有一个 Kubernetes 的集群,且必须配置 kubectl 命令行工具让其与你的集群通信。 建议运行本教程的集群至少有两个节点,且这两个节点不能作为控制平面主机。

显示当前cluster中的全部节点

input format

Bash
1
kubectl get nodes --show-labels

output format

Bash
1
2
3
4
5
```shell
NAME      STATUS    ROLES    AGE     VERSION        LABELS
worker0   Ready     <none>   1d      v1.13.0        ...,kubernetes.io/hostname=worker0/os=.../instance-type=.../zone-id...
worker1   Ready     <none>   1d      v1.13.0        ...,kubernetes.io/hostname=worker1/os=.../instance-type=.../zone-id...
worker2   Ready     <none>   1d      v1.13.0        ...,kubernetes.io/hostname=worker2/os=.../instance-type=.../zone-id...

example

Bash
1
2
3
4
5
NAME                           STATUS   ROLES    AGE    VERSION               LABELS

ip-172-31-12-35.ec2.internal   Ready    <none>   175m   v1.30.0-eks-036c24b   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=t3.medium,beta.kubernetes.io/os=linux,eks.amazonaws.com/capacityType=ON_DEMAND,eks.amazonaws.com/nodegroup-image=ami-07a09baf6da06052d,eks.amazonaws.com/nodegroup=MyEKS-nodegroup,failure-domain.beta.kubernetes.io/region=us-east-1,failure-domain.beta.kubernetes.io/zone=us-east-1a,k8s.io/cloud-provider-aws=b4978bee27209bc5dec03989be19a7a9,kubernetes.io/arch=amd64,kubernetes.io/hostname=ip-172-31-12-35.ec2.internal,kubernetes.io/os=linux,node.kubernetes.io/instance-type=t3.medium,topology.k8s.aws/zone-id=use1-az1,topology.kubernetes.io/region=us-east-1,topology.kubernetes.io/zone=us-east-1a

ip-172-31-75-70.ec2.internal   Ready    <none>   174m   v1.30.0-eks-036c24b   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=t3.medium,beta.kubernetes.io/os=linux,eks.amazonaws.com/capacityType=ON_DEMAND,eks.amazonaws.com/nodegroup-image=ami-07a09baf6da06052d,eks.amazonaws.com/nodegroup=MyEKS-nodegroup,failure-domain.beta.kubernetes.io/region=us-east-1,failure-domain.beta.kubernetes.io/zone=us-east-1f,k8s.io/cloud-provider-aws=b4978bee27209bc5dec03989be19a7a9,kubernetes.io/arch=amd64,kubernetes.io/hostname=ip-172-31-75-70.ec2.internal,kubernetes.io/os=linux,node.kubernetes.io/instance-type=t3.medium,topology.k8s.aws/zone-id=use1-az5,topology.kubernetes.io/region=us-east-1,topology.kubernetes.io/zone=us-east-1f

可以清晰的看出,我的cluster内有两个节点:

  • ip-172-31-12-35.ec2.internal
  • ip-172-31-75-70.ec2.internal

它们的标签分别是后面那一长串...

为节点添加标签

从你的节点中选择一个,为它添加标签

比如我想命令 ip-172-31-12-35.ec2.internal 这个节点的硬盘存储是ssd类型

input format

Bash
1
kubectl label nodes ip-172-31-12-35.ec2.internal disktype=ssd

output format

example

Bash
1
2
 kubectl label nodes ip-172-31-12-35.ec2.internal disktype=ssd
node/ip-172-31-12-35.ec2.internal labeled
Bash
1
2
3
4
5
 kubectl get nodes --show-labels

# 现在它的label集合变成:

beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=t3.medium,beta.kubernetes.io/os=linux,disktype=ssd,eks.amazonaws.com/capacityType=ON_DEMAND,eks.amazonaws.com/nodegroup-image=ami-07a09baf6da06052d,eks.amazonaws.com/nodegroup=MyEKS-nodegroup,failure-domain.beta.kubernetes.io/region=us-east-1,failure-domain.beta.kubernetes.io/zone=us-east-1a,k8s.io/cloud-provider-aws=b4978bee27209bc5dec03989be19a7a9,kubernetes.io/arch=amd64,kubernetes.io/hostname=ip-172-31-12-35.ec2.internal,kubernetes.io/os=linux,node.kubernetes.io/instance-type=t3.medium,topology.k8s.aws/zone-id=use1-az1,topology.kubernetes.io/region=us-east-1,topology.kubernetes.io/zone=us-east-1a

注意到的确多了,disktype=ssd,,说明<label>的添加成功

创建一个将被调度到你选择的节点的 Pod

标签筛选

此 Pod 配置文件描述了一个拥有节点选择器 disktype: ssd 的 Pod。这表明该 Pod 将被调度到有 disktype=ssd 标签的节点

YAML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: v1         # 使用的 Kubernetes API 版本
kind: Pod              # 资源类型是 Pod
metadata:              # 元数据
  name: nginx          # Pod 的名称是 nginx
  labels:              # Pod 的标签
    env: test          # 标签为 env=test,表示环境是测试类型
spec:                  # Pod 的详细规范
  containers:          # Pod 中的容器列表
  - name: nginx        # 容器的名称是 nginx
    image: nginx       # 容器使用的镜像是 nginx
    imagePullPolicy: IfNotPresent  # 拉取镜像的策略是 IfNotPresent(如果本地没有这个镜像才会拉取)
  nodeSelector:        # 节点选择器
    disktype: ssd      # 选择带有 disktype=ssd 标签的节点来运行这个 Pod

这个 YAML 文件定义了一个名为 nginx 的 Pod,它会运行一个名为 nginx 的容器,该容器使用 nginx 镜像,并且只有在本地没有这个镜像的情况下才会从镜像仓库拉取。

这个 Pod 会被调度到带有 disktype=ssd 标签的节点上

PS: --output=wide

--output=widekubectl get 命令的一个参数,用来获取更详细的信息输出。

--output=wide 会显示以下额外的信息:

  • Pod 所运行的节点(NODE 列)
  • Pod 的 IP 地址(IP 列)

例如,运行 kubectl get pods 可能只会显示以下内容:

Bash
1
2
NAME     READY     STATUS    RESTARTS   AGE
nginx    1/1       Running   0          13s

而运行 kubectl get pods --output=wide 则会显示更详细的信息:

Bash
1
2
NAME     READY     STATUS    RESTARTS   AGE    IP           NODE
nginx    1/1       Running   0          13s    10.200.0.4   worker0

example:

  1. 使用该配置文件创建一个 Pod,该 Pod 将被调度到你选择的节点上:

    Bash
    1
    kubectl create -f https://k8s.io/examples/pods/pod-nginx.yaml
    
  2. 验证 Pod 确实运行在你选择的节点上:

    Bash
    1
    kubectl get pods --output=wide
    

    输出类似如下:

    Bash
    1
    2
    NAME     READY     STATUS    RESTARTS   AGE    IP           NODE
    nginx    1/1       Running   0          13s    10.200.0.4   worker0
    

创建一个会被调度到特定节点上的 Pod

名称筛选

你也可以通过设置 nodeName 将某个 Pod 调度到特定的节点:

YAML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  nodeName: foo-node # 调度 Pod 到特定的节点
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent

使用此配置文件来创建一个 Pod,该 Pod 将只能被调度到 foo-node 节点