Helm & Namespaces

Templating Kubernetes Applications & Resource Organization

Lesson 1: Understanding Kubernetes Namespaces

Namespaces are a fundamental Kubernetes concept for organizing and isolating resources within a cluster.

What is a Namespace?

Reject the Official Definition: The standard documentation describes Namespaces as "a number of virtual clusters within one physical cluster," which can be confusing for newcomers.
Simple Definition: A Namespace is simply a space of names (пространство имен) within Kubernetes. It's a logical grouping mechanism for organizing cluster resources.

Core Purpose

Namespaces are primarily used to separate teams, projects, and their resources within a single physical cluster.

Cluster with Multiple Namespaces

namespace: team-a
Pods, Services, Deployments
for Team A
namespace: team-b
Pods, Services, Deployments
for Team B
namespace: production
Production workloads
isolated from dev/test

Enhanced Control Through Namespaces

Dividing a project by Namespaces grants more control, enabling:

1. Access Restriction:
Give teams only the necessary endpoints for their applications. This is manageable through tools like Network Policies, which can restrict traffic between Namespaces.
2. Resource Management:
Tighten resource limits within a Namespace using Resource Quotas. This prevents one team from consuming all cluster resources.

Basic Namespace Commands

# List all namespaces kubectl get namespaces # Create a new namespace kubectl create namespace dev-team # Set default namespace for current context kubectl config set-context --current --namespace=dev-team # Get pods in specific namespace kubectl get pods -n production # Get all resources in a namespace kubectl get all -n team-a

Creating a Namespace via YAML

apiVersion: v1 kind: Namespace metadata: name: development labels: environment: dev team: backend

Resource Quota Example

apiVersion: v1 kind: ResourceQuota metadata: name: dev-quota namespace: development spec: hard: requests.cpu: "10" requests.memory: 20Gi limits.cpu: "20" limits.memory: 40Gi persistentvolumeclaims: "10" pods: "50"
This quota limits the development namespace to a maximum of 50 Pods, 20Gi of memory requests, and 10 CPU cores requested across all workloads.

When to Use Namespaces

Recommended: Namespaces are most beneficial when there are multiple teams working on diverse tasks.
Not Recommended: Don't use Namespaces simply for dividing components of a single application (e.g., frontend, backend, database). For single-team applications, other organizational methods are more appropriate.

Lesson 2: Introduction to Helm - The Kubernetes Package Manager

Helm is the most popular package manager for Kubernetes, providing templating and package management capabilities for complex applications.

What is Helm?

Helm Definition: Helm is a package manager for Kubernetes that allows you to define, install, and upgrade even the most complex Kubernetes applications using reusable, templated packages called Charts.

Why Use Helm?

Without Helm, deploying applications to Kubernetes involves managing multiple YAML files manually:

Problems Without Helm:
  • Repetitive YAML files with hardcoded values
  • Difficult to maintain consistency across environments (dev, staging, prod)
  • No easy way to version or rollback application deployments
  • Complex to share application configurations with teams
  • Manual tracking of what's deployed and where
Benefits of Helm:
  • Templating: Parameterize YAML files using Go templates
  • Reusability: Create charts once, deploy multiple times with different configurations
  • Versioning: Track application versions and rollback when needed
  • Dependency Management: Charts can depend on other charts
  • Package Distribution: Share charts via repositories (like Docker Hub for containers)
  • CI/CD Integration: Seamlessly integrate into automated pipelines

Helm Terminology

Term Definition
Chart A Helm package containing all resource definitions needed to run an application
Release An instance of a chart running in a Kubernetes cluster
Repository A collection of charts available for download (like Artifact Hub)
Values Configuration parameters that customize a chart deployment
Templates Kubernetes manifest files with Go templating syntax

Helm v2 vs. Helm v3

A crucial topic is the comparison between the older second version and the newer third version.

Helm v2 (Legacy)

  • Tiller: Server-side component required in the cluster
  • Security Issues: Tiller had broad permissions, creating security risks
  • Storage: Release info stored in ConfigMaps
  • Status: Deprecated and no longer maintained

Helm v3 (Current)

  • No Tiller: Client-only architecture, more secure
  • Security: Uses Kubernetes RBAC directly
  • Storage: Release info stored in Secrets (more secure, handles larger charts)
  • Status: Current standard, actively maintained
Migration Required: If you're using Helm v2, migration to Helm v3 is necessary. Use the official helm-2to3 plugin for migration.

Installing Helm v3

# macOS brew install helm # Linux (script) curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash # Windows (Chocolatey) choco install kubernetes-helm # Verify installation helm version

Helm vs. Other Solutions

Why Helm is the Standard: While alternatives exist (Kustomize, jsonnet), Helm is positioned as the package manager whose existing analogs are either not obvious or are still too "raw" to offer the same level of full usability and comprehensive process building, particularly for integrating into CI/CD pipelines.

