NGINX 第 7 層負載平衡參考實作

Google Distributed Cloud (GDC) 實體隔離方案提供內建的第 4 層 (L4) 代管負載平衡器,但許多企業應用程式需要進階的第 7 層 (L7) 功能,例如主機轉送、集中式 TLS 管理和複雜的流量拆分。過去,這項作業是透過 Ingress API 完成,但 Kubernetes 社群現在已將該 API 視為功能凍結。

這項參考架構提供自行管理的第 7 層負載平衡解決方案。只要在 GDC Standard 叢集部署熱門的 NGINX Gateway Fabric 開放原始碼控制器,客戶就能將 L7 流量順暢轉送至混合環境。這個架構會使用 TLS 終止 (HTTPRoute),根據伺服器名稱指示 (SNI),將流量轉送至內建容器化 Pod 和託管於外部虛擬機器的應用程式。

架構

GDC 實體隔離方案中 NGINX 第 7 層負載平衡的架構圖。

這項解決方案的主要元件包括:

  • 用戶端:發出 HTTPS 要求,與應用程式互動的實體。
  • GDC 標準叢集:GDC 提供內建方式,可建立 Kubernetes Vanilla 叢集。在這個解決方案中,叢集會託管 L7 LB 及其控制器,以及外部 VM 的工作負載和無頭服務
  • GDC L4 負載平衡器:內建的 L4 負載平衡器可做為進入點,將 TCP/443 流量直接分配給執行閘道控制器的 Kubernetes Pod。
  • 閘道控制器:在標準叢集中執行的 NGINX 運算子。監控 Gateway API 資源 (例如 Gateway 和 HTTPRoute),並動態更新基礎 Proxy。這項解決方案會使用 Nginx Gateway Fabric。
  • 閘道 (含 HTTPRoute):標準化 Kubernetes 資源,定義實體監聽通訊埠 (443) 和採用 TLS 終止作業、以 SNI 為基礎的主機路由規則。
  • 容器化工作負載 (Pod):標準 Kubernetes Deployment,透過一般 Kubernetes Service 在內部公開。
  • VM 型工作負載 (外部):託管於專案網路外部 VM 的工作負載,透過無頭 Kubernetes Service 和包含 VM 直接 IP 的自訂端點,向 Proxy 公開。
  • Harbor Registry:用於在實體隔離環境中儲存及提供 Proxy 和應用程式映像檔的私人 Container Registry。

在標準叢集中,您會建立四個命名空間:

  • 託管 Nginx Gateway Fabric 資源的 nginx-gateway 命名空間:

    nginx-gateway 命名空間資源。

  • 託管 Gateway 資源的 load-balancer 命名空間:

    負載平衡器命名空間資源。

  • vm-app 命名空間託管外部 VM IP vm-app、無頭服務、指向外部 IP 的 EndpointSlice,以及 Gateway 的 HTTPRoute:

    vm-app 命名空間資源。

  • hello-app 命名空間會託管 Deployment、Service、HTTPRoute 和 Gateway,用於示範容器工作負載:

    hello-app 命名空間資源。

事前準備

部署這項解決方案前,請確認您已符合下列必要條件:

  • 所需軟體:helm、docker、kubectl
  • CLI 登入和本機設定:從 GDC 控制台下載 gdcloud CLI,並在本機設定環境。

    export USER_NAME="USER_NAME"
    export PROJECT_ID="PROJECT_ID"
    export ZONE="ZONE"
    export ORG_NAME="ORG_NAME"
    export GDC_URL="GDC_URL"
    
    gdcloud components install gdcloud-k8s-auth-plugin
    
    gdcloud config set core/organization_console_url \
      https://console.$ORG_NAME.$ZONE.$GDC_URL
    gdcloud config set core/zone $ZONE
    gdcloud config set core/project ${PROJECT_ID}
    
    gdcloud auth login # use --login-config-cert option in case of TLS error
    
  • 專案設定:在 GDC 實體隔離方案環境中建立專案,用於存放資源。

    gdcloud projects create $PROJECT_ID
    
  • IAM 角色:為使用者授予「叢集管理員」和「標準叢集管理員」角色,以便管理 Kubernetes 資源,並授予「Harbor 執行個體管理員」角色,以便推送映像檔。

    # Grant standard cluster and cluster admin roles
    gdcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member="user:${USER_NAME}" \
      --role=cluster-admin
    
    gdcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member="user:${USER_NAME}" \
      --role=standard-cluster-admin
    
    # Grant Harbor instance admin role
    gdcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member="user:${USER_NAME}" \
      --role=harbor-instance-admin
    

