サーバレスVPCアクセスとInternal LBでGAE=>GKEを内部通信にする


GAE(Google App Engine)で動いているアプリケーションから、GKE(Google Kubernetes Engine)のクラスタにいるAPIを叩くことになったのですが、インターネットを経由するのが嫌で、GCP内部に閉じたやり方をしたのでご紹介します。

構成概要

GAEのアプリケーションはスタンダード環境、GKEは限定公開クラスタになっていて、privateという名前のVPCネットワークに入っています。APIのServiceはInternal Load BalancerにしてVPC内にエンドポイントを晒し、GAEはサーバレスVPCアクセスコネクタ経由でこのVPCにアクセスしています。あとは気持ちの問題ですが、APIのIPアドレス直叩きはなんか微妙だったので、Cloud DNSでGCP内部解決用のドメインを設定しました。

GAEのアプリケーションにVPCアクセスコネクタを設定する

まずはVPCアクセスコネクタを作成します。公式のドキュメントにしたがって進めれば簡単にできます。

VPCアクセスコネクタの作成が完了したら、app.yamlに設定を追加します。公式のドキュメントにある通り、追加する設定は以下のように書きます。

# app.yaml
vpc_access_connector:
  name: projects/{PROJECT_ID}/locations/{REGION}/connectors/{CONNECTOR_NAME}

先に作成したVPCアクセスコネクタについて、PROJECT_IDREGIONCONNECTOR_NAMEを埋めて gcloud app deployコマンドでデプロイすれば完了です。

Internal Load Balancerを設定する

Serviceの種類をInternal Load Balancerにすることで、VPCネットワーク内部からのみアクセスできるようになります。難しい設定は特に必要なく、cloud.google.com/load-balancer-type: "internal"というアノテーションをつけるだけです。

apiVersion: v1
kind: Service
metadata:
  name: myapi
  annotations:
    cloud.google.com/load-balancer-type: "internal"
spec:
  type: LoadBalancer
  loadBalancerIP: {LOAD_BANANCER_IP} #最初コメントアウトしておく
  selector:
    app: myapi
  ports:
    - name: web
      port: 80
      targetPort: 8080

loadBalancerIPは作成時に自動的に割り振られるので、最初はコメントアウトしておいて、割り振られたら {LOAD_BALANCER_IP}に入れます。割り振られているかどうかは、kubectlコマンドで確認できます。割り振られると下のようにEXTERNAL-IPにVPCネットワーク内のIPアドレスが表示されます。

kubectl get svc myapi

NAME    TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)        AGE
myapi   LoadBalancer   10.0.18.117   192.168.32.55   80:32179/TCP   1m

Cloud DNSで内部通信用のドメインを設定する

ここまでで、GAEのアプリケーションからVPCネットワークに接続し、GKE上で稼働するAPIにIPアドレスでアクセスできるようになりました。上の例だと、GAEのアプリケーション内からhttp://192.168.32.55を指定すればAPIにつながる状態になっています。

ここからは気持ちの問題なのですが、このIPアドレスに内部用のDNS名を設定します。これは非常に簡単にできます。

Cloud DNSのWebコンソールを開き、ゾーンを作成ボタンからフォームを開きます。

フォームに必要情報を入力してゾーンを作成します。ゾーンのタイプを非公開にして、ネットワークには当該のVPCネットワークを指定します。非公開ネットワークのDNSなので、すでに使っているものでなければ好きなドメインを設定できます。下の例では、api.privateという名前にしました。

作成が完了すると、DNSゾーンのページが表示されます。

あとは、先ほどのIPに紐づけてAレコードを追加すれば完了です。めでたく、http://my.api.privateという名前でアクセスできるようになりました。

まとめ

この記事では、GAEからGKEに内部通信する方法をご紹介しました。

僕たちのチームでは、アプリケーションにはGAE、データ関連のバッチ処理などのためにGKE上にArgoを立てて利用しているのですが、アプリケーションからArgoのRest APIにアクセスしたい要件があり今回ご紹介した方法で実装しました。

最初は外向きにIPを公開しないといけないかもと思って認証をどうするかとかも考えていたのですが、サーバレスVPCアクセスとInternal Load Balancerのおかげで内部に閉じた作りにすることができてよかったです。

この記事がもし何かの参考になれば嬉しいです。