ネットワークセキュリティ - Amazon EKS

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

ネットワークセキュリティ

ネットワークセキュリティにはいくつかのファセットがあります。1 つ目は、サービス間のネットワークトラフィックの流れを制限するルールの適用です。2 つ目は、転送中のトラフィックの暗号化です。EKS にこれらのセキュリティ対策を実装するメカニズムはさまざまですが、多くの場合、次の項目が含まれます。

トラフィックコントロール

  • ネットワークポリシー

  • セキュリティグループ

ネットワーク暗号化

  • サービスメッシュ

  • コンテナネットワークインターフェイス (CNIs)

  • Ingress Controllers と Load Balancer

  • Nitro インスタンス

  • cert-manager を使用する ACM プライベート CA

ネットワークポリシー

Kubernetes クラスター内では、すべての Pod 間通信がデフォルトで許可されています。この柔軟性は実験の促進に役立ちますが、安全とは見なされません。Kubernetes ネットワークポリシーは、ポッド間 (多くの場合、東部/西部トラフィック) およびポッドと外部サービス間のネットワークトラフィックを制限するメカニズムを提供します。Kubernetes ネットワークポリシーは、OSI モデルのレイヤー 3 と 4 で動作します。ネットワークポリシーは、ポッド、名前空間セレクタ、ラベルを使用して送信元ポッドと送信先ポッドを識別しますが、IP アドレス、ポート番号、プロトコル、またはこれらの組み合わせを含めることもできます。ネットワークポリシーは、多くの場合、イングレスルールとエグレスルールと呼ばれるポッドへのインバウンド接続とアウトバウンド接続の両方に適用できます。

Amazon VPC CNI プラグインのネイティブネットワークポリシーのサポートにより、ネットワークポリシーを実装して、kubernetes クラスター内のネットワークトラフィックを保護できます。これにより、アップストリームの Kubernetes ネットワークポリシー API と統合され、Kubernetes 標準との互換性と準拠が保証されます。アップストリーム API でサポートされているさまざまな識別子を使用してポリシーを定義できます。デフォルトでは、すべてのイングレストラフィックとエグレストラフィックがポッドに許可されます。policyType Ingress を持つネットワークポリシーが指定されている場合、ポッドへの許可された接続のみがポッドのノードからの接続であり、イングレスルールで許可されている接続です。出力ルールにも同じことが当てはまります。複数のルールが定義されている場合、すべてのルールの結合が決定時に考慮されます。したがって、評価の順序はポリシー結果には影響しません。

重要

EKS クラスターを初めてプロビジョニングする場合、VPC CNI ネットワークポリシー機能はデフォルトで有効になっていません。これを有効にするには、サポートされている VPC CNI アドオンバージョンをデプロイし、vpc-cni アドオンtrueENABLE_NETWORK_POLICYフラグを に設定します。詳細な手順については、Amazon EKS ユーザーガイドを参照してください。

レコメンデーション

ネットワークポリシーの開始方法 - 最小特権の原則に従う

デフォルトの拒否ポリシーを作成する

RBAC ポリシーと同様に、ネットワークポリシーでは最小特権のアクセス原則に従うことをお勧めします。まず、名前空間で を使用してすべてのインバウンドトラフィックとアウトバウンドトラフィックを制限するすべてのポリシーを拒否します。

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny namespace: default spec: podSelector: {} policyTypes: - Ingress - Egress

default-deny

default-deny
注記

上記のイメージは、Tufin のネットワークポリシービューワーによって作成されました。

DNS クエリを許可するルールを作成する

すべてのルールをデフォルトで拒否すると、ポッドが名前解決のために CoreDNS をクエリできるようにするルールなど、追加のルールのレイヤーを開始できます。

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-dns-access namespace: default spec: podSelector: matchLabels: {} policyTypes: - Egress egress: - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system podSelector: matchLabels: k8s-app: kube-dns ports: - protocol: UDP port: 53

allow-dns-access

allow-dns-access

名前空間/ポッド間のトラフィックフローを選択的に許可するルールを段階的に追加する

アプリケーションの要件を理解し、必要に応じてきめ細かな入出力ルールを作成します。以下の例は、ポート 80 の進入トラフィックを app-oneから に制限する方法を示していますclient-one。これにより、攻撃対象領域が最小限に抑えられ、不正アクセスのリスクが軽減されます。

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-ingress-app-one namespace: default spec: podSelector: matchLabels: k8s-app: app-one policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: k8s-app: client-one ports: - protocol: TCP port: 80

allow-ingress-app-one

allow-ingress-app-one

