September 4, 2020 By Takeyuki Nakajo 6 min read

In this article, we will explain how you can expose an application to the Internet with the Ingress application load balancer (ALB).

There are three options to expose an application if you are using a standard classic Kubernetes cluster (the NodePort is the only option if you are using a free Kubernetes cluster):

Ingress is a Kubernetes service that balances network traffic workloads in your cluster by forwarding public or private requests to your apps. You can use Ingress to expose multiple app services to the public or to a private network by using a unique public or private route:

Prerequisites

Deploying an application

Deploy a sample Hello World app into a Kubernetes pod in your project.

1. Create a new namespace for your project:

$ kubectl create namespace project-a

2. Set the namespace preference so that you don’t need to specify the namespace for all subsequent kubectl commands in that context:

$ kubectl config set-context --current --namespace=project-a

3. Clone the source code for the sample Hello World app:

$ git clone https://github.com/IBM/container-service-getting-started-wt.git
$ cd "container-service-getting-started-wt/Lab 1"

4. Build a Docker image (Note: You need to have the Docker image running locally):

$ ibmcloud cr build -t us.icr.io/tn_namespace/hello-world:1 .

5. To pull images into a non-default Kubernetes namespace in IBM Cloud Kubernetes Service, you must add a new secret in your new namespace. You can copy the existing default secret into the new namespace. See more details here:

$ kubectl get secret all-icr-io -n default -o yaml | sed 's/default/project-a/g' | kubectl create -n project-a -f -

6. Verify that the secret copied:

$ kubectl get secrets
NAME                  TYPE                                  DATA   AGE
project-a-us-icr-io   kubernetes.io/dockerconfigjson        1      10s

7. Create a deployment to deploy the app:

$ kubectl create deployment hello-world-deployment --image=us.icr.io/tn_namespace/hello-world:1
deployment.apps/hello-world-deployment created

8. Verify the deployment—hello-world-deployment—and the app are running on a pod:

$ kubectl get deployment hello-world-deployment
NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
hello-world-deployment   1/1     1            1           1m5s
$ kubectl get pods
NAME                                     READY   STATUS    RESTARTS   AGE
hello-world-deployment-56999cc7cf-fk6ph   1/1     Running   0          1m50s

9. Scale up the number of replicas. Running three instances makes the app more highly available than just one instance:

$ kubectl scale deployment/hello-world-deployment --replicas=3
deployment.apps/hello-world-deployment scaled
$ kubectl get deployment hello-world-deployment
NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
hello-world-deployment   3/3     3            3           2m40s

Creating an Ingress service

The following diagram shows how Ingress directs communication from the Internet to an app in a classic single-zone cluster.

The ALB checks if a routing rule for the myapp path in the cluster exists. If a matching rule is found, the request is proxied according to the rules that you defined in the Ingress resource to the pod where the app is deployed. The source IP address of the package is changed to the IP address of the worker node where the app pod runs. If multiple app instances are deployed in the cluster, the ALB load balances the requests between the app pods.

See more details in the doc: How does a request get to my app in a classic cluster?

Use the following steps to create an Ingress application load balancer (ALB) service to expose your app.

1. Create a ClusterIP service

Create a Kubernetes ClusterIP service for the app deployment that you want to expose. Your app can be exposed by a Kubernetes service to be included in the Ingress load balancing:

$ kubectl expose deploy hello-world-deployment --name hello-world-svc --port 8080
service/my-app-svc exposed
$ kubectl get services
NAME              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
hello-world-svc   ClusterIP   172.21.82.31   <none>        8080/TCP   7s
$ kubectl describe service hello-world-svc
Name:              hello-world-svc
Namespace:         project-a
Labels:            app=hello-world-deployment
Annotations:       <none>
Selector:          app=hello-world-deployment
Type:              ClusterIP
IP:                172.21.82.31
Port:              <unset>  8080/TCP
TargetPort:        8080/TCP
Endpoints:         172.30.233.41:8080,172.30.233.42:8080,172.30.233.43:8080
Session Affinity:  None
Events:            <none>

Make sure to include a label to your deployment in the metadata section of your configuration file—such as app=hello-world-deployment. This label is needed to identify all pods where your app runs so that the pods can be included in the Ingress load balancing.

2. Select an app domain

You can choose the domain through which your apps will be accessible. You can use the IBM-provided domain, such as mycluster-<hash>-0000.us-south.containers.appdomain.cloud/myapp, to access your app:

$ ibmcloud ks cluster get --cluster tncluster  | grep Ingress
Ingress Subdomain:              tncluster-5be51ad3139a99d89cdf8f97c78ef71c-0000.us-south.containers.appdomain.cloud   
Ingress Secret:                 tncluster-5be51ad3139a99d89cdf8f97c78ef71c-0000   

3. Select TLS termination

You can choose whether to use TLS termination. The ALB load balances HTTP network traffic to the apps in your cluster. To also load balance incoming HTTPS connections, you can configure the ALB to decrypt the network traffic and forward the decrypted request to the apps that are exposed in your cluster. If you use the IBM-provided Ingress subdomain, you can use the IBM-provided TLS certificate, which is stored as a Kubernetes secret in the default namespace. 

4. Create the Ingress resource

Create an Ingress configuration file that is named—for example, myingress.yaml—to define the routing rules that the ALB uses to route traffic to your app service.

