0%

操作Kubernetes

什么是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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # 运行 2 个容器化应用程序副本
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80

使用 kube apply 命令可以创建该 .yaml 文件中的 Deployment 对象:

1
2
3
4
5
6
7
8
9
10
[root@k8s-master k8s-yamls]# kubectl apply -f nginx-deployment.yaml 
deployment.apps/nginx-deployment created
[root@k8s-master k8s-yamls]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-54f57cf6bf-528xn 1/1 Running 0 4m35s
nginx-deployment-54f57cf6bf-bgclh 1/1 Running 0 4m35s

#删除
[root@k8s-master k8s-yamls]# kubectl delete -f nginx-deployment.yaml
deployment.apps "nginx-deployment" deleted

必填字段

在上述的 .yaml 文件中,如下字段是必须填写的:

  • apiVersion 用来创建对象时所使用的Kubernetes API版本
  • kind 被创建对象的类型
  • metadata 用于唯一确定该对象的元数据:包括 namenamespace,如果 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
2
3
4
5
6
kubectl diff -f configs/
kubectl apply -f configs/

#递归处理目录中的内容
kubectl diff -R -f configs/
kubectl apply -R -f configs/

三、名称

Kubernetes REST API 中,所有的对象都是通过 nameUID 唯一性确定。

Names

同一个名称空间下,同一个类型的对象,可以通过 name 唯一性确定。如果删除该对象之后,可以再重新创建一个同名对象。

例如,下面的配置文件定义了一个 name 为 nginx-demo 的 Pod,该 Pod 包含一个 name 为 nginx 的容器:

1
2
3
4
5
6
7
8
9
10
apiVersion: v1
kind: Pod
metadata:
name: nginx-demo
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80

UIDs

UID 是由 Kubernetes 系统生成的,唯一标识某个 Kubernetes 对象的字符串。

Kubernetes集群中,每创建一个对象,都有一个唯一的 UID。用于区分多次创建的同名对象(如前所述,按照名字删除对象后,重新再创建同名对象时,两次创建的对象 name 相同,但是 UID 不同。)

四、名称空间

何时使用名称空间

  1. 名称空间的用途是,为不同团队的用户(或项目)提供虚拟的集群空间(划分集群的资源),也可以用来区分开发环境/测试环境、准上线环境/生产环境。
  2. 名称空间为名称提供了作用域。名称空间内部的同类型对象不能重名,但是跨名称空间可以有同名同类型对象。名称空间不可以嵌套,任何一个Kubernetes对象只能在一个名称空间中。
  3. 在 Kubernetes 将来的版本中,同名称空间下的对象将默认使用相同的访问控制策略。
  4. 当Kubernetes对象之间的差异不大时,无需使用名称空间来区分,例如,同一个软件的不同版本,只需要使用 labels 来区分即可。

如何使用名称空间

查看名称空间

执行命令 kubectl get namespaces 可以查看名称空间

Kubernetes 安装成功后,默认有初始化了三个名称空间:

  • default 默认名称空间,如果 Kubernetes 对象中不定义 metadata.namespace 字段,该对象将放在此名称空间下
  • kube-system Kubernetes系统创建的对象放在此名称空间下
  • kube-public 此名称空间自动在安装集群是自动创建,并且所有用户都是可以读取的(即使是那些未登录的用户)。主要是为集群预留的,例如,某些情况下,某些Kubernetes对象应该被所有集群用户看到。

在执行请求时设定namespace

执行 kubectl 命令时,可以使用 --namespace 参数指定名称空间,例如:

1
2
kubectl run nginx --image=nginx --namespace=<your_namespace>
kubectl get pods --namespace=<your_namespace>

设置名称空间偏好

可以通过 set-context 命令改变当前kubectl 上下文的名称空间,后续所有命令都默认在此名称空间下执行。

1
2
3
kubectl config set-context --current --namespace=<your_namespace>
# 验证结果
kubectl config view --minify | grep 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
2
3
4
5
# 在名称空间里
kubectl api-resources --namespaced=true

# 不在名称空间里
kubectl api-resources --namespaced=false