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


この記事はGMOアドマーケティング Advent Calendar 2019の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

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

前提

  • 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が表示されます

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が起動する

serviceが作成され、LoadBalancer経由でRedmineを閲覧できる

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

DBの作成

CloudSQLのWeb UIからRedmineに使うDBを先に作成しておく。

チャートのカスタマイズ

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を建てる事ができました。

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書かなくて良い)
  • Kubernetes podsからCloud SQLへプライベートIPで接続できる(同一VPCを利用する)
  • chartにはカスタマイズ用のパラメータが存在する。

今後について

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

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

引き続き、GMOアドマーケティング Advent Calendar 2019 をお楽しみください