設定 Google Cloud Armor

本頁面說明如何使用 BackendConfig 自訂資源在 Google Kubernetes Engine 中設定 Google Cloud Armor。

總覽

在 GKE 叢集中,HTTP(S) 負載平衡會處理連入流量。HTTP(S) 負載平衡是 Cloud Load Balancing 的元件。 HTTP(S) 負載平衡器通常是由 GKE Ingress 控制器設定,它會從 Kubernetes Ingress 物件取得設定資訊。Ingress 會與一或多個 Service 物件建立關聯。每個 Service 物件都會保留用來將傳入要求導向特定 Pod 及通訊埠的轉送資訊。

從 Kubernetes 1.10.5-gke.3 版開始,您可以為負載平衡器提供額外的設定,方法是建立 Service 通訊埠與 BackendConfig 自訂資源之間的關聯。

GKE Ingress 控制器會讀取 BackendConfig 中的設定資訊,並據此設定負載平衡器。BackendConfig 會保留 Cloud Load Balancing 專屬的設定資訊。 Kubernetes Ingress 與 Service 資源不提供設定特定供應商功能 (如 Google Cloud Armor) 的方法,但 BackendConfig 提供這個設定方法。

以下大致說明如何在這個練習中設定 BackendConfig:

  1. 建立 BackendConfig。
  2. 建立 Service,將 Service 的其中一個通訊埠與 BackendConfig 建立關聯。
  3. 建立 Ingress,將 Ingress 與 (Service、通訊埠) 組合建立關聯。

事前準備

如要準備這項工作,請執行下列步驟:

  • 確認您已啟用 Google Kubernetes Engine API。
  • 啟用 Google Kubernetes Engine API
  • 確認您已安裝 Cloud SDK
  • 設定預設的專案 ID
    gcloud config set project [PROJECT_ID]
  • 如果您使用區域叢集,請設定預設的運算區域
    gcloud config set compute/zone [COMPUTE_ZONE]
  • 如果您使用地區叢集,請設定預設的運算地區
    gcloud config set compute/region [COMPUTE_REGION]
  • gcloud 更新到最新版本:
    gcloud components update

建立命名空間

為本指南中的物件建立 Kubernetes 命名空間:

kubectl create namespace cloud-armor-how-to

建立部署

這個部署資訊清單宣告您要執行 hello-app 網路應用程式的兩個備用資源:

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: cloud-armor-how-to
  name: my-deployment
spec:
  selector:
    matchLabels:
      app: hello-app
  replicas: 2
  template:
    metadata:
      labels:
        app: hello-app
    spec:
      containers:
      - name: hello-app-container
        image: gcr.io/google-samples/hello-app:1.0
        ports:
        - containerPort: 8080

將資訊清單複製到名為 my-deployment.yaml 的檔案,然後建立部署:

kubectl apply -f my-deployment.yaml

建立 Google Cloud Armor 安全性政策與規則

建立 Google Cloud Armor 安全性政策:

gcloud beta compute security-policies create ca-how-to-security-policy \
    --description "policy for Google Cloud Armor how-to topic"

為您的安全性政策建立規則:

gcloud beta compute security-policies rules create 1000 \
    --security-policy ca-how-to-security-policy \
    --description "Deny traffic from 192.0.2.0/24." \
    --src-ip-ranges "192.0.2.0/24" \
    --action "deny-404"

查看安全性政策:

gcloud beta compute security-policies describe ca-how-to-security-policy

輸出:

...
kind: compute#securityPolicy
name: ca-how-to-security-policy
rules:
- action: deny(404)
  description: Deny traffic from 192.0.2.0/24.
  kind: compute#securityPolicyRule
  match:
    config:
      srcIpRanges:
      - 192.0.2.0/24
    versionedExpr: SRC_IPS_V1
  preview: false
  priority: 1000
  ...

建立 BackendConfig

以下是 BackendConfig 的資訊清單。資訊清單會指定安全性政策:

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  namespace: cloud-armor-how-to
  name: my-backend-config
spec:
  securityPolicy:
    name: "ca-how-to-security-policy"

將資訊清單複製到名為 my-backend-config.yaml 的檔案,然後建立 BackendConfig:

kubectl apply -f my-backend-config.yaml

查看 BackendConfig:

kubectl get backendconfig my-backend-config --namespace cloud-armor-how-to --output yaml

輸出會顯示指定的安全性政策:

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  name: my-backend-config
  namespace: cloud-armor-how-to
  ...
spec:
  securityPolicy:
    name: ca-how-to-security-policy

建立服務

以下是 Service 的資訊清單:

apiVersion: v1
kind: Service
metadata:
  namespace: cloud-armor-how-to
  name: my-service
  labels:
    app: hello-app
  annotations:
    beta.cloud.google.com/backend-config: '{"ports": {"80":"my-backend-config"}}'
spec:
  type: NodePort
  selector:
    app: hello-app
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080

將資訊清單儲存到名為 my-service.yaml 的檔案,然後建立 Service:

kubectl apply -f my-service.yaml

查看 Service:

kubectl get service my-service --namespace cloud-armor-how-to --output yaml

指令會輸出類似以下的結果:

apiVersion: v1
kind: Service
metadata:
  annotations:
    beta.cloud.google.com/backend-config: '{"ports": {"80":"my-backend-config"}}'
  labels:
    app: hello-app
  name: my-service
  namespace: cloud-armor-how-to
  ...
spec:
  clusterIP: 10.19.249.137
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 32629
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: hello-app
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}