ネットワークポリシーの適用のモニタリング

  • ネットワークポリシーエディタを使用する

    • ネットワークポリシーエディタは、ネットワークフローログからの視覚化、セキュリティスコア、自動生成に役立ちます。

    • インタラクティブにネットワークポリシーを構築する

  • 監査ログ

    • EKS クラスターの監査ログを定期的に確認する

    • 監査ログは、ネットワークポリシーの変更など、クラスターで実行されたアクションに関する豊富な情報を提供します。

    • この情報を使用して、ネットワークポリシーへの経時的な変更を追跡し、不正または予期しない変更を検出します。

  • 自動テスト

    • 本番環境をミラーリングするテスト環境を作成し、ネットワークポリシーに違反しようとするワークロードを定期的にデプロイすることで、自動テストを実装します。

  • メトリクスのモニタリング

    • オブザーバビリティエージェントを設定して、VPC CNI ノードエージェントから prometheus メトリクスをスクレイプします。これにより、 はエージェントのヘルスと sdk エラーをモニタリングできます。

  • ネットワークポリシーを定期的に監査する

    • ネットワークポリシーを定期的に監査して、現在のアプリケーション要件を満たしていることを確認します。アプリケーションが進化するにつれて、監査により冗長な進入、退出ルールを削除し、アプリケーションに過剰なアクセス許可がないことを確認する機会が得られます。

  • Open Policy Agent (OPA) を使用してネットワークポリシーが存在することを確認する

    • 以下に示すような OPA ポリシーを使用して、アプリケーションポッドをオンボーディングする前にネットワークポリシーが常に存在することを確認します。このポリシーは、対応するネットワークポリシーが存在しないk8s-app: sample-app場合、ラベル付きの k8s ポッドのオンボーディングを拒否します。

package kubernetes.admission
import data.kubernetes.networkpolicies

deny[msg] {
    input.request.kind.kind == "Pod"
    pod_label_value := {v["k8s-app"] | v := input.request.object.metadata.labels}
    contains_label(pod_label_value, "sample-app")
    np_label_value := {v["k8s-app"] | v := networkpolicies[_].spec.podSelector.matchLabels}
    not contains_label(np_label_value, "sample-app")
    msg:= sprintf("The Pod %v could not be created because it is missing an associated Network Policy.", [input.request.object.metadata.name])
}
contains_label(arr, val) {
    arr[_] == val
}

トラブルシューティング

vpc-network-policy-controller、node-agent ログをモニタリングする

EKS コントロールプレーンコントローラーマネージャーログを有効にして、ネットワークポリシー機能を診断します。コントロールプレーンログを CloudWatch ロググループにストリーミングし、CloudWatch Log Insights を使用して高度なクエリを実行できます。ログから、ネットワークポリシーに解決されるポッドエンドポイントオブジェクト、ポリシーの照合ステータスを表示し、ポリシーが期待どおりに動作している場合はデバッグできます。

さらに、Amazon VPC CNI では、EKS ワーカーノードから Amazon Cloudwatch へのポリシー適用ログの収集とエクスポートを有効にすることができます。有効にすると、CloudWatch Container Insights を活用して、ネットワークポリシーに関連する使用状況に関するインサイトを提供できます。

Amazon VPC CNI には、ノード上の eBPF プログラムとやり取りするためのインターフェイスを提供する SDK も付属しています。SDK は、 aws-nodeがノードにデプロイされたときにインストールされます。SDK バイナリは、ノードの /opt/cni/bin ディレクトリにインストールされています。起動時に、SDK は eBPF プログラムやマップの検査などの基本的な機能をサポートします。

sudo /opt/cni/bin/aws-eks-na-cli ebpf progs

ネットワークトラフィックメタデータのログ記録

AWS VPC フローログは、送信元と送信先の IP アドレスやポートなど、VPC を通過するトラフィックに関するメタデータを、受け入れられた/ドロップされたパケットとともにキャプチャします。この情報は、Pod を含む VPC 内のリソース間の疑わしいアクティビティや異常なアクティビティを探すために分析できます。ただし、ポッドの IP アドレスは置き換えられると頻繁に変更されるため、フローログだけでは不十分である可能性があります。Calico Enterprise は、ポッドラベルやその他のメタデータを使用してフローログを拡張するため、ポッド間のトラフィックフローを簡単に解読できます。

セキュリティグループ

EKS は AWS VPC セキュリティグループ (SGs) を使用して、Kubernetes コントロールプレーンとクラスターのワーカーノード間のトラフィックを制御します。セキュリティグループは、ワーカーノード、他の VPC リソース、および外部 IP アドレス間のトラフィックを制御するためにも使用されます。EKS クラスター (Kubernetes バージョン 1.14-eks.3 以降) をプロビジョニングすると、クラスターセキュリティグループが自動的に作成されます。このセキュリティグループにより、EKS コントロールプレーンとマネージド型ノードグループからのノード間の無制限の通信が可能になります。簡単にするために、アンマネージド型ノードグループを含むすべてのノードグループにクラスター SG を追加することをお勧めします。

