Skip to main content

Managing Multi-Tenancy

1. Creating Tenant Namespaces

Property Description Example
metadata.name Name of the namespace tenant-a
metadata.labels Labels to identify the tenant {"tenant.id": "a", "environment": "production"}
spec Optional specification for namespace features {"finalizers": ["kubernetes"]}

Example: Create a Tenant Namespace

apiVersion: v1
kind: Namespace
metadata:
  name: tenant-a
  labels:
    tenant.id: a
    environment: production
Note: Namespaces are scoped to a single Kubernetes cluster and do not provide resource isolation across clusters.

2. Setting Resource Quotas

Resource Scope Description Example
limits.cpu cpu Maximum CPU usage per pod 2
limits.memory memory Maximum memory usage per pod 512Mi
requests.cpu cpu Minimum CPU requested per pod 0.5
requests.memory memory Minimum memory requested per pod 256Mi

Example: Resource Quota Definition

apiVersion: v1
kind: ResourceQuota
metadata:
  name: prod-quota
spec:
  hard:
    cpu: "2"
    memory: 512Mi
    pods: "10"
Note: Resource quotas are enforced at the namespace level and apply to all pods within that namespace.
Warning: Setting quotas too low can cause pods to be evicted or fail to start.

3. Configuring Limit Ranges

Example: Define LimitRange for Namespace

apiVersion: v1
kind: LimitRange
metadata:
  name: mem-limit-range
spec:
  limits:
  - default:
      memory: 512Mi
    defaultRequest:
      memory: 256Mi
    type: Container
Field Description Values
spec.limits[].type Resource type to apply limits to Container, PersistentVolumeClaim
spec.limits[].default Default resource limit for each container cpu, memory
spec.limits[].defaultRequest Default resource request for each container cpu, memory
Note: LimitRanges are enforced at pod creation time and cannot be changed after a pod is created.
Warning: LimitRanges do not apply to Pod objects directly, but only to containers within pods in the namespace where the LimitRange is defined.

4. Implementing RBAC Isolation

Resource Permission Description
Role get, list, watch Read access to resources within a namespace
ClusterRole get, list, watch Read access to cluster-wide resources
RoleBinding bind Assigns roles to users or groups within a namespace
ClusterRoleBinding bind Assigns cluster roles to users or groups across the entire cluster

Example: Creating a Role for Pod Access

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

Example: Binding Role to User

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: production
subjects:
- kind: User
  name: alice
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io
Note: RBAC rules are additive; permissions granted to a user or group are cumulative across all bindings.

5. Using Network Policies

Example: Basic Network Policy

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8080
Field Description Values
apiVersion API version of the NetworkPolicy networking.k8s.io/v1
kind Kind of the resource NetworkPolicy
metadata.name Name of the NetworkPolicy String
spec.podSelector Selector to identify pods to which this policy applies LabelSelector
spec.policyTypes Types of policy (Ingress, Egress) ["Ingress", "Egress"]
spec.ingress Rules for incoming traffic List<NetworkPolicyIngressRule>
spec.egress Rules for outgoing traffic List<NetworkPolicyEgressRule>
Note: Network policies are enforced by the CNI plugin. Ensure your cluster supports network policies (e.g., Calico, Cilium).

Example: Deny All Ingress

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-ingress
spec:
  podSelector: {}
  policyTypes:
    - Ingress

Example: Allow From Specific Namespace

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-frontend-namespace
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: frontend-namespace
      ports:
        - protocol: TCP
          port: 8080

6. Configuring Pod Security

Policy Description Configuration Notes
Pod Security Standards Enforce security policies for pods in a namespace pod-security.kubernetes.io/enforce=privileged Values: enforce, audit, warn
Enforce Level Level of enforcement for pod security enforce=restricted Options: privileged, baseline, restricted
Namespace Label Label to apply pod security policy to a namespace pod-security.kubernetes.io/enforce=baseline Applied to namespace metadata

Example: Applying Pod Security Standard

apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: baseline

Example: Enforcing Restricted Policy

apiVersion: v1
kind: Namespace
metadata:
  name: dev
  labels:
    pod-security.kubernetes.io/enforce: restricted