建立標準叢集

本節將引導您在 Google Distributed Cloud 實體隔離方案環境中設定標準 Kubernetes 叢集。標準叢集提供彈性且穩固的基礎,可部署各種工作負載,包括 Nginx Gateway Controller 和自訂應用程式。請按照下列步驟操作,確保叢集設定正確,且可供後續部署作業存取。

  1. 執行下列指令,找出可用的虛擬機器映像檔類型:

    gdcloud compute machine-types list
    
  2. 為叢集 worker 節點選取合適的機器類型。在本教學課程中,建議您使用至少有 4 個 vCPU 的機型。

    export MACHINE_TYPE="MACHINE_TYPE"
    
  3. 取得管理 API 伺服器 kubeconfig 並設定別名:

    export CLUSTER_NAME="CLUSTER_NAME"
    
    KUBECONFIG=kubeconfig-admin.yaml gdcloud clusters \
      get-credentials ${ORG_NAME}-admin
    
    alias km="kubectl --kubeconfig kubeconfig-admin.yaml"
    
  4. 建立含有 2 個 worker 節點的標準叢集:

    km create -f - <<EOF
    apiVersion: cluster.gdc.goog/v1
    kind: Cluster
    metadata:
      name: ${CLUSTER_NAME}
      namespace: ${PROJECT_ID}
    spec:
      nodePools:
      - machineTypeName: ${MACHINE_TYPE}
        nodeCount: 2
        name: ${CLUSTER_NAME}-node-pool
    EOF
    

    如要進一步瞭解可用選項,請參閱說明文件。

    標準叢集建立作業最多可能需要 60 分鐘才能完成。如要檢查狀態,請使用下列指令:

    km get clusters/${CLUSTER_NAME} \
      -n ${PROJECT_ID} \
      --watch
    

    叢集準備就緒後,輸出內容應會顯示「Running」狀態,如下所示:

    NAME         STATE     K8S VERSION
    my-cluster   Running   1.30.12-gke.300
    
  5. 叢集準備就緒後,請擷取其憑證:

    KUBECONFIG=kubeconfig-${CLUSTER_NAME}.yaml gdcloud clusters \
      get-credentials ${CLUSTER_NAME} \
      --standard \
      --project ${PROJECT_ID} \
      --zone ${ZONE}
    
  6. 建立別名,讓本指南其餘部分的 kubectl 指令更簡潔。這個別名將用於與標準叢集互動:

    alias kk="kubectl --kubeconfig kubeconfig-${CLUSTER_NAME}.yaml"
    
  7. 為控制器、「hello-app」示範容器化應用程式,以及 VM 型示範應用程式建立命名空間:

    kk create namespace load-balancer
    kk create namespace hello-app
    kk create namespace vm-app
    

建立及整合 Harbor Registry

