Skip to content

Commit b133faf

Browse files
committed
add documentation for aws ingress controller
1 parent 97035fa commit b133faf

File tree

3 files changed

+394
-0
lines changed

3 files changed

+394
-0
lines changed
Lines changed: 394 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,394 @@
1+
# Publish your website as a public secured service
2+
3+
4+
## Requirements
5+
6+
7+
- read the previous chapter [Deploy abcdesktop on AWS with Amazon Elastic Kubernetes Service](aws)
8+
- an AWS account
9+
- your own internet domain
10+
- `aws` command line interface [aws-cli](https://aws.amazon.com/cli/)
11+
- `kubectl` command line
12+
- `helm` command line
13+
14+
## Overview
15+
16+
In this chapter we are going to, use a `nginx-ingress-controller` to host your abcdesktop service with a public IP Address, then configure dns zone file to use your own domain name, and activate TLS to secure your service.
17+
18+
## Add tags for public subnets
19+
20+
By default, when creating your VPC, the public subnets does not have the `kubernetes.io/role/elb=1` tag, but this tag is mandatory in order to expose our service using a nginx ingress controller with AWS. Actually, AWS scans your VPC, searching for the subnets with this percise tag to place the ingress controller.
21+
22+
To do so, run the following command
23+
24+
```
25+
aws ec2 create-tags --resources <your_public_subnets_ids> --tags Key=kubernetes.io/role/elb,Value=1
26+
```
27+
28+
> You can find your public subnets ids in the `Subnets` page of the VPC dashboard on AWS console
29+
30+
You can check if the tags have been applied by running the following command
31+
32+
```
33+
aws ec2 describe-subnets --filters "Name=vpc-id,Values=<your_vpc_id>" "Name=tag:kubernetes.io/role/elb,Values=1" --query 'Subnets[*].[SubnetId,AvailabilityZone]' --output table
34+
```
35+
36+
You should read on stdout
37+
38+
```
39+
--------------------------------------------
40+
| DescribeSubnets |
41+
+---------------------------+--------------+
42+
| subnet-09c09bd5bbdec72a6 | us-east-1b |
43+
| subnet-02d592feab5bb0faf | us-east-1a |
44+
+---------------------------+--------------+
45+
46+
```
47+
48+
## Deploy nginx ingress controller
49+
50+
You will now deploy a nginx ingress controller on your cluster using `helm`.
51+
52+
First, run the following command to add the nginx ingress controller repository :
53+
54+
```
55+
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx && helm repo update
56+
```
57+
58+
Then install it on your cluster
59+
60+
```
61+
helm install ingress-nginx ingress-nginx/ingress-nginx --namespace ingress-nginx --create-namespace
62+
```
63+
64+
Once the installation process completed, you can check that the service has been createed by running this command :
65+
66+
```
67+
kubectl get svc ingress-nginx-controller -n ingress-nginx
68+
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
69+
ingress-nginx-controller LoadBalancer 172.20.87.254 <pending> 80:32337/TCP,443:30414/TCP 34s
70+
```
71+
72+
You will see that `EXTERNAL-IP` is `<pending>` forever, it is totally noraml because by default the controller is considering your service as internal, to make it public you should add annotations by running the following command
73+
74+
```
75+
kubectl annotate svc ingress-nginx-controller -n ingress-nginx service.beta.kubernetes.io/aws-load-balancer-scheme=internet-facing service.beta.kubernetes.io/aws-load-balancer-type=nlb --overwrite
76+
```
77+
78+
Now you can run the previous command until you get an `EXTERNAL-IP`
79+
80+
```
81+
kubectl get svc ingress-nginx-controller -n ingress-nginx
82+
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
83+
ingress-nginx-controller LoadBalancer 172.20.87.254 k8s-ingressn-ingressn-dc31c08978-b7ef1bca03cfe45b.elb.us-east-1.amazonaws.com 80:32337/TCP,443:30414/TCP 3m
84+
85+
```
86+
87+
### Create new record
88+
89+
We are going to create a new record `hello` (`hello.aws.pepins.net`) using `k8s-ingressn-ingressn-dc31c08978-b7ef1bca03cfe45b.elb.us-east-1.amazonaws.com` as an alias.
90+
91+
First, you will need your load balancer hosted zone id. To get, run the following command :
92+
93+
```
94+
aws elbv2 describe-load-balancers --region us-east-1 --query 'LoadBalancers[0].CanonicalHostedZoneId'
95+
```
96+
97+
You should get something like this
98+
99+
```
100+
Z26RNL4JYFTOTI
101+
```
102+
103+
Now paste the following lines in a `create-record-abcdesktop-aws.json` file :
104+
105+
```
106+
{
107+
"Comment": "create a new record for abcdesktop on aws",
108+
"Changes": [
109+
{
110+
"Action": "CREATE",
111+
"ResourceRecordSet": {
112+
"Name": "hello.aws.pepins.net.",
113+
"Type": "A",
114+
"AliasTarget": {
115+
"HostedZoneId": "<your_hosted_zone_id>",
116+
"DNSName": "k8s-ingressn-ingressn-dc31c08978-b7ef1bca03cfe45b.elb.us-east-1.amazonaws.com",
117+
"EvaluateTargetHealth": false
118+
}
119+
}
120+
}
121+
]
122+
}
123+
```
124+
125+
Now, you will need to retrieve the hosted zone id of your domain on route 53. You can get it through the Route 53 web interface, or by running the following command :
126+
127+
```
128+
aws route53 list-hosted-zones --query 'HostedZones[*].[Name,Id]' --output table
129+
```
130+
131+
You should read something like this
132+
133+
```
134+
--------------------------------------------------------
135+
| ListHostedZones |
136+
+------------------+-----------------------------------+
137+
| aws.pepins.net. | /hostedzone/Z0710575SCBYT0OUKZP |
138+
+------------------+-----------------------------------+
139+
```
140+
141+
Finally, run this command to add the record :
142+
143+
```
144+
aws route53 change-resource-record-sets --hosted-zone-id <your_domain_hosted_zone_id> --change-batch file://create-record-abcdesktop-aws.json
145+
```
146+
147+
For example
148+
149+
```
150+
aws route53 change-resource-record-sets --hosted-zone-id Z0710575SCBYT0OUKZP --change-batch file://create-record-abcdesktop-aws.json
151+
```
152+
153+
You should read something like this
154+
155+
```
156+
{
157+
"ChangeInfo": {
158+
"Id": "/change/C07091422RBO1K64I6QWN",
159+
"Status": "PENDING",
160+
"SubmittedAt": "2026-01-14T13:30:30.133000+00:00",
161+
"Comment": "create a new record for abcdesktop on aws"
162+
}
163+
}
164+
```
165+
166+
If you go to your Route 53 web console, you should see the record you juste added
167+
168+
![aws record added](img/record-added.png)
169+
170+
From your local device, you can open a web browser
171+
172+
![reach your website from your new name](img/http-dns-connect.png)
173+
174+
175+
Web browser doesn't allow usage of websocket without secure protocol. To login you need `https` protocol.
176+
177+
As you can see, your website is `Not Secured`, we are going to add X509 SSL certificate to secure your service.
178+
179+
## Enable HTTPS
180+
181+
### Install Cert Manager add-on on AWS EKS marketplace
182+
183+
Navigate to the Add-ons section of your cluster on the AWS console, then click on `Get more add-ons` and install Cert Manager.
184+
185+
![cert manager](img/cert-manager.png)
186+
187+
Once intalled, you can inspect the Kubernetes ressources created by Cert Manager :
188+
189+
```
190+
kubectl get all -n cert-manager
191+
```
192+
193+
The output looks similar to the following
194+
195+
```
196+
NAME READY STATUS RESTARTS AGE
197+
pod/cert-manager-76f99d9cbb-z5dgj 1/1 Running 0 3h26m
198+
pod/cert-manager-76f99d9cbb-z7jnv 1/1 Running 0 3h26m
199+
pod/cert-manager-cainjector-558b47dbf9-h55gx 1/1 Running 0 3h26m
200+
pod/cert-manager-cainjector-558b47dbf9-lvgzl 1/1 Running 0 3h26m
201+
pod/cert-manager-webhook-7db584cc6c-9qz5q 1/1 Running 0 3h26m
202+
pod/cert-manager-webhook-7db584cc6c-l5s58 1/1 Running 0 3h26m
203+
204+
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
205+
service/cert-manager ClusterIP 172.20.196.196 <none> 9402/TCP 3h26m
206+
service/cert-manager-cainjector ClusterIP 172.20.102.95 <none> 9402/TCP 3h26m
207+
service/cert-manager-webhook ClusterIP 172.20.105.49 <none> 443/TCP,9402/TCP 3h26m
208+
209+
NAME READY UP-TO-DATE AVAILABLE AGE
210+
deployment.apps/cert-manager 2/2 2 2 3h26m
211+
deployment.apps/cert-manager-cainjector 2/2 2 2 3h26m
212+
deployment.apps/cert-manager-webhook 2/2 2 2 3h26m
213+
214+
NAME DESIRED CURRENT READY AGE
215+
replicaset.apps/cert-manager-76f99d9cbb 2 2 2 3h26m
216+
replicaset.apps/cert-manager-cainjector-558b47dbf9 2 2 2 3h26m
217+
replicaset.apps/cert-manager-webhook-7db584cc6c 2 2 2 3h26m
218+
```
219+
220+
The cert-manager pods and webhook service are running.
221+
222+
Cert-Manager creates custom resource definitions (CRDs). Cert-Manager relies on three important CRDs to issue certificates from a Certificate Authority (such as Let’s Encrypt):
223+
224+
Issuer: Defines a namespaced certificate issuer, which allows you to use different CAs in each namespace.
225+
226+
ClusterIssuer: Similar to Issuer, but it does not belong to a namespace and can be used to issue certificates in any namespace.
227+
228+
Certificate: Defines a namespaced resource that references an Issuer or ClusterIssuer for issuing certificates.
229+
230+
Inspect the CRDs by running the following command :
231+
232+
```
233+
kubectl get crd -l app.kubernetes.io/name=cert-manager
234+
```
235+
236+
The output looks similar to the following
237+
238+
```
239+
NAME CREATED AT
240+
certificaterequests.cert-manager.io 2026-01-19T10:23:33Z
241+
certificates.cert-manager.io 2026-01-19T10:23:34Z
242+
challenges.acme.cert-manager.io 2026-01-19T10:23:33Z
243+
clusterissuers.cert-manager.io 2026-01-19T10:23:34Z
244+
issuers.cert-manager.io 2026-01-19T10:23:34Z
245+
orders.acme.cert-manager.io 2026-01-19T10:23:33Z
246+
```
247+
248+
### Configure Production-Ready TLS Certificates for nginx
249+
250+
You can issue the certificate using an Issuer. Configure a certificate issuers resource for Cert-Manager, which fetches the TLS certificate for nginx to use. The certificate issuer uses the HTTP-01 challenge provider to accomplish this task.
251+
252+
Create the following manifest, replace `<your-valid-email-address>` with your own value, and save it as cert-manager-issuer.yaml :
253+
254+
```
255+
apiVersion: cert-manager.io/v1
256+
kind: Issuer
257+
metadata:
258+
name: letsencrypt-nginx
259+
spec:
260+
acme:
261+
email: <your-valid-email-address>
262+
server: https://acme-v02.api.letsencrypt.org/directory
263+
privateKeySecretRef:
264+
name: letsencrypt-nginx-private-key
265+
solvers:
266+
# Use the HTTP-01 challenge provider
267+
- http01:
268+
ingress:
269+
class: nginx
270+
```
271+
272+
The ACME issuer configuration has the following fields:
273+
274+
email: Email address to be associated with the ACME account.
275+
server: URL used to access the ACME server’s directory endpoint.
276+
privateKeySecretRef: Kubernetes secret to store the automatically generated ACME account private key.
277+
278+
The ingress resources use the HTTP-01 challenge.
279+
280+
```
281+
kubectl apply -f cert-manager-issuer.yaml -n abcdesktop
282+
```
283+
284+
The output looks similar to the following
285+
286+
```
287+
issuer.cert-manager.io/letsencrypt-nginx created
288+
```
289+
290+
Verify that the Issuer resource is created:
291+
292+
```
293+
kubectl get issuer -n abcdesktop
294+
```
295+
296+
The output looks similar to the following
297+
298+
```
299+
NAME READY AGE
300+
letsencrypt-nginx True 7s
301+
```
302+
303+
Next, configure each nginx ingress resource to use TLS. Open the previous `abcdesktop_host.yaml` manifest you created previously for the route application, add the `annotations` and `tls` sections shown below, and save the `abcdesktop_host.yaml` file : You can also add dedicated `nginx.ingress.kubernetes.io` annotations to increase default timeout values. Replace `hello.aws.pepins.net` by own FQDN
304+
305+
```
306+
apiVersion: networking.k8s.io/v1
307+
kind: Ingress
308+
metadata:
309+
name: ingress-abcdesktop
310+
namespace: abcdesktop
311+
annotations:
312+
cert-manager.io/issuer: letsencrypt-nginx
313+
nginx.org/client-max-body-size: "256M"
314+
nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
315+
nginx.ingress.kubernetes.io/proxy-read-timeout: "1800"
316+
nginx.ingress.kubernetes.io/proxy-send-timeout: "1800"
317+
nginx.ingress.kubernetes.io/proxy-body-size: "256M"
318+
spec:
319+
tls:
320+
- hosts:
321+
- hello.aws.pepins.net
322+
secretName: letsencrypt-nginx-echo
323+
rules:
324+
- host: hello.aws.pepins.net
325+
http:
326+
paths:
327+
- path: /
328+
pathType: Prefix
329+
backend:
330+
service:
331+
name: http-router
332+
port:
333+
number: 80
334+
ingressClassName: nginx
335+
```
336+
337+
Run the following command to configure the hosts to use TLS:
338+
339+
```
340+
kubectl apply -f abcdesktop_host.yaml -n abcdesktop
341+
```
342+
343+
After a few minutes, check the state of the ingress object:
344+
345+
```
346+
kubectl get ingress -n abcdesktop
347+
NAME CLASS HOSTS ADDRESS PORTS AGE
348+
ingress-abcdesktop nginx hello.aws.pepins.net k8s-ingressn-ingressn-dc31c08978-b7ef1bca03cfe45b.elb.us-east-1.amazonaws.com 80, 443 42m
349+
```
350+
351+
You see that 443 appeard in the `PORTS` section.
352+
353+
Check that the certificate resource is created
354+
355+
```
356+
kubectl get certificates -n abcdesktop
357+
```
358+
359+
The output looks similar to the following
360+
361+
```
362+
NAME READY SECRET AGE
363+
letsencrypt-nginx-echo True letsencrypt-nginx-echo 3m27s
364+
```
365+
366+
Run a simple curl command line `curl -Li https://hello.aws.pepins.net/` to confirm that your secured abcdesktop service is running.
367+
368+
```
369+
curl -Li https://hello.aws.pepins.net/
370+
HTTP/2 200
371+
date: Mon, 19 Jan 2026 14:06:46 GMT
372+
content-type: text/html
373+
content-length: 56291
374+
vary: Accept-Encoding
375+
last-modified: Tue, 16 Dec 2025 11:52:18 GMT
376+
etag: "694147f2-dbe3"
377+
accept-ranges: bytes
378+
x-frame-options: SAMEORIGIN
379+
x-xss-protection: 1; mode=block
380+
strict-transport-security: max-age=31536000; includeSubDomains
381+
382+
<!doctype html>
383+
...
384+
```
385+
386+
## Reach your website using `https` protocol
387+
388+
You can now connect to your abcdesktop desktop pulic web site using `https` protocol.
389+
390+
![reach your website using https](img/https-dns-connect.png)
391+
392+
The status is secured and we get some informations from the certificate
393+
394+
![reach your website using https](img/certificate-ingress-ok.png)
75.6 KB
Loading
47 KB
Loading

0 commit comments

Comments
 (0)