Intermediate

Kubernetes for Developers: Volumes and Multi-container Pods

Use storage in Kubernetes, multi-container pod patterns and service accounts for security.

Level: Intermediate
Prerequisites: Basic knowledge of Kubernetes and containers


Table of Contents

  1. Course Overview
  2. Course Introduction
  3. Using Storage in Kubernetes
  4. Multi-container Pod Use Cases
  5. Securing Applications with Service Accounts
  6. Bringing It All Together — Final Demo
  7. Reference Tables
  8. Architecture Diagrams

1. Course Overview

This course goes beyond Kubernetes basics to tackle real-world topics:

  • Persistent storage: storage solutions, integration with high-performance and high-availability storage services
  • Multi-container Pods: init containers and all sidecar patterns
  • Security: securing applications running in Kubernetes

By the end of this course, you will have the skills needed to work with Kubernetes applications in production.


2. Course Introduction

Agenda

ModuleContent
Module 3Storage — volumes, persistence, PV/PVC, CSI, static and dynamic provisioning
Module 4Multi-container Pods — init containers, sidecar, adapter, ambassador
Module 5Service Accounts — AuthN/AuthZ, RBAC
Module 6Final demo integrating all concepts

Before starting, it is recommended to have completed at least one of the following courses:

  • Getting Started with Kubernetes
  • Kubernetes for Developers: Core Concepts

3. Using Storage in Kubernetes

3.1 Storage Overview

Storage is a critical topic for production applications. Most business-critical applications rely on data that must be available and protected.

Historical context (before containers):

  • On-premises deployment with physical servers
  • Dedicated storage systems (EMC, NetApp, etc.)
  • High-performance and high-availability volumes exposed as local disks to servers
  • These systems handled replication, failover, and encryption automatically

With Kubernetes:

  • Kubernetes does not reinvent the storage wheel
  • The model: let storage systems do their magic, Kubernetes simply consumes them
  • A plugin (CSI driver) connects the external storage system to the Kubernetes cluster

3.2 Decoupling the Data Lifecycle

The problem with the base container model

Container started → Data written → Container deleted/crashed → Data LOST

In the default container model, the data lifecycle is coupled to the container lifecycle. This is acceptable for stateless applications but unacceptable for stateful applications.

Analogy: It is like storing your photos only on your phone, without cloud backup. If the phone is lost, so are the photos.

The solution: decoupling lifecycles

Application (container) ←→ Volume (external storage)
                              ↑
                    INDEPENDENT lifecycle

Benefits:

  • Data survives container death
  • Data sharing between containers
  • Access from multiple pods (depending on access mode)

3.3 The Kubernetes PersistentVolume Subsystem

graph LR
    A[External storage system<br/>50Gi volume] -->|CSI Plugin| B[PersistentVolume PV<br/>Kubernetes object]
    B -->|Binding| C[PersistentVolumeClaim PVC<br/>Storage request]
    C -->|Referenced in| D[Pod Spec<br/>volumes + volumeMounts]
    D -->|Mounted in| E[Container<br/>/data]

Kubernetes API storage objects

ObjectRoleScope
StorageClassDefines a storage class/tier + the provisionerCluster
PersistentVolume (PV)Represents an external volume in KubernetesCluster
PersistentVolumeClaim (PVC)Storage request made by an applicationNamespace

Access Modes

ModeAbbreviationDescription
ReadWriteOnceRWORead/write by a single node
ReadOnlyManyROXRead-only by multiple nodes
ReadWriteManyRWXRead/write by multiple nodes

YAML — PersistentVolume (static provisioning)

apiVersion: v1
kind: PersistentVolume
metadata:
  name: ps-pv
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  csi:
    driver: pd.csi.storage.gke.io
    volumeHandle: projects/PROJECT_ID/zones/ZONE/disks/ps-vol

YAML — PersistentVolumeClaim

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ps-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 50Gi
  storageClassName: ""   # empty = manual binding to an existing PV

