{"id":520,"date":"2021-02-28T02:22:44","date_gmt":"2021-02-28T01:22:44","guid":{"rendered":"https:\/\/nubisoft.io\/blog\/?p=520"},"modified":"2021-12-30T14:53:57","modified_gmt":"2021-12-30T13:53:57","slug":"how-to-set-up-kubernetes-ingress-with-aws-alb-ingress-controller","status":"publish","type":"post","link":"https:\/\/nubisoft.io\/blog\/how-to-set-up-kubernetes-ingress-with-aws-alb-ingress-controller\/","title":{"rendered":"How to set up Kubernetes Ingress with AWS ALB Ingress Controller"},"content":{"rendered":"\n<h4 class=\"wp-block-heading\">In this blog post you will learn how to set up ingress for your Kubernetes application with AWS Application Load Balancer.<\/h4>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"461\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2021\/02\/philipp-berndt-5i0GnoTTjSE-unsplash.jpg\" alt=\"\" class=\"wp-image-522\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2021\/02\/philipp-berndt-5i0GnoTTjSE-unsplash.jpg 640w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2021\/02\/philipp-berndt-5i0GnoTTjSE-unsplash-300x216.jpg 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n\n\n\n<p>Mots of workloads run on your Kubernetes cluster ultimately need to be exposed to end-users. This is where Ingress comes to play &#8211; a special Kubernetes object responsible for providing external access to the services in a cluster. Typically, you define there rules, how HTTP traffic is routed to the backend services. But every ingress resource must be of some Ingress class that points to a controller, which will, in the end, implement rules with cloud infrastructure and services. When you are on AWS the natural choice is to use <a href=\"https:\/\/kubernetes-sigs.github.io\/aws-load-balancer-controller\/latest\/\" data-type=\"URL\" data-id=\"https:\/\/kubernetes-sigs.github.io\/aws-load-balancer-controller\/latest\/\" target=\"_blank\" rel=\"noreferrer noopener\">Application Load Balancer<\/a> for it. Let&#8217;s see how to do that!<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Installation<\/h5>\n\n\n\n<p>Before we can use ALB, we must first install the controller in our cluster. In this tutorial, I&#8217;ll use an <strong>alb-demo<\/strong> EKS cluster located in <strong>eu-central-1<\/strong> region. As usually in AWS, let&#8217;s start with defining some IAM permissions so that controller can access ALB resources. First, we need to create an IAM OIDC provider for our cluster with the following command.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">eksctl utils associate-iam-oidc-provider \\\n    --region eu-central-1 \\\n    --cluster alb-demo \\\n    --approve<\/pre>\n\n\n\n<p>Next, we create a dedicated IAM policy called <code>AWSLoadBalancerControllerIAMPolicy<\/code>. We use a predefined template, but feel free to modify it if needed.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">curl -o iam-policy.json https:\/\/raw.githubusercontent.com\/kubernetes-sigs\/aws-load-balancer-controller\/v2.1.2\/docs\/install\/iam_policy.json\n\naws iam create-policy \\\n    --policy-name AWSLoadBalancerControllerIAMPolicy \\\n    --policy-document file:\/\/iam-policy.json<\/pre>\n\n\n\n<p>Finally, we can create an IAM role and ServiceAccount for the controller in the <code>kube-system<\/code> namespace. Please note, that we must use the policy ARN from the previous step.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">eksctl create iamserviceaccount \\\n--cluster=alb-demo \\\n--region=eu-central-1 \\\n--namespace=kube-system \\\n--name=aws-load-balancer-controller \\\n--attach-policy-arn=arn:aws:iam::&lt;AWS_ACCOUNT_ID>:policy\/AWSLoadBalancerControllerIAMPolicy \\\n--override-existing-serviceaccounts \\\n--approve<\/pre>\n\n\n\n<p>Now we are ready to deploy the ALB controller to our cluster. The easiest way to do that is to use a Helm chart from the official EKS chart repository.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">helm repo add eks https:\/\/aws.github.io\/eks-charts\nkubectl apply -k \"github.com\/aws\/eks-charts\/stable\/aws-load-balancer-controller\/\/crds?ref=master\"\nhelm install aws-load-balancer-controller eks\/aws-load-balancer-controller -n kube-system \\ \n--set clusterName=alb-demo \\\n--set serviceAccount.create=false \\\n--set serviceAccount.name=aws-load-balancer-controller<\/pre>\n\n\n\n<p>And that&#8217;s it, you can now use ALB when creating ingress for the application. Let&#8217;s see how to do that!<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">ALB configuration<\/h5>\n\n\n\n<p>For the purpose of this tutorial, we will deploy a simple web application into the Kubernetes cluster and expose it to the Internet with an ALB ingress controller. Complete source code is available in the GitLab <a href=\"https:\/\/gitlab.com\/nubisoft-public\/alb-demo\" data-type=\"URL\" data-id=\"https:\/\/gitlab.com\/nubisoft-public\/alb-demo\" target=\"_blank\" rel=\"noreferrer noopener\">repository<\/a>.<\/p>\n\n\n\n<p>Let&#8217;s first run the application on the EKS cluster by creating a deployment and service.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">kubectl apply -f app-deployment.yaml\nkubectl apply -f app-service.yaml<\/pre>\n\n\n\n<p>Now we can deploy the ingress, however before we do that, let&#8217;s take a closer look at it.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">apiVersion: networking.k8s.io\/v1beta1\nkind: Ingress\nmetadata:\n  name: alb-demo-ingress\n  annotations:\n    kubernetes.io\/ingress.class: alb\n    alb.ingress.kubernetes.io\/scheme: internet-facing\n    alb.ingress.kubernetes.io\/listen-ports: '[{\"HTTP\": 80}]'\n    alb.ingress.kubernetes.io\/healthcheck-protocol: HTTP\n    alb.ingress.kubernetes.io\/healthcheck-port: http-healthcheck\n    alb.ingress.kubernetes.io\/healthcheck-path: \/healthcheck\nspec:\n  rules:\n    - http:\n        paths:\n          - path: \/*\n            backend:\n              serviceName: app-service\n              servicePort: 80<\/pre>\n\n\n\n<p>Apart from the standard ingress definition you probably noticed the special annotations attached to this resource. That is where we tell the ingress controller how to configure ALB. In our case, we want to expose our backend service to the Internet at HTTP port 80. We also define a health check so that the load balancer won&#8217;t route traffic to instances that are down. Let&#8217;s deploy the ingress.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">kubectl apply -f ingress.yaml\nkubectl describe ingress\/alb-demo-ingress<\/pre>\n\n\n\n<p>After executing the above command you will probably see the following output.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Name:             alb-demo-ingress\nNamespace:        alb-demo\nAddress:          \nDefault backend:  default-http-backend:80 (&lt;error: endpoints \"default-http-backend\" not found>)\nRules:\n  Host        Path  Backends\n  ----        ----  --------\n  *           \n              \/*   alb-demo-service:80 (172.31.24.80:80)\nAnnotations:  alb.ingress.kubernetes.io\/healthcheck-path: \/healthcheck\n              alb.ingress.kubernetes.io\/healthcheck-port: http-healthcheck\n              alb.ingress.kubernetes.io\/healthcheck-protocol: HTTP\n              alb.ingress.kubernetes.io\/scheme: internet-facing\n              kubernetes.io\/ingress.class: alb\nEvents:\n  Type     Reason            Age               From     Message\n  ----     ------            ----              ----     -------\n  Warning  FailedBuildModel  2s (x10 over 6s)  ingress  Failed build model due to couldn't auto-discover subnets: unable to discover at least one subnet<\/pre>\n\n\n\n<p>Deploy failed with error message: <strong>Failed build model due to couldn&#8217;t auto-discover subnets: unable to discover at least one subnet<\/strong>. This is because we must explicitly mark our subnets with a special tag: <code>kubernetes.io\/role\/elb=1<\/code>. Once this is done, deploying ingress is successful and you can access the app from the browser.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"448\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2021\/02\/image-1024x448.png\" alt=\"\" class=\"wp-image-534\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2021\/02\/image-1024x448.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2021\/02\/image-300x131.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2021\/02\/image-768x336.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2021\/02\/image.png 1061w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h5 class=\"wp-block-heading\">SSL Support<\/h5>\n\n\n\n<p>It&#8217;s always a good idea to serve your application over a secure SSL connection so let&#8217;s see how we can enable it in ALB. As with most of the configuration, this can be done by adding additional annotations to the ingress definition.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"yaml\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">apiVersion: networking.k8s.io\/v1beta1\nkind: Ingress\nmetadata:\n  name: alb-demo-ingress\n  annotations:\n    kubernetes.io\/ingress.class: alb\n    alb.ingress.kubernetes.io\/scheme: internet-facing\n    alb.ingress.kubernetes.io\/listen-ports: '[{\"HTTP\": 80}, {\"HTTPS\": 443}]'\n    alb.ingress.kubernetes.io\/healthcheck-protocol: HTTP\n    alb.ingress.kubernetes.io\/healthcheck-port: http-healthcheck\n    alb.ingress.kubernetes.io\/healthcheck-path: \/healthcheck\n    alb.ingress.kubernetes.io\/certificate-arn: arn:aws:acm:eu-central-1:&lt;ACCOUNT_ID>:certificate\/&lt;CERTIFICATE_ID>\n    alb.ingress.kubernetes.io\/listen-ports: '[{\"HTTP\": 80}, {\"HTTPS\":443}]'\n    alb.ingress.kubernetes.io\/actions.ssl-redirect: '{\"Type\": \"redirect\", \"RedirectConfig\": { \"Protocol\": \"HTTPS\", \"Port\": \"443\", \"StatusCode\": \"HTTP_301\"}}'\n\nspec:\n  rules:\n    - http:\n        paths:\n          - path: \/*\n            backend:\n              serviceName: ssl-redirect\n              servicePort: use-annotation\n          - path: \/*\n            backend:\n              serviceName: app-service\n              servicePort: 80\n<\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">Summary<\/h5>\n\n\n\n<p>As you can see using the ALB ingress controller to expose Kubernetes workloads to the Internet is pretty straightforward, although it requires few preparation steps. Most of the configuration is done using annotations, so make sure you&#8217;ve read the <a rel=\"noreferrer noopener\" href=\"https:\/\/kubernetes-sigs.github.io\/aws-load-balancer-controller\/latest\/guide\/ingress\/annotations\/\" data-type=\"URL\" data-id=\"https:\/\/kubernetes-sigs.github.io\/aws-load-balancer-controller\/latest\/guide\/ingress\/annotations\/\" target=\"_blank\">full documentation<\/a>.<\/p>\n\n\n\n<p>With ALB ingress controller your web application is exposed to end users over the Internet. When traffic grows you may need to scale your infrastructure to ensure best user experience. Read our blog post <a href=\"https:\/\/nubisoft.io\/blog\/how-to-enable-kubernetes-cluster-autoscaling-in-aws\/\" data-type=\"URL\" data-id=\"https:\/\/nubisoft.io\/blog\/how-to-enable-kubernetes-cluster-autoscaling-in-aws\/\">How to enable Kubernetes cluster autoscaling in AWS<\/a> to ensure it&#8217;s done automatically!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this blog post you will learn how to set up ingress for your Kubernetes application with AWS Application Load Balancer. Mots of workloads run on your Kubernetes cluster ultimately need to be exposed to end-users. This is where Ingress comes to play &#8211; a special Kubernetes object responsible for providing external access to the [&hellip;]<\/p>\n","protected":false},"author":5,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_case_study_excerpt":"","footnotes":""},"categories":[55],"tags":[102,32,103,46],"class_list":["post-520","post","type-post","status-publish","format-standard","hentry","category-devops","tag-alb","tag-aws","tag-ingress","tag-kubernetes"],"_links":{"self":[{"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/posts\/520","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/comments?post=520"}],"version-history":[{"count":19,"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/posts\/520\/revisions"}],"predecessor-version":[{"id":776,"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/posts\/520\/revisions\/776"}],"wp:attachment":[{"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/media?parent=520"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/categories?post=520"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/tags?post=520"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}