見出し画像

k8s 環境を M1/M2 Mac に作る

こんにちは、プラットフォームエンジニアをやっている t.g. です。
こないだ kubenetes をきちんと触る機会に恵まれました。そのときの備忘録的にローカル Mac に k8s 環境を用意する手順を残しておきます。

kubernetes 環境は「ほぼ」クラウド上での動作と同じことがローカル環境で出来てしまうのですごいですよね。




やりたいこと

  • kubectl コマンドを使って、ローカルにリソースを作りたい。

  • helm コマンドを使って、ローカルにリソースを作りたい。

  • できるだけ、AWS EKS や GCP GKE と同じ手順を踏めるようにしたい。


minikube vs MicroK8s

Mac でk8s を動かすのであれば、単一ノードを簡単にセットアップできるツールが必要になります。
よく使われているものは minikube と MicroK8s でしょうか。

minikube

  • Win, Lin, Mac 対応

  • ARM 対応

  • VM, コンテナ、ベアメタルに対応

  • シングルノードのみサポート

  • GPU サポート

MicroK8s

  • Win, Lin, Mac 対応

  • ARM 対応

  • VM, コンテナ、ベアメタルに対応

  • マルチノードサポート(HA)

  • GPU サポート

ほとんど僅差で違いはないのですが、ドキュメントの読みやすさで 今回は minikube を利用しました。


minikube を Mac で使う上での注意点

  • docker ではなく VM で動作させる
    MAC にインストール済みの docker-desktop を利用するほうが仮想マシンよりも速いです。
    ただ、`docker images` コマンドを動作させるためには、仮想マシンを利用する方が楽でした。
    そのため、今回は仮想マシンを MAC 上に作成し、仮想マシン上で k8s 環境を動かしています

  • hyperkit ではなく qemu でVMを動作
    minikube をVMで動かす場合、まず hyperkit の利用ドキュメントがヒットします。
    ARM 上で hyperkit は動かないため、今回はqemu でVM制御しています。



インストール

インストールは非常に簡単で、qemu -> socket_vmnet -> minikube の順番にbrew install していくだけです。
ここで minikube はデフォルトでは QEMU のnetworkに非対応なため、socket_vmnet をインストールします。

$ brew install qemu

$ brew install socket_vmnet
$ brew tap homebrew/services
$ HOMEBREW=$(which brew) && sudo ${HOMEBREW} services start socket_vmnet

$ brew install minikube


起動

初起動時は、driver, network を指定します。
また、VM にアサインするRAMもデフォルトは小さいため拡張して起動します。

さらに、MAC ターミナルで docker コマンドを打ち込んだときに、ローカルのdocker エンジンではなく、VM上のdocker を利用する指定を入れています。

# Qemu driver と socket_vmnet でMinikube 起動
# さらにRAM を増強
$ minikube start --driver qemu --network socket_vmnet --memory 8192

# 二度目以降は minikube start でOK

# minikube VM 上のdocker を使うように指定
$ eval $(minikube docker-env)

ちなみに、minikube VM 上の docker を使うように指定すると、接続先は以下のようになっていました。

$ docker context ls
NAME            DESCRIPTION                               DOCKER ENDPOINT                               ERROR
default *       Current DOCKER_HOST based configuration   tcp://192.168.105.4:2376                      
desktop-linux   Docker Desktop                            unix:///Users/user1/.docker/run/docker.sock   
Warning: DOCKER_HOST environment variable overrides the active context. To use a context, either set the global --context flag, or unset DOCKER_HOST environment variable.



テスト - helm で wordpress

kubectl でも良いのですがひとっ飛びで helm を使ってみます。
まずは、helm をインストールします。

$ brew install helm

次に、bitnami/wordpress をインストールします。
必要な repo を追加 -> install -> 確認しています。

# Add bitnami repo
$ helm repo add bitnami https://charts.bitnami.com/bitnami

# Add bitnami/wordpress chart
$ helm install test-wordpress bitnami/wordpress

# pods 確認
$ kubectl get pods
NAME                              READY   STATUS    RESTARTS   AGE
test-wordpress-765f46d879-j6mlp   1/1     Running   0          2m57s
test-wordpress-mariadb-0          1/1     Running   0          2m57s