YAML — Pod using a PVC

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  volumes:
    - name: data-vol
      persistentVolumeClaim:
        claimName: ps-pvc
  containers:
    - name: app
      image: nginx
      volumeMounts:
        - mountPath: /data
          name: data-vol

PVC lifecycle

stateDiagram-v2
    [*] --> Pending: PVC created
    Pending --> Bound: Available PV found / created
    Bound --> Released: Pod deleted, PVC deleted
    Released --> Available: reclaimPolicy=Recycle
    Released --> [*]: reclaimPolicy=Delete
    Released --> Released: reclaimPolicy=Retain (manual intervention)

3.4 The Container Storage Interface (CSI)

History: In-tree vs Out-of-tree

graph TB
    subgraph "Old model (In-tree)"
        K1[Kubernetes Core Code] --> D1[EMC Driver]
        K1 --> D2[NetApp Driver]
        K1 --> D3[AWS EBS Driver]
    end

    subgraph "New CSI model (Out-of-tree)"
        K2[Kubernetes Core Code] -->|Standard interface| CSI[CSI Layer]
        CSI --> P1[EMC CSI Plugin]
        CSI --> P2[NetApp CSI Plugin]
        CSI --> P3[AWS EBS CSI Plugin]
    end

Problems with the in-tree model:

  • Third-party code had to be open source (Apache 2.0)
  • Bug fixes were tied to the Kubernetes release cycle
  • Kubernetes maintainers had to manage third-party code

Benefits of CSI:

  • Vendors can publish patches independently
  • No open-source license constraint
  • Standardized interface → portability across orchestrators (K8s, Mesos, etc.)

3.5 Static Provisioning

Flow:

  1. Administrator manually creates a volume on the storage system
  2. Administrator creates a PersistentVolume object that maps that volume
  3. Developer creates a PersistentVolumeClaim
  4. Kubernetes automatically binds the PVC to the matching PV
  5. The Pod references the PVC

Limitations: Does not scale in large environments — manual management for every volume.

3.6 Dynamic Provisioning

Flow:

  1. Administrator creates a StorageClass (once only)
  2. Developer creates a PersistentVolumeClaim referencing the StorageClass
  3. Kubernetes automatically creates the PV and volume on the backend
  4. The Pod uses the PVC

YAML — StorageClass

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ps-sc-fast
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-ssd
reclaimPolicy: Delete
allowVolumeExpansion: true

YAML — PVC with StorageClass (dynamic provisioning)

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ps-pvc-dynamic
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: ps-sc-fast  # references the StorageClass

Advantage: The StorageClass automatically creates volumes on demand — scalable and efficient.

3.7 Advanced Volume Features

Raw Block Volumes

Some applications (notably databases) write directly to unformatted raw volumes for better performance.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: block-pvc
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Block          # <-- raw block (not Filesystem)
  resources:
    requests:
      storage: 10Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: block-pod
spec:
  volumes:
    - name: block-vol
      persistentVolumeClaim:
        claimName: block-pvc
  containers:
    - name: app
      image: ubuntu
      volumeDevices:         # <-- volumeDevices (not volumeMounts)
        - name: block-vol
          devicePath: /dev/block

Volume Clones

Clone an existing volume to create an identical new PVC:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: cloned-pvc
spec:
  dataSource:
    name: source-pvc      # source PVC to clone
    kind: PersistentVolumeClaim
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

Volume Snapshots

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: my-snapshot
spec:
  volumeSnapshotClassName: csi-hostpath-snapclass
  source:
    persistentVolumeClaimName: my-pvc

3.8 Summary — Storage

graph TB
    EXT[External storage system<br/>cloud or on-prem] -->|CSI Plugin| K8S

    subgraph K8S [Kubernetes Cluster]
        PV[PersistentVolume PV]
        PVC[PersistentVolumeClaim PVC]
        SC[StorageClass]
        POD[Pod]

        SC -->|creates automatically| PV
        PVC -->|bind| PV
        POD -->|references| PVC
    end

