こんにちは!アンドパッド開発部のyokohamaです。
ITコンサル、WEBサービス会社を経て昨年5月にアンドパッドにジョインしました。
突然ですがアンドパッドでは社内で様々な勉強会を開催しています。
Vue, Flutter,マイクロサービスなどいろんなテーマの勉強会が開催されていて、所属に関わらず各々好きな勉強会に参加することができます。
自分はKubernetes/マイクロサービス勉強会と機械学習勉強会に参加しています。
勉強会に参加する目的は人それぞれだと思いますが、自分は怠け者なので学習をさぼらないようにペースメーカーとして勉強会に参加し続けています。
機械学習勉強会についてもいつか記事にできればと思っていますが、今日はKubernetes(k8s)に関しての記事なります。
k8sは入社前は全く触ったことがありませんでしたが、この勉強会のおかげで少しずつ触れるようになってきました。
ちなみにk8s/マイクロサービス勉強会ではこれまで以下のようなことをやってきました。
- Kubernetes完全ガイドの輪読
- Microservices Reference Architecture | NGINXの輪読
- Kubernetes公式サイトの輪読
- マイクロサービス関連記事の相互紹介
- マイクロサービス関連ツールのソースコードリーディング
これらの学習の中でお世話になったのがminikubeというツールです。
minikubeはローカルに軽量なk8s環境を立ち上げることができるツールです。
基本的に通常のk8sと同じことができるので手元でちょっと触ってみたいときに非常に便利です。
(当然EKSやGKEと違って無料なのでクラスターを落とし忘れて高額請求に涙することもありません!)
minikubeはk8sの公式サイトでも紹介されていてクラスターを立ち上げてpodをデプロイするところまでは比較的簡単に行えます。
Kubernetes、Docker辞めるってさ
ところで昨年末、Kubernetes 1.20からDockerが非推奨になるというニュースで界隈が少しざわついたのを覚えていますでしょうか。
内容としてはk8sの"ランタイム"としてのDockerが非推奨になるということで、DockerでビルドしたDockerイメージは継続してk8sにデプロイすることが出来るのでさほど慌てなくても大丈夫です。
(詳しくは公式が解説しているのでこちらをご参照ください。)
なのでDockerでビルドしたDockerイメージはminikubeでも使い続けられるようです。
が、この記事を読んだときにそういえばこれまで配布されているDockerイメージをminikube上にデプロイしたり、
ECRにpushした自作のDockerイメージをEKSで使うことはあっても意外と自作のDockerイメージをローカルのminikubeで動かしたことがないことに気づきました。
組み合わせ | 使用経験 |
---|---|
minikube×配布イメージ | あり |
パブリッククラウドマネージドk8s×配布イメージ | あり |
パブリッククラウドマネージドk8s×自作イメージ | あり |
minikube×自作イメージ | なし |
ちょっと気になったのでどうすればよいのか知らべてみました。
(なおminikubeにこだわらなければ素直にDocker on MacでKubernetesを立ち上げればDocker on Mac上の自作のDockerイメージを使うことができます。あくまでminikubeを使いたい人向けの記事になるのでご注意ください。)
自作のDockerイメージをローカルのminikubeで動かす方法
調べてみたところ実現方法として以下の3つがありそうでした
①1度Docker HubやECR等のパブリッククラウド上のイメージレジストリにイメージをpushし、そこからpullしてくる
②ローカルにイメージレジストリを立ててそこにイメージをpushし、そこからpullしてくる
③ローカルのminikube内のDockerデーモン内でイメージをビルドする
①はせっかくローカルでminikubeを立ち上げているのにわざわざイメージをリモートのレジストリにpushした後pullしてくることになるので、サクッと動作させたいときには向いていません。
残るは②と③ですが、③のほうが簡単そうだったので今回は③を試してみました。
(ちなみに②のやり方はこちらで紹介されています)
なお、今回はDocker for Macで検証しています。
そもそもDocker for Macの構成がどうなっているか
(docker公式より転載)
普段意識することはありませんが、Docker はクライアント・サーバ型のアーキテクチャです。
通常ローカルのMacでdocker build
するとDocker for Mac上のDockerデーモンにイメージが登録されます。
minikubeはこのDocker for Mac上のDockerデーモンにアクセスすることができないので、通常だとここにDockerイメージを登録してもminikube上のクラスターにpodをデプロイすることはできません。 一方でminikube内にもDockerデーモンが存在します。このDockerデーモンは配布されているイメージをpullしてきたものが登録されています。 なので、ローカルのDockerクライアントからminikube上のDockerデーモンにイメージを登録することが出来れば、minikubeでローカルビルドのDockerイメージを使うことが出来ます。 具体的にどうすればよいかというと、以下のコマンドを叩きます。
minikube docker-env
このコマンドによって、Docker用の環境変数が設定されローカルのDockerクライアントの向き先がminikube上のDockerデーモンに変わります。
(minikubeのコマンドなのでminikube側の向き先が変わりそうな気がしますが、Dockerクライアント側の向き先が変わることがポイントです)
自作イメージをminikube上で立ち上げてみる
せっかくなので実際にNuxt.jsアプリのDockerイメージを自作してminikube上で立ち上げてみたいと思います。
事前準備
nuxtアプリを作ります。設定が聞かれますが今回はただ動けば良いのでEnter連打で大丈夫です。
$ yarn create nuxt-app sample-app yarn create v1.22.4 [1/4] 🔍 Resolving packages... [2/4] 🚚 Fetching packages... [3/4] 🔗 Linking dependencies... [4/4] 🔨 Building fresh packages... success Installed "create-nuxt-app@3.5.2" with binaries: - create-nuxt-app create-nuxt-app v3.5.2 ✨ Generating Nuxt.js project in first-app ? Project name: first-app ? Programming language: JavaScript ? Package manager: Yarn ? UI framework: None ? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection) ? Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert selection) ? Testing framework: None ? Rendering mode: Universal (SSR / SSG) ? Deployment target: Server (Node.js hosting) ? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection) ? What is your GitHub username? ? Version control system: Git $ cd sample-app
次にnuxtアプリ用のDockerfileを用意します。
Dockerfile
FROM node:14.4.0-alpine WORKDIR /app # このようにpackage.jsonのCOPYとyarn installを分けておくと、 # 他のファイルを修正した際にyarn installをやり直さないのでイメージのビルドが早いです COPY package*.json ./ RUN yarn install COPY . . RUN yarn run build ENV HOST 0.0.0.0 EXPOSE 3000 CMD ["yarn", "run", "start"]
minikubeを立ち上げる
ついでにダッシュボードも立ち上げておきます。(minikubeは始めからダッシュボードが使える状態になっているのも嬉しいポイントです)
$ minikube start $ minikube dashboard
Dockerクライアントの向き先を変えてDockerイメージをビルドする
別のターミナルを立ち上げてDockerを操作してきます
# 向き先を確認(変更前) $ docker context ls NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR default * moby Current DOCKER_HOST based configuration unix:///var/run/docker.sock https://192.168.64.7:8443 (default) swarm # 向き先を変更 $ eval $(minikube -p minikube docker-env -u) # 向き先を確認(変更後。DOCKER ENDPOINTがunix:///var/run/docker.sockからtcp://192.168.64.7:2376に変わっている。) $ docker context list NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR default * moby Current DOCKER_HOST based configuration tcp://192.168.64.7:2376 https://192.168.64.7:8443 (default) swarm
コンテナイメージをビルドします
$ docker build -t sample-app:minikube .
ここでの注意点はDockerイメージにはlatest以外のタグを付けておく必要があるということです。
latestのままだとpodを立ち上げる際にErrImagePullになってしまいます。
マニフェストファイル(YAML)を準備します。
k8s/deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: sample-app labels: app: sample-app spec: replicas: 3 selector: matchLabels: app: sample-app template: metadata: labels: app: sample-app spec: containers: - name: sample-app image: sample-app:minikube ports: - containerPort: 3000
名前空間を作り、マニフェストファイルをapplyします。
# namespace作成 $ kubectl create namespace sample namespace/sample created # マニフェストファイルをapply $ kubectl apply -f k8s/deployment.yaml --namespace=sample deployment.apps/first-app created
ダッシュボードで確認してみます。
無事podが3つ立ち上がりました。
サービスの公開
# サービスの作成 $ kubectl expose deployment sample-app --type=NodePort --port=3000 --namespace=sample service/sample-app exposed # サービスのurlを取得 $ minikube service sample-app --url --namespace=sample
出力されたURLを開くとNuxt.jsの画面が表示されるはずです
もし途中で上手く動かなくなった場合は、一度minikube delete
でクラスターを削除してから再度minikube start
でクラスターを作成し直してください。
気軽にクラスターを再作成できるのもminikubeの良い点です。
片付け
# サービスの削除 $ kubectl delete service sample-app --namespace=sample # デプロイメントの削除 $ kubectl delete deployment sample-app --namespace=sample # namespaceの削除(これだけ少し時間がかかる) $ kubectl delete namespace sample # Dockerクライアントの向き先をminikubeからローカルのDockerデーモンに戻す $ eval $(minikube -p minikube docker-env -u) # minikubeを停止する $ minikube stop
最後に
k8s関連のツールは公式サイトが充実していてチュートリアルで必要となるイメージは基本的にすべて配布してくれています。
そのおかげで自作イメージをビルドしなくてもだいたいのツールを動かせてしまうのですが、やはり自作イメージを動かしてみると理解が進みます。
この記事がこれからk8sを始めてみたい方の一助になれば幸いです。
採用案内
アンドパッドはまさに今マイクロサービス化の真っ只中にいます。 一緒にマイクロサービスを作り上げていく仲間を絶賛大募集中なので興味ある方のご応募ぜひお待ちしております!