A Developer's Guide to Kubernetes Components

Kubernetes is the backbone of modern cloud-native applications. It simplifies deploying, scaling, and managing containerized workloads. But for developers, understanding its core concepts—like Pods, Deployments, and Services—is essential to building scalable and resilient apps. In this guide, you learn about Kubernetes components from a developer’s point of view, complete with real-life use cases and visual diagrams. Understanding Kubernetes Objects Kubernetes uses a declarative object model. Each object’s spec defines the desired state. The status reflects the current state. Common fields are: apiVersion: API version (e.g., v1) kind: Object type (e.g., Pod, Service) metadata: Name, namespace, labels spec: Desired configuration status: System-managed status For certain objects like Secrets and ConfigMaps, data and stringData fields are used to store key-value pairs.​Kubernetes API Server accepts object definitions in a JSON format, most often such definition manifests in a YAML format which is converted by kubectl in a JSON payload and sent to the API Server. Enable Autocompletion (Optional) Autocompletion enhances your CLI experience. For example, in Bash: source

May 7, 2025 - 09:17
 0
A Developer's Guide to Kubernetes Components

Kubernetes is the backbone of modern cloud-native applications. It simplifies deploying, scaling, and managing containerized workloads. But for developers, understanding its core concepts—like Pods, Deployments, and Services—is essential to building scalable and resilient apps.

In this guide, you learn about Kubernetes components from a developer’s point of view, complete with real-life use cases and visual diagrams.

Understanding Kubernetes Objects

Kubernetes uses a declarative object model. Each object’s spec defines the desired state. The status reflects the current state. Common fields are:

  • apiVersion: API version (e.g., v1)
  • kind: Object type (e.g., Pod, Service)
  • metadata: Name, namespace, labels
  • spec: Desired configuration
  • status: System-managed status

For certain objects like Secrets and ConfigMaps, data and stringData fields are used to store key-value pairs.​Kubernetes API Server accepts object definitions in a JSON format, most often such definition manifests in a YAML format which is converted by kubectl in a JSON payload and sent to the API Server.

Enable Autocompletion (Optional)

Autocompletion enhances your CLI experience. For example, in Bash:

source <(minikube completion bash)

Nodes

A node is a physical or virtual machine in a Kubernetes cluster. Each node runs the following:

  • kubelet: Ensures containers in a Pod are running.
  • kube-proxy: Manages network rules for communication.
  • Container runtime: Runs containers (e.g., Docker, containerd).

In a cloud-native e-commerce app, each node could run pods handling different services—payments, inventory, or recommendations.

There are two types of nodes:

  • Control plane nodes: Manage the cluster. They run the API server, scheduler, controller manager, and etcd.
  • Worker nodes: Run application workloads.

image of Kubernetes architecture

Image credits : https://trainingportal.linuxfoundation.org

Namespaces

Namespaces partition cluster resources and isolate workloads. They allow teams to share a cluster without interfering with each other.

Default namespaces:

  • default: For user-defined resources.
  • kube-system: For system-level components.
  • kube-public: Readable by all users.
  • kube-node-lease: Used for node heartbeats.

If multiple users and teams use the same Kubernetes cluster you can partition the cluster into virtual sub-clusters using Namespaces. The names of the resources/objects created inside a Namespace are unique, but not across Namespaces in the cluster.

To list all namespaces:

kubectl get namespaces

To create a namespace:

kubectl create namespace \

Namespaces support:

  • Unique resource names within each namespace
  • Resource isolation by team, project, or environment
  • Resource quotas and limits

A good practice, however, is to create additional Namespaces, as desired, to virtualize the cluster and isolate users, developer teams, apps, or tiers.

Pods

A Pod is the smallest deployable unit in Kubernetes. It can contain one or more containers that share:

  • The same network namespace
  • Storage volumes

Pods are ephemeral and typically managed by higher-level objects like Deployments.

Single- and Multi-Container Pods
Image credits : https://trainingportal.linuxfoundation.org

Example, nginx-pod.yaml:

apiVersion: v1  
kind: Pod  
metadata:  
  name: nginx-pod  
spec:  
  containers:  
  \- name: nginx  
    image: nginx:1.22.1  
    ports:  
    \- containerPort: 80

Apply the manifest:

kubectl apply \-f nginx-pod.yaml

Generate the manifest without creating the Pod:

kubectl run nginx-pod \--image=nginx:1.22.1

