はじめに
このチュートリアルでは、docker composeで構築されたサンプルのアプリケーションをKubernetes上にデプロイします。DockerとKubernetesを一通り勉強したが、Kubernetes上にどのようにアプリケーションをデプロイするか分からない方におススメです。
目的
Kubernetes初級者やDevOps技術の学習者が、dockerとの違いを理解し、Kubernetes上にアプリケーションをデプロイする練習となることを目的としています。また、Kubernetes上でのコンテナイメージやボリューム、ネットワーク構成などを実際にデプロイしながら学びます。
対象:
- LinuxやDocker、Kubernetesについての基礎知識がある
- Dockerでアプリケーションのビルドをしたことがある
- Webアプリケーションの基礎知識
- Avinton Academy Docker compose 演習を実施済み
目標
こちらのdocker composeで構築されたサンプルアプリケーションをKubernetes上にデプロイします。アプリケーションの仕組みを理解するためにcompose.yamlをよく読み、一通りREADME通りにアプリケーションを動かしてみてください。
最終的な完成品として、以下の図のようにKubernetes上にデプロイします。
事前準備
必要なもの:
- インターネット接続のあるLinux環境 (VM可)
- 4GB memory + 4 CPU以上推奨
- Dockerコマンドを利用できるビルド環境
1. ローカル環境にKubernetes環境を構築
以下のチュートリアルでは、簡単にセットアップできて便利なminikubeを使用します。minikubeはdockerコンテナとしてKubernetesクラスターをローカル環境上に構築できます。Kubernetesのバージョンはv1.25.2を使用します。任意のKubernetesクラスター、バージョンでも構いません。nodeがReadyステータスになっていることを確認してください。
1 |
$ minikube start --nodes 2 |
1 2 3 |
$ kubectl get node NAME STATUS ROLES AGE VERSION minikube Ready control-plane 4m30s v1.25.2 |
2. PV/PVCを利用可能にする
任意のKubernetes Storage(CSI)をインストールします。minikubeの場合はデフォルトで準備されている以下のStorage classを使用します。
1 2 3 |
$ kubectl get storageclass NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE standard (default) k8s.io/minikube-hostpath Delete Immediate false 5m33s |
3. Container registryの準備
デプロイしたいアプリケーションのコンテナイメージを、Kubernetes側から利用できるようにする必要があります。minikubeの場合はこちらのリンクを参考にしてregistryのアドオンを有効化してください。
必要に応じてホスト側とminikube側の両方でinsecure registryの設定を行ってください。minikubeではクラスターの構築時にinsecure registryのアドレスを指定する必要があります。
1 2 |
$ minikube start --nodes 2 --insecure-registry "192.168.49.0/24" $ minikube addons enable registry |
クラウド上のレジストリやDockerHubを利用している方はそちらでも構いません。Kubernetesクラスター上でイメージをpullできることを確認してください。
タスク – サンプルアプリケーションのデプロイ
0. 準備
kubectl
コマンドを正しく使用できることを確認してください。今回は、compose-to-kube
というnamespaceを作成し、その中で作業します。
1 |
kubectl create namespace compose-to-kube |
またデプロイ対象となるアプリケーションの含まれるレポジトリをクローンします。nginx-flask-mysql
ディレクトリに移動します。
1 2 |
git clone https://github.com/docker/awesome-compose.git cd nginx-flask-mysql |
1. DBのデプロイ
サンプルではMariaDBを使用しています。MariaDBはMySQLから派生したオープンソースのデータベースです。
DBなどのデータの状態を保持する”ステートフル”なアプリケーションをデプロイする場合は、Statefulsetが適しています。こちらのブログを参考にMariaDBをデプロイしてください。
YAMLファイルはそれぞれMariaDBのGitHubレポジトリから利用できます。YAMLファイルをダウンロード後、それぞれ以下の条件を満たすように設定してください。
- mariadb-sts.yaml:
- Serviceのnameは
db
に変更してください - MariaDBのイメージには
mariadb:10-focal
を使用してください datadir
Volumeには100MBを割り当ててください- Volumeのstorageclassは適宜変更してください
- Replicaの数は1に変更してください
- 2つの環境変数を設定してください
MARIADB_ROOT_PASSWORD
: Secretmariadb-secret
からmariadb-root-password
の値を取得MARIADB_DATABASE
: “example”を指定してください
- Serviceのnameは
- mariadb-secret.yaml:
mariadb-root-password
の値は、こちらのファイルpassword.txtにある文字列db-78n9n
に変更してください
最終的に次のコマンドでDBの一覧が取得できれば完了です。
1 2 3 4 5 6 7 8 9 10 |
$ kubectl exec -it mariadb-sts-0 -n compose-to-kube -- mariadb -uroot -pdb-78n9n -e "SHOW DATABASES;" +--------------------+ | Database | +--------------------+ | example | | information_schema | | mysql | | performance_schema | | sys | +--------------------+ |
2. Backend
2.1 コンテナイメージのビルド&プッシュ
backend
ディレクトリに移動してコンテナイメージをビルドします。(注: buildkitを有効化する必要があります)
1 2 3 |
$ docker images backend REPOSITORY TAG IMAGE ID CREATED SIZE backend latest 316613d9976e 3 hours ago 293MB |
imageをkubernetesクラスター内のレジストリにpushします。 Minikubeの場合はこちらを参考にしてください。
2.1 Deployment YAMLファイルの作成
backendはDeploymentとして作成します。Deploymentでは作成したいレプリカの数を指定したり、バージョンのロールアウトやスケーリングが容易になります。
以下の条件を満たすように設定してください。
- Secret
mariadb-secret
のmariadb-root-password
の値を/run/secrets/db-password
のパスにマウントしてください- ヒント: subPathを使用することで単一のファイルとしてマウントできます
- Replicaの数は1に指定してください
- TCP port 8000でリッスンするようにしてください
2.2 Service YAMLファイルの作成
Serviceを作成して、他のコンテナからbackend
としてアクセスできるようにします。
以下の条件を満たすように設定してください。
backend
という名前で作成してください- TCP port 8000でリッスンするようにしてください
- selectorを正しく指定して、2.1で作成したdeploymentのPodを指定してください
3. Nginx Proxy
最後に、Nginx Proxy(フロントエンド)をたててクラスター外部からbackendにアクセスできるようにします。
3.1 ConfigMapを作成
サンプルのレポジトリから、Nginxのconfファイルを取得します。そのファイルを使用してConfigMapを作成してください。
3.2 Deployment YAMLファイルの作成
NginxはDeploymentとして作成します。以下の条件を満たすように設定してください。
- imageは
nginx:1.13-alpine
を使用してください - TCP port 80でリッスンするようにしてください
- 3.1で作成したConfigMapを
/etc/nginx/conf.d/default.conf
としてマウントしてください- ヒント: subPathを使用することで単一のファイルとしてマウントできます
- Replicaの数は1に指定してください
3.3 Service YAMLファイルの作成
以下の条件を満たすように設定してください。
proxy
という名前で作成してください- TCP port 80でリッスンするようにしてください
- selectorを正しく指定して、3.2で作成したdeploymentのPodを接続してください
NodePort
タイプとして作成してください
検証
デプロイしたアプリケーションを検証します。次のコマンドで作成したすべてのリソースを確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
$ kubectl get po,deployment,sts,svc,secrets,cm -n compose-to-kube NAME READY STATUS RESTARTS AGE pod/backend-deployment-6ccddcbc8d-hc69j 1/1 Running 0 50m pod/mariadb-sts-0 1/1 Running 0 42m pod/nginx-deployment-6dc94b544-s28cn 1/1 Running 0 8m40s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/backend-deployment 1/1 1 1 63m deployment.apps/nginx-deployment 1/1 1 1 11m NAME READY AGE statefulset.apps/mariadb-sts 1/1 42m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/backend ClusterIP 10.99.58.242 <none> 8000/TCP 26m service/db ClusterIP None <none> 3306/TCP 42m service/proxy NodePort 10.111.63.234 <none> 80:32755/TCP 2m1s NAME TYPE DATA AGE secret/mariadb-secret Opaque 1 91m NAME DATA AGE configmap/kube-root-ca.crt 1 92m configmap/nginx-conf 1 15m |
次のコマンドでproxyサービスのNodePortを確認します。以下の例では32755
です。環境によって異なります。
1 2 3 |
$ kubectl get svc -n compose-to-kube proxy NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE proxy NodePort 10.111.63.234 <none> 80:32755/TCP 3m8s |
次にKubernetesのnodeのIPアドレスを確認します。以下の例では192.168.49.2
です。環境によって異なります。
1 2 3 |
$ kubectl get node -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME minikube Ready control-plane 96m v1.25.2 192.168.49.2 <none> Ubuntu 20.04.5 LTS 5.4.0-128-generic docker://20.10.18 |
次のような出力が返ってきたら成功です。可能な方はブラウザからもアクセスしてみてください。
1 2 |
$ curl 192.168.49.2:32755 <div> Hello Blog post #1</div><div> Hello Blog post #2</div><div> Hello Blog post #3</div><div> Hello Blog post #4</div> |
ログを確認します。nginx-deploymentとbackendの両方のコンテナにアクセスしたログが確認できました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$ kubectl logs -n compose-to-kube nginx-deployment-6dc94b544-xh9tj 172.17.0.1 - - [20/Oct/2022:07:52:56 +0000] "GET / HTTP/1.1" 200 132 "-" "curl/7.68.0" "-" $ $ $ kubectl logs -n compose-to-kube backend-deployment-6ccddcbc8d-w48dk * Serving Flask app 'hello.py' (lazy loading) * Environment: development * Debug mode: on WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on all addresses (0.0.0.0) * Running on http://127.0.0.1:8000 * Running on http://172.17.0.7:8000 Press CTRL+C to quit * Restarting with stat * Debugger is active! * Debugger PIN: 625-488-550 172.17.0.1 - - [20/Oct/2022 07:52:56] "GET / HTTP/1.0" 200 - |
課題
- backend, proxy, dbのそれぞれのReplicaの数を,(1)
kubectl scale
、(2)kubectl apply
を利用して3つにスケールしてください - Nginx proxyはどのような場合に便利ですか
- ConfigMap, Secretはどのような場合に便利ですか
- Kubernetesでは実現可能で、docker composeでは実現不可能な特徴や機能はなにがありますか
チャレンジ課題
backendのhello.py
を編集して、DBのhost, port, database, userなどの値を環境変数から取得できるように更新してください。その後、新しくConfigMap backend-conf
を作成し、backendのdeploymentからそれぞれの値を環境変数として取得できるようにしてください。
まとめ
このタスクではdocker composeで記述されたアプリケーションをKubernetes上デプロイしました。まず、minikubeを使用したローカルのKubernetes環境の準備を行いました。Deployment、StatefulSet、Service、ConfigMap、SecretのYAMLを定義しました。その後、アプリケーションをデプロイし、NodePort経由でbackendのサービスにアクセスできることを確認しました。
Kubernetes上にデプロイしたことで、Kubernetesが定義された理想的な状態を維持します。replica数の変更やConfigの変更をkubectlなどを使用して、Kubernetes API経由で操作することができます。これにより、管理の自動化やCI/CDパイプラインの実装、モニタリングシステムとの統合など、より高度な操作を実現できます。また、nodeの数が2個以上に増えた場合などのスケーラビリティ、冗長性、負荷分散なども可能になります。