The ability to use internal registry is implemented by the registry module.

The internal registry allows for optimizing the downloading and storage of images, as well as helping to ensure availability and fault tolerance for Deckhouse Kubernetes Platform.

Modes of operation with the internal registry

The registry module, which implements internal storage, operates in the following modes:

  • Direct: Enables the internal container image registry. Access to the internal registry is performed via the fixed address registry.d8-system.svc:5001/system/deckhouse. This fixed address allows Deckhouse images to avoid being re-downloaded and components to avoid being restarted when registry parameters change. Switching between modes and registries is done through the deckhouse ModuleConfig. The switching process is automatic (for more details, see the switching examples below) for more information. The architecture of the mode is described in the section Direct Mode Architecture.
  • Unmanaged: Operation without using the internal registry. Access within the cluster is performed directly to the external registry. There are two types of the Unmanaged mode:
    • Configurable: A mode managed via the registry module. Switching between modes and registries is handled through the ModuleConfig of deckhouse. The switch is performed automatically (for more details, see the switching examples below).
    • Non-configurable (deprecated): The default mode. Configuration parameters are set during cluster installation or changed in a running cluster using the (deprecated) helper change registry command.
  • The Direct mode requires using the Containerd or Containerd V2 CRI on all cluster nodes. For CRI setup, refer to the ClusterConfiguration.

Restrictions on working with the internal registry

Working with the internal registry using the registry module has a number of limitations and restrictions concerning installation, operating conditions, and mode switching.

Cluster installation limitations

DKP cluster bootstrap is only supported in non-configurable Unmanaged mode. Registry settings during bootstrap are specified through initConfiguration.

Registry configuration via the deckhouse moduleConfig during DKP cluster bootstrap is not supported.

Operating conditions restrictions

The registry module works under the following conditions:

  • If CRI containerd or containerd v2 is used on the cluster nodes. To configure CRI, refer to the ClusterConfiguration configuration.
  • The cluster is fully managed by DKP. The module will not work in Managed Kubernetes clusters.

Mode switching restrictions

Mode switching restrictions are as follows:

  • For the first switch, migration of user registry configurations must be performed. For more details, see the Registry Module: FAQ section.
  • Switching to the non-configurable Unmanaged mode is only available from the Unmanaged mode. For more details, see the Registry Module: FAQ section.

Examples of switching

Switching to Direct Mode

To switch an already running cluster to Direct mode, follow these steps:

When changing the registry mode or registry parameters, Deckhouse will be restarted.

  1. Before switching, perform the migration to use the registry module.

  2. Make sure the registry module is enabled and running. To do this, execute the following command:

    d8 k get module registry -o wide
    

    Example output:

    NAME       WEIGHT ...  PHASE   ENABLED   DISABLED MESSAGE   READY
    registry   38     ...  Ready   True                         True
    
  3. Make sure all master nodes are in the Ready state and do not have the SchedulingDisabled status, using the following command:

    d8 k get nodes
    

    Example output:

    NAME       STATUS   ROLES                 ...
    master-0   Ready    control-plane,master  ...
    master-1   Ready    control-plane,master  ...
    master-2   Ready    control-plane,master  ...
    

    Example of output when the master node (master-2 in the example) is in the SchedulingDisabled status:

    NAME       STATUS                      ROLES                 ...
    master-0   Ready    control-plane,master  ...
    master-1   Ready    control-plane,master  ...
    master-2   Ready,SchedulingDisabled    control-plane,master  ...
    
  4. Ensure the Deckhouse job queue is empty and contains no errors:

    d8 system queue list
    

    Example output:

    Summary:
    - 'main' queue: empty.
    - 107 other queues (0 active, 107 empty): 0 tasks.
    - no tasks to handle.
    
  5. Set the Direct mode configuration in the ModuleConfig deckhouse. If you’re using a registry other than registry.deckhouse.io, refer to the deckhouse module documentation for correct configuration.

    Configuration example:

    apiVersion: deckhouse.io/v1alpha1
    kind: ModuleConfig
    metadata:
      name: deckhouse
    spec:
      version: 1
      enabled: true
      settings:
        registry:
          mode: Direct
          direct:
            imagesRepo: registry.deckhouse.io/deckhouse/ee
            scheme: HTTPS
            license: <LICENSE_KEY> # Replace with your license key
    
  6. Check the registry switch status in the registry-state secret using this guide.

    Example output:

    conditions:
    # ...
      - lastTransitionTime: "..."
        message: ""
        reason: ""
        status: "True"
        type: Ready
    hash: ..
    mode: Direct
    target_mode: Direct
    

