Qbec
repository·main·Indexed 41 days ago
https://github.com/splunk/qbecA 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.
What's inside Qbec
- 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).
What is Qbec?
mainQbec is a CLI tool designed to create Kubernetes objects across multiple Kubernetes clusters or namespaces. It uses jsonnet for configuration and is conceptually similar to tools likekubecfgandksonnet.Filter objects using component, kind, and namespace filters
mainMost 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
-cresults 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 secretand-k secretsboth targetSecret).- Include:
-k kind1 -k kind2 - Exclude:
-K kind1 -K kind2 - Note: Abbreviations like
deployfordeploymentare 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|falseto explicitly control this behavior. - Note: Using namespace/cluster filters requires cluster access to retrieve metadata, even for commands like
qbec showthat normally do not require it.
- Include:
Use the --app-tag flag for scoped branch builds
mainThe
--app-tagcommand-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. IfnamespaceTagSuffixis enabled, this value can be automatically suffixed with the tag.
qbec apply --app-tag=foo envHow garbage collection works in qbec
mainGarbage collection (GC) is enabled by default in qbec. It does not require special flags like--gc-tagto 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.Structure of the runtime parameters object
mainWhen using
paramsub-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-levelcomponentskey, 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" } } }Use the baseline environment for local operations
mainqbec 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:showcomponentsubcommandsparamsubcommands
When running commands against the baseline environment, your code should be able to handle the
_environment name and return appropriate default values.Manage environment-specific component inclusion and exclusion
mainBy default, qbec includes all supported files found in the application's
componentsdirectory. You can refine this list inqbec.yamlto 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.
Understand qbec environments
mainAn environment represents a target cluster, defined by a server URL and an optional
defaultNamespace. qbec supports two primary deployment models:- One environment per cluster: Every environment is a separate cluster. You can create cluster-scoped objects and objects in multiple namespaces.
- 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.
How qbec implements garbage collection
mainqbec follows a five-step process to safely identify and remove stale objects while avoiding the accidental deletion of system-managed resources:
- Load server metadata: qbec maps all supported group/version/kind combinations to the server's preferred canonical versions, accounting for API aliasing (e.g.,
extensionstoapps). - Determine scope: qbec scans all source objects (ignoring component/kind filters) to compute the list of affected namespaces (including the environment's
defaultnamespace) and identifies if any cluster-scoped objects are required. - 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
kindfilters, but ignorecomponentfilters.
- Handle special cases: qbec filters the remote list to remove objects created by controllers and always removes
Endpointsobjects from the candidate list. - Delete objects: qbec compares the remote list against the local canonical list, applies
componentfilters to the remaining remote objects, and deletes them one by one in reverse apply order.
- Load server metadata: qbec maps all supported group/version/kind combinations to the server's preferred canonical versions, accounting for API aliasing (e.g.,
How runtime configuration and environments work
mainqbec uses the
qbec.io/envexternal variable to determine the current environment.- For
paramsub-commands: qbec strictly uses the runtime configuration file to resolve parameters based on the value ofqbec.io/env. - For other commands: qbec sets the
qbec.io/envvariable 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 theqbec initcommand to scaffold a recommended file organization.- For
Understand qbec components
mainComponents 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.