Kubernetes バージョン 1.14 および EKS バージョン eks.3 以前は、EKS コントロールプレーンとノードグループに個別のセキュリティグループが設定されていました。コントロールプレーンとノードグループのセキュリティグループの最小ルールと推奨ルールは、https://docs.aws.amazon.com/eks/latest/userguide/sec-group-reqs.html にあります。コントロールプレーンセキュリティグループの最小ルールでは、ワーカーノード SG からのポート 443 のインバウンドを許可します。このルールにより、kubelets は Kubernetes API サーバーと通信できます。また、ワーカーノード SG へのアウトバウンドトラフィック用のポート 10250 も含まれています。10250 は kubelets がリッスンするポートです。同様に、最小ノードグループルールでは、コントロールプレーン SG からのインバウンドポート 10250 とコントロールプレーン SG へのアウトバウンドポート 443 が許可されます。最後に、ノードグループ内のノード間の無制限の通信を許可するルールがあります。

クラスター内で実行される サービス間の通信を制御し、RDS データベースなどのクラスター外で実行される サービスを実行する必要がある場合は、ポッドのセキュリティグループを検討してください。ポッドのセキュリティグループを使用すると、既存のセキュリティグループをポッドのコレクションに割り当てることができます。

警告

ポッドの作成前に存在しないセキュリティグループを参照すると、ポッドはスケジュールされません。

SecurityGroupPolicy オブジェクトを作成し、 PodSelectorまたは を指定することで、セキュリティグループに割り当てられるポッドを制御できますServiceAccountSelector。セレクターを に設定する{}と、 で参照される SGs がSecurityGroupPolicy、名前空間内のすべてのポッドまたは名前空間内のすべてのサービスアカウントに割り当てられます。ポッドのセキュリティグループを実装する前に、すべての考慮事項を理解しておく必要があります。

重要

ポッドSGs を使用する場合は、クラスターセキュリティグループへのポート 53 アウトバウンドを許可する SGs を作成する必要があります。同様に、ポッドセキュリティグループからのポート 53 インバウンドトラフィックを受け入れるようにクラスターセキュリティグループを更新する必要があります

重要

セキュリティグループの制限は、ポッドのセキュリティグループを使用する場合にも適用されるため、慎重に使用してください。

重要

ポッド用に設定されたすべてのプローブについて、クラスターセキュリティグループ (kubelet) からのインバウンドトラフィックのルールを作成する必要があります

重要

ポッドのセキュリティグループは、EC2 インスタンスの ENI 密度を高めるために作成された ENI トランキングと呼ばれる機能に依存しています。ポッドが SG に割り当てられると、VPC コントローラーはノードグループからのブランチ ENI をポッドに関連付けます。ポッドがスケジュールされた時点でノードグループに十分なブランチ ENIs がない場合、ポッドは保留状態のままになります。インスタンスがサポートできるブランチ ENIs の数は、インスタンスタイプ/ファミリーによって異なります。詳細については、https://docs.aws.amazon.com/eks/latest/userguide/security-groups-for-pods.html#supported-instance-types を参照してください。

ポッドのセキュリティグループでは、ポリシーデーモンのオーバーヘッドなしでクラスター内外のネットワークトラフィックを AWS ネイティブに制御できますが、他のオプションも使用できます。たとえば、Cilium ポリシーエンジンを使用すると、ネットワークポリシーで DNS 名を参照できます。Calico Enterprise には、ネットワークポリシーを AWS セキュリティグループにマッピングするためのオプションが含まれています。Istio のようなサービスメッシュを実装している場合は、Egress Gateway を使用して、ネットワーク出力を特定の完全修飾ドメインまたは IP アドレスに制限できます。このオプションの詳細については、Istio の出力トラフィック制御に関する 3 つのパートシリーズを参照してください。

Pod でネットワークポリシーとセキュリティグループを使用するタイミング

Kubernetes ネットワークポリシーを使用するタイミング

  • pod-to-podトラフィックの制御

    • クラスター内のポッド間のネットワークトラフィック (東西トラフィック) の制御に適しています。

  • IP アドレスまたはポートレベルでトラフィックを制御する (OSI レイヤー 3 または 4)

