18
12

More than 5 years have passed since last update.

KubernetesでRailsを動かしてみよう!

Posted at

今回は GoogleCloudPlatform の GKE を利用し、Rails を動かしてみました。

Kubernetes Engine クラスタの作成

Kubernetes Engine クラスタは、マスターと、ノードと呼ばれる複数のワーカーマシンで構成されます。

アプリケーションをクラスタにデプロイすると、アプリケーションがノードに配置され、それらのノードで実行されます。

GKE ではクラスタを作成するためには次のコマンドを実行します。

$ gcloud container clusters create rails-cluster

※クラスタの作成は完了するのに数分かかります。

認証情報の登録

認証情報は base64 でハッシュ化した値を登録する必要がありますので、まずは登録したい文字列を base64 でハッシュ化します。

$ echo -n "database_root_password" | base64
ZGF0YWJhc2Vfcm9vdF9wYXNzd29yZA==

$ echo -n "secret_key_base" | base64
c2VjcmV0X2tleV9iYXNl

次にマニフェストファイルを作成し、先ほどの値をそのまま記述します。

secret.yml
apiVersion: v1
kind: Secret
metadata:
  name: rails
type: Opaque
data:
  database_root_password: ZGF0YWJhc2Vfcm9vdF9wYXNzd29yZA==
  secret_key_base: c2VjcmV0X2tleV9iYXNl

次のコマンドを実行することにより、このマニフェストファイルをデプロイすることができます。

$ kubectl create -f secret.yml

永続ストレージの作成

Kubernetes で作成される Docker コンテナではデータの永続化は行われないので、MySQL 用に永続ストレージを作成します。

$ gcloud compute disks create --size 200GB mysql-data

ここでは 200GB に指定して永続ストレージを作成しています。

MySQL をデプロイする

mysql.yml というファイル名でマニフェストファイルを作成しデプロイします。

secretKeyRef で先ほど登録した認証情報を、volumes の部分で永続ストレージを参照するようにします。

mysql.yml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - image: mysql:5.6
          name: mysql
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: rails
                  key: database_root_password
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql-persistent-storage
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-persistent-storage
          gcePersistentDisk:
            pdName: mysql-data
            fsType: ext4

secret.yml と同じように、このマニフェストファイルをデプロイします。

$ kubectl create -f mysql.yml

ここでは Docker コンテナに永続ストレージをアタッチするので、ポッドのステータスが Running になるまでは少し時間がかかります。

kubectl get pod コマンドでポッドのステータスを確認することができます。

$ kubectl get pod
NAME                     READY     STATUS    RESTARTS   AGE
mysql-xxxxxxxxxx-xxxxx   1/1       Running   0          1m

次に、mysql-service.yml で MySQL コンテナの 3306 ポートを公開する Service を作成し、あとで作成する Rails コンテナからアクセスできるようにします。

mysql-service.yml
apiVersion: v1
kind: Service
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  type: ClusterIP
  ports:
    - port: 3306
  selector:
    app: mysql

デプロイします。

$ kubectl create -f mysql-service.yml

作成された Service の一覧は kubectl get service コマンドで確認できます。

$ kubectl get service
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.xx.xx.xx     <none>        443/TCP    29m
mysql        ClusterIP   10.xx.xx.xx     <none>        3306/TCP   7m

Rails アプリケーションをデプロイする

まずは MySQL と同じようにマニフェストファイルを作成し、その後 Service を作成し、外部からアクセスできるようにします。

app.yml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: rails
  labels:
    app: rails
spec:
  replicas: 1
  selector:
    matchLabels:
      app: rails
  template:
    metadata:
      labels:
        app: rails
    spec:
      containers:
        - image: busybox
          name: rails
          env:
            - name: DATABASE_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: rails
                  key: database_root_password
            - name: SECRET_KEY_BASE
              valueFrom:
                secretKeyRef:
                  name: rails
                  key: secret_key_base
          ports:
            - containerPort: 3000
              name: rails

後ほど、rails アプリケーションの image ファイルをデプロイするので、ここでは適当な image ファイルを指定しています。

デプロイします。