Lesson 3: Working with Helm - Essential Commands

Learn the fundamental Helm commands for managing charts and releases in your Kubernetes cluster.

Adding Chart Repositories

Chart repositories are collections of charts you can install from.

# Add the official stable charts repository helm repo add stable https://charts.helm.sh/stable # Add Bitnami repository (popular for production-ready charts) helm repo add bitnami https://charts.bitnami.com/bitnami # Update repository information helm repo update # List added repositories helm repo list # Search for charts in repositories helm search repo nginx # Search Artifact Hub (central chart registry) helm search hub wordpress

Installing Charts

# Install a chart with a release name helm install my-nginx bitnami/nginx # Install with custom namespace helm install my-app bitnami/wordpress --namespace production --create-namespace # Install with custom values inline helm install my-db bitnami/postgresql --set postgresqlPassword=secretpass # Install with custom values file helm install my-app ./my-chart -f custom-values.yaml # Dry-run to see what would be deployed (without actually deploying) helm install my-app bitnami/nginx --dry-run --debug
Best Practice: Always use --dry-run --debug first to verify the generated manifests before actual installation.

Managing Releases

# List all releases helm list # List releases in all namespaces helm list --all-namespaces # Get release status helm status my-nginx # Get release history helm history my-nginx # Upgrade a release helm upgrade my-nginx bitnami/nginx --set replicaCount=3 # Upgrade or install (if doesn't exist) helm upgrade --install my-app bitnami/nginx # Rollback to previous revision helm rollback my-nginx # Rollback to specific revision helm rollback my-nginx 2

Inspecting Charts

# Show chart information helm show chart bitnami/nginx # Show default values helm show values bitnami/nginx # Show all chart information helm show all bitnami/nginx # Download a chart to local directory helm pull bitnami/nginx # Download and extract helm pull bitnami/nginx --untar

Customizing Installations with Values

Values files allow you to customize chart deployments without modifying the chart itself.

# First, get the default values helm show values bitnami/nginx > values.yaml # Edit values.yaml with your custom settings # Example custom-values.yaml: --- replicaCount: 3 image: tag: 1.21.0 service: type: LoadBalancer port: 8080 resources: requests: memory: "256Mi" cpu: "100m" limits: memory: "512Mi" cpu: "200m" # Install with custom values helm install my-nginx bitnami/nginx -f custom-values.yaml
Multiple Values Files: You can specify multiple -f flags. Values are merged with later files taking precedence:
helm install app ./chart -f base-values.yaml -f prod-values.yaml

Uninstalling Releases

# Uninstall a release helm uninstall my-nginx # Uninstall and keep history helm uninstall my-nginx --keep-history # Uninstall from specific namespace helm uninstall my-app --namespace production

Debugging Failed Installations

# Get detailed information about release helm get all my-nginx # Get manifest that was deployed helm get manifest my-nginx # Get values used in the release helm get values my-nginx # Get hooks associated with release helm get hooks my-nginx # Template locally without installing helm template my-nginx bitnami/nginx -f custom-values.yaml
Common Issues:
  • Insufficient RBAC permissions
  • Invalid values causing template rendering errors
  • Resource conflicts (e.g., duplicate Service names)
  • Namespace doesn't exist (use --create-namespace)

Lesson 4: Creating Custom Helm Charts

Learn how to create your own Helm charts to package and distribute your Kubernetes applications.

Creating a New Chart

# Create a new chart scaffold helm create my-app # This creates the following structure: my-app/ ├── Chart.yaml # Chart metadata ├── values.yaml # Default configuration values ├── charts/ # Chart dependencies ├── templates/ # Kubernetes manifest templates │ ├── deployment.yaml │ ├── service.yaml │ ├── ingress.yaml │ ├── _helpers.tpl # Template helpers │ └── NOTES.txt # Post-install notes └── .helmignore # Files to ignore when packaging

Chart.yaml - Chart Metadata

apiVersion: v2 name: my-app description: A Helm chart for my awesome application type: application version: 1.0.0 # Chart version appVersion: "2.3.1" # Application version keywords: - web - nodejs - api maintainers: - name: Your Name email: you@example.com url: https://yoursite.com dependencies: - name: postgresql version: 11.x.x repository: https://charts.bitnami.com/bitnami condition: postgresql.enabled

values.yaml - Default Values

replicaCount: 2 image: repository: myapp tag: "1.0.0" pullPolicy: IfNotPresent service: type: ClusterIP port: 80 targetPort: 8080 ingress: enabled: false className: nginx hosts: - host: myapp.example.com paths: - path: / pathType: Prefix resources: limits: cpu: 200m memory: 256Mi requests: cpu: 100m memory: 128Mi autoscaling: enabled: false minReplicas: 2 maxReplicas: 10 targetCPUUtilizationPercentage: 80 postgresql: enabled: true auth: database: myapp username: myuser

