kubernetes
docker-compose
minikube
kompose

Docker ComposeからMinikube + Komposeに移行してみよう

More than 1 year has passed since last update.


はじめに

Kubernetesがコンテナオーケストレーションツールのデファクトになったといわれて久しい1ですが、今年のAWS re:InventではAmazon EKS2の発表もあり、これからKubernetesに取り組もうという人もいるのではないかと思います。

かくいう私もその一人で、最近この辺りの技術に入門して色々と試していたので、今日はそのまとめを記します。


用語解説


Minikube

Kubernetesクラスタをローカルマシン上で構築できるようにしてくれるものです。

Kubernetesクラスタを自前で一から構築するのは非常に大変そう(やったことはありません)なのですが、これを使うと簡単に試すことができます。

CIなどでも活用できそうです。


Kompose

Docker Composeの設定ファイルをKubernetes向けに変換するツールです。


また、変換によって生成されたリソース群を、docker-composeライクなインタフェースで制御することもできます。


この記事で行うこと


  1. PostgreSQLをバックエンドとするシンプルなRailsのWebアプリケーションを用意します。

  2. このWebアプリケーションをDocker化して、Docker Composeを使った開発環境を構築します。


  3. Komposeを使ってDocker Composeの設定をKubernetes向けに変換し、Minikube上で動かします。

以降では、DockerやDocker Composeについては、ある程度知っているという前提で書きます。

使用するソースコードや設定ファイルは https://github.com/progrhyme/compose-to-minikube にまとめましたので、適宜ご参照ください。


必要なもの

ツール
筆者環境のバージョン
公式インストールガイド

Docker
17.05.0-ce
https://docs.docker.com/engine/installation/

Docker Compose
1.17.0
https://docs.docker.com/compose/install/

kubectl
v1.8
https://kubernetes.io/docs/tasks/tools/install-kubectl/

Minikube
v0.24.1
https://github.com/kubernetes/minikube#installation

Kompose
1.5.0
http://kompose.io/installation/

全てのツールがWindows, Mac OS, Linuxの各プラットフォームに対応しているので、いずれかの環境であれば動かせると思います。

※ここでは、個々の細かいインストール手順は省略します。

筆者はUbuntu 16.04で作業しました。


Railsアプリケーションの作成

PostgreSQLを使うアプリケーションを次のように作成します。

rails new my_app --database=postgresql

後の作業でDB接続先を環境変数から渡すようにするので、 config/database.yml を次のように編集しておきます。


config/database.yml

default: &default

adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
url: <%= ENV['DATABASE_URL'] %>

development:
<<: *default

test:
<<: *default

production:
<<: *default


動作確認をするため、適当なModelをControllerと共に生成しておきます。

bundle exec rails g scaffold person name:string age:integer

これで、 /people/people/new などのエンドポイントによって、DBのCRUDが試せるようになりました。


アプリケーションをDocker化する

上のRailsアプリケーションをDockerで動かすため、下のようなDockerfileを書きました。


Dockerfile

FROM ruby:2.4.2

RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs

RUN mkdir /app
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . ./

CMD bundle exec rails server -b 0.0.0.0 -p ${PORT:-3000}


下のコマンドで、Dockerイメージのビルドを試すことができます。

docker build -t progrhyme/compose2minikube:v1 .


Docker Composeによる開発環境構築

上で用意したRailsアプリケーションをDBと連携して動作させるため、Docker Composeによってローカルマシン上でクラスタを構築します。

下のような設定ファイルを docker-compose.yml として作成しました。


docker-compose.yml

version: "3"

services:
db:
image: postgres:9.5
environment:
- POSTGRES_USER=${MY_APP_DATABASE_USER}
- POSTGRES_PASSWORD=${MY_APP_DATABASE_PASSWORD}
- POSTGRES_DB=${MY_APP_DATABASE_NAME}
rails:
build:
context: .
ports:
- "3000:${PORT:-3000}"
environment:
- DATABASE_URL=postgres://${MY_APP_DATABASE_USER}:${MY_APP_DATABASE_PASSWORD}@db:5432/${MY_APP_DATABASE_NAME}
depends_on:
- db