Key points:

  • External storage exists outside of Kubernetes
  • Each system has its CSI plugin
  • PV = Kubernetes representation of an external volume
  • PVC = application storage request
  • StorageClass = automatic and dynamic provisioning
  • All containers in a Pod can share the Pod’s volumes

4. Multi-container Pod Use Cases

4.1 Pod Theory

Why Pods?

The Pod is the smallest deployable unit in Kubernetes. You do not deploy containers directly — Kubernetes requires them to be encapsulated in Pods.

What Pods provide to containers:

FeatureDescription
Probesstartup probe, readiness probe, liveness probe
Affinitiesnode affinity, pod affinity, anti-affinity
PoliciesrestartPolicy, terminationGracePeriodSeconds
Co-schedulingguarantees multiple containers are on the same node
Shared network namespaceall containers in a Pod share the same IP
Shared volumesvolumes are accessible by all containers in the Pod

Internal Pod architecture

graph TB
    subgraph POD [Pod — Shared execution environment]
        subgraph NET [Shared network namespace]
            C1[Main container<br/>app]
            C2[Sidecar container<br/>helper]
            IC[Init Container<br/>runs before]
        end
        VOL[Shared volume<br/>emptyDir / PVC]
        C1 <-->|mount| VOL
        C2 <-->|mount| VOL
        IC -->|prepares| VOL
    end
    POD -->|unique IP| NET2[Cluster network]

Main rule: One container = one responsibility. Initialization and integration logic goes in separate containers.

4.2 The Init Container Pattern

Concept

An init container is a special container that:

  • Runs before the main container
  • Runs once and must complete successfully
  • There can be multiple init containers (they run sequentially)
  • The main container starts only if all init containers succeed
sequenceDiagram
    participant K as Kubernetes
    participant I1 as Init Container 1
    participant I2 as Init Container 2
    participant A as App Container

    K->>I1: Start
    I1-->>K: Completes (exit 0)
    K->>I2: Start
    I2-->>K: Completes (exit 0)
    K->>A: Start
    A-->>K: Running...

Typical use cases

  • Clone a Git repository into a shared volume before the web server starts
  • Wait for an API or database to be available
  • Initialize permissions on files/directories
  • Prepare datasets

Analogy: The init container is like a constructor in a programming language — it prepares the environment before the main code runs.

YAML — Init Container

apiVersion: v1
kind: Pod
metadata:
  name: init-demo
spec:
  # Volume shared between init container and app container
  volumes:
    - name: web-content
      emptyDir: {}

  # Init container: clones a Git repo
  initContainers:
    - name: git-cloner
      image: alpine/git
      command:
        - git
        - clone
        - https://github.com/example/ps-web.git
        - /web-content
      volumeMounts:
        - name: web-content
          mountPath: /web-content

  # Main container: serves the cloned content
  containers:
    - name: web-server
      image: nginx
      ports:
        - containerPort: 80
      volumeMounts:
        - name: web-content
          mountPath: /usr/share/nginx/html

YAML — Init Container waiting for a service

initContainers:
  - name: wait-for-api
    image: busybox
    command:
      - sh
      - -c
      - |
        until wget -q --spider http://my-api-service:8080/health; do
          echo "Waiting for API..."
          sleep 5
        done
        echo "API is ready!"

4.3 The Sidecar Pattern

Concept

A sidecar is a container that runs in parallel with the main container, throughout the lifetime of the Pod. It is the most generic pattern — adapter and ambassador are specialized variants of it.

graph LR
    subgraph POD [Pod]
        MAIN[Main container<br/>nginx / app] <-->|Shared volume| VOL[emptyDir]
        SIDE[Sidecar<br/>git-sync] <-->|Shared volume| VOL
    end
    SIDE -->|periodic sync| GIT[GitHub Repo]

Difference from Init Container

