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

Private cloud use cases: 6 ways private cloud brings value to enterprise business

7 min read - As cloud computing continues to transform the enterprise workplace, private cloud infrastructure is evolving in lockstep, helping organizations in industries like healthcare, government and finance customize control over their data to meet compliance, privacy, security and other business needs.  According to a report from Future Market Insights (link resides outside ibm.com), the global private cloud services market is forecast to grow to USD 405.30 billion by 2033, up from USD 92.64 billion in 2023.  What is a private cloud? A private cloud is…

Hyperscale vs. colocation: Go big or go rent?

9 min read - Here’s the situation: You’re the CIO or similarly empowered representative of an organization. Different voices within your business are calling attention to the awesome scalability and power of hyperscale computing, which you’ve also noticed with increasing interest. Now the word comes down from on high that you’ve been tasked with designing and implementing your company’s hyperscale computing solution—whatever that should be. Your organization already has an ambitious agenda in mind for whatever IT infrastructure you wind up choosing. The company…

IBM Tech Now: March 25, 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 95 On this episode, we're covering the IBM X-Force Threat Intelligence Index 2024: IBM X-Force Cyber Range Combating deepfakes Stay plugged in You can check out the IBM Blog Announcements for a full rundown…

IBM Newsletters

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