2023年11月5日追記
macOS アップデート後に問題が発生した方は記事の最後を参照してください。
WSL/Ubuntu
での構築方法は同時に公開した記事を参照してください。
開発環境の構築はエンジニアにとって最初の登竜門ですが、コンテナ環境は特に Docker Desktop の有料化やローカルでの Kubernetes の実行などのハードルもあり、経験豊富なエンジニアにとっても一筋縄にはいかない難しさがあるように感じます。
今回は Windows(WSL)
Mac
Linux(Ubuntu)
ユーザーが同一の開発体験を得られることを目標にコンテナ開発環境の構築方法をご紹介します。
また、
-
Kubernetes
を学びたいがどうして良いかわからない -
本番環境に近いコンテナ実行環境
をローカルで実現したい -
CI/CD
を回して高速にコンテナアプリケーションを開発したい
という方も参考にしてみてください。
前提条件
Mac OS のパッケージマネージャー Homebrew
を利用しますので事前にセットアップしておいてください。
Skaffold とは
Google が開発しオープンソースで提供している、ローカルで Kubernetes ネイティブなアプリケーションを開発するためのコマンドラインツールです。
Golang で書かれておりシングルバイナリで動きます。
Google Cloud Deploy
を用いればローカルだけではなくクラウドでもデリバリーパイプラインを構築できますし、Kustomize
Helm
など Kubernetes をより効率的に扱う支援ツールにも対応しているので覚えておいて損はないと思います。
MicroK8s とは
MicroK8s
はローカルでも動作する軽量な Kubernetes ディストリビューションです。
他の候補としては Minikube
や K3s
等が挙げられますが、 MicroK8s はエンタープライズサポートや複数ノード対応など本番環境としての運用も可能で、開発や本番で有用なアドオンも充実しているのが特徴です。
詳しくは本家の比較表を参照してください。
ちなみに私は以前は Minikube を使っていましたが registry
hostpath-storage
linkerd
といった実用的なアドオンに惹かれて乗り換えました。
Mac に MicroK8s (+ Multipass ) をインストールする
Mac では MicroK8s は Multipass という仮想マシン管理ツールで作成された Ubuntu 上で動作します。
どちらも Canonical 社が開発しているので相性については問題なく、以下のコマンドで Multipass と MicroK8s の両方がインストールされます。
brew install ubuntu/microk8s/microk8s
microk8s install
# リリースチャンネルを指定する場合
microk8s install --channel 1.21
microk8s install
で失敗した場合は microk8s uninstall
して Mac を再起動してやり直してみてください。
ちなみに今は大丈夫ですが、 Apple シリコンの Mac が登場してすぐの頃はインストールされる Multipass のバージョンが 1.7
で Apple シリコンに対応していなかったので Github の Multipassリポジトリ から対応したバージョン 1.8 以降
を手動でインストールする必要がありました。
当時は Apple シリコンの Mac で Docker Desktop を動作させるには Rossetta 2
をインストールする必要があったので、Rossetta 2 なしで Docker 環境を作る際に Mutipass はとても重宝しました(今は Docker Deskop も Rosseta 2 が必須要件ではなくなったようです1)。
Kubernetes の設定ファイルは .kube
に格納されます。
存在しない場合は作成し、存在する場合は既存のものとマージします。
cd $HOME
mkdir .kube
cd .kube
microk8s config > config
既存の環境と分けて設定を管理したい場合は先ほどの手順を .kube
ではなく .microk8s
フォルダで実行し KUBECONFIG
環境変数を利用するか --kubeconfig
フラグを利用してください(後述する Skaffold
にも --kubeconfig
は指定できます)。
export KUBECONFIG=$HOME/.microk8s/config
# または
kubectl --kubeconfig=$HOME/.microk8s/config
再起動し以下のコマンドで MicroK8s が正常に動作していることを確認します。
(起動には少し時間がかかります)
microk8s status
MicroK8s には多くの便利なアドオンがありますが今回有効にするのは以下の2つです。
microk8s enable dns
microk8s enable registry
Kubernetes に慣れていない方はダッシュボードを使うことで状態をグラフィカルに確認できます。
アドオンを有効にするだけではなく追加でポートフォワード等の設定も必要なので脚注をご確認ください。2
ダッシュボードのインストールからアクセスに必要な設定までを一度にやってくれるコマンドがあります(version 1.19+)。
microk8s dashboard-proxy
ダッシュボードの起動後にターミナルに URL と トークンが表示されます。
指示の通りに https://192.168.64.2:10443
にアクセスするとトークンを入力できますのでコピー&ペーストしてサインインしてください。
※ Multipass 上の MicroK8s VM インスタンスの IPアドレスは環境によって異なりますので microk8s info --all
コマンドで確認してください
Checking if Dashboard is running.
Infer repository core for addon dashboard
Infer repository core for addon metrics-server
Waiting for Dashboard to come up.
Trying to get token from microk8s-dashboard-token
Waiting for secret token (attempt 0)
Dashboard will be available at https://192.168.64.2:10443
Use the following token to login:
<TOKEN>
Forwarding from 0.0.0.0:10443 -> 8443
Mutipass 上の Ubuntu に Docker Engine をインストールする
今回は Docker Desktop に頼らずに Docker 環境を作成します。
問題点は macOS には Docker CLI はインストールできますが Docker Engine はインストールできないことです。
そこで Mac に Docker CLI を、 Multipass 上の Ubuntu に Docker Engine をそれぞれインストールしてローカル環境内で連携させることで Docker 環境を構築します。
まずは Mac から Multipass 上の Ubuntu にログインします。
( microk8s install
で自動で作成されたものをそのまま使います)
multipass shell microk8s-vm
ログインできたら IP アドレスを確認してメモしておきます。
(おそらく 192.168.64.2
かと思います)
次に Ubuntu に Docker Engine をインストールしますが概ね公式の手順の通りです。
Install Docker Engine on Ubuntu
Docker CLI は Mac 側のものを使うため本来は不要ですが、念の為に Docker CLI もインストールしています(但し Docker Compose は除外しています)。
# GPG キーの設定やリポジトリの更新は公式通りのため省略
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin
さて、ここからが Mac + MicroK8s + Docker + Skaffold のための少しトリッキーな設定となります。
まず、 Docker Engine API を外部から実行できるようにします。
sudo systemctl edit docker
nano
エディタが起動するので以下の記述を貼り付けますが、その際 [PORT]
をウェルノウンポート以外の任意の番号に書き換えてください。
特に Docker Engine のデフォルトポート 2376
は避けておきましょう。
(セキュアにするために通信を TLS
で保護する方法もありますが少し複雑なのでご希望の方は脚注を実践してください3)
また、最初の何も指定されていない ExexStart=
も必要なので消さないようにしてください。
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:[PORT] --containerd=/run/containerd/containerd.sock
書き換えたら Docker を再起動します。
sudo systemctl restart docker
Mac に Docker CLI をインストールする
Mac には以下のコマンドで Docker CLI をインストールできます。
brew install docker
Docker Desktop を利用する場合はこの後さらに cask
オプションをつけて GUI アプリケーションをインストールしますがここでは行いません。
DOCKER_HOST
環境変数に先ほどメモした接続先の VM マシンの IP アドレスとポート番号を指定します。
何度も実行しなくても良いように .bashrc
や .zshrc
などのシェルスクリプトの設定ファイルに以下を追記してください。
export DOCKER_HOST=tcp://192.168.64.2:[PORT]
exec $SHELL -l
で設定を再読み込みできます。
docker images
コマンド等で正常に返ってくれば Docker のセットアップは完了です。
ちなみに、 Mac + Docker だけ使えれば良い場合は Docker Context
による ssh
構成で接続した方がセキュアなためオススメです。
ただ今回は Skaffold とも連携させる必要があり、Skaffold は Docker Context を認識できないため上記のような方法を取っています。
Mac に Skaffold をインストールする
最後に Skaffold をセットアップします。
快適な環境までもう一息ですので頑張りましょう。
以下のコマンドで Skaffold をインストールします。
brew install skaffold
インストールができたら MicroK8s の組み込みレジストリを登録します。
以下のコマンドで現在の Kubernetes コンテキスト(接続先クラスタ)で利用するレジストリを登録します。
skaffold config set insecure-registries localhost:32000
skaffold config set default-repo localhost:32000
今までの手順の通りであれば Skaffold に登録されるコンテキスト名は microk8s
となるはずです。
~/.skaffold/config
ファイルの中を見ると設定を確認できますが、異なる場合は kubectl config current-context
コマンドを実行して表示されるコンテキスト名を確認してください。
kubeContexts:
- kube-context: microk8s
default-repo: localhost:32000
insecure-registries:
- localhost:32000
最後に microk8s status
で registry
アドオンが enabled
であることを確認しておきましょう。
お疲れ様でした。これで環境は完成です!
Skaffold を構成してコンテナをローカルの MicroK8s にデプロイする
Dockerfile と Kubernetes のマニフェストファイルを作成し、 Skaffold で Docker Build と MicroK8s へのデプロイの一連の流れを構成します。
テストシナリオとして Postgres データベースを Pod で立ち上げてローカルから接続してみます。
サンプルソースも用意しておいたので git clone
してください。
ディレクトリ構成
.
└── skaffold-microk8s-example/
├── skaffold.yaml
├── kubernetes-manifests/
│ └── pod.yaml
└── src/
└── infra/
└── database/
├── Dockerfile
├── 0_create_database.sql
└── 1_insert_table.sql
Docker コンテナ設定ファイル
FROM postgres:14.4-alpine
COPY *.sql /docker-entrypoint-initdb.d/
DROP DATABASE IF EXISTS test_db;
CREATE DATABASE test_db;
¥c test_db;
CREATE TABLE example_tbl (
id serial PRIMARY KEY,
name TEXT
);
INSERT INTO example_tbl (name) VALUES ('aoyagi');
Skaffold 設定ファイル
apiVersion: skaffold/v4beta2
kind: Config
build:
tagPolicy:
sha256: {}
local:
push: true
useBuildkit: true
artifacts:
- image: example-db
context: src/infra/database
deploy:
kubeContext: microk8s
profiles:
- name: local
portForward:
- resourceType: pod
resourceName: my-example-pod
port: 5432
manifests:
rawYaml: [
"./kubernetes-manifests/pod.yaml"
]
Kubernetes マニフェストファイル
apiVersion: v1
kind: Pod
metadata:
name: my-example-pod
spec:
containers:
- name: my-example-pod
image: example-db
ports:
- containerPort: 5432
env:
- name: POSTGRES_USER
value: postgres
- name: POSTGRES_PASSWORD
value: postgres
- name: POSTGRES_DB
value: test_db
- name: TZ
value: Asia/Tokyo
全ての準備が整ったら Skaffold を実行してみましょう。
skaffold.yaml
のあるパスで以下のコマンドを実行します。
skaffold dev -p local
コンテナが MicroK8s へデプロイされたらお手元のDB接続ツールで接続してみましょう。
接続情報 | 設定値 |
---|---|
ホスト | localhost |
ポート | 5432 |
ユーザー名 | postgres |
パスワード | postgres |
データベース名 | test_db |
これだけでは Skaffold の良さが伝わりきらないので Skaffoldを実行したまま 1_insert_table.sql
にデータを追加してみましょう。
INSERT INTO example_tbl (name) VALUES ('aoyagi');
+ INSERT INTO example_tbl (name) VALUES ('your_name');
Skaffold が変更を自動で検知してコンテナを再作成し MicroK8s にデプロイします。
開発中は仕様が頻繁に変わりますが変更の都度環境を再作成してくれることで安全性が高まります。
環境をイミュータブルに作成することの良さはまたどこかでお伝えできればと思いますが、タイトルの目標は達成できましたので本記事はここまでとなります。
本投稿が皆様の快適なコンテナ開発ライフの一助になれば幸いです。
補足:macOS アップデート後に MicroK8s が正常に動作しなくなる問題の対処法
2023年11月5日更新
macOS 12 以降にアップグレード後に環境によっては MicroK8s の起動に必要な Multipass で VM マシンが Unknown
になってしまう問題が発生する場合があり、私も長らく悩まされていましたが以下の方法で解消することができました。どうやら OS アップデートで DHCP のリースログファイルが破損してしまうことが原因のようですので、同様の事象が発生した方は関連リソースを一度削除して PC を再起動してください。
# 破損した DHCP のリースログファイルを削除する
$ sudo rm /var/db/dhcpd_leases
# OS 再起動
現在は以下の環境で問題なく動作しています。
- macOS Sonoma 14.1.2
- MicroK8s 1.28.2 revision 6041
- multipass 1.12.2+mac
解決の糸口になった Issue です。
2023年12月3日追記
Mac の OS アップデート実施前に microk8s stop
で VM マシンを終了しておくと DHCP リースログが破損しないことを確認しました。
もし停止コマンドを実行せずアップデートしてしまい VM マシンが Unknown になってしまう場合は前述した方法で復旧してみてください。
2024年2月25日追記
Apple M3 Silicon で Multipass インスタンスが起動しない問題がバージョン 1.13.1 で解消されたようです。
以下のコマンドでアップグレードできます。
brew upgrade multipass
M1 ですが以下の環境で正常に動作することを確認済みです。
- macOS Sonoma 14.3.1
- MicroK8s v1.28.7 revision 6565
- multipass 1.13.1+mac