Note: Pod Security Admission is available in Kubernetes v1.23+ and requires the PodSecurity admission controller to be enabled.
Warning: Setting enforce=privileged allows any pod to run with elevated privileges and should be used carefully.
Enforcement Level Description Restrictions Use Case
privileged Allows any pod to run with full privileges No restrictions System-level namespaces or legacy apps
baseline Allows minimal pod configuration Disallows hostPath, hostNetwork, and hostPID Default for most namespaces
restricted Most restrictive policy Disallows privileged containers, host namespaces, and unsafe capabilities High-security environments

7. Using Virtual Clusters

Feature Description Usage
Virtual Cluster A virtual cluster is a logical grouping of resources within a Kubernetes cluster that isolates workloads and configurations. Used to provide multi-tenancy and resource isolation in a shared cluster environment.
Namespace Isolation Each virtual cluster can be associated with one or more namespaces to isolate workloads. Enforced via RBAC and namespace-level resource quotas.
Resource Quotas Limit the amount of resources (CPU, memory) that can be consumed by a virtual cluster. Configured via ResourceQuota objects in each namespace.

Example: Creating a Virtual Cluster with Namespaces

apiVersion: v1
kind: Namespace
metadata:
  name: tenant-a
  labels:
    virtual-cluster: "tenant-a"
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota-tenant-a
  namespace: tenant-a
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi
Note: Virtual clusters are not a built-in Kubernetes feature but can be implemented using namespaces, RBAC, and resource quotas.

Virtual Clusters vs. Dedicated Clusters

  • Virtual Clusters: Shared cluster with isolation via namespaces and quotas.
  • Dedicated Clusters: Isolated clusters for each tenant, offering stronger isolation.

8. Implementing Hierarchical Namespaces

Property Description Example
namespace.name Name of the namespace production
namespace.labels Labels to organize namespaces {"environment": "prod", "team": "backend"}
namespace.annotations Annotations for metadata {"description": "Production backend services"}

Example: Creating a Hierarchical Namespace

apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    environment: prod
    team: backend
  annotations:
    description: "Production backend services"
Note: Hierarchical namespaces can be managed using label and annotation keys to group related namespaces under a common structure.

Best Practices for Hierarchical Namespaces

  • Use consistent naming conventions across teams.
  • Apply labels to enable filtering and grouping of namespaces.
  • Implement RBAC policies to control access at the namespace level.

9. Monitoring Tenant Resources

Resource Metric Description Units
CPU Usage container_cpu_usage_seconds_total Total CPU time consumed by containers seconds
Memory Usage container_memory_usage_bytes Current memory usage in bytes bytes
Network I/O container_network_receive_bytes_total Total bytes received over network interface bytes
Disk I/O container_fs_reads_bytes_total Total bytes read from disk bytes

Example: Querying CPU Usage for a Namespace

query="container_cpu_usage_seconds_total{namespace=\"tenant-a\"}"
prometheus-cli query "$query"
Note: Ensure that namespace labels are consistently applied to all resources in a tenant for accurate monitoring.

Key Metrics to Monitor

  • CPU Usage - Track for overconsumption or throttling.
  • Memory Usage - Watch for out-of-memory (OOM) events.
  • Network I/O - Identify potential bandwidth bottlenecks.
  • Disk I/O - Monitor for storage contention or slow disk access.

10. Implementing Cost Allocation

Resource Cost Allocation Method Description
Namespace label Assign cost tags to namespaces using labels for billing purposes
ResourceQuota limit Set resource limits per namespace to control consumption and cost
HorizontalPodAutoscaler autoscale Automatically scale pods based on CPU or memory usage to optimize costs

Example: Labeling Namespaces for Cost Tracking

apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    cost-center: engineering
    owner: team-alpha

Example: Setting Resource Limits

apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota
  namespace: production
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi

Example: Configuring Horizontal Pod Autoscaler

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
Note: Cost allocation in Kubernetes requires integration with cloud provider billing systems or third-party tools like kube-cost for detailed cost tracking.
Warning: Misconfigured resource limits can lead to performance degradation or application downtime.

Was this article helpful?