GuardDuty EKS Runtime Monitoring 用エージェントで複数パラメータを設定可能になったので試してみた

GuardDuty EKS Runtime Monitoring の v1.5.0 からエージェントに対して複数パラメータを設定可能になりました。

今回設定可能になったパラメータは下記になります。

  • CPU settings(Requests, Limits)
  • Memory settings(Request, Limits)
  • PriorityClass settings
  • dnsPolicy settings

設定可能になったパラメータ

まず、設定可能になったパラメータを確認してみます。

CPU settings, Memory settings

Requests はコンテナが利用するリソースの最低保証量になり、Limits はリソースの最大量になります。
CPU のデフォルトは Requests が 200mCPU、Limits が 1CPU です。
メモリのデフォルトは Requests が 256MiB、Limits が 1GiB です。

Configure GuardDuty security agent (add-on) parameters for Amazon EKS | Amazon GuardDuty

特に設定せずにインストールしてみた所、ドキュメント記載通りの値になっていました。

    Limits:
      cpu:     1
      memory:  1Gi
    Requests:
      cpu:     200m
      memory:  256Mi

Pod を 2 台起動しつつ、リソース使用量を見てみましたが、このくらいであれば全然リソースを使っていないですね。

$ kubectl top pod -n amazon-guardduty
NAME                        CPU(cores)   MEMORY(bytes)   
aws-guardduty-agent-4tcc8   70m          55Mi

ただ、セキュリティを担保する役割を持つ以上、積極的に触る内容では無くこの分も踏まえてリソースを確保するという考え方が良いと思います。
そもそも、CPU、メモリ共に Requests を今の値より下げることはできず、そのような使い方は想定されていません。
継続的に Requests を超えてリソースを利用しているのであれば、安定動作のために Requests を増やすような使い方で利用するのが良いと思います。

PriorityClass settings

Podがスケジューリングされる優先度を定義可能です。
元々 Kubernetes にデフォルトで存在する PriorityClass である system-cluster-critical、 system-node-critical に加えて、エージェント追加時に登録される aws-guardduty-agent.priorityclass-high、 aws-guardduty-agent.priorityclass から選択可能です。

$ kubectl get priorityclass
NAME                                     VALUE        GLOBAL-DEFAULT   AGE
aws-guardduty-agent.priorityclass        1000000      false            3h40m
aws-guardduty-agent.priorityclass-high   100000000    false            3h39m
system-cluster-critical                  2000000000   false            3h55m
system-node-critical                     2000001000   false            3h55m

設定を行わない場合のデフォルト値は aws-guardduty-agent.priorityclass です。

Priority:             1000000
Priority Class Name:  aws-guardduty-agent.priorityclass

デフォルトの aws-guardduty-agent.priorityclass が一番 priority 値が低いため、こちらの設定を行うことでエージェントの優先度を上げることが可能です。
また、Kubernetes にはプリエンプトと呼ばれる機能があり、リソースに空きが無い場合に他の優先度の低い Pod を終了してスケジュール可能にすることができます。
デフォルトの設定では preemptionPolicy が Never になっているため、スケジューリング時は他の優先度の低い Pod より優先されますが、他の Pod をプリエンプトはしない設定になります。
余裕を持ったリソース確保が望ましいとは思いますが、コンピューティングリソースが潤沢で無い場合は、priority 値を適切に設計した上でエージェントの PriorityClass を変更しても良いかもしれません。

dnsPolicy settings

Pod がどのように名前解決を行うかを設定可能です。
定義可能な値が決まっており、以下の3つから選択できます。

"ClusterFirst": "www.kubernetes.io"のようなクラスタードメインのサフィックスにマッチしないようなDNSクエリーは、Nodeから継承された上流のネームサーバーにフォワーディングされます。
"Default": そのPodはPodが稼働しているNodeから名前解決の設定を継承します。
"ClusterFirstWithHostNet": hostNetworkによって稼働しているPodに対しては、ユーザーは明示的にDNSポリシーを"ClusterFirstWithHostNet"とセットするべきです。
PodのDNSポリシー

何も設定しなかった際は Default ではなく、 ClusterFirst になります。
クラスタ内の Service 等に対する DNS クエリは クラスター内の DNS サーバ (coredns 等) に問い合わせつつ、それ以外は Node から継承された上流のネームサーバーにフォワーディングする設定です。

