|
| 1 | +# Using a Network Load Balancer with the NGINX Ingress controller on Amazon EKS |
| 2 | + |
| 3 | +## Kubernetes Ingress |
| 4 | + |
| 5 | +Is an API object that provides a colection of routing rules that govern how external/internal users access Kubernetes services running in a cluster. An ingress controller is responsible for reading the ingress resource information and processing it appropriately. |
| 6 | + |
| 7 | +## What is a Network Load Balancer? |
| 8 | + |
| 9 | +An AWS Network Load Balancer functions ath the fourth layer of the Open Systems Interconnection (OSI) model. It can handle millions of requests per second. After the load balancer receives a connection request, it selects a target from the target group for the default rule. It attempts to open a TCP connection to the selected targte on the port specified in the listener configuration. |
| 10 | + |
| 11 | +## Exposing your application on Kubernetes |
| 12 | + |
| 13 | +Ingress is not a service type, but it acts as the entry point for your cluster. It lets you consolidate your routing rules into a single resource, as it can expose multiple services under the same IP address. |
| 14 | + |
| 15 | +Kubernetes supports a high-level abstraction called Ingress, which allows simple host- or URL-based HTTP routing. An Ingress is a core concept of Kubernetes. It is always implemented by a third party proxy; these implementations are know as ingress controllers. An ingress controller is responsible for reading the ingress resource information and processing data accordingly. |
| 16 | + |
| 17 | +An Ingress controller is a DaemonSet or Deployment, deployed as Kubernetes Pod, that watches the endpoint of the API server for updates to the Ingress resource. Its job is to satisfy requests for Ingresses. |
| 18 | + |
| 19 | +## Why do I need a load blancer in front of an ingress? |
| 20 | + |
| 21 | +Ingress is tightly integrated into Kubernetes, meaning that your existing workflows around `kubectl` will likely extend nicely to managing ingress. An Ingress controller does not tipically eliminate the need for an external load blancer, it simply adds an additional layer of routing and control behind the load balancer. |
| 22 | + |
| 23 | +Pods and nodes are not guaranteed to live for the whole lifetime that the user intends: pods are ephemeral and vulnerable to kill signals from Kubernetes during occassion such as: |
| 24 | + |
| 25 | +* Scalling |
| 26 | +* Memory or CPU sturation |
| 27 | +* Rescheduling for more efficient reource use |
| 28 | +* Downtime due to outside factors |
| 29 | + |
| 30 | +The load balancer (Kubernetes service) is a construct that stands as a single, fixed-service endpoint for a given set of pods or worker nodes. To take advantage of the previously-discussed benefits of a Network Load Balancer (NLB), we create a Kubernetes service of type:loadbalancer with the NLB annotations, and this load balancer sits in front of the ingress controller – which is itself a pod or a set of pods. In AWS, for a set of EC2 compute instances managed by an Autoscaling Group, there should be a load balancer that acts as both a fixed referable address and a load balancing mechanism. |
| 31 | + |
| 32 | +## How to use a Network Load Balancer with the NGINX Ingress resource in Kubernetes |
| 33 | + |
| 34 | +### Step 1. Create the mandatory resources for NGINX Ingress in your cluster: |
| 35 | + |
| 36 | +This will create the `nginx-ingress` and the `network load balancer` |
| 37 | + |
| 38 | +```bash |
| 39 | +$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-0.32.0/deploy/static/provider/aws/deploy.yaml |
| 40 | +``` |
| 41 | + |
| 42 | +Create `apple.deploy.yaml` |
| 43 | + |
| 44 | +```yaml |
| 45 | +kind: Pod |
| 46 | +apiVersion: v1 |
| 47 | +metadata: |
| 48 | + name: apple-app |
| 49 | + labels: |
| 50 | + app: apple |
| 51 | +spec: |
| 52 | + containers: |
| 53 | + - name: apple-app |
| 54 | + image: hashicorp/http-echo |
| 55 | + args: |
| 56 | + - "-text=apple" |
| 57 | + |
| 58 | +--- |
| 59 | +kind: Service |
| 60 | +apiVersion: v1 |
| 61 | +metadata: |
| 62 | + name: apple-service |
| 63 | +spec: |
| 64 | + selector: |
| 65 | + app: apple |
| 66 | + ports: |
| 67 | + - port: 5678 |
| 68 | + |
| 69 | +``` |
| 70 | + |
| 71 | +Create `banana.deploy.yaml` |
| 72 | + |
| 73 | +```yaml |
| 74 | +kind: Pod |
| 75 | +apiVersion: v1 |
| 76 | +metadata: |
| 77 | + name: banana-app |
| 78 | + labels: |
| 79 | + app: banana |
| 80 | +spec: |
| 81 | + containers: |
| 82 | + - name: banana-app |
| 83 | + image: hashicorp/http-echo |
| 84 | + args: |
| 85 | + - "-text=banana" |
| 86 | + |
| 87 | +--- |
| 88 | +kind: Service |
| 89 | +apiVersion: v1 |
| 90 | +metadata: |
| 91 | + name: banana-service |
| 92 | +spec: |
| 93 | + selector: |
| 94 | + app: banana |
| 95 | + ports: |
| 96 | + - port: 5678 |
| 97 | + |
| 98 | +``` |
| 99 | + |
| 100 | + |
| 101 | +Create some services |
| 102 | + |
| 103 | +```bash |
| 104 | +$ kubectl apply -f ./apple.deploy.yaml |
| 105 | +$ kubectl apply -f ./banana.deploy.yaml |
| 106 | +``` |
| 107 | + |
| 108 | +## Step 2. Defining the Ingress resource to route traffic to the services created above |
| 109 | + |
| 110 | +Now declare an Ingress to route requests to `/apple` to the first service, and requests to `/banana` to second service. Create `fruits.ingress.yml` |
| 111 | + |
| 112 | +```yml |
| 113 | +apiVersion: extensions/v1beta1 |
| 114 | +kind: Ingress |
| 115 | +metadata: |
| 116 | + name: example-ingress |
| 117 | +spec: |
| 118 | + rules: |
| 119 | + - host: jaimesalas.com |
| 120 | + http: |
| 121 | + paths: |
| 122 | + - path: /apple |
| 123 | + backend: |
| 124 | + serviceName: apple-service |
| 125 | + servicePort: 5678 |
| 126 | + - path: /banana |
| 127 | + backend: |
| 128 | + serviceName: banana-service |
| 129 | + servicePort: 5678 |
| 130 | + |
| 131 | +``` |
| 132 | + |
| 133 | +And apply to our cluster |
| 134 | + |
| 135 | +```bash |
| 136 | +$ kubectl apply -f fruits.ingress.yml |
| 137 | +``` |
| 138 | + |
| 139 | +Now to check that our ingress is working we need the `dns` of NLB that we have created, the easiest way to do this is run: |
| 140 | + |
| 141 | +```bash |
| 142 | +$ kubectl get ingress |
| 143 | +NAME CLASS HOSTS ADDRESS PORTS AGE |
| 144 | +example-ingress <none> jaimesalas.com a2e47070555144b06a0cd99a242d6753-ef17945a5e983c95.elb.eu-west-3.amazonaws.com 80 39m |
| 145 | +``` |
| 146 | +The above adress is the `NLB` resource that's forwarding traffic to the ingress controller, if we run the following |
| 147 | + |
| 148 | +**-I** the response only contains the headers |
| 149 | + |
| 150 | +```bash |
| 151 | +$ curl -I http://a2e47070555144b06a0cd99a242d6753-ef17945a5e983c95.elb.eu-west-3.amazonaws.com |
| 152 | +``` |
| 153 | + |
| 154 | +We get the following response |
| 155 | + |
| 156 | +``` |
| 157 | +HTTP/1.1 404 Not Found |
| 158 | +Server: nginx/1.17.10 |
| 159 | +Date: Wed, 16 Dec 2020 16:53:31 GMT |
| 160 | +Content-Type: text/html |
| 161 | +Content-Length: 154 |
| 162 | +Connection: keep-alive |
| 163 | +``` |
| 164 | + |
| 165 | +> NOTE: The default server returns a "Not Found" page with 404 status code for all the requests for domains where no Ingress rules are defined. The Ingress Controller, based on the defined rules, doesn't divert traffic to the specified backend service, unless the request matches with the configuration. |
| 166 | +
|
| 167 | +Beacuse the **host** field is configured for the Ingress object, you must supply the **Host** header of the request with the same `hostname` |
| 168 | + |
| 169 | +```bash |
| 170 | +$ curl -I -H "Host: jaimesalas.com" http://a2e47070555144b06a0cd99a242d6753-ef17945a5e983c95.elb.eu-west-3.amazonaws.com/apple/ |
| 171 | +``` |
| 172 | + |
| 173 | +And now we get the following result |
| 174 | + |
| 175 | +``` |
| 176 | +HTTP/1.1 200 OK |
| 177 | +Server: nginx/1.17.10 |
| 178 | +Date: Wed, 16 Dec 2020 17:07:35 GMT |
| 179 | +Content-Type: text/plain; charset=utf-8 |
| 180 | +Content-Length: 6 |
| 181 | +Connection: keep-alive |
| 182 | +X-App-Name: http-echo |
| 183 | +X-App-Version: 0.2.3 |
| 184 | +``` |
| 185 | + |
| 186 | +## Step 3. Clean up |
| 187 | + |
| 188 | +Deelete Ingress resource |
| 189 | + |
| 190 | +```bash |
| 191 | +$ kubectl delete -f fruits.ingress.yml |
| 192 | +``` |
| 193 | + |
| 194 | +Delete services |
| 195 | + |
| 196 | +```bash |
| 197 | +$ kubectl delete -f ./apple.deploy.yaml |
| 198 | +$ kubectl delete -f ./banana.deploy.yaml |
| 199 | +``` |
| 200 | + |
| 201 | +Delete NGINX Ingress Controller and NLB |
| 202 | + |
| 203 | +```bash |
| 204 | +$ kubectl delete -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-0.32.0/deploy/static/provider/aws/deploy.yaml |
| 205 | +``` |
0 commit comments