Namespace で分けられるもの、分けられないもの

v1.37 時点(2026年10月26日 確認)

Kubernetes 基本仕様第37回 / 全45回 ・ 第8部 セキュリティとアクセス制御
目次

この記事では 1 つのクラスタの中でリソースをグループに分ける Namespace の仕組みを、図で説明します。Namespace で分けられるもの(名前の範囲や、ResourceQuota などが効く範囲)と、分けられないもの(ノードのようなクラスタ全体のリソースや、Pod どうしの通信)の境目がわかります。Namespace を消すと中のリソースがどうなるのかもわかります。後半では kind のクラスタで、2 つの Namespace に同じ名前のリソースを作り、Namespace を消すと中身も消える様子を試す手順を示します。

この回から第8部(セキュリティとアクセス制御)に入ります。Namespace は第3回で「リソースをグループに分ける仕組み」として紹介し、その後の多くの回で「仕組みは第37回」と予告してきました。この回では第4回で見た kube-system や kube-node-lease の内容を前提にしています。まだの方は先にこちらをどうぞ。

基本仕様 ・ 第4回 コントロールプレーンとノードの構成クラスタを形づくるコントロールプレーンとノードの構成を図で説明します。kube-apiserver・etcd・kube-scheduler・kube-controller-manager と、kubelet・コンテナランタイム・kube-proxy の役割を押さえ、kind のクラスタで kube-system の Pod を一覧して各コンポーネントと対応づける手順を紹介します。

以下の図は 1 つのクラスタの中で、Namespace に属するリソースと、Namespace に属さないクラスタ全体のリソースがどこにあるかを表しています。後半の手順で作る Namespace team-a と team-b を例にしています。

Namespace ごとに分かれるリソースと、Namespace に属さないクラスタ全体のリソース

team-a と team-b には、同じ app-config という名前の ConfigMap があります。Namespace が違えば、同じ種類のリソースに同じ名前を付けられるからです。一方、ノードや PersistentVolume は、どの Namespace にも属しません。右の枠の Namespace は team-a や team-b のような Namespace のリソースそのものです。左の 2 つの枠はそれぞれの Namespace に属するリソースの範囲を表しています。Namespace そのものが右の枠に入る理由は「Namespace に属するリソースと属さないリソース」で説明します。2 つの Namespace をつなぐ両向きの矢印は、既定では Pod どうしの通信が Namespace をまたいで互いに届くことを表しています。図では Pod がどのノードで動くかを省いています。

参考:Namespaces | Kubernetes、Namespaces | Kubernetes、Multi-tenancy | Kubernetes

Namespace とは

Namespace は 1 つのクラスタの中で、リソースのグループを分けて隔てるための仕組み です。公式ドキュメントは Namespace について、次の 3 つを説明しています。

  • Namespace は名前の範囲になる(名前は Namespace の中で重ならなければよい)
  • Namespace の中に Namespace は作れない(入れ子にできない)
  • 1 つのリソースが属せる Namespace は 1 つだけ

参考:Namespaces | Kubernetes、Namespaces | Kubernetes

ただし、すべてのリソースが Namespace に属するわけではありません。どのリソースが属し、どれが属さないかは「Namespace の仕組み」で説明します。

Namespace そのものも Kubernetes のリソースで、apiVersion は v1、kind は Namespace です。Namespace の名前は第23回で見たとおり DNS の名前の一部になるので、RFC 1123 の DNS ラベルの形でなければなりません(must)。DNS ラベルは第8回で見た、63 文字以内で小文字の英数字と - だけを使うなどの名前の決まりです。

参考:Namespaces | Kubernetes、Share a Cluster with Namespaces | Kubernetes、Object Names and IDs | Kubernetes、Namespace | Kubernetes API Reference

なぜ Namespace が必要なのか

1 つのクラスタをいくつものチームやプロジェクトで分け合う場面を考えます。公式ドキュメントのタスクのページは、Namespace が異なるプロジェクト、チーム、顧客のあいだで 1 つのクラスタを分け合うのを助けると説明しています。そのために Namespace が提供するのは、名前の範囲と、クラスタの一部分に認可と決まり(ポリシー)を結び付ける仕組みの 2 つです。認可は第3回で見た、その操作をしてよいかの判断です。

参考:Share a Cluster with Namespaces | Kubernetes

Namespace を分けずに 1 つの Namespace をみんなで使うと、すべてのチームのリソースが 1 つの名前の範囲に入ります。あるチームが app-config という ConfigMap を作ると、ほかのチームは同じ名前を使えません。資源の上限(第30回の ResourceQuota)や権限(第38回の RBAC)も、チームごとに分けて決めにくくなると考えられます。同じページによると、Namespace は名前の衝突を避けるとき、信頼できる利用者に管理を任せるとき、利用者のまとまりごとに資源の使い方を制限するときの範囲になります。

参考:Share a Cluster with Namespaces | Kubernetes

一方で、Namespace はいつも要るものではありません。公式ドキュメントの勧めはクラスタの使われ方で 2 つに分かれます。1 つは利用者の数で、Namespace は多くの利用者が複数のチームやプロジェクトに分かれている環境のためのものです。利用者が数人から数十人のクラスタなら、Namespace を作ったり考えたりする必要はまったくないはずだ(should not need)と書かれています。Namespace は、それが提供する機能が必要になってから使い始めます。同じソフトウェアのバージョン違いのような、少しだけ違うリソースを分けるために Namespace を分ける必要はありません。そのときは同じ Namespace の中でラベル(第11回)を使って見分けます。

参考:Namespaces | Kubernetes

もう 1 つは本番かどうかです。公式ドキュメントは、本番のクラスタでは default の Namespace を使わないことを検討する(consider)よう勧め、ほかの Namespace を作って使うよう書いています。その理由はこのメディアで確かめた範囲の公式ドキュメントには書かれていません。2 つを合わせると、利用者の少ない手元のクラスタなら default だけで困らないが、本番のクラスタでは自分の Namespace を作るのを検討する、と読めます。さらに、複数の利用者でクラスタを共有する環境(マルチテナント)に限った話として、マルチテナントのページは、同じ利用者が動かすワークロードでもワークロードごとに Namespace を分けるのがよくあるやり方だと紹介しています。

参考:Namespaces | Kubernetes、Multi-tenancy | Kubernetes

