LoginSignup
6
4

Skaffold + MicroK8s で快適なコンテナ開発環境を構築する(Mac編)

Last updated at Posted at 2022-09-15

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 ディストリビューションです。
他の候補としては MinikubeK3s 等が挙げられますが、 MicroK8s はエンタープライズサポートや複数ノード対応など本番環境としての運用も可能で、開発や本番で有用なアドオンも充実しているのが特徴です。
詳しくは本家の比較表を参照してください。

MicroK8s vs K3s vs minikube

ちなみに私は以前は 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

image.png

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 コマンドを実行して表示されるコンテキスト名を確認してください。

~/.skaffold/config
kubeContexts:
- kube-context: microk8s
  default-repo: localhost:32000
  insecure-registries:
  - localhost:32000

最後に microk8s statusregistry アドオンが 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 コンテナ設定ファイル

Dockerfile
FROM postgres:14.4-alpine

COPY *.sql /docker-entrypoint-initdb.d/
0_create_database.sql
DROP DATABASE IF EXISTS test_db;
CREATE DATABASE test_db;
1_insert_table.sql
¥c test_db;

CREATE TABLE example_tbl (
  id serial PRIMARY KEY,
  name TEXT
);

INSERT INTO example_tbl (name) VALUES ('aoyagi');

Skaffold 設定ファイル

skaffold.yaml
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 マニフェストファイル

pod.yaml
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 にデータを追加してみましょう。

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
  1. Docker Desktop for Apple silicon

  2. Addon:dashboard - MicroK8s

  3. Use TLS (HTTPS) to protect the Docker daemon socket - docs.docker.com

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4