使用 Istio 保護 Kubernetes 服務

本教學課程適用於對使用 Istio 服務網格感興趣的 Kubernetes 使用者和管理員,瞭解如何安全地部署 Kubernetes 服務,並啟用相互 TLS (mTLS) 通訊。

Istio 和 Cloud Service Mesh

Istio 不是 Google 支援的產品。建議您改用代管的 Cloud Service Mesh。詳情請參閱「在 GKE 上佈建代管 Cloud Service Mesh 控制層」。

Cloud Service Mesh 具有下列優點:

  • 您可以使用 Fleet API 佈建受管理 Cloud Service Mesh,不必使用 istioctl 等用戶端工具。
  • Cloud Service Mesh 會自動將 Sidecar Proxy 插入工作負載,不必授予容器進階權限。
  • 您無須進行任何額外設定,即可查看網格和服務的豐富資訊主頁,然後使用這些指標設定服務水準目標 (SLO) 和快訊,監控應用程式的健康狀態。
  • 系統會自動升級代管 Cloud Service Mesh 控制層,確保您取得最新的安全性修補程式和功能。
  • Cloud Service Mesh 代管資料層會自動升級工作負載中的 Sidecar Proxy,因此當 Proxy 升級和安全修補程式可用時,您不需要自行重新啟動服務。
  • Cloud Service Mesh 是受支援的產品,可使用標準開放原始碼 Istio API 進行設定。詳情請參閱支援的功能

目標

本教學課程包含下列步驟:

  • 建立 GKE Autopilot 叢集。
  • 使用 istioctl 指令列工具安裝 Istio。
  • 部署範例應用程式,測試雙向傳輸層安全標準 (mTLS) 驗證。
  • 設定 Istio,使用 PeerAuthentication 自訂資源,透過 mTLS 驗證服務間的通訊。
  • 使用 Kiali 資訊主頁驗證 mTLS 驗證。

費用

在本文件中,您會使用下列 Google Cloud的計費元件:

如要根據預測用量估算費用,請使用 Pricing Calculator

初次使用 Google Cloud 的使用者可能符合免費試用期資格。

完成本文所述工作後,您可以刪除建立的資源,避免繼續計費,詳情請參閱「清除所用資源」。

事前準備

Cloud Shell 已預先安裝本教學課程所需的軟體,包括 kubectlgcloud CLITerraform。如果您未使用 Cloud Shell,則必須安裝 gcloud CLI。

  1. 安裝 Google Cloud CLI。

  2. 設定 gcloud CLI,使用您的聯合身分。

    詳情請參閱「使用聯合身分登入 gcloud CLI」。

  3. 執行下列指令,初始化 gcloud CLI:

    gcloud init
  4. 建立或選取 Google Cloud 專案

    選取或建立專案所需的角色

    • 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您已獲授角色,即可選取任何專案。
    • 建立專案:如要建立專案,您需要「專案建立者」角色 (roles/resourcemanager.projectCreator),其中包含 resourcemanager.projects.create 權限。瞭解如何授予角色
    • 建立 Google Cloud 專案:

      gcloud projects create PROJECT_ID

      PROJECT_ID 替換為您要建立的 Google Cloud 專案名稱。

    • 選取您建立的 Google Cloud 專案:

      gcloud config set project PROJECT_ID

      PROJECT_ID 替換為 Google Cloud 專案名稱。

  5. 確認專案已啟用計費功能 Google Cloud

  6. 啟用 GKE API:

    啟用 API 時所需的角色

    如要啟用 API,您需要具備服務使用情形管理員 IAM 角色 (roles/serviceusage.serviceUsageAdmin),其中包含 serviceusage.services.enable 權限。瞭解如何授予角色

    gcloud services enable container.googleapis.com
  7. 將角色授予使用者帳戶。針對下列每個 IAM 角色,執行一次下列指令: roles/container.clusterAdmin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE

    更改下列內容:

準備環境

