Kubernetes Architecture (Objects + YAML)

Kubernetes is a control plane + node runtime that converts declarative YAML into real workloads. This page uses an Accordion to explain the most important Kubernetes objects and how they work together, with real-life analogies and production-style YAML examples.

Control Plane Workloads Networking Config + Secrets Storage

How Kubernetes “Thinks”

Declarative state
You declare the desired state (YAML). The control plane continuously reconciles actual state to match desired state. If a Pod dies, the system recreates it (because the desired state says so).
Control Plane (brains)
API Server (front door), Scheduler (places Pods), Controller Manager (reconciliation), etcd (state database).
Worker Nodes (muscle)
kubelet (node agent), container runtime, CNI networking, kube-proxy (service routing).

A practical mental model
  • Namespace = project boundary / environment boundary
  • Deployment = desired number of Pods + rolling updates
  • Service = stable virtual endpoint to reach Pods
  • Ingress = HTTP routing rules into Services
  • ConfigMap/Secret = externalize configuration and credentials
  • PV/PVC = persistent storage (stateful workloads)

Common Real-Life Use Case

A company hosts a Spring Boot UI/API in AKS/EKS/GKE. Users hit https://app.company.com. Ingress routes to Service. Service load-balances to Pods created by a Deployment. ConfigMap holds app config. Secret holds DB password. A PVC stores uploaded files.

Why these objects exist
They separate concerns: deployment (lifecycle), networking (routing), config, and storage.

Kubernetes Objects (Accordion)

Functional goal

A Namespace is a logical partition inside the cluster. It scopes names, helps apply policies/quotas, and prevents “dev” and “prod” resources from colliding.

Real-life example

One cluster hosts multiple teams. Team A deploys into team-a-dev and team-a-prod. Team B deploys into team-b-dev and team-b-prod. RBAC can restrict who can change what.

YAML example
apiVersion: v1
kind: Namespace
metadata:
  name: spring-demo
  labels:
    owner: platform-team
    env: dev

Functional goal

A Pod is the basic runtime unit. It groups containers that must share: network identity (same IP/port space) and volumes. Most apps use one container per pod.

Real-life example

A Spring Boot app runs as one container. Optionally a sidecar container ships logs to a central system. Both live in the same Pod so they can share filesystem and localhost network.

YAML example
apiVersion: v1
kind: Pod
metadata:
  name: spring-ui-api
  namespace: spring-demo
  labels:
    app: spring-ui-api
spec:
  containers:
    - name: app
      image: myacr.azurecr.io/spring-ui-api:1.0
      ports:
        - containerPort: 9087
In production you typically do not manage Pods directly; you use a Deployment (next).

Functional goal

A Deployment declares “I want N identical Pods” and manages lifecycle: rollout, rollback, scaling, self-healing. If a node dies, pods are rescheduled elsewhere.

Real-life example

You want 2 replicas of your UI/API for availability. During an upgrade, Kubernetes replaces them gradually (rolling update) to avoid downtime.

YAML example
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-ui-api
  namespace: spring-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: spring-ui-api
  template:
    metadata:
      labels:
        app: spring-ui-api
    spec:
      containers:
        - name: app
          image: myacr.azurecr.io/spring-ui-api:1.0
          ports:
            - containerPort: 9087

Functional goal

Pods are ephemeral (IPs change). A Service provides a stable virtual IP/DNS name and load balances traffic to matching Pods using label selectors.

Real-life example

Your Ingress routes to spring-ui-api-svc. The service then distributes traffic across Pod replicas (replica-1, replica-2, etc.).

YAML example
apiVersion: v1
kind: Service
metadata:
  name: spring-ui-api-svc
  namespace: spring-demo
spec:
  selector:
    app: spring-ui-api
  ports:
    - name: http
      port: 80
      targetPort: 9087
  type: ClusterIP

Functional goal

Ingress defines L7 rules: hostname and path → service:port. It does not handle traffic by itself; it needs an Ingress Controller.

