GKE Kubernetes で CloudSQL を利用する

Cloud SQL を利用するためには、直接接続するのではなく、 Cloud SQL Proxy を利用します。
Cloud SQL Proxy は Docker image として公開されているため、こちらを使います。


Googleのドキュメント通りに設定すれば通信出来ます。
Pod 内に Proxy の Container を含める構成になっており、この構成をサイドカーパターンと呼びます。

cloud.google.com

サンプル通りのやり方

ポイントは1つだけ、CloudSQL Client の役割をつけたサービスアカウントを作成し、cloudsql-instance-credentials などの名前で json を保存します。

kubectl create secret generic cloudsql-instance-credentials --from-file credentials.json=./secret/projectname-1234567890.json

簡単にするため、ユーザー名パスワードは埋め込みました。
Pod内のContainer同士は、127.0.0.1 でアクセスできます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deploy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
    spec:
      containers:
        - name: app-backend
          image: gcr.io/project_desu/app:0.9
          ports:
            - containerPort: 3000
          env:
            - name: PORT
              value: '3000'
            - name: DATABASE_HOST
              value: 127.0.0.1
            - name: DATABASE_DATABASE
              value: hoge
            - name: DATABASE_USER_NAME
              value: name_desu
            - name: DATABASE_PASSWORD
              value: password_desu
        - image: gcr.io/cloudsql-docker/gce-proxy:1.12
          name: cloudsql-proxy
          ports:
            - containerPort: 3306
          command: ["/cloud_sql_proxy", "--dir=/cloudsql",
                    "-instances=PROJECT_NAME:asia-northeast1:INSTANCE_NAME=tcp::3306",
                    "-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:

Service を使い Pod を分ける方法

アプリケーションの数だけ Container が増えることになるため、リソースが限られている時など上記の方法を避けたい場合があります。Serviceを利用しアクセスするためには下記のように設定します。

TCPにバインドするIPアドレス 0.0.0.0 を指定することがポイントです。
これによって、Service経由のホスト名db-cluster-ip で Podにアクセス出来ます。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: db-deploy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: db
  template:
    metadata:
      labels:
        app: db
    spec:
      containers:
        - image: gcr.io/cloudsql-docker/gce-proxy:1.12
          name: cloudsql-proxy
          ports:
            - containerPort: 3306
          command: ["/cloud_sql_proxy", "--dir=/cloudsql",
                    "-instances=PROJECT_NAME:asia-northeast1:INSTANCE_NAME=tcp:0.0.0.0:3306",
                    "-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:
apiVersion: v1
kind: Service
metadata:
  name: db-cluster-ip
spec:
  type: ClusterIP
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: db