如要設定環境,請按照下列步驟操作:

  1. 設定環境變數:

    export PROJECT_ID=PROJECT_ID
    gcloud config set project $PROJECT_ID
    gcloud config set compute/region us-central1
    

    PROJECT_ID 替換為 Google Cloud專案 ID

  2. 複製 GitHub 存放區:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
    
  3. 變更為工作目錄:

    cd kubernetes-engine-samples/service-mesh/istio-tutorial
    

建立 GKE 叢集

啟用 Istio 要求的 Linux 功能:NET_RAWNET_ADMIN。 根據預設,GKE Autopilot 不允許 NET_ADMIN,但您可以在 GKE 1.27 以上版本中,使用 --workload-policies=allow-net-admin 指令啟用 NET_ADMIN

gcloud container clusters create-auto istio-cluster \
    --location="us-central1" \
    --workload-policies="allow-net-admin"

如要進一步瞭解 GKE Autopilot 安全性,請參閱「內建安全設定」。

安裝 Istio

您可以使用 Istioctl 在 GKE 叢集上安裝 Istio。

在本教學課程中,您將安裝 Istio,並使用建議用於實際工作環境部署作業的預設組態設定檔

  1. 安裝 Istio:

    • 如要安裝最新版 Istio,請按照下列步驟操作:

      curl -L https://istio.io/downloadIstio | sh -
      
    • 如要安裝特定版本的 Istio,請按照下列步驟操作:

      export ISTIO_VERSION=VERSION_NUMBER
      curl -L https://istio.io/downloadIstio | TARGET_ARCH=$(uname -m) sh -
      

      VERSION_NUMBER 替換為要安裝的 Istio 版本。如要瞭解 Istio 版本,請參閱「版本公告」。

  2. istioctl 指令列工具新增至 PATH:

    cd istio-*
    export PATH=$PWD/bin:$PATH
    
  3. 在叢集上安裝 Istio:

    istioctl install --set profile="default" -y
    

    這個步驟可能需要幾分鐘的時間。

  4. 等待 Istio Pod 準備就緒:

    watch kubectl get pods -n istio-system
    

    輸出結果會與下列內容相似:

    NAME                                    READY   STATUS        RESTARTS   AGE
    istio-ingressgateway-5c47bff876-wjm96   1/1     Running       0          2m54s
    istiod-5fc7cb65cd-k8cp4                 1/1     Running       0          2m57s
    

    當 Istio Pod 處於 Running 狀態時,請按下 Ctrl+C 返回指令列。

部署範例應用程式

在本節中,您將使用 Bank of Anthos 範例應用程式建立服務網格,並啟用 mTLS 驗證。

  1. 新增命名空間標籤,指示 Istio 啟用 Envoy 補充資訊 Proxy 的自動插入功能:

    kubectl label namespace default istio-injection=enabled
    
  2. 部署範例應用程式:

    cd ..
    git clone https://github.com/GoogleCloudPlatform/bank-of-anthos.git
    kubectl apply -f bank-of-anthos/extras/jwt/jwt-secret.yaml
    kubectl apply -f bank-of-anthos/kubernetes-manifests/
    
  3. 等待應用程式準備就緒:

    watch kubectl get pods
    

    輸出結果會與下列內容相似:

    NAME                                 READY   STATUS    RESTARTS   AGE
    accounts-db-0                        2/2     Running   0          2m16s
    balancereader-5c695f78f5-x4wlz       2/2     Running   0          3m8s
    contacts-557fc79c5-5d7fg             2/2     Running   0          3m7s
    frontend-7dd589c5d7-b4cgq            2/2     Running   0          3m7s
    ledger-db-0                          2/2     Running   0          3m6s
    ledgerwriter-6497f5cf9b-25c6x        2/2     Running   0          3m5s
    loadgenerator-57f6896fd6-lx5df       2/2     Running   0          3m5s
    transactionhistory-6c498965f-tl2sk   2/2     Running   0          3m4s
    userservice-95f44b65b-mlk2p          2/2     Running   0          3m4s
    

    Pod Running 後,請按下 Ctrl+C 返回指令列。

  4. 請查看下列資訊清單:

    # Copyright 2020 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: frontend-gateway
    spec:
      selector:
        istio: ingressgateway # use Istio default gateway implementation
      servers:
      - port:
          number: 80
          name: http
          protocol: HTTP
        hosts:
        - "*"
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: frontend-ingress
    spec:
      hosts:
      - "*"
      gateways:
      - frontend-gateway
      http:
      - route:
        - destination:
            host: frontend
            port:
              number: 80

    這個資訊清單會說明 Istio Gateway 和 VirtualService 資源,這些資源會公開應用程式,並將 Istio 做為 Ingress 控制器。

  5. 將資訊清單套用至叢集:

    kubectl apply -f bank-of-anthos/extras/istio/frontend-ingress.yaml
    