Real-life example

app.company.com/ routes to your UI/API service, while app.company.com/api routes to a backend API service.

YAML example
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: spring-ui-api-ingress
  namespace: spring-demo
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
    - host: app.company.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: spring-ui-api-svc
                port:
                  number: 80

Functional goal

The Ingress Controller watches Ingress objects and programs a real proxy/router to implement them. It is usually deployed as a Deployment + Service (type LoadBalancer).

Real-life example

In AKS, you might use NGINX ingress (in-cluster) or AGIC (Azure Application Gateway fronting AKS).

YAML example (IngressClass + Controller Service)
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: nginx
spec:
  controller: k8s.io/ingress-nginx

---
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  type: LoadBalancer
  selector:
    app.kubernetes.io/name: ingress-nginx
  ports:
    - name: http
      port: 80
      targetPort: 80
    - name: https
      port: 443
      targetPort: 443

Functional goal

A ConfigMap stores non-sensitive configuration separate from images. Lets you change config without rebuilding containers.

Real-life example

Configure Spring profiles, feature flags, external URLs, or logging levels.

YAML example
apiVersion: v1
kind: ConfigMap
metadata:
  name: spring-ui-api-config
  namespace: spring-demo
data:
  SPRING_PROFILES_ACTIVE: "aks"
  LOGGING_LEVEL_ROOT: "INFO"
  APP_WELCOME_MESSAGE: "Hello from Kubernetes!"

Functional goal

A Secret stores sensitive values (passwords, API keys). It can be mounted as files or injected as environment variables.

Real-life example

Database password or OAuth client secret used by your Spring Boot application.

Kubernetes Secrets are base64-encoded by default (not encrypted unless you enable encryption at rest). In production, consider integration with a managed secret store (e.g., Azure Key Vault) and CSI drivers.
YAML example
apiVersion: v1
kind: Secret
metadata:
  name: spring-ui-api-secret
  namespace: spring-demo
type: Opaque
data:
  DB_PASSWORD: c3VwZXJzZWNyZXQ=  # base64("supersecret")

Functional goal

Pods are ephemeral. A PersistentVolume (PV) represents storage, and a PersistentVolumeClaim (PVC) is a request for that storage. In cloud clusters, PVs are often created dynamically via a StorageClass.

Real-life example

A report generator uploads PDFs and must retain them even if the Pod restarts. The app mounts a PVC at /data.

YAML example (PVC + Pod mount)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: uploads-pvc
  namespace: spring-demo
spec:
  accessModes: [ "ReadWriteOnce" ]
  resources:
    requests:
      storage: 5Gi

---
apiVersion: v1
kind: Pod
metadata:
  name: uploader
  namespace: spring-demo
spec:
  containers:
    - name: app
      image: myacr.azurecr.io/uploader:1.0
      volumeMounts:
        - name: uploads
          mountPath: /data
  volumes:
    - name: uploads
      persistentVolumeClaim:
        claimName: uploads-pvc

Why these matter
  • DaemonSet: one Pod per node (log agents, monitoring agents)
  • StatefulSet: stable identities + storage (databases)
  • Job/CronJob: batch tasks (nightly report generation)
  • HPA: auto-scale replicas based on CPU/memory/custom metrics
  • RBAC: who can do what (least privilege)
Real-life examples

CronJob runs a nightly inventory sync. HPA scales UI pods during Black Friday traffic. RBAC prevents developers from modifying prod namespaces.

YAML snippet (HPA + CronJob)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: spring-ui-api-hpa
  namespace: spring-demo
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: spring-ui-api
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 60

---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: nightly-report
  namespace: spring-demo
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: job
              image: myacr.azurecr.io/report-job:1.0
              args: ["--mode=nightly"]
What you should remember
Kubernetes is “desired state + continuous reconciliation.” Most application deployments boil down to: Namespace + Deployment + Service + Ingress plus ConfigMap/Secret and PVC when needed.