|Index|SUSE Telco Cloud Documentation|Setting up the management cluster|Image preparation for air-gap environments

30 Image preparation for air-gap environments

This section describes how to prepare the image for air-gap environments showing only the differences from the previous sections. The following changes to the previous section (Image preparation for connected environments (Chapter 29, Image preparation for connected environments)) are required to prepare the image for air-gap environments:

  • The mgmt-cluster.yaml file must be modified to include the embeddedArtifactRegistry section with the images field set to all container images to be included into the EIB output image.

  • The custom/scripts/99-register.sh script must be removed when use an air-gap environment.

To include the SUSE Private Registry in the management cluster for future downstream deployments, the following changes are also required:

  • The mgmt-cluster.yaml file must be modified to include the helm chart section as well as the embedded artifacts with the new images to include them in the EIB output image.

  • The kubernetes/values and kubernetes/manifests folders must include additional manifest files to properly configure the SUSE Private Registry in the management cluster.

Note
Note

You will need certain credentials, which can be retrieved by following the official SUSE Private Registry documentation.

30.1 Modifications in the definition file

The mgmt-cluster.yaml file must be modified to include the embeddedArtifactRegistry section. In this section the images field must contain the list of all container images to be included in the output image.

Note
Note

The following example mgmt-cluster.yaml file includes both the embeddedArtifactRegistry section and the SUSE Private Registry feature. Make sure to the listed images contain the component versions you need.

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.2-Base-SelfInstall-GM.install.iso
  outputImageName: eib-mgmt-cluster-image.iso
operatingSystem:
  isoConfiguration:
    installDevice: /dev/sda
  users:
  - username: root
    encryptedPassword: $ROOT_PASSWORD
  packages:
    packageList:
    - jq
    sccRegistrationCode: $SCC_REGISTRATION_CODE
kubernetes:
  version: v1.35.3+rke2r3
  helm:
    charts:
      - name: private-registry-helm
        createNamespace: true
        installationNamespace: kube-system
        repositoryName: privateregistry
        targetNamespace: suse-private-registry
        valuesFile: privateregistry.yaml
        version: 1.1.1
      - name: cert-manager
        repositoryName: jetstack
        version: 1.20.1
        targetNamespace: cert-manager
        valuesFile: certmanager.yaml
        createNamespace: true
        installationNamespace: kube-system
      - name: longhorn
        version: 1.11.1
        repositoryName: rancher-application-collection
        targetNamespace: longhorn-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: longhorn.yaml
      - name: metallb
        version: 306.0.2+up0.15.3
        targetNamespace: metallb-system
        createNamespace: true
        repositoryName: suse-edge-charts
        installationNamespace: kube-system
      - name: metal3
        version: 306.0.26+up0.15.0
        repositoryName: suse-edge-charts
        targetNamespace: metal3-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: metal3.yaml
      - name: rancher-turtles-providers
        version: 306.0.6+up0.26.1
        repositoryName: suse-edge-charts
        targetNamespace: cattle-turtles-system
        createNamespace: true
        installationNamespace: kube-system
      - name: neuvector-crd
        version: 109.0.1+up2.8.13
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: neuvector
        version: 109.0.1+up2.8.13
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: rancher
        version: 2.14.1
        repositoryName: rancher-prime
        targetNamespace: cattle-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: rancher.yaml
    repositories:
      - name: jetstack
        url: https://charts.jetstack.io
      - name: rancher-charts
        url: https://charts.rancher.io/
      - name: suse-edge-charts
        url: oci://registry.suse.com/edge/charts
      - name: rancher-prime
        url: https://charts.rancher.com/server-charts/prime
      - name: rancher-application-collection
        url: oci://dp.apps.rancher.io/charts
        authentication:
          username: $\{APPS.RANCHER.IO_USERNAME\}
          password: $\{APPS.RANCHER.IO_ACCESS_TOKEN\}
      - name: privateregistry
        authentication:
          username: ${PRIVATE_REGISTRY_USERNAME}
          password: ${PRIVATE_REGISTRY_PASSWORD}
        plainHTTP: false
        skipTLSVerify: false
        url: oci://registry.suse.com/private-registry
    network:
      apiHost: $API_HOST
      apiVIP: $API_VIP
    nodes:
    - hostname: mgmt-cluster-node1
      initializer: true
      type: server
