{"id":1912,"date":"2023-08-14T08:05:45","date_gmt":"2023-08-14T13:05:45","guid":{"rendered":"https:\/\/blog.ls-al.com\/?p=1912"},"modified":"2023-08-14T08:05:45","modified_gmt":"2023-08-14T13:05:45","slug":"traefik-in-kubernetes-using-terraform-helm-and-aws-alb","status":"publish","type":"post","link":"https:\/\/blog.ls-al.com\/traefik-in-kubernetes-using-terraform-helm-and-aws-alb\/","title":{"rendered":"traefik in kubernetes using terraform + helm and AWS ALB"},"content":{"rendered":"

If you are using Traefik in kubernetes but you want to use an AWS ALB (application load balancer) this recipe may work for you. You will note a few important things:<\/p>\n

    \n
  1. Traefik relies on the underlying kubernetes provider to create an Ingress. If not specified this will be a loadbalancer CLB (classic load balancer). There is a way to make this a NLB (network load balancer) but the AWS provider is not doing an ALB so Traefik can't do an ALB. This recipe therefore relies on a NodePort service and ties the Ingress (ALB) to the NodePort service via the ingressclass annotation. If you do not like or want to use NodePort this is not for you.<\/li>\n
  2. Yet to confirm can this recipe work if you did not intentionally install the AWS LBC (load balancer controller). And does this work on non AWS EKS or self-managed kubernetes on AWS.<\/li>\n
  3. Still looking at why the AWS Target group health check is not able to use the \/ping or \/dashboard. This may be an issue with my security groups but for now I just created manually a IngressRoute \/<>-health on the Traefik web entrypoint and updated the Target Group health check either programatically or in the AWS console.<\/li>\n
  4. I did not want to complicate this with kubernetes so I am using the simplest way for helm to communicate with the cluster and point to the environment kube config to get to the cluster.<\/li>\n
  5. I did some minimal templating to change the helm release name and corresponding kubernetes objects but for this post I just hard coded for simplicity.<\/li>\n
  6. I commented out deployment as Daemonset for my testing. You need to decide what is better in your environment Deployment or Daemonset.<\/li>\n<\/ol>\n

    providers.tf<\/h3>\n
    provider \"helm\" {\n  kubernetes {\n    config_path = \"~\/.kube\/config-eks\"\n  }\n}<\/code><\/pre>\n

    versions.tf<\/h3>\n
    terraform {\n  required_providers {\n    helm = {\n      source  = \"hashicorp\/helm\"\n      version = \">= 2.0.1\"\n    }\n  }\n  required_version = \">= 0.15\"\n}<\/code><\/pre>\n

    helm values<\/h3>\n
    additionalArguments:\n- --providers.kubernetescrd.ingressclass=traefik-pub\n\n#deployment:\n#  kind: DaemonSet\n\nservice:\n  enabled: true\n  type: NodePort\n\nservice:\n  enabled: true\n  type: NodePort\nextraObjects:\n  - apiVersion: networking.k8s.io\/v1\n    kind: Ingress\n    metadata:\n      name: traefik-pub\n      annotations:\n        kubernetes.io\/ingress.class: alb\n        alb.ingress.kubernetes.io\/scheme: internet-facing\n        alb.ingress.kubernetes.io\/security-groups: sg-,\n        #alb.ingress.kubernetes.io\/actions.ssl-redirect: '{\"Type\": \"redirect\", \"RedirectConfig\":\n        #  { \"Protocol\": \"HTTPS\", \"Port\": \"443\", \"StatusCode\": \"HTTP_301\"}}'\n        alb.ingress.kubernetes.io\/backend-protocol: HTTP\n        alb.ingress.kubernetes.io\/certificate-arn: arn:aws:acm:us-east-1::certificate\/b6ead273-66e9-4768-ad25-0924dca35cdb\n        alb.ingress.kubernetes.io\/healthcheck-path: \"\/traefik-pub-health\"\n        alb.ingress.kubernetes.io\/healthcheck-port: \"traffic-port\"\n        #alb.ingress.kubernetes.io\/healthcheck-protocol: HTTP\n        alb.ingress.kubernetes.io\/listen-ports: '[{\"HTTP\": 80}, {\"HTTPS\":443}]'\n    spec:\n      defaultBackend:\n        service:\n          name: traefik-pub\n          port:\n            number: 80  \n\ningressClass:\n  enabled: true\n  isDefaultClass: false\n\ningressRoute:\n  dashboard:\n    enabled: true\n    # Additional ingressRoute annotations (e.g. for kubernetes.io\/ingress.class)\n    annotations:\n      kubernetes.io\/ingress.class: traefik-pub\n    # Additional ingressRoute labels (e.g. for filtering IngressRoute by custom labels)\n    labels: {}\n    entryPoints:\n    - traefik\n    labels: {}\n    matchRule: PathPrefix(\/dashboard<\/code>) || PathPrefix(\/api<\/code>)\n    middlewares: []\n    tls: {}\n\nrollingUpdate:\n  maxUnavailable: 1\n  maxSurge: 1<\/code><\/pre>\n

    variables.tf (shortened for documentation)<\/h3>\n
    variable \"traefik_name\" {\n  description = \"helm release name\"\n  type        = string\n  default     = \"traefik-pub\"\n}\n\nvariable \"namespace\" {\n  description = \"Namespace to install traefik chart into\"\n  type        = string\n  default     = \"test\"\n}\n\nvariable \"traefik_chart_version\" {\n  description = \"Version of Traefik chart to install\"\n  type        = string\n  default     = \"21.2.1\"\n}<\/code><\/pre>\n

    chart.tf<\/h3>\n
    resource \"helm_release\" \"traefik\" {\n  namespace        = var.namespace\n  create_namespace = true\n  name             = var.traefik_name\n  repository       = \"https:\/\/traefik.github.io\/charts\"\n  chart            = \"traefik\"\n  version          = var.traefik_chart_version\n  timeout = var.timeout_seconds\n\n  values = [\n    file(\"values.yml\")\n  ]\n\n  set {\n    name  = \"deployment.replicas\"\n    value = var.replica_count\n  }\n\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"

    If you are using Traefik in kubernetes but you want to use an AWS ALB (application load balancer) this recipe<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[119,88,118],"tags":[],"class_list":["post-1912","post","type-post","status-publish","format-standard","hentry","category-kubernetes","category-terraform","category-traefik"],"_links":{"self":[{"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/posts\/1912","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/comments?post=1912"}],"version-history":[{"count":1,"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/posts\/1912\/revisions"}],"predecessor-version":[{"id":1913,"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/posts\/1912\/revisions\/1913"}],"wp:attachment":[{"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/media?parent=1912"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/categories?post=1912"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/tags?post=1912"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}