やってみた

アドオン設定の JSON スキーマは下記のようになります。

{
  "$ref": "#/definitions/GuardDutyAgent",
  "$schema": "http://json-schema.org/draft-06/schema#",
  "definitions": {
    "GuardDutyAgent": {
      "additionalProperties": false,
      "properties": {
        "dnsPolicy": {
          "enum": [
            "ClusterFirstWithHostNet",
            "ClusterFirst",
            "Default"
          ],
          "type": "string"
        },
        "priorityClassName": {
          "enum": [
            "aws-guardduty-agent.priorityclass",
            "aws-guardduty-agent.priorityclass-high",
            "system-cluster-critical",
            "system-node-critical"
          ],
          "type": "string"
        },
        "resources": {
          "$ref": "#/definitions/Resources"
        }
      },
      "title": "GuardDutyAgent",
      "type": "object"
    },
    "Limits": {
      "additionalProperties": false,
      "properties": {
        "cpu": {
          "pattern": "^([2-9]\\d{2}|[1-9]\\d{3}|10000)m$",
          "type": "string"
        },
        "memory": {
          "pattern": "^(256|[3-9]\\d{2}|[1-9]\\d{3}|1\\d{4}|20000)Mi$",
          "type": "string"
        }
      },
      "title": "Limits",
      "type": "object"
    },
    "Requests": {
      "additionalProperties": false,
      "properties": {
        "cpu": {
          "pattern": "^([2-9]\\d{2}|[1-9]\\d{3}|10000)m$",
          "type": "string"
        },
        "memory": {
          "pattern": "^(256|[3-9]\\d{2}|[1-9]\\d{3}|1\\d{4}|20000)Mi$",
          "type": "string"
        }
      },
      "title": "Requests",
      "type": "object"
    },
    "Resources": {
      "additionalProperties": false,
      "properties": {
        "limits": {
          "$ref": "#/definitions/Limits"
        },
        "requests": {
          "$ref": "#/definitions/Requests"
        }
      },
      "title": "Resources",
      "type": "object"
    }
  },
  "description": "Advanced configuration parameters of AWS GuardDuty Agent (EKS Runtime Monitoring Addon)"
}

下記 JSON ファイルを用意して、 CLI ベースで更新してみました。

{
  "priorityClassName": "aws-guardduty-agent.priorityclass-high"
}
aws eks update-addon --cluster-name test-cluster --addon-name aws-guardduty-agent --addon-version v1.5.0-eksbuild.1 --configuration-values 'file://aws-guardduty-agent-setting.json' --resolve-conflicts OVERWRITE

更新完了後、無事設定値が反映されていました。

$ kubectl describe pod aws-guardduty-agent-hng6r -n amazon-guardduty | grep "Priority Class Name"
Priority Class Name:  aws-guardduty-agent.priorityclass-high

新しい API が利用可能になったのではなく、設定可能な項目値が増えるといった形なので、現時点で Terraform 経由でも設定可能です。
※ 下記は EKS Module を利用した場合

module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "~> 20.8.3"

  cluster_name                   = "test-cluster"
  cluster_version                = "1.29"
  cluster_endpoint_public_access = true

  vpc_id     = module.vpc.vpc_id
  subnet_ids = concat(module.vpc.public_subnets, module.vpc.private_subnets)

  cluster_addons = {
    aws-guardduty-agent = {
      most_recent = true
      configuration_values = jsonencode({
        priorityClassName = "aws-guardduty-agent.priorityclass"
        dnsPolicy = "ClusterFirst"
        resources = {
          limits = {
            cpu    = "500m"
            memory = "500Mi"
          }
          requests = {
            cpu    = "200m"
            memory = "256Mi"
          }
        }
      })
    }
  }

  eks_managed_node_groups = {
    initial = {
      node_group_name = "test-ng"
      instance_types  = ["m3.medium"]

      min_size     = 1
      max_size     = 1
      desired_size = 1
      subnet_ids   = module.vpc.private_subnets
    }
  }
}

まとめ

GuardDuty EKS Runtime Monitoring エージェントに対して複数パラメータを設定可能になりました。
より安定して動作させられるよう、必要に応じて調整してみて下さい!