Kamaji Documentation

repository·master·Indexed 24 days ago

https://github.com/clastix/kamaji

Kamaji is a Kubernetes Control Plane Manager that runs control plane components as Pods in a management cluster. It enables efficient, scalable, and multi-tenant hosted control planes using a declarative approach via TenantControlPlane and Datastore CRDs. It supports resource optimization, fast provisioning with Blue/Green deployments, and integrates with Cluster API through a dedicated provider.

Tokens
172.3K
Snippets
225
Records
842
Agent score
81%

What's inside Kamaji

  1. What is the Tenant Control Plane in Kamaji?

    master

    Kamaji uses a 'Tenant Control Plane' model to manage Kubernetes clusters at scale. Instead of provisioning dedicated machines for every cluster, Kamaji runs the control plane components (kube-apiserver, kube-scheduler, and kube-controller-manager) as pods within a central Management Cluster.

    Key Characteristics

    • Upstream Compatibility: Control plane components are standard CNCF-compliant Kubernetes binaries. Kamaji uses kubeadm for setup and lifecycle management.
    • Resource Efficiency: Running control planes as pods allows for high-density multi-tenancy on shared infrastructure.
    • High Availability: Control plane pods are managed via Kubernetes Deployments, providing self-healing, rolling updates, and autoscaling capabilities.
    • Declarative Management: Clusters are managed via the TenantControlPlane custom resource, making it suitable for GitOps and Infrastructure as Code (IaC) workflows.
  2. What is Kamaji and how does it work?

    master

    Kamaji is a Kubernetes Control Plane Manager that implements the Hosted Control Plane concept. Instead of running Kubernetes Control Plane components on dedicated machines, Kamaji runs them as Pods within a management cluster.

    Core Abstractions

    Kamaji extends the Kubernetes API using Custom Resource Definitions (CRDs) to manage two primary resources:

    1. TenantControlPlane (short-name: tcp): A Namespace-scoped resource that defines the desired state of a specific Kubernetes Control Plane. It allows you to configure:

      • Kubernetes configuration values.
      • Pod options (limits, requests, tolerations, node selectors, etc.).
      • Exposure methods (e.g., ClusterIP, LoadBalancer, or NodePort).
      • Core addons like kube-proxy, CoreDNS, and konnectivity.
    2. Datastore: A cluster-scoped resource that acts as the backing store for one or more TenantControlPlane instances. It manages the state of the managed clusters.

    Key Benefits

    • Resource Optimization: Decoupling the control plane from the datastore allows for high density and reduced hardware requirements (up to 60% savings).
    • Fast Provisioning & Updates: Control planes can be ready in ~16 seconds, and updates use Blue/Green deployment to ensure zero downtime and avoid mixed versions.
    • Automated Management: Handles certificate rotation via kubeadm, manages core addons, and provides auto-healing for the TenantControlPlane objects.
  3. Interpret RouteParentStatus conditions

    master

    RouteParentStatus.conditions describes the status of a route with respect to its Gateway. A route is considered Accepted if at least one of its rules is implemented by the Gateway.

    Note on Availability: A route's availability depends on both the Gateway's own status conditions and its listener status.

    Common reasons for missing 'Accepted' conditions:

    • The Route refers to a non-existent parent.
    • The Route type is not supported by the controller.
    • The Route is in a namespace the controller cannot access.
  4. Kamaji design principles and isolation model

    master

    Kamaji is built on several core principles to ensure production-grade multi-tenancy:

    • Unidirectional Management: The Management Cluster manages Tenant Clusters, but communication is strictly one-way. Tenant Clusters cannot access or see the Management Cluster.
    • Strong Isolation: Different Tenant Clusters cannot communicate with each other. Isolation is enforced at both the control plane and the datastore levels.
    • Declarative Operations: Management is performed using Kubernetes Custom Resource Definitions (CRDs), allowing for a fully declarative lifecycle.
    • CNCF Compliance: Kamaji uses unmodified upstream Kubernetes components and kubeadm for control plane setup, ensuring compatibility with standard Kubernetes tooling and CNCF conformance.
  5. Configure additional volumes in TenantControlPlane

    master
    The TenantControlPlane resource allows you to define additionalVolumes within the spec.controlPlane.deployment field. These volumes are mounted into the control plane deployment containers. Supported volume types include hostPath, image, iscsi, and several deprecated types. Use these to provide persistent storage, host files, or OCI artifacts to your control plane components.
  6. Reuse Kamaji templates across different cloud providers

    master

    Kamaji allows for modular template architecture. You can host shared templates (like KamajiControlPlaneTemplate and KubeadmConfigTemplate) in a central namespace and reference them in provider-specific ClusterClass resources. This ensures that the control plane logic remains consistent while only the infrastructure templates (AWS, Azure, etc.) change.

    # Example: AWS Cluster Class referencing shared Kamaji templates
    apiVersion: cluster.x-k8s.io/v1beta1
    kind: ClusterClass
    metadata:
      name: kamaji-aws-class
    spec:
      controlPlane:
        ref:
          apiVersion: controlplane.cluster.x-k8s.io/v1alpha1
          kind: KamajiControlPlaneTemplate
          name: kamaji-controlplane
          namespace: cluster-templates  # Shared template
      
      infrastructure:
        ref:
          apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
          kind: AWSClusterTemplate
          name: aws-cluster-template  # AWS-specific
      
      workers:
        machineDeployments:
        - class: default-worker
          template:
            bootstrap:
              ref:
                apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
                kind: KubeadmConfigTemplate
                name: kubeadm
                namespace: cluster-templates  # Shared template
            infrastructure:
              ref:
                apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
                kind: AWSMachineTemplate
                name: aws-worker-template  # AWS-specific
  7. Configure ephemeral volumes in KamajiControlPlaneTemplate

    master

    Ephemeral volumes are handled by a cluster storage driver and their lifecycle is tied to the pod. They are created before the pod starts and deleted when the pod is removed.

    When to use ephemeral volumes:

    • The volume is only needed while the pod runs.
    • You need features like restoring from snapshots or capacity tracking.
    • The storage driver is specified via a storage class and supports dynamic provisioning via a PersistentVolumeClaim.

    Note: For volumes that must persist longer than an individual pod's lifecycle, use PersistentVolumeClaim or vendor-specific APIs instead. For lightweight local ephemeral volumes, use a CSI driver directly.

    This is configured via spec.template.spec.deployment.extraVolumes[index].ephemeral.

  8. Customize ClusterClass using Variables and JSON Patching

    master

    The ClusterClass allows for highly flexible cluster deployments through two mechanisms:

    Variable System

    Variables define parameters that can be customized during cluster creation. Each variable includes an OpenAPI v3 schema for validation, requirement status, default values, and type constraints (e.g., minimum, maximum, enum).

    JSON Patching System

    Patches apply the values provided via variables to the base templates at cluster creation time.

    • Standard Patching: Uses jsonPatches with operations like replace or add to map a variable to a specific path in a template.
    • Conditional Patching: Uses the enabledIf field to apply a patch only if a specific condition is met (e.g., if a string is not empty).

    This allows a single ClusterClass to serve multiple use cases (e.g., small vs. large worker nodes) by simply changing the input variables.

    # Example of a variable definition
    variables:
    - name: machineSpecs
      required: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            numCPUs:
              type: integer
              minimum: 2
              maximum: 64
              default: 4
    
    # Example of a JSON patch applying a variable
    patches:
    - name: machineResources
      definitions:
      - selector:
          apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
          kind: VSphereMachineTemplate
          matchResources:
            machineDeploymentClass:
              names: ["default-worker"]
        jsonPatches:
        - op: add
          path: /spec/template/spec/numCPUs
          valueFrom:
            variable: machineSpecs.numCPUs
  9. How Konnectivity works in Kamaji

    master

    Kamaji uses Konnectivity to enable secure communication between the control plane and worker nodes, even in complex or restricted network environments. This is essential for operations like execing into pods, retrieving logs, port forwarding, and collecting metrics.

    The architecture consists of two components:

    1. Konnectivity Server: Runs as a sidecar container within each Tenant Control Plane pod (exposed on port 8132). It manages connections from worker nodes and routes traffic.
    2. Konnectivity Agent: Runs on worker nodes and initiates outbound connections to the Konnectivity server to establish a reliable tunnel.

    When a worker node joins a Tenant Cluster, the agents automatically establish these connections, making the communication path transparent to the user.

  10. Assign a specific Datastore to a TenantControlPlane

    master

    You can implement sharding or pooling strategies by assigning a specific Datastore resource to a TenantControlPlane using the spec.dataStore field.

    • If spec.dataStore is provided: The tenant uses the named Datastore resource.
    • If spec.dataStore is omitted: The tenant uses the default datastore configured in the Kamaji operator (via the --datastore CLI argument).
    apiVersion: kamaji.clastix.io/v1alpha1
    kind: TenantControlPlane
    metadata:
      name: k8s-133
      labels:
        tenant.clastix.io: k8s-133
    spec:
      dataStore: mysql-gold # This must match the name of your Datastore resource
      controlPlane:
        deployment:
          replicas: 2
        service:
          serviceType: LoadBalancer
      # ... other spec fields
  11. Configure Pod Anti-Affinity Rules

    master

    Pod anti-affinity allows you to define rules to avoid scheduling pods on the same nodes, zones, or other specific locations as existing pods. This is configured via KamajiControlPlaneTemplate.spec.template.spec.deployment.affinity.podAntiAffinity.

    There are two types of anti-affinity rules:

    1. requiredDuringSchedulingIgnoredDuringExecution: Hard constraints. If the anti-affinity requirements are not met at scheduling time, the pod will not be scheduled onto the node. Multiple elements are intersected (all must be satisfied).
    2. preferredDuringSchedulingIgnoredDuringExecution: Soft constraints. The scheduler will attempt to satisfy these rules by calculating a sum of weights. It prefers nodes with the highest sum (where weight is subtracted for each matching podAffinityTerm).
  12. Configure Pod Anti-Affinity in KamajiControlPlaneTemplate

    master

    You can define pod anti-affinity rules within a KamajiControlPlaneTemplate to ensure that certain pods are not co-located on the same nodes. This is configured under spec.template.spec.deployment.affinity.podAntiAffinity.

    There are two types of anti-affinity rules:

    1. Required: requiredDuringSchedulingIgnoredDuringExecution. The scheduler must avoid nodes that host pods matching the selector.
    2. Preferred: preferredDuringSchedulingIgnoredDuringExecution. The scheduler will try to avoid these nodes but is not strictly required to.

    To define which pods to avoid, you use a labelSelector which can consist of matchLabels (simple key-value pairs) or matchExpressions (complex logic using operators like In, NotIn, Exists, or DoesNotExist).