Switching to Unmanaged Mode

To switch an already running cluster to Unmanaged mode, follow these steps:

Changing the registry mode or its parameters will cause Deckhouse to restart.

  1. Before switching, perform the migration to use the registry module.

  2. Make sure the registry module is enabled and running. To do this, execute the following command:

    d8 k get module registry -o wide
    

    Example output:

    NAME       WEIGHT ...  PHASE   ENABLED   DISABLED MESSAGE   READY
    registry   38     ...  Ready   True                         True
    
  3. Ensure the Deckhouse job queue is empty and contains no errors:

    d8 system queue list
    

    Example output:

    Summary:
    - 'main' queue: empty.
    - 107 other queues (0 active, 107 empty): 0 tasks.
    - no tasks to handle.
    
  4. Set the Unmanaged mode configuration in the ModuleConfig deckhouse. If you’re using a registry other than registry.deckhouse.io, refer to the deckhouse module documentation for correct configuration.

    Configuration example:

    apiVersion: deckhouse.io/v1alpha1
    kind: ModuleConfig
    metadata:
      name: deckhouse
    spec:
      version: 1
      enabled: true
      settings:
        registry:
          mode: Unmanaged
          unmanaged:
            imagesRepo: registry.deckhouse.io/deckhouse/ee
            scheme: HTTPS
            license: <LICENSE_KEY> # Replace with your license key
    
  5. Check the registry switch status in the registry-state secret using this guide.

    Example output:

    conditions:
    # ...
      - lastTransitionTime: "..."
        message: ""
        reason: ""
        status: "True"
        type: Ready
    hash: ..
    mode: Unmanaged
    target_mode: Unmanaged
    
  6. If you need to switch back to the old registry management method, refer to the instruction.

This is a deprecated format for registry management.

Migration to the registry module

During the migration, Containerd v1 will switch to the new registry configuration format. Containerd v2 uses the new format by default. For more details, see the section with a description of configuration methods.

For containerd v2

  1. Switch to using the registry module. To do this, specify the Unmanaged mode parameters in the deckhouse moduleConfig. If you are using a registry other than registry.deckhouse.io, refer to the deckhouse module documentation for proper configuration.

    You can view the current registry settings using the following command:

    d8 k -n d8-system exec -it svc/deckhouse-leader -c deckhouse -- deckhouse-controller global values | yq e '.modulesImages.registry' -
    

    Specify this configuration when setting up the Unmanaged mode:

    apiVersion: deckhouse.io/v1alpha1
    kind: ModuleConfig
    metadata:
      name: deckhouse
    spec:
      version: 1
      enabled: true
      settings:
        registry:
          mode: Unmanaged
          unmanaged:
            imagesRepo: registry.deckhouse.io/deckhouse/ee
            scheme: HTTPS
            license: <LICENSE_KEY> # Replace with your license key
    
  2. Wait for the switch to complete. Example status output:

    conditions:
    # ...
      - lastTransitionTime: "..."
        message: ""
        reason: ""
        status: "True"
        type: Ready
    hash: ..
    mode: Unmanaged
    target_mode: Unmanaged
    