CriterionInit ContainerSidecar
TimingBefore the main appIn parallel with the app
DurationRuns once and terminatesRuns continuously
UsageInitializationContinuous integration

YAML — Sidecar (continuous git-sync)

apiVersion: v1
kind: Pod
metadata:
  name: sidecar-demo
spec:
  volumes:
    - name: web-content
      emptyDir: {}

  containers:
    # Main container
    - name: web-server
      image: nginx
      volumeMounts:
        - name: web-content
          mountPath: /usr/share/nginx/html

    # Sidecar: continuous sync from Git
    - name: git-sync
      image: k8s.gcr.io/git-sync:v3.1.6
      env:
        - name: GIT_SYNC_REPO
          value: https://github.com/example/ps-web.git
        - name: GIT_SYNC_DEST
          value: /web-content
        - name: GIT_SYNC_PERIOD
          value: "30"      # sync every 30 seconds
      volumeMounts:
        - name: web-content
          mountPath: /web-content

4.4 The Adapter Pattern

Concept

The adapter is a specialized sidecar that transforms the format of data (metrics, logs) from the main application to a format expected by external tools.

Typical use case: Prometheus expects metrics in a specific format. If your application exposes metrics in a different format, an adapter sidecar handles the translation.

graph LR
    subgraph POD [Pod]
        APP[App Container<br/>native format metrics] -->|internal port| ADP[Adapter Container<br/>transforms format]
    end
    ADP -->|Prometheus format| PROM[Prometheus Server]

YAML — Adapter Pattern

apiVersion: v1
kind: Pod
metadata:
  name: adapter-demo
spec:
  containers:
    # Main container: exposes metrics in a custom format
    - name: web-app
      image: nigelpoulton/nginxadapter:1.0
      ports:
        - containerPort: 8080

    # Adapter sidecar: transforms metrics for Prometheus
    - name: prometheus-adapter
      image: nginx/nginx-prometheus-exporter:0.4.2
      args:
        - -nginx.scrape-uri=http://localhost:8080/nginx_status
      ports:
        - containerPort: 9113   # Prometheus port

Best practice: List the main container first in the containers array — it receives the focus of kubectl exec and kubectl logs commands by default.

4.5 The Ambassador Pattern

Concept

The ambassador is a specialized sidecar that acts as a proxy between the main container and external systems. The main container does not know the details of external connections — it communicates only with the ambassador on localhost.

Analogy: Like a political ambassador who manages relations with a foreign nation on behalf of their government — the president (main container) does not need to know the diplomatic protocol details.

graph LR
    subgraph POD [Pod]
        APP[App Container<br/>talks to localhost:9000] -->|localhost| AMB[Ambassador Container<br/>intelligent proxy]
    end
    AMB -->|manages certs, auth, routing| EXT[External API / External Service]

Benefits

  • The main container does not change when the external API changes (address, port, certificates)
  • Connection logic is centralized in the ambassador
  • Simplifies testing (mock the ambassador)

YAML — Ambassador Pattern

apiVersion: v1
kind: Pod
metadata:
  name: ambassador-demo
spec:
  containers:
    # Main container: connects to localhost:9000
    - name: app
      image: nigelpoulton/app:1.0
      env:
        - name: AMBASSADOR_URL
          value: http://localhost:9000

    # Ambassador sidecar: proxy to external API
    - name: ambassador
      image: nigelpoulton/ambassador:1.0
      ports:
        - containerPort: 9000
      env:
        - name: EXTERNAL_API_URL
          value: https://external-api.example.com
        - name: API_KEY
          valueFrom:
            secretKeyRef:
              name: api-secrets
              key: api-key

4.6 Summary — Multi-container Pods