Harbor 是容器映像檔登錄檔,內建 GDC 實體隔離方案支援。本節將逐步引導您將 Harbor Registry 與標準叢集整合,包括設定憑證和 Secret,以便安全地提取及推送映像檔。

  1. 在專案中建立 Harbor 執行個體。
  2. 在 Harbor 執行個體中建立 Harbor 專案。
  3. 設定環境變數:

    export HARBOR_INSTANCE_NAME="HARBOR_INSTANCE_NAME"
    export HARBOR_INSTANCE_URL="HARBOR_INSTANCE_URL"
    export HARBOR_PROJECT="HARBOR_INSTANCE_PROJECT"
    export IMAGE_PULL_SECRET_NAME="harbor-secret"
    
  4. 使用機器人帳戶登入 Harbor 執行個體:

    docker --config=./docker login ${HARBOR_INSTANCE_URL}
    
  5. 在標準叢集中建立 Secret:

    kk create secret docker-registry ${IMAGE_PULL_SECRET_NAME} \
      --from-file=.dockerconfigjson=./docker/config.json \
      -n load-balancer
    
    kk create secret docker-registry ${IMAGE_PULL_SECRET_NAME} \
      --from-file=.dockerconfigjson=./docker/config.json \
      -n hello-app
    

部署容器化試用版應用程式

本節將詳細說明如何在 GDC 實體隔離 Kubernetes 叢集中,部署容器化範例應用程式 (hello-app)。您將建立必要的 Kubernetes Deployment 和 Service 資源,以便執行 hello-app 並在叢集內部公開,為使用 L7 負載平衡器存取做好準備。

  1. 將容器化試用版應用程式的範例圖片上傳至 Harbor:

    docker pull gcr.io/google-samples/hello-app:1.0 \
      --platform linux/amd64
    docker tag gcr.io/google-samples/hello-app:1.0 \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/hello-app:1.0
    docker --config=./docker push \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/hello-app:1.0
    
  2. 在標準叢集中部署下列資訊清單:

    cat << EOF > hello-app.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-app
      namespace: hello-app
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: hello-app
      template:
        metadata:
          labels:
            app: hello-app
        spec:
          containers:
          - name: hello-server
            image: ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/hello-app:1.0
            ports:
            - containerPort: 8080
          imagePullSecrets:
          - name: ${IMAGE_PULL_SECRET_NAME}
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: hello-app
      namespace: hello-app
    spec:
      type: ClusterIP
      selector:
        app: hello-app
      ports:
        - protocol: TCP
          port: 80
          targetPort: 8080
    EOF
    
    kk apply -f hello-app.yaml
    

接著,確認 Deployment 和 Service 是否存在:

kk get svc,deploy -n hello-app

在 VM 中部署試用版應用程式

本節將詳細說明如何在 Kubernetes 叢集外的虛擬機器 (VM) 中部署示範應用程式。在 VM 上設定 HTTP 伺服器,模擬負載平衡器可公開的外部應用程式,展示負載平衡器管理叢集內外資源流量的能力。

首先,為試用版應用程式建立 VM

  1. 在網路瀏覽器中開啟 GDC 控制台。
  2. 選取建立標準 Kubernetes 叢集的專案。
  3. 開啟選單,然後點選「虛擬機器」。
  4. 點選「建立執行個體」。
  5. 將 VM 命名為 vm-workload。2 個 vCPU 映像檔就足以完成範例。
  6. 選取 Ubuntu 22.04 發行版本做為開機磁碟映像檔,其中已預先安裝 Python。
  7. 點選「建立」。
  8. 請稍候幾分鐘,等待 VM 準備就緒。
  9. 建立 VM 的 SSH 連線:
    1. 在 GDC 控制台中,按一下 VM。
    2. 按一下「使用 SSH 連線」。

連線至 SSH 控制台後,請執行下列指令:

mkdir ~/simple-server
cd ~/simple-server
echo 'Welcome to my VM!' > index.html
python3 -m http.server --bind 0.0.0.0 8080 &

如要將流量轉送至 VM,請建立無頭 Service (不含選取器)。這個位址會使用 EndpointSlice 資源,手動對應至 VM 的內部 IP 位址。

kk apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: vm-app-svc
  namespace: vm-app
spec:
  ports:
  - protocol: TCP
    port: 443
    targetPort: 443
EOF

執行下列指令,取得 vm-workload VM 的 IP 位址:

gdcloud compute instances list --project ${PROJECT_ID} \
  | grep workload-vm | awk '{print $3}'

