什么是Kubernetes对象,管理Kubernetes对象,名称(name),名称空间(namespace)的概念
一、什么是Kubernetes对象
Kubernetes对象指的是Kubernetes系统的持久化实体,所有这些对象合起来,代表了集群的实际情况。常规的应用里,应用程序的数据存储在数据库中,Kubernetes将其数据以Kubernetes对象的形式通过 api server存储在 etcd 中。具体来说,这些数据(Kubernetes对象)描述了:
- 集群中运行了哪些容器化应用程序(以及在哪个节点上运行)
- 集群中对应用程序可用的资源
- 应用程序相关的策略定义,例如,重启策略、升级策略、容错策略
- 其他Kubernetes管理应用程序时所需要的信息
操作 Kubernetes 对象(创建、修改、删除)的方法主要有:
- kubectl 命令行工具
- kuboard 图形界面工具
kubectl、kuboard 最终都通过调用 kubernetes API 来实现对 Kubernetes 对象的操作。
对象的spec和status
每一个 Kubernetes 对象都包含了两个重要的字段:
spec必须由您来提供,描述了您对该对象所期望的 目标状态status只能由 Kubernetes 系统来修改,描述了该对象在 Kubernetes 系统中的 实际状态
Kubernetes通过对应的控制器,不断地使实际状态趋向于期望的目标状态。
例如,一个 Kubernetes Deployment 对象可以代表一个应用程序在集群中的运行状态。当创建 Deployment 对象时,可以通过 Deployment 的 spec 字段指定需要运行应用程序副本数(假设为3)。Kubernetes 从 Deployment 的 spec 中读取这些信息,并创建指定容器化应用程序的 3 个副本,再将实际的状态更新到 Deployment 的 status 字段。Kubernetes 系统将不断地比较 实际状态 staus 和 目标状态 spec 之间的差异,并根据差异做出对应的调整。例如,如果任何一个副本运行失败了,Kubernetes 将启动一个新的副本,以替代失败的副本
描述Kubernetes对象
在 Kubernetes 中创建一个对象时,必须提供
- 该对象的 spec 字段,通过该字段描述您期望的 目标状态
- 该对象的一些基本信息,例如名字
如果使用 kubectl 创建对象,必须编写 .yaml 格式的文件下面是一个 kubectl 可以使用的 .yaml 文件:
1 | apiVersion: apps/v1 |
使用 kube apply 命令可以创建该 .yaml 文件中的 Deployment 对象:
1 | [root@k8s-master k8s-yamls]# kubectl apply -f nginx-deployment.yaml |
必填字段
在上述的 .yaml 文件中,如下字段是必须填写的:
- apiVersion 用来创建对象时所使用的Kubernetes API版本
- kind 被创建对象的类型
- metadata 用于唯一确定该对象的元数据:包括
name和namespace,如果namespace为空,则默认值为default - spec 描述您对该对象的期望状态
二、管理Kubernetes对象
三种管理方式
| 管理方式 | 操作对象 | 推荐的环境 | 参与编辑的人数 | 学习曲线 |
|---|---|---|---|---|
| 指令性的命令行 | Kubernetes对象 | 开发环境 | 1+ | 最低 |
| 指令性的对象配置 | 单个 yaml 文件 | 生产环境 | 1 | 适中 |
| 声明式的对象配置 | 包含多个 yaml 文件的多个目录 | 生产环境 | 1+ | 最高 |
指令性的命令行
当使用指令性的命令行(imperative commands)时,用户通过向 kubectl 命令提供参数的方式,直接操作集群中的 Kubernetes 对象。此时,用户无需编写或修改 .yaml 文件。
这是在 Kubernetes 集群中执行一次性任务的一个简便的办法。由于这种方式直接修改 Kubernetes 对象,也就无法提供历史配置查看的功能。
例子
创建一个 Deployment 对象,以运行一个 nginx 实例:
1 | kubectl run nginx --image nginx |
下面的命令完成了相同的任务,但是命令格式不同:
1 | kubectl create deployment nginx --image nginx |
优缺点
与编写 .yaml 文件进行配置的方式相比的优势:
- 命令简单,易学易记,只需要一个步骤,就可以对集群执行变更
缺点:
- 使用命令,无法进行变更review的管理;不提供日志审计;没有创建新对象的模板
指令性的对象配置
使用指令性的对象配置(imperative object configuration)时,需要向 kubectl 命令指定具体的操作(create,replace,apply,delete等),可选参数以及至少一个配置文件的名字。配置文件中必须包括一个完整的对象的定义,可以是 yaml 格式,也可以是 json 格式。
通过配置文件创建对象
1 | kubectl create -f nginx.yaml |
删除两个配置文件中的对象
1 | kubectl delete -f nginx.yaml -f redis.yaml |
直接使用配置文件中的对象定义,替换Kubernetes中对应的对象:
1 | kubectl replace -f nginx.yaml |
声明式的对象配置
当使用声明式的对象配置时,用户操作本地存储的Kubernetes对象配置文件,然而,在将文件传递给 kubectl 命令时,并不指定具体的操作,由 kubectl 自动检查每一个对象的状态并自行决定是创建、更新、还是删除该对象。使用这种方法时,可以直接针对一个或多个文件目录进行操作(对不同的对象可能需要执行不同的操作)。
处理 configs 目录中所有配置文件中的Kubernetes对象,根据情况创建对象、或更新Kubernetes中已经存在的对象。可以先执行 diff 指令查看具体的变更,然后执行 apply 指令执行变更:
1 | kubectl diff -f configs/ |
三、名称
Kubernetes REST API 中,所有的对象都是通过 name 和 UID 唯一性确定。
Names
同一个名称空间下,同一个类型的对象,可以通过 name 唯一性确定。如果删除该对象之后,可以再重新创建一个同名对象。
例如,下面的配置文件定义了一个 name 为 nginx-demo 的 Pod,该 Pod 包含一个 name 为 nginx 的容器:
1 | apiVersion: v1 |
UIDs
UID 是由 Kubernetes 系统生成的,唯一标识某个 Kubernetes 对象的字符串。
Kubernetes集群中,每创建一个对象,都有一个唯一的 UID。用于区分多次创建的同名对象(如前所述,按照名字删除对象后,重新再创建同名对象时,两次创建的对象 name 相同,但是 UID 不同。)
四、名称空间
何时使用名称空间
- 名称空间的用途是,为不同团队的用户(或项目)提供虚拟的集群空间(划分集群的资源),也可以用来区分开发环境/测试环境、准上线环境/生产环境。
- 名称空间为
名称提供了作用域。名称空间内部的同类型对象不能重名,但是跨名称空间可以有同名同类型对象。名称空间不可以嵌套,任何一个Kubernetes对象只能在一个名称空间中。 - 在 Kubernetes 将来的版本中,同名称空间下的对象将默认使用相同的访问控制策略。
- 当Kubernetes对象之间的差异不大时,无需使用名称空间来区分,例如,同一个软件的不同版本,只需要使用 labels 来区分即可。
如何使用名称空间
查看名称空间
执行命令 kubectl get namespaces 可以查看名称空间
Kubernetes 安装成功后,默认有初始化了三个名称空间:
- default 默认名称空间,如果 Kubernetes 对象中不定义
metadata.namespace字段,该对象将放在此名称空间下 - kube-system Kubernetes系统创建的对象放在此名称空间下
- kube-public 此名称空间自动在安装集群是自动创建,并且所有用户都是可以读取的(即使是那些未登录的用户)。主要是为集群预留的,例如,某些情况下,某些Kubernetes对象应该被所有集群用户看到。
在执行请求时设定namespace
执行 kubectl 命令时,可以使用 --namespace 参数指定名称空间,例如:
1 | kubectl run nginx --image=nginx --namespace=<your_namespace> |
设置名称空间偏好
可以通过 set-context 命令改变当前kubectl 上下文的名称空间,后续所有命令都默认在此名称空间下执行。
1 | kubectl config set-context --current --namespace=<your_namespace> |
名称空间与DNS
当创建一个 Service 时,Kubernetes 为其创建一个对应的DNS 条目。该 DNS 记录的格式为 <service-name>.<namespace-name>.svc.cluster.local ,也就是说,如果在容器中只使用 <service-name> ,其DNS将解析到同名称空间下的 Service。这个特点在多环境的情况下非常有用,例如将开发环境、测试环境、生产环境部署在不同的名称空间下,应用程序只需要使用<service-name>即可进行服务发现,无需为不同的环境修改配置。如果跨名称空间访问服务,则必须使用完整的域名(fully qualified domain name,FQDN)。
并非所有对象都在名称空间里
大部分的 Kubernetes 对象(例如,Pod、Service、Deployment、StatefulSet等)都必须在名称空间里。但是某些更低层级的对象,是不在任何名称空间中的,例如nodes、persistentVolumes、storageClass等
执行一下命令可查看哪些 Kubernetes 对象在名称空间里,哪些不在:
1 | # 在名称空间里 |