Expose Kubernetes Applications

KubernetesKubernetesBeginner
Practice Now

Introduction

In this lab, you will learn how to expose Kubernetes applications using various techniques, including creating internal and external services, working with labels, and exploring the basics of Ingress. You will start by setting up a local Kubernetes cluster using Minikube, then deploy a sample NGINX application and expose it both internally and externally. You will also explore the use of labels to organize and select resources, and finally, you will learn about Ingress and see a simple Ingress YAML example.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL kubernetes(("`Kubernetes`")) -.-> kubernetes/TroubleshootingandDebuggingCommandsGroup(["`Troubleshooting and Debugging Commands`"]) kubernetes(("`Kubernetes`")) -.-> kubernetes/BasicCommandsGroup(["`Basic Commands`"]) kubernetes(("`Kubernetes`")) -.-> kubernetes/AdvancedCommandsGroup(["`Advanced Commands`"]) kubernetes(("`Kubernetes`")) -.-> kubernetes/ConfigurationandVersioningGroup(["`Configuration and Versioning`"]) kubernetes(("`Kubernetes`")) -.-> kubernetes/BasicsGroup(["`Basics`"]) kubernetes/TroubleshootingandDebuggingCommandsGroup -.-> kubernetes/describe("`Describe`") kubernetes/BasicCommandsGroup -.-> kubernetes/create("`Create`") kubernetes/BasicCommandsGroup -.-> kubernetes/get("`Get`") kubernetes/BasicCommandsGroup -.-> kubernetes/delete("`Delete`") kubernetes/AdvancedCommandsGroup -.-> kubernetes/apply("`Apply`") kubernetes/ConfigurationandVersioningGroup -.-> kubernetes/version("`Version`") kubernetes/ConfigurationandVersioningGroup -.-> kubernetes/label("`Label`") kubernetes/BasicsGroup -.-> kubernetes/initialization("`Initialization`") subgraph Lab Skills kubernetes/describe -.-> lab-434647{{"`Expose Kubernetes Applications`"}} kubernetes/create -.-> lab-434647{{"`Expose Kubernetes Applications`"}} kubernetes/get -.-> lab-434647{{"`Expose Kubernetes Applications`"}} kubernetes/delete -.-> lab-434647{{"`Expose Kubernetes Applications`"}} kubernetes/apply -.-> lab-434647{{"`Expose Kubernetes Applications`"}} kubernetes/version -.-> lab-434647{{"`Expose Kubernetes Applications`"}} kubernetes/label -.-> lab-434647{{"`Expose Kubernetes Applications`"}} kubernetes/initialization -.-> lab-434647{{"`Expose Kubernetes Applications`"}} end

Start the Kubernetes Cluster

In this step, you'll learn how to start and verify a local Kubernetes cluster using Minikube. This is an essential first step for developing and testing Kubernetes applications on your local machine.

First, start the Minikube cluster:

minikube start

Example output:

😄  minikube v1.29.0 on Ubuntu 22.04
âœĻ  Automatically selected the docker driver
📌  Using Docker driver with root permissions
ðŸ”Ĩ  Creating kubernetes in kubernetes cluster
🔄  Restarting existing kubernetes cluster
ðŸģ  Preparing Kubernetes v1.26.1 on Docker 20.10.23 ...
🚀  Launching Kubernetes ...
🌟  Enabling addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace

Verify the cluster status using multiple commands:

minikube status
kubectl get nodes

Example output for minikube status:

minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

Example output for minikube kubectl -- get nodes:

NAME       STATUS   ROLES           AGE   VERSION
minikube   Ready    control-plane   1m    v1.26.1

These commands confirm that:

  1. Minikube is successfully running
  2. A local Kubernetes cluster has been created
  3. The cluster is ready to use
  4. You have a single-node cluster with control plane capabilities

Deploy a Sample Application

In this step, you'll learn how to create and deploy a Kubernetes application using a YAML manifest. We'll create a simple NGINX web server deployment to demonstrate the process of defining and applying Kubernetes resources.

First, create a directory for your Kubernetes manifests:

mkdir -p ~/project/k8s-manifests
cd ~/project/k8s-manifests

Create a YAML file for an NGINX deployment:

nano nginx-deployment.yaml

Add the following deployment manifest:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80

Save the file (Ctrl+X, then Y, then Enter).

Apply the deployment to the Kubernetes cluster:

kubectl apply -f nginx-deployment.yaml

Example output:

deployment.apps/nginx-deployment created

Verify the deployment and pods:

kubectl get deployments
kubectl get pods

Example output for kubectl get deployments:

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           1m

Example output for kubectl get pods:

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-xxx-yyy            1/1     Running   0          1m
nginx-deployment-xxx-zzz            1/1     Running   0          1m
nginx-deployment-xxx-www            1/1     Running   0          1m

