Service exposure with Ingress
Ingress in Kubernetes allows external traffic to reach your applications running within the cluster. This guide will demonstrate how to configure ingress to expose your applications, assign a DNS record for easier discovery, and secure communications using TLS.
Install the Ingress Controller
We’ll use the NGINX Ingress Controller and deploy it using Helm, a package manager for Kubernetes. If Helm is not yet installed on your system, follow the instructions in the official documentation.
You can install the NGINX Ingress controller using the following command:
helm upgrade --install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--namespace ingress-nginx --create-namespace
This command deploys the controller in the ingress-nginx
namespace, creating the namespace if it doesn’t exist.
Once the deployment is complete, verify that the service ingress-nginx-controller
has an external IP address assigned:
kubectl get service --namespace ingress-nginx
You should see something like this:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.248.35.52 154.41.192.39 80:30253/TCP,443:32378/TCP 47s
ingress-nginx-controller-admission ClusterIP 10.248.60.91 <none> 443/TCP 47s
By default, without any further configuration, accessing the ingress controller via the external IP address will yield a 404 page:
export EXTERNAL_IP=$(kubectl get service ingress-nginx-controller \
--namespace ingress-nginx \
--output jsonpath='{.status.loadBalancer.ingress[0].ip}')
Make a request to the ingress controller.
curl http://${EXTERNAL_IP}
Deploy a Sample Application
Begin by creating a deployment that listens on port 80:
kubectl create deployment demo --image nginx --port 80
Then, create a service object that exposes the deployment :
kubectl expose deployment demo
Next, configure ingress for external access to the application:
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
labels:
app: demo
name: demo
spec:
ingressClassName: nginx
rules:
- http:
paths:
- backend:
service:
name: demo
port:
number: 80
path: /
pathType: Prefix
EOF
Now, accessing the ingress controller via the external IP address will provide a default NGINX welcome page:
export EXTERNAL_IP=$(kubectl get service ingress-nginx-controller \
--namespace ingress-nginx \
--output jsonpath='{.status.loadBalancer.ingress[0].ip}')
Make a request to the ingress controller.
curl http://${EXTERNAL_IP}
Set Up DNS
We’ll be utilizing the cluster domain provided by metalstack.cloud. To retrieve it, execute the following command:
kubectl config view --minify --output jsonpath="{.clusters[*].cluster.server}"
The output should resemble:
https://api.demo.0123456789.k8s.metalstackcloud.io
We’re interested in the part following https://api.:
export CLUSTER_DOMAIN=$(kubectl config view --minify --output jsonpath='{.clusters[*].cluster.server}' | cut -d'.' -f2-)
Next, configure the DNS name:
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
dns.gardener.cloud/class: garden
dns.gardener.cloud/dnsnames: demo.${CLUSTER_DOMAIN}
dns.gardener.cloud/ttl: "180"
labels:
app: demo
name: demo
spec:
ingressClassName: nginx
rules:
- host: demo.${CLUSTER_DOMAIN}
http:
paths:
- backend:
service:
name: demo
port:
number: 80
path: /
pathType: Prefix
EOF
If successful, the previously displayed page should be accessible at:
curl http://demo.${CLUSTER_DOMAIN}
Configuring TLS
To secure your DNS name with a TLS certificate, we can instruct the platform to generate one for us using the annotation cert.gardener.cloud/purpose: managed
. This process creates a secret, demo-tls-secret
, which contains the certificate:
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert.gardener.cloud/purpose: managed
dns.gardener.cloud/class: garden
dns.gardener.cloud/dnsnames: demo.${CLUSTER_DOMAIN}
dns.gardener.cloud/ttl: "180"
labels:
app: demo
name: demo
spec:
ingressClassName: nginx
rules:
- host: demo.${CLUSTER_DOMAIN}
http:
paths:
- backend:
service:
name: demo
port:
number: 80
path: /
pathType: Prefix
tls:
- hosts:
- demo.${CLUSTER_DOMAIN}
secretName: demo-tls-secret
EOF
After setting up TLS, you should be able to access the page:
curl http://demo.${CLUSTER_DOMAIN}