CKA Practice Question 2
CKA Practice Question 2
Question 2: Migrate from Ingress to Gateway API
Scenario:
Migrate an existing web application from Ingress to Gateway API. We must maintain HTTPSaccess.
A GatewayClass named nginx is installed in the cluster.
Tasks:
First, create a Gateway named
web-gatewaywith hostnamegateway.web.k8s.localthat maintains the existing routing rules and listener configuration from the existing Ingress resource namedweb.Next, create an HTTPRoute named
web-routefor hostnamegateway.web.k8s.localthat maintains the existing routing rules from the current Ingress resource namedweb.You can test your Gateway API configuration with the following command:
[candidate@cka2025] $ curl https://gateway.web.k8s.localFinally, delete the existing Ingress resource named
web.
Task Requirements:
- Namespace:
default(or as specified in the exam) - GatewayClass:
nginx(already installed) - Gateway Name:
web-gateway - Gateway Hostname:
gateway.web.k8s.local - HTTPRoute Name:
web-route - Existing Ingress:
web(to be deleted after migration) - Protocol: HTTPS
- Validation:
curl https://gateway.web.k8s.localshould work
Weight: 8%
Solution
Step 0: Understand the Current Setup
First, examine the existing Ingress resource to understand what needs to be migrated:
# View the existing Ingress
kubectl get ingress web -o yaml
# Save it for reference
kubectl get ingress web -o yaml > ingress-web-backup.yamlExample Ingress Configuration:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
namespace: default
spec:
ingressClassName: nginx
tls:
- hosts:
- gateway.web.k8s.local
secretName: web-tls-secret
rules:
- host: gateway.web.k8s.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80Step 1: Verify GatewayClass
# Check if the nginx GatewayClass exists
kubectl get gatewayclass
# View details
kubectl get gatewayclass nginx -o yamlExpected Output:
NAME CONTROLLER ACCEPTED AGE
nginx nginx.org/gateway-controller true 5dStep 2: Create the Gateway Resource
Create a Gateway named web-gateway that listens on HTTPS with the hostname gateway.web.k8s.local:
# Create the Gateway
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: web-gateway
namespace: default
spec:
gatewayClassName: nginx
listeners:
- name: https
protocol: HTTPS
port: 443
hostname: gateway.web.k8s.local
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: web-tls-secret
allowedRoutes:
namespaces:
from: Same
EOFAlternative: Using kubectl create (if available in your K8s version)
# Note: This is a simplified example, you'll likely need to use YAML
kubectl create gateway web-gateway \
--class=nginx \
--namespace=defaultKey Points
- gatewayClassName: Must match the installed GatewayClass (
nginx) - protocol: HTTPS to maintain secure access
- hostname: Must match
gateway.web.k8s.local - tls.mode:
Terminatemeans the Gateway handles TLS termination - certificateRefs: Reference the same TLS secret used by the Ingress
Step 3: Create the HTTPRoute Resource
Create an HTTPRoute named web-route that routes traffic from the Gateway to the backend service:
# Create the HTTPRoute
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: web-route
namespace: default
spec:
parentRefs:
- name: web-gateway
namespace: default
hostnames:
- gateway.web.k8s.local
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: web-service
port: 80
EOFKey Points
- parentRefs: Links this HTTPRoute to the
web-gatewayGateway - hostnames: Must match the Gateway hostname
- matches: Defines path matching rules (equivalent to Ingress paths)
- backendRefs: Points to the backend service (same as Ingress backend)
Step 4: Verify the Gateway and HTTPRoute
# Check Gateway status
kubectl get gateway web-gateway
kubectl describe gateway web-gateway
# Check HTTPRoute status
kubectl get httproute web-route
kubectl describe httproute web-route
# View detailed configuration
kubectl get gateway web-gateway -o yaml
kubectl get httproute web-route -o yamlExpected Gateway Status:
NAME CLASS ADDRESS PROGRAMMED AGE
web-gateway nginx 10.96.100.50 True 30sExpected HTTPRoute Status:
NAME HOSTNAMES AGE
web-route ["gateway.web.k8s.local"] 30sStep 5: Test the Configuration
# Test HTTPS access
curl https://gateway.web.k8s.local
# Test with verbose output
curl -v https://gateway.web.k8s.local
# If you need to bypass certificate validation (testing only)
curl -k https://gateway.web.k8s.local
# Check from within the cluster
kubectl run test-pod --rm -it --image=curlimages/curl -- \
curl https://gateway.web.k8s.localExpected Output:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Web Application</title>
</head>
<body>
<h1>Success! Gateway API is working.</h1>
</body>
</html>Step 6: Delete the Old Ingress Resource
Once you've confirmed the Gateway API is working correctly, delete the old Ingress:
# Delete the Ingress
kubectl delete ingress web
# Verify it's deleted
kubectl get ingressImportant
Only delete the Ingress AFTER you've verified that the Gateway API configuration is working correctly!
Complete Solution Summary
Here's the complete workflow in order:
# 1. Backup existing Ingress
kubectl get ingress web -o yaml > ingress-web-backup.yaml
# 2. Verify GatewayClass
kubectl get gatewayclass nginx
# 3. Create Gateway
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: web-gateway
namespace: default
spec:
gatewayClassName: nginx
listeners:
- name: https
protocol: HTTPS
port: 443
hostname: gateway.web.k8s.local
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: web-tls-secret
allowedRoutes:
namespaces:
from: Same
EOF
# 4. Create HTTPRoute
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: web-route
namespace: default
spec:
parentRefs:
- name: web-gateway
namespace: default
hostnames:
- gateway.web.k8s.local
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: web-service
port: 80
EOF
# 5. Verify Gateway and HTTPRoute
kubectl get gateway web-gateway
kubectl get httproute web-route
# 6. Test the configuration
curl https://gateway.web.k8s.local
# 7. Delete old Ingress
kubectl delete ingress webBest Practices
1. Always Backup Before Migration
# Backup all Ingress resources
kubectl get ingress -A -o yaml > all-ingress-backup.yaml
# Backup specific Ingress
kubectl get ingress web -o yaml > ingress-web-backup.yaml
# Backup related services
kubectl get svc web-service -o yaml > service-backup.yaml2. Understand Gateway API Architecture
Gateway API is the successor to Ingress and provides:
- Better role separation: GatewayClass (infra) → Gateway (ops) → Routes (devs)
- More expressive routing: Header-based, query parameter routing, etc.
- Protocol support: HTTP, HTTPS, TCP, UDP, gRPC
- Portable: Works across different implementations
3. Verify TLS Certificates
# Check if the TLS secret exists
kubectl get secret web-tls-secret
# View certificate details
kubectl get secret web-tls-secret -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text -noout
# Verify certificate matches hostname
kubectl get secret web-tls-secret -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -subject4. Use Proper Path Matching
Gateway API supports different path matching types:
# Exact match
- path:
type: Exact
value: /api/v1/users
# Prefix match (most common)
- path:
type: PathPrefix
value: /api
# Regular expression (if supported by implementation)
- path:
type: RegularExpression
value: /api/v[0-9]+/.*5. Implement Health Checks
# Check Gateway status
kubectl get gateway web-gateway -o jsonpath='{.status.conditions[*].type}'
# Check if Gateway is programmed
kubectl get gateway web-gateway -o jsonpath='{.status.conditions[?(@.type=="Programmed")].status}'
# Check HTTPRoute status
kubectl get httproute web-route -o jsonpath='{.status.parents[*].conditions[*].type}'6. Use Labels and Annotations
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: web-gateway
labels:
app: web
environment: production
migrated-from: ingress
annotations:
description: "Migrated from Ingress web on 2026-01-10"
migration-ticket: "JIRA-1234"7. Monitor Gateway Metrics
# Check Gateway events
kubectl get events --field-selector involvedObject.name=web-gateway
# Check HTTPRoute events
kubectl get events --field-selector involvedObject.name=web-route
# View Gateway controller logs (example for nginx)
kubectl logs -n nginx-gateway -l app=nginx-gateway-controller8. Implement Gradual Migration
For production environments, use a gradual migration strategy:
# Step 1: Deploy Gateway alongside Ingress
# Step 2: Test Gateway with a subset of traffic
# Step 3: Gradually shift traffic from Ingress to Gateway
# Step 4: Monitor for issues
# Step 5: Delete Ingress only when confident9. Use ReferenceGrant for Cross-Namespace Access
If your backend service is in a different namespace:
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-gateway-to-backend
namespace: backend-namespace
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: default
to:
- group: ""
kind: Service10. Document the Migration
# Add annotations to track migration
kubectl annotate gateway web-gateway \
migration-date="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
migrated-from="ingress/web" \
migrated-by="candidate@cka2025"
kubectl annotate httproute web-route \
migration-date="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
original-ingress="web"Common Pitfalls to Avoid
Common Mistakes
Wrong API Version: Gateway API is
gateway.networking.k8s.io/v1, notnetworking.k8s.io/v1Missing GatewayClass: Verify the GatewayClass exists before creating Gateway
Hostname Mismatch: Gateway hostname and HTTPRoute hostname must match
TLS Secret Not Found: Ensure the TLS secret exists in the same namespace as the Gateway
Wrong Parent Reference: HTTPRoute must reference the correct Gateway name
Deleting Ingress Too Early: Always test Gateway first before deleting Ingress
Namespace Issues: Gateway and HTTPRoute must be in the correct namespace
Port Mismatch: Ensure backend service port matches the HTTPRoute backendRef port
Protocol Confusion: Use HTTPS in Gateway listener, but HTTP in HTTPRoute backendRef (if backend is HTTP)
Not Checking Status: Always verify Gateway and HTTPRoute status before testing
Time-Saving Tips
- Use
kubectl apply -f -with heredoc for quick resource creation - Keep Gateway API YAML templates ready
- Use
kubectl explain gateway.specto quickly check field requirements - Practice the migration flow multiple times
- Use
kubectl get gateway,httprouteto view both resources at once - Remember: Gateway API uses
backendRefs(plural), notbackend(singular)
Important Notes
- Gateway API is the successor to Ingress (more powerful and flexible)
- Not all clusters have Gateway API installed by default
- Different implementations (nginx, istio, envoy) may have slight differences
- Always check the
statusfield to verify resources are properly configured - Gateway API supports advanced features like traffic splitting, header manipulation, etc.
- In the exam, focus on basic migration - don't overcomplicate
Ingress vs Gateway API Comparison
| Feature | Ingress | Gateway API |
|---|---|---|
| API Group | networking.k8s.io | gateway.networking.k8s.io |
| Role Separation | Single resource | GatewayClass → Gateway → Routes |
| Protocol Support | HTTP/HTTPS only | HTTP, HTTPS, TCP, UDP, gRPC |
| Routing Capabilities | Basic path/host | Advanced (headers, query params, etc.) |
| Traffic Splitting | Limited | Native support |
| Cross-namespace | Limited | ReferenceGrant support |
| Maturity | GA (stable) | GA (v1.0 released) |
| Future | Maintenance mode | Active development |
Gateway API Key Concepts
1. GatewayClass
- Defines the controller implementation (nginx, istio, etc.)
- Managed by cluster operators
- Similar to IngressClass
2. Gateway
- Defines listeners (ports, protocols, hostnames)
- Managed by cluster operators
- Can be shared by multiple Routes
3. HTTPRoute
- Defines routing rules
- Managed by application developers
- References a Gateway as parent
4. TLS Configuration
- Terminate: Gateway handles TLS, backends use HTTP
- Passthrough: Gateway forwards encrypted traffic to backends
Quick Reference Commands
# Essential commands for this task (in order)
kubectl get ingress web -o yaml > backup.yaml
kubectl get gatewayclass nginx
kubectl apply -f gateway.yaml
kubectl apply -f httproute.yaml
kubectl get gateway web-gateway
kubectl get httproute web-route
kubectl describe gateway web-gateway
kubectl describe httproute web-route
curl https://gateway.web.k8s.local
kubectl delete ingress webExam Tips for This Question
Read Carefully: Note the exact names required (web-gateway, web-route, etc.)
Time Allocation: This is an 8% question, allocate approximately 10-12 minutes
API Version: Use
gateway.networking.k8s.io/v1(not v1beta1 or v1alpha2)Verify Before Deleting: Always test the Gateway configuration before deleting the Ingress
Check Status Fields: Use
kubectl describeto check if resources are properly configuredHTTPS vs HTTP: Gateway listener uses HTTPS, but backend might use HTTP
Use kubectl explain: If unsure about fields, use
kubectl explain gateway.spec.listenersDon't Overthink: The migration is straightforward - just map Ingress fields to Gateway API equivalents
Additional Practice
Try these variations to deepen your understanding:
- Create a Gateway with multiple listeners (HTTP and HTTPS)
- Implement path-based routing with multiple HTTPRoutes
- Configure header-based routing
- Set up traffic splitting between two backend services
- Implement cross-namespace routing with ReferenceGrant
- Configure TLS passthrough instead of termination
- Add request/response header manipulation
- Implement timeout and retry policies
Related Concepts
- Gateway API: Next-generation Ingress for Kubernetes
- GatewayClass: Defines the controller implementation
- HTTPRoute: HTTP-specific routing rules
- TLS Termination: Decrypting HTTPS at the Gateway
- Service Mesh: Gateway API can integrate with service meshes
- Load Balancing: Gateway handles traffic distribution