graph TB
    subgraph PATTERNS [Multi-container Pod Patterns]
        INIT[Init Container<br/>🔵 runs BEFORE the app<br/>once only<br/>initialization]
        SC[Generic Sidecar<br/>🟢 runs IN PARALLEL<br/>continuously<br/>continuous integration]
        AD[Adapter<br/>🟡 Sidecar variant<br/>transforms data<br/>metrics / logs]
        AM[Ambassador<br/>🔴 Sidecar variant<br/>proxy to the outside<br/>connection abstraction]
    end

    INIT -.->|Precondition for| SC
PatternTypeTimingPrimary usage
Init ContainerSpecial (non-sidecar)Before the appInitialization, waiting for dependencies
SidecarGeneric sidecarContinuous parallelContent sync, log forwarding
AdapterSpecialized sidecarContinuous parallelFormat transformation (metrics/logs)
AmbassadorSpecialized sidecarContinuous parallelProxy to external systems

5. Securing Applications with Service Accounts

5.1 Kubernetes AuthN and AuthZ

Overview

In Kubernetes, everything goes through the API server — both kubectl commands from humans and requests from applications in Pods.

graph LR
    U[Human user<br/>kubectl] -->|User Account<br/>TLS certificates| API[API Server]
    APP[Application in Pod] -->|Service Account<br/>JWT token| API
    API -->|AuthN| AUTHN[Who are you?<br/>Authentication]
    AUTHN -->|AuthZ| AUTHZ[What are you allowed to do?<br/>Authorization RBAC]

Two types of secured entities:

TypeEntityManaged by
User AccountHumans, external tools (kubectl)Outside Kubernetes (identity management)
Service AccountApplications in PodsKubernetes (native API objects)

Principle of least privilege: Each entity should have only the minimum permissions necessary for its work.

5.2 Discovering Service Accounts

Default behavior

  • Every namespace automatically has a default Service Account
  • Every Pod is automatically associated with the default Service Account of its namespace (if not specified)
  • An admission controller watches Pod creation and assigns the default SA if absent
  • SA tokens are automatically mounted in the Pod

Inspecting Service Accounts

# List service accounts
kubectl get serviceaccounts

# Details of a service account
kubectl describe serviceaccount default

# See the SA of a Pod
kubectl get pod my-pod -o yaml | grep serviceAccountName

Service Account structure

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-service-account
  namespace: default

5.3 Using Service Accounts

Create a Service Account and configure RBAC

# 1. Create the Service Account
apiVersion: v1
kind: ServiceAccount
metadata:
  name: service-reader
  namespace: default
---
# 2. Create a Role (permissions)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: service-reader-role
  namespace: default
rules:
  - apiGroups: [""]
    resources: ["services"]
    verbs: ["get", "list", "watch"]
---
# 3. Bind the Role to the Service Account (RoleBinding)
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: service-reader-binding
  namespace: default
subjects:
  - kind: ServiceAccount
    name: service-reader
    namespace: default
roleRef:
  kind: Role
  name: service-reader-role
  apiGroup: rbac.authorization.k8s.io

Assigning a Service Account to a Pod

apiVersion: v1
kind: Pod
metadata:
  name: my-app-pod
spec:
  serviceAccountName: service-reader   # <-- specify the SA
  containers:
    - name: app
      image: my-app:1.0

Useful commands

# Create an SA via CLI
kubectl create serviceaccount service-reader

# Check the rights of an SA
kubectl auth can-i list services --as=system:serviceaccount:default:service-reader

5.4 Summary — Service Accounts

  • Everything goes through the API server (AuthN → AuthZ)
  • Humans use User Accounts (managed outside Kubernetes)
  • Applications in Pods use Service Accounts (managed inside Kubernetes)
  • RBAC is the standard authorization plugin (enabled by default on most clusters)
  • By default, Pods receive the default SA which has very limited permissions
  • In production: create dedicated SAs with the principle of least privilege

6. Bringing It All Together — Final Demo

The final demo combines all course concepts in a single multi-resource YAML file (separated by ---):

# finale-eks-disk.yml — Complete example integrating everything

# 1. StorageClass — dynamic provisioning
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ps-sc-final
provisioner: ebs.csi.aws.com
parameters:
  type: gp2
