GKEとCloud SQLを使ってhelmでRedmineを建ててみる


この記事は[:calendar:GMOアドマーケティング Advent Calendar 2019](https://qiita.com/advent-calendar/2019/gmo-am)の18日目の記事です。

## 自己紹介

GMOアドマーケティングでインフラ開発に携わっています、@sandatsです。
最近はGCPに触れる機会が多く、今回は勉強も含めてGKE + Cloud SQL + helmでRedmineを建ててみました。


## 登場人物の紹介

### GKE(Google Kubernetes Engine)

GCPのインフラを利用して構成されるKubernetes

### Cloud SQL

GCPが提供するマネージドDBサービス
MySQL/Postgre SQL/SQL Serverが使える

### Helm

Kubernetesのパッケージ管理ツール
今回はHelm 3を利用

### Redmine

タスク/チケット/進捗などなど管理ツール
お世話になってます:pray:

## 前提

- helmがインストールされている
- GCPでKubernetesクラスタが起動している
- GCPでCloud SQLが起動し、プライベート IPが有効になっている
- KubernetesとCloud SQLのVPCが同じVPCネットワークを使っている

## 参考したドキュメントやリンク

Helm Quickstart
https://helm.sh/docs/intro/quickstart/

Helm charts Redmine
https://github.com/helm/charts/tree/master/stable/redmine

### 環境

helm : v3.0.1
Kubernetes : v1.13.11-gke.14

```
 ~  helm version
version.BuildInfo{Version:"v3.0.1", GitCommit:"7c22ef9ce89e0ebeb7125ba2ebf7d421f3e82ffa", GitTreeState:"clean", GoVersion:"go1.13.4"}

 ~  kubectl version
Client Version: version.Info{Major:"1", Minor:"13+", GitVersion:"v1.13.11-dispatcher", GitCommit:"2e298c7e992f83f47af60cf4830b11c7370f6668", GitTreeState:"clean", BuildDate:"2019-09-19T22:26:40Z", GoVersion:"go1.11.13", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"13+", GitVersion:"v1.13.11-gke.14", GitCommit:"56d89863d1033f9668ddd6e1c1aea81cd846ef88", GitTreeState:"clean", BuildDate:"2019-11-07T19:12:22Z", GoVersion:"go1.12.11b4", Compiler:"gc", Platform:"linux/amd64"}
```

## helmからRedmineをインストール

helmからRedmineをinstall

```
 ~  helm install infra-redmine stable/redmine
NAME: infra-redmine
LAST DEPLOYED: Mon Dec 16 18:27:27 2019
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the Redmine URL:

  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
        Watch the status with: 'kubectl get svc --namespace default -w infra-redmine'


  export SERVICE_IP=$(kubectl get svc --namespace default infra-redmine --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")
  echo "Redmine URL: http://$SERVICE_IP/"

2. Login with the following credentials

  echo Username: user
  echo Password: $(kubectl get secret --namespace default infra-redmine -o jsonpath="{.data.redmine-password}" | base64 --decode)
```

`helm ls` でインストールしたRedmineの情報が確認できる

```
 ~  helm ls
NAME         	NAMESPACE	REVISION	UPDATED                             	STATUS  	CHART         	APP VERSION
infra-redmine	default  	1       	2019-12-18 15:23:23.329367 +0900 JST	deployed	redmine-14.0.1	4.0.5
```

しばらくすると、2つのpodsが**READY 1/1**になる

```
 ~  kubectl get pods
NAME                             READY   STATUS    RESTARTS   AGE
infra-redmine-5799684fc8-r4h25   1/1     Running   1          16m
infra-redmine-mariadb-0          1/1     Running   0          15m
```

kubectl get serviceでEXTERNAL-IPをメモします

```
 ~  kubectl get service
NAME                    TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
infra-redmine           LoadBalancer   10.109.4.121   35.243.123.53   80:31675/TCP   26m
infra-redmine-mariadb   ClusterIP      10.109.6.209   <none>          3306/TCP       26m
kubernetes              ClusterIP      10.109.0.1     <none>          443/TCP        126m
```

EXTERNAL-IPに適当なブラウザからアクセスするとRedmineが表示されます
![スクリーンショット 2019-12-16 18.56.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315813/1427f767-0998-8adf-4205-b50af5735c10.png)

### Redmineの削除

`helm uninstall`を実行するとRedmineのdeployments、pods、serviceが削除されます。早い。

```
 ~  helm uninstall infra-redmine
release "infra-redmine" uninstalled
 ~  helm ls
NAME	NAMESPACE	REVISION	UPDATED	STATUS	CHART	APP VERSION

 ~  kubectl get service
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.109.0.1   <none>        443/TCP   142m
 ~  kubectl get pods
No resources found.
```

### ここまでのまとめ

#### 素の状態でインストールするとRedmineとMariaDBのpodsが起動する
![Redmine on k8s.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315813/133fed11-7463-aee7-24bf-f837340a2ffe.png)

#### serviceが作成され、LoadBalancer経由でRedmineを閲覧できる
![Redmine on k8s with GCLB.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315813/2fbd5a2d-3716-dca7-3daa-54773e5bece4.png)

つづいて、Redmineのpodsはそのままにして、MariaDBのpodsを起動させずにCloud SQLへ接続する設定に変更します。

### DBの作成

CloudSQLのWeb UIからRedmineに使うDBを先に作成しておく。
![cloudsql_redmine.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315813/6714b6a3-c748-51c7-8c14-9c21b479120d.png)

### チャートのカスタマイズ

Helmではchart毎にカスタマイズ可能なパラメータが存在する。
https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing

`helm show values チャート名`でカスタマイズ可能な値が表示される。

```
 ~  helm show values stable/redmine
## Global Docker image parameters
## Please, note that this will override the image parameters, including dependencies, configured to use the global value
## Current available global Docker image parameters: imageRegistry and imagePullSecrets
##
# global:
#   imageRegistry: myRegistryName
#   imagePullSecrets:
#     - myRegistryKeySecretName
#   storageClass: myStorageClass

## Bitnami Redmine image version
## ref: https://hub.docker.com/r/bitnami/redmine/tags/
##
image:
  registry: docker.io
  repository: bitnami/redmine
  tag: 4.0.5-debian-9-r28
  ## Specify a imagePullPolicy
  ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent'
  ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images
  ##
  pullPolicy: IfNotPresent
# ...
```

パラメータを編集して、RedmineをCloud SQLに接続しつつ、DB用のPodsを起動しないようにします。

### チャートのカスタマイズ

チャートのカスタマイズパラメータをファイルに書き出す。

```
 ~  helm show values stable/redmine > helm_redmine.yaml
```

書き出したファイルを開き、mariadbのenabledをtrueからfalseにする。

```
mariadb:
  ## Whether to deploy a mariadb server to satisfy the applications database requirements. To use an external database set this to false and configure the externalDatabase parameters
  enabled: false
  ## Disable MariaDB replication
  replication:
    enabled: false
```

同様にexternalDatabaseでCloud SQLへ接続するための情報を記述。(host、name、user、passwordを変更)

```
externalDatabase:
  ## Database host
  host: 10.153.16.3

  ## Database name
  name: redmine

  ## Database User
  user: root

  ## Database Password
  password: hogehoge

  ## Database port number (use 5432 when using PostgreSQL)
  port: 3306
```

修正したファイルを指定して、`helm install`を実行。

```
 ~  helm install infra-redmine stable/redmine -f helm_redmine.yaml
NAME: infra-redmine
LAST DEPLOYED: Wed Dec 18 15:32:35 2019
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get the Redmine URL:

  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
        Watch the status with: 'kubectl get svc --namespace default -w infra-redmine'


  export SERVICE_IP=$(kubectl get svc --namespace default infra-redmine --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")
  echo "Redmine URL: http://$SERVICE_IP/"

2. Login with the following credentials

  echo Username: user
  echo Password: $(kubectl get secret --namespace default infra-redmine -o jsonpath="{.data.redmine-password}" | base64 --decode)

```

前回とは異なり、今回はRedmineのpodsのみ起動する。

```
 ~  kubectl get pods
NAME                             READY   STATUS    RESTARTS   AGE
infra-redmine-7b76bbb49f-zjd6v   1/1     Running   0          23m
```

この状態で、`kubectl get svc`に表示されるEXTERNAL-IPにアクセスすると同様にRedmineのトップページが表示されます。

```
 ~  kubectl get svc
NAME            TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
infra-redmine   LoadBalancer   10.203.9.231   35.230.106.77   80:31731/TCP   8m38s
kubernetes      ClusterIP      10.203.0.1     <none>          443/TCP        21m
```

チャートのパラメータをカスタマイズして、Cloud SQLを使ってRedmineを建てる事ができました。
![Redmine on k8s with CloudSQL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315813/f9187465-692b-8163-e2b9-859f054e66e7.png)

### DBの中身を確認

RedmineがCloud SQLを使っているのか確かめる為、RedmineコンテナからmysqlコマンドでCloud SQLに接続します。

```
 ~  kubectl exec -it infra-redmine-7b76bbb49f-zjd6v /bin/sh
# which mysql
/opt/bitnami/mysql/bin/mysql
# mysql -h 10.153.16.3 redmine -p
Enter password:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 2909
Server version: 5.7.14-google (Google)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [redmine]> show tables;
+-------------------------------------+
| Tables_in_redmine                   |
+-------------------------------------+
| ar_internal_metadata                |
| attachments                         |
| auth_sources                        |
| boards                              |
| changes                             |
| changeset_parents                   |
| changesets                          |
| changesets_issues                   |
| comments                            |
| custom_field_enumerations           |
| custom_fields                       |
| custom_fields_projects              |
| custom_fields_roles                 |
| custom_fields_trackers              |
| custom_values                       |
| documents                           |
| email_addresses                     |
| enabled_modules                     |
| enumerations                        |
| groups_users                        |
| import_items                        |
| imports                             |
| issue_categories                    |
| issue_relations                     |
| issue_statuses                      |
| issues                              |
| journal_details                     |
| journals                            |
| member_roles                        |
| members                             |
| messages                            |
| news                                |
| open_id_authentication_associations |
| open_id_authentication_nonces       |
| projects                            |
| projects_trackers                   |
| queries                             |
| queries_roles                       |
| repositories                        |
| roles                               |
| roles_managed_roles                 |
| schema_migrations                   |
| settings                            |
| time_entries                        |
| tokens                              |
| trackers                            |
| user_preferences                    |
| users                               |
| versions                            |
| watchers                            |
| wiki_content_versions               |
| wiki_contents                       |
| wiki_pages                          |
| wiki_redirects                      |
| wikis                               |
| workflows                           |
+-------------------------------------+
56 rows in set (0.001 sec)
```
コンテナ内からCloudSQLのプライベートIPでDBに接続できました。
Redmineのテーブルも存在する事が確認できました。

## まとめ

- 1コマンドでHelmからRedmineを起動できる(yaml書かなくて良い:thumbsup:)
- Kubernetes podsからCloud SQLへプライベートIPで接続できる(同一VPCを利用する)
- chartにはカスタマイズ用のパラメータが存在する。

## 今後について

インフラで使っていくツールをk8sに乗せかえていきたいです:muscle:


明日は、@mSpringさんによる「TensorFlowにおけるクリッピングと正規化」です！

引き続き、[:calendar:GMOアドマーケティング Advent Calendar 2019](https://qiita.com/advent-calendar/2019/gmo-am) をお楽しみください:relaxed: