ドライラン

このタスクでは、新しい実験的なアノテーションistio.io/dry-runを使用して、ポリシーを実際に適用せずにドライランすることで、Istioの認可ポリシーを設定する方法を示します。

ドライランのアノテーションを使用すると、認可ポリシーを本番トラフィックに適用する前に、その効果をより良く理解できます。これにより、誤った認可ポリシーによって本番トラフィックが中断するリスクを軽減できます。

始める前に

このタスクを開始する前に、次のことを行ってください。

  • Istioの認可の概念を読んでください。

  • Istioのインストールガイドに従ってIstioをインストールしてください。

  • ドライランのトレース結果を確認するためにZipkinをデプロイします。Zipkinタスクに従って、クラスターにZipkinをインストールしてください。

  • ドライランのメトリック結果を確認するためにPrometheusをデプロイします。Prometheusタスクに従って、クラスターにPrometheusをインストールしてください。

  • テストワークロードをデプロイします

    このタスクでは、httpbincurlの2つのワークロードを使用します。どちらも名前空間fooにデプロイされます。両方のワークロードはEnvoyプロキシサイドカーで実行されます。次のコマンドでfoo名前空間を作成し、ワークロードをデプロイします。

    ZipZip
    $ kubectl create ns foo
    $ kubectl label ns foo istio-injection=enabled
    $ kubectl apply -f @samples/httpbin/httpbin.yaml@ -n foo
    $ kubectl apply -f @samples/curl/curl.yaml@ -n foo
    
  • ドライランのログ結果を確認するためにプロキシのデバッグレベルのログを有効にします

    $ istioctl proxy-config log deploy/httpbin.foo --level "rbac:debug" | grep rbac
    rbac: debug
    
  • 次のコマンドでcurlhttpbinにアクセスできることを確認します

    $ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl http://httpbin.foo:8000/ip -s -o /dev/null -w "%{http_code}\n"
    200
    

ドライランポリシーの作成

  1. 次のコマンドで、ドライランのアノテーション"istio.io/dry-run": "true"を使用して認可ポリシーを作成します

    $ kubectl apply -n foo -f - <<EOF
    apiVersion: security.istio.io/v1
    kind: AuthorizationPolicy
    metadata:
      name: deny-path-headers
      annotations:
        "istio.io/dry-run": "true"
    spec:
      selector:
        matchLabels:
          app: httpbin
      action: DENY
      rules:
      - to:
        - operation:
            paths: ["/headers"]
    EOF
    

    次のコマンドを使用すると、既存の認可ポリシーをすばやくドライランモードに変更することもできます

    $ kubectl annotate --overwrite authorizationpolicies deny-path-headers -n foo istio.io/dry-run='true'
    
  2. ポリシーがドライランモードで作成されているため、パス/headersへのリクエストが許可されていることを確認します。次のコマンドを実行して、curlからhttpbinに20件のリクエストを送信します。このリクエストには、常にZipkinトレースをトリガーするためのヘッダーX-B3-Sampled: 1が含まれています

    $ for i in {1..20}; do kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl http://httpbin.foo:8000/headers -H "X-B3-Sampled: 1" -s -o /dev/null -w "%{http_code}\n"; done
    200
    200
    200
    ...
    

プロキシログでのドライラン結果の確認

ドライランの結果は、shadow denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]の形式でプロキシのデバッグログにあります。次のコマンドを実行してログを確認します

$ kubectl logs "$(kubectl -n foo -l app=httpbin get pods -o jsonpath={.items..metadata.name})" -c istio-proxy -n foo | grep "shadow denied"
2021-11-19T20:20:48.733099Z debug envoy rbac shadow denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]
2021-11-19T20:21:45.502199Z debug envoy rbac shadow denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]
2021-11-19T20:22:33.065348Z debug envoy rbac shadow denied, matched policy ns[foo]-policy[deny-path-headers]-rule[0]
...

ログの詳細については、トラブルシューティングガイドも参照してください。

Prometheus を使用したメトリクスでのドライラン結果の確認

  1. 次のコマンドでPrometheusダッシュボードを開きます

    $ istioctl dashboard prometheus
    
  2. Prometheusダッシュボードで、次のメトリックを検索します

    envoy_http_inbound_0_0_0_0_80_rbac{authz_dry_run_action="deny",authz_dry_run_result="denied"}
    
  3. クエリされたメトリックの結果を次のように確認します

    envoy_http_inbound_0_0_0_0_80_rbac{app="httpbin",authz_dry_run_action="deny",authz_dry_run_result="denied",instance="10.44.1.11:15020",istio_io_rev="default",job="kubernetes-pods",kubernetes_namespace="foo",kubernetes_pod_name="httpbin-74fb669cc6-95qm8",pod_template_hash="74fb669cc6",security_istio_io_tlsMode="istio",service_istio_io_canonical_name="httpbin",service_istio_io_canonical_revision="v1",version="v1"}  20
    
  4. クエリされたメトリックの値は20です(送信したリクエスト数によっては異なる値になる場合があります。値が0より大きければ問題ありません)。これは、ポート80httpbinワークロードに適用されたドライランポリシーが1つのリクエストに一致したことを意味します。ポリシーがドライランモードでなかった場合、そのリクエストは拒否されます。

  5. 以下はPrometheusダッシュボードのスクリーンショットです

    Prometheus dashboard
    Prometheusダッシュボード

Zipkin を使用したトレーシングでのドライラン結果の確認

  1. 次のコマンドでZipkinダッシュボードを開きます

    $ istioctl dashboard zipkin
    
  2. curlからhttpbinへのリクエストのトレース結果を見つけます。Zipkinの遅延によりトレース結果が表示されない場合は、さらにリクエストを送信してみてください。

  3. トレース結果では、名前空間fooのドライランポリシーdeny-path-headersによってリクエストが拒否されたことを示す次のカスタムタグが見つかるはずです

    istio.authorization.dry_run.deny_policy.name: ns[foo]-policy[deny-path-headers]-rule[0]
    istio.authorization.dry_run.deny_policy.result: denied
    
  4. 以下はZipkinダッシュボードのスクリーンショットです

    Zipkin dashboard
    Zipkinダッシュボード

まとめ

プロキシのデバッグログ、Prometheusメトリック、Zipkinトレースの結果は、ドライランポリシーがリクエストを拒否することを示しています。ドライランの結果が期待どおりでない場合は、ポリシーをさらに変更できます。

より多くの本番トラフィックでテストできるように、ドライランポリシーをしばらく維持することをお勧めします。

ドライランの結果に確信が持てたら、ドライランモードを無効にして、ポリシーが実際にリクエストを拒否するように開始できます。これは、次のいずれかの方法で実現できます

  • ドライランのアノテーションを完全に削除します。または

  • ドライランのアノテーションの値をfalseに変更します。

制限事項

ドライランのアノテーションは現在実験段階であり、次の制限があります

  • ドライランのアノテーションは現在、ALLOWポリシーとDENYポリシーのみをサポートしています。

  • プロキシでALLOWポリシーとDENYポリシーが別々に適用されるという事実により、ALLOWポリシーとDENYポリシーに対して2つの個別のドライラン結果(つまり、ログ、メトリック、トレースタグ)があります。リクエストはALLOWポリシーによって許可される可能性があっても、別のDENYポリシーによって拒否される可能性があるため、両方のドライラン結果を考慮する必要があります。

  • プロキシログ、メトリック、トレースのドライラン結果は手動トラブルシューティング用であり、事前の通知なしにいつでも変更される可能性があるため、APIとして使用しないでください。

クリーンアップ

  1. 構成から名前空間fooを削除します

    $ kubectl delete namespace foo
    
  2. 不要になった場合はPrometheusとZipkinを削除します。

この情報は役に立ちましたか?
改善のための提案はありますか?

フィードバックありがとうございます!