#   - hostname: mgmt-cluster-node2
#     type: server
#   - hostname: mgmt-cluster-node3
#     type: server
embeddedArtifactRegistry:
  registries:
    - uri: dp.apps.rancher.io
      authentication:
        username: $\{APPS.RANCHER.IO_USERNAME\}
        password: $\{APPS.RANCHER.IO_ACCESS_TOKEN\}
    - uri: registry.suse.com
      authentication:
        username: ${PRIVATE_REGISTRY_USERNAME}
        password: ${PRIVATE_REGISTRY_PASSWORD}
  images:
    - name: registry.suse.com/private-registry/harbor-core:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-jobservice:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-portal:1.1.1-1.20
    - name: registry.suse.com/private-registry/harbor-registry:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-registryctl:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-trivy-adapter:1.1.1-1.24
    - name: registry.rancher.com/rancher/hardened-cluster-autoscaler:v1.10.3-build20260206
    - name: registry.rancher.com/rancher/hardened-cni-plugins:v1.9.0-build20260309
    - name: registry.rancher.com/rancher/hardened-coredns:v1.14.2-build20260310
    - name: registry.rancher.com/rancher/hardened-k8s-metrics-server:v0.8.1-build20260206
    - name: registry.rancher.com/rancher/hardened-multus-cni:v4.2.4-build20260310
    - name: registry.rancher.com/rancher/hardened-traefik:v3.6.10-build20260309
    - name: registry.rancher.com/rancher/klipper-helm:v0.9.14-build20260309
    - name: registry.rancher.com/rancher/mirrored-cilium-cilium:v1.19.1
    - name: registry.rancher.com/rancher/mirrored-cilium-operator-generic:v1.19.1
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-attacher:4.11.0-11.1
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-provisioner:5.3.0-11.1
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-resizer:2.1.0-4.1
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-snapshotter:8.5.0-11.1
    - name: dp.apps.rancher.io/containers/kubernetes-csi-livenessprobe:2.18.0-11.1
    - name: dp.apps.rancher.io/containers/kubernetes-csi-node-driver-registrar:2.16.0-11.1
    - name: dp.apps.rancher.io/containers/longhorn-backing-image-manager:1.11.1-1.2
    - name: dp.apps.rancher.io/containers/longhorn-engine:1.11.1-1.1
    - name: dp.apps.rancher.io/containers/longhorn-instance-manager:1.11.1-1.1
    - name: dp.apps.rancher.io/containers/longhorn-manager:1.11.1-1.2
    - name: dp.apps.rancher.io/containers/longhorn-share-manager:1.11.1-1.1
    - name: dp.apps.rancher.io/containers/longhorn-ui:1.11.1-1.2
    - name: dp.apps.rancher.io/containers/rancher-support-bundle-kit:0.0.81-7.3
    - name: registry.rancher.com/rancher/mirrored-sig-storage-snapshot-controller:v8.2.0
    - name: registry.rancher.com/rancher/neuvector-compliance-config:1.0.12
    - name: registry.rancher.com/rancher/neuvector-controller:5.5.1
    - name: registry.rancher.com/rancher/neuvector-enforcer:5.5.1
    - name: registry.rancher.com/rancher/nginx-ingress-controller:v1.14.5-hardened1
    - name: registry.rancher.com/rancher/cluster-api-addon-provider-fleet:v0.14.1
    - name: registry.rancher.com/rancher/fleet-agent:v0.15.1
    - name: registry.rancher.com/rancher/fleet:v0.15.1
    - name: registry.rancher.com/rancher/rancher-webhook:v0.10.4
    - name: registry.rancher.com/rancher/turtles:v0.26.1
    - name: registry.rancher.com/rancher/rancher:v2.14.1
    - name: registry.rancher.com/rancher/shell:v0.1.24
    - name: registry.rancher.com/rancher/system-upgrade-controller:v0.19.1
    - name: registry.rancher.com/rancher/cluster-api-controller:v1.12.2
    - name: registry.suse.com/rancher/cluster-api-provider-metal3:v1.12.3
    - name: registry.rancher.com/rancher/cluster-api-provider-rke2-bootstrap:v0.24.3
    - name: registry.rancher.com/rancher/cluster-api-provider-rke2-controlplane:v0.24.3
    - name: registry.rancher.com/rancher/ip-address-manager:v1.12.3
    - name: registry.rancher.com/rancher/kubectl:v1.35.2
    - name: registry.rancher.com/rancher/mirrored-cluster-api-controller:v1.12.2
    - name: registry.rancher.com/rancher/scc-operator:v0.4.0
    - name: registry.rancher.com/rancher/kubectl:v1.33.1
    - name: registry.suse.com/edge/3.6/ironic-python-agent:3.0.8