Ensure that the resource deploys into the same namespace as the app services that you specified in the resource. If your apps are exposed by services in different namespaces in one cluster, add a wildcard subdomain to the beginning of the domain, such as subdomain1.custom_domain.net or subdomain1.mycluster-<hash>-0000.us-south.containers.appdomain.cloud. Use a unique subdomain for each Ingress resource that you create in the cluster.

See more details to add the Ingress annotations here.

Example configuration for the Ingress resource:

$ cat myingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myingress
  annotations:
    kubernetes.io/ingress.class: "public-iks-k8s-nginx"
spec:
  rules:
  - host: subdomain1.mycluster-fra04-b3-157851-5be51ad3139a99d89cdf8f97c78ef71c-0000.eu-de.containers.appdomain.cloud
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: hello-world-svc
            port:
              number: 8080

Apply the Ingress configuration to create:

$ kubectl apply -f myingress.yaml
ingress.networking.k8s.io/myingress configured

Verify that the Ingress resource was created successfully. If messages in the events describe an error in your resource configuration, change the values in your resource file and reapply the file for the resource:

$ kubectl describe ingress myingress
...
Rules:
  Host                                                                                            Path  Backends
  ----                                                                                            ----  --------
  subdomain1.tncluster-5be51ad3139a99d89cdf8f97c78ef71c-0000.us-south.containers.appdomain.cloud  
                                                                                                  /   hello-world-svc:8080 (172.30.233.41:8080,172.30.233.42:8080,172.30.233.43:8080)
...
Events:
  Type    Reason   Age   From                                                 Message
  ----    ------   ----  ----                                                 -------
  Normal  Success  51s   public-crbsps9s2d08ovk65207gg-alb1-56c8bc6f8d-7bkpt  Successfully applied ingress resource.

Access your app with the Ingress subdomain and the path—https://<ingress_subdomain>/<app_path>:

$ curl subdomain1.tncluster-5be51ad3139a99d89cdf8f97c78ef71c-0000.us-south.containers.appdomain.cloud:80
Hello world from hello-world-deployment-56999cc7cf-vsr2q! Your app is up and running in a cluster!

5. Set up a custom domain

If you choose a custom domain, you can set it up through the following steps:

  • Register a custom domain by working with your Domain Name Service (DNS) provider or by using IBM Cloud DNS.
  • Define an alias for your custom domain by specifying the IBM-provided subdomain as a Canonical Name record (CNAME).
  • Change the host name with your custom domain in the Ingress configuration.

Example configuration for the Ingress resource:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: myingress
spec:
   tls:
  - hosts:
    - <your custom domain>
    secretName: <secret for your customer domain>
  rules:
  - host: <your custom domain>


apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myingress
  annotations:
    kubernetes.io/ingress.class: "public-iks-k8s-nginx"
spec:
   tls:
  - hosts:
    - <your custom domain>
    secretName: <secret for your customer domain>
  rules:
  - host: <your custom domain>
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: hello-world-svc
            port:
              number: 8080

You can access with your customer domain:

$ curl https://<your custom domain>/<app_path>
Hello world from hello-world-deployment-56999cc7cf-vsr2q! Your app is up and running in a cluster!

Cleanup

1. Check all your resources that have the app=hello-world-deployment label:

$ kubectl get all -l app=hello-world-deployment -n project-a

2. Then, you can delete all the resources with the label:

$ kubectl delete all -l app=hello-world-deployment-n project-a
  pod "hello-world-deployment-56999cc7cf-vsr2q" deleted
  service "hello-world-service" deleted
  deployment.apps "hello-world-deployment" deleted

3. Delete the Ingress resource and the namespace:

$ kubectl delete ingress myingress
ingress.extensions "myingress" deleted
$ kubectl delete namespace project-a
namespace "project-a" deleted

Summary

I hope that you now understand how you can expose an application to the outside of your Kubernetes cluster with the Ingress application load balancer (ALB) so that users can access the app from the Internet.

For more more information, you can see the following:

Was this article helpful?
YesNo

More from Cloud

Bigger isn’t always better: How hybrid AI pattern enables smaller language models

5 min read - As large language models (LLMs) have entered the common vernacular, people have discovered how to use apps that access them. Modern AI tools can generate, create, summarize, translate, classify and even converse. Tools in the generative AI domain allow us to generate responses to prompts after learning from existing artifacts. One area that has not seen much innovation is at the far edge and on constrained devices. We see some versions of AI apps running locally on mobile devices with…

IBM Tech Now: April 8, 2024

< 1 min read - ​Welcome IBM Tech Now, our video web series featuring the latest and greatest news and announcements in the world of technology. Make sure you subscribe to our YouTube channel to be notified every time a new IBM Tech Now video is published. IBM Tech Now: Episode 96 On this episode, we're covering the following topics: IBM Cloud Logs A collaboration with IBM watsonx.ai and Anaconda IBM offerings in the G2 Spring Reports Stay plugged in You can check out the…

The advantages and disadvantages of private cloud 

6 min read - The popularity of private cloud is growing, primarily driven by the need for greater data security. Across industries like education, retail and government, organizations are choosing private cloud settings to conduct business use cases involving workloads with sensitive information and to comply with data privacy and compliance needs. In a report from Technavio (link resides outside ibm.com), the private cloud services market size is estimated to grow at a CAGR of 26.71% between 2023 and 2028, and it is forecast to increase by…

IBM Newsletters

Get our newsletters and topic updates that deliver the latest thought leadership and insights on emerging trends.
Subscribe now More newsletters