Labels and Selectors

Labels are key-value pairs used to organize, select, and manage Kubernetes objects. They are used by controllers and services to organize and manage resources, hence many objects can have the same Label(s).

Label Selectors:

  • Equality-based: Select resources matching specific key-value pairs.​
    • kubectl get pods -l env=dev
  • Set-based: Select resources matching a set of values.​
    • kubectl get pods -l 'env in (dev, qa)'

Labels and Selector diagram

Image credits : https://trainingportal.linuxfoundation.org

Use labels to group resources logically (e.g., by environment, app version).

ReplicaSets

A ReplicaSet ensures a specific number of identical Pods are always running.

Key features:

  • Self-healing: Replaces failed Pods
  • Scalable: Supports manual and automated scaling
  • Uses label selectors to identify Pods

For example, consider a ReplicaSet with a replica count set to 3 for a specific Pod template. Pod-1, Pod-2, and Pod-3 are identical, running the same app container image, being cloned from the same Pod template.

Although the three Pod replicas are said to be identical, they have unique Pod name and IP address. The Pod object ensures that the application can be individually placed on any worker node of the cluster as a result of the scheduling process.

YAML Example

apiVersion: apps/v1  
kind: ReplicaSet  
metadata:  
  name: frontend  
  labels:  
    app: guestbook  
spec:  
  replicas: 3  
  selector:  
    matchLabels:  
      app: guestbook  
  template:  
    metadata:  
      labels:  
        app: guestbook  
    spec:  
      containers:  
      \- name: php-redis  
        image: gcr.io/google\_samples/gb-frontend:v3

To create the ReplicaSet:​

kubectl create \-f redis-rs.yaml

Assume that one of the Pods is forced to unexpectedly terminate (due to insufficient resources, timeout, its hosting node has crashed, etc.), causing the current state to no longer match the desired state.

The ReplicaSet detects that the current state is no longer matching the desired state and triggers a request for an additional Pod to be created, thus ensuring that the current state matches the desired state.

ReplicaSet (Creating a Pod to Match Current State with Desired State)
Image credits : https://trainingportal.linuxfoundation.org

Deployments

Deployments manage the creation, deletion, and updates of Pods. A Deployment automatically creates a ReplicaSet, which then creates a Pod.

There is no need to manage ReplicaSets and Pods separately, the Deployment will manage them on our behalf.

YAML Example

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

** Apply the manifest:**

kubectl apply \-f def-deploy.yaml

When you update the Pod template (for example, a container image), Kubernetes performs a rolling update. Each update creates a new ReplicaSet and marks it as a new revision.

Once the rolling update has completed, the Deployment will show both ReplicaSets A and B, where A is scaled to 0 (zero) Pods, and B is scaled to 3 Pods. This is how the Deployment records its prior state configuration settings, as Revisions.

Deployment (ReplicaSet B Created)
Image credits : https://trainingportal.linuxfoundation.org

When you update the Pod template (for example, a container image), Kubernetes performs a rolling update. Each update creates a new ReplicaSet and marks it as a new revision.

DaemonSets

A DaemonSet ensures a Pod runs on all (or some) Nodes in the cluster. It's ideal for running background agents (e.g., log collectors, monitoring tools).

In contrast, the ReplicaSet and Deployment operators by default have no control over the scheduling and placement of multiple Pod replicas on the same Node.

YAML Example

apiVersion: apps/v1  
kind: DaemonSet  
metadata:  
  name: fluentd-agent  
  labels:  
    k8s-app: fluentd-agent  
spec:  
  selector:  
    matchLabels:  
      k8s-app: fluentd-agent  
  template:  
    metadata:  
      labels:  
        k8s-app: fluentd-agent  
    spec:  
      containers:  
      \- name: fluentd  
        image: quay.io/fluentd\_elasticsearch/fluentd:v4.5.2

Create the DaemonSet:

kubectl create \-f fluentd-ds.yaml

Whenever a Node is added to the cluster, a Pod from a given DaemonSet is automatically placed on it. When any one Node crashes or it is removed from the cluster, the respective DaemonSet operated Pods are garbage collected. If a DaemonSet is deleted, all Pod replicas it created are deleted as well.

Authentication, Authorization, and Admission Control

