はじめに
こんにちは!
本記事は「本気で学ぶKubernetes」シリーズの第16回です。このシリーズでは、Kubernetesの基礎から実践まで、段階的に学んでいきます。
このシリーズは、第1回から順に読むことで体系的に学べる構成にしています。
まだご覧になっていない方は、ぜひ最初からご覧ください!
今回はNamespaceやLabelによるリソース整理やConfigMapを使った設定の外部化について触れていきたいと思います。
この記事は人間がKubernetesの公式ドキュメントを読み漁りながら書いていますのでご安心ください!
Namespaceとは
これまでは暗黙的にdafault namespaceを利用してリソースを作成してきました。実際の運用だと、開発環境と本番環境で同じ構成のリソースを作成するケースも少なくないと思います。
その場合、同じ名称だと間違えてリソース削除をしています可能性もあります。
NamespaceはKubernetesクラスタ内のリソースを論理的に分離する機能で、1つのクラスタの中に複数の「空間」で区切ってリソースを整理するようなイメージです。
KubernetesにはデフォルトでいくつかのNamespaceが用意されていますので、コマンドで確認してみます。
kubectl get namespaces
# NAME STATUS AGE
# default Active 10d
# kube-node-lease Active 10d
# kube-system Active 10d
# kube-public Active 10d
- default: 何も指定しないときに使われるNamespace
- kube-node-lease: ノードのハートビート情報を管理するNamespace
- kube-system: Kubernetes自身が使うNamespace(Metrics Serverなどもここにいます)
- kube-public: 全ユーザーがアクセス可能な公開用のNamespace
出典: Kubernetes公式ドキュメント - Namespaces
Namespaceを作成してみる
以下のコマンドでNamespaceを作成することができます。
# dev環境用のNamespaceを作成
kubectl create namespace dev
# namespace/dev created
# 確認
kubectl get namespaces
# NAME STATUS AGE
# default Active 10d
# dev Active 5s
# kube-node-lease Active 10d
# kube-public Active 10d
# kube-system Active 10d
もちろんYAMLファイルでも作成できます。
kubernetesはほぼ全ての定義をYAMLで宣言できますので、インフラ管理としてこちらの利用の方が推奨されると思います。
apiVersion: v1
kind: Namespace
metadata:
name: dev
kubectl apply -f dev-namespace.yaml
Namespace内にリソースをデプロイする
Namespaceを作成したら、その中にリソースをデプロイしてみます。
今回は明示的にNamespaceを適用したいのでマニフェストを作成していきます。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: dev # ここでNamespaceを指定
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
デプロイして確認してみます。
kubectl apply -f nginx-deployment-dev.yaml
# deployment.apps/nginx-deployment created
# dev namespaceのPodを確認
kubectl get pods -n dev
# NAME READY STATUS RESTARTS AGE
# nginx-deployment-xxxxxxxxxx-xxxxx 1/1 Running 0 10s
# nginx-deployment-xxxxxxxxxx-yyyyy 1/1 Running 0 10s
# default namespaceには何もありません
kubectl get pods
# No resources found in default namespace.
Namespace間のService通信
少し発展的な話になりますが、Namespace内のServiceはDNSクエリでアクセスすることができますが、名前空間を指定しない場合はPodの名前空間のみにDNSクエリは限定されてしまいます。
そのため、
例えば、「dev」というnamespaceにnginx-serviceというServiceがあった場合、同じNamespace内からはhttp://nginx-serviceでアクセスできますが、別のNamespaceからはhttp://nginx-service.dev.svc.cluster.localという完全修飾子のDNS名を使う必要があります。
詳細は以下の公式ドキュンメントをご参照ください。
出典: Kubernetes公式ドキュメント - DNS for Services and Pods
Label/Selectorとは
続いてはlabelsとselectorについて改めて触れていきたいと思います。
以前の記事で以下のようにServiceとDeploymentのマニフェストを作成しました。
# Service
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx # app=nginxというLabelを持つPodを対象にする
ports:
- port: 80
targetPort: 80
# Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx # このLabelがServiceのSelectorとマッチする
spec:
containers:
- name: nginx
image: nginx:1.21
Serviceのselector.app: nginxの部分ととDeploymentのlabels.app: nginxの部分が一致することで、Serviceは対象となるPodを見つけることができました。
出典: Kubernetes公式ドキュメント - Labels and Selectors
複数Labelによる柔軟なリソース管理
Labelは単一のKey-Valueペアだけでなく、複数組み合わせることで柔軟にリソースを分類・管理できます。
例えば以下のようなLabelを組み合わせてリソース管理を行うことができます。
labels:
app: webapp # アプリケーション名
env: production # 環境(dev/staging/prod)
version: v2.1.0 # バージョン
tier: frontend # レイヤー(frontend/backend/database)
なお、Kubernetes公式ドキュメントでは以下のような推奨Labelが紹介されていました。
-
app.kubernetes.io/name: アプリケーション名(例: mysql) -
app.kubernetes.io/instance: アプリケーションのインスタンス名(例: mysql-abcxyz) -
app.kubernetes.io/version: アプリケーションのバージョン(例: 5.7.21) -
app.kubernetes.io/component: アーキテクチャ内のコンポーネント(例: database) -
app.kubernetes.io/part-of: このアプリケーションが属する上位アプリケーション(例: wordpress) -
app.kubernetes.io/managed-by: アプリケーションの管理ツール(例: helm)
kubernetesを活用するケースでは多くのリソースが乱立することが多いと思いますので、Labelを適切に割り当てることで大規模なクラスタ構成になっても効率的にリソースを管理できますね。
出典: Kubernetes公式ドキュメント - Recommended Labels
selectorとtemplateLabelの関係について
先ほどのDeploymentマニフェストをもう一度見てみましょう。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx # ここと...
template:
metadata:
labels:
app: nginx # ここが一致している必要がある
selector.matchLabelsとtemplate.metadata.labelsは必ず一致している必要があります。
Deploymentはselectorで指定したLabelを持つPodを管理対象とします。一方、template.metadata.labelsはDeploymentが新しく作成するPodに付けるLabelです。
この2つが一致していないとDeploymentが作成したPodを管理できなくなるため、Kubernetesはこの2つが一致を強制しています。
公式ドキュメントにも記載されていますので、こちらも記事をご参照ください。
出典: Kubernetes公式ドキュメント - Deployment
ConfigMapとは
最後はConfigMapについて触れていきたいと思います。
ConfigMapは設定データをKey-Value形式で保存しPodから参照できるようにする機能です。
似たような機能にSecretというものがありますが、パスワードなどの機密情報はSecret、それ以外の設定情報はConfigMapを使うと覚えておけば良いです。
開発エンジニアは.envファイルをイメージしておくとわかりやすいと思います。
出典: Kubernetes公式ドキュメント - ConfigMaps
ConfigMapを使ってみる
実際にConfigMapを作成します。
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: dev
data:
APP_ENV: "development"
APP_DEBUG: "true"
DATABASE_HOST: "localhost"
DATABASE_PORT: "5432"
コマンドで作成してみます。
kubectl apply -f app-config.yaml
# configmap/app-config created
# 確認
kubectl get configmap -n dev
# NAME DATA AGE
# app-config 4 5s
# 詳細確認
kubectl describe configmap app-config -n dev
# Name: app-config
# Namespace: dev
# Labels: <none>
# Annotations: <none>
#
# Data
# ====
# APP_DEBUG:
# ----
# true
# APP_ENV:
# ----
# development
# DATABASE_HOST:
# ----
# localhost
# DATABASE_PORT:
# ----
# 5432
環境変数として使用
そして何より重要なポイントが、ConfigMapのデータを環境変数としてPodに渡すことができるという点です。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-with-config
namespace: dev
spec:
replicas: 1
selector:
matchLabels:
app: nginx-config
template:
metadata:
labels:
app: nginx-config
spec:
containers:
- name: nginx
image: nginx:1.21
env:
- name: APP_ENV
valueFrom:
configMapKeyRef:
name: app-config
key: APP_ENV
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_HOST
上記はサンプルですが、envセクションでAPP_ENVやDATABASE_HOSTを設定しています。
これによりConfigMapで定義した設定情報を読み込んでマニフェストで利用することができます。
クリーンアップ
最後にリソースを削除します。Namespaceを削除すると、その中のリソースも全て削除されるので便利です。
# Namespaceを削除すると、中のリソースも全て削除される
kubectl delete namespace dev
# namespace "dev" deleted
Namespaceを削除するとDeploymentやConfigMap、Podなどのリソースも全て削除されます。本番環境では必ず慎重に操作するようにしてください。
まとめと次回予告
今回はNamespace、Label/Selector、ConfigMapについて学びました。
Namespaceを使えば簡単に環境を分離でき、ConfigMapを使えば設定を外部化して環境ごとに切り替えられることがわかりました。
Kubernetesの開発現場においては、環境分離はほぼ必須の知識になってきますのでNamespaceによる分離やConfigMapによる設定外部化は必ず押さえておきましょう!
次回は、kubernetesにおけるDeploymentの更新とロールバックについて学習していきたいと思います。
それでは、また次回!