EKS Addon Configuration via Terraform

Written by Luke Arntz on August 17, 2023
[ addon ] [ aws ] [ eks ] [ clusterip ] [ kubernetes ] [ coredns ] [ daily note ] [ terraform ] [ configuration ] [ jq ]

Contents

EKS Addon Configuration via Terraform

This is a quick overview of how to pass custom configuration values to EKS managed addons using Terraform.

Configuration Schema

Before you begin find the addon version you need and describe the available configuration options:

❯ aws eks describe-addon-versions --addon-name coredns --kubernetes-version 1.27 | jq -r '.addons[].addonVersions[] | select(.compatibilities[].defaultVersion == true) | .addonVersion'
v1.10.1-eksbuild.1

❯ aws eks describe-addon-configuration --addon-name coredns  --addon-version v1.10.1-eksbuild.1 | jq -r .configurationSchema | jq
{
  "$ref": "#/definitions/Coredns",
  "$schema": "http://json-schema.org/draft-06/schema#",
  "definitions": {
    "Coredns": {
      "additionalProperties": false,
      "properties": {
        "affinity": {
          "default": {
            "affinity": {
              "nodeAffinity": {
                "requiredDuringSchedulingIgnoredDuringExecution": {
                  "nodeSelectorTerms": [
                    {
                      "matchExpressions": [
                        {
                          "key": "kubernetes.io/os",
                          "operator": "In",
                          "values": [
                            "linux"
                          ]
                        },
                        {
                          "key": "kubernetes.io/arch",
                          "operator": "In",
                          "values": [
                            "amd64",
                            "arm64"
                          ]
                        }
                      ]
                    }
                  ]
                }
              },
              "podAntiAffinity": {
                "preferredDuringSchedulingIgnoredDuringExecution": [
                  {
                    "podAffinityTerm": {
                      "labelSelector": {
                        "matchExpressions": [
                          {
                            "key": "k8s-app",
                            "operator": "In",
                            "values": [
                              "kube-dns"
                            ]
                          }
                        ]
                      },
                      "topologyKey": "kubernetes.io/hostname"
                    },
                    "weight": 100
                  }
                ]
              }
            }
          },
          "description": "Affinity of the coredns pods",
          "type": [
            "object",
            "null"
          ]
        },
        "computeType": {
          "type": "string"
        },
        "corefile": {
          "description": "Entire corefile contents to use with installation",
          "type": "string"
        },
        "nodeSelector": {
          "additionalProperties": {
            "type": "string"
          },
          "type": "object"
        },
        "replicaCount": {
          "type": "integer"
        },
        "resources": {
          "$ref": "#/definitions/Resources"
        },
        "tolerations": {
          "default": [
            {
              "key": "CriticalAddonsOnly",
              "operator": "Exists"
            },
            {
              "key": "node-role.kubernetes.io/master",
              "operator": "NoSchedule"
            }
          ],
          "description": "Tolerations of the coredns pod",
          "items": {
            "type": "object"
          },
          "type": "array"
        }
      },
      "title": "Coredns",
      "type": "object"
    },
    "Limits": {
      "additionalProperties": false,
      "properties": {
        "cpu": {
          "type": "string"
        },
        "memory": {
          "type": "string"
        }
      },
      "title": "Limits",
      "type": "object"
    },
    "Resources": {
      "additionalProperties": false,
      "properties": {
        "limits": {
          "$ref": "#/definitions/Limits"
        },
        "requests": {
          "$ref": "#/definitions/Limits"
        }
      },
      "title": "Resources",
      "type": "object"
    }
  }
}

Terraform Configuration

The configuration_values must be in json format. The easiest way to do this is to use the jsonencode() function included with terraform.

data "aws_eks_addon_version" "coredns" {
  addon_name         = "coredns"
  kubernetes_version = module.eks.cluster_version
  most_recent        = false # use the default version for the cluster rather than latest
}

resource "aws_eks_addon" "coredns" {
  cluster_name      = module.eks.cluster_id
  addon_name        = "coredns"
  addon_version     = data.aws_eks_addon_version.coredns.version
  resolve_conflicts = "OVERWRITE"

  # This requires the consul-dns svc ClusterIP be set to 172.20.0.5. 
  # https://github.com/hashicorp/consul-k8s/blob/6e9f4731e76642dbb5d0869cdf1aa3fa40e1681a/charts/consul/values.yaml#L1687-L1691
  configuration_values = jsonencode({
    corefile = <<-EOT
    .:53 {
        errors
        health
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          fallthrough in-addr.arpa ip6.arpa
        }
        prometheus :9153
        forward . /etc/resolv.conf
        cache 30
        loop
        reload
        loadbalance
    }
    consul {
        errors
        cache 30
        forward . 172.20.0.5
    }
EOT
    tolerations = [
      {
        effect = "NoSchedule"
        key    = "node-role.kubernetes.io/master"
      },
      {
        key      = "CriticalAddonsOnly"
        operator = "Exists"
      },
      {
        key    = "role",
        value  = "karpenter"
        effect = "NoSchedule"
      }
    ]
  })
}

Final Notes

That basically covers it. A couple notes about the example above. The CoreDNS corefile includes a block to forward lookups for hostnames that end in .consul to the DNS service listening on IP address 172.20.0.5. To facilitate this you must set your consul-dns service to use that IP address for the ClusterIP. This also requires specifying the k8s ipv4 service CIDR to something like 172.20.0.0/16.

Some additional information related to this can be found at the links below.

Related Articles

Top