To manage Kubernetes resources, all API requests go through three control stages:

  • Authentication: Authenticate a user based on credentials provided as part of API requests.
  • Authorization: Authorizes the API requests submitted by the authenticated user.
  • Admission Control: Software modules that validate and/or modify user requests.

Controlling Access to the API
Image credits : https://trainingportal.linuxfoundation.org

Authentication

Authentication verifies the identity of a user or service making a request to the API server. Kubernetes doesn’t store user objects but supports various authentication methods:

Different user types:

  • Normal users: Managed externally (e.g., client certificates, static token files, OIDC).
  • Service accounts: Used by in-cluster processes. Automatically created per namespace and mount credentials into pods. The Service Accounts are tied to a particular Namespace and mount the respective credentials to communicate with the API server as Secrets.

If properly configured, Kubernetes can also support anonymous requests, along with requests from Normal Users and Service Accounts.

Authorization

Authorization determines whether an authenticated user is allowed to perform an action.

More than one module can be configured for one Kubernetes cluster, and each module is checked in sequence. If any authorizer approves or denies a request, then that decision is returned immediately.

Supported Modes

  • Node Authorization: Grants kubelet access to node- and pod-related APIs.
  • Attribute-Based Access Control (ABAC): Policy-based access using user attributes.
    • To enable ABAC mode, you must start the API server with the --authorization-mode=ABAC option, while specifying the authorization policy with --authorization-policy-file=PolicyFile.json.
  • Webhook: Sends authorization requests to an external service.
    • To enable the Webhook authorizer, we need to start the API server with the --authorization-webhook-config-file=SOME_FILENAME option, where SOME_FILENAME is the configuration of the remote authorization service.
  • Role-Based Access Control (RBAC) (Recommended).

Example: Role granting pod read access in lfs158 namespace

apiVersion: rbac.authorization.k8s.io/v1  
kind: Role  
metadata:  
  namespace: lfs158  
  name: pod-reader  
rules:  
\- apiGroups: \[""\]  
  resources: \["pods"\]  
  verbs: \["get", "watch", "list"\]

In Kubernetes, multiple Roles can be attached to subjects like users, service accounts, etc. In RBAC, you can create two kinds of Roles:

  • Role: Grants namespace-scoped permissions.
  • ClusterRole: Grants cluster-wide permissions.

Once the role is created, youcan bind it to users with a RoleBinding object. There are two kinds of RoleBindings:

  • RoleBinding: Binds a Role or ClusterRole to users/groups/service accounts in a namespace.
  • ClusterRoleBinding: Binds a ClusterRole at the cluster scope.

Example: RoleBinding for user bob

apiVersion: rbac.authorization.k8s.io/v1  
kind: RoleBinding  
metadata:  
  name: pod-read-access  
  namespace: lfs158  
subjects:  
\- kind: User  
  name: bob  
  apiGroup: rbac.authorization.k8s.io  
roleRef:  
  kind: Role  
  name: pod-reader  
  apiGroup: rbac.authorization.k8s.io

Admission Control

Admission controllers validate or modify API requests after authentication and authorization but before persistence.

Controller Types

  • Validating: Check request validity.
  • Mutating: Modify request objects.

Examples

  • LimitRanger: Enforces resource limits.
  • ResourceQuota: Enforces resource quotas.
  • DefaultStorageClass: Sets default storage class.
  • AlwaysPullImages: Forces images to always be pulled.

Enable admission controllers with:

\--enable-admission-plugins=NamespaceLifecycle,ResourceQuota,PodSecurity,DefaultStorageClass

Custom controllers can be created as admission webhooks to support dynamic, external validation or mutation.

Accessing Application Pods

Each Pod is assigned a dynamic IP address. If a Pod is restarted, Kubernetes assigns a new IP. If you're connecting directly to a Pod IP, you'll lose access when the Pod is replaced.

A New Pod Is Created After an Old One Terminated Unexpectedly
Image credits : https://trainingportal.linuxfoundation.org

Example: Accessing Pods by IP

For example, a client accesses Pods using their individual IPs. If one Pod fails, a new Pod is created with a different IP. The client must then detect and update its target IPs, which adds complexity and increases overhead.

To overcome this situation, Kubernetes provides a higher-level abstraction called Service, which logically groups Pods and defines a policy to access them. This grouping is achieved via Labels and Selectors.

**apiVersion: apps/v1**  
**kind: Deployment**  
**metadata:**  
  **labels:**  
    **app: frontend**  
  **name: frontend**  