For Containerd v1

  • During the switch, containerd v1 will be restarted.
  • During the switch, containerd v1 will be migrated to the new registry configuration scheme.
  • During the switch, custom registry configurations for containerd v1 will be temporarily unavailable.
  1. Make sure that nodes with containerd v1 do not have any custom registry configurations located in the /etc/containerd/conf.d directory.

  2. If configurations are present, you need to migrate to the new registry configuration format in containerd. To do this, add new configuration files to the /etc/containerd/registry.d directory. These configurations will take effect after switching to the registry module. To add configurations, prepare a NodeGroupConfiguration. For more details, see the section with a description of configuration methods. Example:

    apiVersion: deckhouse.io/v1alpha1
    kind: NodeGroupConfiguration
    metadata:
      name: containerd-additional-config-auth.sh
    spec:
      # The step can be arbitrary, as restarting the containerd service is not required
      weight: 0
      bundles:
        - '*'
      nodeGroups:
        - "*"
      content: |
        # Copyright 2023 Flant JSC
        #
        # Licensed under the Apache License, Version 2.0 (the "License");
        # you may not use this file except in compliance with the License.
        # You may obtain a copy of the License at
        #
        #     http://www.apache.org/licenses/LICENSE-2.0
        #
        # Unless required by applicable law or agreed to in writing, software
        # distributed under the License is distributed on an "AS IS" BASIS,
        # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
        # See the License for the specific language governing permissions and
        # limitations under the License.
      
        REGISTRY_URL=private.registry.example
    
        mkdir -p "/etc/containerd/registry.d/${REGISTRY_URL}"
        bb-sync-file "/etc/containerd/registry.d/${REGISTRY_URL}/hosts.toml" - << EOF
        [host]
          [host."https://${REGISTRY_URL}"]
            capabilities = ["pull", "resolve"]
            [host."https://${REGISTRY_URL}".auth]
              username = "username"
              password = "password"
        EOF
    
  3. Apply the NodeGroupConfiguration. Wait until the configuration files appear in the /etc/containerd/registry.d directory on all nodes.

  4. Verify that the configurations are working correctly. To do this, use the following command:

    # For HTTPS:
    ctr -n k8s.io images pull --hosts-dir=/etc/containerd/registry.d/ private.registry.example/registry/path:tag
    
    # For HTTP:
    ctr -n k8s.io images pull --hosts-dir=/etc/containerd/registry.d/ --plain-http private.registry.example/registry/path:tag
    
  5. Switch to using the registry module. To do this, specify the Unmanaged mode parameters in the deckhouse moduleConfig. If you are using a registry other than registry.deckhouse.io, refer to the deckhouse module documentation for proper configuration.

    You can view the current registry settings using the following command:

    d8 k -n d8-system exec -it svc/deckhouse-leader -c deckhouse -- deckhouse-controller global values | yq e '.modulesImages.registry' -
    

    Specify this configuration when setting up the Unmanaged mode:

    apiVersion: deckhouse.io/v1alpha1
    kind: ModuleConfig
    metadata:
      name: deckhouse
    spec:
      version: 1
      enabled: true
      settings:
        registry:
          mode: Unmanaged
          unmanaged:
            imagesRepo: registry.deckhouse.io/deckhouse/ee
            scheme: HTTPS
            license: <LICENSE_KEY> # Replace with your license key
    
  6. After applying, wait for the following message to appear in the switch status:

    Example output:

    conditions:
    # ...
    - lastTransitionTime: "2025-08-13T15:22:34Z"
      message: |
        Check current nodes configuration
        2/2 node(s) Unready:
        - master-0: has custom toml merge containerd configuration
        - worker-5e389be0-578df-s5sm5: has custom toml merge containerd configuration
      reason: Processing
      status: "False"
      type: ContainerdConfigPreflightReady
    

    This message means that there are old registry configurations on the nodes located in the /etc/containerd/conf.d directory. The switch to the new containerd configuration is currently blocked. To allow the switch, you need to remove the old configuration files.

  7. Remove the old configuration files to allow switching to the registry module. To do this, create a NodeGroupConfiguration, for example:

    apiVersion: deckhouse.io/v1alpha1
    kind: NodeGroupConfiguration
    metadata:
      name: containerd-additional-config-auth.sh
    spec:
      # To add a file before the '032_configure_containerd.sh' step
      weight: 0
      bundles:
        - '*'
      nodeGroups:
        - "*"
      content: |
        # Copyright 2023 Flant JSC
        #
        # Licensed under the Apache License, Version 2.0 (the "License");
        # you may not use this file except in compliance with the License.
        # You may obtain a copy of the License at
        #
        #     http://www.apache.org/licenses/LICENSE-2.0
        #
        # Unless required by applicable law or agreed to in writing, software
        # distributed under the License is distributed on an "AS IS" BASIS,
        # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
        # See the License for the specific language governing permissions and
        # limitations under the License.
      
        file="/etc/containerd/conf.d/old-config.toml"
    
        [ -f "$file" ] && rm -f "$file"
    
  8. After removing the old configurations, make sure that the switch has resumed. Example of the switch status:

    conditions:
    # ...
    - lastTransitionTime: "2025-08-13T16:42:09Z"
      message: ""
      reason: ""
      status: "True"
      type: ContainerdConfigPreflightReady
    
  9. Wait for the switch to complete. Example of the switch status:

    conditions:
    # ...
      - lastTransitionTime: "..."
        message: ""
        reason: ""
        status: "True"
        type: Ready
    hash: ..
    mode: Unmanaged
    target_mode: Unmanaged
    

