takaya030の備忘録

PHP、Laravel、Docker などの話がメインです

Kubernetes で Lumen を動かす

Google Container Engine (GKE) で Kubernetes を使って Lumen を動かしたときの手順メモ。
今回は ReplicationController で pod を 3 個立ててみました。

Docker イメージの作成

1 個の pod 内で nginx と php-fpm の 2 つのコンテナを起動させます。そのための Docker イメージを作成します。

nginx の Dockerfile

FROM nginx:latest
MAINTAINER takaya030

ADD server.conf /etc/nginx/conf.d/server.conf

server.conf

同じ pod のコンテナは同じホストで起動するので php-fpm を localhost:9000 で参照する設定にしています。

server {
    listen 80 default;
    server_name _;
    root /webapp/public;
    index index.php index.html index.htm;
    charset utf-8;

    access_log off;
    error_log off;

    rewrite ^(.+)/$ $1;

    location / {
        # try_files $uri $uri/ /index.php$is_args$args;
        try_files $uri /index.php?$query_string;
    }

    location ~ ^/index.php$ {
        fastcgi_pass localhost:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

nginx イメージのビルド

$ docker build -t gcr.io/my_project_id/lumen_nginx .

php-fpm + lumen の Dockerfile

k8s_lumen フォルダはこちらで作成した Lumen の実行環境になります。

FROM php:7-fpm
MAINTAINER takaya030

RUN apt-get update \
  && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng12-dev libmcrypt-dev \
  && docker-php-ext-install pdo_mysql mysqli mbstring gd iconv mcrypt

RUN mkdir /webapp
COPY k8s_lumen /webapp

php-fpm イメージのビルド

$ docker build -t gcr.io/my_project_id/lumen_php7 .

イメージを Container Registry へ push

$ gcloud docker push gcr.io/my_project_id/lumen_nginx
$ gcloud docker push gcr.io/my_project_id/lumen_php7

ReplicationController の作成

rc-k8slumen.yaml

apiVersion: v1
kind: ReplicationController
metadata:
  name: k8slumen
spec: 
  replicas: 3
  selector:
    app: weblumen
  template:
    metadata:
      name: k8slumen
      labels:
        app: weblumen
    spec:
      containers:
        - name: nginx
          image: gcr.io/my-project-id/lumen_nginx
          ports:
            - containerPort: 80
        - name: lumen
          image: gcr.io/my-project-id/lumen_php7
          ports:
            - containerPort: 9000

ReplicationController の作成

$ kubectl create -f rc-k8slumen.yaml
replicationcontroller "k8slumen" created

ReplicationController の作成確認

$ kubectl get rc
NAME       DESIRED   CURRENT   AGE
k8slumen   3         3         27s

service の作成

service-k8slumen.yaml

apiVersion: v1
kind: Service
metadata:
  name: lumentest
spec:
  ports:
    -
      port: 80
      targetPort: 80
  selector:
    app: weblumen
  type: LoadBalancer

service の作成

$ kubectl create -f service-k8slumen.yaml
service "lumentest" created

service の作成確認

$ kubectl get services
NAME         CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
kubernetes   10.3.240.1     <none>        443/TCP   7m
lumentest    10.3.255.153                 80/TCP    17s

動作確認

この状態で pod が 3 個起動しています。

$ kubectl get pods -l app=weblumen -o wide
NAME             READY     STATUS    RESTARTS   AGE       NODE
k8slumen-5r9jc   2/2       Running   0          1m        gke-cluster-1-default-pool-a58af72c-3ais
k8slumen-itl2h   2/2       Running   0          1m        gke-cluster-1-default-pool-a58af72c-yx7i
k8slumen-xfed2   2/2       Running   0          1m        gke-cluster-1-default-pool-a58af72c-4rtd

service を作成してから 1 分程経過するとグローバルIP (EXTERNAL-IP) が割り当てられるので、 http://EXTERNAL-IP にブラウザでアクセスして以下のように表示されれば成功です。
f:id:takaya030:20160702234718p:plain
ロードバランスされているので、ブラウザをリロードした際、前回と別の pod にリクエストしたときは以下のように Server IP が変化します。
f:id:takaya030:20160702234754p:plain
f:id:takaya030:20160702234807p:plain

フェイルオーバー(failover)の検証

試しに pod を一つ削除してみます。

$ kubectl delete pod k8slumen-5r9jc
pod "k8slumen-5r9jc" deleted

kubernetes が pod の減少を検知して自動で pod を立ち上げます。
pod のリストを見ると新しい pod が追加されているのが分かります。

$ kubectl get pods -l app=weblumen -o wide
NAME             READY     STATUS    RESTARTS   AGE       NODE
k8slumen-itl2h   2/2       Running   0          31m       gke-cluster-1-default-pool-a58af72c-yx7i
k8slumen-w468c   2/2       Running   0          12s       gke-cluster-1-default-pool-a58af72c-3ais
k8slumen-xfed2   2/2       Running   0          31m       gke-cluster-1-default-pool-a58af72c-4rtd

後始末

service、ReplicationController の削除
ReplicationController を削除すれば pod も自動で削除されます

$ kubectl delete -f service-k8slumen.yaml
service "lumentest" deleted

$ kubectl delete -f rc-k8slumen.yaml
replicationcontroller "k8slumen" deleted