輸出內容會是設定 EndpointSlice 資源所需的 VM IP 位址。

建立資源 EndpointSlice,該資源會連線至 VM 應用程式無選取器 Service,並指定流量應轉送至的 VM IP。

apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
  name: vm-app-endpoints
  namespace: vm-app
  labels:
    kubernetes.io/service-name: vm-app-svc
addressType: IPv4
ports:
  - port: 8080
endpoints:
  - addresses:
    - "VM_IP"
    conditions:
      ready: true

建立自行簽署的憑證

本節將引導您為應用程式產生自行簽署的 TLS 憑證。為方便起見,本指南使用自行簽署的憑證,但在正式環境中,您必須使用正式環境等級的憑證,詳情請參閱「選用:使用可用於正式環境的憑證」。這些憑證對於在 Nginx 閘道啟用 HTTPS 終止至關重要,可確保用戶端與負載平衡器之間的通訊經過加密,適用於容器化和 VM 型工作負載。

  1. 為容器化應用程式建立憑證:

    openssl req -x509 -newkey rsa:2048 -nodes \
      -keyout tls-containerized.key \
      -out tls-containerized.crt \
      -subj "/CN=k8s-app.example.com" \
      -days 365
    
    kk create secret tls tls-containerized \
      --namespace load-balancer \
      --key tls-containerized.key \
      --cert tls-containerized.crt
    
    kk create secret tls tls-containerized \
      --namespace hello-app \
      --key tls-containerized.key \
      --cert tls-containerized.crt
    
  2. 為 VM 應用程式建立憑證:

    openssl req -x509 -newkey rsa:2048 -nodes \
      -keyout tls-vm.key \
      -out tls-vm.crt \
      -subj "/CN=vm-app.example.com" \
      -days 365
    
    kk create secret tls tls-vm \
      --namespace load-balancer \
      --key tls-vm.key \
      --cert tls-vm.crt
    
    kk create secret tls tls-vm \
      --namespace vm-app \
      --key tls-vm.key \
      --cert tls-vm.crt
    

部署 NGINX

本節將概略說明部署 Nginx Gateway Controller 的步驟,包括安裝 Gateway API 自訂資源定義 (CRD)、使用 Helm 設定 Nginx Gateway Fabric,以及在標準叢集中驗證安裝作業。這樣一來,基礎架構就能進行進階第 7 層轉送。

安裝 Gateway API CRD

部署控制器之前,Gateway API 必須在叢集中安裝自訂資源定義 (CRD)。我們會使用 Gateway API 專案的官方實驗性自訂資源定義 (CRD) (本指南使用 1.2.0 版)。

  1. 安裝實驗性 CRD:

    kk apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/experimental-install.yaml
    
  2. 執行 kk get crd gateways.gateway.networking.k8s.io,確認 CRD 已成功安裝。

安裝 NGINX Gateway Fabric