30.2 Modifications in the custom folder

  • The custom/scripts/99-register.sh script must be removed when using an air-gap environment. As you can see in the directory structure, the 99-register.sh script is not included in the custom/scripts folder.

30.3 Modifications in the kubernetes folder

  • You need to modify the ${MGMT_CLUSTER_REGISTRY_IP} with a reserved static IP for the SUSE Private Registry in the following file:

    1. kubernetes/manifests/metallb-registry.yaml

      apiVersion: metallb.io/v1beta1
      kind: L2Advertisement
      metadata:
        name: private-registry
        namespace: metallb-system
      spec:
        ipAddressPools:
        - private-registry-pool
      ---
      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        name: private-registry-pool
        namespace: metallb-system
      spec:
        addresses:
        - ${MGMT_CLUSTER_REGISTRY_IP}/32
        serviceAllocation:
          namespaces:
          - suse-private-registry
    2. kubernetes/helm/values/privateregistry.yaml

      core:
        secretName: suse-registry-tls
      expose:
        tls:
          certSource: secret
          enabled: true
          secret:
            secretName: suse-registry-tls
        type: loadBalancer
      externalURL: https://${MGMT_CLUSTER_REGISTRY_IP}
      persistence:
        persistentVolumeClaim:
          registry:
            size: 20Gi
  • The kubernetes/manifests/suse-private-registry-creds.yaml must be created with the following content:

apiVersion: v1
kind: Secret
metadata:
  name: suse-registry
  namespace: suse-private-registry
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: ${DOCKER_CONFIG_JSON_BASE64}
---
apiVersion: v1
kind: Secret
metadata:
    name: suse-registry-tls
    namespace: suse-private-registry
type: kubernetes.io/tls
data:
    tls.crt: ${TLS_CRT_BASE64}
    tls.key: ${TLS_KEY_BASE64}

You need to modify the ${DOCKER_CONFIG_JSON_BASE64}, ${TLS_CRT_BASE64} and ${TLS_KEY_BASE64}. To correctly configure the docker config json (base64), you can do the following:

# ${DOCKER_CONFIG_JSON_BASE64} CONTENT
echo -n '{"auths":{"<MGMT_CLUSTER_REGISTRY_IP>":{"username":"<USERNAME>","password":"<PASSWORD>","auth":"<AUTH>"}}}' | base64 -w 0

where the IP is the same as the previously configured ${MGMT_CLUSTER_REGISTRY_IP}, and the <USERNAME>, and <PASSWORD> values can be retrieved from the SUSE Private Registry official documentation; the <AUTH> value set in the auth field is the base64 encoding of the <USERNAME>:<PASSWORD> concatenation.

To set the content of the tls.crt and tls.key fields in the suse-registry-tls Secret manifest above, you can generate your own TLS self-signed certificate and related private key by running the following commands:

# Generate a self-signed certificate and key
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365 -nodes

# Convert them to base64 for the suse-private-registry-creds.yaml file
cat cert.pem | base64 -w 0
cat key.pem | base64 -w 0