ポッドに AWS セキュリティグループを使用するタイミング (SGP)

  • 既存の AWS 設定を活用する

    • AWS サービスへのアクセスを管理する複雑な EC2 セキュリティグループのセットがすでにあり、EC2 インスタンスから EKS にアプリケーションを移行する場合、SGPs はセキュリティグループのリソースを再利用してポッドに適用するために非常に適しています。

  • AWS サービスへのアクセスを制御する

    • EKS クラスター内で実行されているアプリケーションは、他の AWS サービス (RDS データベース) と通信し、ポッドから SGPs を使用します。

  • ポッドとノードのトラフィックの分離

    • ポッドトラフィックを残りのノードトラフィックから完全に分離する場合は、 POD_SECURITY_GROUP_ENFORCING_MODE=strict モードで SGP を使用します。

ポッドとネットワークポリシーのセキュリティグループを使用するベストプラクティス

  • レイヤードセキュリティ

    • レイヤードセキュリティアプローチに SGP ネットワークポリシーと kubernetes ネットワークポリシーの組み合わせを使用する

    • SGPs を使用してクラスターの一部ではない AWS サービスへのネットワークレベルのアクセスを制限し、kubernetes ネットワークポリシーはクラスター内のポッド間のネットワークトラフィックを制限できます。

  • 最小権限の原則

    • ポッドまたは名前空間間の必要なトラフィックのみを許可する

  • アプリケーションをセグメント化する

    • 可能な限り、アプリケーションをネットワークポリシーでセグメント化して、アプリケーションが侵害された場合に爆発半径を小さくします。

  • ポリシーをシンプルかつ明確に保つ

    • Kubernetes ネットワークポリシーは非常に詳細で複雑な場合があるため、設定ミスのリスクを軽減し、管理オーバーヘッドを軽減するために、できるだけシンプルに保つのが最善です。

  • アタックサーフェスを減らす

    • アプリケーションの露出を制限して攻撃対象領域を最小限に抑える

重要

ポッドのセキュリティグループには、 strictと の 2 つの強制モードがありますstandard。EKS クラスターのポッド機能にネットワークポリシーとセキュリティグループの両方を使用する場合は、 standard モードを使用する必要があります。

ネットワークセキュリティに関しては、多くの場合、レイヤードアプローチが最も効果的なソリューションです。kubernetes ネットワークポリシーと SGP を組み合わせて使用すると、EKS で実行されているアプリケーションに堅牢なdefense-in-depth戦略を提供できます。

Service Mesh ポリシーの適用または Kubernetes ネットワークポリシー

service mesh は、アプリケーションに追加できる専用のインフラストラクチャレイヤーです。これにより、独自のコードに追加することなく、オブザーバビリティ、トラフィック管理、セキュリティなどの機能を透過的に追加できます。

サービスメッシュは OSI モデルのレイヤー 7 (アプリケーション) でポリシーを適用しますが、kubernetes ネットワークポリシーはレイヤー 3 (ネットワーク) とレイヤー 4 (トランスポート) で動作します。このスペースには、AWS AppMesh、Istio、Linkerd など、多くのサービスがあります。

ポリシーの適用にサービスメッシュを使用するタイミング

  • サービスメッシュに既存の投資を行う

  • トラフィック管理、オブザーバビリティ、セキュリティなどのより高度な機能が必要

    • トラフィック制御、負荷分散、サーキットブレーク、レート制限、タイムアウトなど。

    • サービスのパフォーマンスに関する詳細なインサイト (レイテンシー、エラー率、1 秒あたりのリクエスト数、リクエストボリュームなど)

    • mTLS などのセキュリティ機能にサービスメッシュを実装して活用したい

よりシンプルなユースケースで Kubernetes ネットワークポリシーを選択する

  • 相互に通信できるポッドを制限する

  • ネットワークポリシーは、サービスメッシュよりも必要なリソースが少ないため、単純なユースケースや、サービスメッシュの実行と管理のオーバーヘッドが正当化されない可能性がある小規模なクラスターに適しています。

注記

ネットワークポリシーとサービスメッシュを一緒に使用することもできます。ネットワークポリシーを使用してポッド間のセキュリティと分離のベースラインレベルを提供し、サービスメッシュを使用してトラフィック管理、オブザーバビリティ、セキュリティなどの追加機能を追加します。

ThirdPartyのネットワークポリシーエンジン