DockerHubで提供されているPostgreSQLのイメージでは、上のような環境変数によって初期データベースユーザ名、パスワード、データベース名を設定することができます。

${MY_APP_DATABASE_USER}, ... といった変数は下のように環境変数で設定しました。

export MY_APP_DATABASE_USER=myapp

export MY_APP_DATABASE_PASSWORD=password
export MY_APP_DATABASE_NAME=my_app_development

docker-compose.ymlでは、上の設定のように環境変数を直接YAMLに記述して、比較的シンプルな設定ファイルを作ることができます。

また、上の設定中の DATABASE_URL で記しているように、 rails のコンテナ内からはservice db に対してホスト名 db でアクセスすることができます。


動作確認

上で構築したクラスタを動かしてみます。

下のコマンドでdbとrailsのコンテナを起動できます。

docker-compose up

http://0.0.0.0:3000 でRailsサーバが稼働しますが、DBマイグレーションを実施していないため、アクセスするとエラーになってしまいます。

マイグレーションは以下のように実行できます:

docker-compose exec rails rake db:migrate

ここで rails はdocker-composeから見たserviceの識別名です。

再度アクセスすると、Railsの画面を確認できるでしょう。

http://0.0.0.0:3000/people にアクセスすると、scaffoldで生成したRails開発者にお馴染みのコントローラ画面が表示されます。

image.png


KomposeによってMinikube上でアプリケーションを動かす

以下では、先の手順で作成したDocker ComposeのクラスタをMinikube上で動かしていきます。


下準備


Minikubeを立ち上げておく

まず、予めMinikubeを起動しておきましょう。

※必要なツール類のインストールは済んでいるものとします。

minikube start

初回はコンテナイメージのpullなどでかなり時間が掛かると思います。

無事に起動したら、下のようなコマンドで状態を確認することができます。

minikube status

minikube dashboard # ブラウザでダッシュボードを開く

minikube startによって、kubectlのコンテキストにMinikubeがセットされ、kubectlコマンドでクラスタに対する操作が可能になります。


ローカルでDockerレジストリを動かす

Kubernetesにはコンテナイメージをビルドする機能はありません。

従って、サンプルアプリケーションのカスタムイメージをどこかのレジストリにpushし、そこからpullするように設定する必要があります。

サンプルなのでDockerHubに置いても良いのですが、ここでは公式のDocker Registryイメージを利用して、ローカルでレジストリサーバを動かすことにしました。

以下のように、Dockerで簡単にレジストリサーバを動かすことができます:

docker run -d -p 5000:5000 \

-v ~/.dockerregistry:/var/lib/registry \
--restart always \
--name registry \
registry:2

ここでは、 ローカルマシンの ~/.dockerregistry ディレクトリを永続化用のボリュームとしてマウントしています。

このレジストリに、上でビルドしたDockerイメージをpushしておきます。

docker tag progrhyme/compose2minikube:v1 localhost:5000/progrhyme/compose2minikube:v1

docker push localhost:5000/progrhyme/compose2minikube:v1


Docker Compose設定を変換する

上の手順で作った docker-compose.ymlkompose convert で変換してみます。

$ cd <docker-compose.ymlがあるディレクトリ>

$ kompose convert
INFO Kubernetes file "db-service.yaml" created
INFO Kubernetes file "rails-service.yaml" created
INFO Kubernetes file "db-deployment.yaml" created
INFO Kubernetes file "rails-deployment.yaml" created

上手く設定を変換することができました。

ただし、 kompose up してローカルマシンからサービスにアクセス可能にするために、2点ほど修正する必要がありました。



  1. docker-compose.yml で、コンテナイメージとしてローカルレジストリにpushしたイメージを指定するようにしておく


  2. rails-service.yaml で、Serviceのtypeを変更

それぞれの差分としては以下のようになります:

# docker-compose.yml

