十数個のマニフェストを含む namespace は、デプロイするのは簡単でも、説明するのは難しいものです。YAML は API サーバーに必要な情報をすべて伝えますが、新しく入ったメンバーに「どの Service がどの Deployment の前に立っているのか」「なぜ checkout API が payments を呼んでいるのか」は教えてくれません。このガイドでは、Kubernetes YAML から構成図を手で起こすための再現可能な手順を紹介します。オブジェクトを棚卸しし、特定のフィールドから関係を読み取り、何を省くかを決め、レイアウトを組み、図を最新に保つ、という流れです。最後に、同じ結果を Archboard の Kubernetes パックで描き直します。
魔法はありません。フィールドを読み、エッジを描くだけです。そこが肝心です。図が捉えるべきなのは意図であり、意図はあなたが書き加えるものです。
ステップ 1: オブジェクトを棚卸しする
テンプレートではなく、レンダリング済みのマニフェストから始めます。Helm や Kustomize を使っている場合は、実際に適用される内容を見るために先にレンダリングします。
helm template shop ./charts/shop -f values-prod.yaml > rendered.yaml
kubectl kustomize overlays/prod > rendered.yaml
ワークロードがすでに動いているなら、クラスターに問い合わせます。リソースの種類は明示しましょう。
kubectl get deploy,svc,ing,cm,secret,pvc,hpa,networkpolicy -n shop
kubectl get all に頼らないでください。all カテゴリには Pod、Service、Deployment、ReplicaSet、StatefulSet、DaemonSet、Job、CronJob、HPA が含まれますが、Ingress、ConfigMap、Secret、PVC、NetworkPolicy、ServiceAccount は含まれません。その中のいくつかは、まさに図に描きたいエッジを持っています。
関係を持つオブジェクトについては、spec 全体を取得します。
kubectl get ingress -n shop -o yaml
kubectl get svc -n shop -o custom-columns=NAME:.metadata.name,SELECTOR:.spec.selector
kubectl get pods -n shop --show-labels
棚卸しの結果は、種類・名前・namespace のフラットなリストとして書き出します。このリストが作図のチェックリストになります。
例: 1 つのサービスを Kubernetes YAML から図にする
shop namespace にある 1 つのサービスについての、小さいながら典型的な構成です。
apiVersion: apps/v1
kind: Deployment
metadata:
name: checkout-api
namespace: shop
spec:
selector:
matchLabels:
app: checkout-api
template:
metadata:
labels:
app: checkout-api
tier: backend
spec:
containers:
- name: api
image: registry.example.com/shop/checkout-api:1.14.2
ports:
- containerPort: 8080
resources:
requests:
cpu: 250m
envFrom:
- configMapRef:
name: checkout-config
- secretRef:
name: checkout-db-credentials
---
apiVersion: v1
kind: Service
metadata:
name: checkout-api
namespace: shop
spec:
selector:
app: checkout-api
ports:
- port: 80
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shop
namespace: shop
spec:
ingressClassName: nginx
rules:
- host: shop.example.com
http:
paths:
- path: /api/checkout
pathType: Prefix
backend:
service:
name: checkout-api
port:
number: 80
---
apiVersion: v1
kind: ConfigMap
metadata:
name: checkout-config
namespace: shop
data:
PAYMENTS_URL: http://payments.shop.svc.cluster.local
LOG_LEVEL: info
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: checkout-api
namespace: shop
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: checkout-api
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
オブジェクトは 5 つ。参照されているが表示されていない Secret が 1 つ、そして設定値の中に隠れた依存関係が 1 つあります。
ステップ 2: フィールドから関係を見つける
Kubernetes のオブジェクトが ID で互いを参照することはほとんどありません。名前で、あるいはもっと多くの場合ラベルで参照します。ラベルとセレクターが接着剤です。始める前に Kubernetes のラベルとセレクターのドキュメント を読み直しておく価値があります。
トラフィックの順にリストをたどります。
- Ingress → Service。 各 path の
backend.service.nameとport.numberが Service を直接指定します。host と path はエッジのラベルになります。 - Service → Deployment。 Service が Deployment を名前で指すことはありません。
spec.selectorが Deployment のspec.template.metadata.labelsのラベルと一致します。ここではapp: checkout-apiが一致するので、エッジを描きます。確信が持てないときは、kubectl get endpointslices -n shopで Service が実際に選択した Pod のアドレスを確認できます。エンドポイントがなければ、セレクターが何にも一致していないか、一致した Pod にまだ IP が割り当てられていないということです。 - Deployment → ConfigMap / Secret / PVC。
envFrom、env[].valueFrom、volumes[](configMap、secret、persistentVolumeClaim.claimName)を見ます。 - HPA → Deployment。
spec.scaleTargetRefが対象を指定します。 - NetworkPolicy。
spec.podSelectorが保護対象の Pod を選び、ingress[].fromはその Pod と通信できる相手を、egress[].toはその Pod がどこへ接続できるかを表します。 - 隠れた依存関係。
PAYMENTS_URLはpayments.shop.svc.cluster.localを指しています。checkout と payments を結ぶフィールドはありませんが、呼び出しは実在します。ツールが見落とし、人間がいちばん必要とするのがこのエッジです。
YAML フィールドから図の要素へ
| YAML フィールド | 図の要素 |
|---|---|
metadata.namespace |
オブジェクトを囲む Namespace フレーム |
kind: Deployment |
Deployment ノード、レプリカ数はラベル |
Ingress rules[].host + paths[].path |
Ingress ノード、出ていくエッジに host/path |
Ingress backend.service.name |
Ingress → Service のエッジ |
Service selector ↔ テンプレートの labels |
Service → Deployment のエッジ |
Service port → targetPort |
エッジのラベル(例: 80 → 8080) |
envFrom / volumes[].configMap |
ConfigMap → Deployment のエッジ |
secretRef / volumes[].secret |
Secret → Deployment のエッジ |
persistentVolumeClaim.claimName |
PVC → Deployment のエッジ |
HPA scaleTargetRef |
Deployment の横に HPA ノード、3–10 のラベル |
NetworkPolicy podSelector、ingress[].from |
保護対象のワークロードの横に NetworkPolicy ノード |
| 設定値に含まれる Service の DNS 名 | 依存先 Service へのエッジ |
ステップ 3: 何を省くかを決める
すべてを描いた図は、何も伝えません。実践で役立つルールは次のとおりです。
- レプリカ数はボックスではなくラベルにする。 Deployment ノードを 1 つ描き、
3–10 replicas (HPA)と書き添えます。同じ Pod のボックスを 3 つ並べるとノイズが増え、HPA がスケールした瞬間に図が間違いになります。 - ReplicaSet は隠す。 ロールアウトの実装の詳細にすぎません。
- Pod は意味があるときだけ描く。 たとえば単独の Pod や、Node へのスケジューリングを説明するときです。
- 定型的なものはまとめる。 ServiceAccount、デフォルトの RBAC、イメージ pull 用の Secret は、たいていキャンバスではなくノートに書けば十分です。
- 判断の理由になるものは残す。 checkout がデータベースに直接到達できない理由が NetworkPolicy なら、それは図に残します。
ステップ 4: レイアウトを組む
南北方向のトラフィックを左から右へ並べます。クライアント → Ingress → Service → Deployment → 下流の Service やデータストア、という順です。設定(ConfigMap、Secret)は供給先のワークロードの下に、スケーリング(HPA)は上に置きます。namespace はそれぞれフレームとして描くと、namespace をまたぐ呼び出しがフレームの外に出るエッジとして目立ちます。エッジには矢印だけでなく、プロトコルとポートを書きましょう。
自動可視化ツールと手描きの図
エコシステムには、API サーバーからクラスターのライブ状態を読み取り、グラフとして描画するツールもあります。いま何が動いているかについては正確で、デバッグには便利です。ただしトレードオフがあります。すべての ReplicaSet、Pod、エンドポイントを表示し、環境変数の中にある依存関係は見えず、「なぜそれが存在するのか」「何が計画されているのか」といった意図は表現できません。手で描いた図は網羅性では劣りますが、オンボーディング、設計レビュー、障害対応時の文脈共有にはより役立ちます。両方を使い分けるチームも多くあります。
ステップ 5: 最新に保つ
図が信頼できるのは、マニフェストと一緒に変わる場合だけです。
- 図のファイルをマニフェストの隣に置き、同じプルリクエストでレビューします。
- PR テンプレートに 1 行加えます。「Ingress、Service のセレクター、HPA、NetworkPolicy を変更しますか? 図を更新してください。」
- 定期レビューでステップ 1 の棚卸しコマンドを再実行し、図と比較します。
Archboard で例を描き直す
Archboard では、いま作った棚卸しをもとに、図に何を載せるかを決めながら、Kubernetes の kind に対応するノードで描いていきます。
- Google または GitHub でサインインし、図を作成します。
- Kubernetes パックから Namespace を追加します。フレームとして描かれるので、名前を
shopにします。 - フレームの外の左側に、クライアントを表す Core の Box または Text を置きます。
- フレームの中に Ingress、Service、Deployment を左から右へ配置します。ポート同士を接続し、エッジに
shop.example.com/api/checkoutと80 → 8080のラベルを付けます。 - Deployment の下に ConfigMap と Secret を追加して接続します。上には
3–10, CPU 70%というラベルの HPA を置きます。 payments用に 2 つ目の Service を追加し、Deployment から接続して、隠れた依存関係を見えるようにします。- フェンスされたコードブロックで書いた重要な YAML の抜粋や、短い「なぜ」のメモを入れた Markdown ブロックをキャンバスに置きます。
- 図を JSON でエクスポートしてマニフェストの隣にコミットし、README 用に SVG か PNG もエクスポートします。
ダイアグラムの内容
- shop
- Clients
- checkout-api
- checkout-config
- checkout-db-credentials
- payments
- HTTPS
- shop.example.com/api/checkout
- 80 → 8080
- PAYMENTS_URL
- CPU 70%
- envFrom
この例は、Free プランの 1 図あたり 15 ダイアグラムノードの上限に収まります。メモ・テキストは別枠で数えられ、150 件まで使えます。参考レイアウトとして /examples/kubernetes-ingress-flow と /examples/kubernetes-microservices を開いてください。上の図の Archboard で開く と同じように、どちらも この事例を使う で自分のワークスペースにコピーできます。ほかのパターンは /use-cases/kubernetes にあります。
よくある質問
Archboard に Kubernetes の YAML をインポートできますか?
はい、出発点として使えます。レンダリング済みのマニフェストや kubectl get -o yaml の出力を無料のKubernetes YAML から図を作るツールに貼り付けると、Namespace を枠として描き、Ingress、Service、ワークロード、ConfigMap、Secret、ボリュームを YAML の定義どおりにつなぎます。表示だけならアカウントは不要で、無料アカウントがあれば結果を Archboard で新しい図として開くか、エディターの YAML からインポート… で既存の図に追加できます。YAML とは同期しないため、結果の確認と最新の状態の維持には、この記事の手順がそのまま役立ちます。
Pod はすべて描くべきですか? 通常は不要です。レプリカ数のラベルを付けた Deployment ノード 1 つのほうがわかりやすく、HPA がスケールしても正しいままです。
Helm チャートはどうすればよいですか?
まず helm template でレンダリングし、テンプレートではなく出力結果を図にします。
どのフィールドにも現れない依存関係はどう見つけますか?
ConfigMap や env の値から svc.cluster.local などのホスト名を検索し、サービスのオーナーに確認します。