こんにちは。仙台オフィスの阿部です。
はじめに
弊社では、GCPを始めとしていくつかのパブリッククラウドサービスを利用しています。そのため、要件によってはパブリッククラウドサービス間での通信が必要となります。
今回の内容は、GCPのGKEのPodから他クラウドサービスへの通信が出来ずにハマった話とその解決方法です。内容的に真新しい内容ではありませんが、このブログが誰かの目に止まって少しでも役に立ってくれたら幸いです。
事象
繰り返しになりますが、GKEのPodから他パブリックサービスに設置しているDBサーバに接続出来ませんでした。 以下の状態だったといえます。
GCPに構築したVPCからはCloudVPNを利用してVPN接続します。初め、VPCとCloudVPNの設定を確認しました。GCEのインスタンスを立て、疎通確認としてGCEからDBサーバへのpingを実行したところ、正常に接続できます。GKEのPodからの接続が不可であるという状況です。
原因
事象で示した図からも分かる通り、送信元IPアドレスとサブネットのIPアドレス範囲の相違が接続不可の原因となります。GKEにおけるIPアドレスの管理については、公式の以下の記事が参考になります。
解決方法
IPマスカレードエージェントを利用します。こちらも公式ドキュメントがあります。
IPマスカレードとはIPアドレスの変換技術です。GKEにおいては、IPマスカレードエージェントを利用することでパケットの送信元IPアドレスをPodのアドレスからNodeのアドレスに変換して通信することが可能となります。 今回の環境では、ガイドに記載されたデフォルトのマスカレード以外の宛先にある宛先範囲にマッチし、マスカレードされずに通信した結果、接続不可となっていました。(gkeバージョンは1.18.16-gke.502利用)
IPマスカレードエージェントを利用した場合の通信は以下のようになります。
IPマスカレードエージェント設定方法
DaemonSet作成
以下のマニフェストからDaemonSetを作成します。
apiVersion: apps/v1 kind: DaemonSet metadata: name: ip-masq-agent namespace: kube-system spec: selector: matchLabels: k8s-app: ip-masq-agent template: metadata: labels: k8s-app: ip-masq-agent spec: hostNetwork: true containers: - name: ip-masq-agent image: gcr.io/google-containers/ip-masq-agent-amd64:v2.5.0 args: - --masq-chain=IP-MASQ # To non-masquerade reserved IP ranges by default, uncomment the line below. # - --nomasq-all-reserved-ranges securityContext: privileged: true volumeMounts: - name: config mountPath: /etc/config volumes: - name: config configMap: # Note this ConfigMap must be created in the same namespace as the # daemon pods - this spec uses kube-system name: ip-masq-agent optional: true items: # The daemon looks for its config in a YAML file at /etc/config/ip-masq-agent - key: config path: ip-masq-agent tolerations: - effect: NoSchedule operator: Exists - effect: NoExecute operator: Exists - key: "CriticalAddonsOnly" operator: "Exists"
ConfigMap作成
以下の内容を記載したファイルを作成します。ファイル名はconfigとします。
nonMasqueradeCIDRs: - 10.0.0.0/8 resyncInterval: 60s
nonMasqueradeCIDRsには、PodのIPアドレスを保持したい宛先範囲を指定します。
ConfigMapを作成します。以下ではip-masq-agentというリソース名で作成しています。
kubectl create configmap ip-masq-agent \ --from-file config \ --namespace kube-system
通信の確認
Node内に一時的なPodを立て、そのPod内からpingを実行して通信確認を行います。
kubectl run -it debug --image=alpine:latest --rm --restart=Never -- ping xx.xx.xx.xx
無事通信することができました。
Autopilotモードの場合
IPマスカレードエージェントはnamespace=kube-systemにDaemonSetを作成します。Autopilotモードで試したところ、以下のエラーが発生して作成することが出来ませんでした。公式ドキュメントの冒頭にStandardモードにのみ適用される旨のアイコンが表示されているとおり、Autopilotモードにはやはり対応していなさそうです。
Error from server (Forbidden): error when creating "ip-masq-agent.yml": daemonsets.apps is forbidden: User "xxxxx" cannot create resource "daemonsets" in API group "apps" in the namespace "kube-system": GKEAutopilot authz: the namespace "kube-system" is managed and the request's verb "create" is denied