使用 Helm 部署 NGINX Gateway Fabric 控制器。這個控制器會監控 Gateway API 資源,並設定 NGINX 處理流量。

  1. 設定 NGINX 映像檔標記:

    helm template nfg oci://ghcr.io/nginx/charts/nginx-gateway-fabric | grep "image:" # get the tag of the nginx-gateway-fabric (in following case 2.4.2)
    
    export NGINX_TAG="2.4.2"
    
  2. 提取 NGINX Gateway Fabric 和 NGINX 映像檔,然後推送至 Harbor 登錄檔:

    docker pull ghcr.io/nginx/nginx-gateway-fabric:${NGINX_TAG}
    docker tag ghcr.io/nginx/nginx-gateway-fabric:${NGINX_TAG} \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx-gateway-fabric:${NGINX_TAG}
    docker --config=./docker push \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx-gateway-fabric:${NGINX_TAG}
    
    docker pull nginx:1.27.3
    docker tag nginx:1.27.3 \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx:1.27.3
    docker --config=./docker push \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx:1.27.3
    
  3. 建立 nginx-gateway 命名空間,並新增 Harbor 映像檔提取密鑰:

    kk create namespace nginx-gateway
    
    kk create secret docker-registry ${IMAGE_PULL_SECRET_NAME} \
      --from-file=.dockerconfigjson=./docker/config.json \
      -n nginx-gateway
    
  4. 使用 Helm 部署 NGINX Gateway Fabric,並指向 Harbor 登錄檔中的映像檔:

    KUBECONFIG=kubeconfig-${CLUSTER_NAME}.yaml helm upgrade --install ngf \
      oci://ghcr.io/nginx/charts/nginx-gateway-fabric \
      --create-namespace -n nginx-gateway \
      --set nginxGateway.image.tag="${NGINX_TAG}" \
      --set nginxGateway.image.repository="${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx-gateway-fabric" \
      --set nginx.image.repository="${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx" \
      --set nginxGateway.serviceAccount.imagePullSecret="${IMAGE_PULL_SECRET_NAME}" \
      --set nginx.imagePullSecret="${IMAGE_PULL_SECRET_NAME}"
    

    Kubernetes 部署作業會使用提供的 Secret (${IMAGE_PULL_SECRET_NAME}),安全地從 Harbor 提取映像檔,其中包含 Harbor 機器人帳戶的憑證。

  5. 確認 GatewayClass 資源已接受:

    kk get gatewayclass
    

    您應該會看到 nginx 與 ACCEPTED = True 一起列出。

建立閘道執行個體

定義監聽通訊埠 443 的邏輯負載平衡器執行個體。我們會將其設為 Terminate 模式,也就是說,閘道會執行 TLS 終止作業,並在傳遞流量前解密。

建立並套用 gateway.yaml:

cat << EOF > gateway.yaml 
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: my-gateway
  namespace: load-balancer
spec:
  gatewayClassName: nginx
  listeners:
  - name: https-k8s-workload
    hostname: "k8s-app.example.com"
    port: 443
    protocol: HTTPS
    allowedRoutes: 
      namespaces: 
        from: All
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        name: tls-containerized 
  - name: https-vm-workload
    hostname: "vm-app.example.com"
    port: 443
    protocol: HTTPS
    allowedRoutes: 
      namespaces: 
        from: All
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        name: tls-vm 
EOF

kk apply -f gateway.yaml

檢查 PROGRAMMED 是否為 True,確認閘道是否已成功部署:

kk get gateway my-gateway --n load-balancer

確認代管 GDC L4 負載平衡器已與閘道一併部署為服務

kk get services -n load-balancer

確認 Nginx 服務已建立並設定,輸出內容應如下所示:

NAME               TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)         AGE
my-gateway-nginx   LoadBalancer   10.252.19.148   10.200.32.43   443:30649/TCP   45h

定義 L7 轉送邏輯 (HTTPRoute)

將 HTTPRoute 繫結至閘道,定義如何根據要求的主機名稱 (SNI) 分配流量。

建立並套用 routing.yaml:

cat << EOF > routing.yaml 
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: k8s-http-route
  namespace: hello-app
spec:
  parentRefs:
  - name: my-gateway 
    namespace: load-balancer
  hostnames:
  - "k8s-app.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: hello-app 
      namespace: hello-app
      port: 80          
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: vm-http-route
  namespace: vm-app
spec:
  parentRefs:
  - name: my-gateway
    namespace: load-balancer
  hostnames:
  - "vm-app.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: vm-app-svc  
      namespace: vm-app
      port: 443       
EOF

kk apply -f routing.yaml   

擷取負載平衡器 IP

執行指令,取得 Nginx 負載平衡器的 IP

kk get services/my-gateway-nginx \
  -n load-balancer \
  -o jsonpath='{.status.loadBalancer.ingress[0].ip}'

驗證應用程式存取權時,會需要這項資訊。這個值區稍後會稱為 LOAD_BALANCER_IP。

建立用戶端 VM