:
- POSTGRES_DB=${MY_APP_DATABASE_NAME}
rails:
- build:
- context: .
+ image: localhost:5000/progrhyme/compose2minikube:v1
ports:
- "3000:${PORT:-3000}"
environment:
:

# rails-service.yaml
:
targetPort: 3000
selector:
io.kompose.service: rails
+ type: NodePort
status:
loadBalancer: {}

2について、KubernetesのServiceのtypeはデフォルトではClusterIPとなっており、クラスタ内からしかアクセスできません。

クラスタ外からアクセス可能にするには、NodePortLoadBalancerにする必要があります。


動作確認

kompose convertで生成した設定ファイル内のリソースには io.kompose.service といったキーのlabelやselectorが付加されています。

Komposeはこれらのlabel等を使ってリソースを管理しているのでしょう。

kompose upすると、リソース群をKubernetesクラスタ上に作成します。

$ kompose up

INFO We are going to create Kubernetes Deployments, Services and PersistentVolumeClaims for your Dockerized application. If you need differe
nt kind of resources, use the 'kompose convert' and 'kubectl create -f' commands instead.

INFO Deploying application in "default" namespace
INFO Successfully created Service: db
INFO Successfully created Service: rails
INFO Successfully created Deployment: db
INFO Successfully created Deployment: rails

Your application has been deployed to Kubernetes. You can run 'kubectl get deployment,svc,pods,pvc' for details.

rails, dbのDeploymentとServiceが作成されました。

kubectlコマンドでPodの状態を確認してみましょう。

$ kubectl get pods

NAME READY STATUS RESTARTS AGE
db-65644f9968-4zx5w 1/1 Running 0 5s
rails-6896549fc6-45mmw 1/1 Running 0 5s

新しく作ったdbコンテナは空っぽなので、またDBマイグレーションが必要です。

kubectlコマンドを使ってrailsコンテナでコマンドを実行します。

kubectl exec -it rails-6896549fc6-45mmw rake db:migrate

さて、実は先ほど編集した rails-service.yaml の変更はクラスタに反映されていません。

反映するためには、 kubectl apply コマンドを実行します。

$ kubectl apply -f rails-service.yaml

Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
service "rails" configured

警告は出ますが、変更は適用されました。

kubectlコマンドとminikubeコマンドで確認してみます。

$ kubectl get services

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
db ClusterIP None <none> 55555/TCP 6m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 1d
rails NodePort 10.96.140.120 <none> 3000:31308/TCP 6m

$ minikube service list
|-------------|----------------------|------------------------|
| NAMESPACE | NAME | URL |
|-------------|----------------------|------------------------|
| default | db | No node port |
| default | kubernetes | No node port |
| default | rails | http://127.0.0.1:31308 |
| kube-system | kube-dns | No node port |
| kube-system | kubernetes-dashboard | http://127.0.0.1:30000 |
|-------------|----------------------|------------------------|

ブラウザで http://127.0.0.1:31308 にアクセスすると、Railsが動いているのを確認できます。

または、 minikube service rails コマンドによって、該当のURLをブラウザで開くことができます。


所感

Kubernetesの設定はDocker Composeより複雑で、必要な事前知識も多いのですが、Komposeによってそれらをスキップして動作する設定を作れるのは便利だと思います。

MinikubeやKomposeによって、Kubernetesの開発環境もだいぶ便利になってきていると感じました。

本番でKubernetesを使うなら、開発環境はこんな感じで構築すると良さそうです。


今後やりたいこと

上で紹介した docker-compose.yml について、開発時はプロジェクトのディレクトリをマウントしておくと便利だと思いますが、Kubernetesでのやり方をまだ調べきれていないので、その辺りも試しておきたいなと思っています。


むすびに

思いのほか色々な要素を詰め込んだエントリになってしまったので、説明が足りなかったり、わかりにくくなっている部分があるかもしれません。

また、試したばかりのことも多いです。

何か誤りなどありましたら、コメントなどでお知らせ下さい。


参考


脚注