**spec:**  
  **replicas: 3**  
  **selector:**  
    **matchLabels:**  
      **app: frontend**  
    **template:**  
      **metadata:**  
        **labels:**  
          **app: frontend**  
      **spec:**  
        **containers:**  
        **\- image: frontend-application**  
        **name: frontend-application**  
        **ports:**  
        **\- containerPort: 5000**

Services

A Kubernetes Service provides a stable network endpoint for a group of Pods. It automatically routes traffic to healthy Pods and load balances requests.

Services use label selectors to identify target Pods.

Create a Service to Expose Pods

First, define a Deployment that runs your application and labels the Pods:

apiVersion: apps/v1  
kind: Deployment  
metadata:  
  name: frontend  
spec:  
  replicas: 3  
  selector:  
    matchLabels:  
      app: frontend  
  template:  
    metadata:  
      labels:  
        app: frontend  
    spec:  
      containers:  
        \- name: frontend-application  
          image: frontend-application  
          ports:  
            \- containerPort: 5000

Then, expose these Pods using a Service:

apiVersion: v1  
kind: Service  
metadata:  
  name: frontend-svc  
spec:  
  selector:  
    app: frontend  
  ports:  
    \- port: 80  
      targetPort: 5000  
      protocol: TCP

By default, the Service type is ClusterIP, which exposes the Service only within the cluster.

To apply the Service:

kubectl apply \-f frontend-svc.yaml

Or use kubectl expose:

