kubernetes
GKE
cloudsql
ulgeekDay 3

冗長構成のCloud SQLとGKEの接続方法

最近仕事でGCPを触りはじめ、特にGKEを使ったアプリケーションの構築に興味を持っています。基本的には、まず公式ドキュメントやチュートリアルで理解を深めているのですが、それだけでは分からなかった点があったので、まとめました。
今回は、冗長構成したCloud SQLに対して、GKE上のコンテナから接続する方法を紹介します。一般的に高可用性や負荷分散を目的として、データベースを冗長構成することがあると思います。Cloud SQLの場合、Masterインスタンスに対して、Failover Replicaを作成することで、耐障害性と負荷性能を高める構成をとることができます。GKEからCloud SQLインスタンスに接続するには、Cloud SQL Proxy Docker イメージを使うことが一般的で、単一のCloud SQLインスタンスに接続する方法は、公式ドキュメントにも記載されていますが、複数のインスタンスへの接続設定はなかったため、実際に試した設定をまとめました。

サービス構成

  • 最終的に以下の構成を構築します
  • GKE
    • 接続の検証のために、mysql-clientコンテナを立てます
    • Cloud SQLに接続するために、cloudsql-proxyコンテナを立てます
  • Cloud SQL
    • Master, Failover Replica, Read Replicaの3種類があります
    • Failover ReplicaはRead Replicaとしても使うことができ、ゾーン障害時にはMasterに昇格します
    • 耐障害性と負荷性能を高めるため、Master(write専用)とFailover Replica(read専用)の構成としました

構成_20171130_03.JPG

構築手順

Cloud SQLの設定

  • 公式ドキュメントを参考に、Masterインスタンスを作成

GKEの設定

Cluster作成

  • 公式ドキュメントを参考にClusterを作成
  • 今回の構成を作成するにあたっては、zoneは適宜選択してよい
    • GPCではデフォルトのVPCネットワークが用意されているので、指定しなければデフォルトのVPCに構築され、ファイヤウォールルールも適用される
    • 今回は外部にアプリケーションを公開する想定はないので、ネットワークに関しても気にする必要はない

Cloud SDKインストール

  • 公式ドキュメントを参考にCloud SDKをインストール
  • Webブラウザ上のcloud Shellからもgcloudコマンドは使えるが、後続の設定でローカルでの作業が必要になるため、用意しておく
    • gcloud initでgcloudコマンドを使用できるようにする

操作するクラスターの指定とkubectlコマンドの取得

  • 以下のコマンドをCloud SDKで実行
$ gcloud config set container/cluster [NAME]
$ gcloud container clusters get-credentials [NAME] --zone=[zone name]
$ gcloud auth application-default login

接続のための認証情報設定

Dockerイメージのデプロイ

  • デプロイするイメージは以下の2つ
    • mysql-client:接続を確認するためのDockerイメージ
    • cloudsql-proxy:Cloud SQL Proxy Docker イメージ ※公式のイメージを使う

mysql-clientのイメージを作成

  • Dockerfileからイメージを作成する
Dockerfile
FROM mysql

ENTRYPOINT ["tail", "-f", "/dev/null"]
  • pullしたイメージをContainer registoryにpushする
$ docker tag [image_id] asia.gcr.io/[project_id]/[image]:tag
$ gcloud docker -- push asia.gcr.io/[project_id]/[image]:tag

イメージのデプロイ

  • GKEにイメージをデプロイする際には、Kubernetesのコマンドを使用する
  • Kubernetesにはコンテナの集合体であるPodという概念があり、Podを作成するために、以下のyamlファイル(Deployment)を作成する
    • cloudsql-proxyの接続先をカンマ区切りで並べ、ポートは違うものにするのがポイント
test-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: gke-sql-test
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: gke-sql-test
    spec:
      imagePullSecrets:
      - name : gcp-registry-key
      containers:
      - image: asia.gcr.io/[project_id]/[image]:tag
        name: mysql-client
      - image: gcr.io/cloudsql-docker/gce-proxy:1.11
        name: cloudsql-proxy
        command: ["/cloud_sql_proxy", "--dir=/cloudsql",
                  "-instances={Master接続名}=tcp:3306,{Failover Replica接続名}=tcp:3307",
                  "-credential_file=/secrets/cloudsql/credentials.json"]
        volumeMounts:
          - name: cloudsql-instance-credentials
            mountPath: /secrets/cloudsql
            readOnly: true
          - name: ssl-certs
            mountPath: /etc/ssl/certs
          - name: cloudsql
            mountPath: /cloudsql
      volumes:
        - name: cloudsql-instance-credentials
          secret:
            secretName: cloudsql-instance-credentials
        - name: ssl-certs
          hostPath:
            path: /etc/ssl/certs
        - name: cloudsql
          emptyDir:
  • 以下のコマンドを実行する
$ kubectl create -f test-deployment.yaml

以上で設定は終了です。
最後に実際にインスタンスに接続することができるか、mysql-clientコンテナにログインして確認を行いたいと思います。

検証

  • mysql-clientコンテナにログイン
$ kubectl exec -it gke-sql-test -c mysql-client /bin/bash
  • mysqlのコマンドで接続を確認する
$ mysql -h 127.0.0.1 -P 3306 -u [user-name] -p
$ mysql -h 127.0.0.1 -P 3307 -u [user-name] -p