# service 確認
$ kubectl get svc
NAME                     TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
kubernetes               ClusterIP      10.96.0.1       <none>        443/TCP                      26d
test-wordpress           LoadBalancer   10.102.88.72    <pending>     80:30650/TCP,443:32573/TCP   2m30s
test-wordpress-mariadb   ClusterIP      10.108.201.85   <none>        3306/TCP                     2m30s


ローカル MAC からブラウザで接続してみます。
minikube コマンドを利用し、出てきたURL にブラウザでアクセスが可能なことを確認します。

# LB への External-IP を外に見せる
$ minikube service test-wordpress --url

http://192.168.105.4:30650
http://192.168.105.4:32573


minikube を使うのは(EKSにはないので) ちょっと・・という場合、こちら。
kubectl port-forward を使ってポートをフォワードさせます
こちらも同様にブラウザでテスト接続ができました。

$ kubectl port-forward services/test-wordpress 33380:80

Forwarding from 127.0.0.1:33380 -> 8080
Forwarding from [::1]:33380 -> 8080
Handling connection for 33380
Handling connection for 33380


最後に bitnami/wordpress を削除しておきます。

$ helm delete test-wordpress
release "test-wordpress" uninstalled


minikube 停止


また、minikube VMも停止しておきます。
VM に貴重なRAMを取られ続けるのは大変ですので。

$ minikube stop

✋  Stopping node "minikube"  ...
🛑  1 node stopped.

$ minikube status

minikube
type: Control Plane
host: Stopped
kubelet: Stopped
apiserver: Stopped
kubeconfig: Stopped


どうしてもクラウド版と異なるところ

一方で、クラウドリソースと連携しているところはどうしても読み替えが必要になります。
具体的には ingress (AWSだと ALB やNLBを使う部分)や storage class (AWS だと ECS-CSI driverを使う部分) 部分になります。

ここらあたりは「しゃあない」の精神で読み替えていくことにしました。
ファンシーなやり方を見つけたらまた共有するということで。

おまけ(もう必須) - autocompletion

なくても動きますが生産性バク上がりなツールとして、autocompletionはもう必須でした。
Linux command の autocompletion はサブコマンドを [TAB] キーで補完してくれるので、うろ覚えになりがちなものを簡単に補完してくれます。

$ kubectl  <-- ここで TABキーを押すと、サブコマンドを出してくれる
 -- completions --
annotate       -- Update the annotations on a resource
api-resources  -- Print the supported API resources on the server
api-versions   -- Print the supported API versions on the server, in the form of "group/version"
apply          -- Apply a configuration to a resource by file name or stdin
   (snip)

さらにサブコマンドのような静的なものに限らず、pod名やservice名なども動的に補完してくれます。
同様に、pod 名など途中まで記述したものも補完してくれるので大助かりです。

$ kubectl describe -n kube-system pod <-- ここで TAB キーを押すと、起動中の pod を表示してくれる
 -- completions --
coredns-6f6b679f8f-xcfd6          kube-apiserver-minikube           kube-proxy-f7wcx                  storage-provisioner             
etcd-minikube                     kube-controller-manager-minikube  kube-scheduler-minikube 


自分は以下のコマンドを ~/.zshrc ファイルに入れることで、minikube, kubectl, helm の補完を有効にしています。
Zshell 以外の場合は本家ドキュメントを参考にしてください。

# kubectl zsh autocompletion 1/2
autoload -Uz compinit
compinit

# minikube completion
source <(minikube completion zsh)
# kubectl zsh autocompletion 2/2
source <(kubectl completion zsh)
# helm autocompletion
source <(helm completion zsh)


まとめ

今回は、ローカル Mac (M1/M2) で k8s 環境を構築し、kubectl や helm が利用できるようにしました。

ローカル環境ならではの気軽さで試せると思います。
今回記事には含めませんでしたが、Istio のようなサービスメッシュもこの環境で動作します。
意外に深い使い方にも対応していますので、また面白い使い方が出ましたら共有していきたいと思います。