GKE + Istioな環境でCloudSQLを使うための設定

公開日: 2018年7月5日GitHub

前提

  • CloudSQLにアクセスするためにはcloud_sql_proxyを用いてTCP接続のproxyプロセスを立ち上げる必要がある
  • 一方でIstioを利用しているとき、すべてのネットワークアクセスはIstioによってInterceptされてしまう
    • これはKubernetes内のクラスタ内のIPだけでなく、外部サーバーを利用するときも同様の挙動をする

By default, Istio-enabled services are unable to access URLs outside of the cluster because iptables is used in the pod to transparently redirect all outbound traffic to the sidecar proxy, which only handles intra-cluster destinations.

引用元

何が問題か

  • cloud_sql_proxyは、指定されたサービスアカウントの認証キーを使ってaccounts.google.comなどにアクセスして認証をした上で、CloudSQLのサーバーとコネクションを確立する。
  • Istioがcloud_sql_proxyの外部アクセスをinterceptするのが問題
    • cloud_sql_proxyがaccounts.google.comなどにアクセスできないので、そもそも認証・認可されない
    • 認証・認可されても、CloudSQLのサーバー自体も外部IPなのでこれにもアクセスできない。

解決策

https://istio.io/docs/tasks/traffic-management/egress/#calling-external-services-directly

によると以下の2方針で解決できる。

  1. Istioで外部サービスへの直接的なアクセスを実現するためにはServiceEntryを作成することが必要。
  2. Istioでインストール時にinterceptするIPアドレスをcidrで指定し、外部IPへのアクセスをinterceptしないようにする

今回は前者の方針をとった。

実装

以下のように設定すると無事にKubernetes + Istioの環境でCloudSQLを使える。

cloud_sql_proxyのPodの作成

https://github.com/GoogleCloudPlatform/cloudsql-proxy/blob/master/Kubernetes.md

を参照し、PodとServiceを作成する。

ServiceEntityの作成

以下、ServiceEntityをaccounts.google.comwww.googleapis.com、CloudSQLのサーバーのそれぞれに作成する。

ServiceEntityについては以下を参照。

実際のコードは以下から利用しています。 https://github.com/istio/istio/issues/6593

GCPのAPIサーバーの設定

1cat <<EOF | istioctl create -f -
2apiVersion: networking.istio.io/v1alpha3
3kind: ServiceEntry
4metadata:
5 name: account-google-serviceentry-rule
6spec:
7 hosts:
8 - accounts.google.com
9 ports:
10 - number: 443
11 name: https
12 protocol: HTTPS
13EOF
14
15cat <<EOF | istioctl create -f -
16apiVersion: networking.istio.io/v1alpha3
17kind: ServiceEntry
18metadata:
19 name: googleapis-serviceentry-rule
20spec:
21 hosts:
22 - www.googleapis.com
23 ports:
24 - number: 443
25 name: https
26 protocol: HTTPS
27EOF
28

外部MySQLのIPの設定

1cat <<EOF | istioctl create -f -
2apiVersion: networking.istio.io/v1alpha3
3kind: ServiceEntry
4metadata:
5 name: mysql-serviceentry-rule
6spec:
7 hosts:
8 - MySQLサーバーのIPを書く
9 ports:
10 - number: 3307
11 name: tcp
12 protocol: TCP
13EOF
14

Kubernetes内でMySQLサーバーにアクセスする

Kubernetes内からcloud_sql_proxyのPodへアクセスすればMySQLサーバーにアクセスできる

This site uses Google Analytics.
source code