Node是kubernetes集群的工作节点,可以是物理机也可以是虚拟机。
Node包括如下状态信息:
--hostname-override
参数替代。True
Unknown
,健康为True
,否则为False
。True
,否则为False
。True
,否则为False
。禁止pod调度到该节点上
kubectl cordon
驱逐该节点上的所有pod
kubectl drain
该命令会删除该节点上的所有Pod(DaemonSet除外),在其他node上重新启动它们,通常该节点需要维护时使用该命令。直接使用该命令会自动调用kubectl cordon
命令。当该节点维护完成,启动了kubelet后,再使用kubectl uncordon
即可将该节点添加到kubernetes集群中。
在一个Kubernetes集群中可以使用namespace创建多个“虚拟集群”,这些namespace之间可以完全隔离,也可以通过某种方式,让一个namespace中的service可以访问到其他的namespace中的服务,我们在CentOS中部署kubernetes1.6集群的时候就用到了好几个跨越namespace的服务,比如Traefik ingress和kube-system
namespace下的service就可以为整个集群提供服务,这些都需要通过RBAC定义集群级别的角色来实现。
因为namespace可以提供独立的命名空间,因此可以实现部分的环境隔离。当你的项目和人员众多的时候可以考虑根据项目属性,例如生产、测试、开发划分不同的namespace。
kubectl create namespace dev
Label是附着到object上(例如Pod)的键值对。可以在创建object的时候指定,也可以在object创建后随时指定。Labels的值对系统本身并没有什么含义,只是对用户才有意义。
"labels": {
"key1" : "value1",
"key2" : "value2"
}
Kubernetes最终将对labels最终索引和反向索引用来优化查询和watch,在UI和命令行中会对它们排序。不要在label中使用大型、非标识的结构化数据,记录这样的数据应该用annotation。
Label能够将组织架构映射到系统架构上(就像是康威定律),这样能够更便于微服务的管理,你可以给object打上如下类型的label:
"release" : "stable"
, "release" : "canary"
"environment" : "dev"
, "environment" : "qa"
, "environment" : "production"
"tier" : "frontend"
, "tier" : "backend"
, "tier" : "cache"
"partition" : "customerA"
, "partition" : "customerB"
"track" : "daily"
, "track" : "weekly"
"team" : "teamA"
,"team:" : "teamB"
Label key的组成:
kubernetes.io/
由kubernetes保留Label value的组成:
Label不是唯一的,很多object可能有相同的label。
通过label selector,客户端/用户可以指定一个object集合,通过label selector对object的集合进行操作。
Label selector有两种类型:
=
、==
、!=
操作符,可以使用逗号分隔多个表达式in
、notin
、!
操作符,另外还可以没有操作符,直接写出某个label的key,表示过滤有某个key的object而不管该key的value是何值,!
表示没有该label的object$ kubectl get pods -l environment=production,tier=frontend
$ kubectl get pods -l 'environment in (production),tier in (frontend)'
$ kubectl get pods -l 'environment in (production, qa)'
$ kubectl get pods -l 'environment,environment notin (frontend)'
在service
、replicationcontroller
等object中有对pod的label selector,使用方法只能使用等于操作,例如:
selector:
component: redis
在Job
、Deployment
、ReplicaSet
和DaemonSet
这些object中,支持set-based的过滤,例如:
selector:
matchLabels:
component: redis
matchExpressions:
- {key: tier, operator: In, values: [cache]}
- {key: environment, operator: NotIn, values: [dev]}
如Service通过label selector将同一类型的pod作为一个服务expose出来。
图片 - label示意图
另外在node affinity和pod affinity中的label selector的语法又有些许不同,示例如下:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- e2e-az1
- e2e-az2
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
Annotation,顾名思义,就是注解。Annotation可以将Kubernetes资源对象关联到任意的非标识性元数据。使用客户端(如工具和库)可以检索到这些元数据。
Label和Annotation都可以将元数据关联到Kubernetes资源对象。Label主要用于选择对象,可以挑选出满足特定条件的对象。相比之下,annotation 不能用于标识及选择对象。annotation中的元数据可多可少,可以是结构化的或非结构化的,也可以包含label中不允许出现的字符。
annotation和label一样都是key/value键值对映射结构:
"annotations": {
"key1" : "value1",
"key2" : "value2"
}
以下列出了一些可以记录在 annotation 中的对象信息:
如果不使用annotation,您也可以将以上类型的信息存放在外部数据库或目录中,但这样做不利于创建用于部署、管理、内部检查的共享工具和客户端库。
如 Istio 的 Deployment 配置中就使用到了 annotation:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: istio-manager
spec:
replicas: 1
template:
metadata:
annotations:
alpha.istio.io/sidecar: ignore
labels:
istio: manager
spec:
serviceAccountName: istio-manager-service-account
containers:
- name: discovery
image: harbor-001.jimmysong.io/library/manager:0.1.5
imagePullPolicy: Always
args: ["discovery", "-v", "2"]
ports:
- containerPort: 8080
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: apiserver
image: harbor-001.jimmysong.io/library/manager:0.1.5
imagePullPolicy: Always
args: ["apiserver", "-v", "2"]
ports:
- containerPort: 8081
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
alpha.istio.io/sidecar
注解就是用来控制是否自动向 pod 中注入 sidecar 的。
Taint(污点)和 Toleration(容忍)可以作用于 node 和 pod 上,其目的是优化 pod 在集群间的调度,这跟节点亲和性类似,只不过它们作用的方式相反,具有 taint 的 node 和 pod 是互斥关系,而具有节点亲和性关系的 node 和 pod 是相吸的。另外还有可以给 node 节点设置 label,通过给 pod 设置 nodeSelector
将 pod 调度到具有匹配标签的节点上。
Taint 和 toleration 相互配合,可以用来避免 pod 被分配到不合适的节点上。每个节点上都可以应用一个或多个 taint ,这表示对于那些不能容忍这些 taint 的 pod,是不会被该节点接受的。如果将 toleration 应用于 pod 上,则表示这些 pod 可以(但不要求)被调度到具有相应 taint 的节点上。
以下分别以为 node 设置 taint 和为 pod 设置 toleration 为例。
为 node1 设置 taint:
kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule
删除上面的 taint:
kubectl taint nodes node1 key1:NoSchedule-
kubectl taint nodes node1 key1:NoExecute-
kubectl taint nodes node1 key2:NoSchedule-
查看 node1 上的 taint:
kubectl describe nodes node1
只要在 pod 的 spec 中设置 tolerations 字段即可,可以有多个 key
,如下所示:
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
- key: "node.alpha.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 6000
value
的值可以为 NoSchedule
、PreferNoSchedule
或 NoExecute
。tolerationSeconds
是当 pod 需要被驱逐时,可以继续在 node 上运行的时间。Kubernetes 垃圾收集器的角色是删除指定的对象,这些对象曾经有但以后不再拥有 Owner 了。
注意:垃圾收集是 beta 特性,在 Kubernetes 1.4 及以上版本默认启用。
一些 Kubernetes 对象是其它一些的 Owner。例如,一个 ReplicaSet 是一组 Pod 的 Owner。具有 Owner 的对象被称为是 Owner 的 Dependent。每个 Dependent 对象具有一个指向其所属对象的 metadata.ownerReferences
字段。
有时,Kubernetes 会自动设置 ownerReference
的值。例如,当创建一个 ReplicaSet 时,Kubernetes 自动设置 ReplicaSet 中每个 Pod 的 ownerReference
字段值。在 1.6 版本,Kubernetes 会自动为一些对象设置 ownerReference
的值,这些对象是由 ReplicationController、ReplicaSet、StatefulSet、DaemonSet 和 Deployment 所创建或管理。
也可以通过手动设置 ownerReference
的值,来指定 Owner 和 Dependent 之间的关系。
这有一个配置文件,表示一个具有 3 个 Pod 的 ReplicaSet:
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
name: my-repset
spec:
replicas: 3
selector:
matchLabels:
pod-is-for: garbage-collection-example
template:
metadata:
labels:
pod-is-for: garbage-collection-example
spec:
containers:
- name: nginx
image: nginx
如果创建该 ReplicaSet,然后查看 Pod 的 metadata 字段,能够看到 OwnerReferences 字段:
kubectl create -f https://k8s.io/docs/concepts/abstractions/controllers/my-repset.yaml
kubectl get pods --output=yaml
输出显示了 Pod 的 Owner 是名为 my-repset 的 ReplicaSet:
apiVersion: v1
kind: Pod
metadata:
...
ownerReferences:
- apiVersion: extensions/v1beta1
controller: true
blockOwnerDeletion: true
kind: ReplicaSet
name: my-repset
uid: d9607e19-f88f-11e6-a518-42010a800195
...
当删除对象时,可以指定是否该对象的 Dependent 也自动删除掉。自动删除 Dependent 也称为 级联删除。Kubernetes 中有两种 级联删除 的模式:background 模式和 foreground 模式。
如果删除对象时,不自动删除它的 Dependent,这些 Dependent 被称作是原对象的 孤儿。
在 background 级联删除 模式下,Kubernetes 会立即删除 Owner 对象,然后垃圾收集器会在后台删除这些 Dependent。
在 foreground 级联删除 模式下,根对象首先进入 “删除中” 状态。在 “删除中” 状态会有如下的情况:
deletionTimestamp
字段metadata.finalizers
字段包含了值 “foregroundDeletion”一旦被设置为 “删除中” 状态,垃圾收集器会删除对象的所有 Dependent。垃圾收集器删除了所有 “Blocking” 的 Dependent(对象的 ownerReference.blockOwnerDeletion=true
)之后,它会删除 Owner 对象。
注意,在 “foreground 删除” 模式下,Dependent 只有通过 ownerReference.blockOwnerDeletion
才能阻止删除 Owner 对象。在 Kubernetes 1.7 版本中将增加 admission controller,基于 Owner 对象上的删除权限来控制用户去设置 blockOwnerDeletion
的值为 true,所以未授权的 Dependent 不能够延迟 Owner 对象的删除。
如果一个对象的ownerReferences
字段被一个 Controller(例如 Deployment 或 ReplicaSet)设置,blockOwnerDeletion
会被自动设置,没必要手动修改这个字段。
通过为 Owner 对象设置 deleteOptions.propagationPolicy
字段,可以控制级联删除策略。可能的取值包括:“orphan”、“Foreground” 或 “Background”。
对很多 Controller 资源,包括 ReplicationController、ReplicaSet、StatefulSet、DaemonSet 和 Deployment,默认的垃圾收集策略是 orphan
。因此,除非指定其它的垃圾收集策略,否则所有 Dependent 对象使用的都是 orphan
策略。
下面是一个在后台删除 Dependent 对象的例子:
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Background"}' \
-H "Content-Type: application/json"
下面是一个在前台删除 Dependent 对象的例子:
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Foreground"}' \
-H "Content-Type: application/json"
下面是一个孤儿 Dependent 的例子:
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
-H "Content-Type: application/json"
kubectl 也支持级联删除。 通过设置 --cascade
为 true,可以使用 kubectl 自动删除 Dependent 对象。设置 --cascade
为 false,会使 Dependent 对象成为孤儿 Dependent 对象。--cascade
的默认值是 true。
下面是一个例子,使一个 ReplicaSet 的 Dependent 对象成为孤儿 Dependent:
kubectl delete replicaset my-repset --cascade=false