はじめに
Kubernetesがコンテナオーケストレーションツールのデファクトになったといわれて久しい1ですが、今年のAWS re:InventではAmazon EKS2の発表もあり、これからKubernetesに取り組もうという人もいるのではないかと思います。
かくいう私もその一人で、最近この辺りの技術に入門して色々と試していたので、今日はそのまとめを記します。
更新履歴
- 2020-05-09 Compose on Kubernetesについて追記
- 2017-12-12 初稿投稿
用語解説
Minikube
Kubernetesクラスタをローカルマシン上で構築できるようにしてくれるものです。
Kubernetesクラスタを自前で一から構築するのは非常に大変そう(やったことはありません)なのですが、これを使うと簡単に試すことができます。
CIなどでも活用できそうです。
Kompose
Docker Composeの設定ファイルをKubernetes向けに変換するツールです。
また、変換によって生成されたリソース群を、docker-composeライクなインタフェースで制御することもできます。
この記事で行うこと
- PostgreSQLをバックエンドとするシンプルなRailsのWebアプリケーションを用意します。
- このWebアプリケーションをDocker化して、Docker Composeを使った開発環境を構築します。
- Komposeを使ってDocker Composeの設定をKubernetes向けに変換し、Minikube上で動かします。
以降では、DockerやDocker Composeについては、ある程度知っているという前提で書きます。
使用するソースコードや設定ファイルは https://github.com/progrhyme/compose-to-minikube にまとめましたので、適宜ご参照ください。
2020-05-09追記: Compose on Kubernetesについて
2018年12月、Docker社がCompose on Kubernetesというツールを発表しました3。
これを使うと、設定をKubernetes向けに変換することなく、次のようなコマンドで直接Kubernetesクラスタにデプロイすることが可能です。
docker stack deploy --namespace my-app --compose-file /path/to/docker-compose.yml mystack
ただし、利用にはDocker DesktopまたはDocker Enterpriseが必要とのことです。
利用できるのであれば、こちらの方が便利なケースもありそうです。
必要なもの
ツール | 筆者環境のバージョン | 公式インストールガイド |
---|---|---|
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
を次のように編集しておきます。
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を書きました。
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
として作成しました。
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開発者にお馴染みのコントローラ画面が表示されます。
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.yml
を kompose 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点ほど修正する必要がありました。
-
docker-compose.yml
で、コンテナイメージとしてローカルレジストリにpushしたイメージを指定するようにしておく -
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
となっており、クラスタ内からしかアクセスできません。
クラスタ外からアクセス可能にするには、NodePort
やLoadBalancer
にする必要があります。
動作確認
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でのやり方をまだ調べきれていないので、その辺りも試しておきたいなと思っています。
むすびに
思いのほか色々な要素を詰め込んだエントリになってしまったので、説明が足りなかったり、わかりにくくなっている部分があるかもしれません。
また、試したばかりのことも多いです。
何か誤りなどありましたら、コメントなどでお知らせ下さい。
参考
-
https://kubernetes.io/ ... Kubernetes公式サイト
- Running Kubernetes Locally via Minikube | Kubernetes ... MinikubeのGetting Startedガイド
- http://kompose.io/ ... Kompose公式サイト
-
https://docs.docker.com/ ... Dockerドキュメンテーション
- https://docs.docker.com/compose/ ... Docker Compose
-
From Docker Compose to Minikube – Skillshare Writings – Medium
- Skillshareでプロダクション/QA環境をKubernetesに移行したことに続いて、開発環境をDocker ComposeからMinikubeに移行した事例。
脚注
-
Container orchestration: Moving from fleet to Kubernetes | CoreOS ↩
-
Amazon Elastic Container Service for Kubernetes. https://aws.amazon.com/eks/ ↩
-
Simplifying Kubernetes with Docker Compose and Friends - Docker Blog ↩