注:该笔记整理自Kubernetes官方文档中的内容,笔记中使用的观点与资源均来源于官方文档以及我个人的理解,如果涵盖其它来源的观点,会额外标明引用。
目录
1、Kubernetes对象的理解
2、描述Kubernetes对象
3、对象管理
4、对象名称与ID
5、标签与选择算符
5.1、标签选择算符
5.2、更新标签
6、名字空间
7、注解
8、字段选择器(Field Selector)
9、Finalizers
10、属主与附属
Kubernetes对象,是Kubernetes系统中的持久化的实体,它们联合表示集群的信息,包括:
哪些容器化应用在运行?
哪些资源可以被应用使用?
应用运行时的行为策略
通过创建Kubernetes中的对象,你可以向Kubernetes系统表达“我希望这个集群是什么状态的”。
Kubernetes中几乎所有对象都包含两个属性:规约(spec)以及状态(status)
如果一个对象存在spec字段,则你必须要在创建对象时设置其内容,描述你所希望的该对象具有的特征。
status字段表述的是对象的状态信息,表示为当前状态,这个属性由Kubernetes系统维护。
我们已经知道,Kubernetes对象创建时,必须要对其进行描述,如何描述它呢?一般情况下,使用的是一个清单(Manifest)文件(该文件一般为yaml文件,当然也可以使用json文件),这里给出一个创建Deployment类型的对象的清单文件:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # 告知 Deployment 运行 2 个与该模板匹配的 Pod
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
并通过kubectl中的kubectl apply进行创建:
kubectl apply -f https://k8s.io/examples/application/deployment.yaml
清单文件中必须包含以下几个字段:
apiVersion:创建该对象使用的kubernetes API的版本
kind:创建的对象类别
mete-data:帮助标识对象的数据,包括name、UID、namespace
spec:规约
kubectl是管理对象的主要工具,它支持不同的管理方式:
指令式命令:直接使用命令对集群上活跃的对象进行操作。
指令式对象配置:将操作写入清单文件中,然后对单个清单进行操作。
声明式对象配置:对整个目录下的yaml文件进行批量操作,但是只能让kubectl自动控制
集群中的每一个对象都存在一个名称来标识在同类资源中的唯一性。值得注意的是,这里指的是同类资源,例如,在一个名字空间中只能存在一个Pod的名称为:“myapp-1234”,但是可以同时存在一个Pod与一个Deployment对象,他们的名称都为“myapp-1234”,因为他们的资源类别是不同的。
而UID则更为严格,它标识了一个Kubernetes对象在整个集群中的唯一性。
名称通常并不是完全随意确定的,它可能需要满足一些约束:DNS子域名、RFC标签名等、路径分段名称等。
标签是附加到Kubernetes对象上的键值对,它主要定义对用户有意义的属性,以下为一个标签的实例:
"metadata": {
"labels": {
"key1" : "value1",
"key2" : "value2"
}
}
标签使得查询与监听操作更加高效,它允许用户以松耦合的方式将自身项目的组织结构映射到Kubernetes的系统对象,且无需用户储存这些信息。
标签分为两部分:前缀、名称,二者通过反斜杠/进行分隔,其中名称段是必须的,而前缀则可以选择是否指定,前缀的命名必须为DNS子域。如果不指定前缀,则默认该标签对用户私有。值得注意的是 kubernetes.io/ 和 k8s.io/ 是Kubernetes系统保留的。
标签选择算符是Kubernetes中的核心分组选择原语。API当前支持两种选择算符:基于等值的和基于集合的。标签选择算符可以由多个由逗号分割的需求组成,在这里,逗号通常作为逻辑与(&&)的意思。需要注意的是,不存在逻辑或(||)的算符。
基于等值的需求:=、==、!=三种选择算符,前两个都表示相等,最后一个表示不等。示例如下:
environment = production
tier != frontend
第一条指令选择出所有键为environment值为production的资源。后者选择键为tier,但是值不是frontend的资源以及不含有tier的资源。
可以使用指令:environment=production,tier!=frontend
来过滤掉production环境中,非frontend层的资源。
基于集合的需求:允许你通过一组值来过滤键,它支持三种操作符:in、notin、exists。示例如下:
environment in (production, qa)
tier notin (frontend, backend)
partition
!partition
第一个示例选择所有键为environment,值为production或qa的资源。
第二个示例选择所有键为tier,值部位frontend且不为backend的资源,以及所有没有tier键的资源
第三个示例选择包含了partition标签的资源;没有校验值。
第四个示例选择了没有partition标签的资源;没有校验值。
这里给出一些推荐使用的标签:
示例:
kubectl label pods -l app=nginx tier=fe
意义:首先筛选出所有app=nginx的资源,然后使用tier=fe标记它们。
名字空间是Kubernetes的一种机制,他将集群资源划分为相互隔离的几个组,同一个名字空间中的资源名称要唯一,不同名字空间中的资源名字可以相同。名字空间的作用范围仅限于带有名字空间属性的资源,一些集群范围的资源不受名字空间约束。
名字空间通常被用来对多个用户进行资源划分,当存在很多跨团队项目或用户场景时较为实用,对于一个集群而言,如果它只有几个到几十个用户,完全没有必要使用名字空间。
Kubernetes启动时会存在四个名字空间:
default:Kubernetes包含这个名字空间,这是为了方便你,可以不创建新的名字空间即可开始使用集群,在生产集群中,请不要考虑使用default名字空间。
kube-node-lease:该名字空间包含用于与各个节点关联的Lease(租约)对象。 节点租约允许 kubelet 发送心跳, 由此控制面能够检测到节点故障。
kube-public:所有的客户端可见,预留为集群使用,以便于使某些资源对于集群整体都是可见的,注意,这是一个约定,而不是要求。
kube-system:Kubernetes系统创建的对象。
注:避免使用kube-前缀创建名字空间,因为这是Kubernetes系统保留的名字空间。
大部分资源,包括Pod、Service、副本控制器等都位于某些名字空间中,但是名字资源本身不在名字空间之中,且一些底层资源,比如节点、持久卷不位于任何名字空间之中。
标签与注解都可以将元数据(描述数据信息的数据)附加到Kubernetes对象上。与标签不同,标签可以用于查询对象集合,但是注解不可以,注解只用于描述数据的信息,它可以很小或很大,可以为结构化的也可以为非结构化的,同时,它可以包好在标签中不被允许的字符。与标签相似,注解也是键值对,以下为一个注解的示例:
"metadata": {
"annotations": {
"key1" : "value1",
"key2" : "value2"
}
}
注:Map中的键值对必须都是字符串。
注解的定义规则与标签几乎一致,其键也是“DNS子域/名称”,值可以包含所有字符,但是必须使用[a-z0-9A-Z]
开头和结尾。
字段选择器允许你通过资源的字段对资源进行筛选,例如:metadata.name=my-service
、status.phase=Pending
具体的kubectl语句为:
kubectl get pods --field-selector status.phase=Running
Finalizer是带有名字空间的键,它会告诉Kubernetes当某些条件被满足后,再完全删除被标记为删除的资源。Finalizer提醒控制器清理被删除对象的资源。
当你告诉Kubernetes需要删除一个指定了Finalizer的对象时,Kubernetes API通过填充 .metadata.deletionTimestamp
来标记删除的对象,并返回“202”(表示HTTP已接受),并使该对象进入只读状态。此时,控制平面或其他组件会执行相关操作,当这些操作完成后,控制器会删除目标对象相关的Finalizer,当 metadata.finalizers
字段为空时,Kubernetes 认为删除已完成并删除对象。Finalizer通常与垃圾回收有关。
使用清单文件进行对象创建时,你可以指定finalizer字段,当你删除一个指定了finalizer的对象时,Kubernetes API会注意到该字段,并执行以下操作:
修改对象,将你开始执行删除的时间加入.metadata.deletionTimestamp
中。
禁止该对象被删除,直到 metadata.finalizers
中的所有项被删除。
返回“202”状态码(HTTP “Accepted”)
在Kubernetes中,通常存在一些对象是其他对象的属主(Owner)或者附属(Dependent)附属对象存在字段metadata.ownerReferences
用于引用其属主对象,一个有效的引用通常需要包括一个命名空间下的名称与UID,Kubernetes自动为某些对象的附属对象设置属主引用的值,你可以手动调整它们,但是通常不需要这样做,可以Kubernetes自动管理。
附属对象还有一个字段 ownerReferences.blockOwnerDeletion
,该字段使用布尔值,这个字段控制该附属对象是否可以阻止其属主对象的删除。如果控制器已经设置了metadata.ownerReferences
,则这个值默认设置为true。
注1:Kubernetes不允许跨名字空间指定属主,一个名字空间中的附属,可以指定集群范围的属主或该名字空间的属主。如果附属与属主不处于同一名字空间,则认为该属主引用是缺失的,如果该附属的所有属主引用都不存在,则该附属会被删除。
注2:集群范围的附属只能指定集群范围的属主,如果指定了名字空间范围的属主,该附属的属主引用则会被认为是无法解析的,并且不能被垃圾回收。
属主关系可以对集群进行保护,举一个例子:一个永久卷资源(Persistent Volume)作为属主,使用它的Pod为附属,如果你尝试对该资源进行删除,kubernetes.io/pv-protection
Finalizer会阻止你,并只会使该永久卷的状态设置为“Terminating”,只有当已经没有Pod挂载在其上的时候,该永久卷资源才会被完全删除。