グローバルネットワークポリシー、DNS ホスト名ベースのルール、レイヤー 7 ルール、ServiceAccount ベースのルール、明示的な拒否/ログアクションなどの高度なポリシー要件がある場合は、サードパーティーのネットワークポリシーエンジンを検討してください。Calico は、EKS と連携する Tigera のオープンソースポリシーエンジンです。Calico は、Kubernetes ネットワークポリシー機能のフルセットの実装に加えて、Istio と統合した場合の HTTP などのレイヤー 7 ルールのサポートなど、より豊富な機能を備えた拡張ネットワークポリシーをサポートしています。Calico ポリシーの範囲は、名前空間、ポッド、サービスアカウント、またはグローバルに設定できます。ポリシーがサービスアカウントにスコープされている場合、一連の入出力ルールがそのサービスアカウントに関連付けられます。適切な RBAC ルールを設定すると、チームがこれらのルールを上書きするのを防ぎ、IT セキュリティプロフェッショナルが名前空間の管理を安全に委任できるようになります。同様に、Cilium の保守者も、ネットワークポリシーを拡張して、HTTP などのレイヤー 7 ルールの部分的なサポートを含めました。Cilium は DNS ホスト名もサポートしており、Kubernetes サービス/ポッドと VPC 内外で実行されるリソース間のトラフィックを制限するのに役立ちます。対照的に、Calico Enterprise には、Kubernetes ネットワークポリシーを AWS セキュリティグループと DNS ホスト名にマッピングできる機能が含まれています。

一般的な Kubernetes ネットワークポリシーのリストは、https://github.com/ahmetb/kubernetes-network-policy-recipes にあります。Calico の同様のルールのセットは、https://docs.projectcalico.org/security/calico-network-policy で入手できます。

Amazon VPC CNI ネットワークポリシーエンジンへの移行

一貫性を維持し、予期しないポッド通信動作を回避するには、クラスターに 1 つのネットワークポリシーエンジンのみをデプロイすることをお勧めします。3P から VPC CNI ネットワークポリシーエンジンに移行する場合は、VPC CNI ネットワークポリシーのサポートを有効にする前に、既存の 3P NetworkPolicy CRDs を Kubernetes NetworkPolicy リソースに変換することをお勧めします。また、移行したポリシーを本番環境に適用する前に、別のテストクラスターでテストします。これにより、ポッド通信動作の潜在的な問題や不整合を特定して対処できます。

移行ツール

移行プロセスを支援するために、既存の Calico/Cilium ネットワークポリシー CRD を Kubernetes ネイティブネットワークポリシーに変換する K8s Network Policy Migrator と呼ばれるツールを開発しました。 CRDs 変換後、VPC CNI ネットワークポリシーコントローラーを実行している新しいクラスターで、変換されたネットワークポリシーを直接テストできます。このツールは、移行プロセスを合理化し、スムーズに移行できるように設計されています。

重要

移行ツールは、ネイティブの kubernetes ネットワークポリシー API と互換性のある 3P ポリシーのみを変換します。3P プラグインが提供する高度なネットワークポリシー機能を使用している場合、移行ツールはそれらをスキップしてレポートします。

移行ツールは、現在 AWS VPC CNI Network ポリシーエンジニアリングチームではサポートされておらず、ベストエフォートベースでお客様に提供されることに注意してください。このツールを使用して移行プロセスを容易にすることをお勧めします。ツールで問題やバグが発生した場合は、GitHub の問題を作成してください。お客様からのフィードバックは当社にとって貴重なものであり、当社のサービスの継続的な改善に役立ちます。

その他のリソース

転送中の暗号化

PCI、HIPAA、またはその他の規制に準拠する必要があるアプリケーションは、転送中にデータを暗号化する必要がある場合があります。現在、TLS は、ワイヤ上のトラフィックを暗号化するための事実上の選択肢です。TLS は、以前の SSL と同様に、暗号化プロトコルを使用してネットワーク経由で安全な通信を提供します。TLS は対称暗号化を使用して、セッションの開始時にネゴシエートされた共有シークレットに基づいてデータを暗号化します。以下は、Kubernetes 環境でデータを暗号化する方法のいくつかです。

Nitro インスタンス

C5n, G4, I3en, M5dn, M5n, P3dn, R5dnR5n など、次の Nitro インスタンスタイプ間で交換されるトラフィックは、デフォルトで自動的に暗号化されます。トランジットゲートウェイやロードバランサーなどの中間ホップがある場合、トラフィックは暗号化されません。転送中の暗号化の詳細と、デフォルトでネットワーク暗号化をサポートするインスタンスタイプの完全なリストについては、「転送中の暗号化」を参照してください。

コンテナネットワークインターフェイス (CNIs)

WeaveNet は、すべてのトラフィックを NaCl 暗号化を使用して自動的に暗号化するように設定でき、高速データパストラフィックには IPsec ESP を使用できます。

サービスメッシュ

転送中の暗号化は、App Mesh、Linkerd v2、Istio などのサービスメッシュで実装することもできます。AppMesh は、X.509 証明書または Envoy の Secret Discovery Service (SDS) による mTLS をサポートしています。Linkerd と Istio はどちらも mTLS をサポートしています。