按照步驟建立用戶端 VM

  1. 在網路瀏覽器中開啟 GDC 控制台。
  2. 開啟選單,然後點選「虛擬機器」。
  3. 點選「建立執行個體」。
  4. 建立名為 client 的 VM,選取小型機器類型,並選取預先安裝 curl 的 Rocky Linux 或 Ubuntu。
  5. 點選「建立」。
  6. 請稍候幾分鐘,等待 VM 準備就緒。
  7. VM 準備就緒後,請建立與 VM 的 SSH 連線:
    1. 在 GDC 控制台中,按一下 VM。
    2. 按一下「使用 SSH 連線」。

驗證已驗證存取權和路由

如要測試轉送功能,請從用戶端 VM 執行 curl 指令。您可以使用定義的主機名稱和負載平衡器的 IP 位址,連線至這兩個應用程式。

在 curl 中傳遞 --resolve 旗標,即可強制將網域名稱解析為 GDC 實體隔離方案 L4 負載平衡器的 IP 位址。請注意,我們傳遞 -k 旗標來信任自行簽署的憑證。

測試 Kubernetes 容器化應用程式:

curl -k --resolve k8s-app.example.com:443:$LOAD_BALANCER_IP https://k8s-app.example.com -v

測試外部 VM 應用程式:

curl -k --resolve vm-app.example.com:443:$LOAD_BALANCER_IP https://vm-app.example.com -v

如果設定正確,閘道控制器會順暢地做為 TLS 終止器,並將流量傳遞至目的地。

選用:使用可用於正式環境的憑證

本節說明如何運用 GDC 實體隔離方案 CA 服務,建立私人根憑證授權單位 (CA)、為工作負載核發已簽署的憑證,以及安全地更新 GDC 實體隔離方案標準叢集和用戶端 VM。

本節說明如何使用 GDC 實體隔離方案憑證授權單位服務,建立私人根憑證授權單位 (CA),並為應用程式核發有效憑證。在用戶端 VM 安裝這個根 CA 後,您就能確認 TLS 終止作業可與信任的憑證搭配運作,不必略過 SSL 警告 (例如使用 curl -k)。

授予必要權限並取得憑證

如要管理 CA 服務及核發憑證,使用者必須具備專案中的適當 IAM 角色。

  1. 授予 certificate-authority-service-admin 和 certificate-requester 角色:

    gdcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member=user:${USER_NAME} \
      --role=certificate-authority-service-admin
    
    gdcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member=user:${USER_NAME} \
      --role=certificate-requester
    
  2. 取得 Management API 伺服器的憑證:

    gdcloud clusters get-credentials ${ORG_NAME}-admin
    

建立根 CA

您將在專案命名空間的 Management API 伺服器中建立憑證授權單位。

  1. 套用 CertificateAuthority 資源:

    km apply -f - <<EOF
    apiVersion: pki.security.gdc.goog/v1
    kind: CertificateAuthority
    metadata:
      name: my-root-ca
      namespace: ${PROJECT_ID}
    spec:
      caProfile:
        commonName: "My Root CA"
        duration: 87600h # 10 years
        keyAlgorithm: RSA_2048
        maxChainLength: 1
      caType: ROOT
      keyLocation: HSM
      rotationPolicy:
        cronTime: 0 0 1 1 *
    EOF
    
    km -n ${PROJECT_ID} get \
    certificateauthority.pki.security.gdc.goog/my-root-ca -ojson \
    | jq -r '
    .status.conditions[] | select( .type as $id | "Ready" | index($id)) .status'
    

核發及部署憑證

CA 準備就緒後,您將為容器化應用程式和 VM 應用程式要求憑證。這些要求會在 Management API 伺服器中執行,且產生的金鑰必須移至標準叢集。

為這兩個網域建立要求:

km apply -f - <<EOF
apiVersion: pki.security.gdc.goog/v1
kind: CertificateRequest
metadata:
  name: tls-containerized-req
  namespace: ${PROJECT_ID}