設定 mTLS

Istio 預設會啟用相互傳輸層安全標準 (mTLS) 驗證。也就是說,Istio 會監控已遷移至 Istio Proxy 的伺服器工作負載,並自動設定用戶端 Proxy,與這些工作負載建立 mTLS 連線。此外,Istio 也會設定用戶端 Proxy,在連線至沒有 Sidecar Proxy 的工作負載時,不要使用 mTLS。

Istio 可設定 mTLS,在下列三種模式中運作:

  • PERMISSIVE:工作負載可接受 mTLS 和純文字流量。
  • STRICT:工作負載只接受 mTLS 流量。
  • DISABLE:mTLS 已停用。如要使用自己的安全解決方案,請使用這個模式。

您可以全域、依命名空間或依工作負載套用 mTLS 設定。在本教學課程中,您將使用 STRICT mTLS 模式,為每個命名空間套用設定。

  1. 請查看下列資訊清單:

    apiVersion: security.istio.io/v1beta1
    kind: PeerAuthentication
    metadata:
      name: default
    spec:
      mtls:
          mode: STRICT

    這個資訊清單說明對等互連驗證 Istio 自訂資源。

  2. 將資訊清單套用至叢集:

    kubectl apply -f peer-authentication.yaml
    

如要進一步瞭解 Istio 中的 mTLS,請參閱「相互 TLS 驗證」。

確認已啟用 mTLS

Kiali 是 Istio 服務網格的網頁式觀測能力資訊主頁,可提供微服務環境的圖形檢視畫面,方便您監控及疑難排解應用程式問題。您可以使用 Kiali 驗證 mTLS 驗證是否已啟用,且在 Istio 服務網格中正常運作。Kiali 需要 Prometheus 做為遙測資料來源。本教學課程使用 Google Cloud Managed Service for Prometheus

安裝查詢介面

  1. 使用 roles/monitoring.viewer 建立 IAM 服務帳戶,允許查詢介面存取指標:

    gcloud iam service-accounts create monitoring \
        --display-name="Service account for query interface"
    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member "serviceAccount:monitoring@PROJECT_ID." \
        --role roles/monitoring.viewer
    gcloud iam service-accounts add-iam-policy-binding \
      monitoring@PROJECT_ID. \
        --role roles/iam.workloadIdentityUser \
        --member "serviceAccount:PROJECT_ID.[monitoring/default]"
    
  2. 建立 Kubernetes 命名空間:

    kubectl create namespace monitoring
    
  3. 在命名空間中註解預設 Kubernetes 服務帳戶,以設定 Workload Identity Federation for GKE

    kubectl annotate serviceaccount -n monitoring default \
        iam.gke.io/gcp-service-account=monitoring@PROJECT_ID. --overwrite
    
  4. 部署查詢介面工作負載:

    kubectl -n monitoring apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/prometheus-engine/v0.7.1/examples/frontend.yaml
    
  5. 請查看下列資訊清單:

    apiVersion: monitoring.googleapis.com/v1
    kind: PodMonitoring
    metadata:
      name: istiod
      namespace: istio-system
    spec:
      selector:
        matchLabels:
          app: istiod
      endpoints:
      - port: 15014
        path: /metrics
        timeout: 30s
        interval: 60s

    這份資訊清單說明 PodMonitoring 資源,用於收集 Istio 和 Envoy Proxy 指標。

  6. 將資訊清單套用至叢集:

    kubectl apply -f pod-monitorings.yaml
    
  7. 取得範例應用程式的連結:

    INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    echo "http://$INGRESS_HOST"
    
  8. 開啟連結即可查看範例應用程式。使用預設使用者名稱和密碼登入,在微服務之間產生流量。