Wait for the pods to be in the "Running" state before proceeding.

Let's break down the YAML manifest:

  • apiVersion: Specifies the Kubernetes API version
  • kind: Defines the resource type (Deployment)
  • metadata: Provides name and labels for the deployment
  • spec.replicas: Sets the number of pod replicas
  • selector: Helps the deployment manage the correct pods
  • template: Defines the pod specification
  • containers: Specifies the container image and port

This deployment creates three identical NGINX pods, demonstrating how Kubernetes manages containerized applications.

Create a Service via YAML to Expose the Application Internally or Externally

In this step, you'll learn how to create Kubernetes Services to expose your NGINX deployment internally and externally. We'll demonstrate two common service types: ClusterIP and NodePort.

First, navigate to your project directory:

cd ~/project/k8s-manifests

Create a ClusterIP service YAML file:

nano nginx-clusterip-service.yaml

Add the following service manifest:

apiVersion: v1
kind: Service
metadata:
  name: nginx-clusterip-service
spec:
  selector:
    app: nginx
  type: ClusterIP
  ports:
    - port: 80
      targetPort: 80

Now, create a NodePort service YAML file:

nano nginx-nodeport-service.yaml

Add the following service manifest:

apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport-service
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080

Apply both service configurations:

kubectl apply -f nginx-clusterip-service.yaml
kubectl apply -f nginx-nodeport-service.yaml

Example output:

service/nginx-clusterip-service created
service/nginx-nodeport-service created

Verify the services:

kubectl get services

Example output:

NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes                  ClusterIP   10.96.0.1        <none>        443/TCP        30m
nginx-clusterip-service     ClusterIP   10.104.xxx.xxx   <none>        80/TCP         1m
nginx-nodeport-service      NodePort    10.108.yyy.yyy   <none>        80:30080/TCP   1m

To access the NodePort service, get the Minikube IP:

minikube ip

Example output:

192.168.49.2

Key differences between service types:

  • ClusterIP: Internal cluster access only
  • NodePort: Exposes service on a static port on each node's IP
  • NodePort range: 30000-32767

Verify Service Configuration

In this step, you'll learn how to use kubectl describe service to inspect the detailed configuration of Kubernetes services and understand their network properties.

First, ensure you're in the project directory:

cd ~/project/k8s-manifests

Describe the ClusterIP service in detail:

kubectl describe service nginx-clusterip-service

Example output:

Name:              nginx-clusterip-service
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.104.xxx.xxx
IPs:               10.104.xxx.xxx
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.0.7:80,10.244.0.8:80,10.244.0.9:80
Session Affinity:  None
Events:            <none>

Now, describe the NodePort service:

kubectl describe service nginx-nodeport-service

Example output:

Name:                     nginx-nodeport-service
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=nginx
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.108.yyy.yyy
IPs:                      10.108.yyy.yyy
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30080/TCP
Endpoints:                10.244.0.7:80,10.244.0.8:80,10.244.0.9:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

Inspect the service endpoints to verify network connectivity:

kubectl get endpoints

Example output:

NAME                        ENDPOINTS                               AGE
kubernetes                  192.168.49.2:8443                       45m
nginx-clusterip-service     10.244.0.7:80,10.244.0.8:80,10.244.0.9:80   15m
nginx-nodeport-service      10.244.0.7:80,10.244.0.8:80,10.244.0.9:80   15m

Key information to understand from the service description:

  • Selector: Shows which pods are part of the service
  • IP: Cluster-internal IP address of the service
  • Endpoints: List of pod IP addresses and ports serving the service
  • Port and TargetPort: Define how traffic is routed
  • NodePort: External port for NodePort service type

Use Labels to Organize and Select Resources

In this step, you'll learn how to use labels in Kubernetes to organize and select resources efficiently. Labels are key-value pairs that help you manage and organize Kubernetes objects.

First, verify the current labels on your pods:

kubectl get pods --show-labels

Example output:

NAME                                READY   STATUS    RESTARTS   AGE   LABELS
nginx-deployment-xxx-yyy            1/1     Running   0          30m   app=nginx,pod-template-hash=xxx
nginx-deployment-xxx-zzz            1/1     Running   0          30m   app=nginx,pod-template-hash=yyy
nginx-deployment-xxx-www            1/1     Running   0          30m   app=nginx,pod-template-hash=zzz

Select pods using specific labels:

kubectl get pods -l app=nginx

Example output:

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-xxx-yyy            1/1     Running   0          30m
nginx-deployment-xxx-zzz            1/1     Running   0          30m
nginx-deployment-xxx-www            1/1     Running   0          30m

Let's add a custom label to one of the pods:

kubectl label pods nginx-deployment-xxx-yyy environment=development

Replace nginx-deployment-xxx-yyy with the name of one of your pods.