kubectl expose deployment frontend \--name=frontend-svc \\  
  \--port=80 \--target-port=5000`

How Services Group Pods

Services use label selectors to identify groups of Pods. You can define separate Services for each group:

  • frontend-svc — targets Pods with app=frontend
  • db-svc — targets Pods with app=db

Accessing the Pods Using Service Object
Image credits : https://trainingportal.linuxfoundation.org

When you create a Service, Kubernetes:

  • Assigns it a ClusterIP (accessible only inside the cluster)
  • Maps that ClusterIP to a list of Pod IPs and ports (called Endpoints)
  • Uses kube-proxy to route traffic based on IP rules

To view the Service and its endpoints:

kubectl get service,endpoints frontend-svc

The client connects to the Service via its ClusterIP. The Service forwards traffic to one of the selected Pods and performs load balancing.

The user/client now connects to a Service via its ClusterIP, which forwards traffic to one of the Pods attached to it. A Service provides load balancing by default while selecting the Pods for traffic forwarding.

Load Balancing and Failover

A Service balances traffic across all healthy Pods. When a Pod is replaced, the Service updates its endpoints list and redirects traffic to the new Pod—no changes needed in client configuration.

Note: Each endpoint includes the Pod's IP and its target port.

Kube-proxy

In Kubernetes, each node runs kube-proxy, a network proxy that maintains network rules on nodes. It enables communication to your Pods from network sessions inside or outside of your cluster.

Each node runs kube-proxy, which:

  • Service Management: kube-proxy watches the Kubernetes API for changes in Service and Endpoint objects, updating the node's network rules accordingly.
  • Traffic Routing: It uses either iptables or IPVS to handle traffic routing. By default, iptables is used, which is simple and well-supported but less efficient than IPVS.

For each new Service, kube-proxy configures iptables rules on each node to capture traffic for the Service's ClusterIP and forward it to one of the Service's endpoints. This enables any node to receive external traffic and route it internally based on the iptables rules. When a Service is removed, kube-proxy deletes the corresponding iptables rules from all nodes.

The kube-proxy agent runs on every node, and iptables rules are redundantly populated across nodes. Each iptables instance stores routing rules for the entire cluster, ensuring that Service objects implement distributed load balancing.

Kube-proxy description diagram
Image credits : https://trainingportal.linuxfoundation.org

Traffic Policies

Kubernetes Services support traffic policies that influence routing decisions:

  • Cluster (Default): Routes traffic to all ready endpoints, regardless of their node.
  • Local: Routes traffic only to endpoints on the same node as the client. If no local endpoints are available, the traffic is dropped.

You can configure these policies in your Service manifest:

apiVersion: v1  
kind: Service  
metadata:  
  name: frontend-svc  
spec:  
  selector:  
    app: frontend  
  ports:  
    \- protocol: TCP  
      port: 80  
      targetPort: 5000  
  internalTrafficPolicy: Local  
  externalTrafficPolicy: Local

Service Discovery

Kubernetes supports two service discovery mechanisms:

  • Environment Variables: For each active Service, Kubernetes injects environment variables into new Pods. For example: REDIS_MASTER_SERVICE_PORT.
    • Note: These variables are set only when the Pod starts.
  • DNS-Based Discovery: Kubernetes DNS creates names like: my-svc.my-namespace.svc.cluster.local

This allows Services to be discoverable within the cluster.

ServiceType

Kubernetes Services can be exposed in different ways, defined by the type field:

  • Is only accessible within the cluster.
  • Is accessible from within the cluster and the external world.
  • Maps to an entity which resides either inside or outside the cluster.

Access scope is decided by ServiceType property, defined when creating the Service.

ClusterIP (default)

Exposes the Service on an internal IP, making it accessible only within the cluster.

ClusterIP exposing the service on NodePort
Image credits : https://trainingportal.linuxfoundation.org

NodePort

Exposes the Service on a static port on each node’s IP. A ClusterIP Service, to which the NodePort Service routes, is automatically created.

LoadBalancer

Exposes the Service externally using a cloud provider's load balancer. NodePort and ClusterIP Services, to which the external load balancer routes, are automatically created.

LoadBalancer exposing the service
Image credits : https://trainingportal.linuxfoundation.org

Note: Requires cloud provider support.

ExternalIP

Maps a Service to an external IP address. Traffic that is ingressed into the cluster with the ExternalIP (as destination IP) on the Service port, gets routed to one of the Service endpoints

External Ip to access the Service
Image credits : https://trainingportal.linuxfoundation.org

The administrator must configure external routing.

ExternalName

Maps the Service to an external DNS name using a CNAME record. No proxying occurs.

Multi-Port Services

Expose multiple ports in a single Service:

apiVersion: v1  
kind: Service  
metadata:  
  name: my-service  
spec:  
  selector:  
    app: myapp  
  type: NodePort  
  ports:  
    \- name: http  
      protocol: TCP  
      port: 8080  
      targetPort: 80  
      nodePort: 31080  
    \- name: https  
      protocol: TCP  
      port: 8443  
      targetPort: 443  
      nodePort: 31443

This is a helpful feature when exposing Pods with one container listening on more than one port, or when exposing Pods with multiple containers listening on one or more ports.

Port Forwarding for Local Testing

Use kubectl to forward a local port to a Service for testing:

kubectl port-forward svc/frontend-svc 8080:80

This is useful for debugging applications without exposing the Service externally.

Kubernetes Ingress

Kubernetes Services support internal routing, but defining routing logic per Service leads to duplication and limited flexibility. Ingress decouples routing rules from individual Services and acts as a centralized entry point for external traffic.

Ingress defines HTTP and HTTPS routing rules and acts as a single entry point for external traffic into your cluster. It configures a Layer 7 (application layer) load balancer and supports the following capabilities:

  • TLS termination: Offload SSL at the edge.
  • Name-based virtual hosting: Route traffic by hostname.
  • Fanout routing: Route traffic by URL path.
  • Custom routing rules: Use annotations to enable advanced behaviors.
  • Load balancing: Distribute traffic across Service backends.

Kubernetes Ingrees
Image credits : https://trainingportal.linuxfoundation.org

Instead of accessing a Service directly, clients connect to the Ingress endpoint. The Ingress resource defines routing rules that forward requests to the appropriate Service based on hostnames and URL paths.

Note: The Ingress resource itself does not handle traffic. An Ingress Controller—such as NGINX—interprets the rules and manages request forwarding.

Example: Name-Based Virtual Hosting

Use this pattern to route traffic based on the request hostname.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: virtual-host-ingress
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/service-upstream: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: blue.example.com
    http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: webserver-blue-svc
            port:
              number: 80
  - host: green.example.com
    http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: webserver-green-svc
            port:
              number: 80

In this example, requests to blue.example.com and green.example.com are routed to their respective backend Services.

Name-Based Virtual Hosting Ingress
Image credits : https://trainingportal.linuxfoundation.org

Example: Path-Based Fanout Routing

Use this pattern to route traffic based on the URL path.

apiVersion: networking.k8s.io/v1  
kind: Ingress  
metadata:  
  name: fan-out-ingress  
  namespace: default  
  annotations:  
    nginx.ingress.kubernetes.io/service-upstream: "true"  
spec:  
  ingressClassName: nginx  
  rules:  
  \- host: example.com  
    http:  
      paths:  
      \- path: /blue  
        pathType: ImplementationSpecific  
        backend:  
          service:  
            name: webserver-blue-svc  
            port:  
              number: 80  
      \- path: /green  
        pathType: ImplementationSpecific  
        backend:  
          service:  
            name: webserver-green-svc  
            port:  
              number: 80

Requests to example.com/blue and example.com/green are routed to the corresponding Services.

The ingress is fulfilled by an Ingress Controller, which is a reverse proxy responsible for traffic routing based on rules defined in the Ingress resource.

Ingress Controller

The Ingress resource only defines routing rules. It does not route traffic on its own. An Ingress Controller is responsible for fulfilling these rules.

An Ingress Controller:

  • Monitors the Kubernetes API for changes to Ingress resources
  • Configures the Layer 7 load balancer
  • Acts as a reverse proxy for external traffic

Popular Ingress Controllers

  • NGINX Ingress Controller
  • AWS Load Balancer Controller
  • GCE L7 Load Balancer
  • Istio Ingress

Note: Each controller may require specific annotations. Always specify the correct ingressClassName and annotations for compatibility.

Deploy an Ingress Resource

After enabling the Ingress Controller, deploy your Ingress resource using:

kubectl create \-f virtual-host-ingress.yaml

Annotations

Annotations allow you to store non-identifying metadata on Kubernetes objects in key-value pairs. They're not used for selection but provide auxiliary information to tools.

Common use cases:

  • Store build/release IDs, Git branch names.
  • Reference logging or monitoring tools.
  • Annotate ingress controller data.

Example: Add annotations during Deployment creation

apiVersion: apps/v1  
kind: Deployment  
metadata:  
  name: webserver  
  annotations:  
    description: "Deployment PoC \- 2 Mar 2022"  
spec:  
  ...

Resource Quotas and Limit Ranges

In multi-tenant Kubernetes clusters, it's essential to prevent any single user or team from consuming excessive resources. Kubernetes provides ResourceQuota and LimitRange objects to enforce such constraints.

Resource Quotas

ResourceQuota objects limit the aggregate resource consumption per namespace. They can restrict:

  • Object counts (Pods, Services, ConfigMaps, etc.)
  • Compute resources (CPU, memory).
  • Storage resources (PersistentVolumeClaims).

Example:

apiVersion: v1  
kind: ResourceQuota  
metadata:  
  name: compute-resources  
  namespace: devspace  
spec:  
  hard:  
    requests.cpu: "1"  
    limits.cpu: "2"  
    requests.memory: 1Gi  
    limits.memory: 2Gi

Limit Ranges

LimitRange objects set default request and limit values for Pods or Containers within a namespace. They ensure that containers don't consume excessive resources and help maintain cluster stability.

Example:

apiVersion: v1
kind: LimitRange
metadata:
 name: cpu-limits
 namespace: devspace
spec:
 limits:
 - default:
     cpu: 500m
   defaultRequest:
     cpu: 500m
   max:
     cpu: "1"
   min:
     cpu: 100m
   type: Container

Autoscaling

Autoscaling in Kubernetes adjusts the number of running objects based on resource utilization, availability, and requirements. There are several types of autoscalers:

Horizontal Pod Autoscaler (HPA)

HPA automatically scales the number of pod replicas based on CPU utilization or other select metrics.

kubectl autoscale deploy myapp \--min=2 \--max=10 \--cpu-percent=80

Vertical Pod Autoscaler (VPA)

VPA adjusts the CPU and memory requests and limits for containers based on usage. It helps optimize resource allocation for individual pods.

Cluster Autoscaler

The Cluster Autoscaler adjusts the number of nodes in your cluster when pods fail to launch due to insufficient resources or when nodes in the cluster are underutilized. In Azure Kubernetes Service (AKS), it's recommended to let the Kubernetes Cluster Autoscaler manage the required scale settings.

Autoscaling in Kubernetes

Job Scheduling

Jobs

A Job creates one or more Pods to perform a specific task and ensures that the specified number of Pods successfully terminate. Jobs are useful for batch processing tasks.

Configuration Options:

  • parallelism: Number of Pods to run in parallel.
  • completions: Number of successful completions needed.
  • activeDeadlineSeconds: Duration in seconds the Job may be active.
  • backoffLimit: Number of retries before marking the Job as failed.
  • ttlSecondsAfterFinished: Time to retain the Job after completion.

Example:

apiVersion: batch/v1  
kind: Job  
metadata:  
  name: data-cleanup  
spec:  
  template:  
    spec:  
      containers:  
      \- name: cleaner  
        image: busybox  
        command: \["sh", "-c", "cleanup.sh"\]  
      restartPolicy: Never  
  backoffLimit: 4

CronJobs

CronJobs schedule Jobs to run periodically at fixed times, dates, or intervals. They are useful for recurring tasks like backups or report generation .

Configuration Options:

  • schedule: Cron format schedule string.
  • startingDeadlineSeconds: Deadline in seconds for starting the Job if it misses its scheduled time.
  • concurrencyPolicy: Specifies how to treat concurrent executions.

Example:

apiVersion: batch/v1  
kind: CronJob  
metadata:  
  name: db-backup  
spec:  
  schedule: "0 1 \* \* \*"  
  jobTemplate:  
    spec:  
      template:  
        spec:  
          containers:  
          \- name: backup  
            image: backup-tool  
          restartPolicy: OnFailure

StatefulSets

StatefulSets manage the deployment and scaling of Pods with unique, persistent identities. Unlike Deployments, StatefulSets guarantee the ordering and uniqueness of Pods, making them ideal for stateful workloads.

Key Features

  • Persistent storage: Each Pod in a StatefulSet gets its own PersistentVolume. This volume is retained across Pod restarts or rescheduling.
  • Stable network identity: Each Pod receives a unique and consistent DNS name, allowing predictable network communication (for example, pod-0.service-name).
  • Ordered operations: Pods are created, updated, and deleted in a defined order, one at a time. This ensures safe startup, updates, and shutdowns.

Real-World Example

Use StatefulSets to deploy clustered databases or distributed systems where each node must retain its identity and storage.

Use Case: Cassandra or Redis Clusters

In a Cassandra cluster:

  • Each node (Pod) requires a stable hostname for cluster gossip protocol.
  • Each node needs its own storage volume to persist data across rescheduling.
apiVersion: apps/v1  
kind: StatefulSet  
metadata:  
  name: redis  
spec:  
  serviceName: "redis"  
  replicas: 3  
  selector:  
    matchLabels:  
      app: redis  
  template:  
    metadata:  
      labels:  
        app: redis  
    spec:  
      containers:  
        \- name: redis  
          image: redis:7.0  
          volumeMounts:  
            \- name: redis-data  
              mountPath: /data  
  volumeClaimTemplates:  
    \- metadata:  
        name: redis-data  
      spec:  
        accessModes: \[ "ReadWriteOnce" \]  
        resources:  
          requests:  
            storage: 1Gi

Custom Resources

Custom Resources are user-defined API objects that allow you to store and retrieve structured data in Kubernetes. Combined with controllers, they help automate custom workflows or represent external systems inside your cluster.

Custom Resource Definitions (CRDs)

CRDs are the most common way to add custom resources. They allow you to define custom objects without modifying the Kubernetes source code .

apiVersion: apiextensions.k8s.io/v1  
kind: CustomResourceDefinition  
metadata:  
name: databases.example.com  
spec:  
group: example.com  
versions:  
\- name: v1  
served: true  
storage: true  
schema:  
openAPIV3Schema:  
type: object  
properties:  
spec:  
type: object  
properties:  
engine:  
type: string  
scope: Namespaced  
names:  
plural: databases  
singular: database  
kind: Database  
shortNames:  
\- db

Once registered, you can create resources like:

apiVersion: example.com/v1  
kind: Database  
metadata:  
name: my-postgres-db  
spec:  
engine: postgres

Use a CRD to manage custom services like Database, Cache, or Queue, with a controller automating provisioning tasks across your infrastructure.

API Aggregation

API Aggregation is an advanced extension mechanism. It lets you run a separate API server behind the Kubernetes API, delegating requests to custom endpoints.

  • Your API server must implement Kubernetes-style authentication, authorization, and admission control.
  • You write and deploy your own API server.

This method is more complex but offers greater flexibility.

Security Contexts

Security Contexts define privilege and access controls for Pods and containers. You can use them to enforce non-root execution, set file system permissions, and limit privilege escalation.

Example: Secure Pod Configuration

apiVersion: v1  
kind: Pod  
metadata:  
  name: secure-pod  
spec:  
  securityContext:  
    runAsUser: 1000       \# Runs Pod as non-root user  
    fsGroup: 2000         \# Shared file system group  
  containers:  
  \- name: app  
    image: busybox  
    securityContext:  
      allowPrivilegeEscalation: false  \# Prevents gaining extra privileges

Note: Always run containers as a non-root user unless absolutely necessary.

Pod Security Admission

Pod Security Admission (PSA) is a built-in admission controller in Kubernetes. It enforces security standards at the namespace level by applying predefined policies.

  • Restricted: Strictest, enforces non-root and drops capabilities.
  • Baseline: Reasonably secure defaults.
  • Privileged: Allows full capabilities—use with caution.

Example: Enable Restricted Policy

kubectl label namespace my-namespace \\ pod-security.kubernetes.io/enforce=restricted

Network Policies

Network Policies control traffic flow to and from Pods. By default, all traffic is allowed unless restricted by a policy.

Example: Allow Only Frontend to Access Database

apiVersion: networking.k8s.io/v1  
kind: NetworkPolicy  
metadata:  
  name: allow-frontend  
spec:  
  podSelector:  
    matchLabels:  
      role: db  
  ingress:  
  \- from:  
    \- podSelector:  
        matchLabels:  
          role: frontend  
    ports:  
    \- port: 5432

Combine multiple policies to fine-tune network security for microservices.

A diagram explaining network policies

Metrics Server

The Metrics Server is a lightweight resource monitoring component. It provides CPU and memory usage data for Pods and nodes.

Example Commands:

kubectl top pods  
kubectl top nodes

Metrics Server in Kubernetes

Prometheus

Prometheus is a robust monitoring tool that collects and queries time-series metrics.

  • Scrapes metrics from applications and Kubernetes components.
  • Supports alerting and visualizations via Grafana.

Example Use Case:

Monitor HTTP request rates and latency in a web application. Integrate alerts when request rates spike or response times degrade.

Helm: Kubernetes Package Manager

Helm is the de facto package manager for Kubernetes. It enables developers to deploy and manage complex applications using templated YAML files—called charts—that follow DRY (Don't Repeat Yourself) principles.

Package and deploy complex applications like WordPress, NGINX Ingress, or custom APIs using reusable charts. A chart includes:

  • Template files for resource definitions
  • Configuration values
  • Metadata (e.g., chart name, version)

Charts can be stored in repositories—similar to how .deb or .rpm packages are stored for Linux distributions—or in container registries.

Key Benefits

  • Reusable templates: Use Helm charts to define, install, and upgrade Kubernetes applications.
  • Version control: Roll back to previous releases with a single command.
  • GitOps friendly: Integrates well with tools like Argo CD and Flux for continuous delivery.

How Helm Works

Helm is a command-line tool that runs alongside kubectl and uses your existing kubeconfig file to connect securely to your cluster. It performs the following actions:

  1. Searches chart repositories based on your criteria.
  2. Downloads the selected chart to your local system.
  3. Uses the Kubernetes API to deploy the resources defined in the chart.

You can also use Helm to upgrade or delete deployments.

Benefits:

  • DRY deployment configs
  • Easy upgrades/rollbacks
  • Integrates with GitOps workflows

Service Mesh: Advanced Service Communication

A service mesh abstracts communication between microservices into a dedicated infrastructure layer. It helps manage:

  • Secure communication: Enforces mutual TLS (mTLS) between Pods.
  • Advanced traffic routing: Supports strategies like canary releases and A/B testing.
  • Observability: Collects traffic metrics, latency data, and failure insights without modifying app code.

Architecture Overview

Each Pod includes a sidecar proxy that handles communication and policy enforcement. These proxies form the data plane, while a central control plane manages configuration and telemetry.

  • Data Plane: Handles service traffic. This usually includes sidecar proxies injected into each Pod, or node-level proxies in some implementations.
  • Control Plane: Manages configuration, service discovery, policy enforcement, and telemetry.

The sidecar proxy intercepts all inbound and outbound traffic to the Pod, enabling consistent policy enforcement and observability without modifying the application code.

Decoupling of networking logic from application code

Popular Service Meshes

Name Notable Feature
Istio Full-featured, widely adopted
Linkerd Lightweight and CNCF-supported

Next steps

For more information, refer to: