前回の記事でAmazon EKSアドオンの設定の際のスキーマについて書きました。
今回は具体的にAmazon VPC CNIプラグインの設定をする際、ENIConfigの設定で初見では中々気づきづらいエラーが出て解消するのに難儀したという話をしようと思います。
今回も前回と同じく、以下の記事の内容を理解しておくとすんなり分かるタイプの話が多くなるでしょう。
Amazon VPC CNIプラグインでカスタムネットワークの設定をする
Amazon EKSを使っている際、たとえば「普段使っているVPC内のprivate subnetが確保しているIPv4アドレスよりも多い数が確保できるsubnetとIPv4アドレスを使用して、pod用にIPアドレスを割り振りたい」など諸々要件があってカスタムネットワークの設定が必要になったとします。
そういうときにはAmazon VPC CNIプラグインに設定を追加して対応してやる必要があります。詳しくは以下AWS公式ドキュメントを参照。
機能の概要
Amazon EKS アドオン API に新しい
configurationValues
パラメータが追加されました。ローンチ時点では、このパラメータは、JSON BLOB として設定を受け入れます。YAML のサポートも近日中に開始される予定です。JSON BLOB は、作成または更新しようとしているアドオンの特定バージョンごとの JSON Schema に準拠する必要があります。スキーマは、新しい API である Amazon EKS DescribeAddonConfiguration API を通じて利用可能です。以下で説明するように、configurationValues
パラメータはaws eks create-addon
およびaws eks update-addon
AWS CLI コマンドで使用できます。
ここで書かれているように、 configurationValues
というパラメータに設定を書いてやります。
Terraformでここに設定を追加したい場合、ドキュメントのこの箇所のように、 aws_eks_addon
リソースの configuration_values
argument にjsonencode関数でエンコードしたJSON形式のObjectを入れてやればいいです。
ただ、ここでENIConfigの設定を入れようとすると結構はまりポイントがありました。
ENIConfigカスタムリソースのスキーマのはまりポイント
前回の記事にも掲載した、Amazon VPC CNIプラグインの設定のスキーマから、ENIConfigに関わる部分だけ取り出してみます。
{ "$ref": "#/definitions/VpcCni", "$schema": "http://json-schema.org/draft-06/schema#", "definitions": { "Affinity": { "type": [ "object", "null" ] }, "EniConfig": { "additionalProperties": false, "properties": { "create": { "type": "boolean" }, "region": { "type": "string" }, "subnets": { "additionalProperties": { "additionalProperties": false, "properties": { "id": { "type": "string" }, "securityGroups": { "items": { "type": "string" }, "type": "array" } }, "required": [ "id" ], "type": "object" }, "minProperties": 1, "type": "object" } }, "required": [ "create", "region", "subnets" ], "type": "object" }, # 省略 }, "description": "vpc-cni" }
これはawscliで返ってきた値をjqでパースしたjsonなので要素の並び方がjq由来なのも手伝っているのでしょうが、このスキーマをパッと見てどんな感じか分かるでしょうか?
特に $.eniConfig.subnets
の箇所の定義に自信を持って設定できるでしょうか?
私はJSONスキーマに慣れていないこともあり、この定義をちゃんと見ていたはずなのですが、結果的に読み切れて無くてTerraformの設定時によく分からないエラーに遭遇して時間を溶かしてしまいました。
具体的にはterraform plan時に出た、以下の様なエラーです。
module.eks_addon.aws_eks_addon.vpc_cni: Creating... ╷ │ Error: creating EKS Add-On (dev-cluster:vpc-cni): InvalidParameterException: ConfigurationValue provided in request is not supported: Json schema validation failed with error: [$.eniConfig.subnets: array found, object expected] │ { │ RespMetadata: { │ StatusCode: 400, │ RequestID: "my-request-id" │ }, │ AddonName: "vpc-cni", │ ClusterName: "dev-cluster", │ Message_: "ConfigurationValue provided in request is not supported: Json schema validation failed with error: [$.eniConfig.subnets: array found, object expected]" │ } │ │ with module.eks_addon.aws_eks_addon.vpc_cni, │ on ../modules/eks_addon.tf line 4, in resource "aws_eks_addon" "vpc_cni": │ 4: resource "aws_eks_addon" "vpc_cni" { │ ╵
$.eniConfig.subnets: array found, object expected
というエラーが表示され、「え?ここはarrayじゃないの?」となってしまいました。
定義のほうをちゃんと見ると $.eniConfig.subnets
はobjectが型として指定されているのは分かるのですが、 "type": "object"
までの記述が離れていて大分見分けが付きづらい状態です。
「ではどういう風に書けばいいのか?」という問いに対する答えを書いてしまうと、eniConfigの箇所には以下の様にavailability zoneの値をkeyにし、subnetの情報をそこに紐付ければいいです。
eniConfig = { create = true region = "ap-northeast-1" subnets = { "ap-northeast-1a" = { id = "subnet-aaaaa", securityGroups = ["sg-yyyyy"] }, }
aws_eks_addon
リソースの configuration_values
引数にjsonencode関数で適切に変換しつつ上記のeniConfig
要素を入れると、以下の様なCustom Resourceを作るのと同等になります。
apiVersion: crd.k8s.amazonaws.com/v1alpha1 kind: ENIConfig metadata: name: ap-northeast-1a spec: securityGroups: - "sg-yyyyy" subnet: "subnet-aaaaa"
$.eniConfig.subnets
に設定したobjectのkeyにあたる ap-northeast-1a
がENIConfig Custom Resourceの .metadata.name
に設定されています。
ここがAmazon VPC CNIプラグインの設定をTerraformで行う時に一番分かりづらかったところです。
この形に適合するように値を変更したら、 Json schema validation failed with error
というエラーは消え、実際にterraform applyすると必要な設定・リソースが入ることを確認できました。