Namespace の仕組み

Namespace に属するリソースと属さないリソース

公式ドキュメントによると、Pod、Service、Deployment など、ほとんどのリソースはどれかの Namespace に属します。ただし Namespace のリソースそのものは Namespace に属しません。ノードや PersistentVolume のような低いレベルのリソースも、どの Namespace にも属しません。どのリソースが Namespace に属するかは、kubectl api-resources に --namespaced=true または --namespaced=false を付けて確かめられます。

参考:Namespaces | Kubernetes、kubectl api-resources | Kubernetes

kubectl のリファレンスには、kubectl api-resources で取り出したリソースの種類の表があります。このシリーズで扱ってきた種類を、その表の NAMESPACED 列で分けると次のとおりです。表には、Kubernetes v1.25.0 の時点で正確だったものだと断り書きがあります。

NAMESPACEDリソースの種類(扱った回)
true(Namespace に属する)Pod(第8回)、Deployment(第12回)、ConfigMap(第17回)、Secret(第18回)、Service(第21回)、NetworkPolicy(第25回)、PersistentVolumeClaim(第27回)、LimitRange と ResourceQuota(第30回)、Lease(第4回)、Event(第3回)、ServiceAccount、Role、RoleBinding
false(Namespace に属さない)Namespace、Node(第4回)、PersistentVolume(第27回)、StorageClass(第27回)、IngressClass(第24回)、APIService(第35回)、ClusterRole、ClusterRoleBinding、CustomResourceDefinition

参考:Command line tool (kubectl) | Kubernetes

Event は第3回で触れた、クラスタのどこかで起きた出来事の報告で、kubectl describe の Events: の欄に並ぶものです。ServiceAccount、Role、RoleBinding、ClusterRole、ClusterRoleBinding は第38回、CustomResourceDefinition は第44回で扱います。

参考:Event | Kubernetes API Reference

