Qbec

repository·main·Indexed 41 days ago

https://github.com/splunk/qbec

A CLI tool for managing Kubernetes objects across multiple clusters or namespaces using Jsonnet-based configurations. It allows for the synchronization of components via the `apply` command, supports external program execution during evaluation, and provides environment-specific context management.

Tokens
33.3K
Snippets
103
Records
154
Agent score
48%

What's inside Qbec

  1. Overview of qbec

    main
    qbec is a command-line tool designed to configure and create Kubernetes objects across multiple environments, clusters, and namespaces. It leverages jsonnet for configuration and is intended for managing complex Kubernetes deployments with features like environment-specific component lists, automatic garbage collection, and support for transient objects (e.g., one-off jobs or pods with generated names).
  2. Filter objects using component, kind, and namespace filters

    main

    Most qbec commands support filters to restrict the scope of execution.

    Component Filters

    Use these to include or exclude specific components defined in your project.

    • Include: -c component1 -c component2
    • Exclude: -C component1 -C component2
    • Note: All specified components must exist in the components directory. If a component is already excluded for an environment, specifying it with -c results in a warning and no effect.

    Kind Filters

    Use these to filter by Kubernetes object kind. Comparisons are case-insensitive and handle simple pluralization (e.g., -k secret and -k secrets both target Secret).

    • Include: -k kind1 -k kind2
    • Exclude: -K kind1 -K kind2
    • Note: Abbreviations like deploy for deployment are not supported.

    Namespace and Cluster Scope Filters

    Filter objects by Kubernetes namespace.

    • Include: -p namespace1 -p namespace2
    • Exclude: -P namespace1 -P namespace2
    • Cluster-scoped objects: By default, cluster-scoped objects are filtered out when a namespace filter is applied. Use --include-cluster-objects=true|false to explicitly control this behavior.
    • Note: Using namespace/cluster filters requires cluster access to retrieve metadata, even for commands like qbec show that normally do not require it.
  3. Use the --app-tag flag for scoped branch builds

    main

    The --app-tag command-line argument allows you to scope qbec objects to a specific application, environment, and tag. This is used to ensure that branch builds run in their own 'scope' and do not interfere with mainline builds or trigger unintended Garbage Collection (GC) of mainline objects.

    When using --app-tag, qbec provides the following:

    • Scoped GC: Garbage Collection is restricted to the specific tag, preventing it from deleting mainline or other tagged objects.
    • Jsonnet Variable qbec.io/tag: The tag value is exposed as an external variable so components can use it to create unique names.
    • Jsonnet Variable qbec.io/defaultNs: The name of the default namespace used for the run is exposed. If namespaceTagSuffix is enabled, this value can be automatically suffixed with the tag.
    qbec apply --app-tag=foo env
  4. How garbage collection works in qbec

    main
    Garbage collection (GC) is enabled by default in qbec. It does not require special flags like --gc-tag to function. When running commands, qbec identifies objects that are no longer defined in your configuration and marks them for deletion. Diffs will explicitly show the objects that would be deleted by the GC process. You can disable garbage collection on demand if needed.
  5. Structure of the runtime parameters object

    main

    When using param sub-commands, qbec expects your runtime configuration file (e.g., params.libsonnet) to return a JSON object structured by component names. The object must contain a top-level components key, with each subsequent key representing a component name and its associated configuration parameters.

    Your configuration must also be able to handle the baseline environment, represented by the underscore _ character.

    {
      "components": {
        "component1": {
          "param1": "value1",
          "param2": "value2"
        },
        "component2": {
          "param1": "value1"    
        }
      }
    }
  6. Use the baseline environment for local operations

    main

    qbec automatically provides a special baseline environment named _. This environment does not represent a real cluster and is used for local commands that do not affect a cluster, such as:

    • show
    • component subcommands
    • param subcommands

    When running commands against the baseline environment, your code should be able to handle the _ environment name and return appropriate default values.

  7. Manage environment-specific component inclusion and exclusion

    main

    By default, qbec includes all supported files found in the application's components directory. You can refine this list in qbec.yaml to control which components are applied to specific environments:

    • Default Exclusions: You can supply a list of components that are excluded from all environments by default. These must be explicitly included in an environment to be deployed.
    • Explicit Inclusion/Exclusion: You can provide per-environment lists to explicitly include or exclude specific components.
  8. Understand qbec environments

    main

    An environment represents a target cluster, defined by a server URL and an optional defaultNamespace. qbec supports two primary deployment models:

    1. One environment per cluster: Every environment is a separate cluster. You can create cluster-scoped objects and objects in multiple namespaces.
    2. Multiple environments per cluster: Multiple environments share a single cluster but use different namespaces. In this model, you should only create namespace-scoped objects and omit namespace metadata in the object definitions to allow qbec to manage them via the environment's defaultNamespace.
  9. How qbec implements garbage collection

    main

    qbec follows a five-step process to safely identify and remove stale objects while avoiding the accidental deletion of system-managed resources:

    1. Load server metadata: qbec maps all supported group/version/kind combinations to the server's preferred canonical versions, accounting for API aliasing (e.g., extensions to apps).
    2. Determine scope: qbec scans all source objects (ignoring component/kind filters) to compute the list of affected namespaces (including the environment's default namespace) and identifies if any cluster-scoped objects are required.
    3. List remote objects:
      • For a single namespace: Queries that namespace for objects matching the qbec application and environment labels.
      • For multiple namespaces: Performs a cross-namespace list query using label filters (requires permissions to list across namespaces).
      • For cluster-scoped objects: Queries all cluster-scoped objects.
      • Note: Listings use canonical versions and respect kind filters, but ignore component filters.
    4. Handle special cases: qbec filters the remote list to remove objects created by controllers and always removes Endpoints objects from the candidate list.
    5. Delete objects: qbec compares the remote list against the local canonical list, applies component filters to the remaining remote objects, and deletes them one by one in reverse apply order.
  10. How runtime configuration and environments work

    main

    qbec uses the qbec.io/env external variable to determine the current environment.

    • For param sub-commands: qbec strictly uses the runtime configuration file to resolve parameters based on the value of qbec.io/env.
    • For other commands: qbec sets the qbec.io/env variable to the environment name. It is your responsibility to ensure your component code correctly uses this variable to configure itself.

    To simplify the setup of these files and ensure the baseline environment (_) is correctly handled, you can use the qbec init command to scaffold a recommended file organization.

  11. Understand qbec components

    main

    Components are the source code representations of Kubernetes objects. You typically group related objects (e.g., a microservice's Deployment, Service, and ConfigMap) into a single component.

    Components can be loaded from:

    • jsonnet files: These allow for customization of object definitions across different environments.
    • json files
    • yaml files
    • helm charts: qbec can load objects from Helm charts, often using jsonnet libraries to produce them.