了解一下namespace
抽象的
命名空间是一种将用户创建的资源划分为逻辑命名组的机制。
动机
单个集群应该能够满足多个用户群组的需求。
每个用户群组都希望能够独立于其他群组工作。
每个用户群组都有自己的:
- 资源(Pod、服务、复制控制器等)
- 策略(谁可以或不能在他们的社区中采取行动)
- 限制(这个群组被允许这么多配额等)
集群运营商可以为每个唯一的用户群组创建一个命名空间。
命名空间为以下各项提供了唯一的范围:
- 命名资源(避免基本命名冲突)
- 将管理权限委托给受信任的用户
- 限制群组资源消耗的能力
用例
- 作为集群运营商,我希望在单个集群上支持多个用户群组。
- 作为集群运营商,我想将集群分区的权限委托给这些群组中的受信任用户。
- 作为集群运营商,我想限制每个群组可以消耗的资源量,以限制对使用集群的其他群组的影响。
- 作为集群用户,我希望与与我的用户群组相关的资源进行交互,而不受其他用户群组在集群上的操作的影响。
这个群组可以理解为范围限定最初翻译是社区觉得怪就改了一下。
设计
数据模型
命名空间为多种资源定义了一个逻辑上命名的组。
type Namespace struct { TypeMeta `json:",inline"` ObjectMeta `json:"metadata,omitempty"` Spec NamespaceSpec `json:"spec,omitempty"` 状态 NamespaceStatus `json:"status,omitempty"` }
Namespace名称是DNS兼容标签。
在将内容与名称空间关联之前,名称空间必须存在。
如果有关联的内容,则不能删除命名空间。
将资源关联到Namespace需要满足以下条件:
- 资源的Kind必须在服务器上注册为具有RESTScopeNamespace
- 资源的TypeMeta.Namespace字段必须具有引用现有命名空间的值
与命名空间相关联的资源的名称对该命名空间中的该类型是唯一的。
目的是在资源url中使用;由客户在创建时提供,并鼓励对人友好;旨在促进单例对象的幂等创建、空间唯一性、区分不同的实体以及跨操作引用特定实体。
授权
命名空间为访问与命名空间相关联的内容提供了授权范围。
限制资源消耗
命名空间提供了限制资源消耗的作用域。
限制范围定义了单个实体在命名空间中可以消耗的资源的最小/最大限制。
请参阅准入控制:限制范围
ResourceQuota跟踪命名空间中资源的总体使用情况,允许集群操作人员定义命名空间可能使用的硬资源使用限制。
请参阅准入控制:资源配额
终结者
在创建Namespace时,创建者可以提供Finalizer对象的列表。
键入 FinalizerName 字符串 // 这些是 Kubernetes 的内部终结器,除非在这里定义,否则必须是限定名 const ( FinalizerKubernetes FinalizerName = "kubernetes" ) // NamespaceSpec 描述 Namespace 类型 NamespaceSpec struct { // Finalizers 是一个不透明的值列表,必须为空才能从存储中永久删除对象 Finalizers [] FinalizerName }
FinalizerName是限定名。
API服务器强制Namespace只能在Namespace. spec . finalizer为空时从存储中删除。
finalize操作是修改namspace . spec . finalizer字段创建后的唯一机制。
每个创建的命名空间在默认设置的初始命名空间. spec .终结器列表中都有kubernetes作为项。
阶段
命名空间可能存在于以下阶段。
type NamespacePhase string const( NamespaceActive NamespacePhase = "Active" NamespaceTerminating NamespacePhase = "Terminating" ) type NamespaceStatus struct { ... Phase NamespacePhase }
如果命名空间没有ObjectMeta.DeletionTimestamp,则该命名空间处于活动阶段。
如果命名空间具有ObjectMeta.DeletionTimestamp,则该命名空间处于终止阶段。
活跃的
在创建时,命名空间进入活动阶段。 这意味着内容可能与一个名称空间相关联,并且与该名称空间的所有正常交互都允许在集群中发生。
如果一个Namespace发生DELETE请求,Namespace. objectmeta . deletiontimestamp被设置为当前服务器时间。 namespace控制器观察更改,并将namespace . status . phase设置为Terminating。
终止
命名空间控制器监视具有namespace . objectmeta . deletiontimestamp值设置的命名空间对象,以便知道何时启动集群已知的命名空间相关内容的优雅终止。
命名空间控制器枚举该命名空间中的每个已知资源类型,并逐个删除它。
准入控制阻塞了该名称空间中新资源的创建,以防止出现竞争条件,即控制器可能认为所有给定的资源类型已经从名称空间中删除,而实际上一些其他的非法客户端代理已经创建了新对象。 在这个场景中使用准入控制允许单个对象的每个注册中心实现不需要考虑Namespace生命周期。
一旦命名空间控制器已知的所有对象都被删除,命名空间控制器就会对命名空间执行一个finalize操作,将kubernetes值从namespace . specific . finalizer列表中删除。
如果命名空间控制器看到其ObjectMeta的命名空间。 如果设置了DeletionTimestamp,并且它的Namespace. spec . finalizer列表为空,它将通过向API服务器发送一个最终的DELETE操作来通知服务器将Namespace从存储中永久删除。
在有些情况下,名称空间控制器无法保证清除所有资源。 在清理运行期间,它尝试尽最大努力删除资源,记住发生的错误并通过名称空间状态条件报告回来。 有些错误可能是暂时的,并将在接下来的清理运行中自动解决,其他错误可能需要手动干预。
以下是报告名称空间终止进程的状态条件:
-
NamespaceDeletionDiscoveryFailure报告命名空间终止的第一阶段-资源发现期间的错误。
-
NamespaceDeletionGroupVersionParsingFailure报告在解析所有发现的资源的GVK时发生的错误。
-
NamespaceDeletionContentFailure报告错误,阻止控制器删除属于成功发现和解析的GVK的资源。
当某个阶段的任何部分失败时,名称空间控制器将设置适当的状态条件,并提供一个描述错误的消息。
控制器成功通过该阶段后,它将设置状态条件以报告成功。
失败的命名空间终止的示例,其中NamespaceDeletionContentFailure不再报告任何错误,而NamespaceDeletionDiscoveryFailure继续失败。
"status": { "phase": "Terminating", "conditions": [ { "type": "NamespaceDeletionDiscoveryFailure", "status": "True", "lastTransitionTime": "2021-06-12T08:43:29Z", "reason": "DiscoveryFailed", "message": "Discovery failed for some groups, 2 failing: unable to retrieve the complete list of server APIs: discovery.k8s.io/v1: the server could not find the requested resource, policy/v1: the server could not find the requested resource" }
REST API
与命名空间API交互:
Action | HTTP Verb | Path | Description |
---|---|---|---|
CREATE | POST | /api/{version}/namespaces | Create a namespace |
LIST | GET | /api/{version}/namespaces | List all namespaces |
UPDATE | PUT | /api/{version}/namespaces/{namespace} | Update namespace {namespace} |
DELETE | DELETE | /api/{version}/namespaces/{namespace} | Delete namespace {namespace} |
FINALIZE | PUT | /api/{version}/namespaces/{namespace}/finalize | Finalize namespace {namespace} |
WATCH | GET | /api/{version}/watch/namespaces | Watch all namespaces |
此规范将名称finalize保留为命名空间的子资源。
因此,由类型为finalize的名称空间管理resourceType是无效的。
与与命名空间相关联的内容进行交互:
Action | HTTP Verb | Path | Description |
---|---|---|---|
CREATE | POST | /api/{version}/namespaces/{namespace}/{resourceType}/ | Create instance of {resourceType} in namespace {namespace} |
GET | GET | /api/{version}/namespaces/{namespace}/{resourceType}/{name} | Get instance of {resourceType} in namespace {namespace} with {name} |
UPDATE | PUT | /api/{version}/namespaces/{namespace}/{resourceType}/{name} | Update instance of {resourceType} in namespace {namespace} with {name} |
DELETE | DELETE | /api/{version}/namespaces/{namespace}/{resourceType}/{name} | Delete instance of {resourceType} in namespace {namespace} with {name} |
LIST | GET | /api/{version}/namespaces/{namespace}/{resourceType} | List instances of {resourceType} in namespace {namespace} |
WATCH | GET | /api/{version}/watch/namespaces/{namespace}/{resourceType} | Watch for changes to a {resourceType} in namespace {namespace} |
WATCH | GET | /api/{version}/watch/{resourceType} | Watch for changes to a {resourceType} across all namespaces |
LIST | GET | /api/{version}/list/{resourceType} | List instances of {resourceType} across all namespaces |
API服务器在资源创建时验证命名空间是否与路径上的{Namespace}匹配。
如果最终用户没有基于传入请求的Namespace上下文填充资源,API服务器将把资源与Namespace关联起来。 如果正在创建或更新的资源的Namespace与请求中的Namespace不匹配,那么API服务器将拒绝该请求。
存储
命名空间提供唯一的标识符空间,因此必须位于资源的存储路径中。
在etcd中,我们希望继续支持有效的跨名称空间WATCH。
将内容保存在etcd中的资源的存储路径如下:
/ {k8s_storage_prefix} / {resourceType} / {resource.Namespace} / {resource.Name}
这使得消费者可以通过WATCH /registry/{resourceType}来查看特定{resourceType}的名称空间的变化。
Kubelet
kubelet会用一个与集群id相关联的名称空间从文件或http源注册pod的it源
例如:OpenShift Origin管理Kubernetes命名空间
在本例中,我们将演示该设计如何允许在Kubernetes之上构建代理,这些代理管理它们自己的与Namespace关联的资源类型集,以参与Namespace终止。
OpenShift在Kubernetes中创建一个命名空间
例如:OpenShift Origin管理Kubernetes命名空间
在本例中,我们将演示该设计如何允许在Kubernetes之上构建代理,这些代理管理它们自己的与Namespace关联的资源类型集,以参与Namespace终止。
OpenShift在Kubernetes中创建一个命名空间
{ "apiVersion":"v1", "kind": "Namespace", "metadata": { "name": "development", "labels": { "name": "development" } }, "spec": { "finalizers": ["openshift.com/origin", "kubernetes"] }, "status": { "phase": "Active" } }
OpenShift然后创建一组与“开发”名称空间相关联的资源(荚、服务等)。 它还在自己的存储中创建自己的资源集,这些资源与Kubernetes未知的“开发”名称空间相关联。
用户在Kubernetes中删除命名空间,命名空间现在有以下状态:
{ "apiVersion":"v1", "kind": "Namespace", "metadata": { "name": "development", "deletionTimestamp": "...", "labels": { "name": "development" } }, "spec": { "finalizers": ["openshift.com/origin", "kubernetes"] }, "status": { "phase": "Terminating" } }
Kubernetes名称空间控制器观察到名称空间有一个deletionTimestamp,并开始终止它所知道的名称空间中的所有内容。 成功后,它执行一个finalize操作,通过从终结器列表中删除kubernetes来修改命名空间:
{ "apiVersion":"v1", "kind": "Namespace", "metadata": { "name": "development", "deletionTimestamp": "...", "labels": { "name": "development" } }, "spec": { "finalizers": ["openshift.com/origin"] }, "status": { "phase": "Terminating" } }
OpenShift Origin有自己的命名空间控制器,该控制器正在观察集群状态,并且它观察到同一个命名空间有一个分配给它的deletionTimestamp。 它也将从自己管理的与该名称空间相关联的存储中清除资源。 完成后,它执行一个finalize操作,并从终结器列表中删除对“openshift.com/origin”的引用。
这将导致以下状态
{ "apiVersion":"v1", "kind": "Namespace", "metadata": { "name": "development", "deletionTimestamp": "...", "labels": { "name": "development" } }, "spec": { "finalizers": [] }, "status": { "phase": "Terminating" } }
此时,同步循环中的Kubernetes名称空间控制器将看到名称空间有一个删除时间戳,并且它的终结器列表是空的。 因此,它知道与该名称空间相关联的所有内容都已被清除。 它执行最后一个DELETE操作从存储中删除命名空间。
此时,与该名称空间相关的所有内容以及名称空间本身都消失了
那么上面内容简单要点总结:名称空间下所有关联资源全部删除后,才会删除finalizers
。而
finalizers
的删除才会最终删除空间资源
https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/namespaces.md#finalizers