基础用法
标签和选择算符
标签(Labels) 是附加到 Kubernetes 对象 (比如 Pod)上的键值对。 标签旨在用于指定对用户有意义且相关的对象的标识属性,但不直接对核心系统有语义含义。 标签可以用于组织和选择对象的子集。标签可以在创建时附加到对象,随后可以随时添加和修改。 每个对象都可以定义一组键/值标签。每个键对于给定对象必须是唯一的。
JSON "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-scheduler
、kube-controller-manager
、 kube-apiserver
、kubectl
或其他第三方自动化工具)必须指定前缀 。
例如,以下是一个清单 (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 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
基于集合的需求
基于集合 的标签需求允许你通过一组值来过滤键。 支持三种操作符:in
、notin
和 exists
(只可以用在键标识符上)。例如:
Text Only 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 labels :
app : guestbook
tier : frontend
Redis 的主从节点会有不同的 tier
标签,甚至还有一个额外的 role
标签:
YAML labels :
app : guestbook
tier : backend
role : master
以及
YAML labels :
app : guestbook
tier : backend
role : replica
标签使得我们能够按照所指定的任何维度对我们的资源进行切片和切块:
Bash kubectl apply -f examples/guestbook/all-in-one/guestbook-all-in-one.yaml
kubectl get pods -Lapp -Ltier -Lrole
Text Only 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 kubectl get pods -lapp= guestbook,role= replica
Text Only 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 kubectl label pods -l app = nginx tier = fe
Text Only 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 kubectl get pods -l app = nginx -L tier
Text Only 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 kubectl get nodes --show-labels
output format
Bash ``` 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 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 kubectl label nodes ip-172-31-12-35.ec2.internal disktype = ssd
output format
example
Bash ❯ kubectl label nodes ip-172-31-12-35.ec2.internal disktype = ssd
node/ip-172-31-12-35.ec2.internal labeled
Bash ❯ 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=wide
是 kubectl get
命令的一个参数,用来获取更详细的信息输出。
--output=wide
会显示以下额外的信息:
Pod 所运行的节点(NODE
列)
Pod 的 IP 地址(IP
列)
例如,运行 kubectl get pods
可能只会显示以下内容:
Bash NAME READY STATUS RESTARTS AGE
nginx 1 /1 Running 0 13s
而运行 kubectl get pods --output=wide
则会显示更详细的信息:
Bash NAME READY STATUS RESTARTS AGE IP NODE
nginx 1 /1 Running 0 13s 10 .200.0.4 worker0
example:
使用该配置文件创建一个 Pod,该 Pod 将被调度到你选择的节点上:
Bash kubectl create -f https://k8s.io/examples/pods/pod-nginx.yaml
验证 Pod 确实运行在你选择的节点上:
Bash kubectl get pods --output= wide
输出类似如下:
Bash NAME READY STATUS RESTARTS AGE IP NODE
nginx 1 /1 Running 0 13s 10 .200.0.4 worker0
创建一个会被调度到特定节点上的 Pod
名称筛选
你也可以通过设置 nodeName
将某个 Pod 调度到特定的节点:
YAML apiVersion : v1
kind : Pod
metadata :
name : nginx
spec :
nodeName : foo-node # 调度 Pod 到特定的节点
containers :
- name : nginx
image : nginx
imagePullPolicy : IfNotPresent
使用此配置文件来创建一个 Pod,该 Pod 将只能被调度到 foo-node
节点