Skip to content

Commit e1be1bb

Browse files
authored
Merge pull request #296814 from MicrosoftDocs/main
Merge main to live, 4 AM
2 parents 98fb810 + 3df4562 commit e1be1bb

File tree

191 files changed

+2900
-552
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

191 files changed

+2900
-552
lines changed

articles/application-gateway/for-containers/how-to-cert-manager-lets-encrypt-gateway-api.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ services: application-gateway
55
author: greg-lindsay
66
ms.service: azure-appgw-for-containers
77
ms.topic: how-to
8-
ms.date: 3/31/2025
8+
ms.date: 3/21/2025
99
ms.author: greglin
1010
---
1111

@@ -15,7 +15,7 @@ This guide demonstrates how to use cert-manager to automatically issue and renew
1515

1616
For the purposes of this example, we have cert-manager configure certificates issued from Let's Encrypt to demonstrate an end-to-end deployment, where Application Gateway for Containers is providing TLS offloading.
1717

18-
[ ![A figure showing cert-manager retrieving a certificate from Let's Encrypt and storing it into Kubernetes' secret store for TLS with Application Gateway for Containers.](./media/how-to-cert-manager-lets-encrypt-gateway-api/how-to-cert-manager-lets-encrypt-gateway-api.svg) ](./media/how-to-cert-manager-lets-encrypt-gateway-api/how-to-cert-manager-lets-encrypt-gateway-api.svg#lightbox)
18+
[![A diagram showing cert-manager retrieving a certificate from Let's Encrypt and storing it into Kubernetes' secret store for TLS with Application Gateway for Containers.](./media/how-to-cert-manager-lets-encrypt-gateway-api/how-to-cert-manager-lets-encrypt-gateway-api.svg) ](./media/how-to-cert-manager-lets-encrypt-gateway-api/how-to-cert-manager-lets-encrypt-gateway-api.svg#lightbox)
1919

2020
For certificates to be issued by Let's Encrypt, a challenge is required by the authority to validate domain ownership. This validation happens by allowing cert-manager to create a pod and HTTPRoute resource that exposes an endpoint during certificate issuance, proving your ownership of the domain name.
2121

Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
---
2+
title: Cert-manager and Let's Encrypt with Application Gateway for Containers - Ingress API
3+
description: Learn how to configure Application Gateway for Containers with certificates managed by the Cloud Native Computing Foundation (CNCF) project cert-manager.
4+
services: application-gateway
5+
author: philwelz
6+
ms.service: azure-appgw-for-containers
7+
ms.topic: how-to
8+
ms.date: 3/21/2025
9+
ms.author: greglin
10+
---
11+
12+
# Cert-manager and Let's Encrypt with Application Gateway for Containers - Ingress API
13+
14+
This guide demonstrates how to use cert-manager to automatically issue and renew SSL/TLS certificates to one or more frontends of your Azure Application Gateway for Containers deployment. We use the Ingress API to configure the necessary resources.
15+
16+
For the purposes of this example, we have cert-manager configure certificates issued from Let's Encrypt to demonstrate an end-to-end deployment, where Application Gateway for Containers is providing TLS offloading.
17+
18+
[![A diagram showing cert-manager retrieving a certificate from Let's Encrypt and storing it into Kubernetes' secret store for TLS with Application Gateway for Containers.](./media/how-to-cert-manager-lets-encrypt-ingress-api/how-to-cert-manager-lets-encrypt-ingress-api.svg) ](./media/how-to-cert-manager-lets-encrypt-ingress-api/how-to-cert-manager-lets-encrypt-ingress-api.svg#lightbox)
19+
20+
For certificates to be issued by Let's Encrypt, a challenge is required by the authority to validate domain ownership. This validation happens by allowing cert-manager to create a pod and Ingress resource that exposes an endpoint during certificate issuance, proving your ownership of the domain name.
21+
22+
More details on cert-manager and Let's Encrypt with AKS in general may be found [here](https://cert-manager.io/docs/tutorials/getting-started-aks-letsencrypt/).
23+
24+
## Prerequisites
25+
26+
1. If following the BYO deployment strategy, ensure that you set up your Application Gateway for Containers resources and [ALB Controller](quickstart-deploy-application-gateway-for-containers-alb-controller.md)
27+
2. If following the ALB managed deployment strategy, ensure that you provision your [ALB Controller](quickstart-deploy-application-gateway-for-containers-alb-controller.md) and the Application Gateway for Containers resources via the [ApplicationLoadBalancer custom resource](quickstart-create-application-gateway-for-containers-managed-by-alb-controller.md).
28+
3. Deploy sample HTTP application
29+
Apply the following deployment.yaml file on your cluster to create a sample web application to demonstrate the header rewrite.
30+
31+
```bash
32+
kubectl apply -f https://raw.githubusercontent.com/MicrosoftDocs/azure-docs/refs/heads/main/articles/application-gateway/for-containers/examples/traffic-split-scenario/deployment.yaml
33+
```
34+
35+
This command creates the following on your cluster:
36+
37+
- a namespace called `test-infra`
38+
- two services called `backend-v1` and `backend-v2` in the `test-infra` namespace
39+
- two deployments called `backend-v1` and `backend-v2` in the `test-infra` namespace
40+
41+
### Install Cert-Manager
42+
43+
Install cert-manager using Helm:
44+
45+
```bash
46+
helm repo add jetstack https://charts.jetstack.io --force-update
47+
helm upgrade -i \
48+
cert-manager jetstack/cert-manager \
49+
--namespace cert-manager \
50+
--create-namespace \
51+
--version v1.17.1 \
52+
--set installCRDs=true
53+
```
54+
55+
### Create a ClusterIssuer
56+
57+
Create a ClusterIssuer resource to define how cert-manager communicates with Let's Encrypt. For this example, an HTTP challenge is used. During challenge, cert-manager creates an `Ingress` resource and corresponding pod presenting a validation endpoint to prove ownership of the domain. This is done by creating a temporary Ingress resource with the `http01` challenge type. This Ingress resource and corresponding pod created by cert-manager is deleted after the challenge is completed.
58+
59+
>[!Tip]
60+
>Other challenges supported by Let's Encrypt are documented on [letsencrypt.org - Challenge Types](https://letsencrypt.org/docs/challenge-types/)
61+
62+
# [ALB managed deployment](#tab/alb-managed)
63+
64+
Create the ClusterIssuer resource
65+
66+
```bash
67+
kubectl apply -f - <<EOF
68+
apiVersion: cert-manager.io/v1
69+
kind: ClusterIssuer
70+
metadata:
71+
name: letsencrypt-prod
72+
spec:
73+
acme:
74+
server: https://acme-v02.api.letsencrypt.org/directory # production endpoint
75+
#server: https://acme-staging-v02.api.letsencrypt.org/directory # staging endpoint
76+
77+
privateKeySecretRef:
78+
name: letsencrypt-private-key
79+
solvers:
80+
- http01:
81+
ingress:
82+
ingressClassName: azure-alb-external
83+
# This section is required for the Ingress resource created by cert-manager during the challenge
84+
ingressTemplate:
85+
metadata:
86+
annotations:
87+
alb.networking.azure.io/alb-name: alb-test
88+
alb.networking.azure.io/alb-namespace: alb-test-infra
89+
EOF
90+
```
91+
92+
# [Bring your own (BYO) deployment](#tab/byo)
93+
94+
1. Set the following environment variables
95+
96+
```bash
97+
RESOURCE_GROUP='<resource group name of the Application Gateway For Containers resource>'
98+
RESOURCE_NAME='alb-test'
99+
100+
RESOURCE_ID=$(az network alb show --resource-group $RESOURCE_GROUP --name $RESOURCE_NAME --query id -o tsv)
101+
FRONTEND_NAME='frontend'
102+
```
103+
104+
2. Create the ClusterIssuer resource
105+
106+
```bash
107+
kubectl apply -f - <<EOF
108+
apiVersion: cert-manager.io/v1
109+
kind: ClusterIssuer
110+
metadata:
111+
name: letsencrypt-prod
112+
namespace: test-infra
113+
spec:
114+
acme:
115+
server: https://acme-v02.api.letsencrypt.org/directory # production endpoint
116+
#server: https://acme-staging-v02.api.letsencrypt.org/directory # staging endpoint
117+
118+
privateKeySecretRef:
119+
name: letsencrypt-private-key
120+
solvers:
121+
- http01:
122+
ingress:
123+
ingressClassName: azure-alb-external
124+
# This section is required for the Ingress resource created by cert-manager during the challenge
125+
ingressTemplate:
126+
metadata:
127+
annotations:
128+
alb.networking.azure.io/alb-id: $RESOURCE_ID
129+
alb.networking.azure.io/alb-frontend: $FRONTEND_NAME
130+
EOF
131+
```
132+
133+
---
134+
135+
Verify the resource was created by running the following command:
136+
137+
```bash
138+
kubectl get ClusterIssuer -A -o yaml
139+
```
140+
141+
The status should show `True` and type `Ready` under conditions.
142+
143+
```yaml
144+
status:
145+
acme:
146+
lastPrivateKeyHash: x+xxxxxxxxxxxxxxxxxxxxxxx+MY4PAEeotr9XH3V7I=
147+
lastRegisteredEmail: [email protected]
148+
uri: https://acme-staging-v02.api.letsencrypt.org/acme/acct/190567584
149+
conditions:
150+
- lastTransitionTime: "2025-03-20T16:00:21Z"
151+
message: The ACME account was registered with the ACME server
152+
observedGeneration: 1
153+
reason: ACMEAccountRegistered
154+
status: "True"
155+
type: Ready
156+
```
157+
---
158+
## Deploy the required Ingress resource
159+
160+
# [ALB managed deployment](#tab/alb-managed)
161+
162+
Create an Ingress
163+
164+
```bash
165+
kubectl apply -f - <<EOF
166+
apiVersion: networking.k8s.io/v1
167+
kind: Ingress
168+
metadata:
169+
name: ingress-01
170+
namespace: test-infra
171+
annotations:
172+
alb.networking.azure.io/alb-name: alb-test
173+
alb.networking.azure.io/alb-namespace: alb-test-infra
174+
cert-manager.io/cluster-issuer: letsencrypt-prod
175+
spec:
176+
ingressClassName: azure-alb-external
177+
tls:
178+
- hosts:
179+
- backend-v1.contoso.com
180+
# - backend-v2.contoso.com # You can uncomment this and the host line to add an aditional subject alternate name (SAN) to the certificate
181+
secretName: tls-backend
182+
rules:
183+
- host: backend-v1.contoso.com
184+
http:
185+
paths:
186+
- path: /
187+
pathType: Prefix
188+
backend:
189+
service:
190+
name: backend-v1
191+
port:
192+
number: 8080
193+
# - host: backend-v2.contoso.com
194+
# http:
195+
# paths:
196+
# - path: /
197+
# pathType: Prefix
198+
# backend:
199+
# service:
200+
# name: backend-v2
201+
# port:
202+
# number: 8080
203+
EOF
204+
```
205+
206+
# [Bring your own (BYO) deployment](#tab/byo)
207+
208+
1. Set the following environment variables
209+
210+
```bash
211+
RESOURCE_GROUP='<resource group name of the Application Gateway For Containers resource>'
212+
RESOURCE_NAME='alb-test'
213+
214+
RESOURCE_ID=$(az network alb show --resource-group $RESOURCE_GROUP --name $RESOURCE_NAME --query id -o tsv)
215+
FRONTEND_NAME='frontend'
216+
```
217+
218+
2. Create an Ingress resource
219+
220+
```bash
221+
kubectl apply -f - <<EOF
222+
apiVersion: networking.k8s.io/v1
223+
kind: Ingress
224+
metadata:
225+
name: ingress-01
226+
namespace: test-infra
227+
annotations:
228+
alb.networking.azure.io/alb-id: $RESOURCE_ID
229+
alb.networking.azure.io/alb-frontend: $FRONTEND_NAME
230+
cert-manager.io/cluster-issuer: letsencrypt-prod
231+
spec:
232+
ingressClassName: azure-alb-external
233+
tls:
234+
- hosts:
235+
- backend-v1.contoso.com
236+
# - backend-v2.contoso.com # You can uncomment this and the host line to add an aditional subject alternate name (SAN) to the certificate
237+
secretName: tls-backend
238+
rules:
239+
- host: backend-v1.contoso.com
240+
http:
241+
paths:
242+
- path: /
243+
pathType: Prefix
244+
backend:
245+
service:
246+
name: backend-v1
247+
port:
248+
number: 8080
249+
# - host: backend-v2.contoso.com
250+
# http:
251+
# paths:
252+
# - path: /
253+
# pathType: Prefix
254+
# backend:
255+
# service:
256+
# name: backend-v2
257+
# port:
258+
# number: 8080
259+
EOF
260+
```
261+
262+
---
263+
264+
Once the ingress resource is created, ensure the status shows the hostname of your load balancer:
265+
266+
```bash
267+
kubectl get ingress ingress-01 -n test-infra -o yaml
268+
```
269+
270+
Example output of successful Ingress creation.
271+
272+
```yaml
273+
status:
274+
loadBalancer:
275+
ingress:
276+
- hostname: xxxxxxxxxxxxxxxx.fz13.alb.azure.com
277+
ports:
278+
- port: 443
279+
protocol: TCP
280+
```
281+
282+
As mentioned previously, cert-manager creates a temporary Ingress resource and pod to perform the challenge:
283+
284+
```bash
285+
kubectl get pods -n test-infra
286+
NAME READY STATUS RESTARTS AGE
287+
backend-v1-56d99ddb49-mwmcc 1/1 Running 0 10m
288+
backend-v2-8b5d4679b-rsfrg 1/1 Running 0 10m
289+
cm-acme-http-solver-5lmmv 1/1 Running 0 2s
290+
291+
kubectl get ingress -n test-infra
292+
NAME CLASS HOSTS ADDRESS PORTS AGE
293+
cm-acme-http-solver-zrp47 azure-alb-external backend-v1.contoso.com xxxxxxxxxxxxxxxx.fz13.alb.azure.com 80 8s
294+
ingress-01 azure-alb-external backend-v1.contoso.com xxxxxxxxxxxxxxxx.fz13.alb.azure.com 80, 443 10s
295+
```
296+
297+
You can check the status of the challenge by running:
298+
299+
```bash
300+
kubectl get challenges.acme.cert-manager.io -n test-infra
301+
NAME STATE DOMAIN AGE
302+
cert-backend-1-2982214480-3407407859 pending backend-v1.contoso.com 16s
303+
304+
kubectl get certificaterequests.cert-manager.io -n test-infra
305+
NAME APPROVED DENIED READY ISSUER REQUESTER AGE
306+
cert-backend-1 True False letsencrypt-prod system:serviceaccount:cert-manager:cert-manager 34s
307+
```
308+
309+
When the challenge is successful, the status changes to `READY=True` and the certificate is issued:
310+
311+
```bash
312+
kubectl get certificate -n test-infra
313+
NAME READY SECRET AGE
314+
cert-backend True cert-backend 1m
315+
```
316+
317+
>[!Tip]
318+
>You can synchronize the hostnames of Ingress resources created in AKS automatically with Azure DNS zones by utilizing [External DNS](https://kubernetes-sigs.github.io/external-dns/latest/docs/tutorials/azure/) and [Workload Identity](https://kubernetes-sigs.github.io/external-dns/latest/docs/tutorials/azure/#managed-identity-using-workload-identity).
319+
320+
## Test access to the application
321+
322+
The environment is now configured to route traffic to the sample application using the hostname associated with your certificate.
323+
324+
>[!IMPORTANT]
325+
>Ensure you replace `contoso.com` with the domain name you are expecting the certificate to be issued to.
326+
327+
```bash
328+
curl https://backend-v1.contoso.com -v 2>&1 | grep issuer
329+
```
330+
331+
You should see the following output:
332+
333+
`* issuer: C=US; O=Let's Encrypt; CN=R11`
334+
335+
You have successfully installed the ALB Controller, deployed a backend application, obtained a certificate from Let's Encrypt using cert-manager, and configured traffic routing to the application through Application Gateway for Containers.

0 commit comments

Comments
 (0)