Migration back from the registry module

  • This is a deprecated registry management format.
  • During the switch, containerd v1 will be restarted.
  • During the switch, containerd v1 will be migrated to the legacy registry configuration scheme.
  • During the switch, custom registry configurations for containerd v1 will be temporarily unavailable.
  1. Switch the registry to Unmanaged mode. If you are using a registry other than registry.deckhouse.io, refer to the deckhouse module documentation for proper configuration.

    Example configuration:

    apiVersion: deckhouse.io/v1alpha1
    kind: ModuleConfig
    metadata:
      name: deckhouse
    spec:
      version: 1
      enabled: true
      settings:
        registry:
          mode: Unmanaged
          unmanaged:
            imagesRepo: registry.deckhouse.io/deckhouse/ee
            scheme: HTTPS
            license: <LICENSE_KEY>
    
  2. Check the switch status using the instruction. Example output:

    conditions:
    # ...
    - lastTransitionTime: "..."
      message: ""
      reason: ""
      status: "True"
      type: Ready
    hash: ..
    mode: Unmanaged
    target_mode: Unmanaged
    
  3. Switch the registry to the non-configurable Unmanaged mode. Example configuration:

    apiVersion: deckhouse.io/v1alpha1
    kind: ModuleConfig
    metadata:
      name: deckhouse
    spec:
      version: 1
      enabled: true
      settings:
        registry:
          mode: Unmanaged
    
  4. Check the switch status using the instruction. Example output:

    conditions:
    # ...
    - lastTransitionTime: "..."
      message: ""
      reason: ""
      status: "True"
      type: Ready
    hash: ..
    mode: Unmanaged
    target_mode: Unmanaged
    
  5. If containerd v1 is used and custom registry configurations are applied in the cluster, they must be replaced with the old format. To do this, prepare the registry configurations in the old format. These configurations do not need to be applied at this stage. Example configuration:

    apiVersion: deckhouse.io/v1alpha1
    kind: NodeGroupConfiguration
    metadata:
      name: containerd-additional-config-auth.sh
    spec:
      # To add a file before the '032_configure_containerd.sh' step
      weight: 31
      bundles:
        - '*'
      nodeGroups:
        - "*"
      content: |
        # Copyright 2023 Flant JSC
        #
        # Licensed under the Apache License, Version 2.0 (the "License");
        # you may not use this file except in compliance with the License.
        # You may obtain a copy of the License at
        #
        #     http://www.apache.org/licenses/LICENSE-2.0
        #
        # Unless required by applicable law or agreed to in writing, software
        # distributed under the License is distributed on an "AS IS" BASIS,
        # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
        # See the License for the specific language governing permissions and
        # limitations under the License.
      
        REGISTRY_URL=private.registry.example
    
        mkdir -p /etc/containerd/conf.d
        bb-sync-file /etc/containerd/conf.d/additional_registry.toml - << EOF
        [plugins]
          [plugins."io.containerd.grpc.v1.cri"]
            [plugins."io.containerd.grpc.v1.cri".registry]
              [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
                [plugins."io.containerd.grpc.v1.cri".registry.mirrors."${REGISTRY_URL}"]
                  endpoint = ["https://${REGISTRY_URL}"]
              [plugins."io.containerd.grpc.v1.cri".registry.configs]
                [plugins."io.containerd.grpc.v1.cri".registry.configs."${REGISTRY_URL}".auth]
                  username = "username"
                  password = "password"
                  # OR
                  auth = "dXNlcm5hbWU6cGFzc3dvcmQ="
        EOF
    
  6. Delete the registry-bashible-config secret. This will trigger containerd v1 to switch back to the legacy registry format:

    d8 k -n d8-system delete secret registry-bashible-config
    
  7. After deletion, wait for the switch to complete. Use the instruction to track the progress. Example output:

    conditions:
    # ...
    - lastTransitionTime: "..."
      message: ""
      reason: ""
      status: "True"
      type: Ready
    hash: ..
    mode: Unmanaged
    target_mode: Unmanaged
    
  8. If containerd v1 is used, apply the previously prepared NodeGroupConfiguration with custom registry configurations.

  9. Disable the registry module. Example:

    apiVersion: deckhouse.io/v1alpha1
    kind: ModuleConfig
    metadata:
      name: registry
    spec:
      enabled: false
      settings: {}
      version: 1
    

Check registry mode switch status

The status of the registry mode switch can be retrieved using the following command:

d8 k -n d8-system -o yaml get secret registry-state | yq -C -P '.data | del .state | map_values(@base64d) | .conditions = (.conditions | from_yaml)'

Example output:

conditions:
  - lastTransitionTime: "2025-07-15T12:52:46Z"
    message: 'registry.deckhouse.io: all 157 items are checked'
    reason: Ready
    status: "True"
    type: RegistryContainsRequiredImages
  - lastTransitionTime: "2025-07-11T11:59:03Z"
    message: ""
    reason: ""
    status: "True"
    type: ContainerdConfigPreflightReady
  - lastTransitionTime: "2025-07-15T12:47:47Z"
    message: ""
    reason: ""
    status: "True"
    type: TransitionContainerdConfigReady
  - lastTransitionTime: "2025-07-15T12:52:48Z"
    message: ""
    reason: ""
    status: "True"
    type: InClusterProxyReady
  - lastTransitionTime: "2025-07-15T12:54:53Z"
    message: ""
    reason: ""
    status: "True"
    type: DeckhouseRegistrySwitchReady
  - lastTransitionTime: "2025-07-15T12:55:48Z"
    message: ""
    reason: ""
    status: "True"
    type: FinalContainerdConfigReady
  - lastTransitionTime: "2025-07-15T12:55:48Z"
    message: ""
    reason: ""
    status: "True"
    type: Ready
mode: Direct
target_mode: Direct

The output displays the status of the switch process. Each condition can have a status of True or False, and may contain a message field with additional details.

Description of conditions:

Condition Description
ContainerdConfigPreflightReady State of the containerd configuration preflight check. Verifies there are no custom containerd auth configurations on the nodes.
TransitionContainerdConfigReady State of preparing the containerd configuration for the new mode. Verifies that the configuration contains both the old and new mode settings.
FinalContainerdConfigReady State of finalizing the switch to the new containerd mode. Verifies that the containerd configuration has been successfully applied and contains only the new mode settings.
DeckhouseRegistrySwitchReady State of switching Deckhouse and its components to use the new registry. True means Deckhouse successfully switched and is ready to operate.
InClusterProxyReady State of In-Cluster Proxy readiness. Checks that the In-Cluster Proxy has started successfully and is running.
CleanupInClusterProxy State of cleaning up the In-Cluster Proxy if it is not needed in the selected mode. Verifies that all related resources have been removed.
Ready Overall state of registry readiness in the selected mode. Indicates that all other conditions are met and the module is ready to operate.