こんにちは、現場の最前線でインフラの荒波に揉まれているエンジニアの皆さん、あるいはこれからその深淵に足を踏み入れようとしている勇敢な挑戦者の皆さん。
今日は、現代のソフトウェア開発において「最強の武器」の一つとなる、GitHub Actionsを用いたKubernetes(k8s)へのCI/CDパイプライン構築についてお話しします。
「k8sを触り始めたけれど、デプロイのたびに手動でコマンドを打つのが不安だ」「本番環境への自動化って、結局何が正解なの?」そんな悩みを持つあなたへ。この記事を読み終える頃には、あなたは「ボタン一つで、安全かつ確実に世界へコードを届ける魔法」を手に入れているはずです。
では、一緒にその扉を開けてみましょう。
—
1. 勝利の設計図:GitOpsとCI/CDの全体アーキテクチャ
まず、私たちがこれから作り上げる「理想郷」の地図を確認しましょう。
手動デプロイの最大の問題は「再現性」と「透明性」の欠如です。誰が、いつ、どのバージョンをデプロイしたのか? それを解決するのが、Gitを唯一の正解(Single Source of Truth)とするGitOps的思想です。
1. Code Push: 開発者がGitHubへコードをプッシュする。
2. CI (Continuous Integration): GitHub Actionsが起動し、テストを実行。Dockerイメージをビルドする。
3. Registry Push: ビルドしたイメージをGitHub Container Registry(GHCR)に格納する。
4. CD (Continuous Deployment): クラスターに接続し、新しいイメージをデプロイ(マニフェストを反映)する。
この流れの中で、「一度作ったイメージは二度と変更しない(Immutable Infrastructure)」という原則を守ることが、冪等性(べきとうせい)を担保する鍵となります。
—
2. 燃料を運ぶ:GitHub ActionsからGHCRへのプッシュ
まずは、コンテナという「荷物」を「倉庫(レジストリ)」に届ける工程です。ここでは、GitHubが提供するレジストリであるGHCRを使います。
以下のワークフローファイル(`.github/workflows/deploy.yml`)を見てください。これが自動化の心臓部です。
name: Build and Deploy to K8s
on:
push:
branches: [ “main” ] # mainブランチにマージされたら発動
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write # GHCRへの書き込み権限
steps:
- name: Checkout repository
uses: actions/checkout@v4
# 1. レジストリへのログイン(パスワードを直接書かないのがプロの嗜み)
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# 2. メタデータの抽出(タグ付けを自動化し、トレーサビリティを確保)
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=,format=short
# 3. ビルド & プッシュ
# ‘latest’タグは極力避け、GitのSHA(ハッシュ値)で管理するのが現場の鉄則
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
【現場の知恵】
`latest`タグを本番環境で使うのはやめましょう。何が動いているか不明瞭になり、ロールバックが困難になります。Gitのコミットハッシュ(SHA)をタグに使うことで、「このコードがこのイメージだ」という完全な紐付けが可能になります。
—
3. 聖域への接続:kubectlを使った自動デプロイ
荷物が倉庫に届いたら、次はk8sクラスターに「これを動かしてくれ」と命令を出す番です。
ここでは、最も標準的な`kubectl`を使った手法を紹介します。しかし、クラスターの認証情報をGitHub Actionsにどう渡すかが問題です。
事前準備:Kubeconfigの取得
あなたのクラスターの接続情報(Kubeconfig)を、GitHubのリポジトリ設定の `Settings > Secrets and variables > Actions` に `KUBE_CONFIG` という名前で保存してください。
deploy:
needs: build-and-push # ビルドが終わってから実行
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
# Kubeconfigを設定してkubectlを使えるようにする
- name: Set up Kubeconfig
run: |
mkdir -p ~/.kube
echo “${{ secrets.KUBE_CONFIG }}” > ~/.kube/config
chmod 600 ~/.kube/config
# イメージの更新とデプロイ
# 既存のマニフェスト内のイメージタグを、今回ビルドしたものに書き換えて反映
- name: Deploy to Kubernetes
run: |
IMAGE_TAG=${GITHUB_SHA::7}
# 宣言的なapplyこそがk8sの真髄。
# 現場ではHelmを使いたいところですが、まずは基本のkubectlから。
sed -i “s|ghcr.io/my-user/my-repo:.|ghcr.io/my-user/my-repo:${IMAGE_TAG}|g” k8s/deployment.yaml
kubectl apply -f k8s/
【現場の知恵】
本来、本番環境への接続は「踏み台」や「VPN」越しであるべきです。GitHub ActionsのRunnerがクラウド(AWS/GCP/Azure)上にあるなら、OIDC (OpenID Connect) を使って一時的な認証トークンを発行するのが、2024年現在の「最高峰のセキュリティ」です。
—
4. 影の主役:シークレット情報の安全な管理
アプリケーションが必要とするAPIキーやデータベースのパスワード。これらをGitにコミットするのは、家に鍵をかけずに泥棒を招待するようなものです。
k8sには `Secret` リソースがありますが、これもBase64エンコードされているだけで暗号化はされていません。
1. GitHub Secrets: デプロイ時に必要な情報はここに隠す。
2. K8s Secrets: クラスタ内に手動、あるいは外部ツールで作成しておく。
3. 推奨される進化形: 現場では Sealed Secrets(暗号化したままGit管理できる)や External Secrets Operator(AWS Secrets Managerなどから同期する)を導入します。
まずは一歩目として、「環境変数はConfigMap、機密情報はSecret」という使い分けを徹底しましょう。
—
結びに:これをマスターしたあなたへ
お疲れ様でした。これであなたは、コードを書き、プッシュするだけで、世界中のユーザーに最新の機能を届けるパイプラインのオーナーになりました。
今回紹介したのは「基礎」ですが、これこそがすべての「極み」への出発点です。
- 冪等性: 何度実行しても同じ状態になるマニフェスト。
- 可観測性: どのバージョンが動いているか一目でわかるタグ管理。
- 安全性: 認証情報を外に出さない設計。
これらを意識するだけで、あなたのインフラ構築の質は劇的に向上します。毎日のデプロイ作業が、恐怖から「楽しみ」へと変わる瞬間を、ぜひ体感してください。
もし、さらに深い「Helmによるテンプレート化」や「ArgoCDによるプル型デプロイ」に興味が湧いたら、いつでもまたここに来てください。深淵は、常にあなたの挑戦を待っています。
Happy Orchestrating!