Kubernetes 101: Deploy Your First App on a Cluster

Why Kubernetes Matters in 2026

Kubernetes has become the de facto standard for container orchestration. Whether you’re running a startup or managing enterprise infrastructure, understanding Kubernetes is no longer optional for backend and DevOps engineers. In this guide, we’ll go from zero to deploying a live application on a Kubernetes cluster, covering every core concept along the way.

By the end of this tutorial, you’ll understand pods, services, deployments, and how to write YAML manifests that define your application’s desired state. We’ll use a real Node.js application as our example, but the concepts apply to any containerized workload.

Setting Up Your Environment

Before we deploy anything, you need a Kubernetes cluster and the kubectl command-line tool. For local development, Minikube or Kind (Kubernetes in Docker) are the best options.

ADVERTISEMENT
# Install kubectl on Linux/macOS
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/

# Install Minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube

# Start a local cluster
minikube start --driver=docker

# Verify the cluster is running
kubectl cluster-info
kubectl get nodes

You should see your Minikube node listed with a Ready status. If you’re using a cloud provider like AWS EKS, GKE, or AKS, follow their documentation to configure kubectl with the appropriate kubeconfig.

Understanding Pods: The Smallest Unit

A Pod is the smallest deployable unit in Kubernetes. It wraps one or more containers that share networking and storage. In practice, most pods run a single container. Let’s create one directly to understand the concept.

# Run a pod directly (for learning purposes only)
kubectl run my-nginx --image=nginx:1.25 --port=80

# Check pod status
kubectl get pods
kubectl describe pod my-nginx

# View logs from the pod
kubectl logs my-nginx

# Execute a command inside the pod
kubectl exec -it my-nginx -- /bin/bash

# Clean up
kubectl delete pod my-nginx

While you can create pods directly, you should never do this in production. Pods are ephemeral. If a pod dies, nothing restarts it. That’s where Deployments come in.

Deployments: Declarative Application Management

A Deployment tells Kubernetes the desired state of your application: which container image to run, how many replicas, and how to handle updates. Kubernetes continuously works to match the actual state to your declared intent.

Here’s a complete Deployment manifest for a Node.js application. Save this as deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: node-app
  labels:
    app: node-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: node-app
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: node-app
    spec:
      containers:
        - name: node-app
          image: node:20-alpine
          command: ["node", "-e", "
            const http = require('http');
            const server = http.createServer((req, res) => {
              res.writeHead(200);
              res.end('Hello from Kubernetes! Pod: ' + process.env.HOSTNAME);
            });
            server.listen(3000);
          "]
          ports:
            - containerPort: 3000
          resources:
            requests:
              memory: "64Mi"
              cpu: "50m"
            limits:
              memory: "128Mi"
              cpu: "100m"
          readinessProbe:
            httpGet:
              path: /
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /
              port: 3000
            initialDelaySeconds: 15
            periodSeconds: 20

Apply it and watch Kubernetes bring up your replicas:

# Apply the deployment
kubectl apply -f deployment.yaml

# Watch pods come up in real time
kubectl get pods -w

# Check deployment status
kubectl rollout status deployment/node-app

# Scale up or down
kubectl scale deployment/node-app --replicas=5

# View deployment details
kubectl describe deployment node-app

Services: Exposing Your Application

Pods get random IP addresses that change when they restart. A Service provides a stable endpoint for accessing your pods. Save this as service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: node-app-service
spec:
  type: LoadBalancer
  selector:
    app: node-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000
# Apply the service
kubectl apply -f service.yaml

# Get the external IP (or use minikube service)
kubectl get svc node-app-service

# For Minikube, open the service in your browser
minikube service node-app-service

Kubernetes offers three main Service types: ClusterIP (internal only, the default), NodePort (exposes on each node’s IP at a static port), and LoadBalancer (provisions an external load balancer on cloud providers). For production on AWS or GCP, LoadBalancer automatically creates an ELB or Cloud Load Balancer.

ConfigMaps and Secrets

Hardcoding configuration inside container images is a bad practice. Kubernetes provides ConfigMaps for non-sensitive data and Secrets for credentials.

# Create a ConfigMap from literal values
kubectl create configmap app-config \
  --from-literal=NODE_ENV=production \
  --from-literal=LOG_LEVEL=info

# Create a Secret for database credentials
kubectl create secret generic db-creds \
  --from-literal=DB_HOST=postgres.default.svc \
  --from-literal=DB_PASSWORD=supersecret123

# Reference them in your deployment spec under containers:
# envFrom:
#   - configMapRef:
#       name: app-config
#   - secretRef:
#       name: db-creds

Rolling Updates and Rollbacks

One of Kubernetes’ strongest features is zero-downtime deployments. When you update the container image in your Deployment, Kubernetes gradually replaces old pods with new ones.

# Update the image (triggers rolling update)
kubectl set image deployment/node-app node-app=node:22-alpine

# Watch the rollout
kubectl rollout status deployment/node-app

# Something wrong? Roll back instantly
kubectl rollout undo deployment/node-app

# View rollout history
kubectl rollout history deployment/node-app

Essential kubectl Commands to Remember

Here is a quick reference of the commands you’ll use daily:

# Cluster info
kubectl cluster-info
kubectl get nodes

# Workloads
kubectl get pods -o wide
kubectl get deployments
kubectl get replicasets
kubectl top pods              # CPU/memory usage

# Debugging
kubectl describe pod <name>
kubectl logs <pod> -f         # stream logs
kubectl logs <pod> --previous # logs from crashed container
kubectl exec -it <pod> -- sh

# Cleanup
kubectl delete -f deployment.yaml
kubectl delete -f service.yaml

Conclusion

You’ve just deployed a real application on Kubernetes using pods, deployments, services, ConfigMaps, and secrets. The key mental model is declarative: you tell Kubernetes what you want, and it figures out how to make it happen. From here, explore Ingress controllers for HTTP routing, Helm for package management, and namespaces for multi-tenant clusters. Kubernetes has a learning curve, but once these fundamentals click, everything else builds on top of them.

ADVERTISEMENT

Leave a Comment

Your email address will not be published. Required fields are marked with an asterisk.