Kubit logoKubit

What is a Pack?

A Pack is a Kubernetes custom resource for installing and managing a Helm chart. You define the chart, version, and values in a Pack manifest, and Pack Operator keeps the actual cluster state reconciled with that definition.

If you are new to Helm, read Helm and Helm charts in Kubernetes first.

Most users install and manage Packs from Kubchi > Packs in the Kubit panel. This page is the technical reference for the same resource when working with YAML, kubectl, GitOps, or kubit-cli. For panel installation, see Install a Pack in Kubchi.

Pack, chart, and operator relationship

A Helm chart contains an application's templates and default values. Pack selects the chart version and settings to install in a namespace. Pack Operator reads this definition, validates and applies the Helm output, and records the result in Pack status.

Each Pack corresponds to a Helm Release in the same namespace. A spec change may upgrade that release. Before applying a production change, inspect it with kubit helm-diff.

Prerequisites

To work directly with a Pack manifest, you need:

  • Access to a cluster with Pack Operator installed.
  • Permission to read or modify Pack resources in the target namespace.
  • An accessible ClusterPackRepository that provides the chart.
  • Permission to read resources referenced by chart values.

When you use only Kubchi, Kubit prepares many of these prerequisites for the project.

Create a Pack manifest

This example installs the Redis chart from the cluster-wide kubit-paas repository in the my-project namespace. Match the version and values structure to the chart documentation.

apiVersion: k8s.kubit.ir/v1alpha1
kind: Pack
metadata:
  name: redis
  namespace: my-project
spec:
  managed: true
  chart:
    repository:
      kind: ClusterPackRepository
      name: kubit-paas
    name: redis
    version: '0.1.6'
    autoUpgrade: false
  vars: {}
  values: {}

spec.managed is optional. Omitting it is equivalent to spec.managed: true; Pack Operator manages the resource in both cases. Only an explicit spec.managed: false stops operator management. The example states managed: true explicitly.

The main manifest fields are:

FieldPurpose
metadata.namePack and Helm Release name
metadata.namespaceInstallation namespace
spec.managedOptional; omission means true, and only explicit false stops management
spec.chart.repository.kindRepository kind; ClusterPackRepository
spec.chart.repository.nameChart repository resource name
spec.chart.nameChart name in the repository
spec.chart.versionChart version or constraint; when omitted, the newest selectable version is used
spec.chart.autoUpgradeEnables automatic-upgrade checks for a non-exact version
spec.chart.autoUpgradeDelayDelay before automatic upgrade, such as 1h or 1d2h
spec.varsVariables available while rendering values
spec.valuesValues applied over chart defaults

Choose the repository scope

PackRepository is namespaced, and only Packs in that namespace can use it. Choose it when a repository should be available to one project or environment.

ClusterPackRepository is cluster-scoped, so Packs in different namespaces can use it with the required permission. Cluster scope does not make repository credentials public; keep the username and password access-restricted.

Select a chart version

spec.chart.version accepts an exact version or a version constraint. Pack Operator filters repository versions with this constraint and selects the highest matching version. Quote the value so YAML treats it as a string.

version valueAllowed versions
‎'0.1.6'‎Only 0.1.6
‎'~=0.1.6'‎At least 0.1.6 and below 0.2.0
‎'~=1.4'‎At least 1.4 and below 2.0
‎'>=0.1.6,<0.2.0'‎The intersection of both constraints
‎'==0.1.*'‎Every version in the 0.1 branch
‎'>=0.1.6,!=0.1.8,<0.2.0'‎The 0.1 branch from 0.1.6, excluding 0.1.8

Supported operators include ‎==‎, ‎!=‎, ‎~=‎, ‎<‎, ‎<=‎, ‎>‎, and ‎>=‎. Comma-separated constraints must all match. Do not use syntax such as ‎^1.2.3‎ or 1.x || 2.x; those belong to other package managers.

If version is omitted, the highest selectable repository version is used. A range alone does not enable automatic upgrades. Automatic upgrade also requires autoUpgrade: true, a valid autoUpgradeDelay, and a non-exact version. An exact version such as ‎'0.1.6'‎ does not enter the automatic-upgrade queue.

Configure chart values

