區域 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}/locations/${REGION}/meshes/grpc-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/${PROJECT}/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 和地區網格,為 HTTP 服務設定 Envoy Sidecar Proxy 設定

本節說明如何使用區域網格和區域 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}/locations/${REGION}/meshes/sidecar-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/${PROJECT}/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 現在已設定為指定服務進行負載平衡,其為代管執行個體群組後端間的 HTTPRoute 所指定。

使用 Envoy Sidecar 建立 HTTP 用戶端

在本節中,您會使用 Envoy Sidecar 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_INBOUND_PORT="15006"
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|ENVOY_INBOUND_PORT|${ENVOY_INBOUND_PORT}|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 的回應,並在主控台中顯示主機名稱。

使用區域性 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 伺服器設定

為示範用途,您將建立具有自動調整資源配置 VM 的區域後端服務 (使用代管執行個體群組 - MIG),透過通訊埠 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}/locations/${REGION}/meshes/sidecar-mesh
    rules:
    - action:
        destinations:
        - serviceName: projects/${PROJECT}/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。服務擁有者日後需要這個 ID,才能將路由附加至這個網格。

  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 代理程式或無代理程式) 時,需要在啟動設定中指定網格資源所在的專案編號和網格名稱。sh TRAFFICDIRECTOR_GCP_PROJECT_NUMBER=HOST_PROJECT_NUMBER TRAFFICDIRECTOR_MESH_NAME=MESH_NAME

為區域性 Cloud Service Mesh 設定已發布的服務後端

發布的服務後端可讓您設定區域 Cloud Service Mesh,透過 Private Service Connect 將流量轉送至發布的服務。

如要進一步瞭解已發布的服務後端,請參閱已發布的服務後端

完成下列各節的步驟之前,請先執行下列操作:

  • 確認供應商和用戶虛擬私有雲網路屬於同一個機構。
  • 找出要存取服務的服務連結 URI
  • 找出 Cloud Service Mesh 用戶端使用的虛擬私有雲網路名稱。這是 TRAFFICDIRECTOR_NETWORK_NAME 設定的必要條件。

設定環境變數

為方便起見,請儲存下列值,這樣一來,本節中的所有範例都可以複製並貼到指令列:

export PROJECT_NUMBER="PROJECT_NUMBER"
export REGION="us-central1"
export MESH_NAME="my-mesh"
export NETWORK_NAME="default"
export SUBNET_NAME="default"
export SERVICE_ATTACHMENT_URI="SERVICE_ATTACHMENT_URI"
export BACKEND_SERVICE_NAME="published-service-backend"

用戶端設定

為確保系統將正確的 Private Service Connect 端點傳送至 Cloud Service Mesh 用戶端 (Envoy 或無 Proxy 的 gRPC),您必須在節點中繼資料中加入 TRAFFICDIRECTOR_NETWORK_NAME 變數。

TRAFFICDIRECTOR_GCP_PROJECT_NUMBER=${PROJECT_NUMBER}
TRAFFICDIRECTOR_MESH_NAME=${MESH_NAME}
TRAFFICDIRECTOR_NETWORK_NAME=${NETWORK_NAME}

建立區域性網格

gcloud network-services meshes import ${MESH_NAME} \
    --location=${REGION} \
    --source=- <<EOF
name: ${MESH_NAME}
EOF

建立 Private Service Connect 端點

如要連線至服務附件,用戶端網路中必須有 Private Service Connect 端點。

  1. 為端點保留內部 IP 位址。如果沒有要使用的子網路,請建立一個

    gcloud compute addresses create psc-endpoint-ip \
        --region=${REGION} \
        --subnet=${SUBNET_NAME} \
        --purpose=GCE_ENDPOINT
    
  2. 為端點建立轉送規則:

    gcloud compute forwarding-rules create psc-endpoint \
        --region=${REGION} \
        --network=${NETWORK_NAME} \
        --address=psc-endpoint-ip \
        --target=${SERVICE_ATTACHMENT_URI}
    

使用已發布的服務後端建立後端服務

如要使用已發布的服務後端,請將服務連結 URI 新增至區域後端服務,做為後端。

  1. 建立區域後端服務:

    gcloud beta compute backend-services create published-service-backend \
        --load-balancing-scheme=INTERNAL_SELF_MANAGED \
        --protocol=HTTP \
        --region=${REGION}
    
  2. 將後端服務與服務連結建立關聯 (將服務連結 URI 中的 /regions 換成 /locations):

    gcloud beta compute backend-services add-backend published-service-backend \
        --region=${REGION} \
        --service=${SERVICE_ATTACHMENT_URI}
    

使用 HTTPRoute 設定轉送

  • 建立 HTTPRoute 並附加至網格:

    gcloud network-services http-routes import published-service-backend-route \
        --location=${REGION} \
        --source=- <<EOF
    name: published-service-backend-route
    hostnames:
    - helloworld-gce
    meshes:
    - projects/${PROJECT_NUMBER}/locations/${REGION}/meshes/${MESH_NAME}
    rules:
    - action:
        destinations:
        - serviceName: projects/${PROJECT_NUMBER}/locations/${REGION}/backendServices/${BACKEND_SERVICE_NAME}
    EOF
    

網格中的用戶端現在可以使用主機名稱 helloworld-gce 存取已發布的服務。

閘道 TLS 路由

本節說明如何使用區域性閘道和區域性 TLSRoute 資源,設定以 Envoy Proxy 為基礎的 Ingress 閘道。

區域性外部直通式網路負載平衡器會將流量導向 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 替換為您要使用的其他網路名稱。

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

在某些情況下,服務網格設定會包含不同專案擁有的服務。舉例來說,在 Shared 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 規格建立區域 Gateway 資源:

    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_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