安裝 Kiali

建議您使用 Kiali Operator 安裝 Kiali。

  1. 安裝 Kiali Operator:

    helm repo add kiali https://kiali.org/helm-charts
    helm repo update
    helm install \
        --namespace kiali-operator \
        --create-namespace \
        kiali-operator \
        kiali/kiali-operator
    
  2. 請查看下列資訊清單:

    apiVersion: kiali.io/v1alpha1
    kind: Kiali
    metadata:
      name: kiali
      namespace: istio-system
    spec:
      deployment:
        namespace: istio-system
      auth:
        strategy: anonymous
      external_services:
        custom_dashboards:
          prometheus:
            url: "http://frontend.monitoring:9090/"
            auth:
              type: none
        prometheus:
          url: "http://frontend.monitoring:9090/"
          auth:
            type: none
        tracing:
          enabled: false
        grafana:
          enabled: false

    這個資訊清單說明定義 Kiali 伺服器的 Operator 自訂資源。

  3. 將資訊清單套用至叢集:

    kubectl apply -f kiali.yaml
    
  4. 等待 Kiali 伺服器準備就緒:

    watch kubectl get pods -n istio-system
    

    輸出結果會與下列內容相似:

    NAME                                    READY   STATUS    RESTARTS   AGE
    istio-ingressgateway-6845466857-92zp8   1/1     Running   0          9m11s
    istiod-6b47d84cf-4cqlt                  1/1     Running   0          12m
    kiali-5f6b7c8d9-abcde                   1/1     Running   0          1m
    

    Pod Running 後,請按下 Ctrl+C 返回指令列。

  5. 在 Kiali 伺服器服務上設定通訊埠轉送,以便存取資訊主頁:

    kubectl -n istio-system port-forward svc/kiali 8080:20001
    
  6. 開啟網頁預覽。在 Kiali 中,前往「Graph」部分,然後在「Display」下拉式選單中選取「Security」選項。這個檢視畫面會顯示圖表中每個節點的安全狀態。如果節點顯示「已啟用 mTLS」徽章,表示該服務已啟用 mTLS;如果節點未顯示徽章,表示 mTLS 未啟用。

清除所用資源

為避免因為本教學課程所用資源,導致系統向 Google Cloud 收取費用,請刪除含有相關資源的專案,或者保留專案但刪除個別資源。

刪除專案

    刪除 Google Cloud 專案:

    gcloud projects delete PROJECT_ID

刪除個別資源

如果您使用現有專案,但不想刪除專案,請刪除個別資源。

  1. 刪除 Kiali:

    kubectl -n istio-system delete kiali kiali
    helm uninstall --namespace kiali-operator kiali-operator
    
  2. 刪除監控資源:

    kubectl -n monitoring delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/prometheus-engine/v0.7.1/examples/frontend.yaml
    
  3. 刪除範例應用程式:

    kubectl delete -f bank-of-anthos/extras/istio/frontend-ingress.yaml
    kubectl delete -f bank-of-anthos/kubernetes-manifests
    
  4. 解除安裝 Istio:

    istioctl uninstall --purge -y
    
  5. 刪除 GKE 叢集:

    gcloud container clusters delete --location us-central1 istio-cluster --quiet
    

後續步驟