この違いは API のパスにも表れます。第5回で見たとおり、Pod のような Namespace に属するリソースのパスには /namespaces/<Namespace>/ が入ります。公式ドキュメントによると、すべてのリソースの種類は、クラスタの範囲のもの(/apis/GROUP/VERSION/*)か、Namespace の範囲のもの(/apis/GROUP/VERSION/namespaces/NAMESPACE/*)のどちらかです。ノードのようなクラスタの範囲のリソースのパスには、Namespace を入れる場所がありません。そのため、kubectl でノードを一覧するときに Namespace を指定しても、一覧は Namespace で分かれないと考えられます。後半の手順で確かめます。

参考:Kubernetes API Concepts | Kubernetes

名前の決まりもこの区別に沿っています。公式ドキュメントによると、Kubernetes は API グループ、リソースの種類、Namespace(Namespace に属する種類の場合)、名前の 4 つでオブジェクトを区別します。同じ Namespace に myapp-1234 という名前の Pod は 1 つしか置けませんが、Pod と Deployment なら同じ myapp-1234 を付けられます。Namespace に属さない種類では Namespace が区別に入らないので、名前が重なってはいけない範囲はクラスタ全体だと読めます。

参考:Object Names and IDs | Kubernetes

最初からある 4 つの Namespace

公式ドキュメントによると、Kubernetes は 4 つの Namespace がある状態で始まります。それぞれの用途を次の表にまとめます。

Namespace公式ドキュメントの説明
defaultNamespace を先に作らなくても、新しいクラスタを使い始められるようにするための Namespace。タスクのページでは、ほかの Namespace を持たないオブジェクトのための既定の Namespace
kube-node-leaseノードごとの Lease を置く Namespace。kubelet はこれでハートビートを送り、コントロールプレーンはノードの故障を見つける(第4回)
kube-public認証されていないものも含めて、すべてのクライアントが読める Namespace。主にクラスタが使うためのもので、「公開」は慣習で、必須の決まりではない
kube-systemKubernetes のシステムが作るオブジェクトのための Namespace(第4回)

参考:Namespaces | Kubernetes、Share a Cluster with Namespaces | Kubernetes

kube- で始まる名前は Kubernetes のシステムの Namespace のために予約されています。そのため公式ドキュメントは kube- で始まる名前の Namespace を作らないよう(Avoid)注意しています。第4回の注意点で「作らないよう勧められている」と書いたのは、この注意のことです。

参考:Namespaces | Kubernetes

最初からある 4 つのうち 3 つは消せないように守られています。kube-apiserver の NamespaceLifecycle というアドミッションコントローラーは、システムが予約した 3 つの Namespace(default、kube-system、kube-public)の削除を防ぎます。アドミッションコントローラーは第30回で見た、kube-apiserver へのリクエストを保存する前に確かめるもので、第40回で詳しく扱います。v1.37 の公式ドキュメントでは、NamespaceLifecycle は既定で有効なアドミッションコントローラーの一覧に入っています。kube-node-lease はこの 3 つに含まれていません。消したときにどうなるかは、このメディアで確かめた範囲の公式ドキュメントには書かれていません。

参考:Admission Control in Kubernetes | Kubernetes、Admission Control in Kubernetes | Kubernetes

操作する Namespace の決まり方

kubectl で Namespace に属するリソースを扱うとき、どの Namespace を対象にするかは次の順で決まります。

順決め方
1コマンドに -n(--namespace)を付けたら、その Namespace
2付けていなければ、コンテキストの namespace(第3回)
3コンテキストに namespace が無ければ、default だと考えられる(第3回、第5回)

参考:Namespaces | Kubernetes、Command line tool (kubectl) | Kubernetes、kubectl get | Kubernetes

表は手元の PC のようにクラスタの外で kubectl を動かす場合です。Pod の中で kubectl を動かす場合は決まり方が違いますが、このシリーズでは扱いません。3 番目は第3回と同じく、公式ドキュメントに明記されていないので推測です。手がかりは、このあと見る API リファレンスの「空の Namespace は default と同じ扱い」という説明です。後半の「コンテキストの Namespace を変える」の段で、この動きを確かめます。

kubectl get に -A(--all-namespaces)を付けると、すべての Namespace のリソースを一覧します。このとき、現在のコンテキストの Namespace は使われず、-n(--namespace)で Namespace を指定しても無視されます。

参考:Command line tool (kubectl) | Kubernetes、kubectl get | Kubernetes

マニフェストの metadata.namespace にはリソースを置く Namespace を書けます。API リファレンスによると、このフィールドは名前が重なってはいけない範囲を決めるもので、空の Namespace は default と同じ扱いです。Namespace に属さないオブジェクトでは、このフィールドは空になります。metadata.namespace は作ったあとで変えられません(Cannot be updated)。別の Namespace に置きたくなったら、その Namespace に作り直すことになると考えられます。

参考:ObjectMeta | Kubernetes API Reference

コンテキストの namespace は公式ドキュメントの次のコマンドで変えられます。そのコンテキストで、以降のすべての kubectl のコマンドが使う Namespace を保存する、と説明されています。

console
$ kubectl config set-context --current --namespace=<insert-namespace-name-here>

参考:Namespaces | Kubernetes、kubectl config set-context | Kubernetes

--current は現在のコンテキストを書き換える指定です。リファレンスの書式(kubectl config set-context [NAME | --current])のとおり、--current の代わりにコンテキストの名前を書くこともできます。第3回で見たとおり、kubectl config のコマンドは kubeconfig のファイルを書き換えます。そのため、このコマンドは --context のようにその 1 回だけに効くのではなく、公式ドキュメントの説明のとおり、以降のコマンドにも効き続けます。

後半の手順では --current ではなく kind-kind を名前で指定します。このシリーズでは kubectl config use-context で現在のコンテキストを切り替えず、--context でクラスタを指定してきました(第3回)。現在のコンテキストが kind-kind だとは限らないので、名前で指定します。また、kubectl config set-context には --context を付けません。書き換えるコンテキストは、引数の kind-kind で決まるからです。

参考:kubectl config set-context | Kubernetes、kubectl config | Kubernetes

Namespace で分けられるもの

Namespace で分けられるものは大きく 3 つで、ここまで見た名前の範囲、Namespace の中でしか参照できないもの、Namespace ごとに効く決まりです。

Pod の定義から参照する ConfigMap(第17回)や PersistentVolumeClaim(第27回)は、それを使う Pod と同じ Namespace になければなりません(must)。第18回で見たとおり、Pod のボリュームの secretName も Pod と同じ Namespace の Secret の名前です。ただし第17回で見たとおり、アプリケーションが Kubernetes の API を直接使えば、別の Namespace の ConfigMap も読めます。第6回で見た所有者の参照(ownerReferences)も同じで、公式ドキュメントによると、Namespace をまたぐ参照は設計上許されていません。Namespace に属する所有者は、従うオブジェクトと同じ Namespace になければなりません(must)。

参考:ConfigMaps | Kubernetes、Persistent Volumes | Kubernetes、Pod | Kubernetes API Reference、Garbage Collection | Kubernetes

Namespace は決まりを当てはめる範囲にもなります。マルチテナントのページによると、Kubernetes のセキュリティの決まりの多くは Namespace の範囲で働きます。たとえば RBAC の Role と NetworkPolicy は Namespace に属するリソースで、RBAC を使えば、利用者や ServiceAccount を 1 つの Namespace に限れます。Namespace の範囲で働く主なものを次の表にまとめます。

仕組みNamespace との関係
ResourceQuota、LimitRange(第30回)置いた Namespace の中だけに効く
Role、RoleBinding(第38回)Namespace の単位でアクセスを制御する。ClusterRole と ClusterRoleBinding は Namespace に属さない
NetworkPolicy(第25回)ポリシーを置いた Namespace の中で、適用する Pod を選ぶ(空の podSelector はその Namespace のすべての Pod)
Pod Security Admission(第39回)Namespace に付けるラベルで、Pod に求める基準を Namespace ごとに決める

参考:Multi-tenancy | Kubernetes、Multi-tenancy | Kubernetes、Command line tool (kubectl) | Kubernetes、Resource Quotas | Kubernetes、NetworkPolicy | Kubernetes API Reference、Pod Security Admission | Kubernetes

決まりの中には Namespace をまたいで相手を選べるものもあります。第25回の NetworkPolicy の namespaceSelector と、第33回で触れた Pod Affinity と Pod Anti-Affinity の namespaces と namespaceSelector がそれにあたります。これらを書かなかったときの相手は、仕組みごとに次のように決まります。

NetworkPolicy では、相手の指定に namespaceSelector を書かずに podSelector だけを書くと、ポリシーと同じ Namespace の Pod が相手になります。空の namespaceSelector はすべての Namespace を選びます。

参考:NetworkPolicy | Kubernetes API Reference

Pod Affinity と Pod Anti-Affinity では、namespaces が空で namespaceSelector も書かれていなければ、規則を書いた Pod の Namespace が対象になります。空の namespaceSelector({})はすべての Namespace に当てはまります。

参考:Assigning Pods to Nodes | Kubernetes

Namespace で分けられないもの

Namespace は名前の範囲を分けますが、何でも分けるわけではありません。公式ドキュメントで確かめられる、Namespace で分けられないものを次の表にまとめます。

分けられないもの公式ドキュメントの説明
ノード、PersistentVolume、StorageClass などNamespace に属さないクラスタ全体のリソース。CustomResourceDefinition(第44回)や Webhook(アドミッションの Webhook の設定など)にも Namespace の分離が当てはまらない
API の操作の権限(Namespace を作るだけでは分かれないと読める)複数のチームで使う環境では、RBAC で利用者のアクセスを必要な Namespace に絞らなければならない(must)(第38回)
Pod どうしの通信既定では、クラスタのすべての Pod は互いに通信できる。NetworkPolicy で制御できる(第25回)
DNS の名前引き既定では、Kubernetes の DNS はクラスタのすべての Namespace をまたいで名前を引ける(第23回)
Pod を動かすノードいくつもの Namespace の Pod が、同じノードで動くことがある(第30回)

参考:Namespaces | Kubernetes、Multi-tenancy | Kubernetes、Multi-tenancy | Kubernetes、Multi-tenancy | Kubernetes、Multi-tenancy | Kubernetes、Resource Quotas | Kubernetes

アドミッションの Webhook は kube-apiserver に届いたリクエストを HTTP で受け取って処理する仕組みで、第40回で扱います。

参考:Dynamic Admission Control | Kubernetes

権限は Namespace を分けただけでは分かれないと読めます。-n は操作する範囲を選ぶだけで、ほかの Namespace の操作を止めるのは第38回の RBAC のような認可の仕組みだと考えられます。公式ドキュメントの API の説明によると、Namespace に属するリソースへのアクセスは、Namespace の範囲の認可の確認で制御されます。マルチテナントのページは、利用者どうしが互いの API のリソースにアクセスしたり変更したりできると、ほかの種類の決まりも変えたり外したりできてしまうと説明しています。そのうえで、複数のチームで使う環境では、RBAC で利用者のアクセスを必要な Namespace に絞らなければならない(must)としています。第18回で見た「ある Namespace で Pod を作れる人は、その Namespace の Secret を読める」という注意も、Namespace と RBAC を組み合わせて考える理由の 1 つだと考えられます。

参考:Kubernetes API Concepts | Kubernetes、Multi-tenancy | Kubernetes、Multi-tenancy | Kubernetes、Secrets | Kubernetes

なお、タスクのページの「ある Namespace を操作する利用者には、ほかの Namespace の中身は見えない」という説明は、-n で一覧の範囲を選んだ例の話で、権限で隠しているわけではないと読めます。同じページは、Kubernetes のポリシーの機能が進むにつれて、この例を Namespace ごとに違う認可の決まりを与える形に広げられる、と書いています。

参考:Share a Cluster with Namespaces | Kubernetes

表の通信と DNS の行は、説明に「既定では」が付いています。Pod どうしの通信は第25回の NetworkPolicy で、Namespace のラベルなどを使って絞れます。ただし NetworkPolicy を使うには、それに対応したネットワークのプラグインが要ります(第25回)。マルチテナントのページは、利用者のあいだで厳しくネットワークを分ける必要がある環境では、Pod どうしの通信を拒否する既定のポリシーから始めるよう勧めています。そのとき、すべての Pod が名前解決のために DNS のサーバーに問い合わせられるようにする規則を、別に足すとしています。DNS の名前引きは DNS のサービスに決まりを設定すれば、Namespace の中に限れるとされています。

参考:Network Policies | Kubernetes、Multi-tenancy | Kubernetes、Multi-tenancy | Kubernetes

ストレージには、Namespace で分けられる部分と分けられない部分があります。マルチテナントのページによると、PersistentVolumeClaim は Namespace に属するので、ストレージの一部を利用者ごとに分けるのに使えます。一方、PersistentVolume はクラスタ全体のリソースで、ワークロードや Namespace とは別のライフサイクルを持ちます。そのため Namespace を消すと、中の PersistentVolumeClaim は一緒に消えますが、PersistentVolume は第27回で見た回収の方針(reclaim policy)に従って扱われると考えられます。

参考:Multi-tenancy | Kubernetes、Persistent Volumes | Kubernetes

自動で付くラベル

公式ドキュメントによると、コントロールプレーンはすべての Namespace に、変えられないラベル kubernetes.io/metadata.name を付けます。ラベルの値は Namespace の名前です。この機能は v1.22 から Stable(安定版)です。第25回では NetworkPolicy の namespaceSelector にこのラベルを書いて、特定の Namespace を名前で選べることを見ました。

参考:Namespaces | Kubernetes、Network Policies | Kubernetes

Namespace を消すと中身も消える

Namespace を消すと、その中のものがすべて削除されます。公式ドキュメントのタスクのページは、Namespace の削除に警告を付けて、Namespace の下のすべてを削除すると注意しています。API の説明にも、Namespace の範囲のリソースは、その Namespace が消されると削除される、とあります。この削除は非同期に進むので、しばらくのあいだ Namespace は Terminating の状態で見えます。第30回の片付けで quota-demo を消すと中の Pod や ResourceQuota が一緒に消えるのは、この仕組みによるものです。

参考:Share a Cluster with Namespaces | Kubernetes、Kubernetes API Concepts | Kubernetes

Namespace の状態(フェーズ)は次の 2 つです。

フェーズ公式ドキュメントの説明
ActiveNamespace は使われている(使える)状態
TerminatingNamespace は削除中で、新しいオブジェクトには使えない

参考:Share a Cluster with Namespaces | Kubernetes、Namespace | Kubernetes API Reference

さきほどの NamespaceLifecycle は、Terminating の Namespace に新しいオブジェクトを作らせず、存在しない Namespace へのリクエストも拒否します。同じ節は、Namespace の削除がその Namespace のすべてのオブジェクト(Pod や Service など)を消す一連の処理を始める、と説明しています。

参考:Admission Control in Kubernetes | Kubernetes

Namespace が完全に消えるまでには、finalizer(ファイナライザー)がかかわります。finalizer は第9回で名前だけ見た、決まった条件が満たされるまでリソースを完全には削除しないよう Kubernetes に伝える印です。公式ドキュメントの Finalizers のページによると、finalizer が付いたオブジェクトの削除は、担当のコントローラーが片付けを終えて finalizer を外すまで終わりません。第27回で見た PersistentVolumeClaim の kubernetes.io/pvc-protection もその例です。Finalizers のページはこうした finalizer を、どのオブジェクトにもある metadata.finalizers の項目として説明しています。

参考:Finalizers | Kubernetes、Persistent Volumes | Kubernetes、ObjectMeta | Kubernetes API Reference

Namespace には metadata.finalizers とは別に、spec.finalizers という一覧もあります。API リファレンスによると、Namespace が完全に消えるには spec.finalizers が空になる必要があり、ほかのオブジェクトと同じく metadata.finalizers も空である必要があります。タスクのページは、Namespace に書ける省略可能な finalizers のフィールドについて、存在しない finalizer(どのコントローラーも扱わない名前の finalizer と読めます)を書くと、Namespace は作れても、削除しようとすると Terminating のまま止まってしまうと注意しています。このフィールドが spec と metadata のどちらの一覧なのかは、そのページには書かれていません。API リファレンスの spec.finalizers の説明がこのページを案内しているので、spec.finalizers の話だと考えられます。

参考:Namespace | Kubernetes API Reference、ObjectMeta | Kubernetes API Reference、Share a Cluster with Namespaces | Kubernetes

以下の図は Namespace の削除をリクエストしてから、Namespace が消えるまでの状態の移り変わりを表しています。

削除をリクエストした Namespace の状態の移り変わり

削除をリクエストすると、Namespace は Terminating になり、中のリソースが消されていきます。finalizer の一覧が空になると、Namespace そのものが消えます。図には描いていませんが、中身を消し終えてから finalizer が空になるという順番は、次に説明する設計文書から考えられるものです。中身を消して回るのも次に述べるコントローラーだと考えられます。赤の道は存在しない finalizer を書いた Namespace のように、finalizer が外れずに止まってしまう場合です。

参考:Share a Cluster with Namespaces | Kubernetes、Namespace | Kubernetes API Reference

中身を消して spec.finalizers の kubernetes という finalizer を外すのは、kube-controller-manager の namespace-controller だと考えられます。このメディアで確かめた範囲の v1.37 の公式ドキュメントには、はっきり書かれていません。手がかりの 1 つ目は kube-controller-manager のリファレンスです。コントローラーの一覧に namespace-controller があり、既定で無効なコントローラーには入っていません。同時に処理する Namespace の数を決める --concurrent-namespace-syncs は、Namespace の終了にかかわるフラグとして説明されています。2 つ目は、タスクのページが案内している Namespace の設計文書(アーカイブ)です。そこには、Namespace のコントローラーが中のリソースを種類ごとに 1 つずつ消すこと、作られた Namespace の spec.finalizers には既定で kubernetes が入ること、中身を消し終えたら finalizer を外すことが書かれています。ただし設計文書は古い提案で、今の実装が同じかは公式ドキュメントでは確かめられません。

参考:kube-controller-manager | Kubernetes、Share a Cluster with Namespaces | Kubernetes、namespaces.md · kubernetes/design-proposals-archive

Terminating のまま止まった Namespace を見ると、finalizer を手で外したくなるかもしれません。公式ドキュメントの Finalizers のページは、削除中のまま止まったオブジェクトでも、finalizer を手で外して削除を進めることは避けるよう注意しています。finalizer にはふつう理由があり、無理に外すとクラスタに問題を起こすことがあるからです。手で外すのは、その finalizer の目的を理解し、別の方法で目的を果たしたとき(関係するオブジェクトを手で片付けたときなど)だけにするべきだ(should)としています。

参考:Finalizers | Kubernetes

手元で試す

ここまでの内容を手元の kind のクラスタで試す手順を示します。最初からある Namespace と、Namespace に属するリソースの種類を確かめたあと、2 つの Namespace に同じ名前の ConfigMap を作ります。続けて、クラスタ全体のリソースは Namespace を指定しても分かれないこと、コンテキストの Namespace を変えるとどうなるかを確かめます。最後に Namespace を消して、中の ConfigMap も消えることを確かめます。

この節で引用する出力の例は、公式ドキュメントに載っている、ほかのクラスタで取ったもので、名前や時間などの値は手元とは違います。各段に書く成功の目安は公式ドキュメントから予想される結果で、手元で実行して確かめたものではありません。

コマンドは macOS や Linux のシェル(bash や zsh)で実行する前提で書いています。Windows では WSL(Windows の中で Linux を動かす仕組み)などを使ってください。

試す環境は次のとおりです。

項目内容
kindv0.33.0
Kubernetesv1.37.0(kind v0.33.0 の既定のノードイメージ)
ノード構成シングルノード(クラスタ名 kind):コントロールプレーン 1
必要なものDocker、kubectl(v1.36〜v1.38)、テキストエディタ、端末(ターミナル)2 つ

参考:Release v0.33.0 · kubernetes-sigs/kind、Version Skew Policy | Kubernetes

この回では第30回と同じく、シングルノードのクラスタを使います。Namespace を作ったり消したりするのは kube-apiserver などのコントロールプレーンの仕事で、ノードが 1 つでも確かめられるからです。kind でクラスタを作る手順は、以下の記事で解説しています。

基本仕様 ・ 第2回 kind で検証用のクラスタを作るDocker のコンテナをノードにして、手元のマシンに Kubernetes のクラスタを作るツール kind の仕組みを図で説明します。kind create cluster で何が起きるかを押さえ、シングルノードとマルチノードのクラスタを作って、ノードの正体が Docker のコンテナであることを確かめる手順を紹介します。

この回では端末を 2 つ使います。これまでの回と同じく、1 つ目の端末は変化の監視(この回では Namespace)に取っておきます。クラスタの準備も含めて、操作は 2 つ目の端末で行います。2 つ目の端末を開いたら、cd でマニフェストを保存するディレクトリに移動しておきます。

シングルノードのクラスタを用意する

2 つ目の端末で、前の回のクラスタが残っていないかを確かめます。

console
$ kind get clusters

kind が表示されたら、作り直さずにそのまま使えるので、クラスタを作る次のコマンドは飛ばします。表示されなければ、クラスタを作ってから、もう一度一覧します。前の回までの multi-node が表示されても、この回では使いません。手元のマシンの資源(メモリなど)に余裕がなければ、kind delete cluster --name multi-node で消してから進めてください。

console
$ kind create cluster
$ kind get clusters

kind get clusters に kind が表示されれば、クラスタができています。第3回で決めたとおり、ここからのコマンドには --context kind-kind を付けて、操作するクラスタをはっきりさせます。続けて、ノードを一覧します。

console
$ kubectl get nodes --context kind-kind

ノードが 1 つ表示され、STATUS 列が Ready になっていれば準備ができています。Ready になっていなければ、少し待ってからもう一度実行します。

参考:Quick Start | kind、kubectl get | Kubernetes

前の回のクラスタを使い続けている場合は、この回で使う team-a と team-b の Namespace が無いことも確かめます。

console
$ kubectl get namespace team-a team-b --context kind-kind

team-a と team-b のそれぞれについて、見つからないことを知らせる行が出れば、この回の手順をそのまま進められます。どちらかが表示されたら、自分で作ったものかを確かめます。消すと中のリソースも一緒に消えるので、残したいものが無いかも先に確かめてください。そのうえで kubectl delete namespace <名前> --context kind-kind で消します。

最初からある Namespace を確かめる

2 つ目の端末で、クラスタの Namespace を一覧します。

console
$ kubectl get namespaces --context kind-kind

公式ドキュメントの例では次のように表示されています。

NAME              STATUS   AGE
default           Active   1d
kube-node-lease   Active   1d
kube-public       Active   1d
kube-system       Active   1d

参考:Namespaces | Kubernetes

最初からある 4 つの Namespace がどれも Active で並んでいます。手元の表示は、例と次の点が違うと考えられます。

違い手元の表示
並ぶ Namespace4 つに加えて、kind が入れる local-path-storage の行もある(第4回)
AGE 列クラスタを作ってからの時間なので、1d ではなく数分などの短い値

参考:kind のソースコード(local-path-provisioner)

local-path-storage は、第4回で kind v0.33.0 のソースコードで確かめた Namespace です。コマンドの namespaces は namespace でも短い名前の ns でも同じです(第3回)。

参考:Command line tool (kubectl) | Kubernetes、Command line tool (kubectl) | Kubernetes

Namespace を監視する

1 つ目の端末で、Namespace を監視します。Namespace は Namespace に属さないので、-n は付けません。この監視は片付けの前まで止めずに続けます。

console
$ kubectl get namespaces --watch --context kind-kind

参考:kubectl get | Kubernetes

さきほど 2 つ目の端末で見たのと同じ Namespace の一覧が表示され、そのあと止まったように見えるはずです。これからの段で Namespace を作ったり消したりすると、この端末に行が書き足されます。

Namespace に属するリソースと属さないリソースを一覧する

2 つ目の端末で、Namespace に属するリソースの種類を一覧します。

console
$ kubectl api-resources --namespaced=true --context kind-kind

続けて、Namespace に属さないリソースの種類を一覧します。

console
$ kubectl api-resources --namespaced=false --context kind-kind

参考:Namespaces | Kubernetes、kubectl api-resources | Kubernetes

どちらも「仕組み」の節で引用した表と同じく、NAME、SHORTNAMES、APIVERSION、NAMESPACED、KIND の列が並ぶと考えられます。行が多いので、NAME 列で探します。1 つ目の一覧には pods や configmaps が、2 つ目の一覧には namespaces、nodes、persistentvolumes、storageclasses が含まれていれば想定どおりです。「仕組み」の節の表は v1.25.0 の時点のものなので、表に無い種類が加わっていることもあると考えられます。

第35回の metrics-server を残している場合は、APIVERSION が metrics.k8s.io/v1beta1 の行も並ぶと考えられます。第35回で入れた metrics-server v0.9.0 は v1beta1.metrics.k8s.io を登録するからです。この API グループの pods は 1 つ目の一覧に、nodes は 2 つ目の一覧に並ぶと考えられます。どちらも Metrics API(第35回)が提供するリソースで、同じ名前でも別の API グループのものです。なお、v1.37 の公式ドキュメントの Metrics API の例は metrics.k8s.io/v1 です。1 つ目の端末には変化が無いはずです。

参考:metrics-server/manifests/base at v0.9.0 · kubernetes-sigs/metrics-server、components.yaml(metrics-server v0.9.0)、Resource metrics pipeline | Kubernetes

2 つの Namespace を作る

第30回では kubectl create namespace で Namespace を作りました。この回はマニフェストで作ります。以下は team-a と team-b の 2 つの Namespace のマニフェストです。公式ドキュメントのタスクのページにある Namespace の書き方をもとに、名前をこの回のものにしました。--- は 1 つのファイルに複数のマニフェストを並べるときの区切りです。namespaces.yaml という名前で保存します。

yaml
apiVersion: v1
kind: Namespace
metadata:
  name: team-a
---
apiVersion: v1
kind: Namespace
metadata:
  name: team-b

参考:Share a Cluster with Namespaces | Kubernetes、Namespace | Kubernetes API Reference

名前はどちらも DNS ラベルの決まりを満たし、kube- で始まりません。2 つ目の端末で、マニフェストを渡します。

console
$ kubectl apply -f namespaces.yaml --context kind-kind

namespace/team-a と namespace/team-b が作られたことを知らせる 2 行が出るはずです。1 つ目の端末には、team-a と team-b の行が Active で書き足されるはずです。

続けて、ラベルの列も付けて一覧します。--show-labels はすべてのラベルを最後の列に表示するオプションです。

console
$ kubectl get namespaces --show-labels --context kind-kind

参考:kubectl get | Kubernetes

最後のラベルの列に、team-a の行は kubernetes.io/metadata.name=team-a、team-b の行は kubernetes.io/metadata.name=team-b が表示されるはずです。マニフェストにはラベルを書いていませんが、コントロールプレーンがすべての Namespace に付けるからです。default などの最初からある Namespace にも、同じ形のラベルが付いているはずです。

参考:Namespaces | Kubernetes

最後に、team-a の中身を YAML の形で表示します。

console
$ kubectl get namespace team-a -o yaml --context kind-kind

metadata.labels に kubernetes.io/metadata.name: team-a が、status.phase に Active があるはずです。spec の finalizers も見てみてください。「仕組み」の節で紹介した設計文書のとおりなら、kubernetes が入っていると考えられます。

参考:Namespace | Kubernetes API Reference、namespaces.md · kubernetes/design-proposals-archive

この段では、1 つ目の端末に team-a と team-b の行が Active で現れ、2 つの Namespace に kubernetes.io/metadata.name のラベルが付いていれば成功です。

同じ名前の ConfigMap を 2 つの Namespace に作る

以下は team-a と team-b に、同じ app-config という名前の ConfigMap を 1 つずつ作るマニフェストです。どちらも metadata.namespace で置く Namespace を書き、data の greeting の値だけを変えています。値はこの回で決めたものです。app-config.yaml という名前で保存します。

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: team-a
data:
  greeting: hello-from-team-a
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: team-b
data:
  greeting: hello-from-team-b

参考:ConfigMap | Kubernetes API Reference

2 つ目の端末で、マニフェストを渡します。マニフェストに Namespace を書いたので、-n は付けません。

console
$ kubectl apply -f app-config.yaml --context kind-kind

configmap/app-config が作られたことを知らせる行が 2 つ出るはずです。同じ名前でも、Namespace が違うので両方とも作られます。1 つ目の端末には変化が無いはずです。

参考:Namespaces | Kubernetes、Object Names and IDs | Kubernetes

すべての Namespace から app-config という名前の ConfigMap を探します。--field-selector はフィールドの値でオブジェクトを絞るオプションで、metadata.name と metadata.namespace はすべてのリソースの種類で使えます。

console
$ kubectl get configmaps -A --field-selector metadata.name=app-config --context kind-kind

参考:Field Selectors | Kubernetes、kubectl get | Kubernetes

app-config の行が 2 つ表示され、NAMESPACE 列でそれぞれ team-a と team-b のものだとわかると考えられます。kind が書き込んだ kubeconfig の利用者(第3回)は、すべての Namespace を読める権限を持つと考えられるので、Namespace が違っても両方が見えるはずです。これは、Namespace だけでは見える範囲が絞られないことの例と読めます(「Namespace で分けられないもの」)。

続けて、それぞれの greeting の値を取り出します。-n で Namespace を指定するだけで、同じ名前でも別の ConfigMap を指せます。

console
$ kubectl get configmap app-config -n team-a -o jsonpath='{.data.greeting}{"\n"}' --context kind-kind
$ kubectl get configmap app-config -n team-b -o jsonpath='{.data.greeting}{"\n"}' --context kind-kind

参考:JSONPath Support | Kubernetes

1 つ目のコマンドで hello-from-team-a、2 つ目のコマンドで hello-from-team-b が表示されるはずです。

同じ Namespace には同じ名前で作れないことを確かめる

今度は同じ team-a にもう 1 つ app-config を作ろうとします。ここでは kubectl apply ではなく kubectl create を使います。第7回で見たとおり、kubectl apply は同じ名前のオブジェクトがあればそれを更新するからです。kubectl create configmap はコマンドの引数から ConfigMap を作るコマンドで、--from-literal でキーと値を渡します。

console
$ kubectl create configmap app-config --from-literal=greeting=another -n team-a --context kind-kind

参考:kubectl create configmap | Kubernetes

作成は失敗し、同じ名前の ConfigMap がすでにあることを知らせるエラーが出るはずです。team-a にはすでに app-config があるからです。公式ドキュメントによると、ある種類のオブジェクトのうち、ある名前を持てるのは同時に 1 つだけです。Namespace に属する種類では、名前が重なってはいけない範囲が Namespace の中でした。このときのエラーの例はこのメディアで確かめた範囲の公式ドキュメントにはありません。続けて値を取り出し直すと、hello-from-team-a のまま変わっていないはずです。

console
$ kubectl get configmap app-config -n team-a -o jsonpath='{.data.greeting}{"\n"}' --context kind-kind

参考:Object Names and IDs | Kubernetes

クラスタ全体のリソースを Namespace を指定して一覧する

2 つ目の端末で、ノードを team-a と team-b を指定して一覧します。

console
$ kubectl get nodes -n team-a --context kind-kind
$ kubectl get nodes -n team-b --context kind-kind

どちらのコマンドでも、同じノードが 1 つ表示されると考えられます。「仕組み」の節で見たとおり、ノードのようなクラスタの範囲のリソースのパスには Namespace を入れる場所が無いので、-n で一覧は分かれないはずです。

参考:Kubernetes API Concepts | Kubernetes、Namespaces | Kubernetes

Namespace の一覧も同じく -n を付けて表示します。

console
$ kubectl get namespaces -n team-a --context kind-kind

team-a だけではなく team-b や default も含めたすべての Namespace が表示されると考えられます。「仕組み」の節の表のとおり、Namespace は Namespace に属さないからです。1 つ目の端末には変化が無いはずです。

この段では、-n を変えてもノードの一覧が同じで、Namespace の一覧も絞られなければ成功です。

コンテキストの Namespace を変える

2 つ目の端末で、kind-kind のコンテキストの Namespace を team-b にします。「仕組み」の節で見たとおり、--current の代わりにコンテキストの名前を書き、--context は付けません。

console
$ kubectl config set-context kind-kind --namespace=team-b

参考:kubectl config set-context | Kubernetes

kind-kind のコンテキストが書き換えられたことを知らせる 1 行が出るはずです。リファレンスによると、すでにあるコンテキストの名前を指定すると、指定した新しいフィールドが今の値の上に重ねられます。そのため、kind-kind が指すクラスタと利用者はそのままで、namespace だけが加わるはずです。1 つ目の端末には変化が無いはずです。kubeconfig を書き換えただけで、クラスタの Namespace は変わらないからです。

今度は -n を付けずに app-config の値を取り出します。

console
$ kubectl get configmap app-config -o jsonpath='{.data.greeting}{"\n"}' --context kind-kind

hello-from-team-b が表示されるはずです。-n を付けていないので、コンテキストに保存した team-b が使われるからです。

参考:Command line tool (kubectl) | Kubernetes

確かめたら、コンテキストの Namespace を消して元に戻します。kubectl config unset は kubeconfig の値を 1 つ消すコマンドで、公式ドキュメントの例(contexts.foo.namespace)と同じ形でコンテキストの namespace を指定します。

console
$ kubectl config unset contexts.kind-kind.namespace

参考:kubectl config unset | Kubernetes

値を消したことを知らせる 1 行が出るはずです。もう一度 -n を付けずに取り出すと、今度は app-config が見つからないことを知らせるエラーが出ると考えられます。コンテキストに namespace が無くなり、default が使われるはずだからです(第3回)。

console
$ kubectl get configmap app-config --context kind-kind

見つからないことを知らせるエラーが出れば、第3回からの推測(コンテキストに namespace が無ければ default)を手元で確かめられたことになります。このあと team-b を消すので、コンテキストの Namespace は必ず元に戻しておきます。

Namespace を消す

2 つ目の端末で、team-a の Namespace を消します。

console
$ kubectl delete namespace team-a --context kind-kind

参考:Share a Cluster with Namespaces | Kubernetes、kubectl delete | Kubernetes

kubectl delete の --wait の既定は true で、リソースが消えるまで待ってから戻ります。リファレンスによると、finalizer も待ちます。そのため、このコマンドは team-a が消えるまで終わらないと考えられます。この回で team-a に作ったのは ConfigMap 1 つだけなので、長くはかからないと考えられます。ただし公式ドキュメントに目安の時間は書かれていないので、すぐに終わらなくても待ちます。Ctrl+C で止めても削除は続くと考えられるので、そのときはこのあとの kubectl get namespace team-a で様子を確かめます。

参考:kubectl delete | Kubernetes、Share a Cluster with Namespaces | Kubernetes、Finalizers | Kubernetes

コマンドが終わるまでのあいだ、1 つ目の端末に team-a の行が Terminating で書き足されるはずです。完全に消えたときに 1 つ目の端末にどう表示されるかは、公式ドキュメントからはわかりません。成功の目安は Terminating の行なので、消えたときの表示は気にしなくてかまいません。

コマンドが終わったら、team-a が残っていないかを確かめます。

console
$ kubectl get namespace team-a --context kind-kind

見つからないことを知らせる 1 行が出れば、team-a は消えています。STATUS 列が Terminating で表示されたら、少し待ってからもう一度実行します。

続けて、すべての Namespace から app-config を探します。

console
$ kubectl get configmaps -A --field-selector metadata.name=app-config --context kind-kind

team-b の app-config の 1 行だけが表示されるはずです。team-a の app-config は team-a と一緒に消えたからです。

参考:Kubernetes API Concepts | Kubernetes

この段では、次の 3 点が合っていれば成功です。

  • 1 つ目の端末に team-a の Terminating の行が現れる
  • kubectl get namespace team-a で見つからないことを知らせる 1 行が出る
  • app-config が team-b の 1 つだけになる

片付け

1 つ目の端末で Ctrl+C を押して、Namespace の監視を止めます。

2 つ目の端末で、残っている team-b の Namespace を消します。中の app-config も一緒に消えます。

console
$ kubectl delete namespace team-b --context kind-kind

コマンドが終わったら、残っていないかを確かめます。

console
$ kubectl get namespace team-b --context kind-kind

見つからないことを知らせる 1 行が出れば、削除できています。Terminating で表示されたら、少し待ってからもう一度実行します。「コンテキストの Namespace を変える」の段の kubectl config unset を飛ばした場合は、ここで実行しておきます。

参考:Share a Cluster with Namespaces | Kubernetes

最後にクラスタを削除し、消えたことを確かめます。続けて次の回を試す場合は、クラスタを残しておいてもかまいません。

console
$ kind delete cluster
$ kind get clusters

kind delete cluster は存在しないクラスタを指定してもエラーを返しません。kind get clusters に kind が表示されなくなったことを確かめます。kubeconfig に kind-kind のコンテキストが残っていたら、第3回の片付けと同じく kubectl config delete-context kind-kind で消します。

参考:Quick Start | kind、kubectl config | Kubernetes

注意点

Namespace でつまずきやすい点と、バージョンで変わる点を、次の表にまとめます。

項目内容
Namespace を消すと中身もすべて消えるPod や ConfigMap などの Namespace に属するリソースが一緒に削除される。削除は非同期で、しばらく Terminating で見える
Namespace に属さないリソースがあるノード、PersistentVolume、StorageClass、Namespace 自身など。-n を付けても分かれないと考えられる
Pod どうしの通信と DNS の名前引きは既定では Namespace をまたぐ通信は NetworkPolicy(第25回)で、名前引きは DNS のサービスの設定で絞れる。NetworkPolicy には対応したネットワークのプラグインが要る
アクセスを Namespace ごとに絞るのは認可複数のチームで使う環境では、RBAC で利用者のアクセスを必要な Namespace に絞らなければならない(must)とされている(第38回)
kube- で始まる名前は避けるシステムの Namespace のために予約されている(Avoid)
default、kube-system、kube-public は消せないNamespaceLifecycle が防ぐ。v1.37 では既定で有効なアドミッションコントローラー
存在しない finalizer を書くと消えなくなる削除しようとすると Terminating のまま止まる。finalizer を手で外すことは避けるよう注意されている
リソースの Namespace は後から変えられないmetadata.namespace は作ったあとで変えられない(Cannot be updated)
コンテキストの Namespace は元に戻すまで効くkubectl config set-context は kubeconfig を書き換える。消した Namespace を指したままにしない
公開のトップレベルドメインと同じ名前の NamespaceService の短い名前が公開の DNS の名前と重なることがある(第23回)。Namespace を作る権限を信頼できる利用者に絞るよう勧められている
kubernetes.io/metadata.name のラベルv1.22 から Stable。コントロールプレーンがすべての Namespace に付け、変えられない

参考:Share a Cluster with Namespaces | Kubernetes、Namespaces | Kubernetes、Namespaces | Kubernetes、ObjectMeta | Kubernetes API Reference、Admission Control in Kubernetes | Kubernetes、Finalizers | Kubernetes、Network Policies | Kubernetes、Multi-tenancy | Kubernetes

コンテキストの Namespace が消した Namespace を指したままだと、-n を付けない作成などのリクエストは、NamespaceLifecycle に拒否されると考えられます。

参考:Admission Control in Kubernetes | Kubernetes

関連記事

次の回では Namespace の単位でアクセスを制御する Role を含め、ServiceAccount と RBAC の仕組みを扱います。

基本仕様 ・ 第38回 ServiceAccount と RBAC の仕組みPod の中のプログラムが API を使うときの身元になる ServiceAccount と、誰にどの操作を許すかを決める RBAC の仕組みを図で説明します。トークンが Pod に届く流れ、Role と RoleBinding の書き方、権限が足し算だけで決まることを押さえ、権限の無い ServiceAccount が断られる様子を kind のクラスタで確かめる手順を紹介します。

Namespace ごとに資源の使い方を制限する LimitRange と ResourceQuota については、以下の記事で解説しています。

基本仕様 ・ 第30回 LimitRange と ResourceQuota の違いNamespace ごとに資源の使い方を制限する LimitRange と ResourceQuota の違いを図で説明します。1 つずつの既定値と範囲を決める LimitRange と、Namespace 全体の合計を決める ResourceQuota が、どちらもアドミッションで働くことを押さえ、kind のクラスタで上限を超える Pod の作成が拒否される様子を試す手順を紹介します。

Namespace をまたぐ Pod どうしの通信を、Namespace のラベルで絞る NetworkPolicy については、以下の記事で解説しています。

基本仕様 ・ 第25回 NetworkPolicy を動かして理解するPod の通信を IP アドレスやポートの単位で制限する NetworkPolicy の仕組みを図で説明します。ポリシーに選ばれた Pod だけが隔離されること、許可の規則の書き方、通信を実際に止めるのはネットワークプラグインであることを押さえ、kind のクラスタでポリシーの前後に届き方が変わる様子を確かめる手順を紹介します。

Kubernetes 基本仕様の目次へ