Example output:

pod/nginx-deployment-xxx-yyy labeled

Now, select pods with multiple label selectors:

kubectl get pods -l app=nginx,environment=development

Example output:

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-xxx-yyy            1/1     Running   0          30m

Remove a label from a pod:

kubectl label pods nginx-deployment-xxx-yyy environment-

Example output:

pod/nginx-deployment-xxx-yyy unlabeled

Demonstrate label selection in services:

kubectl describe service nginx-clusterip-service

Look for the "Selector" section, which shows how services use labels to identify pods.

Key points about labels:

  • Labels are key-value pairs attached to Kubernetes objects
  • Used for organizing, selecting, and filtering resources
  • Can be added, modified, or removed dynamically
  • Services and deployments use labels to manage related pods

Delete and Manage Services

In this step, you'll learn how to delete and manage Kubernetes services using kubectl commands. Understanding service management is crucial for maintaining and cleaning up your Kubernetes resources.

First, list the current services:

kubectl get services

Example output:

NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes                  ClusterIP   10.96.0.1        <none>        443/TCP        1h
nginx-clusterip-service     ClusterIP   10.104.xxx.xxx   <none>        80/TCP         45m
nginx-nodeport-service      NodePort    10.108.yyy.yyy   <none>        80:30080/TCP   45m

Delete a specific service using kubectl delete:

kubectl delete service nginx-clusterip-service

Example output:

service "nginx-clusterip-service" deleted

Verify the service deletion:

kubectl get services

Example output:

NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes                  ClusterIP   10.96.0.1        <none>        443/TCP        1h
nginx-nodeport-service      NodePort    10.108.yyy.yyy   <none>        80:30080/TCP   45m

Delete multiple services at once:

kubectl delete service nginx-nodeport-service

Example output:

service "nginx-nodeport-service" deleted

Verify all services are removed (except the default kubernetes service):

kubectl get services

Example output:

NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   1h

Alternative deletion methods:

## Delete services using YAML file
kubectl delete -f nginx-nodeport-service.yaml

## Delete services by label
kubectl delete service -l app=nginx

Key points about service deletion:

  • Deleting a service removes the network endpoint
  • Pods are not deleted when a service is removed
  • Default kubernetes service cannot be deleted
  • You can delete services using name, YAML file, or labels

Introduce Ingress Basics and Show a Simple Ingress YAML Example

In this step, you'll learn about Kubernetes Ingress, a powerful way to manage external access to services in a Kubernetes cluster. First, enable the Ingress addon in Minikube:

minikube addons enable ingress

Example output:

ðŸ’Ą  ingress is an addon maintained by Kubernetes. For any concerns contact minikube on GitHub.
🔉  ingress was successfully enabled

Create a deployment for two sample applications:

kubectl create deployment web1 --image=nginx:alpine
kubectl create deployment web2 --image=httpd:alpine

Expose these deployments as services:

kubectl expose deployment web1 --port=80 --type=ClusterIP --name=web1-service
kubectl expose deployment web2 --port=80 --type=ClusterIP --name=web2-service

Create an Ingress YAML file:

nano ingress-example.yaml

Add the following Ingress configuration:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - http:
        paths:
          - path: /web1
            pathType: Prefix
            backend:
              service:
                name: web1-service
                port:
                  number: 80
          - path: /web2
            pathType: Prefix
            backend:
              service:
                name: web2-service
                port:
                  number: 80

Apply the Ingress configuration:

kubectl apply -f ingress-example.yaml

Verify the Ingress resource:

kubectl get ingress

Example output:

NAME              CLASS   HOSTS   ADDRESS        PORTS   AGE
example-ingress   nginx   *       192.168.49.2   80      1m

Check Ingress details:

kubectl describe ingress example-ingress

Example output will show routing rules and backend services.

Next, you can use the curl command to verify if the exposed service is working correctly. Assuming your Ingress resource is configured correctly and the Minikube IP is 192.168.49.2, you can run the following command:

curl 192.168.49.2

If the service is working correctly, you should see the appropriate response output.

Key Ingress concepts:

  • Manages external access to services
  • Provides HTTP/HTTPS routing
  • Allows path-based routing
  • Can implement SSL termination
  • More flexible than NodePort or LoadBalancer services

Summary

In this lab, you learned how to start and verify a local Kubernetes cluster using Minikube, which is essential for developing and testing Kubernetes applications on your local machine. You then created and deployed a simple NGINX web server deployment using a YAML manifest, demonstrating the process of defining and applying Kubernetes resources. Additionally, you learned how to create a Kubernetes service to expose your application internally or externally, and how to use labels to organize and select resources. Finally, you explored the basics of Kubernetes Ingress and saw a simple Ingress YAML example.

Other Kubernetes Tutorials you may like