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:
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
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:
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!
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
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: