3-3-命名空间
由多个独立的团队或项目共享使用的Kubernetes集群或许会运行大量彼此无关的工作负载, 即便使用需求相对较小, 部署的对象数量 也可能很快变得难以管理, 进而降低操作响应速度并增加发生危险错误的可能性。Kubernetes使用“名称空间”来帮助降低这种复杂性: 通过一个抽象组件将存在关联关系的对象组织成一个逻辑单元进行统 一管控, 可用于对集群中的任意对象组进行分类、筛选和管理。
注 :
Kubernetes的名称空间不同于Linux系统的名称空间, 它们是各自独立的概念。另外,Kubernetes名称空间并不能实现Pod间的通信隔离, 它仅用于限制资源对象名称的作用域。
1. 名称空间作用
名称空间的核心功能在于限制集群上对象名称的作用域 : 同一类型的资源对象名称在同一个名称空间中必须唯一, 但不同名称空间却可为同一类型的资源使用相同的名称。对于某些场景, 这种功能有着非常实用的价值, 例如名称空间可用于分隔不同应用程序的生命周期环境(例如开发、预发和生产等), 从而能够在每个环境中维护具有相同名称的同一类型的资源对象。
名称空间本身并不具有网络隔离和访问限制等功能, 但它可以作为网络访问控制策略 (NetworkPolicy)、授权策略(RBAC)、资源限制策略 (ResourceQuota)和Pod安全策略(PodSecurityPolicy)等管理逻辑 的承载组件, 这也是支撑集群“多租户”机制的基础组件。
Kubernetes API使用Namespace资源类型来表示名称空间, 它自身是集群级别(或称为全局级别)的资源, 不能嵌套于其他名称空间, 但Kubernetes的绝大多数资源类型都隶属于名称空间级别, 例如Pod、 Service、Deployment和StatefulSet等。而集群级别的资源类型除了 Namespace外还有Node和PersistentVolume等, 它们的名称标识作用域为集群全局。 默认情况下, Kubernetes集群会内置如下4个名称空间, 其中第4 个名称空间是为kubelet引入租约机制后才新增的。
default: 创建名称空间级别的资源对象 , 但未指定从属的名称 空间时将默认使用defaut名称空间。kube-public: 用于为集群上的所有用户(包括匿名用户) 提供 一个公共可用的名称空间, 保留给集群使用, 以防某些资源在整个集群中公开可见 ; 该名称空间的公共属性仅是约定, 并非强制要求。kube-system: 用于部署与Kubernetes系统自身相关的组件, 例如kube-proxy、CNI网络插件, 甚至是kube-apiserver、kube controller-manager和kube-scheduler等控制平面组件的静态Pod等 ; 不建议在该名称空间中运行与系统无关的工作负载。kube-node-lease: 目前是专用于放置kubelet lease对象的名称 空间, 这些对象对于Kubernetes系统自身健康运行至关重要 ; 因而同样不建议在该名称空间中运行与系统无关的工作负载。
kubectl get namespaces命令可以查看系统上的namespaces资 源
root@kubeadm-master1:~# kubectl get namespace
NAME STATUS AGE
default Active 41h
dev Active 23h
kube-flannel Active 39h
kube-node-lease Active 41h
kube-public Active 41h
kube-system Active 41h
kubernetes-dashboard Active 40h对于那些隶属名称空间级别的资源 , 通过API对其进行管理操作时必须明确指定名称空间 , kubectl命令经常使用的选项-n或-- namespace就用于此目的。例如 , 下面用于查看kube-system下的所有 Pod资源的命令:
root@kubeadm-master1:~# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-5f98f8d567-dszzv 1/1 Running 0 39h
coredns-5f98f8d567-pfwsd 1/1 Running 0 39h
etcd-kubeadm-master1.cbear.top 1/1 Running 0 40h
etcd-kubeadm-master2.cbear.top 1/1 Running 0 40h
etcd-kubeadm-master3.cbear.top 1/1 Running 0 40h
kube-apiserver-kubeadm-master1.cbear.top 1/1 Running 0 40h
kube-apiserver-kubeadm-master2.cbear.top 1/1 Running 0 40h
kube-apiserver-kubeadm-master3.cbear.top 1/1 Running 0 40h
kube-controller-manager-kubeadm-master1.cbear.top 1/1 Running 1 (26h ago) 40h
kube-controller-manager-kubeadm-master2.cbear.top 1/1 Running 1 (26h ago) 40h
kube-controller-manager-kubeadm-master3.cbear.top 1/1 Running 1 (26h ago) 40h
kube-proxy-fs2h7 1/1 Running 0 22h
kube-proxy-kzpr4 1/1 Running 0 22h
kube-proxy-pfm9z 1/1 Running 0 22h
kube-proxy-pkqg9 1/1 Running 0 22h
kube-proxy-sdc5t 1/1 Running 0 22h
kube-proxy-vfrnx 1/1 Running 0 22h
kube-scheduler-kubeadm-master1.cbear.top 1/1 Running 1 (26h ago) 40h
kube-scheduler-kubeadm-master2.cbear.top 1/1 Running 0 40h
kube-scheduler-kubeadm-master3.cbear.top 1/1 Running 0 40h
2. 管理namespace
Kubernetes Namespace资源的管理支持3种方式 , 用户可按需选择最适合的一种。本节将以Namespace对象为例详细说明这3种操作方式的用法。不过 , 出于版本控制等目的 , 建议读者在非测试场景中使用命令式对象配置或声明式对象配置的管理机制。
2.1 命令式命令
命令式命令的管理通常是针对集群上的活动对象直接进行 , 用户或管理员针对指定的资源运行create、get、describe、edit和delete 命令即能完成资源的创建、查看、编辑和删除等基础管理操作。以 Namespace资源为例 , 创建名称空间要使用kubectl create namespace 命令 , 例如 , 下面的命令创建了名为myns的名称空间。
root@kubeadm-master1:~# kubectl create namespace myns
namespace/myns createdNamespace资源的名称仅能由字母、数字、连接线、下划线等字符组成。
get命令默认显示资源对象简要状态信息 , 而使用-o yaml或-o json选项。get命令能够返回资源对象的元数据、期望的状态及当前状 态等信息 , 这些其实是Kubernetes保存的当前API对象的完整规范定 义 , 只不过status是由系统自己填充的。以Namespace对象myns为例的命令及结果如下所示。
root@kubeadm-master1:~# kubectl get namespace myns -o yaml
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: "2024-05-09T09:07:39Z"
labels:
kubernetes.io/metadata.name: myns
name: myns
resourceVersion: "337143"
uid: 53970fbf-6387-4ca5-bfc3-33a934da3b94
spec:
finalizers:
- kubernetes
status:
phase: Activeget命令也能够借助--custom-columns选项自定义要显示的字段 , 例如下面的命令只显示了myns名称空间的简要信息中的Name字段。
root@kubeadm-master1:~# kubectl get namespaces/myns -o custom-columns=NAME:metadata.name
NAME
myns若要打印活动对象的详细信息 , 则需要用到kubectl describe命 令 , 该命令可根据资源清单、资源名或卷标等方式过滤输出符合条件的资源对象的信息。命令格式为kubectl describe TYPE/NAME。例 如 , 显示myns名称空间的详细信息 , 可使用类似如下命令。
root@kubeadm-master1:~# kubectl describe namespace myns
Name: myns
Labels: kubernetes.io/metadata.name=myns
Annotations: <none>
Status: Active
No resource quota.
No LimitRange resource.
对于Namespace资源来说 , describe命令能够返回活动对象的名称、标签、注解、状态、资源配额(Resource Quota)和资源限制范围(Limit Range)等信息。不同资源类型的详细描述各不相同 , 但这些详情对于了解目标资源对象的状态或进行错误排查等操作来说至关重要。资源配额用于跟踪名称空间中资源的总体使用情况 , 以及让管理员定义名称空间可以消耗的硬资源上限 , 而限制范围用于定义单个实体可以在Namespace中消耗的资源量的最小及最大约束 , 后面的章节对这两个概念将有详细描述。
对于活动对象 , 并非其每个属性值都支持修改 , 例如Namespace对象的metadata.name字段就不支持修改 , 除非删除并重建它。对于那些支持修改的属性 , 可以使用kubectl edit TYPE NAME命令进行编辑 , 该命令会首先使用get命令获取目标对象的配置清单并保存在临时文件 中 , 打开默认编辑器(由EDITOR或KUBE_EDITOR环境变量定义)进行编 辑 , 在保存后提交(声明式操作命令apply)到系统之上。例如下面的 命令可打开myns名称空间的配置的编辑界面 , 不过 , 名称空间资源并无太多可直接编辑的配置 , 因此一般很少会有修改需求 , 但也有些类型的资源(例如Service和Deployment等)的编辑操作很常见。
root@kubeadm-master1:~# kubectl edit namespace myns
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: "2024-05-09T09:07:39Z"
labels:
kubernetes.io/metadata.name: myns
name: myns
resourceVersion: "337143"
uid: 53970fbf-6387-4ca5-bfc3-33a934da3b94
spec:
finalizers:
- kubernetes
status:
phase: Active不再需要的名称空间可以使用kubectl delete命令予以删除 , 但删除名称空间会级联清除其内部部署的所有资源 , 因而它是一个便捷、强大但又非常危险的命令。在删除之前列出其内部所有资源并再三确认各资源是否仍被需要应该被视作一个常规步骤。管理员切不可对Kubernetes内置的名称空间进行删除操作 , 当然 , 对于不再包含任何资源的自定义名称空间 , 通常可以安全删除。
root@kubeadm-master1:~# kubectl get all -n myns
No resources found in myns namespace.
root@kubeadm-master1:~# kubectl delete namespace myns
namespace "myns" deleted结合名称空间使用的删除命令
2.2 命令式对象配置
命令式对象配置管理机制 , 是将资源操作命令作用于资源对象的 配置清单进行的管理操作 , 常用的命令有create、delete、replace、 get和describe等。与前一节命令式命令的格式不同 , 这些命令都要使 用-f FILENAME选项从配置清单中读取资源对象的相关信息 , 这也是将 它称为命令式对象配置的主要原因。
绝大多数API资源对象的配置格式都遵循资源对象 配置规范 , 主要由apiVersin、kind、metadata和spec这4个一级字段组成 , 其中 , spec是定义期望状态的核心所在。Namespace资源对象的配置格式文档可通过kubectl explain namespaces命令得到。下面的 配置清单定义了一个名为demo的Namespace对象
apiVersion: v1
kind: Namespace
metadata:
name: demo
spec:
finalizers:
- kubernetesNamespace对象仅支持在spec中定义期望使用的终结器 (finalizer , 也称为垃圾收集器) , 用于让监测者在删除名称空间时清除相关的资源 , 它是个可选字段 , 且目前仅支持使用kubernetes作为其属性值。在Namespace对象上指定了不存在的终结器时并不影响创建操作 , 但删除该Namespace对象的操作将会被“卡住” , 即删除操作 将一直停留在Terminating状态。
提示: 如果读者熟悉
JSON, 也可直接将清单文件定义为JSON格式 ;YAML格式的清单文件本身也是由API Server事先将其转换为JSON格式而后才进行应用。
把上面的配置清单保存于以.yaml或.yml结尾的文本格式的文件中 , 例如ns-demo.yaml , 使用kubectl [COMMAND] -f /PATH/TO/YAML_FILE命令就能够使用命令式对象配置进行资源对象创建 , 下面是相应的命令及响应结果。
$kubectl create -f ns-demo.yaml
namespace/demo created命令的返回信息表示Namespace对象demo得以成功创建。事实上 , create命令中的-f选项也支持使用目录路径或URL , 而且目标路径为目录时 , 还支持使用-R选项进行子目录递归。另外 , --record选项可以把命令本身记录为目标对象的注解信息kubernetes.io/changecause , 而--save-config选项则能够把提供给命令的资源对象配置信息保存于对象的注解信息kubectl.kubernetes.io/last-applied configuration中 , 后一个选项的功能与声明式对象配置命令apply的功能相近。 对于命令式对象配置来说 , 查看对象的配置或状态依然要通过get 或describe命令进行 , 但要以-f FILENAME选项从指定配置清单中的 metadata.name字段获取目标资源对象。
root@kubeadm-master1:~# kubectl get -f ns-demo.yaml
NAME STATUS AGE
demo Active 27s kubectl replace命令提供了一种替换式对象更新机制 , 它删除了配置清单中目标资源的名称对应的现存对象 , 并基于配置清单重新创 建了一个同名的该类型对象 , 因此这是一种破坏性更新(disruptive update)机制。同时为命令使用--force[=true]选项可实现立即执行 删除操作而无视宽限期(grace-period)的定义。该命令仅支持更新操作 , 若目标对象不存在时 , 则会报错并终止。例如 , 以前面创建的Namespace对象demo为例 , 删除其指定的终结器 , 首先需要将其 spec.finalizers字段的值修改为空值 , 如下所示。
apiVersion: v1
kind: Namespace
metadata:
name: demo
spec:
finalizers:将上面的配置清单保存于指定的配置清单 , 例如ns-demo v2.yaml , 而后使用下面的命令即可完成替换操作 , 即删除demo之后进行重新创建。我们已经知道 , 删除名称空间时会删除其内部的所有资源 , 因此这种修改操作的破坏性毋庸置疑 , 务必要谨慎使用。实践中 , Namespace对象几乎不存在修改的需求 , 该操作仅是用于描述 replace命令的用法。
root@kubeadm-master1:~# kubectl replace --force -f ns-demo-v2.yaml
namespace "demo" deleted
namespace/demo replaced命令式对象配置的删除操作同样使用delete命令 , 它同样基于配置清单获取目标对象的资源类型及名称标识 , 而后针对相应的对象执行删除操作。例如 , 如下命令可删除前面创建的demo名称空间。再次提醒 , 删除名称空间将级联删除其内部的所有资源。
root@kubeadm-master1:~# kubectl delete -f ns-demo.yaml
namespace "demo" deleted有时候 , 名称空间的正常删除操作可能会莫名卡在Terminating状 态。常用的解决方案是获取并保存目标Namespace对象的JSON格式的配置清单 , 将spec.finalizers字段的值置空 , 而后手动终止相应的名称 空间对象即可。以demo为例 , 首先获取其当前配置:
root@kubeadm-master1:~# kubectl get namespaces/demo -o json
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"creationTimestamp": "2024-05-09T10:59:50Z",
"labels": {
"kubernetes.io/metadata.name": "demo"
},
"name": "demo",
"resourceVersion": "351935",
"uid": "cdd0c611-f532-4870-a23e-12e07809ab47"
},
"spec": {
"finalizers": [
"kubernetes"
]
},
"status": {
"phase": "Active"
}
}
root@kubeadm-master1:~# kubectl get namespaces/demo -o json > ns-demo-term.json编辑ns-demo-term.json文件 , 将其中的spec.finalizers的配置部分修改为如下所示:
.....
},
"spec": {
"finalizers": [
]
},
....而后运行如下命令手动终止demo名称空间:
root@kubeadm-master1:~# kubectl replace --raw "/api/v1/namespaces/demo/finalize" -f ns-demo-term.json
{"kind":"Namespace","apiVersion":"v1","metadata":{"name":"demo","uid":"cdd0c611-f532-4870-a23e-12e07809ab47","resourceVersion":"352425","creationTimestamp":"2024-05-09T10:59:50Z","labels":{"kubernetes.io/metadata.name":"demo"},"managedFields":[{"manager":"kubectl-create","operation":"Update","apiVersion":"v1","time":"2024-05-09T10:59:50Z","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:labels":{".":{},"f:kubernetes.io/metadata.name":{}}}}}]},"spec":{},"status":{"phase":"Active"}}
root@kubeadm-master1:~# kubectl get namespaces/demo -o json
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"creationTimestamp": "2024-05-09T10:59:50Z",
"labels": {
"kubernetes.io/metadata.name": "demo"
},
"name": "demo",
"resourceVersion": "352425",
"uid": "cdd0c611-f532-4870-a23e-12e07809ab47"
},
"spec": {},
"status": {
"phase": "Active"
}
}2.3 声明式对象配置
在命令式对象配置管理机制中 , 若同时指定了多个资源 , 则这些资源必须进行同一种操作(不可以有的进行创建 , 而另外一些进行更新等) , 而且更新操作的replace命令通过完全替换现有活动对象进行资源更新操作 , 对于生产环境来说 , 这并非理想的选择。声明式对象配置操作在管理资源对象时会把配置信息保存在目标对象的注解中 , 并通过比较活动对象的当前配置、前一次管理操作时保存于注解中的配置 , 以及当前命令提供配置生成更新补丁从而完成活动对象的补丁式更新操作。
例如 , 创建前面ns-demo.yaml中定义的名称空间 , 可以直接使用 如下命令进行:
root@kubeadm-master1:~# kubectl apply -f ns-demo.yaml
namespace/demo created若apply的目标对象于集群中已然存在 , 且活动对象的当前配置、 上一次管理操作时保存于注解中的存储 , 以及当前配置清单中的配置存在不同之外 , 则执行的是更新操作。否则 , 活动对象将保持不变。 例如 , 将前面ns-demo-v2.yaml文件定义的配置apply到集群中实现更 新操作的命令如下
root@kubeadm-master1:~# kubectl apply -f ns-demo-v2.yaml
namespace/demo configured命令结果显示资源重新配置完成并已经生效。事实上 , 此类操作也完全能够使用patch命令直接进行补丁操作。而资源对象的删除操作依然可使用apply命令 , 但要同时使用--prune选项 , 命令的格式为 kubectl apply -f --prune -l 。需要注意的 是 , 此命令异常“凶险” , 因为它将基于标签选择器过滤出所有符合条件的对象 , 并检查由-f指定的目录中是否存在某配置文件定义的相应资源对象 , 那些不存在相应定义的资源对象将被删除。因此 , 需要删除资源对象时 , 依然建议使用命令式对象配置的命令kubectl delete进行 , 这样的命令格式操作目标明确且不易出现偏差。