Skip to main content

Managing Namespaces and Multi-Tenancy

1. Creating Namespace in Chart

Property Value Description
namespace myapp-namespace Name of the namespace to create
annotations {"owner": "dev-team"} Annotations to apply to the namespace
labels {"env": "production"} Labels to apply to the namespace

Example: Creating a Namespace with Annotations and Labels

apiVersion: v1
kind: Namespace
metadata:
  name: myapp-namespace
  annotations:
    owner: dev-team
  labels:
    env: production
Note: The namespace will be created if it does not already exist when the chart is installed.

2. Using Release Namespace

Property Values Description
namespace string The Kubernetes namespace where the release will be installed.
createNamespace boolean If true, the namespace will be created if it does not exist.

Example: Setting Release Namespace

apiVersion: v1
kind: Namespace
metadata:
  name: production-apps

---
apiVersion: helm.sh/v1
kind: Release
metadata:
  name: my-app-release
spec:
  chart:
    name: nginx
    version: "1.0.0"
  namespace: production-apps
  createNamespace: true
Note: The namespace must exist or createNamespace must be set to true for the release to install successfully.

3. Installing Charts Across Namespaces

Option Values Description
--namespace string Install the chart into a specific namespace
--create-namespace bool Create the namespace if it does not exist
--atomic bool Fail and rollback if installation fails

Example: Installing a Chart in a Specific Namespace

helm install my-app stable/nginx-ingress --namespace production --create-namespace

Example: Installing with Atomic Rollback

helm install my-app stable/nginx-ingress --namespace staging --atomic
Note: Ensure the user has appropriate RBAC permissions to install in the target namespace.

4. Implementing Namespace Isolation

Property Description Example
namespace The Kubernetes namespace where the chart will be deployed production
nameOverride Overrides the chart's release name in the namespace myapp-prod
fullnameOverride Overrides the full release name including namespace prefix production-myapp-prod

Example: Deploying to a Specific Namespace

apiVersion: v1
kind: Namespace
metadata:
  name: production

---
apiVersion: helm.sh/v2
kind: Release
metadata:
  name: myapp-release
  namespace: production
spec:
  chart:
    name: myapp-chart
    version: "1.0.0"

Example: Using Values to Set Namespace

namespace: staging
nameOverride: "myapp-staging"
fullnameOverride: "staging-myapp-staging"

# In values.yaml
ingress:
  enabled: true
  hosts:
    - host: myapp.staging.example.com
      paths:
        - path: /
          backend:
            serviceName: myapp-service
            servicePort: 80
Note: Helm does not enforce namespace isolation by default. It is the responsibility of the user or CI/CD pipeline to ensure that charts are deployed to the correct namespace.
Warning: Be cautious when deploying charts to namespaces with existing resources. Helm will attempt to upgrade or recreate resources, which may lead to data loss or service disruption.

5. Using Namespace-scoped Resources

Resource Type Namespace Scope Description Example
ConfigMap Yes Stores non-confidential data in key-value pairs
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: production
data:
  config.json: |
    { "debug": false }
Secret Yes Stores sensitive data like passwords or tokens
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
  namespace: staging
type: Opaque
data:
  password: cGFzc3dvcmQ=
Service Yes Exposes an application within a namespace
apiVersion: v1
kind: Service
metadata:
  name: web-service
  namespace: dev
spec:
  selector:
    app: web
  ports:
    - port: 80
Deployment Yes Manages a set of replica Pods
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
  namespace: test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: nginx

Example: Namespace-scoped Resource in Helm Chart

apiVersion: v1
kind: Service
metadata:
  name: {{ include "myapp.fullname" . }}
  namespace: {{ .Values.namespace }}