aws-app-mesh-examples GitHub リポジトリは、Envoy コンテナで X.509 証明書と SPIRE を SDS プロバイダーとして使用して mTLS を設定するためのチュートリアルを提供します。

App Mesh は、AWS Certificate Manager (ACM) によって発行されたプライベート証明書、または仮想ノードのローカルファイルシステムに保存されている証明書による TLS 暗号化もサポートしています。

aws-app-mesh-examples GitHub リポジトリには、ACM によって発行された証明書と Envoy コンテナにパッケージ化された証明書を使用して TLS を設定するためのチュートリアルが用意されています。

Ingress Controllers と Load Balancer

イングレスコントローラーは、クラスター外から発せられる HTTP/S トラフィックを、クラスター内で実行されているサービスにインテリジェントにルーティングする方法です。多くの場合、これらのイングレスは Classic Load Balancer や Network Load Balancer (NLB) などのレイヤー 4 Load Balancerによって前面に配置されます。暗号化されたトラフィックは、ロードバランサー、イングレスリソース、ポッドなど、ネットワーク内のさまざまな場所で終了できます。SSL 接続を終了する方法と場所は、最終的に組織のネットワークセキュリティポリシーによって決まります。たとえば、end-to-endの暗号化を必要とするポリシーがある場合は、Pod でトラフィックを復号化する必要があります。これにより、最初のハンドシェイクの確立にサイクルを費やす必要があるため、Pod に負担がかかります。全体的な SSL/TLS 処理は CPU を大量に消費します。したがって、柔軟性がある場合は、Ingress またはロードバランサーで SSL オフロードを実行してみてください。

AWS Elastic ロードバランサーで暗号化を使用する

AWS Application Load Balancer (ALB) と Network Load Balancer (NLB) はどちらもトランスポート暗号化 (SSL と TLS) をサポートしています。ALB のalb.ingress.kubernetes.io/certificate-arn注釈を使用すると、ALB に追加する証明書を指定できます。注釈を省略すると、コントローラーはホストフィールドを使用して使用可能な AWS Certificate Manager (ACM) 証明書を照合することで、それを必要とするリスナーに証明書を追加しようとします。EKS v1.15 以降では、以下の例に示すように、NLB で service.beta.kubernetes.io/aws-load-balancer-ssl-cert注釈を使用できます。

apiVersion: v1 kind: Service metadata: name: demo-app namespace: default labels: app: demo-app annotations: service.beta.kubernetes.io/aws-load-balancer-type: "nlb" service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "<certificate ARN>" service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443" service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http" spec: type: LoadBalancer ports: - port: 443 targetPort: 80 protocol: TCP selector: app: demo-app //--- kind: Deployment apiVersion: apps/v1 metadata: name: nginx namespace: default labels: app: demo-app spec: replicas: 1 selector: matchLabels: app: demo-app template: metadata: labels: app: demo-app spec: containers: - name: nginx image: nginx ports: - containerPort: 443 protocol: TCP - containerPort: 80 protocol: TCP

SSL/TLS 終了の追加の例を次に示します。

重要

AWS LB コントローラーなどの一部の Ingress は、Ingress Spec の一部としてではなく、注釈を使用して SSL/TLS を実装します。

cert-manager を使用する ACM プライベート CA

TLS と mTLS を有効にして、ACM Private Certificate Authority (CA) と証明書を配布、更新、取り消しするための一般的な Kubernetes アドオンである cert-manager を使用して、イングレス、ポッド、ポッド間で EKS アプリケーションワークロードを保護できます。ACM Private CA は、高可用性で安全なマネージド CA であり、独自の CA を管理するための前払いとメンテナンスのコストはありません。デフォルトの Kubernetes 認証機関を使用している場合は、セキュリティを向上させ、ACM Private CA のコンプライアンス要件を満たす機会があります。ACM Private CA は、FIPS 140-2 Level 3 ハードウェアセキュリティモジュール (非常に安全) でプライベートキーを保護します。これに対して、メモリにエンコードされたキーを格納するデフォルトの CA (安全性が低い) と比較します。また、一元化された CA により、Kubernetes 環境内外の両方のプライベート証明書をより詳細に制御し、監査可能性を向上させることができます。

ワークロード間の相互 TLS の短縮 CA モード

EKS で mTLS に ACM プライベート CA を使用する場合は、存続期間の短い CA モードの存続期間の短い証明書を使用することをお勧めします。汎用 CA モードで有効期間の短い証明書を発行することは可能ですが、有効期間の短い CA モードを使用すると、新しい証明書を頻繁に発行する必要があるユースケースで、費用対効果が向上します (一般モードよりも約 75% 安価)。これに加えて、プライベート証明書の有効期間を EKS クラスター内のポッドの有効期間に合わせて調整する必要があります。ACM Private CA とその利点については、こちらを参照してください。