針對本練習的目的,以下是 Service 需要注意的重要事項:

  • Service 的通訊埠 80 會與名為 my-backend-config 的 BackendConfig 相關聯。這是由 beta.cloud.google.com/backend-config 註解所指定。

  • Service 具有 NodePort 類型。這是要與 Ingress 建立關聯的 Service 所需要的類型。

  • 任何具有 app: hello-app 標籤的 Pod 都是 Service 的成員。這是由 selector 欄位所指定。

  • 導向 TCP 通訊埠 80 上服務的流量會轉送到其中一個成員 Pod 中的 TCP 通訊埠 8080。這是由 porttargetPort 欄位所指定。

保留靜態外部 IP 位址

預留靜態外部 IP 位址:

gcloud compute addresses create cloud-armor-how-to-address --global

查看靜態外部 IP 位址:

gcloud compute addresses list --filter "name=cloud-armor-how-to-address"

輸出:

NAME                        REGION  ADDRESS        STATUS
cloud-armor-how-to-address          203.0.113.2    RESERVED

建立輸入

以下是 Ingress 的資訊清單:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  namespace: cloud-armor-how-to
  name: my-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: "cloud-armor-how-to-address"
spec:
  backend:
    serviceName: my-service
    servicePort: 80

將資訊清單複製到名為 my-ingress.yaml 的檔案,然後建立 Ingress:

kubectl create -f my-ingress.yaml

請稍候幾分鐘,讓 Kubernetes Ingress 控制器設定 Cloud 負載平衡器,然後查看 Ingress:

kubectl get ingress my-ingress --output yaml --namespace cloud-armor-how-to

輸出:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  namespace: cloud-armor-how-to
  ...
spec:
  backend:
    serviceName: my-service
    servicePort: 80
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.2

針對本練習的目的,以下是 Ingress 需要注意的重要事項:

  • 連入流量的 IP 位址列於 loadBalancer:ingress: 底下。

  • Ingress 有一個規則會套用到任何主機提出的傳入 HTTP 要求。這是因為規則中沒有任何 host 欄位。因此根據預設,這個規則會套用到所有主機。

  • 不論網址路徑為何,系統對所有傳入要求都視為相同。這是透過 path/* 指定。

  • 傳入要求會路由到 Pod,該 Pod 為 my-service 的成員。在本練習中,成員 Pod 具有標籤 app: hello-app

  • 要求會轉送到 my-service 中指定的目標通訊埠上的 Pod。在本練習中,Pod 目標通訊埠為 8080。

查看網路應用程式

請稍候幾分鐘。接著,在瀏覽器中,輸入您的靜態外部 IP 位址。

這個頁面會顯示來自 hello-app 網路應用程式的回應。這個網路應用程式是在部署的其中一個 Pod 中執行。

Hello, world!
Version: 1.0.0
Hostname: my-deployment-574ddbdf88-f9fbj

使用 curl 查看網路應用程式:

curl -v [STATIC_ADDRESS]

其中,[STATIC_ADDRESS] 是您的靜態外部 IP 位址。

輸出內容為來自 hello-app 的回應:

Hello, world!
Version: 1.0.0
Hostname: my-deployment-574ddbdf88-zpb94

卸離安全性政策

如要從輸入卸離安全性政策,請在 BackendConfig 中將安全性政策名稱設為空白。以下是卸離安全性政策的範例:

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  namespace: cloud-armor-how-to
  name: my-backend-config
spec:
  securityPolicy:
    name: ""

限制

配額限制

當這項功能在測試版階段時,可寫入的 Google Cloud Armor 規則的數量有固定限制。正式推出這項功能時,將會移除該限制。

僅支援 IP 許可清單和黑名單

Google Cloud Armor 僅支援 IP 許可清單和 IP 黑名單。

疑難排解

找不到 BackendConfig

如果 Service 註解已指定 Service 通訊埠的 BackendConfig,卻找不到實際的 BackendConfig 資源,就會發生這個錯誤。如果您尚未建立 BackendConfig 資源、在錯誤的命名空間中建立 BackendConfig 資源,或是在 Service 註解中拼錯參照名稱,都會發生這種情況。

kubectl get event
KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: error getting BackendConfig for port 80 on service "default/my-service":
no BackendConfig for service port exists

找不到安全性政策

建立 Ingress 物件之後,如果安全性政策沒有正確地與負載平衡器服務建立關聯,請評估 Kubernetes 事件,確認是否有設定錯誤。具體來說,如果 BackendConfig 指定不存在的政策,系統將會定期發出警告事件。 如要修正這個問題,請確認您在 BackendConfig 中指定正確的安全性政策名稱。

kubectl get event
KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: The given security policy "my-policy" does not exist.

清除

完成本頁面的練習後,為避免您的帳戶產生不必要的費用,請按照以下步驟移除資源:

刪除您為本練習建立的 Kubernetes 物件:

kubectl delete ingress my-ingress --namespace cloud-armor-how-to
kubectl delete service my-service --namespace cloud-armor-how-to
kubectl delete backendconfig my-backend-config --namespace cloud-armor-how-to
kubectl delete deployment my-deployment --namespace cloud-armor-how-to
kubectl delete namespace cloud-armor-how-to

刪除您的靜態外部 IP 位址:

gcloud compute addresses delete cloud-armor-how-to-address --global

刪除您的安全性政策:

gcloud beta compute security-policies delete ca-how-to-security-policy

後續步驟

本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Kubernetes Engine 說明文件