spec:
  selector:
    app: {{ include "myapp.name" . }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: 80
Note: Helm charts can define resources in specific namespaces using .Values.namespace or by setting the namespace during installation with --namespace.
Warning: Be cautious when deleting namespaces, as it will remove all resources within that namespace.

6. Managing Cluster-scoped Resources

Resource Type Description Scope Notes
ClusterRole Defines permissions at the cluster level Cluster Used with ClusterRoleBinding to grant access across namespaces
ClusterRoleBinding Binds ClusterRole to users or groups across namespaces Cluster Cannot be scoped to a namespace
PersistentVolume Represents a piece of storage in the cluster Cluster Must be created before PersistentVolumeClaim
StorageClass Defines storage types with provisioners Cluster Used for dynamic volume provisioning
CustomResourceDefinition Extends Kubernetes API with custom resources Cluster Requires CRD to be installed before using custom resources

Example: Defining a ClusterRole for Multi-Tenant Access

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: tenant-admin
rules:
- apiGroups: [""]
  resources: ["namespaces"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "create", "update", "delete"]

Example: Binding ClusterRole to a User

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: tenant-admin-binding
subjects:
- kind: User
  name: alice
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: tenant-admin
  apiGroup: rbac.authorization.k8s.io
Note: Cluster-scoped resources are not namespaced and can be accessed from any namespace. Helm charts should not define cluster-scoped resources unless explicitly required for multi-tenancy or infrastructure setup.

7. Implementing Resource Quotas

Resource Quota Type Default Limit Notes
limits.cpu Resource Unlimited Maximum CPU allocation per namespace
limits.memory Resource Unlimited Maximum memory allocation per namespace
requests.cpu Resource Unlimited Minimum CPU requested per namespace
requests.memory Resource Unlimited Minimum memory requested per namespace
pods Count Unlimited Maximum number of pods allowed in the namespace
services.loadbalancers Count Unlimited Maximum number of LoadBalancer services
services.nodeports Count Unlimited Maximum number of NodePort services

Example: Setting Resource Quotas in a Namespace

apiVersion: v1
kind: ResourceQuota
metadata:
  name: example-quota
  namespace: production
spec:
  hard:
    limits.cpu: "2"
    limits.memory: 4Gi
    requests.cpu: "1"
    requests.memory: 2Gi
    pods: "10"
    services.loadbalancers: "5"
    services.nodeports: "3"
Note: Resource quotas are enforced at the namespace level and apply to all pods within that namespace. They do not prevent individual pods from exceeding their own limits, but rather enforce a total limit across the namespace.
Warning: Setting quotas too low can cause applications to fail or become unresponsive. Always test quota configurations in a non-production environment before applying them.

8. Using LimitRange for Namespaces

Property Values Description
apiVersion v1 The API version of the LimitRange resource
kind LimitRange The kind of the Kubernetes resource
metadata.name example-limit-range Name of the LimitRange resource
spec.limits[].type Container, PersistentVolumeClaim Type of resource to limit (e.g., container or PVC)
spec.limits[].max.cpu 2 Maximum CPU allocation per container
spec.limits[].min.memory 128Mi Minimum memory allocation per container
spec.limits[].default.cpu 500m Default CPU allocation if not specified
spec.limits[].default.memory 256Mi Default memory allocation if not specified

Example: Define LimitRange in a Helm Chart

apiVersion: v1
kind: LimitRange
metadata:
  name: {{ .Values.limitRange.name }}
spec:
  limits:
  - default:
      cpu: {{ .Values.limitRange.defaultCpu }}
      memory: {{ .Values.limitRange.defaultMemory }}
    defaultRequest:
      cpu: {{ .Values.limitRange.defaultRequestCpu }}
      memory: {{ .Values.limitRange.defaultRequestMemory }}
    max:
      cpu: {{ .Values.limitRange.maxCpu }}
      memory: {{ .Values.limitRange.maxMemory }}
    min:
      cpu: {{ .Values.limitRange.minCpu }}
      memory: {{ .Values.limitRange.minMemory }}
    type: Container
Note: LimitRange is applied per namespace and affects all pods created in that namespace unless overridden.
Warning: LimitRange does not enforce limits on resources that are already created; it only applies to new resources.

9. Handling Cross-Namespace References

Reference Type Description Usage Notes
ServiceReference Refers to a Kubernetes Service in another namespace service.name: "my-service"
service.namespace: "other-namespace"
Must have appropriate RBAC permissions to access the service
ConfigMapReference References a ConfigMap in another namespace configMap.name: "my-configmap"
configMap.namespace: "other-namespace"
Used for cross-namespace configuration sharing
SecretReference References a Secret in another namespace secret.name: "my-secret"
secret.namespace: "other-namespace"
Requires proper RBAC to read secrets in other namespaces

Example: Using Cross-Namespace Service in Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: frontend
        image: nginx:latest
        env:
        - name: BACKEND_URL
          valueFrom:
            configMapKeyRef:
              name: backend-config
              key: url
              namespace: backend-namespace
Note: When referencing resources in other namespaces, ensure that the Helm chart has appropriate RBAC rules or that the namespace is properly configured to allow cross-namespace access.

10. Implementing Multi-Tenant Charts

Property Description Example
tenantId Unique identifier for each tenant tenant-123
namespace Kubernetes namespace to deploy tenant resources tenant-123-namespace
configMap Configuration values specific to tenant tenant-123-config

Example: Multi-Tenant Chart Values

tenantId: tenant-123
namespace: tenant-123-namespace
configMap:
  databaseUrl: "postgres://tenant-123-db"
  apiUrl: "https://api.tenant-123.com"
Note: Ensure that each tenant's namespace has appropriate RBAC rules to isolate resources.
Warning: Avoid hardcoding tenant IDs in templates; use values files or secrets instead.

Key Considerations

  • Each tenant should have its own namespace to prevent resource conflicts.
  • Use tenantId as a variable to dynamically generate namespace names.
  • Store tenant-specific configuration in ConfigMaps or Secrets.

Was this article helpful?