ACM セットアップ手順

まず、ACM Private CA 技術ドキュメントに記載されている手順に従って Private CA を作成します。プライベート CA を取得したら、通常のインストール手順に従って cert-manager をインストールします。cert-manager をインストールしたら、GitHub の設定手順に従って Private CA Kubernetes cert-manager プラグインをインストールします。プラグインを使用すると、cert-manager は ACM Private CA にプライベート証明書をリクエストできます。

Private CA と cert-manager とプラグインがインストールされた EKS クラスターができたので、アクセス許可を設定し、発行者を作成します。EKS ノードロールの IAM アクセス許可を更新して、ACM Private CA へのアクセスを許可します。<CA_ARN> をプライベート CA の値に置き換えます。

{ "Version": "2012-10-17", "Statement": [ { "Sid": "awspcaissuer", "Action": [ "acm-pca:DescribeCertificateAuthority", "acm-pca:GetCertificate", "acm-pca:IssueCertificate" ], "Effect": "Allow", "Resource": "<CA_ARN>" } ] }

IAM アカウントのサービスロール、または IRSA を使用することもできます。完全な例については、以下の追加のリソースセクションを参照してください。

Amazon EKS で発行者を作成するには、cluster-issuer.yaml という名前のカスタムリソース定義ファイルを次のテキストで作成し、 <CA_ARN>および <Region>情報をプライベート CA に置き換えます。

apiVersion: awspca.cert-manager.io/v1beta1 kind: AWSPCAClusterIssuer metadata: name: demo-test-root-ca spec: arn: <CA_ARN> region: <Region>

作成した発行者をデプロイします。

kubectl apply -f cluster-issuer.yaml

EKS クラスターは、プライベート CA に証明書をリクエストするように設定されています。上で作成したプライベート CA 発行者にissuerRefフィールドの値を変更することで、cert-manager のCertificateリソースを使用して証明書を発行できるようになりました。証明書リソースを指定してリクエストする方法の詳細については、cert-manager の証明書リソースガイドを参照してください。例については、こちらを参照してください

Istio と cert-manager を使用する ACM プライベート CA

EKS クラスターで Istio を実行している場合は、Istio コントロールプレーン (特に istiod) がルート認証局 (CA) として機能しないようにし、ワークロード間の mTLS のルート CA として ACM プライベート CA を設定できます。このアプローチを使用する場合は、ACM Private CA で存続期間の短い CA モードを使用することを検討してください。詳細については、前のセクションとこのブログ記事を参照してください。

Istio での証明書署名の仕組み (デフォルト)

Kubernetes のワークロードは、サービスアカウントを使用して識別されます。サービスアカウントを指定しない場合、Kubernetes は自動的にサービスアカウントをワークロードに割り当てます。また、サービスアカウントは関連付けられたトークンを自動的にマウントします。このトークンは、Kubernetes API に対して認証するために、ワークロードのサービスアカウントによって使用されます。サービスアカウントは Kubernetes の ID として十分かもしれませんが、Istio には独自の ID 管理システムと CA があります。ワークロードがエンボイサイドカープロキシで起動するときは、信頼できると見なされ、メッシュ内の他のサービスと通信できるようにするために、Istio から割り当てられた ID が必要です。

Istio からこの ID を取得するために、 は証明書署名リクエスト (CSR) と呼ばれるリクエストを Istio コントロールプレーンistio-agentに送信します。この CSR には、処理前にワークロードの ID を検証できるように、サービスアカウントトークンが含まれています。この検証プロセスはistiod、登録機関 (または RA) と CA の両方として機能する によって処理されます。RA は、検証済みの CSR のみが CA に渡すようにするゲートキーパーとして機能します。CSR が検証されると、CA に転送され、サービスアカウントで SPIFFE ID を含む証明書が発行されます。この証明書は、SPIFFE 検証可能な ID ドキュメント (SVID) と呼ばれます。SVID は、識別および通信サービス間の転送中のトラフィックを暗号化するために、リクエスト元のサービスに割り当てられます。

Istio 証明書署名リクエストのデフォルトフロー:

Istio 証明書署名リクエストのデフォルトフロー

ACM Private CA を使用した Istio での証明書署名の仕組み

Istio Certificate Signing Request エージェント (istio-csr) と呼ばれる cert-manager アドオンを使用して、Istio を ACM Private CA と統合できます。このエージェントにより、Istio ワークロードとコントロールプレーンコンポーネントを証明書マネージャー発行者、この場合は ACM Private CA で保護できます。istio-csr エージェントは、受信 CSR を検証するデフォルト設定で istiod が処理するのと同じサービスを公開します。 CSRs ただし、検証後、証明書マネージャーがサポートするリソース (外部 CA 発行者との統合) にリクエストが変換されます。

