Lab Guide: Ingress Resources
Build and test Ingress templates in a Helm chart with path-based routing, TLS, and annotations
Prerequisites
- A running Kubernetes cluster (minikube, kind, or cloud-managed)
- Helm 3 installed
kubectlconfigured and connected to your cluster- An nginx Ingress controller installed:
helm install ingress-nginx ingress-nginx/ingress-nginx
minikube Users
If using minikube, enable the Ingress addon: minikube addons enable ingress. This installs the nginx Ingress controller automatically.
Exercise 1: Basic Ingress Template
Create a Helm chart with a conditional Ingress resource that routes traffic based on hostname and path.
Step 1
Create a new Helm chart:
helm create webapp
cd webapp
Step 2
Replace the contents of values.yaml with the following ingress configuration (keep the existing image and service sections):
# Add/replace the ingress section in values.yaml
ingress:
enabled: true
className: nginx
annotations: {}
hosts:
- host: webapp.local
paths:
- path: /
pathType: Prefix
port: 80
tls: []
Step 3
Open templates/ingress.yaml. If Helm generated one, review it. If not, create it with the following content:
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "webapp.fullname" . }}
labels:
{{- include "webapp.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "webapp.fullname" $ }}
port:
number: {{ .port | default 80 }}
{{- end }}
{{- end }}
{{- end }}
Step 4
Validate the template renders correctly:
helm template my-webapp . | grep -A 30 "kind: Ingress"
Step 5
Verify that disabling ingress removes the resource:
helm template my-webapp . --set ingress.enabled=false | grep "kind: Ingress"
# Should produce no output
Step 6
Install the chart and test:
helm install my-webapp .
kubectl get ingress
kubectl describe ingress my-webapp
Checkpoint
You should see an Ingress resource with host webapp.local and a single path rule pointing to your service on port 80.
Exercise 2: Multi-Host with TLS
Extend the chart to support two hosts with TLS termination.
Step 1
Create a values override file named values-multi.yaml:
ingress:
enabled: true
className: nginx
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
hosts:
- host: www.webapp.local
paths:
- path: /
pathType: Prefix
port: 80
- host: api.webapp.local
paths:
- path: /v1
pathType: Prefix
port: 80
- path: /healthz
pathType: Exact
port: 80
tls:
- secretName: webapp-tls
hosts:
- www.webapp.local
- api.webapp.local
Step 2
Create a self-signed TLS secret for testing:
openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout tls.key \
-out tls.crt \
-subj "/CN=webapp.local"
kubectl create secret tls webapp-tls \
--cert=tls.crt \
--key=tls.key
Step 3
Render the template with the multi-host values:
helm template my-webapp . -f values-multi.yaml
Verify the output contains:
- Two host rules (
www.webapp.localandapi.webapp.local) - Three total path entries (one for www, two for api)
- A
tlsblock with both hosts underwebapp-tls - The
ssl-redirectannotation
Step 4
Upgrade the release with the new values:
helm upgrade my-webapp . -f values-multi.yaml
kubectl get ingress my-webapp -o yaml
Checkpoint
The Ingress should now show two hosts, a TLS section, and the ssl-redirect annotation. If using minikube, add entries to /etc/hosts pointing both hostnames to the minikube IP to test with curl.
Exercise 3: Annotations for Rate Limiting and Auth
Add rate limiting and basic authentication annotations via values.
Step 1
Create an htpasswd secret for basic authentication:
# Install htpasswd if needed: brew install httpd (macOS) or apt install apache2-utils
htpasswd -cb auth admin secretpassword
kubectl create secret generic basic-auth --from-file=auth
rm auth
Step 2
Create a values override file named values-secure.yaml:
ingress:
enabled: true
className: nginx
annotations:
# Rate limiting
nginx.ingress.kubernetes.io/limit-rps: "5"
nginx.ingress.kubernetes.io/limit-connections: "3"
# Basic auth
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: "Restricted Area"
# Upload size
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
hosts:
- host: secure.webapp.local
paths:
- path: /
pathType: Prefix
port: 80
tls: []
Step 3
Render and verify annotations appear in the output:
helm template my-webapp . -f values-secure.yaml | grep -A 20 "annotations:"
You should see all six annotations rendered under metadata.annotations.
Step 4
Upgrade and test the authentication:
helm upgrade my-webapp . -f values-secure.yaml
# Add to /etc/hosts: <minikube-ip> secure.webapp.local
# Test without auth (should get 401):
curl -k http://secure.webapp.local
# Test with auth (should get 200):
curl -k -u admin:secretpassword http://secure.webapp.local
Step 5
Test rate limiting by sending rapid requests:
for i in $(seq 1 20); do
curl -s -o /dev/null -w "%{http_code}\n" \
-u admin:secretpassword \
http://secure.webapp.local
done
# After ~5 requests per second, you should see 503 responses
Checkpoint
You should observe 401 responses without credentials, 200 with correct credentials, and 503 responses when the rate limit is exceeded.
Cleanup
helm uninstall my-webapp
kubectl delete secret webapp-tls basic-auth
rm -f tls.crt tls.key
cd .. && rm -rf webapp