Lesson 04 Namespaces & Labels
Theme:
Lesson 04 · Slide 1

Namespaces & Labels

Organising Kubernetes resources with Helm-driven metadata

Namespaces Labels Annotations Selectors Resource Quotas
Lesson 04 · Slide 2

Kubernetes Namespaces

kubectl get namespaces
# NAME              STATUS   AGE
# default           Active   42d
# kube-system       Active   42d
# kube-public       Active   42d
# kube-node-lease   Active   42d
Lesson 04 · Slide 3

Templating Namespaces in Helm

Helm sets the namespace at install time — every resource rendered receives it automatically.

# Install into a specific namespace
helm install my-app ./mychart -n staging --create-namespace

Reference the release namespace inside templates:

# templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-config
  namespace: {{ .Release.Namespace }}
data:
  env: {{ .Release.Namespace }}
Tip: You rarely need to hardcode namespace: in templates — Helm injects it. Use {{ .Release.Namespace }} only when a resource must reference its own namespace as data.
Lesson 04 · Slide 4

Creating Namespace Resources in Charts

Option A — Let Helm create it

helm install app ./chart \
  -n prod --create-namespace

Simple. Works for most cases.

Option B — Include in the chart

# templates/namespace.yaml
{{- if .Values.namespace.create }}
apiVersion: v1
kind: Namespace
metadata:
  name: {{ .Release.Namespace }}
  labels:
    {{- include "mychart.labels" . | nindent 4 }}
{{- end }}

Useful when the namespace needs labels, annotations, or quotas managed by the chart.

Warning: If the chart creates the namespace and the user passes --create-namespace, both attempts succeed idempotently — but consider documenting the intended approach.
Lesson 04 · Slide 5

Labels & Recommended Labels

Labels are key/value pairs attached to objects — they power selectors used by Services, Deployments, and tooling.

metadata:
  labels:
    app.kubernetes.io/name: myapp
    app.kubernetes.io/instance: myapp-staging
    app.kubernetes.io/version: "1.4.0"
    app.kubernetes.io/component: frontend
    app.kubernetes.io/part-of: ecommerce
    app.kubernetes.io/managed-by: Helm
Best practice: Always use the app.kubernetes.io/* common label schema. It is understood by kubectl, dashboards, and service meshes.
Lesson 04 · Slide 6

Annotations vs Labels

Labels

  • Used for selection & filtering
  • Indexed by the API server
  • Keep values short (< 63 chars)
  • Drive matchLabels in Deployments, Services

Annotations

  • Used for metadata & tooling config
  • Not indexed, not queryable
  • Can hold large values (JSON, URLs, etc.)
  • Examples: Prometheus scrape config, Ingress class hints
metadata:
  annotations:
    prometheus.io/scrape: "true"
    prometheus.io/port: "8080"
    helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
Lesson 04 · Slide 7

Label Selectors in Action

Services route traffic by matching pod labels. Deployments manage pods via matchLabels.

# templates/deployment.yaml
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ include "mychart.name" . }}
      app.kubernetes.io/instance: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app.kubernetes.io/name: {{ include "mychart.name" . }}
        app.kubernetes.io/instance: {{ .Release.Name }}

---
# templates/service.yaml
spec:
  selector:
    app.kubernetes.io/name: {{ include "mychart.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
Rule: A Deployment's selector.matchLabels is immutable after creation. Changing it requires deleting and recreating the Deployment.
Lesson 04 · Slide 8

Metadata Template & Resource Quotas

Centralise labels in _helpers.tpl so every template stays consistent:

# templates/_helpers.tpl
{{- define "mychart.labels" -}}
app.kubernetes.io/name: {{ include "mychart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
helm.sh/chart: {{ include "mychart.chart" . }}
{{- end }}

Pair namespaces with ResourceQuotas to enforce limits:

# templates/resourcequota.yaml
{{- if .Values.resourceQuota.enabled }}
apiVersion: v1
kind: ResourceQuota
metadata:
  name: {{ .Release.Name }}-quota
  namespace: {{ .Release.Namespace }}
spec:
  hard:
    requests.cpu: {{ .Values.resourceQuota.cpu | quote }}
    requests.memory: {{ .Values.resourceQuota.memory | quote }}
    pods: {{ .Values.resourceQuota.pods | quote }}
{{- end }}
1 / ?