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なのでこれにもアクセスできない。
- cloud_sql_proxyが
解決策
https://istio.io/docs/tasks/traffic-management/egress/#calling-external-services-directly
によると以下の2方針で解決できる。
- Istioで外部サービスへの直接的なアクセスを実現するためには
ServiceEntry
を作成することが必要。 - 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.com
、www.googleapis.com
、CloudSQLのサーバーのそれぞれに作成する。
ServiceEntityについては以下を参照。
- https://istio.io/docs/tasks/traffic-management/egress/
- https://istio.io/docs/reference/config/istio.networking.v1alpha3/#ServiceEntry
実際のコードは以下から利用しています。 https://github.com/istio/istio/issues/6593
GCPのAPIサーバーの設定
1cat <<EOF | istioctl create -f -2apiVersion: networking.istio.io/v1alpha33kind: ServiceEntry4metadata:5 name: account-google-serviceentry-rule6spec:7 hosts:8 - accounts.google.com9 ports:10 - number: 44311 name: https12 protocol: HTTPS13EOF1415cat <<EOF | istioctl create -f -16apiVersion: networking.istio.io/v1alpha317kind: ServiceEntry18metadata:19 name: googleapis-serviceentry-rule20spec:21 hosts:22 - www.googleapis.com23 ports:24 - number: 44325 name: https26 protocol: HTTPS27EOF28
外部MySQLのIPの設定
1cat <<EOF | istioctl create -f -2apiVersion: networking.istio.io/v1alpha33kind: ServiceEntry4metadata:5 name: mysql-serviceentry-rule6spec:7 hosts:8 - MySQLサーバーのIPを書く9 ports:10 - number: 330711 name: tcp12 protocol: TCP13EOF14
Kubernetes内でMySQLサーバーにアクセスする
Kubernetes内からcloud_sql_proxy
のPodへアクセスすればMySQLサーバーにアクセスできる