metalstack cloud

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}

Awesome work!

You've completed this developer guide. We have many more, so feel free to explore our other guides! Should you have any questions about our products or need help with metalstack.cloud, please reach out to us anytime.