Rails + MySQL on Kubernetesを試す
前回はMySQLがk8s上で動いたわーい、というところまでやった。今回はRubyOnRailsを動かしてみる。
前提として動かすRailsアプリが必要なんだけど、suburi/docker-mysql-railsというdocker-composeで動かせるものがあったのでありがたくforkして利用することにした(takaishi/docker-mysql-rails)
MySQLの起動(前回と同じ)
前回と同じでOK。
apiVersion: v1
kind: ReplicationController
metadata:
name: mysql
spec:
replicas: 1
selector:
app: mysql
template:
metadata:
name: mysql
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: passw0rd
ports:
- containerPort: 3306
---
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
targetPort: 3306
protocol: TCP
type: LoadBalancer
selector:
app: mysql
作成。
$ kubectl create -f ./mysql.yml
Railsの起動
まずはイメージを用意する
kubernetesはイメージのビルドはできないようなので、dockerコマンドなどでイメージを作成して、レジストリに置く必要がある。DockerHubを使う手もあるが、仕事の場合、そうはいかない可能性も考えられる。今回はローカルにプライベートレジストリを構築し、そこにプッシュしてみる。
さて、プライベートなDockerレジストリを構築するにはどうしたらいいかなと思っていたら、 Local development with Kubernetes という記事を発見した。k8s上にレジストリを構築するもので、手っ取り早そうなのでこれを使うことにする。
apiVersion: v1
kind: ReplicationController
metadata:
name: kube-registry-v0
namespace: kube-system
labels:
k8s-app: kube-registry
version: v0
spec:
replicas: 1
selector:
k8s-app: kube-registry
version: v0
template:
metadata:
labels:
k8s-app: kube-registry
version: v0
spec:
containers:
- name: registry
image: registry:2
resources:
limits:
cpu: 100m
memory: 100Mi
env:
- name: REGISTRY_HTTP_ADDR
value: :5000
- name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY
value: /var/lib/registry
volumeMounts:
- name: image-store
mountPath: /var/lib/registry
ports:
- containerPort: 5000
name: registry
protocol: TCP
volumes:
- name: image-store
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: kube-registry
namespace: kube-system
labels:
k8s-app: kube-registry
kubernetes.io/name: "KubeRegistry"
spec:
selector:
k8s-app: kube-registry
ports:
- name: registry
port: 5000
protocol: TCP
---
apiVersion: v1
kind: Pod
metadata:
name: kube-registry-proxy
namespace: kube-system
spec:
containers:
- name: kube-registry-proxy
image: gcr.io/google_containers/kube-registry-proxy:0.3
resources:
limits:
cpu: 100m
memory: 50Mi
env:
- name: REGISTRY_HOST
value: kube-registry.kube-system.svc.cluster.local
- name: REGISTRY_PORT
value: "5000"
- name: FORWARD_PORT
value: "5000"
ports:
- name: registry
containerPort: 5000
hostPort: 5000
kubectl apply -f local-registry.yml
これで、ローカリリポジトリの準備が整った。後は、動かしたいRailsアプリのイメージを作成し、レジストリにプッシュすれはOK。
$ docker build -t localhost:5000/r_takaishi/docker-mysql-rails .
$ docker push localhost:5000/r_takaishi/docker-mysql-rails
いよいよ起動だ
Rails用のマニフェストは以下の通り。環境変数でDBのホストやパスワード等を渡している。また、コンテナの起動前にdb:createやdb:migrateを行うようにしてみた(が、このPostStartの実行ログがどこに保存されるのかがいまいち分かっていない)。
apiVersion: v1
kind: ReplicationController
metadata:
name: rails
spec:
replicas: 1
selector:
app: rails
template:
metadata:
name: rails
labels:
app: rails
spec:
containers:
- name: rails
image: localhost:5000/r_takaishi/docker-mysql-rails
command: ["bundle", "exec", "rails", "s", "-p", "3000", "-b", "0.0.0.0"]
env:
- name: RAILS_ENV
value: development
- name: MYSQL_HOST
value: mysql.default.svc.cluster.local
- name: MYSQL_USER
value: root
- name: MYSQL_PASSWORD
value: passw0rd
lifecycle:
postStart:
exec:
command:
- /myapp/post-start.sh
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: rails
spec:
ports:
- port: 3000
targetPort: 3000
protocol: TCP
type: LoadBalancer
selector:
app: rails
$ cat post-start.sh
#!/bin/bash
RAILS_ENV=$RAILS_ENV bundle exec rake db:create
RAILS_ENV=$RAILS_ENV bundle exec rake db:migrate
applyする。
kubectl apply -f ./rails.yml
こんな感じで、mysqlとrailsのpodが起動した状態となる。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-8kd4q 1/1 Running 2 4d
rails-l15mm 1/1 Running 0 28m
minikubeでアクセス先URLを取得して、アクセスする。
$ minikube service rails --url
http://192.168.99.100:31452
やったー!
スケールしてみる
コンテナの台数を増やしてみる。railsのpodが1台の所から始めよう。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
mysql-8kd4q 1/1 Running 2 4d
rails-8cnzn 1/1 Running 0 6m
scaleコマンドがある。便利だ。5台にしてみよう。
$ kubectl scale rc rails --replicas=5
replicationcontroller "rails" scaled
そうすると、podが5個に増える。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-8kd4q 1/1 Running 2 4d
rails-8cnzn 1/1 Running 0 7m
rails-nwz9l 0/1 ContainerCreating 0 2s
rails-q4f5z 0/1 ContainerCreating 0 2s
rails-tfcjw 0/1 ContainerCreating 0 2s
rails-zbjqw 0/1 ContainerCreating 0 2s
起動完了。30秒弱で1台から5台にスケールアウトできた。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-8kd4q 1/1 Running 2 4d
rails-8cnzn 1/1 Running 0 7m
rails-nwz9l 1/1 Running 0 25s
rails-q4f5z 1/1 Running 0 25s
rails-tfcjw 1/1 Running 0 25s
rails-zbjqw 1/1 Running 0 25s
減らすのも簡単。scaleコマンドで台数を1にしてやれば、1台になるまでコンテナが減ってくれる。
まとめ
RailsアプリとMySQLをKubernetes上で動かし、アプリの台数を増やしたり減らしたりしてみた。台数の増減がとにかく楽なので、仕事でも使いたいなあと思います。