spec.values contains values applied over the chart defaults. Each key name and type must match the chart's values.yaml or documentation.

This example sets two nested chart values:

spec:
  values:
    replicaCount: 2
    service:
      port: 6379

Pack Operator first renders templates in spec.values, then passes the final values to Helm. Do not copy the complete values structure to change one option. Include only values that differ from chart defaults so changes and chart upgrades are easier to review.

Use templates in values

Strings in spec.values may use Jinja syntax. Expressions such as ‎{{ ... }}‎ produce values, and ‎{% ... %}‎ blocks provide template logic. The main render contexts are:

ContextAvailable data
varsEffective organization, project, and Pack variables
valuesOther values in spec.values
metadataPack name, namespace, labels, and annotations
chartChart name, repository, version, and settings

For example:

spec:
  vars:
    IMAGE_TAG: '7.4'
  values:
    replicaCount: 2
    metrics:
      enabled: true
    image:
      tag: '{{ vars.IMAGE_TAG }}'
    instanceName: '{{ metadata.name }}'
    service:
      port: 6379
      targetPort: '{{ values.service.port }}'
    redisUrl: 'redis://{{ metadata.name }}:{{ values.service.port }}'

Here, image.tag comes from vars.IMAGE_TAG, while service.targetPort and part of redisUrl read values.service.port. Templates can therefore refer to other values as well as vars.

When the entire value is one template expression, the result type is preserved. For example, replicaCount remains a number and metrics.enabled remains a boolean. When the expression is part of a larger string, the result is a string.

Rendering is recursive, so one value may refer to another and key order does not matter. An undefined variable or a cycle such as a -> b -> a causes a validation error.

Useful filters include:

  • to_bool and to_str for type conversion.
  • split to turn a string into a list.
  • to_base64 and from_base64.
  • to_json, from_json, to_yaml, and from_yaml.
  • ternary to select a value from a condition.
  • to_scalar to convert a Kubernetes quantity, such as CPU or memory, to a number.

For example, ‎"true"‎ can be converted to a boolean with ‎'{{ vars.ENABLED | to_bool }}'‎.

Use vars

spec.vars separates template inputs from the chart structure. Defining a variable alone does not change Helm output; consume it from spec.values with an expression such as ‎{{ vars.IMAGE_TAG }}‎.

spec:
  vars:
    IMAGE_TAG: '7.4'
  values:
    image:
      tag: '{{ vars.IMAGE_TAG }}'

Pack Operator merges variables from the organization, project, and Pack. Precedence from lowest to highest is:

  1. Organization variables.
  2. Project variables.
  3. The Pack's spec.vars.

When a name appears at several levels, the value closest to the Pack wins. Variable names are case-sensitive. Use organization or project variables for shared environment settings and spec.vars for installation-specific overrides.

Use Vault in vars and values

Vault encrypts sensitive text before it is stored in a manifest. During rendering, Pack Operator decrypts encrypted values in vars or values with a Vault key from the same namespace.

Create the Vault key in the Pack namespace and encrypt the sensitive value:

printf '%s' "$VAULT_PASSWORD" | kubit -n my-project vault create \
  --vault-id app-vault \
  --vault-password-stdin

printf '%s' "$REDIS_PASSWORD" | kubit -n my-project vault encrypt \
  --vault-id app-vault

Place the complete output of the second command in a variable and use it from values. This example shows only the data shape; replace ENCRYPTED_PAYLOAD with the real command output:

spec:
  vars:
    REDIS_PASSWORD: |
      $KUBIT_VAULT;1.2;AES256;app-vault
      ENCRYPTED_PAYLOAD
  values:
    auth:
      password: '{{ vars.REDIS_PASSWORD }}'

The Vault key must exist in the Pack namespace, and the executing identity or Pack Operator must be allowed to read it. Do not store decrypted text in a manifest, Git, CI logs, or support tickets. After rendering, Helm uses the value for installation, so also restrict access to Helm release Secrets and resources created by the chart.

Use Vault commands in kubit-cli to create, list, and encrypt values. For panel operations, see Manage Vault in Kubchi.

Control Pack management

When spec.managed is absent, Pack Operator treats it as true and manages the Pack. To pause reconciliation, set it explicitly to false:

spec:
  managed: false

