Istio で Kubernetes Service を保護する

このチュートリアルは、Istio サービス メッシュを使用して Kubernetes Services を安全にデプロイし、相互 TLS(mTLS)通信を有効にする方法に関心がある Kubernetes ユーザーと管理者を対象としています。

Istio と Cloud Service Mesh

Istio は、サポートされている Google プロダクトではありません。代わりにマネージド Cloud Service Mesh を実行することをおすすめします。詳細については、GKE Autopilot クラスタで Cloud Service Mesh をプロビジョニングするをご覧ください。

Cloud Service Mesh には次のようなメリットがあります。

  • istioctl などのクライアントサイドのツールを必要とせず、Fleet API を使ってマネージド Cloud Service Mesh をプロビジョニングできます。
  • Cloud Service Mesh は、昇格した権限をコンテナに付与することなく、ワークロードにサイドカー プロキシを自動的に挿入します。
  • 追加の構成なしでメッシュとサービスの詳細なダッシュボードを表示し、その指標を使用することで、サービスレベル目標(SLO)とアラートを構成して、アプリケーションの状況をモニタリングできます。
  • マネージド Cloud Service Mesh コントロール プレーンが自動的にアップグレードされるので、最新のセキュリティ パッチと機能を確実に得られます。
  • Cloud Service Mesh マネージド データプレーンによってワークロードのサイドカー プロキシが自動的にアップグレードするため、プロキシのアップグレードとセキュリティ パッチが提供されたときに自分でサービスを再起動する必要がありません。
  • Cloud Service Mesh はサポートされているプロダクトであり、標準のオープンソースの Istio API を使用して構成できます。詳しくは、サポートされている機能をご覧ください。

環境を準備する

環境の設定手順は次のとおりです。

  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. Envoy サイドカー プロキシの自動挿入を有効にするよう Istio に指示する名前空間ラベルを追加します。

    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 を Ingress コントローラとして使用する Istio の Gateway および VirtualService のリソースが記述されています。

  5. マニフェストをクラスタに適用します。

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

mTLS を構成する

Istio では、相互 TLS(mTLS)認証がデフォルトで有効になっています。つまり、Istio は Istio プロキシに移行されたサーバー ワークロードをモニタリングし、これらのワークロードと mTLS 接続を確立するようにクライアント プロキシを自動的に構成します。Istio はまた、サイドカー プロキシのないワークロードに接続するときには、mTLS を使用しないようにクライアント プロキシを構成します。

Istio では、次の 3 つのモードで動作するように mTLS を構成できます。

  • PERMISSIVE: ワークロードは mTLS と書式なしテキストのトラフィックの両方を受け入れます。
  • STRICT: ワークロードは mTLS トラフィックのみを受け入れます。
  • DISABLE: mTLS は無効です。独自のセキュリティ ソリューションを使用する場合は、このモードを使用します。

mTLS 構成はグローバル、名前空間ごと、またはワークロードごとに適用できます。このチュートリアルでは、STRICT mTLS モードを使用して Namespace ごとに構成を適用します。

  1. 次のマニフェストを確認します。

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

    このマニフェストには、Peer Authentication Istio Custom Resource が記述されています。

  2. マニフェストをクラスタに適用します。

    kubectl apply -f peer-authentication.yaml
    

Istio の mTLS の詳細については、相互 TLS 認証をご覧ください。

mTLS が有効になっていることを確認する

Kiali は、Istio サービス メッシュ用のウェブベースのオブザーバビリティ ダッシュボードです。マイクロサービス環境のグラフが表示され、アプリケーションのモニタリングとトラブルシューティングを行うことができます。Kiali を使用すると、Istio サービス メッシュで mTLS 認証が有効になっていて、正しく機能していることを確認できます。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.iam.gserviceaccount.com" \
        --role roles/monitoring.viewer
    gcloud iam service-accounts add-iam-policy-binding \
      monitoring@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/iam.workloadIdentityUser \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[monitoring/default]"
    
  2. Kubernetes Namespace を作成します。

    kubectl create namespace monitoring
    
  3. Namespace のデフォルトの Kubernetes サービス アカウントにアノテーションを付けて、GKE の Workload Identity 連携を構成します。

    kubectl annotate serviceaccount -n monitoring default \
        iam.gke.io/gcp-service-account=monitoring@PROJECT_ID.iam.gserviceaccount.com --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

    このマニフェストでは、Istio と Envoy Proxy の指標を収集する PodMonitoring リソースを記述します。

  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
    

    Pod が Running の場合は、Ctrl+C を押してコマンドラインに戻ります。

  5. ダッシュボードにアクセスするために、Kiali サーバー Service でポート転送を設定します。

    kubectl -n istio-system port-forward svc/kiali 8080:20001
    
  6. ウェブ プレビューを開きます。Kiali で、[Graph] セクションに移動し、[Display] プルダウンで [Security] オプションを選択します。このビューには、グラフ内の各ノードのセキュリティ状態が表示されます。mTLS 有効のバッジがあるノードは、そのサービスで mTLS が有効であることを示し、バッジのないノードは mTLS が有効になっていないことを示します。