reclaimPolicy: Delete
---
# 2. PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: ps-sc-final
  resources:
    requests:
      storage: 10Gi
---
# 3. ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-sa
  namespace: default
---
# 4. RBAC Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: app-role
  namespace: default
rules:
  - apiGroups: [""]
    resources: ["services", "pods"]
    verbs: ["get", "list"]
---
# 5. RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: app-role-binding
  namespace: default
subjects:
  - kind: ServiceAccount
    name: app-sa
roleRef:
  kind: Role
  name: app-role
  apiGroup: rbac.authorization.k8s.io
---
# 6. Pod — integrates everything
apiVersion: v1
kind: Pod
metadata:
  name: final-demo-pod
  labels:
    app: final-demo
spec:
  serviceAccountName: app-sa              # Service Account

  volumes:
    - name: persistent-data
      persistentVolumeClaim:
        claimName: app-pvc                # PVC for persistent data
    - name: shared-content
      emptyDir: {}                        # Temporary shared volume

  # Init Container — prepares the environment
  initContainers:
    - name: initializer
      image: busybox
      command: ["sh", "-c", "echo 'Init complete' > /shared/ready.txt"]
      volumeMounts:
        - name: shared-content
          mountPath: /shared

  containers:
    # Main container
    - name: app
      image: nginx:1.21
      ports:
        - containerPort: 80
      volumeMounts:
        - name: persistent-data
          mountPath: /data                # Persistent data
        - name: shared-content
          mountPath: /shared             # Shared data

    # Ambassador Sidecar — proxy to external API
    - name: ambassador
      image: envoyproxy/envoy:v1.18.0
      ports:
        - containerPort: 9000
      volumeMounts:
        - name: shared-content
          mountPath: /shared

To deploy:

kubectl apply -f finale-eks-disk.yml

# Verify
kubectl get pods
kubectl get pvc
kubectl describe pod final-demo-pod

7. Reference Tables

Kubernetes volume types

TypePersistenceUsageNotes
emptyDirPod lifetimeSharing between containersDeleted when the Pod terminates
hostPathNode lifetimeAccess to node filesNot recommended in production
configMapPermanent (config)Configuration injectionGenerally read-only
secretPermanent (secret)Passwords, tokens, certsBase64 encoded
persistentVolumeClaimPermanentPersistent application dataRecommended for production
nfsPermanentNetwork shareReadWriteMany possible
csiPermanentVolumes via CSI driversModern standard

Multi-container Pod patterns

PatternContainerRoleData sharing
InitinitContainers[]Initializes before the appShared volume with the app
Sidecarcontainers[]Continuous helperShared volume or localhost
Adaptercontainers[]Transforms outgoing datalocalhost (internal port)
Ambassadorcontainers[]Proxies external connectionslocalhost (internal port)

Essential kubectl commands — Volumes

# PersistentVolumes
kubectl get pv
kubectl describe pv <pv-name>

# PersistentVolumeClaims
kubectl get pvc
kubectl describe pvc <pvc-name>

# StorageClasses
kubectl get storageclass
kubectl get sc

# Inspect volumes of a Pod
kubectl describe pod <pod-name>
kubectl get pod <pod-name> -o yaml | grep -A 20 volumes:

Essential kubectl commands — Multi-container Pods

# Logs of the main container
kubectl logs <pod-name>

# Logs of a specific container
kubectl logs <pod-name> -c <container-name>

# Logs of the init container
kubectl logs <pod-name> -c <init-container-name>

# Exec into a specific container
kubectl exec -it <pod-name> -c <container-name> -- /bin/sh

# View all containers of a Pod
kubectl get pod <pod-name> -o jsonpath='{.spec.containers[*].name}'

Essential kubectl commands — Service Accounts

# List Service Accounts
kubectl get sa
kubectl get serviceaccounts

# View details
kubectl describe sa <sa-name>

