Skip to content

Intermediate · Kubernetes fundamentals · topic 23 of 53 · 35 min

Namespaces, ConfigMaps, Secrets, resources and probes

Explanation

Namespaces divide one cluster between teams and apps. ConfigMaps hold settings and Secrets hold passwords and keys, passed to pods as environment variables or files; Secrets are only base64-encoded by default, so protect them with RBAC, encryption at rest or an external secret manager. Requests and limits tell Kubernetes how much CPU and memory a container needs, and probes tell it whether a container is alive and ready for traffic.

Namespaces

A namespace is a named section of a cluster. Object names must be unique inside a namespace, but two namespaces can each have a Service called api. Teams use namespaces to separate apps or environments, and to set permissions (RBAC) and quotas per namespace. A new cluster has default, kube-system (the cluster's own components) and a few others.

bash
kubectl create namespace payments
kubectl get pods -n payments
kubectl config set-context --current --namespace=payments   # make it your default

ConfigMaps: settings outside the image

You build one image and run it in dev, staging and production. What changes is configuration: the log level, a feature switch, another service's URL. A ConfigMap stores such non-secret settings as key-value pairs, and pods read them as environment variables or as files.

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: payments-config
data:
  LOG_LEVEL: info
  BANK_API_URL: https://bank-sandbox.example.com
  limits.json: |
    {"dailyLimitRupees": 100000}
---
# in the Deployment's pod template:
spec:
  containers:
    - name: api
      image: registry.example.com/payments-api:1.4.2
      envFrom:
        - configMapRef:
            name: payments-config        # every key becomes an env variable
      volumeMounts:
        - name: config
          mountPath: /etc/payments       # limits.json appears as a file here
  volumes:
    - name: config
      configMap:
        name: payments-config
One ConfigMap, used both as environment variables and as a mounted file.

Environment variables are read once when the container starts, so after changing a ConfigMap you must restart the pods: kubectl rollout restart deployment/payments-api. Mounted files are updated after a short delay, but only if your app re-reads them.

Secrets: base64 is not encryption

A Secret looks like a ConfigMap but is meant for passwords, tokens and keys. Its data values are base64-encoded. Base64 is an encoding, a way to write any bytes as plain letters; it is not encryption. Anyone who can read the Secret can decode it in one command.

bash
echo -n 'S3cure#Pass' | base64          # UzNjdXJlI1Bhc3M=
kubectl create secret generic db-credentials --from-literal=password='S3cure#Pass'
kubectl get secret db-credentials -o jsonpath='{.data.password}' | base64 -d
echo -n avoids adding a newline to the value, a very common mistake.

So protect Secrets properly:

  • RBAC (role-based access control): allow get and list on Secrets only to the people and service accounts that need them.
  • Encryption at rest: configure the API server (or turn on the option in your managed cluster) so Secrets are encrypted in etcd, ideally with a cloud KMS key.
  • External secret managers: keep the real values in AWS Secrets Manager, Azure Key Vault, Google Secret Manager or HashiCorp Vault, and sync them into the cluster with a tool such as the External Secrets Operator or the Secrets Store CSI driver.
  • Never commit a plain Secret YAML to Git. If you must keep it in Git, encrypt it first with a tool such as Sealed Secrets or SOPS.

Requests and limits

A request is what the scheduler reserves for a container: it only places the pod on a node with that much free. A limit is the most the container may use. CPU is measured in cores: 1 means one full vCPU and 250m (250 millicores) means a quarter of one. Memory is measured in bytes with suffixes: Mi is a mebibyte (1,048,576 bytes) and Gi a gibibyte; M and G are the decimal versions (1,000,000 and 1,000,000,000).

Going over the CPU limit only slows the container down (throttling). Going over the memory limit gets the container killed, and kubectl describe shows the reason OOMKilled (out of memory), usually with exit code 137. Kubernetes then restarts it, and if it keeps happening you see CrashLoopBackOff.

QoS classWhenUnder memory pressure on the node
GuaranteedEvery container has CPU and memory requests equal to its limitsEvicted last
BurstableAt least one request or limit set, but not GuaranteedIn between
BestEffortNo requests or limits at allEvicted first

Probes: alive, ready, started

ProbeQuestion it asksWhat happens when it fails
livenessIs the app stuck?The kubelet restarts the container
readinessCan it take traffic right now?The pod is removed from Service endpoints until it passes again; no restart
startupHas a slow app finished starting?Liveness and readiness checks wait until it passes; if it never passes, the container is restarted
yaml
containers:
  - name: api
    image: registry.example.com/payments-api:1.4.2
    resources:
      requests:
        cpu: 250m
        memory: 256Mi
      limits:
        memory: 512Mi
    env:
      - name: DB_PASSWORD
        valueFrom:
          secretKeyRef:
            name: db-credentials
            key: password
    startupProbe:
      httpGet: { path: /healthz, port: 8080 }
      failureThreshold: 30
      periodSeconds: 2          # allow up to 60 seconds to start
    livenessProbe:
      httpGet: { path: /healthz, port: 8080 }
      periodSeconds: 10
    readinessProbe:
      httpGet: { path: /ready, port: 8080 }
      periodSeconds: 5
Resources, a Secret as an environment variable, and all three probes in one container.
Tip: Security settings for pods (for example, not running as root) are enforced by Pod Security Admission, which is built in and applies the Pod Security Standards per namespace with a label. It replaced PodSecurityPolicy, which was removed in Kubernetes 1.25.
Careful: Common mistakes. (1) A liveness probe that checks the database: when the database is slow, every pod is restarted at once, making things worse. Liveness should only check the process itself; put dependency checks in readiness. (2) A memory limit that is too low, causing an OOMKilled loop: look at real usage with kubectl top pod (needs metrics-server) and set the limit above the peak. (3) Writing cpu: 1000 when you meant 1000m: that asks for 1000 cores. (4) Mixing up 512M and 512Mi. (5) Putting passwords in a ConfigMap, or in a Secret committed to Git.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Namespaces, ConfigMaps, Secrets, resources and probes · 1/8

Config, secrets, resources, probes

In this lesson you will learn how to configure apps on Kubernetes and keep them healthy.

Prefer a video by a teacher? Find free videos on “kubernetes configmap secret resource requests limits probes tutorial” on YouTube ↗

In real life: A hospital appointment system in Chennai

A hospital group runs its appointment system in three namespaces: dev, staging and prod. The same image runs everywhere; a ConfigMap in each namespace sets the SMS gateway URL and log level. The database password lives in HashiCorp Vault and is synced into a Secret by the External Secrets Operator, and only the prod service account can read it. After the morning OPD rush caused OOMKilled restarts, the team checked kubectl top pod, raised the memory limit from 256Mi to 512Mi, and moved the database check from the liveness probe to the readiness probe so a slow database no longer restarts every pod.

bash
kubectl describe pod appointments-7f9-abcde -n prod | grep -A3 "Last State"
#    Last State:  Terminated
#      Reason:    OOMKilled
#      Exit Code: 137
The clue in kubectl describe that a container ran out of memory.

Practice (0/3 done)

Task 1 · Code · Python

A Secret's data map stores base64 strings. Write decode_secret(data) that returns a new dict with every value decoded to normal text, and encode_secret(values) that does the opposite. Use the base64 module. Example: decode_secret({"user": "YWRtaW4="}) returns {"user": "admin"}.

Task 2 · Code · Python

Write parse_cpu(q) that returns CPU cores as a float ("250m" gives 0.25, "1.5" gives 1.5, "2" gives 2.0), and parse_memory(q) that returns bytes as an int. Memory suffixes: Ki, Mi, Gi, Ti are powers of 1024 (Mi = 1024 ** 2); k, M, G, T are powers of 1000; no suffix means plain bytes. Example: parse_memory("512Mi") gives 536870912.

Task 3 · Question

A container keeps restarting and kubectl describe shows "Reason: OOMKilled". What is the best first fix?

Quick quiz

Question 1

1.How are values in a Kubernetes Secret protected by default?

Question 2

2.What does cpu: 500m mean?

Question 3

3.A pod fails its readiness probe. What happens?

Question 4

4.You changed a ConfigMap that a Deployment reads with envFrom. Why do the pods still see the old values?

Question 5

5.Which pods are evicted first when a node runs out of memory?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

How are values in a Kubernetes Secret protected by default?

Answer: Only base64-encoded, which anyone with read access can decode

Base64 is an encoding. Real protection comes from RBAC, encryption at rest and external secret managers.

What does cpu: 500m mean?

Answer: Half of one CPU core

m means millicores: 500m is 0.5 of a core.

A pod fails its readiness probe. What happens?

Answer: It is removed from Service endpoints until it passes again

Readiness controls traffic. Liveness controls restarts.

You changed a ConfigMap that a Deployment reads with envFrom. Why do the pods still see the old values?

Answer: Environment variables are read when the container starts, so the pods must be restarted

Run kubectl rollout restart deployment/<name> to start fresh pods with the new values.

Which pods are evicted first when a node runs out of memory?

Answer: BestEffort

BestEffort pods have no requests or limits and are the first to go.

Which object replaced PodSecurityPolicy (removed in Kubernetes 1.25) for enforcing Pod Security Standards?Related

Answer: Pod Security Admission, configured with namespace labels

The built-in Pod Security Admission controller enforces privileged, baseline or restricted per namespace.

From Kubernetes security

What do containers in the same pod share?Related

Answer: A network identity (one IP) and optionally volumes

Containers in a pod share the network namespace, so they reach each other on localhost, and can mount the same volumes.

From Pods, ReplicaSets and Deployments

A pod in namespace web calls Service "orders" in namespace shop. Which name works?Related

Answer: orders.shop

The pattern is service.namespace, with .svc.cluster.local optional at the end.

From Services, Ingress and the Gateway API

A Deployment wants 3 replicas. You delete one of its pods by hand. What happens?Related

Answer: A new pod is created to get back to 3

The ReplicaSet controller sees 2 of 3 and creates a replacement. That is self-healing.

From Why Kubernetes, and how a cluster works

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 1 more topic in “Kubernetes fundamentals” before its exam: Helm and Kustomize.
  2. Module 5 exam: Kubernetes fundamentals · 13 questions · 20 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, CI/CD pipelines. 53 topics left in the course before the final exam.

← Previous: Services, Ingress and the Gateway API