🔎

Cloud DNS for GKE で Service Discovery

2023/01/06に公開

こんにちは。Enabling team の山本です。
Retail AI X では、Google Cloud 上で様々なサービスを稼働させており、日々、トライアルの店舗をご利用のお客様へ価値を提供しております。
この記事では、サービス ディスカバリの改善に向けた検証について紹介します。

TL;DR

  • オプションを有効にするだけ。追加サービスの install は不要!
  • Multi Cluster でも、Shared VPC でも、Private Cluster でも同じ設定。シンプルな設定!!
  • ドメインの suffix が変わる!!!

はじめに

弊社が運用するサービスの多くは、GKE を利用した構成となっています。
この blog は、比較的複雑な Network 構成におけるサービス ディスカバリの改善に向けた取り組みについて書きます。

サービス ディスカバリの改善

ご存じのとおり、サービス ディスカバリとは、名前からエンドポイントを判別する機能です。
今回の検討における前提条件は、以下のとおりです。

前提条件

  1. Security とドメイン サービスの境界を作るため、Multi Project の Multi Cluster で構成しています。
  2. Firewall や Subnet などを一元管理するため、Shared VPC を使用しています。
  3. Security の向上のため、外部 IP アドレスを持たない Private Cluster を使用しています。
  4. Production 環境であるため、GA されたサービスである必要があります。

選択肢を検討する

上記の前提条件をクリアするサービスは、以下が考えられます。

Production 環境の変更は気を遣うもので、変更による影響範囲が少ないことが望ましいですし、万が一の切り戻しも準備が必要です。
そういった諸々の事情を考慮し、今回は Cloud DNS for GKE でのサービス ディスカバリを検討します。

設定する

Cloud DNS for GKE を検証するにあたり、弊社内で実在する全てのパターンを検証します。

Case Subnet 限定公開の Google アクセス VPC
1 Default Off ---
2 Custom Off ---
3 Custom On ---
4 Default Off Shared
5 Custom Off Shared
6 Custom On Shared

今回は、この中から case 6 の Runbook を紹介します。

Cluster を作成する

gcloud beta container --project "dns-sandbox-service-a" clusters create "case6a" --zone "asia-northeast1-a" --no-enable-basic-auth --cluster-version "1.24.7-gke.900" --release-channel "regular" --machine-type "e2-medium" --image-type "COS_CONTAINERD" --disk-type "pd-balanced" --disk-size "100" --metadata disable-legacy-endpoints=true --scopes "https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly","https://www.googleapis.com/auth/trace.append" --max-pods-per-node "110" --num-nodes "1" --logging=SYSTEM,WORKLOAD --monitoring=SYSTEM --enable-private-nodes --master-ipv4-cidr "192.168.16.0/28" --enable-ip-alias --network "projects/dns-sandbox-host/global/networks/case6" --subnetwork "projects/dns-sandbox-host/regions/asia-northeast1/subnetworks/case6a" --cluster-secondary-range-name "case6a-pods" --services-secondary-range-name "case6a-services" --no-enable-intra-node-visibility --default-max-pods-per-node "110" --no-enable-master-authorized-networks --addons HorizontalPodAutoscaling,HttpLoadBalancing,GcePersistentDiskCsiDriver --enable-autoupgrade --enable-autorepair --max-surge-upgrade 1 --max-unavailable-upgrade 0 --enable-shielded-nodes --node-locations "asia-northeast1-a" --cluster-dns=clouddns --cluster-dns-scope=vpc --cluster-dns-domain=case6a --quiet

