
<初心者向け>ローカル環境でKubernetesクラスタを構築し、Argo CDでGitOpsデプロイを体験してみた
はじめに
クラウド事業本部、あきやまです。
今、勉強も兼ねてkubernetesを触っています。実はローカルPCだけで、クラスタの構築からGitOpsによる自動デプロイまで体験できることを知りClaude Codeと壁打ちしながら実施していきました。この記事では、kindというツールを使ってKubernetesクラスタを立ち上げ、Argo CDでGitHubリポジトリと連携する方法をステップバイステップで解説します。
また初心者の方でも分かるよう、各コマンドの詳細についても補足を入れながら実施しています。
1. 前提条件・環境
以下がインストールされていることを前提とします。
| ツール | 用途 | インストール方法 |
|---|---|---|
| Homebrew | macOS用パッケージマネージャー | brew.sh |
| Docker | コンテナランタイム | Docker Desktop または OrbStack |
| Git | バージョン管理 | brew install git |
補足: OrbStackとは?
OrbStackはDocker Desktopの代替として使えるmacOS向けのコンテナランタイムです。軽量で高速に動作するのが特徴です。Docker Desktopでも問題なく動作しますので、お好みの方を使ってください。
利用するツール
| 技術 | 説明 |
|---|---|
| kind | Docker上にKubernetesクラスタを作るツール |
| kubectl | Kubernetesを操作するコマンドラインツール |
| Argo CD | GitOpsを実現するCDツール |
| NGINX Ingress Controller | 外部からのHTTPリクエストをクラスタ内に中継するコンポーネント |
2. ツールのインストール
何をやるのか: Kubernetesクラスタの構築・操作に必要な3つのCLIツールをインストールします。
なぜやるのか: これらのツールがないと、クラスタの作成・操作・GitOps管理ができません。
インストール
# kind(Kubernetes in Docker)をインストール
# ローカルPCにDockerコンテナを使って軽量なKubernetesクラスタを作れるツール
brew install kind
# kubectl(クーベシーティーエル)をインストール
# Kubernetesクラスタに命令を送るための公式CLI。Podの作成・削除・ログ確認など何でもできる
brew install kubectl
# Argo CD CLIをインストール
# Argo CDの操作をターミナルから行うためのCLI
brew install argocd
バージョン確認
正しくインストールされたか確認しましょう。
# kindのバージョンを表示
kind version
# kubectlのバージョンを表示
# --client を付けることで、クラスタに接続せずCLI自身のバージョンだけを表示する
# (まだクラスタを作っていないので、--client がないとエラーになる)
kubectl version --client
# Argo CD CLIのバージョンを表示
# --client を付ける理由はkubectlと同じ
argocd version --client
それぞれバージョン番号が表示されれば成功です。
3. kindでKubernetesクラスタを作る
何をやるのか: kindを使って、ローカルPC上にKubernetesクラスタを作成します。
なぜやるのか: Kubernetesを使うには、まずクラスタ(Kubernetesが動く環境)が必要です。kindを使えば、Dockerさえあれば数分でクラスタを立ち上げられます。クラウド上に本番クラスタを作らなくても、ローカルで学習・実験ができるのが大きなメリットです。
クラスタ設定ファイルを作る
まず、クラスタの設定ファイルを作ります。プロジェクトルート直下に kind-config.yaml を作成してください。
# このファイルがkindのクラスタ設定であることを示す
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
# control-plane = マスターノード(クラスタ全体を管理する司令塔)
# kindではこの1台がワーカーノード(実際にアプリが動く場所)も兼務する
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
# Ingress Controllerがこのノードで動けるように目印(ラベル)を付ける
node-labels: "ingress-ready=true"
# extraPortMappings = DockerコンテナのポートをローカルPCに公開する設定
# これがないと、ローカルPCのブラウザやcurlからクラスタ内のアプリにアクセスできない
extraPortMappings:
# ポート80(HTTP)をローカルPCに公開 → curlやブラウザでアクセスできるようになる
- containerPort: 80
hostPort: 80
protocol: TCP
# ポート443(HTTPS)をローカルPCに公開
- containerPort: 443
hostPort: 443
protocol: TCP
# ポート30080はNodePort用(Ingress導入前のアクセス手段として残しておく)
- containerPort: 30080
hostPort: 30080
protocol: TCP
用語解説: extraPortMappingsとは?
kindのクラスタはDockerコンテナの中で動いています。そのため、普通にクラスタを作っただけでは、ローカルPCからクラスタ内のアプリにアクセスできません。extraPortMappingsは「Dockerコンテナのこのポートを、ローカルPCのこのポートに繋いでね」という設定です。これによりlocalhost:80でクラスタ内のアプリにアクセスできるようになります。
クラスタを作成する
# kindクラスタを作成する
# --name k8s-learn → クラスタに「k8s-learn」という名前を付ける
# --config kind-config.yaml → 上で作った設定ファイルを使う
kind create cluster --name k8s-learn --config kind-config.yaml
作成には1〜2分ほどかかります。完了したら、クラスタの情報を確認しましょう。
# クラスタが正常に作成されたか確認する
# --context kind-k8s-learn → kindが自動で作成したコンテキスト名を指定
# (コンテキスト = 「どのクラスタに接続するか」という設定のこと)
kubectl cluster-info --context kind-k8s-learn
「Kubernetes control plane is running at ...」と表示されれば成功です。
ここでつまずきやすいポイント
kind create clusterが失敗する場合は、Dockerが起動しているか確認してください- 「already exists」というエラーが出たら、
kind delete cluster --name k8s-learnで削除してからやり直してください- ポート80が既に使われている場合(例: 別のWebサーバーが動いている)は、そちらを停止してからやり直してください
この時点の構成
今はまだ空のクラスタが出来上がっただけの状態です。ここにアプリをデプロイしていきます。
4. Ingress Controllerのインストールと手動デプロイで動作確認
何をやるのか: NGINX Ingress Controllerをインストールし、kubectl(手動コマンド)でアプリをデプロイして動作確認します。
なぜやるのか: GitOps(Argo CD)に進む前に、まずKubernetesの基本的なデプロイの流れを理解しましょう。「自分の手でコマンドを打ってデプロイする」という体験が、後でArgo CDの自動化のありがたみを実感するための土台になります。
Ingress Controllerをインストールする
まず、外部からクラスタ内のアプリにアクセスするための「入口」を作ります。
# NGINX Ingress Controllerをインストール
# Ingress Controller = 外部からのHTTPリクエストを受け取り、クラスタ内の適切なサービスに振り分ける門番
# kind専用のマニフェストを使う(クラウド版とはLoadBalancerの扱いが異なるため)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
# Ingress ControllerのPodが起動するまで待つ(最大5分)
# --for=condition=ready → Podが「準備完了」状態になるまで待機する
kubectl wait --namespace ingress-nginx \
--for=condition=ready pod \
--selector=app.kubernetes.io/component=controller \
--timeout=300s
用語解説: Ingress(イングレス)とは?
Kubernetesクラスタの外からHTTPリクエストを受け取り、クラスタ内のサービスに振り分ける仕組みです。Ingressには「ルール(どのパスをどのサービスに送るか)」と「Controller(ルールを実際に処理するプログラム)」の2つが必要です。ここではNGINXベースのIngress Controllerを使います。
アプリケーションをデプロイする
まず、マニフェストを格納するディレクトリを作成します。
mkdir -p k8s/base
次に、以下の4つのマニフェストファイルを作成します。
1. k8s/base/namespace.yaml — アプリ用の名前空間を定義する
apiVersion: v1
kind: Namespace
metadata:
name: test
2. k8s/base/deployment.yaml — nginxコンテナを2つのPodで動かす設定
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-app
namespace: test
spec:
replicas: 2
selector:
matchLabels:
app: test-app
template:
metadata:
labels:
app: test-app
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
3. k8s/base/service.yaml — Podへのアクセスを束ねる窓口を定義する
apiVersion: v1
kind: Service
metadata:
name: test-app
namespace: test
spec:
selector:
app: test-app
ports:
- port: 80
targetPort: 80
4. k8s/base/ingress.yaml — 外部からのHTTPリクエストをServiceに振り分けるルールを定義する
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-app
namespace: test
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: test-app
port:
number: 80
4つのファイルを作成したら、まとめてクラスタに適用します。
# k8s/base/ にあるマニフェスト(設定ファイル群)を一括でクラスタに適用する
# -f → 指定したディレクトリ内のYAMLファイルをまとめて適用する
# これにより Namespace、Deployment、Service、Ingressなどが一度に作成される
kubectl apply -f k8s/base/
# Podの起動状態をリアルタイムで監視する
# -n test → testというNamespace(名前空間)の中を見る
# -w → watchモード。状態が変わるたびに画面が更新される。全てRunningになったらCtrl+Cで終了
kubectl get pods -n test -w
用語解説: Pod(ポッド)、Namespace(ネームスペース)、Deployment(デプロイメント)とは?
- Pod: Kubernetesでアプリを動かす最小単位。1つのPodに1つのコンテナが入っている(複数入ることもある)
- Namespace: クラスタ内を論理的に区切る仕組み。「test用の部屋」「argocd用の部屋」のように、リソースをグループ分けできる
- Deployment: 「このアプリを何個のPodで動かすか」「どのイメージを使うか」などを定義する設定。Podが落ちたら自動で再作成してくれる
動作確認
全てのPodがRunningになったら、curlコマンドでアプリの動作を確認しましょう。
# nginxのデフォルトページが表示されることを確認
# 期待結果: 「Welcome to nginx!」を含むHTMLが返ってくる
curl http://localhost/
「Welcome to nginx!」を含むHTMLが返ってくれば、KubernetesへのアプリデプロイとIngress経由のアクセスが成功しています。
この時点の構成
ここまでで「手動デプロイ」は完了です。しかし、毎回 kubectl apply を手で打つのは面倒ですし、「今クラスタに何が適用されているか」がわかりにくいですよね。次のセクションから、この作業を自動化する Argo CD を導入していきます。
5. Argo CDのインストールとアクセス
何をやるのか: Argo CDをKubernetesクラスタにインストールし、Web UIにアクセスできるようにします。
なぜやるのか: Argo CDは「GitOps」を実現するためのツールです。GitOpsとは、Gitリポジトリを信頼できる唯一の情報源(Single Source of Truth)として扱い、Gitに書かれた設定とクラスタの状態を常に同期させる運用手法です。kubectl applyを手で打つ代わりに、Gitにpushするだけでデプロイが完了します。
Argo CDをインストールする
# Argo CD専用のNamespace(名前空間)を作成する
# Argo CDのコンポーネントを他のアプリから分離するため
kubectl create namespace argocd
# Argo CDの公式マニフェストを適用してインストール
# -n argocd → argocd Namespaceにインストールする
# --server-side=true → サーバー側で差分管理するモード
# Argo CDのマニフェストは非常に大きく、通常のapplyだとサイズ上限を超えてエラーになるため
# --force-conflicts → フィールドの所有権の競合を強制的に解決する(初回インストール時に安全に使える)
kubectl apply -n argocd \
-f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml \
--server-side=true --force-conflicts
# Argo CDのサーバーが起動するまで待つ(最大5分)
# Argo CDのDockerイメージのダウンロードに時間がかかる場合があるため、余裕を持って300秒に設定
kubectl wait --for=condition=available --timeout=300s \
deployment/argocd-server -n argocd
Argo CDのWeb UIにアクセスする
Argo CDはクラスタの中で動いているため、ローカルPCからアクセスするには「ポートフォワード」が必要です。
# まず、ログインに必要な初期パスワードを取得する
# Argo CDインストール時にadminユーザーの初期パスワードが自動生成されている
# このパスワードをメモしておく
argocd admin initial-password -n argocd
次に、別のターミナルウィンドウを開いて以下のコマンドを実行します(このコマンドは実行中ずっとターミナルを占有します)。
# ポートフォワードを実行する
# ローカルPCのポート8443をクラスタ内のArgo CDサーバー(ポート443)に接続するトンネルを作る
# 重要: このターミナルは閉じないこと!閉じるとArgo CDにアクセスできなくなる
kubectl port-forward svc/argocd-server -n argocd 8443:443
ブラウザで以下のURLにアクセスしてください。
- URL:
https://localhost:8443 - ユーザー名:
admin - パスワード: 上のコマンドで取得したもの
ここでつまずきやすいポイント
- ブラウザで「この接続ではプライバシーが保護されません」と警告が出ます。これはローカル環境の自己署名証明書が原因なので、**「詳細設定」→「localhost にアクセスする(安全ではありません)」**をクリックして進んでください
- ポートフォワードのターミナルを閉じてしまった場合は、再度
kubectl port-forwardコマンドを実行してください
6. GitHubリポジトリとArgo CDの連携(SSH認証含む)
何をやるのか: GitHubのプライベートリポジトリをArgo CDに登録し、リポジトリ内のKubernetesマニフェストを監視させます。
なぜやるのか: Argo CDがGitリポジトリの変更を検知して自動デプロイするためには、まずリポジトリの場所と認証情報を教えてあげる必要があります。プライベートリポジトリの場合はSSH鍵での認証が必要です。
6a. GitHubリポジトリの準備
まだGitHubにリポジトリを作っていない場合は、以下の手順で準備します(既にpush済みの方はスキップしてください)。
# Gitリポジトリとして初期化する(まだの場合)
git init
# 全ファイルをステージング(コミット対象に追加)
git add .
# 最初のコミットを作成
git commit -m "initial commit"
# GitHubにリモートリポジトリを登録する
# YOUR_USERNAME → 自分のGitHubユーザー名に置き換えてください
git remote add origin git@github.com:YOUR_USERNAME/kubernetes-beginner.git
# GitHubにpushする
# -u → upstream(上流)を設定。以降は「git push」だけでpushできるようになる
git push -u origin main
補足: SSH鍵の準備
GitHubにSSHでアクセスするには、SSH鍵のペア(秘密鍵と公開鍵)が必要です。まだ設定していない方は GitHub公式ドキュメント を参照してください。本番環境ではリポジトリ単位の「Deploy Key」を使うのがベストプラクティスですが、学習用途では個人のSSH鍵でも問題ありません。
6b. Argo CDにリポジトリを登録する
# Argo CD CLIでログインする
# localhost:8443 → ポートフォワード先のアドレス
# --insecure → 自己署名証明書のTLS検証をスキップ(ローカル環境用)
argocd login localhost:8443 --insecure
# プロンプトが表示されたら、ユーザー名「admin」と初期パスワードを入力する
# SSH秘密鍵を使ってプライベートリポジトリを登録する
# この鍵がクラスタ内のSecretとしてコピーされ、
# Argo CDはこの鍵を使ってGitHubリポジトリを定期的にチェック(デフォルト3分間隔)する
argocd repo add git@github.com:YOUR_USERNAME/kubernetes-beginner.git \
--ssh-private-key-path ~/.ssh/argocd_k8s_learn
ここでつまずきやすいポイント
--ssh-private-key-pathのパスは自分のSSH秘密鍵のパスに置き換えてください- 「Permission denied (publickey)」エラーが出る場合は、SSH鍵の公開鍵がGitHubに登録されているか確認してください
- ポートフォワードが切れていると
argocd loginが失敗します。別ターミナルでポートフォワードが動いているか確認してください
6c. Argo CDにアプリケーションを登録する
まず、手動デプロイしたリソースを削除します(Argo CDと手動の両方で管理すると競合するため)。
# Step 5で手動デプロイしたリソースを全て削除する
# 同じリソースを2つの方法(手動 + Argo CD)で管理すると競合が起きるため、
# Argo CDに管理を任せる前に手動デプロイ分を削除する
kubectl delete -f k8s/base/
次に、Argo CDのApplication設定をクラスタに適用します。プロジェクトには k8s/argocd/application.yaml というファイルが用意されています。
# k8s/argocd/application.yaml の内容(参考)
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: test-app
namespace: argocd
spec:
project: default
source:
# 監視するGitリポジトリのURL
repoURL: git@github.com:YOUR_USERNAME/kubernetes-beginner.git
# 監視するブランチ(HEADは最新のコミットを指す)
targetRevision: HEAD
# リポジトリ内の監視対象パス
path: k8s/base
destination:
# デプロイ先のクラスタ(kubernetes.default.svc = 自分自身のクラスタ)
server: https://kubernetes.default.svc
namespace: test
syncPolicy:
automated:
# prune: true → Gitから削除されたリソースはクラスタからも削除する
prune: true
# selfHeal: true → クラスタ側で手動変更されてもGitの状態に自動で戻す
selfHeal: true
syncOptions:
- CreateNamespace=true
# Argo CD Applicationをクラスタに適用する
# これによりArgo CDがGitHubリポジトリのk8s/base/を監視し始める
kubectl apply -f k8s/argocd/application.yaml
# 同期状態を確認する
# Synced = GitとクラスタがSynced(一致)、OutOfSync = 差分あり
argocd app get test-app
# 手動で同期を実行する(初回は手動で正しく動くか確認する)
argocd app sync test-app
同期が成功すると、Argo CDのWeb UI(https://localhost:8443)でアプリケーションが緑色の「Synced」「Healthy」状態になっているはずです。
7. GitOpsを体験する(git push → 自動デプロイ)
何をやるのか: Gitリポジトリのマニフェストを変更してpushし、Argo CDが自動的にクラスタへ反映することを体験します。
なぜやるのか: これこそがGitOpsの真骨頂です。「kubectl apply を手で打つ」のではなく、「Gitにpushするだけ」でデプロイが完了する。この体験を通じて、GitOpsの便利さと安全性を実感してもらいます。
レプリカ数を変更してpushする
k8s/base/deployment.yaml の replicas(Podの数)を変更してみましょう。例えば、現在の値を 3 に変更します。
# k8s/base/deployment.yaml の該当部分
spec:
replicas: 3 # ← この数字を変更する(例: 2 → 3)
変更したら、GitHubにpushします。
# 変更をステージングする
git add k8s/base/deployment.yaml
# コミットする
git commit -m "scale to 3 replicas"
# GitHubにpushする(upstream設定済みなのでブランチ指定不要)
git push
自動同期を確認する
pushした後、少し待ってからArgo CDの状態を確認します。
# Argo CDがGitの変更を検知して同期したか確認する
# selfHeal: true に設定しているので、自動で同期される
# ※ デフォルトでは最大3分間隔でリポジトリをチェックしている
argocd app get test-app
Argo CDのWeb UI(https://localhost:8443)でも確認してみましょう。アプリケーションをクリックすると、Podが3つに増えている様子がビジュアルで確認できます。
# Podの数が変更後の値になっていることを確認
kubectl get pods -n test
補足: なぜ「最大3分」かかるのか?
Argo CDはデフォルトで3分間隔(180秒)でGitリポジトリをポーリング(定期的にチェック)しています。pushした直後に反映されない場合は、少し待つかargocd app sync test-appで手動同期してみてください。
完成後の構成
クリーンアップ
学習が終わったら、以下のコマンドでクラスタを削除してリソースを解放しましょう。
# kindクラスタを完全に削除する(クラスタ内の全リソースも一緒に消える)
kind delete cluster --name k8s-learn
Claude Codeを利用しながら進めていきましたがやはり手を動かすのって大事ですね。
実際、手動かすことで手順書通りいかない部分も確認することができ他の知識のキャッチアップもできました。
引き続きkubernetesの勉強を進めていきたいと思います。