spec:
  certificateAuthorityRef:
    name: my-root-ca
    namespace: ${PROJECT_ID}
  certificateConfig:
    subjectConfig:
      commonName: "k8s-app.example.com"
      dnsNames:
      - "k8s-app.example.com"
  signedCertificateSecret: tls-containerized-signed
---
apiVersion: pki.security.gdc.goog/v1
kind: CertificateRequest
metadata:
  name: tls-vm-req
  namespace: ${PROJECT_ID}
spec:
  certificateAuthorityRef:
    name: my-root-ca
    namespace: ${PROJECT_ID}
  certificateConfig:
    subjectConfig:
      commonName: "vm-app.example.com"
      dnsNames:
      - "vm-app.example.com"
  signedCertificateSecret: tls-vm-signed
EOF

稍待片刻,等待憑證核發。當「Ready」條件為「True」時,表示節點已準備就緒:

km get certificaterequests -n ${PROJECT_ID}

更新標準叢集

如果您已按照本指南前幾節的說明操作,標準叢集中應有自行簽署的 Secret。您必須先刪除這些版本,才能建立新的已簽署版本:

kk delete secret tls-containerized -n load-balancer
kk delete secret tls-vm -n load-balancer

kk delete secret tls-containerized -n hello-app
kk delete secret tls-vm -n vm-app

現在,請從 Management API 伺服器擷取已簽署的憑證,並在標準叢集中建立新的 Secret。

km get secret -n ${PROJECT_ID} tls-containerized-signed \
  -o jsonpath='{.data.tls\.crt}' \
  | base64 -d > tls-containerized.crt

km get secret -n ${PROJECT_ID} tls-containerized-signed \
  -o jsonpath='{.data.tls\.key}' \
  | base64 -d > tls-containerized.key

kk create secret tls tls-containerized \
  --namespace load-balancer \
  --key tls-containerized.key \
  --cert tls-containerized.crt

kk create secret tls tls-containerized \
  --namespace hello-app \
  --key tls-containerized.key \
  --cert tls-containerized.crt

km get secret -n ${PROJECT_ID} tls-vm-signed \
  -o jsonpath='{.data.tls\.crt}' \
  | base64 -d > tls-vm.crt

km get secret -n ${PROJECT_ID} tls-vm-signed \
  -o jsonpath='{.data.tls\.key}' \
  | base64 -d > tls-vm.key

kk create secret tls tls-vm \
  --namespace load-balancer \
  --key tls-vm.key \
  --cert tls-vm.crt

kk create secret tls tls-vm \
  --namespace vm-app \
  --key tls-vm.key \
  --cert tls-vm.crt

負載平衡器會自動取得並重新整理新的密鑰。

設定用戶端信任

如要驗證設定,您必須指示用戶端 VM 信任新的根 CA。

將根 CA 憑證擷取至檔案:

km get secret -n ${PROJECT_ID} my-root-ca-secret \
  -o jsonpath='{.data.tls\.crt}' \
  | base64 -d > my-root-ca.crt

將憑證轉移至用戶端 VM。(您可以複製 my-root-ca.crt 的內容,並貼到用戶端 VM 上的檔案)。

在用戶端 VM 上更新信任存放區。

如果 client VM 是 Ubuntu:

sudo cp my-root-ca.crt /usr/local/share/ca-certificates/
sudo chmod 644 /usr/local/share/ca-certificates/my-root-ca.crt
sudo update-ca-certificates

如果 client VM 是 Rocky Linux:

sudo cp my-root-ca.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust

驗證存取權

現在,您可以使用 curl 存取應用程式,不需加上 -k 旗標。連線將完全受到信任。

測試 Kubernetes 容器化應用程式:

curl -v --resolve k8s-app.example.com:443:LOAD_BALANDER_IP https://k8s-app.example.com

測試 VM 應用程式:

curl -v --resolve vm.example.com:443:LOAD_BALANDER_IP https://vm-app.example.com

如果成功,您會立即看到應用程式輸出內容,且不會出現任何 SSL 憑證警告。