gcloud beta container --project "dns-sandbox-service-a" clusters create "case6b" --zone "asia-northeast1-a" --no-enable-basic-auth --cluster-version "1.24.7-gke.900" --release-channel "regular" --machine-type "e2-medium" --image-type "COS_CONTAINERD" --disk-type "pd-balanced" --disk-size "100" --metadata disable-legacy-endpoints=true --scopes "https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly","https://www.googleapis.com/auth/trace.append" --max-pods-per-node "110" --num-nodes "1" --logging=SYSTEM,WORKLOAD --monitoring=SYSTEM --enable-private-nodes --master-ipv4-cidr "192.168.17.0/28" --enable-ip-alias --network "projects/dns-sandbox-host/global/networks/case6" --subnetwork "projects/dns-sandbox-host/regions/asia-northeast1/subnetworks/case6b" --cluster-secondary-range-name "case6b-pods" --services-secondary-range-name "case6b-services" --no-enable-intra-node-visibility --default-max-pods-per-node "110" --no-enable-master-authorized-networks --addons HorizontalPodAutoscaling,HttpLoadBalancing,GcePersistentDiskCsiDriver --enable-autoupgrade --enable-autorepair --max-surge-upgrade 1 --max-unavailable-upgrade 0 --enable-shielded-nodes --node-locations "asia-northeast1-a" --cluster-dns=clouddns --cluster-dns-scope=vpc --cluster-dns-domain=case6b --quiet

サンプル アプリを deploy する

cat << EOF  | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-html
data:
  index.html: |
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
    html { color-scheme: light dark; }
    body { width: 35em; margin: 0 auto;
    font-family: Tahoma, Verdana, Arial, sans-serif; }
    </style>
    </head>
    <body>
    <h1>case-6-a to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>

    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>

    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-a
spec:
  selector:
    matchLabels:
      run: nginx-a
  replicas: 1
  template:
    metadata:
      labels:
        run: nginx-a
    spec:
      containers:
      - name: nginx-a
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-html-file
          mountPath: /usr/share/nginx/html
      volumes:
        - name: nginx-html-file
          configMap:
            name: nginx-html
            items:
            - key: "index.html"
              path: "index.html"
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-a
  labels:
    run: nginx-a
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: nginx-a
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-a-hl
  labels:
    run: nginx-a
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
  clusterIP: None
  selector:
    run: nginx-a
EOF
cat << EOF  | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-html
data:
  index.html: |
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
    html { color-scheme: light dark; }
    body { width: 35em; margin: 0 auto;
    font-family: Tahoma, Verdana, Arial, sans-serif; }
    </style>
    </head>
    <body>
    <h1>case-6-b to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>

    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>

    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-b
spec:
  selector:
    matchLabels:
      run: nginx-b
  replicas: 1
  template:
    metadata:
      labels:
        run: nginx-b
    spec:
      containers:
      - name: nginx-b
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-html-file
          mountPath: /usr/share/nginx/html
      volumes:
        - name: nginx-html-file
          configMap:
            name: nginx-html
            items:
            - key: "index.html"
              path: "index.html"
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-b
  labels:
    run: nginx-b
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: nginx-b
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-b-hl
  labels:
    run: nginx-b
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
  clusterIP: None
  selector:
    run: nginx-b
EOF

名前解決してみる

yamamoto_daisuke@cloudshell:~ (dns-sandbox-service-b)$ k exec -it nginx-c-d7fd897cc-rwvhd bash
root@nginx-c-d7fd897cc-rwvhd:/# nslookup nginx-c-hl
Server:         169.254.169.254
Address:        169.254.169.254#53

Non-authoritative answer:
Name:   nginx-c-hl.default.svc.case6c
Address: 172.24.0.8

root@nginx-c-d7fd897cc-rwvhd:/# curl nginx-c-hl.default.svc.case6c
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>case-6-c to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@nginx-c-d7fd897cc-rwvhd:/# curl nginx-b-hl.default.svc.case6b
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>case-6-b to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@nginx-c-d7fd897cc-rwvhd:/# curl nginx-a-hl.default.svc.case6a
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>case-6-a to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@nginx-c-d7fd897cc-rwvhd:/#

まとめ

それぞれの case の設定が影響しないように、Project / VPC / Cluster のスクラップ&ビルドを 6 回繰り返したのが疲れました、、
個人的には、ASM などに比べシンプルに Service Discovery を実現できるサービスだと思います。
FYI,
注意点として、(この blog を書いている時点では)Fleet API を使う場合、Cloud DNS for GKE は、使用できないようです。
この条件に当てはまる場合は、ASM や MCS などを利用すると良いでしょう。
これらの詳しいユースケースを知りたい場合は、Google Cloud の Customer Engineer が説明している Webinar がとても参考になります。

Discussion