プルリク単位でステージング環境をつくる。docker, k8s

# 自己紹介

- @mochizukikotaro 
- [株式会社ベーシック](https://basicinc.jp/enjoy-hacking)
  - Rails, CakePHP, AWS
- サーバーサイド、フロントを書きます
- インフラはほぼ触っていません

---

## これまで

- dev: Vagrant
- stg: Itamae, Capistrano
- prd: Itamae, Capistrano 

## いま

- dev: Docker
- stg: Docker, k8s
- prd: Itamae, Capistrano

## 今後

本番も Docker 試してみたい...

---

# 社内の日常

1日に何個も PR が出てきて、何回か本番をデプロイをやるような環境ですので、ステージングが渋滞気味になることがありました。

なので PR ごとに動作確認ができるようなステージング環境がボコボコできたらいいなと思っていました。

---

# [Heroku Review Apps](https://devcenter.heroku.com/articles/github-integration-review-apps) でできます。

---

# それを、docker, k8s をつかって自前でやっている話をします。

---

# 大枠の流れ

![image.png](https://qiita-image-store.s3.amazonaws.com/0/45822/2e3e9cec-0ff1-4d58-cbca-0f145fe4b9f2.png)

---

# label をトリガーにしています


![bananaci.png](https://qiita-image-store.s3.amazonaws.com/0/45822/2a5f515b-a0d0-e810-409b-7fec724c33f5.png)

特定のラベルを付与すると、自動でステージング環境ができあがり GitHub に通知をしてくれます。

※すべての PR を対象にすると莫大なお金がかかるためラベルをトリガーにしています。


---

# BananaCI サーバーでやっていること

![image.png](https://qiita-image-store.s3.amazonaws.com/0/45822/03913cb6-c744-7a1d-6880-791464c8e1e4.png)


```terminal
git clone
git fetch origin pull/123/head ...
bash .bananaci/deployment.sh
```

クローンして、特定のシェルを走らせてるだけ。なので、ほとんど何もやっていないです...。

---

# リポジトリ側でまかなっていること

![image.png](https://qiita-image-store.s3.amazonaws.com/0/45822/1cbdb831-556c-6776-42f3-32a8c0fa9170.png)


## ファイル構成

```terminal
$ cd working-directory

$ tree .bananaci
.bananaci
├── config.yml
├── containers
│   ├── app
│   │   └── Dockerfile
│   ├── db
│   │   └── Dockerfile
│   └── redis
│       └── Dockerfile
├── deployment.sh <- bananaci サーバーで叩かれるコマンド
└── k8s_deploy.yml <- k8s のマニフェストファイル
```


## deployment.sh

```bash:deployment.sh_抜粋
rails_image=gcr.io/${PROJECT_ID}/project-name-rails:${TAG}

# ビルド
docker build -t $rails_image -f .bananaci/Dockerfile .

# プッシュ
gcloud docker -- push $rails_image

# デプロイ
kubectl create -f .bananaci/k8s_deploy.yml
```

ビルドしてプッシュして、最後に `kubectl` コマンドでデプロイをしています。

## k8s_deploy.yml

```yaml:k8s_deploy.yml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: project-name-${SUFFIX}
spec:
  replicas: 1
  template:
    metadata:
      labels:
        application: project-name-bananaci-${SUFFIX}
    spec:
      containers:

      - name: project-name-app-${SUFFIX}
        image: gcr.io/${PROJECT_ID}/project-name-rails:${TAG}
        ports:
        - containerPort: 3000
        args:
        - bash
        - -c
        - RAILS_ENV=staging rake db:migrate db:seed && rails s -b 0.0.0.0 -e staging
        env:
        - name: POSTGRE_HOST
          value: 127.0.0.1
        - name: POSTGRE_DB
          value: "staging"
        - name: POSTGRE_USER
          value: "user"
        - name: POSTGRE_PWD
          value: "****"

      - name: project-name-db-${SUFFIX}
        image: gcr.io/${PROJECT_ID}/project-name-postgres:${TAG}
        ports:
        - containerPort: 5432

---

apiVersion: v1
kind: Service
metadata:
  name: project-name-${SUFFIX}
spec:
  type: LoadBalancer
  ports:
  - port: 3000
    name: project-name-app-${SUFFIX}
  selector:
    application: project-name-bananaci-${SUFFIX}
```

---

# クラスタ内のイメージ

![image.png](https://qiita-image-store.s3.amazonaws.com/0/45822/751a55d8-8f93-e946-b732-8f69914dfe6c.png)

---

# どれくらいのコストか？

およそ

- 4 repository で稼働
- 12 pod
- 8 node
- 10万円 / 月

深夜帯や土日はストップするなどをして上記の金額です。

---

# 感想

- docker-compose くらいの感覚で k8s で環境ができるのでうれしい
- 本番運用ではないので、DB の永続化とか細かいこと考慮しなくて良いので簡単
- なんだかんだ社内のリポジトリでは入れてくれているので便利だと感じてもらえている感

---

# 課題感

- ラベルを付与してからアクセス可能な状態になるまでに 12 分くらいかかったりするので、、遅い
- お金まあまあかかっている
- DB データをどうしているんだ問題

---

# 今後

- 兎に角速くしたい
- もっとシンプルな記述で済ませたい
- オープンにしたい（けど、いろいろ課題があるので...）
- 他のアプローチもあると思うので、お話を聞いてみたいです :bow: 
- そして、本番も docker で運用してみたい。
- 本番 docker のお話も沢山お伺いしたいです :bow: 

---

# 以上です。ありがとうございました！