【Azure】AKS セキュリティ - ACNS による FQDN フィルタリング

# はじめに

Kubernetes を利用したマイクロサービスアーキテクチャでは、アプリケーションのセキュリティ対策として、Podからの外部通信を適切に制御する必要があります。

本記事では、Podからの外部通信制御の新しいアプローチとして、Azure Kubernetes Service(AKS)のネットワークセキュリティの機能として、2024年9月にパブリックプレビューとして提供された Advanced Container Networking Services (ACNS) のFQDN（Fully Qualified Domain Name）フィルタリング機能について紹介します。

## 本記事で学べること
- ACNSの概要と主要機能
- FQDNフィルタリング機能の特徴と利点
- 実際の導入手順と設定例

AKS を利用する方には有効な選択肢になろうかと思いますので、参考になれば幸いです。

:::note warn
ACNS は 登場したばかりのネットワークサービスとなりますので、執筆時と内容が変わっている可能性があります。本記事は2024/12時点のデータをもとに執筆しているためご留意ください。
:::

# ACNS の概要

Advanced Container Networking Services (ACNS) は、Microsoft Azure が提供するコンテナネットワーキングサービスです。OSS の [Cilium](https://docs.cilium.io/en/stable/) と Azure Kubernetes Service (AKS)と密接に連携することで高度なネットワーク機能を提供しています。  

主な特徴：

- 高性能なコンテナネットワーキング
  - FQDN フィルタリングなど高度なネットワークポリシーを提供
  - Cilium のデータプレーンのみが対象
- リアルタイムの可観測性
  - [Hubble](https://github.com/cilium/hubble) によるネットワークポリシーの適用やトラフィックの監視機能などを提供
  - Cilium のデータプレーンでなくとも対象

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3907919/ba2ce9ff-b74f-435d-9d78-5b5b227416bc.png)

参考 (MS公式ドキュメント)：

- [アドバンスト コンテナー ネットワーク サービスとは何ですか?](https://learn.microsoft.com/ja-jp/azure/aks/advanced-container-networking-services-overview?tabs=cilium)
- [コンテナー ネットワークの監視とは](https://learn.microsoft.com/ja-jp/azure/aks/advanced-network-observability-concepts?tabs=non-cilium)  

## 既存の Azure NetworkPolicy の課題

Cilium を採用しない Azure NetworkPolicy には以下の課題があります。

- ドメイン名によるアウトバウンドの通信制御（L7レベル）ができない
  - Azure NetworkPolicy だけでは、アプリケーション層（L7）レベルでのアウトバウンド通信制御ができない。(ドメイン名による制御はできず、IP アドレスによる制御のみ)
  -  L7 レベルの制御を実現するには、Azure Firewall との組み合わせが必須

IP アドレスによる通信制御だけでは、ドメインの IP アドレスが変わるたびに追従する必要があります。
また、Azure Firewall で L7 レベルの制御する場合、アプリケーション開発チームとインフラストラクチャチームの責任分界の観点からも課題がでてきます。Azure Firewall の設定はインフラチームが管理することが多く、アプリケーション要件に応じた柔軟な通信制御が必要な場合、AKS の NetworkPolicy レイヤーでの制御がより適切な選択となります。

### ACNS の FQDN フィルタリング機能の概要

上記の課題を解決する(個人的に)待望の機能として登場したのが FQDN フィルタリング機能となります。
ACNS の FQDN フィルタリング機能は、AKS クラスター内の Pod からのアウトバウンド通信を指定されたドメイン名に基づいて制御することを可能にします。この機能により、特定のドメインへのアクセスのみを許可し、それ以外のすべてのアウトバウンド通信をブロックすることができます。
また、ネットワークポリシーをドメインベースで定義することができるため、IP を動的に変更することなく構成管理を簡素化することができます。
通常のネットワークポリシー同様、ラベルや名前空間などの条件から FQDN フィルタリング機能を適用する Pod を柔軟に指定することができます。  

詳細は [Microsoft公式ドキュメント：高度なコンテナ ネットワーキング サービスによるセキュリティ強化のための FQDN フィルタリング](https://learn.microsoft.com/en-us/azure/aks/advanced-network-container-services-security-concepts) を参照してください。

> Kubernetes クラスターでは、ポッドの IP アドレスが頻繁に変更される可能性があるため、IP アドレスを使用したセキュリティ ポリシーでポッドを保護するのは困難です。FQDN フィルタリングを使用すると、IP アドレスではなくドメイン名を使用してポッド レベルのポリシーを作成できるため、IP アドレスが変更されてもポリシーを更新する必要がなくなります。

留意事項：

一部制約があるため、使用する場合は公式ドキュメント([コンテナー ネットワーク セキュリティとは:考慮事項](https://learn.microsoft.com/ja-jp/azure/aks/container-network-security-concepts#considerations))を一読ください。フルで Cilium の機能を利用したい場合は、手動で Cilium を導入することになります。

> FQDN フィルタリングなどの Advanced Container Networking Services のセキュリティ機能を使用するには、Azure CNI Powered by Cilium および Kubernetes バージョン 1.29 以上が必要です。

# FQDN フィルタリング機能の利用

さっそく試してみましょう。以下のMS公式ドキュメントの手順を参考にしました。

- [アドバンスト コンテナー ネットワークサービスのコンテナー ネットワーク セキュリティのための FQDN フィルタリング機能を設定する](https://learn.microsoft.com/ja-jp/azure/aks/how-to-apply-fqdn-filtering-policies?tabs=cilium)

## 準備

FQDN フィルタリング機能を利用するためには、ACNS を有効化した AKS クラスターが必要となります。
以下では Azure CLI を使用した環境構築手順を説明します。

### プレビュー機能の有効化

```bash
# Install the aks-preview extension
az extension add --name aks-preview
# Update the extension to make sure you have the latest version installed
az extension update --name aks-preview
```

### ACNS 有効化した AKS を作成する

以下は既存の VNET 内に AKS を作成する例です。
※VNET を気にせず、まずは試してみたいという方は、[公式ドキュメントの手順](https://learn.microsoft.com/ja-jp/azure/aks/how-to-apply-fqdn-filtering-policies?tabs=cilium#enable-advanced-container-networking-services) を参照してください。
`--network-dataplane cilium --enable-acns` を指定することで、FQDN フィルタリング機能が利用できる AKS クラスターを作成できます。

```bash
$RESOURCE_GROUP="リソースグループ名"
$CLUSTER_NAME="AKSクラスター名"
$SERVICE_CIDR="10.xxx.xx.0/24"
$DNS_SERVICE_IP="10.xxx.xx.10"
$SUBNET_ID="/subscriptions/{サブスクリプションID}/resourceGroups/....."

# AKS クラスター作成
az aks create \
  --name $CLUSTER_NAME \
  --resource-group $RESOURCE_GROUP \
  --generate-ssh-keys \
  --network-plugin azure \
  --network-plugin-mode overlay \
  --service-cidr $SERVICE_CIDR \
  --dns-service-ip $DNS_SERVICE_IP \
  --vnet-subnet-id $SUBNET_ID \
  --network-dataplane cilium \
  --enable-acns
```

以下のエラーが出た場合、CLI のバージョンが古いため、`az upgrade`でアップデートしてください

```bash
unrecognized arguments: --enable-acns
```

## FQDN フィルタリングの設定

`cilium.io/v2`のパラメータやリファレンスは以下を参考にしました

- [Securing Networks with Cilium](https://docs.cilium.io/en/stable/security/dns/)
- [CiliumNetworkPolicy Paramater](https://doc.crds.dev/github.com/cilium/cilium/cilium.io/CiliumNetworkPolicy/v2@1.9.3)

### 設定例

**`labels.class`に`demo`のラベルが付与されている Pod に、FQDN フィルタリングを適用**  
今回、`www.google.com`と`www.bing.com`のドメインのみ通信許可する設定とします。

1. FQDN フィルタリングポリシーの作成  
  クラスター内の名前解決のため `kube-dns` へのトラフィックの許可は必須  

    ```yaml
    # fqdn-fillter.yaml
    apiVersion: cilium.io/v2
    kind: CiliumNetworkPolicy
    metadata:
    name: outbound-policy
    spec:
    endpointSelector:
        matchLabels:
        class: demo # 適用するラベルを指定する
    egress:
        - toEndpoints:
        - matchLabels:
            "k8s:io.kubernetes.pod.namespace": kube-system
            "k8s:k8s-app": kube-dns
        toPorts: # kube-dns へのトラフィックを許可
        - ports:
        - port: "53"
            protocol: ANY
        rules:
            dns:
            - matchPattern: "*"
        - toFQDNs:
            - matchName: "www.google.com" # 許可したいドメイン
            - matchName: "www.bing.com"
    ```

   ポリシーの適用  

    ```bash
    kubectl apply -f fqdn-fillter.yaml
    ```

1. 動作確認  
    疎通確認のため、今回は疎通確認用の Curl を実行するだけのイメージで確認します。
    ラベルを指定 `--labels=class=demo` することで、FQDN のフィルタリングのポリシーが適用されます。 
    許可したドメインのみレスポンスが返ってくれば OK  

    ```bash
    # curl を実行するだけのイメージを実行
    # labels に class=demo を指定
    kubectl run curl --labels=class=demo --image=curlimages/curl -it --rm -- /bin/sh
    
    # 許可されたドメイン
    curl -I -s https://www.google.com | head -1
    # 実行結果：HTTP/2 200
    
    # ブロックされたドメイン
    curl -I -s https://api.github.com | head -1
    # タイムアウトになる
    ```

    labels に class=demo を指定しない場合は、フィルタリングのポリシーは適用されず、いずれのドメインもブロックされません。

非常に簡単に設定できますね。
今回ラベル名で制御しましたが、通常のネットワークポリシー同様に名前空間単位でも設定できますので、要件に合わせて適切に設定してください。

# さいごに

本記事ではACNS を導入することで、Pod からのアウトバウンド通信で FQDN フィルタリングが実現できることを紹介しました。
Kubernetes をはじめとするコンテナ周辺技術は、システムの基盤となる技術でありながら変化が速いため、日々キャッチアップをしてベストプラクティスを更新していく必要があります。
今回紹介した機能の有無で、どこのレイヤーで通信制御すべきかの設計に関わってきますので、AKS を扱う方の参考になれば幸いです。

## 参考資料

MS公式ドキュメント：

- [アドバンスト コンテナー ネットワーク サービスとは何ですか?](https://learn.microsoft.com/ja-jp/azure/aks/advanced-container-networking-services-overview?tabs=cilium)
- [コンテナー ネットワークの監視とは](https://learn.microsoft.com/ja-jp/azure/aks/advanced-network-observability-concepts?tabs=non-cilium)  
- [高度なコンテナ ネットワーキング サービスによるセキュリティ強化のための FQDN フィルタリング](https://learn.microsoft.com/en-us/azure/aks/advanced-network-container-services-security-concepts) 
- [コンテナー ネットワーク セキュリティとは](https://learn.microsoft.com/ja-jp/azure/aks/container-network-security-concepts)
- [アドバンスト コンテナー ネットワークサービスのコンテナー ネットワーク セキュリティのための FQDN フィルタリング機能を設定する](https://learn.microsoft.com/ja-jp/azure/aks/how-to-apply-fqdn-filtering-policies?tabs=cilium)

## We Are Hiring!

https://www.biprogy.com/recruit/recruiting/