Template Example - Deployment

apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "my-app.fullname" . }} labels: {{- include "my-app.labels" . | nindent 4 }} spec: {{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.replicaCount }} {{- end }} selector: matchLabels: {{- include "my-app.selectorLabels" . | nindent 6 }} template: metadata: labels: {{- include "my-app.selectorLabels" . | nindent 8 }} spec: containers: - name: {{ .Chart.Name }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports: - name: http containerPort: {{ .Values.service.targetPort }} protocol: TCP resources: {{- toYaml .Values.resources | nindent 10 }} env: - name: DATABASE_HOST value: {{ include "my-app.fullname" . }}-postgresql - name: DATABASE_NAME value: {{ .Values.postgresql.auth.database }}

Template Functions and Helpers

Common Template Functions:
  • {{ .Values.key }} - Access values from values.yaml
  • {{ .Chart.Name }} - Access Chart.yaml metadata
  • {{ .Release.Name }} - Access release information
  • {{ include "template-name" . }} - Include named templates
  • {{- if .Values.enabled }} - Conditional logic
  • {{ toYaml .Values.resources | nindent 4 }} - Format YAML with indentation

_helpers.tpl - Reusable Templates

{{/* Generate full name */}} {{- define "my-app.fullname" -}} {{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Common labels */}} {{- define "my-app.labels" -}} helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} app.kubernetes.io/name: {{ include "my-app.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} {{/* Selector labels */}} {{- define "my-app.selectorLabels" -}} app.kubernetes.io/name: {{ include "my-app.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }}

Testing and Packaging Your Chart

# Validate chart syntax helm lint my-app/ # Test template rendering helm template my-app my-app/ -f custom-values.yaml # Install locally for testing helm install test-release ./my-app --dry-run --debug # Package the chart helm package my-app/ # This creates: my-app-1.0.0.tgz # Install from package helm install my-release ./my-app-1.0.0.tgz

Best Practices for Chart Development

Chart Best Practices:
  • Always provide sensible default values
  • Document all configurable values in values.yaml with comments
  • Use helpers.tpl for common labels and naming patterns
  • Make resources optional via enabled flags
  • Include resource limits and requests
  • Test charts with helm lint and helm template
  • Version your charts semantically (semver)
  • Provide clear NOTES.txt for post-installation guidance

CI/CD Integration

Helm in CI/CD: Helm will be revisited when building CI/CD processes. It seamlessly integrates into automated pipelines for continuous deployment, allowing version-controlled, repeatable deployments across environments.
# Example CI/CD deployment command helm upgrade --install my-app ./my-app \ --namespace production \ --create-namespace \ --values values-prod.yaml \ --set image.tag=${CI_COMMIT_SHA} \ --wait \ --timeout 5m
Next Steps:
  • Review the official Helm documentation
  • Practice deploying charts on a test environment
  • Write your own chart for a real application
  • Explore Artifact Hub for community charts
  • Prepare for CI/CD integration

Final Quiz

Test your knowledge of Helm and Kubernetes Namespaces!

Question 1: What is the simplest definition of a Kubernetes Namespace?

a) A virtual cluster within a physical cluster
b) A space of names for organizing cluster resources
c) A container runtime environment
d) A network segmentation tool

Question 2: When are Namespaces most recommended?

a) For dividing components of a single application
b) When multiple teams are working on diverse tasks
c) Only for production environments
d) For every Kubernetes deployment

Question 3: What is a Helm Chart?

a) A Kubernetes cluster monitoring dashboard
b) A package containing all resource definitions needed to run an application
c) A container image repository
d) A network policy configuration

Question 4: What is the major architectural difference between Helm v2 and Helm v3?

a) v3 uses different template syntax
b) v3 removed Tiller (server-side component), using client-only architecture
c) v3 doesn't support chart repositories
d) v3 requires Docker to be installed

Question 5: Where does Helm v3 store release information?

a) In ConfigMaps
b) In Secrets
c) In etcd directly
d) In local filesystem only

Question 6: What command should you use before installing a chart to verify generated manifests?

a) helm verify
b) helm install --dry-run --debug
c) helm validate
d) helm check

Question 7: In a Helm template, how do you access values from values.yaml?

a) {{ .Config.key }}
b) {{ .Values.key }}
c) {{ .Parameters.key }}
d) {{ .Settings.key }}

Question 8: What file contains reusable template definitions in a Helm chart?

a) templates.yaml
b) _helpers.tpl
c) functions.yaml
d) common.tpl
Quiz Complete!
All correct answers are option 'b'. Review the lessons above to understand why these are the best answers.