$ kubectl create -f app.yml

外部から Rails アプリケーションに接続できるようにするため、Service を作成します。

MySQL の場合と異なり、ここでは外部に公開するので type: LoadBalancer となっているのに注意してください。

app-service.yml
apiVersion: v1
kind: Service
metadata:
  name: rails
  labels:
    app: rails
spec:
  type: LoadBalancer
  ports:
    - port: 3000
  selector:
    app: rails

デプロイします。

$ kubectl create -f app-service.yml

kubectl get service で rails の EXTERNAL-IP<pending> から IP が表示されるまで待ちます。

これで http://<EXTERNAL-IP>:3000 でアクセスできるようになりましたが、まだアプリケーションをデプロイしていないので、エラー画面が表示されると思います。

アプリケーションのデプロイ

今回はさくっとローカルに Rails アプリケーションを new したものを使いたいと思います。

$ rails new sampleapp -d mysql
...
* bin/rake: spring inserted
* bin/rails: spring inserted

$ cd sampleapp

マイグレーションと画面表示の確認用に適当な scaffold を実行しておきます。

$ bin/rails generate scaffold user name:string age:integer

database のパスワードは先ほど app.yml で指定した環境変数を参照するように変更します。

config/database.yml
production:
  <<: *default
  host: mysql
  database: sampleapp_production
  username: root
  password: <%= ENV['DATABASE_ROOT_PASSWORD'] %>

Kubernetes では Docker イメージからポッドを作成するので、new した Rails アプリケーションを Docker Registry に登録する必要があります。

GCP には Google Container Registry というサービスがあるので、ここにイメージを push したいと思います。

まずは Dockerfile を作成し、それを build して、イメージファイルを作成したいと思います

Dockerfile
FROM ruby:2.3

ENV APP_ROOT="/app"

RUN \
    mkdir -p $APP_ROOT

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

RUN \
    bundle config --global build.nokogiri --use-system-libraries

WORKDIR $APP_ROOT

ADD . $APP_ROOT

ENV RAILS_ENV production
WORKDIR $APP_ROOT

ENTRYPOINT \
    bundle install && \
    bin/rails db:create && \
    bin/rails db:migrate && \
    bin/rake assets:precompile && \
    bin/rails server -p 3000 -b 0.0.0.0

build して、Google Container Registry にイメージを push します。

$ export PROJECT_ID="$(gcloud config get-value project -q)"
$ docker build -t gcr.io/${PROJECT_ID}/sampleapp:v1 .
$ gcloud docker -- push gcr.io/${PROJECT_ID}/sampleapp:v1

Google Container Registry にイメージを push できたので、rails のポッドをこのイメージファイルを適応したものに変更します。

$ kubectl set image deployment/rails rails=gcr.io/${PROJECT_ID}/sampleapp:v1

実行したあとに pod を確認すると次のように以前の pod が Terminating になり、新しいものが Running になるのが確認できるかと思います。

$ kubectl get pod
NAME                     READY     STATUS        RESTARTS   AGE
mysql-xxxxxxxxxx-xxxxx   1/1       Running       0          40m
rails-xxxxxxxxxx-xxxxx   1/1       Running       0          16s
rails-xxxxxxxxxx-xxxxx   1/1       Terminating   0          21m

新しい pod が Running になったらアプリケーションのデプロイが完了しているので、http://<EXTERNAL-IP>:3000/users にアクセスしてみましょう!

問題なく画面が表示されているのが確認できるはずです!

クリーンアップ

課金されないように今回作成したリソースを全て削除します。

削除しないとどんどん課金されていくので気をつけてください

$ kubectl delete service rails
$ gcloud container clusters delete rails-cluster
$ gcloud compute disks delete mysql-data

まとめ

今回は GCP の GKE を使い、Kubernetes を試してみました。

AWS の EKS の GA など盛り上がりを見せている Kubernetes ですが、弊社でも本番環境での Kubernetes の導入を見据えて絶賛検証中です。

実行環境を作成するだけであれば今回のようにそれほど難しくはないので是非みなさんも Kubernetes を試してみてください!!

18
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
12