ワークロードから CSR がある場合、その CSR は istio-csr に転送され、ACM Private CA に証明書がリクエストされます。istio-csr と ACM Private CA 間のこの通信は、AWS Private CA 発行者プラグインによって有効になります。Cert Manager は、このプラグインを使用して ACM Private CA に TLS 証明書をリクエストします。発行者プラグインは ACM Private CA サービスと通信して、ワークロードの署名付き証明書をリクエストします。証明書が署名されると、istio-csr に返されます。istio-csr は署名されたリクエストを読み取り、CSR を開始したワークロードに返します。

istio-csr を使用した Istio 証明書署名リクエストのフロー

image::istio-csr-with-acm-private-ca.png[istio-csr を使用した Istio 証明書署名リクエストのフロー〕

Istio とプライベート CA のセットアップ手順

  1. まず、このセクションの同じセットアップ手順に従って、以下を完了します。

  2. プライベート CA を作成する

  3. cert-manager をインストールする

  4. 発行者プラグインをインストールする

  5. アクセス許可を設定し、発行者を作成します。発行者は CA を表し、ワークロード証明書の署名istiodとメッシュに使用されます。ACM Private CA と通信します。

  6. istio-system 名前空間を作成します。これは、 istiod certificateおよびその他の Istio リソースがデプロイされる場所です。

  7. AWS Private CA Issuer Plugin で設定された Istio CSR をインストールします。ワークロードの証明書署名リクエストを保持して、承認および署名されていることを確認できます (preserveCertificateRequests=true)。

    helm install -n cert-manager cert-manager-istio-csr jetstack/cert-manager-istio-csr \ --set "app.certmanager.issuer.group=awspca.cert-manager.io" \ --set "app.certmanager.issuer.kind=AWSPCAClusterIssuer" \ --set "app.certmanager.issuer.name=<the-name-of-the-issuer-you-created>" \ --set "app.certmanager.preserveCertificateRequests=true" \ --set "app.server.maxCertificateDuration=48h" \ --set "app.tls.certificateDuration=24h" \ --set "app.tls.istiodCertificateDuration=24h" \ --set "app.tls.rootCAFile=/var/run/secrets/istio-csr/ca.pem" \ --set "volumeMounts[0].name=root-ca" \ --set "volumeMounts[0].mountPath=/var/run/secrets/istio-csr" \ --set "volumes[0].name=root-ca" \ --set "volumes[0].secret.secretName=istio-root-ca"
  8. Istio をカスタム設定でインストールし、メッシュの証明書プロバイダーcert-manager istio-csrとして istiod に置き換えます。このプロセスは、Istio Operator を使用して実行できます。

    apiVersion: install.istio.io/v1alpha1 kind: IstioOperator metadata: name: istio namespace: istio-system spec: profile: "demo" hub: gcr.io/istio-release values: global: # Change certificate provider to cert-manager istio agent for istio agent caAddress: cert-manager-istio-csr.cert-manager.svc:443 components: pilot: k8s: env: # Disable istiod CA Sever functionality - name: ENABLE_CA_SERVER value: "false" overlays: - apiVersion: apps/v1 kind: Deployment name: istiod patches: # Mount istiod serving and webhook certificate from Secret mount - path: spec.template.spec.containers.[name:discovery].args[7] value: "--tlsCertFile=/etc/cert-manager/tls/tls.crt" - path: spec.template.spec.containers.[name:discovery].args[8] value: "--tlsKeyFile=/etc/cert-manager/tls/tls.key" - path: spec.template.spec.containers.[name:discovery].args[9] value: "--caCertFile=/etc/cert-manager/ca/root-cert.pem" - path: spec.template.spec.containers.[name:discovery].volumeMounts[6] value: name: cert-manager mountPath: "/etc/cert-manager/tls" readOnly: true - path: spec.template.spec.containers.[name:discovery].volumeMounts[7] value: name: ca-root-cert mountPath: "/etc/cert-manager/ca" readOnly: true - path: spec.template.spec.volumes[6] value: name: cert-manager secret: secretName: istiod-tls - path: spec.template.spec.volumes[7] value: name: ca-root-cert configMap: defaultMode: 420 name: istio-ca-root-cert
  9. 作成した上記のカスタムリソースをデプロイします。

    istioctl operator init kubectl apply -f istio-custom-config.yaml
  10. これで、ワークロードを EKS クラスターのメッシュにデプロイし、mTLS を適用できるようになりました。

Istio 証明書署名リクエスト

image::istio-csr-requests.png[Istio 証明書署名リクエスト〕

ツールとリソース