Cluster Capacity Analysis Framework

repository·master·Indexed 19 days ago

https://github.com/kubernetes-sigs/cluster-capacity

A framework for estimating how many instances of a specific pod can be scheduled in a Kubernetes cluster by simulating scheduling against local caches. It includes the cluster-capacity CLI for capacity analysis, the genpod utility for generating pod specifications based on namespace resource limits, and the hypercc unified entrypoint.

Tokens
6.9K
Snippets
24
Records
27
Agent score
66%

What's inside cluster-capacity

  1. How the cluster-capacity framework works

    master

    The framework estimates how many instances of a specific pod can be scheduled in a cluster. It uses a scheduler (created by a scheduler factory) and a loopback fake client that intercepts requests and operates over local caches.

    The Estimation Lifecycle:

    1. Capture State: The framework captures the current state of the cluster.
    2. Local Simulation: It translates API requests into local cache operations. This ensures the actual running cluster is not modified by the simulated scheduling.
    3. Estimation: The framework runs the scheduling logic against the local cache and provides the results via available channels.

    Key Assumptions:

    • The pod is assumed to run immediately after scheduling.
    • There is no interaction with Kubelet (no container running, image pulling, or volume handling).
    • There is no interaction with the Apiserver (all interactions use local caches).
    • There is no interaction with controllers.
  2. Configure Kubernetes service port and iptables forwarding

    master

    If your API server is running on a non-standard port (e.g., 6443) and you need to ensure the kubernetes service and network traffic correctly reach it, follow these steps:

    1. Patch the service port: Use kubectl patch to update the kubernetes service port to match your API server's port.
    2. Update iptables: Add a NAT rule to forward traffic from the VIP to the local API server address.
    # change service port
    $ kubectl patch svc kubernetes -p '[{"op": "replace", "path": "/spec/ports/0/port", "value":6443}]' --type="json"
    
    # update iptables to forward the kubernetes service to the Apiserver
    $ sudo iptables -t nat -A PREROUTING -d 10.0.0.1 -p tcp --dport 6443 -j DNAT --to-destination 127.0.0.1
  3. Run Cluster Capacity as a Kubernetes Job

    master

    You can run cluster-capacity as a Kubernetes Job to allow for automated, repeated analysis without manual intervention.

    Prerequisites

    1. Build a container image: Use the provided Dockerfile in the root directory.
      $ docker build -t cluster-capacity-image .
    2. Setup RBAC: Apply the necessary permissions using the provided configuration.
      $ kubectl apply -f config/rbac.yaml
    3. Prepare the Pod Spec: Create a ConfigMap containing the pod specification file you want to analyze.
      $ kubectl create configmap cluster-capacity-configmap --from-file pod.yaml

    Job Configuration

    When defining the Job, you must set the environment variable CC_INCLUSTER to true. This informs the tool that it is running inside a cluster as a pod.

    Example Job specification (cluster-capacity-job.yaml):

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: cluster-capacity-job
    spec:
      parallelism: 1
      completions: 1
      template:
        metadata:
          name: cluster-capacity-pod
        spec:
            containers:
            - name: cluster-capacity
              image: cluster-capacity-image
              imagePullPolicy: "Never"
              volumeMounts:
              - mountPath: /test-pod
                name: test-volume
              env:
              - name: CC_INCLUSTER
                value: "true"
              command:
              - "/bin/sh"
              - "-ec"
              - "/bin/cluster-capacity --podspec=/test-pod/pod.yaml --verbose"
            restartPolicy: "Never"
            serviceAccountName: cluster-capacity-sa
            volumes:
            - name: test-volume
              configMap:
                name: cluster-capacity-configmap

    Execution

    Run the job with:

    $ kubectl create -f cluster-capacity-job.yaml

    Check the results in the job logs:

    $ kubectl logs jobs/cluster-capacity-job
  4. Build and run cluster-capacity

    master

    To use the framework, you can build it from source using make and then run the analysis by providing a pod specification file via the --podspec flag.

    # Build the framework
    $ cd $GOPATH/src/sigs.k8s.io
    $ git clone https://github.com/kubernetes-sigs/cluster-capacity
    $ cd cluster-capacity
    $ make build
    
    # Run the analysis
    $ ./cluster-capacity --podspec=examples/pod.yaml
    $ cd $GOPATH/src/sigs.k8s.io
    $ git clone https://github.com/kubernetes-sigs/cluster-capacity
    $ cd cluster-capacity
    $ make build
    
    $ ./cluster-capacity --podspec=examples/pod.yaml
  5. Perform Namespace scoped analysis using genpod

    master

    Namespaces can have limitations like limit ranges, resource quota, or node selectors that affect schedulability. To account for these, the pod specification must be extended (e.g., setting spec.nodeSelector or spec.containers[i].resources).

    The genpod binary automates this by generating an extended pod specification based on the current limit ranges and node selectors of a specific namespace.

    Step 1: Generate the pod spec

    $ genpod --kubeconfig <path to kubeconfig> --master <API server address> --namespace <NAMESPACE>

    Step 2: Run analysis with the generated spec Use the generated file (e.g., genpod.yaml) and set the --resource-space-mode to ResourceSpacePartial to include admission controller constraints like quotas.

    $ genpod --kubeconfig <path to kubeconfig> --master <API server address> --namespace NAMESPACE
    
    $ ./cluster-capacity --kubeconfig <path to kubeconfig> --master <API server address> --podspec=genpod.yaml --apiserver-config config/apiserver.yaml --verbose --resource-space-mode ResourceSpacePartial
  6. Prerequisites for deploying cluster-capacity on Kubernetes

    master

    Before deploying cluster-capacity as a pod in a Kubernetes cluster, ensure the following requirements are met:

    1. Running Kubernetes Environment: A functional cluster is required.
    2. LimitRanges and Requests: The cluster should have LimitRange objects defined to specify resource limits and requests. If your cluster lacks these, you can apply an example LimitRange object to enable testing.
    3. Service and API Server Connectivity: The kubernetes default service must have the correct port, and traffic from the Virtual IP (VIP) must be forwarded to the running API server. For example, if the kubernetes service is on VIP 10.0.0.1 at port 443, and the API server is running on 127.0.0.1:6443, networking must be configured to bridge this gap.
  7. Run cluster-capacity as a Pod

    master

    If you do not have direct access to a kubeconfig (e.g., you only have web UI access), you can run the framework as a pod within the cluster.

    The following example demonstrates a pod that uses the genpod binary to create a specification for the cluster-capacity namespace and then executes the framework.

    Note: Once the framework pod is running, you can update the pod specification for the estimation by sending a POST request.

    apiVersion: v1
    kind: Pod
    metadata:
      name: cluster-capacity
      labels:
        name: cluster-capacity
    spec:
      containers:
      - name: cluster-capacity
        image: docker.io/gofed/cluster-capacity:latest
        command:
        - "/bin/sh"
        - "-ec"
        - |
          echo "Generating pod"
          /bin/genpod --namespace=cluster-capacity >> /pod.yaml
          cat /pod.yaml
          echo "Running cluster capacity framework"
          /bin/cluster-capacity --period=1 --podspec=/pod.yaml --default-config /config/default-scheduler.yaml
        ports:
        - containerPort: 8081
  8. Configure cluster-capacity analysis and scheduler

    master

    Configuration for the framework is split into two categories:

    Analysis Configuration

    Used to define how the estimation is performed:

    • kubeconfig: Path to the kubeconfig file.
    • apiserver-config: Address of the running Apiserver.
    • podspec: The pod specification to be scheduled.
    • maxLimit: The number of pod instances that, when reached, cause the analysis to stop prematurely.
    • period: The time interval between consecutive analysis runs.
    • resource-space-mode: The mode of resource space exploration.

    Scheduler Configuration

    The framework expects a scheduler created by the default scheduler factory. By default, it looks for a configuration file at config/default-scheduler.yaml. To match the behavior of your actual cluster, it is recommended to use the same scheduler configuration, including enabled predicates and priority functions.

    port: 10251
    address: 0.0.0.0
    algorithmprovider: DefaultProvider
    policyconfigfile: ""
    enableprofiling: false
    contenttype: application/vnd.kubernetes.protobuf
    kubeapiqps: 50
    kubeapiburst: 100
    schedulername: default-scheduler
    hardpodaffinitysymmetricweight: 1
    failuredomains: kubernetes.io/hostname,topology.kubernetes.io/zone,topology.kubernetes.io/region
    leaderelection:
      leaderelect: true
      leaseduration:
        duration: 15s
      renewdeadline:
        duration: 10s
      retryperiod:
        duration: 2s
  9. Provide a pod specification via file or URL

    master

    The --podspec flag allows you to define the pod you want to analyze. It supports two input methods:

    1. Local File: A path to a JSON or YAML file on the local filesystem.
    2. Remote URL: A URL starting with http:// or https:// from which the pod definition will be fetched.

    When a pod specification is loaded, cluster-capacity ensures it has a valid scheduler name (defaulting to the provided scheduler name if empty) and applies standard Kubernetes defaults for DNSPolicy (DNSClusterFirst), RestartPolicy (Always), and TerminationMessagePolicy (FallbackToLogsOnError) if they are not explicitly set.

    # Example using a local file
    cluster-capacity --podspec ./my-pod.yaml
    
    # Example using a remote URL
    cluster-capacity --podspec https://example.com/pod-definition.json
  10. Perform Greedy analysis via CLI

    master

    Greedy analysis explores the entire resource space, limiting the number of pod instances only by available allocatable resources. While only a subset of the pod specification is used, you should provide a valid pod specification (including existing image names).

    Use the cluster-capacity binary with the following flags:

    • --kubeconfig: Path to kubeconfig.
    • --master: API server address.
    • --podspec: Path to the pod YAML file.
    • --verbose: Enable verbose output.
    $ ./cluster-capacity --kubeconfig <path to kubeconfig> --master <API server address> --podspec=examples/pod.yaml --verbose
  11. Generate a sample pod spec with genpod

    master

    The genpod tool is an internal utility used to generate sample pod specifications based on existing resource limits and namespace constraints in a cluster.

    To generate a pod spec for a specific namespace, use:

    $ genpod --kubeconfig <path to kubeconfig> --namespace <namespace>

    Behavioral Details:

    • It identifies the maximum resource limits (CPU, Memory, etc.) available in the namespace.
    • If multiple resource limit objects exist, it takes the minimum of all maximum resources per type.
    • If the namespace is annotated with openshift.io/node-selector, the tool automatically sets that as the pod's nodeSelector.
    $ genpod --kubeconfig <path to kubeconfig>  --namespace <namespace>