
- 1. はじめに
- 2. Kubernetes・Helm・Kustomize の基本
- 3. Kubernetes でシステム構築をする場合のワークフロー
- 4. シンプル環境の構築手順 〜とりあえず Nginx を立てる〜
- 5. ミニデータパイプライン構築の手順
- 6. まとめ
- 参考資料
- We Are Hiring!
1. はじめに
こんにちは、プラットフォーム共通基盤Gの内田です。
こちらはABEJAアドベントカレンダー2025の14日目の記事となります。
Kubernetes を触ることになったけど、「何から始めればいいのか」「選択肢が多すぎて迷う」と感じている方に向けて、Kubernetes初心者の自分が最近のキャッチアップをもとにミニデータパイプラインを作るところまでをまとめました。
Kubernetes を学び始めると、こんな疑問に直面します。
- 用語が多い: Pod / Node / Cluster / Namespace… どれがどの入れ物?
- ツールの選択肢が多い: Helm? Kustomize? 素の YAML? 何を使えばいい?
- 環境構築の方法も多い: AKS / GKE / kind / minikube / Rancher Desktop… どれが自分に合ってる?
公式ドキュメントは充実していますが、初心者にとっては「どこから読めばいいか分からない」状態になりがちです。
この記事では、ローカル環境(Rancher Desktop)で小さなシステムを動かすところまでを、次の流れで整理します。
2章:最低限の基本概念
コンテナ → Pod → Node → Cluster の「箱の構造」と、Helm / Kustomize の位置づけを把握します。後半で実際に環境構築する際に出てくる用語はここで必要最小限に絞って説明します。
3章:実務を見据えたワークフロー
「マニフェストはどう管理するか」「フォルダ構成はどうするか」といった、実際に手を動かす前に知っておきたい判断軸について調べた内容を整理します。選択肢が複数ある場合は、それぞれの特徴と「なぜこの方法を選んだか」を明示します。
4章:Nginx で基本操作を体験
シンプルな Web サーバ(Nginx)を 1 個デプロイして、kubectl コマンドの使い方や Deployment / Service / Ingress の動きを確認します。
5章:データパイプラインで応用
Helm で外部 OSS(Airflow / MinIO)を導入し、複数コンポーネントを組み合わせた小さなデータパイプラインを構築します。「設計図を Kubernetes リソースにマッピングする」感覚を掴みます。
逆にこの記事に出てこないのは、ユーザー認証の追加やセキュリティの話、高度なインフラ設定などです。これらは、また別の機会に検証して記事にしようと思います。
それでは、2章から順に見ていきましょう。
2. Kubernetes・Helm・Kustomize の基本
この章では、後の章で kubectl・helm・kustomize を叩いたときに迷子にならないように、Kubernetes とその周辺ツールの「最低限これだけは押さえておきたいポイント」をざっくり整理します。
Kubernetes については、container / pod / node / cluster / namespace の「入れ物の階層」と、Control Plane と Worker Nodeの役割分担を理解することが重要です。そのうえで、マニフェストをどう管理・デプロイしていくかという観点から、Helm と Kustomize の位置づけを簡単に紹介します。
細かい動作やオプションまで踏み込むとそれだけで本が一冊書けてしまうので、詳しく知りたい場合は公式ドキュメントや専門書を参照してください。
2.1 Kubernetesの役割
Kubernetes を一言で説明すると、「たくさんのコンテナを、複数のマシンの上に自動でいい感じに配置して、壊れたら再起動して、外からもアクセスしやすいように整えてくれる仕組み」です。
ここで重要なのが マニフェスト(manifest) という概念です。マニフェストは、「システムのあるべき姿」を記述した YAML ファイルのことで、「どんなコンテナを」「何個」「どんな設定で」動かすかを宣言的に書きます。このマニフェストを kubectl コマンドで Kubernetes に渡すと、Kubernetes が自動的にその状態を実現してくれます。コードとして管理できるため、再現性の確保や変更履歴の追跡が容易になります。
コンテナをそのまま単体で扱うのではなく、いくつかのレイヤに分けて管理しているのがポイントです。そのレイヤが、container / pod / node / cluster / namespace といった用語で表現されています。
2.2 Container / Pod / Node / Cluster / Namespace の関係
一番下にいるのはコンテナです。これは Docker イメージなどから起動した 1 プロセスの入れ物で、「アプリケーション本体そのもの」に一番近い存在です。 ただ、Kubernetes はコンテナを直接管理するのではなく、そのひとつ外側の「Pod」という単位を最小の実行単位として扱います。
Pod は 1 個以上のコンテナをまとめた箱のようなもので、中に入っているコンテナ同士は同じ IP アドレスとストレージの一部を共有します。多くの場合は「コンテナ 1 個だけが入った Pod」を使いますが、「アプリ本体」と「ログを横取りして別の場所に送るサイドカー」のように、2 個以上のコンテナを 1 Pod にまとめることもあります。
この Pod が乗っかっているのが Node です。Node はコンテナが実際に動いているマシン(VM や物理サーバ)です。1 台の Node の上に複数の Pod がスケジューリングされます。Rancher Desktop の場合は、Mac の中に小さな仮想マシンが用意されており、それが 1 つの Node として振る舞っています。
Node が何台かまとまったものが Cluster です。Cluster は Kubernetes が管理する単位で、「この Cluster に対して kubectl get pods を叩く」とか「この Cluster に Helm でアプリを入れる」といった操作をしています。現実には、Control Plane がいて全体を管理し、Worker Node がその指示に従って Pod を動かす、という構造になっているのですが、その話は次の節で触れます。
もうひとつよく出てくる概念が Namespace です。Namespace は Cluster の中の論理的な区切りで、コンピュータのフォルダのようなものだと思うとイメージしやすいかもしれません。同じ Cluster の中でも dev・stg・prod のように環境ごとに Namespace を分けたり、チームやプロジェクト単位で Namespace を分けたりして、リソース名の衝突を避けたり、アクセス権限を分けたりします。kubectl get pods -n data-pipeline の -n で指定しているのがこの Namespace です。
ここまでで説明した包含関係をまとめると以下のようになります。
%%{init: {'theme':'neutral'}}%%
flowchart TD
%% Kubernetes構成要素別クラス定義
classDef cluster fill:#e8f4f8,stroke:#0077b6,stroke-width:2px;
classDef namespace fill:#dae8fc,stroke:#6c8ebf,stroke-width:2px;
classDef node fill:#d5e8d4,stroke:#82b366,stroke-width:2px;
classDef pod fill:#fff2cc,stroke:#d6b656,stroke-width:2px;
classDef container fill:#ffffff,stroke:#d79b00,stroke-width:2px;
subgraph cluster["Cluster"]
subgraph ns["Namespace"]
subgraph node["Node"]
subgraph pod["Pod"]
c1["Container: my-app-container"]:::container
c2["Container: sidecar (optional)"]:::container
end
end
end
end
%% スタイルの適用
class cluster cluster;
class ns namespace;
class node node;
class pod pod;
2.3 Control Plane と Worker の役割分担
Kubernetes の Cluster の中では、「どの Pod をどの Node に置くか」「落ちた Pod をどう復旧するか」といったことを誰かが管理しなければいけません。その「司令塔」側が Control Plane、実際にコンテナを動かす側が Worker Node という役割です。
Control Plane 側には、いくつか代表的なコンポーネントが動いています。たとえば、kubectl や helm からのリクエストの入り口になっている API Server、Cluster 内の状態(どんな Pod や Service が存在するか)を保存する etcd、「この Pod をどの Node に置くか」を決める Scheduler、Deployment のようなオブジェクトの「あるべき状態」と「実際の状態」を監視して調整する Controller Manager などです。どれも聞き慣れない名前ですが、ここでは「Control Plane 側ではこういったコンポーネントが動いていて、Cluster 全体の調整をしている」とだけざっくりイメージできていれば十分です。詳しく知りたくなったときは Kubernetes の公式ドキュメントや専門書を読むと、それぞれの役割をかなり丁寧に追いかけることができます。
一方で、Worker Node 側には kubelet と呼ばれるエージェントプロセスが常駐しています。kubelet は Control Plane から「この Node にこの Pod を置いてください」といった指示を受け取り、Node 上のコンテナランタイム(containerd など)に具体的なコンテナの起動や停止を依頼します。また、kube-proxy などのコンポーネントが、Node 上での Service やロードバランシングに関わっています。
Rancher Desktop のようなローカル環境では、Control Plane と Worker が 1 台の Node 上に同居している構成になっていることが多く、利用者がそれぞれのプロセスを意識する場面はほとんどありません。ただ、「司令塔としての Control Plane と、実際にコンテナを動かす Worker Node がいる」という役割分担のイメージを持っておくと、後の章でログやイベントを見たときに理解しやすくなります。
ここまでの話から、Control PlaneとWorker Nodeを図示すると以下のような構成になっています。
%%{init: {'theme':'neutral'}}%%
flowchart LR
%% Kubernetes構成要素別クラス定義
classDef cluster fill:#e8f4f8,stroke:#0077b6,stroke-width:2px;
classDef namespace fill:#dae8fc,stroke:#6c8ebf,stroke-width:2px;
classDef node fill:#d5e8d4,stroke:#82b366,stroke-width:2px;
classDef pod fill:#fff2cc,stroke:#d6b656,stroke-width:2px;
classDef container fill:#ffffff,stroke:#d79b00,stroke-width:2px;
classDef service fill:#d5e8d4,stroke:#82b366,stroke-width:2px;
classDef ingress fill:#ffe6cc,stroke:#d79b00,stroke-width:2px;
classDef external fill:#f9f9f9,stroke:#333,stroke-width:2px;
subgraph cp["Control Plane"]
api["API Server"]:::container
sched["Scheduler"]:::container
cm["Controller Manager"]:::container
etcd["etcd (状態ストア)"]:::container
end
subgraph workernode["Worker Node"]
kubelet["kubelet"]:::container
kproxy["kube-proxy"]:::container
pod["Pod(s)"]:::pod
end
api <-->|指示/状態| kubelet
cm --> api
sched --> api
api --> etcd
%% スタイルの適用
class cp node;
class workernode node;
2.4 Helm 〜Kubernetes用パッケージマネージャ〜
次に、この記事の後半で使うことになる Helm について軽く触れておきます。
Helm は、Kubernetes の世界におけるパッケージマネージャです。Linux で言う apt や yum、Python で言う pip のようなものが、Kubernetes 向けに用意されているイメージです。単体の YAML ファイルを kubectl apply で流し込むのではなく、複数のマニフェストを「パッケージ」としてまとめて扱えるようにしてくれます。
中心になる概念は Chart・Release・values.yaml の 3 つです。
- Chart: アプリケーションを構成するマニフェスト(Deployment / Service など)のテンプレート一式。「インストール用の設計図」
- Release: Chart を特定の Cluster と Namespace にインストールした実体。例えば、同じ Airflow の Chart から
airflow-devとairflow-prodという 2 つの Release を作れる - values.yaml: Chart に流し込むパラメータ(レプリカ数、イメージタグ、リソース制限など)。環境ごとに
values.dev.yaml/values.prod.yamlと分けて管理するのが一般的
流れとしては、「Chart(設計図)+ values.yaml(パラメータ)→ 実際の YAML 群を生成 → Cluster に適用 → Release」というイメージです。
%%{init: {'theme':'neutral'}}%%
flowchart LR
%% Kubernetes構成要素別クラス定義
classDef cluster fill:#e8f4f8,stroke:#0077b6,stroke-width:2px;
classDef namespace fill:#dae8fc,stroke:#6c8ebf,stroke-width:2px;
classDef node fill:#d5e8d4,stroke:#82b366,stroke-width:2px;
classDef pod fill:#fff2cc,stroke:#d6b656,stroke-width:2px;
classDef container fill:#ffffff,stroke:#d79b00,stroke-width:2px;
classDef service fill:#d5e8d4,stroke:#82b366,stroke-width:2px;
classDef ingress fill:#ffe6cc,stroke:#d79b00,stroke-width:2px;
classDef external fill:#f9f9f9,stroke:#333,stroke-width:2px;
subgraph dev["ローカル開発環境 / Git"]
chart["Helm Chart<br>(templates/*.yaml)"]:::external
values["values.yaml<br>(values.dev.yaml など)"]:::external
end
chart --> render["テンプレート展開 <br> helm install/upgrade"]:::external
values --> render
render --> rel["Release<br>(クラスタ上のインスタンス)"]:::container
subgraph cls["Kubernetes Cluster"]
rel --> deploy["Deployment / StatefulSet"]:::pod
rel --> svc["Service / Ingress"]:::service
rel --> cm["ConfigMap / Secret"]:::container
end
%% スタイルの適用
class cls cluster;
2.5 Kustomizeで環境ごとの差分を管理する
この記事の後半では、Helm と並んで Kustomize も使います。Helm が「パッケージとしてまとめて配布する」ための仕組みだとすると、Kustomize は「ベースの YAML を環境ごとにカスタマイズする」ための仕組みだとイメージすると分かりやすいです。
Kustomize は「テンプレートエンジン」ではなく、「既存の YAML にパッチを当てて別バージョンを作るレイヤリングツール」です。deployment.yaml や service.yaml のような素のマニフェストをベースとして用意しておき、それに対して「dev 用にはレプリカ数を 1 にする」「prod 用には 3 にする」「この環境ではラベルを追加する」といった差分だけを overlay として記述します。最終的なマニフェストは、ベースと overlay を合成して生成されます。
Kustomize は kubectl にも統合されていて、kubectl apply -k のように -k オプションを付けると、指定したディレクトリ内の kustomization.yaml を解釈して、そこから生成されたマニフェストを apply してくれます。後の章で、base/ と overlays/dev/・overlays/prod/ のようなフォルダ構成を使って環境ごとの差分を管理する場面が出てきますが、そのときに裏側で働いているのが Kustomize です。
%%{init: {'theme':'neutral'}}%%
flowchart TD
%% Kubernetes構成要素別クラス定義
classDef cluster fill:#e8f4f8,stroke:#0077b6,stroke-width:2px;
classDef namespace fill:#dae8fc,stroke:#6c8ebf,stroke-width:2px;
classDef node fill:#d5e8d4,stroke:#82b366,stroke-width:2px;
classDef pod fill:#fff2cc,stroke:#d6b656,stroke-width:2px;
classDef container fill:#ffffff,stroke:#d79b00,stroke-width:2px;
classDef service fill:#d5e8d4,stroke:#82b366,stroke-width:2px;
classDef ingress fill:#ffe6cc,stroke:#d79b00,stroke-width:2px;
classDef external fill:#f9f9f9,stroke:#333,stroke-width:2px;
subgraph base["base/"]
bdep["deployment.yaml"]:::external
bsvc["service.yaml"]:::external
end
subgraph dev["overlays/dev/"]
dpatch["kustomization.yaml<br>+ dev 用パッチ"]:::external
end
subgraph prod["overlays/prod/"]
ppatch["kustomization.yaml<br>+ prod 用パッチ"]:::external
end
base --> dev
base --> prod
dev --> ydev["生成された dev 用マニフェスト"]:::external
prod --> yprod["生成された prod 用マニフェスト"]:::external
ydev --> applydev["kubectl apply -k overlays/dev"]:::external
yprod --> applyprod["kubectl apply -k overlays/prod"]:::external
実務では、Helm と Kustomize を組み合わせるケースもよくあります。たとえば、外部の OSS を導入するときは Helm Chart をそのまま使い、自分たちのアプリケーションや環境ごとの差分は Kustomize で管理する、といった分担です。また、Argo CD や Flux のような GitOps ツールも、バックエンドで Kustomize を利用してマニフェストを組み立てることが多く、Kustomize でのレイヤ構造に慣れておくと、この手のツールにもスムーズに入っていけます。
ここでは、「Helm はパッケージ化・配布のための仕組み」「Kustomize は YAML を環境ごとに管理する仕組み」というくらいのざっくりしたイメージがあれば十分です。細かいフィールドの書き方やオプションは、4 章以降で実際に手を動かしながら見ていきます。
2.6 この章のまとめ
ここまでで、「Kubernetes という箱の中に、どんな入れ物や役割がいるのか」と、「その上で Helm や Kustomize がどんな位置づけなのか」という、大まかな地図を描きました。
コンテナは 1 プロセスの入れ物で、それをまとめた Pod が Kubernetes の最小実行単位になります。Pod は Node の上に配置され、複数 Node が集まって Cluster を構成します。その Cluster の中をさらに Namespace で論理的に区切ることで、環境やチームごとの分離を行います。Cluster の内部では、Control Plane にいる API Server や etcd などのコンポーネントが全体の状態を管理し、Worker Node 上の kubelet が実際にコンテナを起動・停止しています。
Helm は、その Kubernetes 環境にアプリケーション一式をデプロイするためのパッケージマネージャで、Chart・Release・values.yaml という単位でマニフェスト一式を扱います。Kustomize は、既存の YAML をベースに、環境ごとの差分を重ねていくためのツールで、kubectl apply -k の裏側で動いています。外部の OSS を導入するときには主に Helm、自分たちのマニフェストや環境差分の管理には Kustomize、といった役割分担で使われることも多いです。
この基本的なイメージを頭の片隅に置きながら、次の章では「実際のシステムを Kubernetes 上に構築するとき、どんなワークフローやフォルダ構成、ツールの組み合わせを意識すればよいのか」を整理していきます。
3. Kubernetes でシステム構築をする場合のワークフロー
2章では、Kubernetes の基本的な箱の構造と、Helm / Kustomize のざっくりした位置付けを確認しました。ここからは、実際に Kubernetes を使ってシステムを設計・実装・テストしていくときに、どんな流れで考えると整理しやすいかをまとめておきます。
Kubernetes のエコシステムには、同じことをやるのに複数の方法がある場面がたくさんあります。たとえば、
- マニフェストは素の YAML で書くのか、Kustomize でレイヤリングするのか、Helm でパッケージ化するのか
- ローカル環境は kind / minikube / Rancher Desktop のどれを使うのか
- デプロイは手元から
helm upgradeするのか、GitOps ツールに任せるのか
など、いきなり全部の選択肢が視界に入ると、初心者ほど「何から決めればいいのか」が分かりにくくなります。
この章では、あくまで一つの考え方として、
- システム設計〜リソース設計〜マニフェスト管理の流れ(ワークフローの型) と
- フォルダ・ファイル構成のベストプラクティスの一例
を整理しておきます。4章と5章では、このワークフローを小さな Nginx アプリと最小データパイプラインに対して実際に試しながら調査・検討したワークフローがうまくいくか確認していきます。
3.1 まず「どんなシステムを Kubernetes に載せたいのか」をざっくり言語化する
最初にいきなり Deployment の YAML を書き始めるのではなく、「Kubernetes に載せたいシステムの輪郭」をテキストでざっくり整理しておくと、その後のリソース設計やフォルダ構成がぶれにくくなります。
たとえば、この記事の想定システムだと、
- 外部から HTTP でアクセスされるフロント(Nginx や Web アプリ)がある
- 内部には、メッセージブローカや、データ加工の処理コンポーネントがいる
- 将来的には dev / stg / prod のように環境を分けていきたい
といったレベルの整理ができていれば十分です。
この段階では、シーケンス図や構成図まできっちり描かなくてもよくて、
- どんなコンポーネントがいるか
- それぞれは常駐なのか、バッチなのか
- 外部と通信する入口はどこか
くらいを箇条書きにしておくだけでも、後で「どのサービスをどの Namespace に置くか」「どこまでを Helm 1 リリースにまとめるか」といった判断がしやすくなります。
3.2 アプリの構成を Kubernetes のリソースにマッピングする
アプリケーション側の構成をざっくり描けたら、それを Kubernetes のリソースに落としていきます。ここでは完璧を目指す必要はなく、「まずは動かすための最低限のマッピング」が出来ていれば十分です。
たとえば、次のような対応をイメージします。
- 常駐して動き続けるプロセス(Web サーバやメッセージブローカ)は Deployment や StatefulSet にする
- それぞれの Pod に対する入口として Service を用意する
- 外部(ブラウザなど)から HTTP でアクセスする必要があるものは Ingress を定義して、Ingress Controller(Rancher Desktop の場合は Traefik)にルーティングしてもらう
- 最初は 1つの Namespace(例:
<system>-dev)に一式をまとめ、本番を見据える段階で Namespace を環境やドメインごとに分割する
ここで大事なのは、「アプリケーションの構成図」と「Kubernetes のリソース図」を頭の中で重ねてみることです。 4章では Nginx という単純なアプリを題材に、「この Web サーバは Deployment で、この Service 経由で、この Ingress から外部に公開する」といった最小のマッピングを実際にやってみます。5章では、その考え方を複数サービスからなるデータパイプラインに拡張していきます。
3.3 マニフェストをどう管理するか:素の YAML / Helm / Kustomize
アプリケーションの構成と Kubernetes リソースの対応がざっくり見えたら、次に「マニフェストをどう管理するか」を決めます。ここが Kubernetes エコシステムでよく迷いやすいポイントのひとつです。
素の YAML を手書きして kubectl apply しても構いませんが、環境ごとの差分や、依存関係のある複数のリソースをまとめて扱いたくなってくると、Helm や Kustomize を使った方が楽になります。
この記事では、役割のイメージとして次のように割り切ることにします。
外部の OSS コンポーネント(メッセージブローカ、Airflow、cert-manager など)は、基本的に Helm Chart で導入する → すでにコミュニティやベンダーが用意してくれている Chart と values.yaml を活用する
自分たちのアプリケーションや Namespace / Label のような「環境に依存する部分」は Kustomize で扱う →
baseに共通定義を置き、overlays/dev・overlays/prodで差分を管理する
もちろん、Helm だけで最後までやりきる構成もありますし、逆にすべてを Kustomize で組んで Helm を使わないプロジェクトもあります。どの選択肢が絶対正解というわけではなく、チームの好みや既存資産との相性による部分も大きいです。
ここでは、「Chart で配布されている OSS は Helm で」「自作アプリや環境差分は Kustomize で」という分担を前提に話を進めます。4章・5章でも、この方針に沿ったディレクトリ構成とコマンドの打ち方で進めていきます。
3.4 base / overlay とフォルダ構成の基本パターン
ワークフローの話とセットで決めておきたいのが、共通部分(base)と環境差分(overlay)をどう分けるか、そしてそれを反映したフォルダ構成です。
考え方としては、
- 「環境が変わっても基本的に固定であって欲しいもの」を base に寄せる
- 「環境ごとに変わりやすいもの」を overlay(Kustomize)や values.yaml(Helm)に寄せる
というシンプルなルールで十分です。
base に置くものの例
Deployment / StatefulSet / Service / Ingress の「形」
- リソース種別
- 名前(原則として環境間で変えたくないもの)
- ラベルのキー構造
- ポート番号など、めったに変えたくない設定
- アプリケーションが前提とする ConfigMap のキー構成
- Pod 内のコンテナ構成(サイドカーの有無など)
overlay / values に寄せるものの例
- replica 数(dev: 1, prod: 3 など)
- コンテナイメージのタグ(
1.0.0/1.0.1) - CPU / メモリの requests / limits
- 環境ごとの外部エンドポイント(DB の URL、外部 API の URL など)
- Namespace 名・環境ラベル(
env=dev/env=prodなど)
これを反映したディレクトリ構成の一例は、たとえば次のようになります。
repo-root/
apps/
my-app/
base/
deployment.yaml
service.yaml
ingress.yaml
kustomization.yaml
overlays/
dev/
kustomization.yaml
namespace.yaml
prod/
kustomization.yaml
namespace.yaml
ここでのポイントは次の通りです。
apps/配下に、各システム(アプリケーション)ごとの定義を置くbase/に共通マニフェストを配置overlays/に環境ごとの差分(Namespace / replica 数 / リソース量 / ラベル)を配置
この構成にしておくと、
- 環境ごとの差分が overlay で明確に分離される
- 共通部分の変更が base 一箇所で済む
- 後から GitOps ツール(Argo CD や Flux)を導入したいときにも、そのまま流用しやすい
というメリットがあります。
4章では、この構成を使って Web アプリ(Nginx)を題材に、apps/my-app/base と apps/my-app/overlays/dev を実際に作りながら、Kustomize の挙動と Namespace の扱いを確認します。5章では、外部 OSS(Airflow / MinIO)を Helm で追加し、複数サービスからなるデータパイプラインに拡張していきます。
3.5 ローカル → ステージング → 本番への流れを最初にイメージしておく
最後に、少しだけ将来の話に触れておきます。 この記事では Rancher Desktop 上のローカルクラスタを対象にしていますが、実務では最終的にステージング環境や本番クラスタ(EKS / GKE / on-prem など)に展開していくことを想定しているはずです。
最初の段階から、
「このフォルダ構成とツールの組み合わせを、そのままステージングと本番にも持っていけそうか?」
を頭の片隅で意識しておくと、後から大きく作り直す必要が減ります。たとえば、次のような流れをイメージしておくと、今回の学習がそのまま実務にもつながりやすくなります。
- ローカル(Rancher Desktop)では、手元のターミナルから
kubectl/kustomize/helmを直接叩いて検証する - ステージング環境以降では、同じ
k8s/ディレクトリを Git リポジトリ上で管理し、GitOps ツールや CI/CD から apply / install する - ローカルとステージング / 本番で、「マニフェストの出どころ」は同じにしておき、操作の仕組みだけを少しずつ自動化していく
また、マニフェストのテストフローとしては、
Kustomize / Helm から最終的な YAML を生成する
kustomize build k8s/apps/<system>/overlays/devhelm template ... -f values.dev.yaml
- 生成された YAML を、
kubectl apply --dry-run=serverやkubeconformなどでバリデーションする - 検証用クラスタ(ローカル / kind / minikube / dev クラスタ)に apply して動作を確認する
といった流れを最初から決めておくと、そのまま GitHub Actions などの CI パイプラインにも乗せやすくなります。
4. シンプル環境の構築手順 〜とりあえず Nginx を立てる〜
この章では、実際に Rancher Desktop 上の Kubernetes クラスタに Nginx を 1 個デプロイし、Ingress 経由でローカルのブラウザからアクセスできる状態までを、ステップバイステップで作っていきます。
ここまでできると、次のあたりが体感で理解できるはずです。
kubectlでクラスタ / Node / Pod / Service / Ingress の状態を確認する流れ- Deployment → Pod → Service → Ingress のつながり
- Kustomize の
base/overlays/devを使ってマニフェストを適用する手順
4.1 前提条件と環境セットアップ
この章を始める前に、以下の環境を準備します。
必要なツールのインストール
1. Rancher Desktop のインストール
Rancher Desktop の公式サイト から Mac 用のインストーラーをダウンロードしてインストールします。
インストール後、Rancher Desktop を起動して:
- Kubernetes を有効化(Settings → Kubernetes → Enable Kubernetes)
- コンテナランタイムは containerd または dockerd どちらでも OK
2. Homebrew で kubectl / helm / kustomize をインストール
# kubectl(Kubernetes のコマンドラインツール) brew install kubectl # Helm(Kubernetes パッケージマネージャ) brew install helm # Kustomize(YAML カスタマイズツール) brew install kustomize
インストール確認:
kubectl version --client helm version kustomize version
📝 この記事で検証したバージョン - kubectl: v1.34.2 (Kustomize v5.7.1 内蔵) - Helm: v3.18.6 - Kustomize: v5.8.0
多少バージョンが異なっても基本的な操作は同じですが、大きく異なる場合は公式ドキュメントも参照してください。
3. 作業用ディレクトリの準備
このチュートリアルでは、GitHubリポジトリ learn-k8s をクローンして使用することを前提としています。
# リポジトリをクローン git clone https://github.com/uchida-abeja/learn-k8s.git cd learn-k8s
または、新しく練習用ディレクトリを作成する場合は:
mkdir -p ~/learn-k8s-practice cd ~/learn-k8s-practice
以降、このディレクトリをリポジトリルートとして、ここを起点にコマンドを実行します。
接続確認とコンテキスト設定
環境が整ったら、Rancher Desktop のクラスタに接続できているか確認します。
# 現在のコンテキスト確認 kubectl config current-context
ここで rancher-desktop のような名前が返ってくれば、この記事の前提と一致しています。
💡 current-context って何?(要点だけ)
kubectlは~/.kube/configという設定ファイルを読み、
- どの API サーバ(どのクラスタのエンドポイント)に
- どの認証情報で リクエストを送るかを、「context」 という単位で持っています。
kubectl config current-contextは、今アクティブな context(=今どのクラスタに対してコマンドが実行されるか)を教えてくれるものです。 Rancher Desktop を入れるとrancher-desktopという context が、Docker Desktop を入れるとdocker-desktopという context が追加されます。 切り替えたいときはkubectl config use-context rancher-desktopのように指定します。
⚠ 注意1: Rancher Desktop と Rancher Manager は別物
Rancher 関連でいちばんハマりやすいポイントがここです。
Rancher Desktop
- ローカル開発用のツール(Mac/Windows 向け)
- 1台のマシンの中に小さな Kubernetes(k3s)とコンテナランタイムを用意してくれる
- GUI 設定画面はあるが、「Web 管理画面でクラスタを管理するツール」ではない
Rancher Manager
- 既存の Kubernetes クラスタをまとめて管理するための サーバアプリ
- 別の Kubernetes クラスタや VM 上で
rancher/rancherが動き、ブラウザから Web UI にアクセスして使う - EKS / GKE / on-prem など複数クラスタを一元管理する用途
この記事で扱っているのは Rancher Desktop のクラスタ(コンテキスト名:rancher-desktop)だけです。
Rancher Manager の Web 管理画面(https://<host>:8443 など)は、今回のハンズオンとは無関係です。
⚠ 注意2: Docker Desktop のコンテキストと取り違えない
Mac だと Docker Desktop も入っていることが多く、kubectl config current-context が docker-desktop になっている場合があります。
その場合は、この記事のコマンドを実行する前に、コンテキストを切り替えておきます。
kubectl config use-context rancher-desktop
「Rancher Desktop 上で Nginx を立てる」はずが、気づいたら Docker Desktop 側のクラスタにデプロイしていた…という事故を防ぐために、コマンドを打つ前に一度だけ確認しておくと安全です。
4.2 Step 0: クラスタにつながっているか確認する
前提が揃ったら、本当に Rancher Desktop のクラスタに接続できているかを確認します。
# ノードの状態を確認 kubectl get nodes # 全 Namespace の Pod を確認(現時点では system 系だけのはず) kubectl get pods -A
Rancher Desktop を起動したての状態では、以下のような出力が得られるはずです:
NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-6d668d687-rxv5j 1/1 Running 0 46s kube-system helm-install-traefik-crd-q5982 0/1 Completed 0 47s kube-system helm-install-traefik-phj4p 0/1 Completed 1 47s kube-system local-path-provisioner-869c44bfbd-472nm 1/1 Running 0 46s kube-system metrics-server-7bfffcd44-rlv95 1/1 Running 0 46s kube-system svclb-traefik-f0cdde31-cpsdp 2/2 Running 0 44s kube-system traefik-865bd56545-92rrp 1/1 Running 0 44s
重要なのは、kube-system Namespace に traefik が動いていることです。これは Rancher Desktop に最初から含まれている Ingress Controller で、この章で外部からのアクセスを受け付ける役割を果たします。
4.3 Step 1: my-app 用のディレクトリを作る
次に、Nginx を動かすための最小アプリケーションとして my-app を用意します。
構成は、3章で出てきたパターンのミニ版です。
# リポジトリのルートディレクトリに移動(クローンした場合) cd learn-k8s # ディレクトリ構造を作成(まだ存在しない場合) mkdir -p apps/my-app/base mkdir -p apps/my-app/overlays/dev
💡 既存リポジトリを使う場合 このリポジトリをクローンした場合、すでに
apps/my-app/以下のファイルが存在しているので、ディレクトリ作成はスキップして次のステップに進んでください。
最終的に、次のような構成にしていきます。
apps/
my-app/
base/
deployment.yaml
service.yaml
ingress.yaml
kustomization.yaml
overlays/
dev/
kustomization.yaml
namespace.yaml
この my-app が、4章の主役です。
4.4 Step 2: base(共通部分)のマニフェストを書く
まずは base/ 配下に、Nginx の Deployment / Service / Ingress を書いていきます。
4.4.1 Deployment
apps/my-app/base/deployment.yaml:
apiVersion: apps/v1 kind: Deployment # Pod を管理するリソース(常駐プロセス用) metadata: name: my-app-nginx # Deployment の名前 labels: app.kubernetes.io/name: my-app # アプリケーション名 app.kubernetes.io/component: web # コンポーネントの役割 spec: replicas: 1 # Pod の数(dev環境なので1個) selector: # どの Pod を管理するか(template の labels と一致させる) matchLabels: app.kubernetes.io/name: my-app app.kubernetes.io/component: web template: # Pod のテンプレート metadata: labels: # Pod に付けるラベル(selector と一致させる) app.kubernetes.io/name: my-app app.kubernetes.io/component: web spec: containers: - name: nginx # コンテナ名 image: nginx:1.27 # 使用する Docker イメージ ports: - containerPort: 80 # コンテナが公開するポート
標準の Nginx イメージを 1 Pod だけ動かす、最小限の Deployment です。
4.4.2 Service
apps/my-app/base/service.yaml:
apiVersion: v1 kind: Service # Pod へのアクセスを提供するリソース metadata: name: my-app-nginx # Service の名前(Ingress から参照される) labels: app.kubernetes.io/name: my-app app.kubernetes.io/component: web spec: type: ClusterIP # クラスタ内部からのみアクセス可能 selector: # どの Pod にトラフィックを流すか(Deployment の labels と一致) app.kubernetes.io/name: my-app app.kubernetes.io/component: web ports: - port: 80 # Service が受け付けるポート targetPort: 80 # Pod(コンテナ)のポート protocol: TCP name: http
Deployment が作る Pod に対して、クラスタ内部からアクセスするための入口(Service)を定義しています。
4.4.3 Ingress
apps/my-app/base/ingress.yaml:
apiVersion: networking.k8s.io/v1 kind: Ingress # 外部からのHTTPアクセスをルーティングするリソース metadata: name: my-app-nginx # Ingress の名前 labels: app.kubernetes.io/name: my-app app.kubernetes.io/component: web spec: ingressClassName: traefik # Rancher Desktop のデフォルト Ingress Controller rules: # ルーティングルール - http: # host を指定しない = すべてのホストで有効 paths: - path: / # パス(/ = ルート) pathType: Prefix # 前方一致 backend: # 転送先の Service service: name: my-app-nginx # Service 名 port: number: 80 # Service のポート
- Rancher Desktop では Traefik がデフォルトの Ingress Controller として動いているため、
ingress.class: "traefik"を付けています。 - 今回はホスト名を指定せず、「どのホストでも
/に来たリクエストはmy-app-nginxService に流す」というシンプルなルールです。
⚠ 他の Ingress とバッティングしている場合 すでに Rancher Desktop 上で別の Ingress をいじっていると、
/パスが取り合いになることがあります。その場合は、この章の Ingress のpathを/my-appに変えて試してみてください。
4.4.4 base の kustomization.yaml
apps/my-app/base/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization # base で管理するリソース一覧 resources: - deployment.yaml - service.yaml - ingress.yaml
これで、base/ に Nginx をデプロイするための共通定義が揃いました。
4.5 Step 3: dev 環境用の overlay を作る
次に、dev 環境用の Namespace と overlay を作成します。
4.5.1 Namespace マニフェスト
apps/my-app/overlays/dev/namespace.yaml:
apiVersion: v1 kind: Namespace # リソースを論理的にグループ化する単位 metadata: name: my-app-dev # dev 環境用の Namespace 名 labels: app.kubernetes.io/part-of: my-app # このアプリケーションに属する env: dev # 環境ラベル
ここでは Namespace 名を my-app-dev とし、env=dev ラベルを付与しています。
4.5.2 dev 用 kustomization.yaml
apps/my-app/overlays/dev/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization # すべてのリソースをこの Namespace に配置 namespace: my-app-dev # 使用するリソース resources: - ../../base # base の定義を参照 - namespace.yaml # Namespace 自体も作成
namespace: my-app-devと書くことで、base 内のすべてのリソースを dev Namespace に配置します。- 同時に
namespace.yamlをresourcesに含めているので、Namespace 自体も一緒に作られます。
4.6 Step 4: Kustomize でデプロイして、状態を確認する
4.6.1 まずは build して目で確認(任意)
# リポジトリのルートディレクトリで実行 kustomize build apps/my-app/overlays/dev
namespace: my-app-dev が付いた Deployment / Service / Ingress / Namespace の YAML がまとめて表示されれば OK です。
4.6.2 クラスタに適用する
kubectl apply -k apps/my-app/overlays/dev
これで、
my-app-devNamespace- その中の Deployment / Service / Ingress
が一気に作成されます。
4.7 Step 5: Pod / Service / Ingress の状態を確認する
4.7.1 Namespace
kubectl get namespaces | grep my-app
my-app-dev が表示されれば OK。
4.7.2 Pod
kubectl get pods -n my-app-dev
my-app-nginx-xxxx が Running になれば成功です。
もし ImagePullBackOff や CrashLoopBackOff の場合は:
kubectl describe pod -n my-app-dev my-app-nginx-xxxxxxxxxx-xxxxx
で原因を確認します。
4.7.3 Service
kubectl get svc -n my-app-dev
my-app-nginx の ClusterIP が表示されれば OK です。
4.7.4 Ingress
kubectl get ingress -n my-app-dev kubectl describe ingress -n my-app-dev my-app-nginx
イベントにエラーが出ていなければ、Traefik がルールを取り込めています。
⚠ Rancher Manager の画面に Ingress が見えない問題 Rancher Manager から別クラスタを眺めている場合、「今作った Ingress が見えない?」となることがあります。 この記事では Rancher Desktop のローカルクラスタを操作しているので、Rancher Manager の UI ではなく、
kubectlの結果を一次情報として見るようにしてください。
4.8 Step 6: ブラウザから Nginx にアクセスしてみる
最後に、ローカルのブラウザから実際に Nginx にアクセスしてみます。
- まず
http://localhost/を試します。 - 他の Ingress と競合している場合は、Ingress の
pathを/my-appにしたうえでhttp://localhost/my-appを試してください。
CLI で確認する場合は:
curl -v http://localhost/ # あるいは path を変えた場合 curl -v http://localhost/my-app
Nginx の HTML が返ってくれば成功です。
4.9 お片付け(削除の方法)
検証が終わったら、作ったリソースを削除しておきます。
# Kustomize 単位でまとめて削除 kubectl delete -k apps/my-app/overlays/dev # または Namespace ごと削除(中のリソースもまとめて消える) kubectl delete namespace my-app-dev
Kustomizeで削除する場合、手動で追加したリソースが残るので、Namespaceごと削除しちゃった方が楽かもしれません。
4.10 構築したシステムの全体像
この章で構築したリソースの関係を図で整理しておきます。
リソースの階層構造と対応するYAMLファイル
以下の図は、Rancher Desktop上のKubernetesクラスタ内に構築されたNginxアプリケーションの全体構成を示しています。ブラウザからのHTTPリクエストがTraefik(Ingress Controller)を経由し、Ingress、Service、Podと順に転送され、最終的にNginx Containerで処理される様子を表現しています。各要素の右側には、それを定義しているYAMLファイルのパスも記載しています。
%%{init: {'theme':'neutral'}}%%
flowchart TD
%% Kubernetes構成要素別クラス定義
classDef cluster fill:#e8f4f8,stroke:#0077b6,stroke-width:2px;
classDef namespace fill:#dae8fc,stroke:#6c8ebf,stroke-width:2px;
classDef node fill:#d5e8d4,stroke:#82b366,stroke-width:2px;
classDef pod fill:#fff2cc,stroke:#d6b656,stroke-width:2px;
classDef container fill:#ffffff,stroke:#d79b00,stroke-width:2px;
classDef service fill:#d5e8d4,stroke:#82b366,stroke-width:2px;
classDef ingress fill:#ffe6cc,stroke:#d79b00,stroke-width:2px;
classDef external fill:#f9f9f9,stroke:#333,stroke-width:2px;
browser["ブラウザ<br>http://localhost/"]:::external
subgraph cluster["Kubernetes Cluster (Rancher Desktop)"]
subgraph kube-system["Namespace: kube-system"]
traefik["Traefik<br>(Ingress Controller)<br>※ Rancher Desktop標準"]:::ingress
end
subgraph ns["Namespace: my-app-dev"]
ing["Ingress: my-app-nginx<br>Path: /<br>📄 base/ingress.yaml"]:::ingress
svc["Service: my-app-nginx<br>ClusterIP Port: 80<br>📄 base/service.yaml"]:::service
subgraph node["Node (Rancher Desktop VM)"]
subgraph pod["Pod: my-app-nginx-xxxxx"]
container["Container: nginx<br>(nginx:1.27) Port: 80<br>📄 base/deployment.yaml"]:::container
end
end
end
end
browser -->|HTTP Request| traefik
traefik -->|routing| ing
ing -->|backend| svc
svc -->|selector match| pod
%% スタイルの適用
class cluster cluster;
class ns,kube-system namespace;
class node node;
class pod pod;
主要コンポーネントの役割と対応するYAMLファイル
| コンポーネント | 役割 | 定義ファイル |
|---|---|---|
| Browser | http://localhost/ にアクセス |
- |
| Traefik | Rancher Desktop に最初から入っている Ingress Controller。外部からのリクエストを受け付ける | ※ Rancher Desktop標準 |
| Ingress | ルーティングルールを定義。/ パスへのリクエストを my-app-nginx Service に転送 |
base/ingress.yaml |
| Service | Pod への入口。ClusterIP で内部からアクセス可能にし、label selector で Pod を特定 |
base/service.yaml |
| Deployment | Pod の管理者。指定した数(replicas: 1)の Pod を維持 | base/deployment.yaml |
| Pod | コンテナの実行単位。この中で Nginx コンテナが動作。Deployment により自動作成される | base/deployment.yaml の template |
| Container | Nginx が実際に動いているプロセス。Port 80 で HTTP リクエストを処理 | base/deployment.yaml の containers |
| Namespace | リソースを論理的にグループ化する単位。今回は my-app-dev |
overlays/dev/namespace.yaml |
YAMLファイルとKubernetesリソースの対応
この図は、作成したYAMLマニフェストファイルが実際にKubernetes上でどのようなリソースとして展開されるかを示しています。Kustomizeによる統合プロセスと、各YAMLファイルから生成されるKubernetesオブジェクトの関係性を可視化しています。特に、DeploymentからPod、そしてContainerへと自動的に展開される階層構造に注目してください。
%%{init: {'theme':'neutral'}}%%
flowchart TD
%% Kubernetes構成要素別クラス定義
classDef cluster fill:#e8f4f8,stroke:#0077b6,stroke-width:2px;
classDef namespace fill:#dae8fc,stroke:#6c8ebf,stroke-width:2px;
classDef node fill:#d5e8d4,stroke:#82b366,stroke-width:2px;
classDef pod fill:#fff2cc,stroke:#d6b656,stroke-width:2px;
classDef container fill:#ffffff,stroke:#d79b00,stroke-width:2px;
classDef service fill:#d5e8d4,stroke:#82b366,stroke-width:2px;
classDef ingress fill:#ffe6cc,stroke:#d79b00,stroke-width:2px;
classDef external fill:#f9f9f9,stroke:#333,stroke-width:2px;
subgraph yaml["作成したYAMLファイル"]
ns_yaml["overlays/dev/namespace.yaml"]:::external
dep_yaml["base/deployment.yaml"]:::external
svc_yaml["base/service.yaml"]:::external
ing_yaml["base/ingress.yaml"]:::external
kust_base["base/kustomization.yaml"]:::external
kust_dev["overlays/dev/kustomization.yaml"]:::external
end
subgraph k8s["Kubernetesリソース"]
ns["Namespace"]:::namespace
dep["Deployment"]:::pod
pod["Pod"]:::pod
container["Container"]:::container
svc["Service"]:::service
ing["Ingress"]:::ingress
end
ns_yaml -->|作成| ns
dep_yaml -->|作成| dep
dep -->|自動作成| pod
pod -->|含む| container
svc_yaml -->|作成| svc
ing_yaml -->|作成| ing
kust_base -->|まとめる| dep_yaml
kust_base -->|まとめる| svc_yaml
kust_base -->|まとめる| ing_yaml
kust_dev -->|参照| kust_base
kust_dev -->|追加| ns_yaml
kust_dev -->|namespace指定| ns
この章では、「とりあえず Nginx を立てる」までを一通り体験しました。図で見たとおり、ブラウザ → Traefik → Ingress → Service → Pod → Container という流れでリクエストが処理されます。この「Nginx 1 個」の例が理解できていると、5章で扱うような「複数コンポーネントからなるデータパイプライン」も、同じ要領で少しずつ積み上げていけます。
5. ミニデータパイプライン構築の手順
5章では、Nginx単体の最小構成デプロイから一歩進めて 「こんな構成のデータパイプラインを動かしたい」 という設計図を起点に話を始めます。
4章で学んだ「base / overlays」パターンに加えて、ここでは以下を組み合わせます:
- Helm Chart(Airflow / MinIO のような大規模 OSS コンポーネント)
- ConfigMap(Python スクリプトの疎結合な管理)
- イベント駆動型アーキテクチャ(MinIO → Webhook → Airflow)
- Job と CronJob(初期設定と定期実行タスク)
YAML や Python コードの全文は GitHub リポジトリに置く前提で、ここでは「設計の考え方」と「つながり方」に絞って説明します。
5.1 目指すシステム構成
1つの Kubernetes Namespace(data-pipeline-dev) に、次のコンポーネントを配置したシステムの構築を目指します:
コンポーネント構成
%%{init: {'theme':'neutral'}}%%
graph RL
%% Kubernetes構成要素別クラス定義
classDef cluster fill:#e8f4f8,stroke:#0077b6,stroke-width:2px;
classDef namespace fill:#dae8fc,stroke:#6c8ebf,stroke-width:2px;
classDef node fill:#d5e8d4,stroke:#82b366,stroke-width:2px;
classDef pod fill:#fff2cc,stroke:#d6b656,stroke-width:2px;
classDef container fill:#ffffff,stroke:#d79b00,stroke-width:2px;
classDef service fill:#d5e8d4,stroke:#82b366,stroke-width:2px;
classDef ingress fill:#ffe6cc,stroke:#d79b00,stroke-width:2px;
classDef external fill:#f9f9f9,stroke:#333,stroke-width:2px;
%% 構造定義
subgraph Host["Host (Mac)"]
Browser["User / Web Browser"]:::external
subgraph K8s["k8s cluster via rancher-desktop"]
subgraph MgmtNode["Management Node"]
Ingress["Ingress Controller"]:::ingress
end
subgraph WorkerNode["Worker Node"]
%% コンポーネント
Generator["Container: Rosbag Generator<br>(CronJob)"]:::pod
Scheduler["Container: Apache Airflow<br>(Scheduler/WebServer)"]:::pod
Processor["Container: Apache Airflow<br>(Processor / Ephemeral Pod)"]:::pod
MinIO[("Container: MinIO")]:::service
end
end
end
%% --- データフローと接続 ---
%% 外部アクセス
Browser -->|"Access Web Management UI"| Ingress
Ingress --> Scheduler
Ingress --> MinIO
%% Step 1: Generator -> MinIO
Generator -->|"1. Upload dummy rosbag file"| MinIO
%% Step 2: Detection
Scheduler -.->|"2. Detect file upload (Sensor)"| MinIO
%% Spawn Process
Scheduler -->|"Spawn (Trigger)"| Processor
%% Step 3: Fetch
Processor -->|"3. Fetch rosbag file"| MinIO
%% Step 4: Convert (Self processing)
Processor -->|"4. Convert rosbag to CSV"| Processor
%% Step 5: Upload Result
Processor -->|"5. Upload converted CSV"| MinIO
%% スタイルの適用
class Host external;
class K8s cluster;
class MgmtNode,WorkerNode node;
各コンポーネントの役割
このシステムは、以下の6つの主要コンポーネントで構成します。
MinIO(S3互換ストレージ) データの保存場所です。Helm Chart を使用して構築し、
raw-data(生データ)とprocessed-data(加工後データ)という2つのバケットを用意します。認証情報は開発用としてadmin/passwordに設定します。Airflow(ワークフロー管理) データ処理の司令塔です。Helm Chart で Scheduler、Webserver、Worker を構築します。実際のデータ処理は Airflow Worker 自身では行わず、KubernetesPodOperator を使って、処理ごとに独立した Pod を動的に起動・破棄する方式をとります。
CronJob(データジェネレータ) データの発生源です。1分ごとに
generator.pyを実行する Pod を起動し、ダミーの.mcapファイルを生成して MinIO のraw-dataバケットにアップロードします。スクリプトは ConfigMap で管理します。Webhook Receiver(イベント仲介) MinIO と Airflow をつなぐ接着剤のような役割です。MinIO からの「ファイルがアップロードされた」というイベント通知を受け取り、Airflow の REST API を呼び出して DAG をトリガーします。シンプルな Python アプリ(
receiver.py)として実装します。Job(初期設定タスク) MinIOのイベント通知を設定する一度限りのタスクです。MinIO起動後に実行され、
raw-dataバケットへのファイルアップロードイベントをWebhook Receiverに通知するよう設定します。Ingress(外部アクセス) ブラウザから管理画面にアクセスするための入り口です。
airflow.localで Airflow の画面、minio.localで MinIO のコンソールにアクセスできるようにルーティングします。
データ処理の流れ
データは以下のようなイベント駆動型のフローで処理します。
- まず、CronJob が定期的に起動し、ダミーデータを生成して MinIO にアップロードします。
- MinIO はファイルのアップロードを検知すると、即座に Webhook Receiver へイベント通知を送ります。
- 通知を受け取った Webhook Receiver は、Airflow の REST API を叩いて、対応する DAG をトリガーします。
- トリガーされた Airflow DAG は、KubernetesPodOperator を使ってデータ処理専用の Pod を起動します。
- 起動した処理 Pod は、MinIO からデータを読み込んで加工し、結果を再び MinIO に保存して終了します。
5.2 3章のワークフローに沿った設計
3章で説明した開発ワークフローのベストプラクティスに従って、上記のラフ案をシステム設計していきます。
5.2.1 システムの輪郭を言語化する
まず、「どんなシステムを Kubernetes に載せたいのか」をざっくり整理します:
- 目的: ロボットのログデータ(.mcap形式)を自動的に収集・変換するパイプライン
- コンポーネント:
- ストレージ: MinIO(S3互換)
- ワークフロー管理: Airflow
- データ生成: CronJobによる定期実行
- イベント連携: Webhook Receiver
- 処理フロー: イベント駆動型(ファイルアップロード → 通知 → 処理実行)
- 環境: 開発環境(
data-pipeline-devnamespace)から始め、将来的にステージング・本番へ展開
5.2.2 アプリケーション構成を Kubernetes リソースにマッピングする
次に、各コンポーネントを Kubernetes リソースに落とし込みます:
| アプリケーション | Kubernetes リソース | 管理方法 |
|---|---|---|
| MinIO | Helm Chart → Deployment + Service | minio-values.yaml |
| Airflow | Helm Chart → 複数のDeployment + Service | airflow-values.yaml |
| データジェネレータ | CronJob + ConfigMap | cronjob.yaml + pipeline-scripts |
| Webhook Receiver | Deployment + Service | webhook-receiver.yaml + webhook-scripts |
| MinIO初期設定 | Job + ConfigMap | event-setup-job.yaml |
| 外部アクセス | Ingress | ingress.yaml |
| まとめる場所 | Namespace | data-pipeline-dev |
5.2.3 マニフェスト管理方針の決定
3章で説明した役割分担に従います:
- 外部OSS(Airflow / MinIO): Kustomizeの
helmCharts機能でHelm Chartを管理 - 自作アプリ(CronJob / Webhook / Ingress): 通常のKubernetesマニフェストとしてKustomizeで管理
- Pythonスクリプト: ConfigMapとして生成し、各Podにマウント
5.2.4 base / overlays のフォルダ構成
3章のベストプラクティスに沿ったディレクトリ構造:
apps/
data-pipeline/
base/ # 共通の定義
kustomization.yaml
cronjob.yaml
...
overlays/ # 環境ごとの差分
dev/
kustomization.yaml
namespace.yaml
src/ # アプリケーションコード
scripts/
dags/
webhook/
5.3 新しい知識:Job と CronJob
データパイプラインの構築で新たに登場する Kubernetes リソースとして、Job と CronJob があります。
5.3.1 Job とは
Job は、一度限りのタスクを実行するためのリソースです。Deploymentのように常駐するのではなく、タスクが完了したら終了します。
特徴:
- タスクが正常終了するまで Pod を再起動する
- 完了後、Pod は削除されるか保持される(
ttlSecondsAfterFinishedで制御) - 失敗時のリトライ回数を指定可能(
backoffLimit)
このデータパイプラインでは、MinIOのイベント通知設定に使用しています(event-setup-job.yaml):
このJobは、MinIO起動後に一度だけ実行され、
raw-dataバケットに.mcapファイルがアップロードされたときに、Webhook Receiverへ通知するよう設定します。
5.3.2 CronJob とは
CronJob は、定期的にタスクを実行するためのリソースです。Linuxのcronと同じように、スケジュールに従ってJobを起動します。
特徴:
scheduleフィールドでcron形式のスケジュールを指定- 指定した時刻に自動的にJobを作成・実行
- 実行履歴の保持数を制御可能(
successfulJobsHistoryLimit)
このデータパイプラインでは、2つのCronJobを使用しています:
データジェネレータ(
cronjob.yaml): 1分ごとにダミーの.mcapファイルを生成してMinIOにアップロードします。イベント設定の同期(
event-sync-cronjob.yaml): 5分ごとにMinIOのイベント通知設定を確認し、万が一失われていた場合は再設定します。
5.3.3 Job と CronJob の使い分け
| リソース | 用途 | 例 |
|---|---|---|
| Job | 一度限りの初期設定や移行タスク | データベースのマイグレーション、初期設定 |
| CronJob | 定期的なバッチ処理 | ログのアーカイブ、データの集計、バックアップ |
5.4 Helm と Kustomize の統合
このデータパイプラインでは、Kustomizeの helmCharts 機能を使ってHelm ChartとKubernetesマニフェストを統合管理します。
5.4.1 Kustomizeによる Helm 管理
kustomization.yaml の helmCharts セクション:
helmCharts: - name: airflow repo: https://airflow.apache.org version: 1.15.0 releaseName: airflow namespace: default valuesFile: airflow-values.yaml - name: minio repo: https://charts.min.io/ version: 5.4.0 releaseName: minio namespace: default valuesFile: minio-values.yaml
この方式のメリット:
- 単一コマンドでデプロイ: 後述するコマンド一発で全コンポーネントが立ち上がる
- values ファイルで環境差分を吸収: クラスタ固有の設定を調整
- 再現性の確保: Chart のバージョンを明示的に指定
重要な注意点:
kubectl 1.29以降、Helm Chart統合機能を使うには --enable-helm フラグが必須です。また、kubectl apply -k では現在このフラグがサポートされていないため、以下のように2段階でコマンドを実行します:
kubectl kustomize --enable-helm --load-restrictor LoadRestrictionsNone apps/data-pipeline/overlays/dev | kubectl apply -f -
--load-restrictor LoadRestrictionsNone は、Kustomizeが base ディレクトリの外にある src/ ディレクトリのファイルを読み込むために必要です。
5.4.2 ConfigMap による疎結合な管理
Pythonスクリプトは ConfigMap として生成し、コンテナイメージの再ビルドなしでコード更新が可能にします。
kustomization.yaml の configMapGenerator セクション:
configMapGenerator: - name: pipeline-scripts files: - ../src/scripts/generator.py - ../src/scripts/processor.py
これにより、スクリプトの変更時は kubectl apply を再実行するだけで、Podが新しいConfigMapをマウントします。
5.5 Airflow と MinIO の接続設定
設計図では Airflow と MinIO の間に矢印が引いてありますが、その中身はざっくり次の 3 層に分かれます。
5.5.1 MinIO 側:S3 互換ストレージとして立てる
MinIO は Helm Chart で立てると、minio という名前の Service が ClusterIP として立ちます。
クラスタ内からは http://minio:9000 でアクセスできます。
minio-values.yaml での主な設定:
environment: MINIO_NOTIFY_WEBHOOK_ENABLE_PRIMARY: "on" MINIO_NOTIFY_WEBHOOK_ENDPOINT_PRIMARY: "http://webhook-receiver:5000/minio-event"
5.5.2 Airflow 側:Executor と DAG のマウント設定
Airflowで分散タスク実行を行うため、CeleryExecutor を使用します。また、DAGファイル(pipeline.py)はGitSyncやPVCを使わず、ConfigMapとして各コンポーネントにマウントする方式を採用しました。
airflow-values.yaml での主な設定:
# DAGをConfigMapからマウント(Scheduler, Webserver, Worker共通) scheduler: extraVolumes: - name: dags-volume configMap: name: airflow-dags extraVolumeMounts: - name: dags-volume mountPath: /opt/airflow/dags/pipeline.py subPath: pipeline.py # Executor設定 executor: CeleryExecutor redis: enabled: true # API認証とDAGの自動有効化 config: api: auth_backends: airflow.api.auth.backend.basic_auth,airflow.api.auth.backend.session core: dags_are_paused_at_creation: "False"
重要なポイント:
- DAGのマウント:
airflow-dagsConfigMap を/opt/airflow/dags/pipeline.pyに直接マウントすることで、GitSyncなどの複雑な構成を回避しています。 - CeleryExecutor: タスクを複数のWorkerに分散実行するためにRedisと組み合わせて使用します。
- Basic認証: Webhook ReceiverからのREST API呼び出しを許可します。
- DAG自動Unpause: デプロイ直後からDAGが有効(Active)な状態になるように設定しています。
5.5.3 DAG(pipeline.py)側:KubernetesPodOperator で処理 Pod を起動
DAG の中では、KubernetesPodOperator を使って処理用の Pod を動的に起動します。 これにより、Airflow Worker とは独立した環境で重い処理を実行できます。
実際のコード(pipeline.py)の主要部分:
processor = KubernetesPodOperator(
task_id='process_data',
name='ros-processor-job',
namespace='data-pipeline-dev',
image='python:3.9-slim',
cmds=["/bin/bash", "-c"],
arguments=[
"""
pip install --no-cache-dir boto3 pandas &&
python3 /app/processor.py {{ dag_run.conf.get('key', '') }}
"""
],
volumes=[...], # ConfigMap から processor.py をマウント
env_vars={
'MINIO_ENDPOINT': 'http://minio:9000',
'MINIO_ACCESS_KEY': 'admin',
'MINIO_SECRET_KEY': 'password',
},
is_delete_operator_pod=True,
)
ポイント:
- schedule_interval=None: 定期実行ではなく、Webhook Receiver から REST API 経由でトリガーされる
- processor.py のマウント: ConfigMap(
pipeline-scripts)から/app/processor.pyとしてマウント - 環境変数で認証情報を注入: MinIO のエンドポイントと認証情報を Pod に渡す
- 処理完了後に Pod を削除:
is_delete_operator_pod=Trueでリソースを節約 - DAG実行時のパラメータ:
{{ dag_run.conf.get('key', '') }}でWebhookから渡されたファイル名を取得
processor.py が実際に行う処理:
「MinIO の
raw-dataバケットから .mcap ファイルを読み → CSV に変換 →processed-dataバケットに書き戻す」
5.5.4 Webhook Receiver:MinIO と Airflow の橋渡し
Webhook Receiver(receiver.py)は、MinIOからのイベント通知を受け取り、AirflowのREST APIを呼び出します:
@app.route('/minio-event', methods=['POST']) def handle_minio_event(): # ... イベント解析 ... if event_name == 's3:ObjectCreated:Put' and key.endswith('.mcap'): # Airflow DAGをトリガー trigger_dag('rosbag_processor_poc', {'key': key})
5.6 データパイプライン処理の最終形
設計図とコンポーネントが揃ったところで、実際にどうデータが流れるか整理します。すべてのコンポーネントを配置した最終的な構成図は以下のようになります。
%%{init: {'theme':'neutral'}}%%
graph RL
%% Kubernetes構成要素別クラス定義
classDef cluster fill:#e8f4f8,stroke:#0077b6,stroke-width:2px;
classDef namespace fill:#dae8fc,stroke:#6c8ebf,stroke-width:2px;
classDef node fill:#d5e8d4,stroke:#82b366,stroke-width:2px;
classDef pod fill:#fff2cc,stroke:#d6b656,stroke-width:2px;
classDef container fill:#ffffff,stroke:#d79b00,stroke-width:2px;
classDef service fill:#d5e8d4,stroke:#82b366,stroke-width:2px;
classDef ingress fill:#ffe6cc,stroke:#d79b00,stroke-width:2px;
classDef external fill:#f9f9f9,stroke:#333,stroke-width:2px;
subgraph Host["Host Machine"]
User["User / Browser"]:::external
end
subgraph K8s["Kubernetes Cluster"]
subgraph NS["Namespace: data-pipeline-dev"]
%% Persistent Apps (常駐アプリケーション)
subgraph Apps["Persistent Applications"]
Ingress["Ingress Controller"]:::ingress
MinIO["MinIO (Storage)"]:::service
Webhook["Webhook Receiver"]:::service
subgraph Airflow["Airflow Components"]
Web["Webserver"]:::pod
Sch["Scheduler"]:::pod
Wkr["Worker"]:::pod
Redis["Redis"]:::pod
end
end
%% Transient / Periodic Tasks (一時的・定期的なタスク)
subgraph Tasks["Transient & Periodic Tasks"]
Setup["Job: minio-event-setup<br>(Initial Setup / One-time)"]:::pod
Sync["CronJob: minio-event-sync<br>(Config Watchdog / 5min)"]:::pod
Gen["CronJob: rosbag-generator<br>(Data Producer / 1min)"]:::pod
end
%% Dynamic Workers (動的ワーカー)
subgraph Dynamic["Dynamic Workers"]
Proc["Pod: ros-processor-job<br>(KubernetesPodOperator)"]:::pod
end
end
end
%% Access Flow
User -->|"http://airflow.local"| Ingress
User -->|"http://minio.local"| Ingress
Ingress --> Web
Ingress --> MinIO
%% Setup & Maintenance Flow
Setup -.->|"Configure Events (Once)"| MinIO
Sync -.->|"Ensure Config (Periodic)"| MinIO
%% Data Pipeline Flow
Gen -->|"1. Upload .mcap"| MinIO
MinIO -.->|"2. Webhook Event"| Webhook
Webhook -->|"3. Trigger DAG API"| Web
%% Airflow Internal
Web --> Redis
Sch --> Redis
Wkr --> Redis
Sch -->|"4. Spawn Pod"| Proc
%% Processing Flow
Proc -->|"5. Read/Write Data"| MinIO
%% Styles
class Host external;
class K8s cluster;
class NS namespace;
5.6.1 Step 0: 初期設定(Job による一度限りのタスク)
システムのデプロイ時、最初に Job が実行されます:
minio-event-setupJob が起動- MinIO の起動を待機
mcコマンドを使ってraw-dataバケットにイベント通知を設定- 通知先: Webhook Receiver
- イベント:
put(アップロード) - フィルタ:
.mcap拡張子
このJobは一度だけ実行され、完了後10分で自動削除されます(ttlSecondsAfterFinished: 600)。
5.6.2 Step 1: CronJob がダミーデータを MinIO に投げる
- Kubernetes の CronJob(
cronjob.yaml)が 1分ごと(*/1 * * * *)に Pod を起動 - Pod内で
generator.pyを実行し、「ROS 2 のログ形式(.mcap)を模擬したダミーデータ」を生成 - MinIO の
raw-dataバケットにアップロード(例:robot_log_20251127_120000.mcap) - 認証情報は ConfigMap(
pipeline-config)から環境変数として注入
図にすると:
[ CronJob: rosbag-generator ]
└─(毎1分)→ [ Pod ] → generator.py
└─(S3 PUT)→ MinIO: raw-data/robot_log_*.mcap
5.6.3 Step 2: MinIO がイベント通知を Webhook Receiver に送る
- MinIO は、
raw-dataバケットにファイルがアップロードされると、Webhook 通知を送信 - 通知先は
minio-values.yamlの環境変数で設定:http://webhook-receiver:5000/minio-event - Webhook Receiver(
receiver.py)が以下の処理を実行:- MinIO からの POST リクエストを受信
- イベント内容を解析(バケット名、ファイル名、イベントタイプ)
.mcapファイルの場合、Airflow REST API を呼び出して DAG をトリガー
図にすると:
[ MinIO ]
└─(イベント通知)→ [ Webhook Receiver: /minio-event ]
└─(REST API)→ [ Airflow: POST /api/v1/dags/rosbag_processor_poc/dagRuns ]
5.6.4 Step 3: Airflow DAG が処理 Pod を起動してデータを加工
- Webhook Receiver からトリガーされた DAG(
rosbag_processor_poc)が起動 - DAG は KubernetesPodOperator を使って、専用の処理 Pod を起動:
- イメージ:
python:3.9-slim - マウント: ConfigMap(
pipeline-scripts)からprocessor.pyを/app/にマウント - 環境変数: MinIO のエンドポイントと認証情報(
admin / password)
- イメージ:
- 処理 Pod 内で
processor.pyが実行され、以下の処理を実行:- MinIO の
raw-dataバケットから.mcapファイルをダウンロード - CSV として読み込み、データを加工(
processed_flagやprocessed_atカラムを追加) - 結果を
.csvファイルとしてprocessed-dataバケットにアップロード
- MinIO の
- 処理完了後、Pod は自動的に削除される(
is_delete_operator_pod=True)
図にすると:
[ Airflow DAG: rosbag_processor_poc ]
└─[ KubernetesPodOperator ]
└─ 処理 Pod を起動
└─ processor.py
├─ MinIO: raw-data/*.mcap をダウンロード
├─ CSV に変換 & データ加工
└─ MinIO: processed-data/*.csv にアップロード
この方式の利点:
- リソースの効率化: 処理が必要な時だけ Pod を起動し、完了後は削除
- 依存関係の分離: Airflow Worker に pandas などをインストールする必要がない
- スケーラビリティ: 複数ファイルの並列処理が容易(
max_active_runs=3)
5.6.5 監視用CronJob:イベント設定の同期
バックグラウンドで、もう一つのCronJob(minio-event-sync)が5分ごとに実行されます:
- MinIO の現在のイベント設定を確認
- 設定が消えていれば再設定
これにより、何らかの理由でMinIOのイベント通知設定が失われた場合でも、自動的に復旧します。
5.7 実際にデプロイして動作確認する
ここまでで設計と実装が揃ったので、実際にRancher Desktop上にデプロイして動作を確認します。
5.7.1 デプロイコマンド
kubectl kustomize --enable-helm --load-restrictor LoadRestrictionsNone apps/data-pipeline/overlays/dev | kubectl apply -f -
このコマンドは以下を実行します:
kustomization.yamlを読み込みbaseの定義をマージ- Helm Chart(Airflow / MinIO)を展開
- ConfigMap(スクリプト類)を生成
- すべてのリソースを
data-pipeline-devnamespace に適用
5.7.2 リソースの確認
kubectl get pods -n data-pipeline-dev
5.7.3 管理画面へのアクセス
方法1: Ingress経由(推奨)
/etc/hosts に以下を追加:
127.0.0.1 airflow.local minio.local
ブラウザでアクセス:
- Airflow UI:
http://airflow.local(admin/admin) - MinIO Console:
http://minio.local(admin/password)
アクセスに成功すると以下の画面が確認できます。


方法2: Port Forward
kubectl port-forward svc/airflow-webserver 8080:8080 -n data-pipeline-dev kubectl port-forward svc/minio 9001:9001 -n data-pipeline-dev
5.7.4 動作確認
1. CronJobによるデータ生成を確認
kubectl logs -n data-pipeline-dev -l app.kubernetes.io/name=rosbag-generator --tail=20
Successfully uploaded robot_log_*.mcap というメッセージが1分ごとに出力されていれば成功です。
2. MinIOでファイルを確認
MinIO Console (http://minio.local) にアクセスし、raw-data バケットを確認。
.mcap ファイルが1分ごとに追加されているはずです。
3. Webhook Receiverのログを確認
kubectl logs -n data-pipeline-dev -l app.kubernetes.io/name=webhook-receiver --tail=20
Triggered Airflow DAG for file: robot_log_*.mcap というメッセージが表示されていれば、
MinIOからの通知を正しく受信し、Airflowをトリガーできています。
4. Airflow DAGの実行状況を確認
Airflow UI (http://airflow.local) にアクセスし、rosbag_processor_poc DAGを確認:
- DAGがunpause状態(緑の再生ボタン)になっている
- DAG Runsタブで実行履歴を確認
- 各実行の
process_dataタスクが成功(緑)になっている
5. 処理済みデータを確認
MinIO Console で processed-data バケットを確認。
.csv ファイルが追加されていれば、データ処理パイプライン全体が正常に動作しています。
5.8 トラブルシューティング
ここまでの検証環境準備の中で出会ったトラブルをまとめておきます。
5.8.1 DAGが実行されない
症状: Webhook Receiverは動作しているが、DAGが実行されない
確認手順:
DAGがPause状態になっていないか確認: Airflow UIで
rosbag_processor_pocがONになっているか。Webhook Receiverのログを確認:
bash kubectl logs -n data-pipeline-dev -l app.kubernetes.io/name=webhook-receiver403 Forbiddenが表示されている場合、Basic認証が正しく設定されていません。airflow-values.yamlのconfig.api.auth_backendsを確認してください。Airflow SchedulerがDAGを認識しているか確認:
bash kubectl exec -n data-pipeline-dev deployment/airflow-scheduler -c scheduler -- airflow dags list | grep rosbag_processor_poc
5.8.2 Workerがタスクを実行しない
症状: DAGはトリガーされるが、タスクがqueued状態のまま
確認手順:
RedisとWorkerの接続を確認:
bash kubectl logs -n data-pipeline-dev deploy/airflow-workerConnected to redisが表示されれば正常。表示されない場合、Redisが起動していない可能性があります:bash kubectl get pods -n data-pipeline-dev -l component=redisCeleryのキュー状態を確認:
bash kubectl exec -n data-pipeline-dev airflow-worker-0 -c worker -- celery -A airflow.providers.celery.executors.celery_executor_utils inspect stats
5.8.3 MinIOイベント通知が動作しない
症状: ファイルはアップロードされるが、Webhook Receiverに通知が届かない
確認手順:
イベント設定Jobのログを確認:
bash kubectl logs -n data-pipeline-dev job/minio-event-setupEvent notification added successfullyが表示されていれば設定は完了しています。MinIOのイベント設定を直接確認:
bash kubectl exec -n data-pipeline-dev deployment/minio -- mc alias set myminio http://localhost:9000 admin password kubectl exec -n data-pipeline-dev deployment/minio -- mc event list myminio/raw-dataイベント設定を再適用:
bash kubectl delete job minio-event-setup -n data-pipeline-dev kubectl kustomize apps/data-pipeline/overlays/dev --enable-helm --load-restrictor LoadRestrictionsNone | kubectl apply -f -
5.9 リソースのクリーンアップ
検証が完了したら、以下のコマンドでリソースを削除できます:
kubectl delete namespace data-pipeline-dev
個別のリソースを削除したい場合:
# Kustomize経由で削除(Helm Chartは削除されない場合があるため、Namespace削除を推奨) kubectl delete namespace data-pipeline-dev
5章では、3章で説明した開発ワークフローのベストプラクティスに従って、実際のデータパイプラインを構築しました。
この構成は、ローカル環境(Rancher Desktop)で動作確認した後、同じマニフェストをステージング・本番環境にも展開できます。base/overlaysの分離により、環境ごとの差分管理が容易になっています。
実際の YAML や Python コードは GitHub リポジトリにまとめてありますので、手元の Rancher Desktop で試してみてください。
6. まとめ
この記事では、「Kubernetesよく分からん……」というところからスタートして、Rancher Desktop上に小さなシステムを2つ動かしてみました。1つ目はNginxだけのシンプルなWebアプリ、2つ目はAirflow + MinIO + CronJobを組み合わせたミニデータパイプラインです。
前半では、Pod / Deployment / Service / Ingress / Namespace、それからControl PlaneとWorker Nodeにどんなコンポーネントがいるのかをざっくり押さえつつ、「YAMLを書くとクラスタの中で何が起きるのか?」をイメージできるようにしてきました。kubectl config current-context を確認しながら、Kustomizeのbase/overlaysでDeployment → Service → Ingressを管理して、最終的にブラウザから http://localhost/ でNginxにアクセスできるところまで手を動かしました。
後半では、「こんな感じのデータパイプラインを動かしたい」というラフな設計図から出発して、1つのNamespaceの中にMinIO(S3互換ストレージ)とAirflow(DAG実行基盤)、ダミーデータを作るCronJob、MinIOとAirflowを繋ぐWebhook Receiverを置き、 CronJob → MinIO(raw) → Webhook Receiver → Airflow(DAG)→ MinIO(processed) というシンプルな流れを実際に動かしてみました。AirflowとMinIOの連携は、KubernetesPodOperatorで起動する処理用Podに環境変数(エンドポイント、アクセスキー、シークレットキー)を渡し、Pod内でboto3を使ってS3互換APIでMinIOにアクセスする形を確認しています。
このあたりまでできると、
- 外部OSSはHelm Chartで箱ごと入れる
- 自分たちのアプリや環境差分はKustomizeで面倒を見る
という役割分担のイメージがだいぶハッキリしてくると思います。Rancher Desktop上の「1ノード・1クラスタ」という小さな世界ではありますが、「自分の手でミニマムなデータ基盤を構築してみた」という感覚は残るはずです。
とはいえ、ここまでで作ったものはあくまで学習用の環境です。本番システムと比べると、まだまだ足りていないポイントがたくさんあります。
例えば:
- 認証・認可(OIDC / SSO、NamespaceごとのRBAC、NetworkPolicyなど)
- 複数ノード構成(Control Plane / Workerの分離、ストレージの冗長化)
- 信頼性・可用性(PodDisruptionBudget、ローリングアップデート時の挙動設計)
- 監視・ログ(メトリクス収集、ログ集約、ダッシュボード)
- CI/CD・GitOps(ローカルからの kubectl apply ではなく、Git起点のデプロイフロー)
今回触れた infra/ や apps、base と overlays といったディレクトリ構成は、そのままGitHub ActionsやArgo CDに載せやすい形になっているので、「今はローカル検証だけど、この先ステージング・本番へ広げていくイメージ」もつかみやすいはずです。
ざっくり言うと、このブログでやったのは「Rancher Desktop上の小さなクラスタで、Kubernetes / Helm / Kustomizeの基本と、ミニなデータパイプライン構成を手を動かしながら一周してみた」というところまでです。本番へ向けた上記の課題は、今後別のブログ記事にまとめていければと思います。
参考資料
最後に、この記事から一歩進むための公式リソースをまとめておきます。
Kubernetes / Helm / Kustomize
- Kubernetes公式ドキュメント(概念説明、チュートリアル、リファレンス)(Kubernetes Documentation)
- kubectlコマンドのチートシート(kubectl Cheat Sheet)
- Helm公式ドキュメント(Chartの構造、
helm install/helm upgradeの詳細など)(Helm Documentation) - Kustomize公式ドキュメント(
kubectl apply -kの仕組みやパッチの書き方)(Kustomize Documentation)
最初は Kubernetes の Basics チュートリアルと、kubectl チートシートに目を通しつつ、この記事で出てきたコマンドを照らし合わせてみると理解が深まりやすいです。
ローカル環境 / ツール
- Rancher Desktop公式ドキュメント(インストール方法、Kubernetesクラスタ設定など)(Rancher Desktop Documentation)
- Helm Chartの検索ポータル(Airflow / MinIO などのChartもここから探せます)(Artifact Hub)
この記事の構成を手元でなぞる場合は、Rancher Desktopのインストール手順と、helm の基本的な使い方の章をざっと確認しておくのがおすすめです。
Airflow / MinIO
- Apache Airflow公式ドキュメント(Helm Chart、Kubernetes Executor関連の解説など)(Apache Airflow Documentation)
- MinIO公式ドキュメント(Kubernetesへのデプロイ方法、S3互換APIの使い方)(MinIO Documentation)
5章のミニデータパイプラインをもう少し発展させたい場合は、Airflowのチュートリアルと、MinIOのKubernetes向けガイドが良い足がかりになります。
We Are Hiring!
ABEJAは、テクノロジーの社会実装に取り組んでいます。 技術はもちろん、技術をどのようにして社会やビジネスに組み込んでいくかを考えるのが好きな方は、下記採用ページからエントリーください! (新卒の方やインターンシップのエントリーもお待ちしております!) careers.abejainc.com
特に下記ポジションの募集を強化しています!ぜひ御覧ください!