The operator then stops validation, apply, and automatic upgrades, and the Pack phase becomes Unmanaged. Running workloads and the existing Helm Release are not removed. Setting it back to true reconciles the Pack with spec again.

This option pauses management and does not fix errors. While management is disabled, manual changes outside Pack may drift from the manifest and be overwritten when management resumes. Pack deletion also behaves differently; read Delete a Pack first.

Pack exports

A chart author can define Pack outputs in pack-metadata.yaml. See Define Pack exports in a chart for the complete structure. Exports are not part of Pack spec; they may expose an application version, service address, image name, resource usage, or generated value. A chart may also read an export from a Secret, ConfigMap, or another resource in the same namespace.

Only outputs marked for status in chart metadata are stored in status.exports. Use kubit pack exports to read every defined output. The simple format is useful for quick inspection, while dict and list provide structured output.

Some outputs are sensitive. The sensitive flag tells consumers that the output is sensitive, but it does not replace access control. Do not store sensitive output in logs, pipelines, tickets, or Git.

Pack metadata and dependencies

metadata.name, metadata.namespace, labels, and annotations are available to templates and can be used to build environment-dependent names or settings. Keep operational names and annotations stable and documented to avoid unintended behavior.

If a Pack depends on a Secret or ConfigMap, declare the dependency with the restart-on-resource-change annotation so the operator can run the required rollout or restart. For manual operations, use force-upgrade and rollout-restart, and do not modify internal operator annotations directly.

Apply and inspect a Pack

Apply the manifest with kubectl:

kubectl apply -f redis.pack.yaml

Then inspect Pack status and events:

kubectl -n my-project get pack redis
kubectl -n my-project describe pack redis

A successful result uses the Applied phase. The main phases are:

  • Applied: the desired Pack state was applied.
  • Failed: validation or apply failed.
  • Unmanaged: spec.managed is disabled and the operator does not change the Pack.

The main status fields are:

FieldPurpose
status.currentApplied state, including exact chart version, chart and values digests, revision, Helm status, and last deployment time
status.desiredTarget state during processing or failure; cleared after a successful apply
status.errorLatest reportable validation, migration, or apply error
status.exportsOutputs selected by chart metadata for storage in status

When status.desired remains beside a Failed phase, it shows the version and settings the operator attempted to reach. Compare it with status.current to diagnose the difference. All status fields are operator output and must not be edited manually.

Migrate between chart versions

A chart may provide migration rules in pack-migrations.yaml. To create this file, read Migrate Packs between chart versions. A migration is selected by repository, chart name, source version, and target version, and can convert the chart version, vars, or values to the new structure.

Before a manual upgrade, preview the result with kubit pack migrate, review the diff, and record the change only in the source manifest or Git repository. The ‎--inline‎ option changes the input file, so use it only on a versioned file or a recoverable copy.

During an automatic upgrade, the operator first checks for a matching migration. If none matches or execution fails, the normal automatic-upgrade path continues. Test migrations before publishing the chart; do not rely on migration failure to stop an upgrade.

Update a Pack

To change configuration, edit spec.vars or spec.values and apply the manifest again. Pack Operator validates the change, then updates the Helm release.

To record production changes in Git, store the manifest in a repository and use Kubchi GitOps. GitOps is optional and is not required to use Pack. Migration preview rules are covered in Migrate between chart versions.

Automatic upgrade runs only when the feature is enabled in the operator, autoUpgrade is true, autoUpgradeDelay is valid, and the chart version is not exact. After a compatible version is published and the delay passes, the operator checks migrations and runs the upgrade.

Delete a Pack

When spec.managed is true, deleting the Pack resource starts removal of the Helm release and its managed resources:

kubectl -n my-project delete pack redis

Check persistent data and chart volume-retention policies before deletion. When spec.managed is false, deleting the Pack does not uninstall its Helm Release or resources. For managed deletion, set managed back to true, wait for Applied, then delete the resource. Delete an unmanaged Pack directly only when you intend to manage the remaining release outside Pack.

Do not manually remove the Pack finalizer to force deletion; this can leave Helm resources without an owner. If deletion does not finish, inspect events and status.error, then contact Kubit support.

Related guides

Pack reference | Documentations | Kubit