區域 Cloud Service Mesh

透過區域隔離功能,連線至 Cloud Service Mesh 控制層特定區域的用戶端,只能存取該區域內的資源。同樣地,特定地區內的 API 資源只能參照該地區的其他資源。

區域 Cloud Service Mesh 有下列限制:

  • 不支援 Istio API。您無法搭配使用 Kubernetes 和 Istio API,透過地區 Traffic Director 進行作業。這個搶先版僅支援 Google Cloud API。
  • 全球服務路徑 API 的現有注意事項和限制適用於此。
  • 支援 xdSTP 命名配置的最低 Envoy 版本為 v1.31.1。
  • 不支援 Gateway for Mesh API
  • 最低 gRPC 版本為 v1.65。
  • 系統僅支援下列地區:

    africa-south1
    asia-east1
    asia-east2
    asia-northeast1
    asia-northeast2
    asia-northeast3
    asia-south1
    asia-south2
    asia-southeast1
    asia-southeast2
    australia-southeast1
    australia-southeast2
    europe-central2
    europe-north1
    europe-north2
    europe-southwest1
    europe-west10
    europe-west12
    europe-west1
    europe-west2
    europe-west3
    europe-west4
    europe-west6
    europe-west8
    europe-west9
    me-central1
    me-central2
    me-west1
    northamerica-northeast1
    northamerica-northeast2
    northamerica-south1
    southamerica-east1
    southamerica-west1
    us-central1
    us-east1
    us-east4
    us-east5
    us-south1
    us-west1
    us-west2
    us-west3
    us-west4
    

定價

這項功能正式推出後,每個支援區域性 Cloud Service Mesh 的地區都會有區域性 SKU。目前定價與全球相同。

為 Cloud Service Mesh 準備 xDS 用戶端

Compute VM Envoy xDS

手動

手動步驟是以「使用手動 Envoy 部署功能設定 VM」為基礎。主要差異在於 ENVOY_CONTROL_PLANE_REGION 會設定並注入至啟動程序。

  1. 建立執行個體範本:

    gcloud compute instance-templates create td-vm-templategcloud compute instance-templates create td-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=http-td-tag,http-server,https-server \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata=startup-script='#! /usr/bin/env bash
    
    # Set variables
    export ENVOY_CONTROL_PLANE_REGION="us-central1"
    export ENVOY_USER="envoy"
    export ENVOY_USER_UID="1337"
    export ENVOY_USER_GID="1337"
    export ENVOY_USER_HOME="/opt/envoy"
    export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml"
    export ENVOY_PORT="15001"
    export ENVOY_ADMIN_PORT="15000"
    export ENVOY_TRACING_ENABLED="false"
    export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt"
    export ENVOY_ACCESS_LOG="/dev/stdout"
    export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)"
    export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml"
    export GCE_METADATA_SERVER="169.254.169.254/32"
    export INTERCEPTED_CIDRS="*"
    export GCP_PROJECT_NUMBER=PROJECT_NUMBER
    export VPC_NETWORK_NAME=mesh:sidecar-mesh
    export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4)
    
    # Create system user account for Envoy binary
    sudo groupadd ${ENVOY_USER} \
      --gid=${ENVOY_USER_GID} \
      --system
    sudo adduser ${ENVOY_USER} \
      --uid=${ENVOY_USER_UID} \
      --gid=${ENVOY_USER_GID} \
      --home=${ENVOY_USER_HOME} \
      --disabled-login \
      --system
    # Download and extract the Cloud Service Mesh tar.gz file
    cd ${ENVOY_USER_HOME}
    sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \
      -C bootstrap_template.yaml \
      --strip-components 1
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \
      -C iptables.sh \
      --strip-components 1
    sudo rm traffic-director-xdsv3.tar.gz
    
    # Generate Envoy bootstrap configuration
    cat "${BOOTSTRAP_TEMPLATE}" \
      | sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \
      | sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \
      | sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \
      | sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \
      | sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \
      | sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \
      | sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \
      | sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \
      | sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \
      | sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \
      | sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \
      | sudo tee "${ENVOY_CONFIG}"
    
    # Install Envoy binary
    wget -O envoy_key https://apt.envoyproxy.io/signing.key
    cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg
    echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list
    sudo apt-get update
    sudo apt-get install envoy
    
    # Run Envoy as systemd service
    sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \
      --working-directory=${ENVOY_USER_HOME} --unit=envoy.service \
      bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee"
    
    # Configure iptables for traffic interception and redirection
    sudo ${ENVOY_USER_HOME}/iptables.sh \
      -p "${ENVOY_PORT}" \
      -u "${ENVOY_USER_UID}" \
      -g "${ENVOY_USER_GID}" \
      -m "REDIRECT" \
      -i "${INTERCEPTED_CIDRS}" \
      -x "${GCE_METADATA_SERVER}"
    

Compute VM gRPC xDS

與全域 Cloud Service Mesh 類似,gRPC 用戶端也需要設定啟動程序,才能瞭解如何連線至區域 Cloud Service Mesh。

您可以使用 gRPC 啟動程序產生器產生這個啟動程序。如要設為使用區域 Cloud Service Mesh,請指定新旗標:--xds-server-region

在本範例中,將 xds-server-region 設為 us-central1 會自動決定 Cloud Service Mesh 的地區端點:trafficdirector.us-central1.rep.googleapis.com:443.

K8s 手動 Envoy 插入