# Check permissions
kubectl auth can-i <verb> <resource> --as=system:serviceaccount:<namespace>:<sa-name>

# Example
kubectl auth can-i list services --as=system:serviceaccount:default:my-sa

8. Architecture Diagrams

Volume types — Overview

graph TB
    subgraph EPHEMERAL [Ephemeral volumes - tied to Pod lifecycle]
        ED[emptyDir<br/>empty at startup<br/>shared between containers]
        HP[hostPath<br/>file/folder on Node<br/>⚠️ not recommended in prod]
        CM[configMap<br/>configuration data]
        SEC[secret<br/>sensitive data]
    end

    subgraph PERSISTENT [Persistent volumes - survive the Pod]
        PVC2[PersistentVolumeClaim<br/>standard interface<br/>✅ recommended]
        NFS[nfs<br/>network share<br/>RWX possible]
        CSI2[csi<br/>Container Storage Interface<br/>modern standard]
    end

    PVC2 -->|bind| PV[PersistentVolume PV]
    PV -->|CSI Driver| BACK[Backend: AWS EBS / GCE PD / Azure Disk / NFS / etc.]

Data sharing flow between containers

sequenceDiagram
    participant IC as Init Container
    participant VOL as Shared volume (emptyDir)
    participant APP as App Container
    participant SC as Sidecar Container

    Note over IC: Initialization phase
    IC->>VOL: Writes initial data
    IC-->>APP: Completes (exit 0)

    Note over APP,SC: Execution phase (parallel)
    APP->>VOL: Reads/writes app data
    SC->>VOL: Reads app data
    SC-->>APP: Transforms/exposes (via localhost)

Complete architecture — PV/PVC/StorageClass

graph LR
    subgraph ADMIN [Kubernetes Administrator]
        SC3[StorageClass<br/>once]
    end

    subgraph DEV [Developer]
        PVC3[PersistentVolumeClaim<br/>spec: 10Gi]
        PODSPEC[Pod Spec<br/>volumes + volumeMounts]
    end

    subgraph K8S [Kubernetes automatic]
        PROV[CSI Provisioner]
        PV3[PersistentVolume<br/>10Gi created automatically]
    end

    subgraph CLOUD [Cloud Provider]
        DISK[EBS Disk / GCE PD /<br/>Azure Disk]
    end

    SC3 -->|referenced by| PVC3
    PVC3 -->|triggers| PROV
    PROV -->|creates| PV3
    PROV -->|provisions| DISK
    PV3 -->|bind| PVC3
    PVC3 -->|referenced in| PODSPEC

Multi-container Patterns — Visual comparison

graph TB
    subgraph INIT_PAT [Init Pattern]
        I_IC[Init Container] -->|completes| I_APP[App Container]
        I_IC <-->|volume| I_VOL[Volume]
        I_APP <-->|volume| I_VOL
    end

    subgraph SIDECAR_PAT [Sidecar Pattern]
        S_APP[App Container] <-->|volume| S_VOL[Volume]
        S_SC[Sidecar Container] <-->|volume| S_VOL
        EXT_GIT[Git Repo] -->|sync| S_SC
    end

    subgraph ADAPTER_PAT [Adapter Pattern]
        AD_APP[App Container<br/>metrics format A] -->|localhost| AD_SC[Adapter Container<br/>transforms to format B]
        AD_SC -->|format B| PROM[Prometheus]
    end

    subgraph AMB_PAT [Ambassador Pattern]
        AM_APP[App Container<br/>→ localhost:9000] -->|localhost| AM_SC[Ambassador Container]
        AM_SC -->|manages auth/TLS/routing| EXT_API[External API]
    end

Search Terms

kubernetes · developers · volumes · multi-container · pods · containers · service · yaml · accounts · container · pattern · pod · storage · volume · commands · concept · init · provisioning · pvc · account · architecture · essential · kubectl · storageclass

Interested in this course?

Contact us to book it or get a custom training plan for your team.