Deploying an application on Kubernetes

With this practical guide, deploy your first application on Kubernetes: from creating a Deployment and Service to exposing the application externally with NodePort and Ingress.

6 min Updated 24 Sep 2026

Kubernetes Deployment: From Zero to Your First Live Application

If you have ever run your application on a virtual server or VPS, you know how exhausting managing scale, updates, and errors can be. Kubernetes changes this equation: you describe what your application should look like, and Kubernetes takes responsibility for bringing the system to that state and keeping it there. But the starting point is unclear for many developers: where exactly should you begin? In this article, we outline a practical, no-frills path for the Kubernetes deployment of your first application — from creating a Deployment to exposing the service outside the cluster.

We assume you have a Kubernetes cluster available (locally with Minikube, or a cloud cluster) and that the kubectl tool is installed on your system and connected to the cluster. If you don't have a cluster, minikube start is the fastest way to begin. All examples in this article use a simple Nginx application so you can stay focused on the core concepts.

Step One: Creating a Deployment — The Heart of Kubernetes Deployment

In Kubernetes, you don't run containers directly; instead, you define a Deployment that describes the desired state of your application. The Deployment automatically creates a ReplicaSet that keeps a specified number of Pods alive. If a Pod dies, the ReplicaSet immediately replaces it with a new one.

Create a file named deployment.yaml:

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:1.27
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "200m"

Key points in this file:

  • replicas: 3 — meaning three copies of the application should always be running.
  • selector.matchLabels — determines which Pods the Deployment manages. This label must match the Pod template label.
  • resources — setting minimum and maximum resources helps Kubernetes distribute Pods across nodes more intelligently. The value 100m means 0.1 CPU core.

To apply this file to the cluster:

kubectl apply -f deployment.yaml

Check the status:

kubectl get deployments
kubectl get pods

After a few seconds, you should see three Pods with the Running status. If you deliberately delete one of the Pods (kubectl delete pod <pod-name>), Kubernetes will immediately create a new Pod — this is the power of self-healing.

Common Mistake: Forgetting the Selector

One of the most common errors in Kubernetes deployment is a mismatch between selector.matchLabels and the Pod template labels. If these don't match, the Deployment is created but doesn't manage any Pods. Always check errors with kubectl describe deployment nginx-deployment.

Step Two: Creating a Service — The Gateway to Pods

Pods in Kubernetes are ephemeral, and their IPs change each time they are created. To give your application a stable address, you need a Service. A Service is an abstraction layer that distributes traffic among a set of Pods.

Create the service.yaml file:

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

In this definition:

  • selector — specifies which Pods the Service should send traffic to (here, all Pods with the app: nginx label).
  • port — the port on which the Service is available.
  • targetPort — the port the container actually listens on.
  • type: ClusterIP — meaning the Service is only accessible within the cluster. This is the default and most secure option.

Apply it:

kubectl apply -f service.yaml
kubectl get services

Now, from within the cluster, you can access the application at the address nginx-service. For a quick test, use a temporary Pod:

kubectl run test-pod --image=busybox --rm -it -- wget -qO- http://nginx-service

If you receive an HTML response from Nginx, the Service is working correctly.

Common Mistake: Incorrect targetPort

If your application listens on port 8080 but you set targetPort to 80, the Service will be created but you won't get any response. Always set targetPort to the actual container port, not a preferred one.

Step Three: Exposing the Application Outside the Cluster

So far, the application is only accessible within the cluster. To allow external users to connect, you have three main options:

Option 1: NodePort — Quick for Testing

By changing the Service type to NodePort, Kubernetes opens a port in the range 30000–32767 on every node and routes traffic on that port to the Service.

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

After applying, it is accessible externally at http://<node-IP>:30080. This method is great for quick testing but not suitable for production, as ports are limited and hard to manage.

Option 2: LoadBalancer — Suitable for the Cloud

In cloud clusters (such as GKE, EKS, or AKS), changing the type to LoadBalancer causes the cloud provider to create a real Load Balancer with a public IP:

spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 80

After a few minutes, kubectl get svc will show an EXTERNAL-IP that you can access directly from your browser. This method is suitable for simple public services.

Option 3: Ingress — Intelligent Routing

If you have multiple services and want to route traffic based on domain name or path, Ingress is the best choice. Ingress is a cluster-level entry layer that manages HTTP routing rules. First, you need to install an Ingress Controller (such as the NGINX Ingress Controller or Traefik). Then define an Ingress resource:

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

With this definition, all incoming traffic to app.example.com is routed to the nginx-service. Ingress also handles SSL/TLS management by defining tls in the spec.

Common Mistake: Forgetting the Ingress Controller

Many beginners define the Ingress resource but forget to install the Ingress Controller. Without a Controller, the Ingress resource has no effect. Before defining Ingress, make sure to install and run the Controller.

Step Four: Updating and Rolling Back

One of the main advantages of Kubernetes deployment is rolling updates without downtime. To update the Nginx version, simply change the image:

kubectl set image deployment/nginx-deployment nginx=nginx:1.28

Kubernetes gradually replaces old Pods with new ones. If something goes wrong, you can roll back to the previous version with the following command:

kubectl rollout undo deployment/nginx-deployment

You can also view the version history:

kubectl rollout history deployment/nginx-deployment

Summary and Next Steps

In this article, we walked through the complete cycle of Kubernetes deployment for a simple application: creating a Deployment to manage Pods, defining a Service for stable access, and exposing it externally using three methods — NodePort, LoadBalancer, and Ingress. This is the core foundation; from here, you can move on to more advanced topics such as ConfigMap and Secret for configuration management, PersistentVolume for durable data, and HorizontalPodAutoscaler for automatic scaling.

If you're looking for infrastructure where running Kubernetes is smooth and worry-free, ServerNet's cloud services can provide a suitable platform for hosting your cluster. But the most important step is hands-on practice: build a test cluster right now and run your first Deployment. After a few repetitions, this process will become second nature to you.

Was this page helpful?