手動步驟是以「使用手動 Envoy 插入來設定 Google Kubernetes Engine Pod」為基礎。不過,您只需要修改手動 Pod 插入部分。

  1. 將控制層從全域變更為區域:

    wget -q -O - https://storage.googleapis.com/traffic-director/demo/trafficdirector_client_new_api_sample_xdsv3.yaml
    
    sed -i "s/PROJECT_NUMBER/PROJECT_NUMBER/g" trafficdirector_client_new_api_sample_xdsv3.yaml
    
    sed -i "s/MESH_NAME/MESH_NAME/g" trafficdirector_client_new_api_sample_xdsv3.yaml
    
    sed -i "s|trafficdirector.googleapis.com|trafficdirector.${REGION}.rep.googleapis.com|g" trafficdirector_client_new_api_sample_xdsv3.yaml
    
    sed -i "s|gcr.io/google-containers/busybox|busybox:stable|g" trafficdirector_client_new_api_sample_xdsv3.yaml
    
    1. 套用變更:

      kubectl apply -f trafficdirector_client_new_api_sample_xdsv3.yaml
        ```
      

設定指南

本節涵蓋五種獨立的設定和部署模式。這些都是現有全球服務路徑 API 設定指南的區域化版本。

使用區域性 GRPCRoute 和區域性 Cloud Service Mesh 設定無 Proxy gRPC 服務

本節說明如何使用區域性 Cloud Service Mesh 和區域性 GRPCRoute 資源,設定無 Proxy gRPC 服務網格。

為方便起見,請儲存您執行設定的 Google Cloud 專案編號,這樣一來,本指南中的所有範例都可以複製並貼到指令列:

export PROJECT="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-a"

PROJECT_NUMBER 替換為專案編號。

您可以視需要替換下列項目:

  • us-central1 改為您要使用的其他區域。
  • us-central1-a 改為您要使用的其他區域。
  • default,並使用不同的 VPC_NAME。

網狀設定

無 Proxy gRPC 應用程式連線至 xds://hostname 時,gRPC 用戶端程式庫會與 Cloud Service Mesh 建立連線,取得轉送主機名稱要求所需的轉送設定。

  1. 建立網格規格並儲存在 mesh.yaml 檔案中:

    cat <<EOF > mesh.yaml
    name: grpc-mesh
    EOF
    
  2. 使用 mesh.yaml 規格建立網格:

    gcloud network-services meshes import grpc-mesh \
        --source=mesh.yaml \
        --location=${REGION}
    

    建立區域網格後,Cloud Service Mesh 即可提供設定。不過,由於尚未定義任何服務,因此設定是空白的。

gRPC 服務設定

為示範用途,您將建立具有自動調度 VM 資源的區域後端服務 (使用代管執行個體群組 - MIG),透過通訊埠 50051 上的 gRPC 通訊協定提供 hello world 服務。

  1. 建立 Compute Engine VM 執行個體範本,其中包含在 50051 連接埠公開的 helloworld gRPC 服務:

    gcloud compute instance-templates create grpc-td-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=allow-health-checks \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata-from-file=startup-script=<(echo '#! /bin/bash
    set -e
    cd /root
    sudo apt-get update -y
    sudo apt-get install -y openjdk-11-jdk-headless
    curl -L https://github.com/grpc/grpc-java/archive/v1.38.0.tar.gz | tar -xz
    cd grpc-java-1.38.0/examples/example-hostname
    ../gradlew --no-daemon installDist
    # Server listens on 50051
    sudo systemd-run ./build/install/hostname-server/bin/hostname-server')
    
  2. 依據範本建立 MIG:

    gcloud compute instance-groups managed create grpc-td-mig-us-central1 \
      --zone=${ZONE} \
      --size=2 \
      --template=grpc-td-vm-template
    
  3. 為 gRPC 服務設定具名連接埠。這是 gRPC 服務設定為監聽要求的通訊埠。

    gcloud compute instance-groups set-named-ports grpc-td-mig-us-central1 \
      --named-ports=grpc-helloworld-port:50051 \
      --zone=${ZONE}
    

    在本範例中,通訊埠為 50051。

  4. 建立 gRPC 健康狀態檢查。

    gcloud compute health-checks create grpc grpc-helloworld-health-check \
      --use-serving-port --region=${REGION}
    

    服務必須實作 gRPC 健康狀態檢查通訊協定,gRPC 健康狀態檢查才能正常運作。詳情請參閱「建立健康狀態檢查」。

  5. 建立防火牆規則,允許傳入的健康狀態檢查連線抵達您網路中的執行個體:

    gcloud compute firewall-rules create grpc-vm-allow-health-checks \
      --network default --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \
      --target-tags allow-health-checks \
      --rules tcp:50051
    
  6. 使用 INTERNAL_SELF_MANAGED 負載平衡機制建立地區性後端服務,並將健康狀態檢查和先前建立的代管執行個體群組新增至後端服務。系統會使用指定通訊埠名稱中的通訊埠,連線至代管執行個體群組中的 VM。

    gcloud compute backend-services create grpc-helloworld-service \
        --load-balancing-scheme=INTERNAL_SELF_MANAGED \
        --protocol=GRPC \
        --port-name=grpc-helloworld-port \
      --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/grpc-helloworld-health-check" \
        --region=${REGION}
    
  7. 將代管執行個體群組新增至 BackendService

    gcloud compute backend-services add-backend grpc-helloworld-service \
      --instance-group=grpc-td-mig-us-central1 \
      --instance-group-zone=${ZONE} \
      --region=${REGION}
    

使用區域 GRPCRoute 設定路徑

此時,區域網格和 gRPC 伺服器服務已設定完成。現在您可以設定必要的路徑。

  1. 建立區域 GRPCRoute 規格,並儲存在 grpc_route.yaml 檔案中:

    cat <<EOF > grpc_route.yaml
    name: helloworld-grpc-route
    hostnames:
    - helloworld-gce
    meshes:
    - projects/${PROJECT_NUMBER}/locations/${REGION}/meshes/grpc-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/${PROJECT_NUMBER}/locations/${REGION}/backendServices/grpc-helloworld-service
    EOF
    
  2. 使用 grpc_route.yaml 規格建立區域 GRPCRoute:

    gcloud network-services grpc-routes import helloworld-grpc-route \
        --source=grpc_route.yaml \
        --location=${REGION}
    

    Cloud Service Mesh 現在已設定為指定服務進行負載平衡,其為代管執行個體群組後端間的 gRPC 路由所指定。

建立 gRPC 用戶端服務

如要驗證設定,請使用無 Proxy 的 gRPC 資料平面例項化用戶端應用程式。這個應用程式必須在啟動程序檔案中指定網格的名稱。

設定完成後,這個應用程式就能使用 xds:///helloworld-gce 服務 URI,將要求傳送至與 helloworld-gce 相關聯的執行個體或端點。

在下列範例中,請使用 grpcurl 工具測試 gRPC 服務。

  1. 建立用戶端 VM:

    gcloud compute instances create grpc-client \
      --zone=${ZONE}\
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata-from-file=startup-script=<(echo '#! /bin/bash
    set -ex
    export PROJECT=PROJECT_NUMBER
    export REGION=us-central1
    export GRPC_XDS_BOOTSTRAP=/run/td-grpc-bootstrap.json
    echo export GRPC_XDS_BOOTSTRAP=$GRPC_XDS_BOOTSTRAP | sudo tee /etc/profile.d/grpc-xds-bootstrap.sh
    curl -L https://storage.googleapis.com/traffic-director/td-grpc-bootstrap-0.18.0.tar.gz | tar -xz
    ./td-grpc-bootstrap-0.18.0/td-grpc-bootstrap --config-mesh=grpc-mesh --xds-server-uri=trafficdirector.${REGION}.rep.googleapis.com:443 --gcp-project-number=${PROJECT} | sudo tee $GRPC_XDS_BOOTSTRAP
    sudo sed -i "s|\"authorities\": {|\"authorities\": {\n    \"traffic-director.${REGION}.xds.googleapis.com\": {\"xds_servers\":[{\"server_uri\": \"trafficdirector.${REGION}.rep.googleapis.com:443\", \"channel_creds\": [ { \"type\": \"google_default\" } ], \"server_features\": [ \"xds_v3\", \"ignore_resource_deletion\" ]}], \"client_listener_resource_name_template\": \"xdstp://traffic-director.${REGION}.xds.googleapis.com/envoy.config.listener.v3.Listener/${PROJECT}/mesh:grpc-mesh/%s\"},|g" $GRPC_XDS_BOOTSTRAP
    sudo sed -i "s|\"client_default_listener_resource_name_template\": \"xdstp://traffic-director-global.xds.googleapis.com|\"client_default_listener_resource_name_template\": \"xdstp://traffic-director.${REGION}.xds.googleapis.com|g" $GRPC_XDS_BOOTSTRAP')
    

設定環境變數和啟動檔案

用戶端應用程式需要啟動程序設定檔。上一節中的啟動指令碼會設定 GRPC_XDS_BOOTSTRAP 環境變數,並使用輔助指令碼產生啟動程序檔案。產生的啟動程序檔案中的 TRAFFICDIRECTOR_GCP_PROJECT_NUMBER 和區域值,是從中繼資料伺服器取得,該伺服器瞭解 Compute Engine VM 執行個體的這些詳細資料。

您可以使用 -gcp-project-number 選項,手動將這些值提供給輔助指令碼。您必須使用 -config-mesh-experimental 選項,提供與網格資源相符的網格名稱。

  1. 如要驗證設定,請登入用戶端:

    gcloud compute ssh grpc-client --zone=${ZONE}
    
  2. 下載並安裝 grpcurl 工具:

    curl -L https://github.com/fullstorydev/grpcurl/releases/download/v1.9.3/grpcurl_1.9.3_linux_x86_64.tar.gz | tar -xz
    
  3. 使用 grpcurl 工具,並將 xds:///helloworld-gce 設為服務 URI,helloworld.Greeter/SayHello 設為要叫用的服務名稱和方法。

    ./grpcurl --plaintext \
      -d '{"name": "world"}' \
      xds:///helloworld-gce helloworld.Greeter/SayHello
    

    SayHello 方法的參數是透過 -d 選項傳遞。

    您應該會看到類似以下的輸出內容,其中 INSTANCE_NAME 是 VM 執行個體的名稱:

    Greeting: Hello world, from INSTANCE_HOSTNAME
    

這會驗證無 Proxy gRPC 用戶端是否已成功連線至 Cloud Service Mesh,並使用 xDS 名稱解析器瞭解 helloworld-gce 服務的後端。用戶端將要求傳送至其中一個服務後端,不必瞭解 IP 位址或執行 DNS 解析。

使用地區 HTTPRoute 和地區 Mesh,為 HTTP 服務設定 Envoy 補充代理程式設定

本節說明如何使用區域網格和區域 HTTPRoute 資源,設定以 Envoy Proxy 為基礎的服務網格。

為方便起見,請儲存您執行設定的 Google Cloud 專案編號,這樣一來,本指南中的所有範例都可以複製並貼到指令列:

export PROJECT_ID="PROJECT_ID"
export PROJECT="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-a"

請替換下列項目:

  • PROJECT_ID 為您的專案 ID。
  • PROJECT_NUMBER 改成您的專案編號。

您可以視需要替換下列項目:

  • us-central1 改為您要使用的其他區域。
  • us-central1-a 改為您要使用的其他區域。

網狀設定

補充 Envoy Proxy 會從 Cloud Service Mesh 接收服務轉送設定。Sidecar 會顯示區域網格資源的名稱,以識別設定的特定服務網格。從 Cloud Service Mesh 收到的路由設定,會根據 Route 資源中設定的要求參數(例如主機名稱或標頭),將通過 Sidecar Proxy 的流量導向各種區域後端服務。

請注意,網格名稱是 Sidecar Proxy 用來要求與這個網格相關聯設定的金鑰。

  1. 建立區域網格規格,並儲存在 mesh.yaml 檔案中:

    cat <<EOF > mesh.yaml
    name: sidecar-mesh
    EOF
    

    如未指定,攔截通訊埠預設為 15001。

  2. 使用 mesh.yaml 規格建立區域網格:

    gcloud network-services meshes import sidecar-mesh \
        --source=mesh.yaml \
        --location=${REGION}
    

    建立區域網格後,Cloud Service Mesh 即可提供設定。不過,由於尚未定義任何服務,設定會是空白。

HTTP 伺服器設定

為進行示範,您將建立地區性後端服務,並使用代管執行個體群組 (MIG) 自動調度 VM 資源,透過通訊埠 80 上的 gRPC 協定提供「hello world」。

  1. 建立 Compute Engine VM 執行個體範本,其中包含在通訊埠 80 上公開的 helloworld HTTP 服務:

    gcloud compute instance-templates create td-httpd-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=http-td-server \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata=startup-script="#! /bin/bash
    
    sudo apt-get update -y
    sudo apt-get install apache2 -y
    sudo service apache2 restart
    echo '<!doctype html><html><body><h1>'\`/bin/hostname\`'</h1></body></html>' | sudo tee /var/www/html/index.html"
    
  2. 依據範本建立 MIG:

    gcloud compute instance-groups managed create http-td-mig-us-central1 \
      --zone=${ZONE} \
      --size=2 \
      --template=td-httpd-vm-template
    
  3. 建立健康狀態檢查:

    gcloud compute health-checks create http http-helloworld-health-check --region=${REGION}
    
  4. 建立防火牆規則,允許傳入的健康狀態檢查連線抵達您網路中的執行個體:

    gcloud compute firewall-rules create http-vm-allow-health-checks \
      --network default --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \
      --target-tags http-td-server \
      --rules tcp:80
    
  5. 使用 INTERNAL_SELF_MANAGED 的負載平衡機制建立區域後端服務

    gcloud compute backend-services create http-helloworld-service \
        --load-balancing-scheme=INTERNAL_SELF_MANAGED \
        --protocol=HTTP \
    --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/http-helloworld-health-check" \
        --region=${REGION}
    
  6. 將健康狀態檢查和代管或非代管執行個體群組新增至後端服務:

    gcloud compute backend-services add-backend http-helloworld-service \
      --instance-group=http-td-mig-us-central1 \
      --instance-group-zone=${ZONE} \
      --region=${REGION}
    

    本範例會使用代管執行個體群組和 Compute Engine VM 範本,執行先前建立的 HTTP 服務範例。

使用地區性 HTTPRoute 設定轉送

網格資源和 HTTP 伺服器已設定完成。您現在可以使用 HTTPRoute 資源,將主機名稱與後端服務建立關聯,藉此連結這些服務。

  1. 建立 HTTPRoute 規格,並儲存為 http_route.yaml:

    cat <<EOF > http_route.yaml
    name: helloworld-http-route
    hostnames:
    - helloworld-gce
    meshes:
    - projects/${PROJECT_NUMBER}/locations/${REGION}/meshes/sidecar-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/${PROJECT_NUMBER}/locations/${REGION}/backendServices/http-helloworld-service
    EOF
    
  2. 使用 http_route.yaml 規格建立 HTTPRoute:

    gcloud network-services http-routes import helloworld-http-route \
        --source=http_route.yaml \
        --location=${REGION}
    

    Cloud Service Mesh 現在已設定為指定 VIP 進行負載平衡,其為代管執行個體群組後端間的 HTTPRoute 所指定。

使用 Envoy Sidecar 建立 HTTP 用戶端

在本節中,您會使用 Envoy 補充 Proxy 例項化用戶端 VM,以要求稍早建立的 Cloud Service Mesh 設定。請注意,Google Cloud CLI 指令中的 mesh 參數會參照先前建立的網格資源。

gcloud compute instance-templates create td-vm-template \
  --scopes=https://www.googleapis.com/auth/cloud-platform \
  --tags=http-td-tag,http-server,https-server \
  --image-family=debian-11 \
  --image-project=debian-cloud \
  --metadata=startup-script='#! /usr/bin/env bash

# Set variables
export ENVOY_CONTROL_PLANE_REGION="us-central1"
export ENVOY_USER="envoy"
export ENVOY_USER_UID="1337"
export ENVOY_USER_GID="1337"
export ENVOY_USER_HOME="/opt/envoy"
export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml"
export ENVOY_PORT="15001"
export ENVOY_ADMIN_PORT="15000"
export ENVOY_TRACING_ENABLED="false"
export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt"
export ENVOY_ACCESS_LOG="/dev/stdout"
export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)"
export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml"
export GCE_METADATA_SERVER="169.254.169.254/32"
export INTERCEPTED_CIDRS="*"
export GCP_PROJECT_NUMBER=PROJECT_NUMBER
export VPC_NETWORK_NAME=mesh:sidecar-mesh
export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4)

# Create system user account for Envoy binary
sudo groupadd ${ENVOY_USER} \
  --gid=${ENVOY_USER_GID} \
  --system
sudo adduser ${ENVOY_USER} \
  --uid=${ENVOY_USER_UID} \
  --gid=${ENVOY_USER_GID} \
  --home=${ENVOY_USER_HOME} \
  --disabled-login \
  --system
# Download and extract the Cloud Service Mesh tar.gz file
cd ${ENVOY_USER_HOME}
sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz
sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \
  -C bootstrap_template.yaml \
  --strip-components 1
sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \
  -C iptables.sh \
  --strip-components 1
sudo rm traffic-director-xdsv3.tar.gz

# Generate Envoy bootstrap configuration
cat "${BOOTSTRAP_TEMPLATE}" \
  | sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \
  | sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \
  | sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \
  | sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \
  | sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \
  | sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \
  | sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \
  | sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \
  | sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \
  | sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \
  | sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \
  | sudo tee "${ENVOY_CONFIG}"

# Install Envoy binary
wget -O envoy_key https://apt.envoyproxy.io/signing.key
cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list
sudo apt-get update
sudo apt-get install envoy

# Run Envoy as systemd service
sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \
  --working-directory=${ENVOY_USER_HOME} --unit=envoy.service \
  bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee"

# Configure iptables for traffic interception and redirection
sudo ${ENVOY_USER_HOME}/iptables.sh \
  -p "${ENVOY_PORT}" \
 -u "${ENVOY_USER_UID}" \
  -g "${ENVOY_USER_GID}" \
  -m "REDIRECT" \
  -i "${INTERCEPTED_CIDRS}" \
  -x "${GCE_METADATA_SERVER}"
'

gcloud compute instances create td-vm-client \
  --zone=${ZONE} \
  --source-instance-template td-vm-template
  1. 登入建立的 VM:

    gcloud compute ssh td-vm-client --zone=${ZONE}
    
  2. 確認與所建立測試服務的 HTTP 連線:

    curl -H "Host: helloworld-gce" http://10.0.0.1/
    

    指令會從代管執行個體群組中的其中一個 VM 傳回回應,並在主控台中顯示該 VM 的主機名稱。

使用區域性 TCPRoute 設定 TCP 服務

這個設定流程與使用 HTTP 服務設定 Envoy Proxy 非常相似,但後端服務提供的是 TCP 服務,且系統會根據 TCP/IP 參數 (而非 HTTP 通訊協定) 進行路由。

為方便起見,請儲存您執行設定的 Google Cloud 專案編號,這樣本指南中的所有範例都可以複製並貼到指令列:

export PROJECT_ID="PROJECT_ID"
export PROJECT="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-a"

請替換下列項目:

  • PROJECT_ID 為您的專案 ID。
  • PROJECT_NUMBER 改成您的專案編號。

您可以視需要替換下列項目:

  • us-central1 改為您要使用的其他區域。
  • us-central1-a 改為您要使用的其他區域。

網狀設定

  1. 建立區域網格規格,並儲存在 mesh.yaml 檔案中:

    cat <<EOF > mesh.yaml
    name: sidecar-mesh
    EOF
    
  2. 使用 mesh.yaml 規格建立區域網格:

    gcloud network-services meshes import sidecar-mesh \
        --source=mesh.yaml \
        --location=${REGION}
    

TCP 伺服器設定

為示範用途,您將建立地區後端服務,並使用代管執行個體群組 (MIG) 自動調度 VM 資源,透過通訊埠 10000 上的 gRPC 協定提供「Hello World」服務。

  1. 使用 netcat 公用程式,在連接埠 10000 上建立具有測試服務的 Compute Engine VM 執行個體範本:

    gcloud compute instance-templates create tcp-td-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=allow-health-checks \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata=startup-script="#! /bin/bash
    sudo apt-get update -y
    sudo apt-get install netcat -y
    while true;
      do echo 'Hello from TCP service' | nc -l -s 0.0.0.0 -p 10000;
    done &"
    
  2. 依據範本建立 MIG:

    gcloud compute instance-groups managed create tcp-td-mig-us-central1 \
      --zone=${ZONE} \
      --size=1 \
      --template=tcp-td-vm-template
    
  3. 將所建立代管執行個體群組的具名通訊埠設為 port 10000

    gcloud compute instance-groups set-named-ports tcp-td-mig-us-central1 \
      --zone=${ZONE} --named-ports=tcp:10000
    
  4. 建立地區健康狀態檢查:

    gcloud compute health-checks create tcp tcp-helloworld-health-check --port 10000 --region=${REGION}
    
  5. 建立防火牆規則,允許傳入的健康狀態檢查連線抵達您網路中的執行個體:

    gcloud compute firewall-rules create tcp-vm-allow-health-checks \
      --network default --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \
      --target-tags allow-health-checks \
      --rules tcp:10000
    
  6. 使用「INTERNAL_SELF_MANAGED」負載平衡機制建立區域後端服務,並在後端服務新增健康狀態檢查和代管或非代管執行個體群組。

    gcloud compute backend-services create tcp-helloworld-service \
        --region=${REGION} \
        --load-balancing-scheme=INTERNAL_SELF_MANAGED \
        --protocol=TCP \
        --port-name=tcp \
        --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/tcp-helloworld-health-check"
    
  7. 將 MIG 新增至 BackendService:

    gcloud compute backend-services add-backend tcp-helloworld-service \
      --instance-group tcp-td-mig-us-central1 \
      --instance-group-zone=${ZONE} \
      --region=${REGION}
    

使用區域性 TCPRoute 設定轉送

  1. 建立 TCPRoute 規格並儲存至 tcp_route.yaml 檔案:

    cat <<EOF > tcp_route.yaml
    name: helloworld-tcp-route
    meshes:
    - projects/$PROJECT_NUMBER/locations/$REGION/meshes/sidecar-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/$PROJECT_NUMBER/locations/$REGION/backendServices/tcp-helloworld-service
      matches:
      - address: '10.0.0.1/32'
        port: '10000'
    EOF
    
  2. 使用 tcp_route.yaml 規格建立 TCPRoute:

    gcloud network-services tcp-routes import helloworld-tcp-route \
        --source=tcp_route.yaml \
        --location=${REGION}
    

使用 Envoy Sidecar 建立 TCP 用戶端

  1. 建立已連線至 Cloud Service Mesh 的 Envoy VM:

    gcloud compute instance-templates create td-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=http-td-tag,http-server,https-server \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata=startup-script='#! /usr/bin/env bash
    
    # Set variables
    export ENVOY_CONTROL_PLANE_REGION="us-central1"
    export ENVOY_USER="envoy"
    export ENVOY_USER_UID="1337"
    export ENVOY_USER_GID="1337"
    export ENVOY_USER_HOME="/opt/envoy"
    export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml"
    export ENVOY_PORT="15001"
    export ENVOY_ADMIN_PORT="15000"
    export ENVOY_TRACING_ENABLED="false"
    export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt"
    export ENVOY_ACCESS_LOG="/dev/stdout"
    export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)"
    export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml"
    export GCE_METADATA_SERVER="169.254.169.254/32"
    export INTERCEPTED_CIDRS="*"
    export GCP_PROJECT_NUMBER=PROJECT_NUMBER
    export VPC_NETWORK_NAME=mesh:sidecar-mesh
    
    export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4)
    
    # Create system user account for Envoy binary
    sudo groupadd ${ENVOY_USER} \
      --gid=${ENVOY_USER_GID} \
      --system
    sudo adduser ${ENVOY_USER} \
      --uid=${ENVOY_USER_UID} \
      --gid=${ENVOY_USER_GID} \
      --home=${ENVOY_USER_HOME} \
      --disabled-login \
      --system
    # Download and extract the Cloud Service Mesh tar.gz file
    cd ${ENVOY_USER_HOME}
    sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \
      -C bootstrap_template.yaml \
      --strip-components 1
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \
      -C iptables.sh \
      --strip-components 1
    sudo rm traffic-director-xdsv3.tar.gz
    
    # Generate Envoy bootstrap configuration
    cat "${BOOTSTRAP_TEMPLATE}" \
      | sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \
      | sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \
      | sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \
      | sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \
      | sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \
      | sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \
      | sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \
      | sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \
      | sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \
      | sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \
      | sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \
      | sudo tee "${ENVOY_CONFIG}"
    
    # Install Envoy binary
    wget -O envoy_key https://apt.envoyproxy.io/signing.key
    cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg
    echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list
    sudo apt-get update
    sudo apt-get install envoy
    
    # Run Envoy as systemd service
    sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \
      --working-directory=${ENVOY_USER_HOME} --unit=envoy.service \
      bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee"
    
    # Configure iptables for traffic interception and redirection
    sudo ${ENVOY_USER_HOME}/iptables.sh \
      -p "${ENVOY_PORT}" \
    -u "${ENVOY_USER_UID}" \
      -g "${ENVOY_USER_GID}" \
      -m "REDIRECT" \
      -i "${INTERCEPTED_CIDRS}" \
      -x "${GCE_METADATA_SERVER}"
    '
    
    gcloud compute instances create td-vm-client \
      --zone=${ZONE} \
      --source-instance-template td-vm-template
    
  2. 登入建立的 VM:

    gcloud compute ssh td-vm-client --zone=${ZONE}
    
  3. 確認與所建立測試服務的連線:

    curl 10.0.0.1:10000 --http0.9 -v
    

    您應該會看到傳回的文字 Hello from TCP service,以及在遠端 VM 上執行的 netcat 服務傳回的任何文字。

主專案中的區域網格設定

將專案指定為主專案。只要服務帳戶有權在這個專案中建立/更新/刪除網格,就能控制附加至這個專案區域網格的路由設定。

  1. 定義範例中會用到的變數:

    export REGION="us-central1"
    

    您可以選擇將 us-central1 替換為要使用的其他區域。

  2. 建立網格規格並儲存在 mesh.yaml 檔案中:

    cat <<EOF > mesh.yaml
    name: shared-mesh
    EOF
    
  3. 在這個專案中定義網格資源,並設定必要設定:

    gcloud network-services meshes import shared-mesh \
        --source=mesh.yaml \
        --location=${REGION}
    

    請記下這個網格資源的完整 URI。服務擁有者日後需要這個值,才能將路徑附加至這個網格。

  4. networkservices.meshes.use IAM 權限授予這個網格,以及應能將服務資訊附加至這個網格的跨專案服務帳戶:

    gcloud projects add-iam-policy-binding HOST_PROJECT_NUMBER --member='HTTP_ROUTE_SERVICE_OWNER_ACCOUNT' --role='roles/compute.networkAdmin'
    

    現在,所有獲得 networkservices.meshes.use 權限的服務擁有者,都能將轉送規則新增至這個網格。

服務專案中的路徑設定

每個服務擁有者都需要在專案中建立區域後端服務和區域路徑資源,類似於「設定使用 HTTP 服務的 Envoy Proxy」。唯一的差別在於,每個 HTTPRoute/GRPCRoute/TCPRoute 的 meshes 欄位都會有主機專案網格資源的 URI。

  1. 建立 sharedvpc-http-route:

    echo "name: sharedvpc-http-route
    hostnames:
    - helloworld-gce
    meshes:
    - /projects/HOST_PROJECT_NUMBER/locations/${REGION}/meshes/shared-mesh
    rules:
    - action:
        destinations:
        - serviceName: \"SERVICE_URL\"" | \
    gcloud network-services http-routes import sharedvpc-http-route \
        --source=- \
        --location=${REGION}
    

在服務專案中設定用戶端服務

設定位於服務專案中的 Cloud Service Mesh 用戶端 (Envoy Proxy 或無 Proxy) 時,需要在啟動設定中指定網格資源所在的專案編號和網格名稱:

TRAFFICDIRECTOR_GCP_PROJECT_NUMBER=HOST_PROJECT_NUMBER
TRAFFICDIRECTOR_MESH_NAME=MESH_NAME

閘道 TLS 路由

本節將示範如何使用區域性閘道和區域性 TLSRoute 資源,設定以 Envoy Proxy 為基礎的輸入閘道。

區域性外部直通式網路負載平衡器會將流量導向 Envoy Proxy,做為 Ingress 閘道。Envoy Proxy 會使用 TLS 傳遞路由,並將流量直接傳送至後端 VM 執行個體上執行的 HTTPS 伺服器。

定義範例中會用到的變數。

export PROJECT_ID="PROJECT_ID"
export PROJECT_NUMBER="PROJECT_NUMBER"
export REGION="us-central1"
export ZONE="us-central1-b"
export NETWORK_NAME = "default"

取代下列項目:default

  • PROJECT_ID 為您的專案 ID。
  • PROJECT_NUMBER 改成您的專案編號。

您可以視需要替換下列項目:

  • us-central1 改為您要使用的其他區域。
  • us-central1-b 改為您要使用的其他區域。
  • default 替換為您要使用的其他網路名稱。

在多專案共用 VPC 環境中,交叉參照區域網格和區域路徑資源

在某些情況下,服務網格設定包含不同專案擁有的服務。舉例來說,在共用虛擬私有雲或對等互連虛擬私有雲部署作業中,每個專案擁有者都可以定義自己的服務組合,讓所有其他專案都能使用這些服務。

這項設定是「跨專案」設定,因為不同專案中定義的多個資源會合併成單一設定,可提供給 Proxy 或無 Proxy 用戶端。

設定防火牆規則

  1. 設定防火牆規則,允許來自任何來源的流量。編輯通訊埠和來源 IP 位址範圍的指令。

    gcloud compute firewall-rules create allow-gateway-health-checks \
    --network=${NETWORK_NAME} \
    --direction=INGRESS \
    --action=ALLOW \
    --rules=tcp \
    --source-ranges="35.191.0.0/16,209.85.152.0/22,209.85.204.0/22" \
    --target-tags=gateway-proxy
    

設定 IAM 權限

  1. 為閘道 Proxy 建立服務帳戶身分:

    gcloud iam service-accounts create gateway-proxy
    
  2. 將必要的 IAM 角色指派給服務帳戶身分:

    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member="serviceAccount:gateway-proxy@${PROJECT_ID}.iam.gserviceaccount.com" \
      --role="roles/trafficdirector.client"
    
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member="serviceAccount:gateway-proxy@${PROJECT_ID}.iam.gserviceaccount.com" \
      --role="roles/logging.logWriter"
    

設定區域閘道:

  1. 在名為 gateway8443.yaml 的檔案中,建立 HTTP 流量的 Gateway 規格:

    cat <<EOF > gateway8443.yaml
    name: gateway8443
    scope: gateway-proxy-8443
    ports:
    - 8443
    type: OPEN_MESH
    EOF
    
  2. 使用 gateway8443.yaml 規格建立區域閘道資源:

    gcloud network-services gateways import gateway8443 \
        --source=gateway8443.yaml \
        --location=${REGION}
    

建立含有 Envoy Proxy 的代管執行個體群組

在本節中,您將為執行自動部署 Envoy 服務 Proxy 的 VM 建立執行個體範本。Envoys 的範圍設為 gateway-proxy。請勿將服務通訊埠做為 --service-proxy 標記的參數傳遞。

  1. 建立含有 Envoy Proxy 的代管執行個體群組:

    gcloud beta compute instance-templates create gateway-proxy \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=gateway-proxy,http-td-tag,http-server,https-server \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --network-interface=network=${NETWORK_NAME} \
      --service-account="gateway-proxy@${PROJECT_ID}.iam.gserviceaccount.com" \
      --metadata=startup-script='#! /usr/bin/env bash
    
    # Set variables
    export ENVOY_CONTROL_PLANE_REGION="us-central1"
    export GCP_PROJECT_NUMBER=PROJECT_NUMBER
    export VPC_NETWORK_NAME=scope:gateway-proxy-8443
    export ENVOY_USER="envoy"
    export ENVOY_USER_UID="1337"
    export ENVOY_USER_GID="1337"
    export ENVOY_USER_HOME="/opt/envoy"
    export ENVOY_CONFIG="${ENVOY_USER_HOME}/config.yaml"
    export ENVOY_PORT="15001"
    export ENVOY_ADMIN_PORT="15000"
    export ENVOY_TRACING_ENABLED="false"
    export ENVOY_XDS_SERVER_CERT="/etc/ssl/certs/ca-certificates.crt"
    export ENVOY_ACCESS_LOG="/dev/stdout"
    export ENVOY_NODE_ID="$(cat /proc/sys/kernel/random/uuid)~$(hostname -i)"
    export BOOTSTRAP_TEMPLATE="${ENVOY_USER_HOME}/bootstrap_template.yaml"
    export GCE_METADATA_SERVER="169.254.169.254/32"
    export INTERCEPTED_CIDRS="*"
    
    export GCE_ZONE=$(curl -sS -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/zone | cut -d"/" -f4)
    
    # Create system user account for Envoy binary
    sudo groupadd ${ENVOY_USER} \
      --gid=${ENVOY_USER_GID} \
      --system
    sudo adduser ${ENVOY_USER} \
      --uid=${ENVOY_USER_UID} \
      --gid=${ENVOY_USER_GID} \
      --home=${ENVOY_USER_HOME} \
      --disabled-login \
      --system
    # Download and extract the Cloud Service Mesh tar.gz file
    cd ${ENVOY_USER_HOME}
    sudo curl -sL https://storage.googleapis.com/traffic-director/traffic-director-xdsv3.tar.gz -o traffic-director-xdsv3.tar.gz
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/bootstrap_template.yaml \
      -C bootstrap_template.yaml \
      --strip-components 1
    sudo tar -xvzf traffic-director-xdsv3.tar.gz traffic-director-xdsv3/iptables.sh \
      -C iptables.sh \
      --strip-components 1
    sudo rm traffic-director-xdsv3.tar.gz
    
    # Generate Envoy bootstrap configuration
    cat "${BOOTSTRAP_TEMPLATE}" \
      | sed -e "s|ENVOY_NODE_ID|${ENVOY_NODE_ID}|g" \
      | sed -e "s|ENVOY_ZONE|${GCE_ZONE}|g" \
      | sed -e "s|VPC_NETWORK_NAME|${VPC_NETWORK_NAME}|g" \
      | sed -e "s|CONFIG_PROJECT_NUMBER|${GCP_PROJECT_NUMBER}|g" \
      | sed -e "s|ENVOY_PORT|${ENVOY_PORT}|g" \
      | sed -e "s|ENVOY_ADMIN_PORT|${ENVOY_ADMIN_PORT}|g" \
      | sed -e "s|XDS_SERVER_CERT|${ENVOY_XDS_SERVER_CERT}|g" \
      | sed -e "s|TRACING_ENABLED|${ENVOY_TRACING_ENABLED}|g" \
      | sed -e "s|ACCESSLOG_PATH|${ENVOY_ACCESS_LOG}|g" \
      | sed -e "s|BACKEND_INBOUND_PORTS|${BACKEND_INBOUND_PORTS}|g" \
      | sed -e "s|trafficdirector.googleapis.com|trafficdirector.${ENVOY_CONTROL_PLANE_REGION}.rep.googleapis.com|g" \
      | sudo tee "${ENVOY_CONFIG}"
    
    # Install Envoy binary
    wget -O envoy_key https://apt.envoyproxy.io/signing.key
    cat envoy_key | sudo gpg --dearmor > $(pwd)/envoy-keyring.gpg
    echo "deb [arch=$(dpkg --print-architecture) signed-by=$(pwd)/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list
    sudo apt-get update
    sudo apt-get install envoy
    
    # Run Envoy as systemd service
    sudo systemd-run --uid=${ENVOY_USER_UID} --gid=${ENVOY_USER_GID} \
      --working-directory=${ENVOY_USER_HOME} --unit=envoy.service \
      bash -c "/usr/bin/envoy --config-path ${ENVOY_CONFIG} | tee"
    
    # Configure iptables for traffic interception and redirection
    sudo ${ENVOY_USER_HOME}/iptables.sh \
      -p "${ENVOY_PORT}" \
    -u "${ENVOY_USER_UID}" \
      -g "${ENVOY_USER_GID}" \
      -m "REDIRECT" \
      -i "${INTERCEPTED_CIDRS}" \
      -x "${GCE_METADATA_SERVER}"
    '
    
  2. 從執行個體範本建立地區代管執行個體群組:

    gcloud compute instance-groups managed create gateway-proxy \
      --region=${REGION} \
      --size=1 \
      --template=gateway-proxy
    
  3. 設定代管執行個體群組的服務通訊埠名稱:

    gcloud compute instance-groups managed set-named-ports gateway-proxy \
      --named-ports=https:8443 \
      --region=${REGION}
    

設定區域性外部直通式網路負載平衡器

  1. 建立靜態外部區域 IP 位址:

    gcloud compute addresses create xnlb-${REGION} \
      --region=${REGION}
    
  2. 取得為外部負載平衡器保留的 IP 位址:

    gcloud compute addresses describe xnlb-${REGION} \
      --region=${REGION} --format='value(address)'
    
  3. 為閘道 Proxy 建立健康狀態檢查:

    gcloud compute health-checks create tcp xnlb-${REGION} \
      --region=${REGION} \
      --use-serving-port
    
  4. 為閘道 Proxy 建立後端服務:

    gcloud compute backend-services create xnlb-${REGION} \
      --health-checks=xnlb-${REGION} \
      --health-checks-region=${REGION} \
      --load-balancing-scheme=EXTERNAL \
      --protocol=TCP \
      --region=${REGION} \
      --port-name=https
    
  5. 將代管執行個體群組新增為後端:

    gcloud compute backend-services add-backend xnlb-${REGION} \
      --instance-group=gateway-proxy \
      --instance-group-region=${REGION} \
      --region=${REGION}
    
  6. 建立轉送規則,將流量轉送至閘道 Proxy:

    gcloud compute forwarding-rules create xnlb-${REGION} \
      --region=${REGION} \
      --load-balancing-scheme=EXTERNAL \
      --address=${IP_ADDRESS} \
      --ip-protocol=TCP \
      --ports=8443 \
      --backend-service=xnlb-${REGION} \
      --backend-service-region=${REGION}
    

設定執行 HTTPS 服務的代管執行個體群組

  1. 建立執行個體範本,其中包含在通訊埠 8443 上公開的 HTTPS 服務:

    gcloud compute instance-templates create td-https-vm-template \
      --scopes=https://www.googleapis.com/auth/cloud-platform \
      --tags=https-td-server \
      --image-family=debian-11 \
      --image-project=debian-cloud \
      --metadata=startup-script='#! /bin/bash
    
    sudo rm -rf /var/lib/apt/lists/*
    sudo apt-get -y clean
    sudo apt-get -y update
    sudo apt-get -y install apt-transport-https ca-certificates curl gnupg2 software-properties-common
    sudo curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
    sudo add-apt-repository -y "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
    sudo apt-get -y update
    sudo apt-get -y install docker-ce
    sudo which docker
    echo "{ \"registry-mirrors\": [\"https://mirror.gcr.io\"] }" | sudo tee -a /etc/docker/daemon.json
    sudo service docker restart
    sudo docker run -e HTTPS_PORT=9999 -p 8443:9999 --rm -dt mendhak/http-https-echo:22'
    
  2. 依據執行個體範本建立代管執行個體群組:

    gcloud compute instance-groups managed create https-td-mig-us-${REGION} \
      --zone=${ZONE} \
      --size=2 \
      --template=td-https-vm-template
    
  3. 設定代管執行個體群組的服務通訊埠名稱:

    gcloud compute instance-groups managed set-named-ports https-td-mig-us-${REGION} \
      --named-ports=https:8443 \
      --zone=${ZONE}
    
  4. 建立健康狀態檢查:

    gcloud compute health-checks create https https-helloworld-health-check \
      --port=8443 --region=${REGION}
    
  5. 建立防火牆規則,允許傳入的健康狀態檢查連線抵達您網路中的執行個體:

    gcloud compute firewall-rules create https-vm-allow-health-checks \
      --network ${NETWORK_NAME} --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,130.211.0.0/22 \
      --target-tags https-td-server \
      --rules tcp:8443
    
  6. 使用「INTERNAL」INTERNAL_SELF_MANAGED負載平衡機制建立區域後端服務,並新增健康狀態檢查:

    gcloud compute backend-services create https-helloworld-service \
      --region=${REGION} \
      --load-balancing-scheme=INTERNAL_SELF_MANAGED \
      --port-name=https \
      --health-checks="https://www.googleapis.com/compute/v1/projects/${PROJECT}/regions/${REGION}/healthChecks/https-helloworld-health-check"
    
  7. 將代管執行個體群組新增至後端服務,做為後端使用:

    gcloud compute backend-services add-backend https-helloworld-service \
      --instance-group=https-td-mig-us-${REGION} \
      --instance-group-zone=${ZONE} \
      --region=${REGION}
    

使用 TLSRoute 資源設定轉送

  1. 在名為 tls_route.yaml 的檔案中,建立 TLSRoute 規格:

    cat <<EOF > tls_route.yaml
    name: helloworld-tls-route
    gateways:
    - projects/${PROJECT_NUMBER}/locations/${REGION}/gateways/gateway8443
    rules:
    - matches:
      - sniHost:
        - example.com
        alpn:
        - h2
      action:
        destinations:
        - serviceName: projects/${PROJECT_NUMBER}/locations/${REGION}/backendServices/https-helloworld-service
    EOF
    

    在先前的指令中,TLSRoute 會將 example.com 設為 SNI,並將 h2 設為 ALPN。如果比對結果變更如下,TLSRoute 會比對 SNI 或 ALPN:

    - matches:
      - sniHost:
        - example.com
      - alpn:
        - h2
    
  2. 使用 tls_route.yaml 規格建立 TLSRoute 資源:

    gcloud network-services tls-routes import helloworld-tls-route \
        --source=tls_route.yaml \
        --location=${REGION}
    

驗證部署作業

  1. 執行下列 curl 指令,驗證與您建立的測試服務之間的 HTTP 連線:

    curl https://example.com:8443 --resolve example.com:8443:${IP_ADDRESS} -k
    
  2. 這項指令會傳回代管執行個體群組中其中一個 VM 的回應。輸出結果會與下列內容相似:

    {
      "path": "/",
      "headers": {
        "host": "example.com:8443",
        "user-agent": "curl/8.16.0",
        "accept": "*/*"
      },
      "method": "GET",
      "body": "",
      "fresh": false,
      "hostname": "example.com",
      "ip": "::ffff:10.128.0.59",
      "ips": [],
      "protocol": "https",
      "query": {},
      "subdomains": [],
      "xhr": false,
      "os": {
        "hostname": "19cd7812e792"
      },
      "connection": {
        "servername": "example.com"
      }
    

使用負向驗證進行驗證

  1. 在下列指令中,SNI 與 example.com 不符,因此 Gateway 會拒絕連線:

    curl https://invalid-server.com:8443 --resolve invalid-server.com:8443:${IP_ADDRESS} -k
    
  2. 在下列指令中,ALPN 不符合 h2 (HTTP2 通訊協定),因此 Gateway 會拒絕連線:

    curl https://example.com:8443 --resolve example.com:8443:${IP_ADDRESS} -k --http1.1
    

    上述指令都會傳回下列錯誤:

    curl: (35) OpenSSL SSL_connect: Connection reset by peer in connection.
    
  3. 在下列指令中,用戶端會建立純文字 (未加密) 連線,因此 Gateway 會拒絕連線,並顯示 404 Not Found 錯誤:

    curl example.com:8443 --resolve example.com:8443:${IP_ADDRESS} -k