本稿はJCB Advent Calendar 2022の12/8の記事です。
JCB デジタルソリューション開発部 の四方と申します。 本記事では、OSS ライセンスのみでDocker/Kubernets 環境を構築した取り組みについてご紹介します。
やりたいこと
以下を満たすことを目標としました。
- Dockerおよび簡易的なKubernetes クラスタが構築可能であること
- Intel/Apple silicon のどちらでも動作可能であること
- インターネット上で検索し、情報が豊富な製品であること
上記の要件を満たすツールとして、Multipass
, Lima
が候補にあがりました。
はじめにMultipass の導入を試みましたが、私の開発環境では相性が悪く利用を断念することになり、Lima の導入を進めることとなりました。
Lima 概要
Limaは公式リポジトリに記載の通り、Linux の仮想環境を構築します。 機能としてファイル共有、ポートフォワード、containerd(他のコンテナランタイムも利用可)を備えています。
Lima 導入
Lima のGitHub リポジトリを参照し、実際に環境を構築していきます。
コマンドをインストール
Homebrew が利用可能です。
brew install lima
インスタンスの構築
以下のコマンドで環境を構築できます。
limactl start <template://TEMPLATE>
既存のテンプレートが複数提供されており、用途に応じて選択できます。 今回は、docker を使用できることが要件となるためdocker のテンプレートを使用しました。
テンプレートはyaml ファイルでも配布されているので、修正したyaml を利用する場合は以下のコマンドで実行します。 *1https://github.com/lima-vm/lima/blob/master/examples/docker.yaml
limactl start /path/to/docker.yaml
Lima テンプレート修正
デフォルトのテンプレートのままでは弊社の環境では動作しなかったため、テンプレートを修正しました。
中間証明書の設定
proxy の環境等を構築している場合、証明書の設定をする必要があります。
caCerts: # If set to `true`, this will remove all the default trusted CA certificates that # are normally shipped with the OS. # 🟢 Builtin default: false removeDefaults: null # A list of trusted CA certificate files. # The files will be read and passed to cloud-init. files: # - examples/hello.crt # A list of trusted CA certificates. These are directly passed to cloud-init. certs: # - | # -----BEGIN CERTIFICATE----- # YOUR-ORGS-TRUSTED-CA-CERT-HERE # -----END CERTIFICATE----- # - | # -----BEGIN CERTIFICATE----- # YOUR-ORGS-TRUSTED-CA-CERT-HERE # -----END CERTIFICATE-----
この記述を追記することでproxy 環境下でもLima で構築したvm が外部サイトと通信可能になります。
カーネルパラメータの調整
Docker 利用時に下記のメッセージが出るため、こちらもテンプレートを修正し対応しました。
# 下記メッセージが出たため、yaml にカーネルパラメータの調整を追記 max virtual memory areas vm.max_map_count [65530] is too low
provision: - mode: system script: | #!/bin/bash # kernel parameter tuning set -eux -o pipefail sysctl -w vm.max_map_count=262144 sysctl -p
Docker 動作確認
これまでの設定をしていれば、limactl start コマンドでインスタンスが正常に起動します。 実際にmacOS 上からdocker コマンドを叩いてみて動作を確認します。
$ limactl start docker INFO[0000] Using the existing instance "docker" INFO[0001] SSH Local Port: 49591 INFO[0001] [hostagent] Waiting for the essential requirement 1 of 5: "ssh" INFO[0021] [hostagent] The essential requirement 1 of 5 is satisfied : 中略 INFO[0058] READY. Run `limactl shell docker` to open the shell. INFO[0058] Message from the instance "docker": To run `docker` on the host (assumes docker-cli is installed), run the following: ------ docker context create lima-docker --docker "host=***" docker context use lima-docker docker run hello-world ------ # docker コマンドの動作確認 $ docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 2db29710123e: Pull complete Digest: sha256:faa03e786c97f07ef34423fccceeec2398ec8a5759259f94d99078f264e9d7af Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/
問題なくdocker を使用できていることが確認できました。
minikube 構築
ここまででDocker が利用できるようになりましたので、続いてKubernetes クラスタを構築します。 クラスタ構築にはminikube を利用しました。
macOS 上でminikube コマンドを用いる場合、MacBook のCPUアーキテクチャとLimaインスタンスのCPUアーキテクチャが一致している必要があります。
今回はアーキテクチャをあえて一致させないユースケースを考慮して対策を講じました。 そこでminikube コマンドの実行をmacOS 上ではなく、Lima インスタンス側に変更しました。
テンプレートを修正し、Lima インスタンスのCPU アーキテクチャに応じたminikube の導入を自動化しました。
- mode: user script: | #!/bin/bash # minikube install BASEURL=https://storage.googleapis.com/minikube/releases/latest ARCH=$(arch) mkdir -p ~/tmp case "$ARCH" in "x86_64" | "i386" ) curl -Lo ~/tmp/minikube $BASEURL/minikube-linux-amd64;; "aarch64" ) curl -Lo ~/tmp/minikube $BASEURL/minikube-linux-arm64;; * ) echo "default";; esac install ~/tmp/minikube ~/bin/minikube
上記のように記載することで、インスタンスを構築するユーザがCPUのアーキテクチャを意識しなくてもminikube コマンドが利用できるようになりました。
中間証明書の設定 with minikube
Lima インスタンス同様、minikube にも証明書の設定をする必要があります。 以下の証明書の設定をテンプレートに追記しました。
- mode: user script: | #!/bin/bash # certs ディレクトリがなければ作成 mkdir -p ~/.minikube/certs cat <<EOF> ~/.minikube/certs/nscert.pem -----BEGIN CERTIFICATE----- # 証明書 -----END CERTIFICATE----- EOF
ホームディレクトリ配下に.minikube/certs
ディレクトリを作成し、証明書を配置しました。
minikube の起動コマンドに--embed-certs
を追加することで証明書をminikube が認識してくれるようになります。
minikube 構築の自動化
カスタムしたテンプレートを使用するメンバーに、極力コマンドを実行させなくても良いようにminikube の起動は自動化させることにしました。 以下の設定をテンプレートに追記しました。
- mode: user script: | #!/bin/bash # minikube の起動を自動化するためsystemd unit を作成 cat <<EOF> ~/.config/systemd/user/minikube.service [Unit] Description=minikube Requires=docker.service After=docker.service [Service] Type=oneshot RemainAfterExit=yes WorkingDirectory=~ ExecStart=/usr/local/bin/minikube start --wait-timeout=15m0s --embed-certs ExecStop=/usr/local/bin/minikube stop Restart=on-failure [Install] WantedBy=default.target EOF systemctl --user enable minikube.service systemctl --user start minikube.service
minikube をsystemd 管理で起動させることによって、Lima インスタンス起動時に自動でKubernetes クラスタが構築されるようになりました。
動作確認
ここまでの設定を反映したdocker.yaml を使用して、Lima インスタンスを起動しKubernetes クラスタ上にpod を動かしてみます。
$ limactl list NAME STATUS SSH ARCH CPUS MEMORY DISK DIR docker Running 127.0.0.1:49591 x86_64 4 8GiB 64GiB /Users/shikata/.lima/docker $ alias lsd='limactl shell docker' $ alias lsdmk='limactl shell docker minikube kubectl --' # minikube の動作状況を確認 $ lsd minikube status minikube type: Control Plane host: Running kubelet: Running apiserver: Running kubeconfig: Configured # 試しにnginx のpod を起動 $ lsdmk run nginx --image=nginx pod/nginx created $ lsdmk get pods NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 9s # コンテナ内に入り、curl でレスポンスが帰ることを確認 $ lsdmk exec -it nginx -- bash root@nginx:/# curl localhost <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> root@nginx:/# exit exit
問題なくKubernetes クラスタとして動作していることが確認できました。
まとめ
OSS ライセンスのみでDocker/Kubernetes 構築を実施いたしました。 テンプレートを修正するだけで対応が可能なLima の柔軟性を感じることが出来ました。
最後になりますが、JCBでは我々と一緒に働きたいという人材を募集しています。 詳しい募集要項等については採用ページをご覧下さい。
本文および図表中では、「™」、「®」を明記しておりません。 Google Cloud, GCPならびにすべてのGoogleの商標およびロゴはGoogle LLCの商標または登録商標です。 記載されているロゴ、システム名、製品名は各社及び商標権者の登録商標あるいは商標です。
*1:テンプレート