Registry v2: Exposing the Registry

By default, use the internal registry service for workloads inside the cluster. Expose Registry v2 only when developer machines, CI systems, or other external clients must push or pull images.

Prerequisites

  • Registry v2 is installed and available.
  • You have permission to update Config/cluster and create or reference TLS Secrets in image-registry-system.
  • The cluster has an Ingress controller that can route traffic to image-registry-system.
  • For a custom host, prepare a DNS record and a TLS certificate whose Subject Alternative Name matches the Registry hostname.

Expose the Default Registry

Enable the default external endpoint in Config/cluster:

kubectl patch configs.imageregistry.operator.alauda.io cluster \
  --type=merge \
  -p '{"spec":{"defaultRoute":true}}'

The Operator renders a Kubernetes Ingress named default-route in image-registry-system.

Verify the generated Ingress and Registry configuration:

kubectl get configs.imageregistry.operator.alauda.io cluster -o yaml
kubectl -n image-registry-system get ingress default-route

Get the generated host:

REGISTRY_HOST="$(
  kubectl -n image-registry-system get ingress default-route \
    -o jsonpath='{.spec.rules[0].host}'
)"

echo "$REGISTRY_HOST"

Expected results:

  • Config/cluster.spec.defaultRoute is true.
  • The default-route Ingress exists in image-registry-system.
  • REGISTRY_HOST contains the hostname assigned to the default route.

If the Ingress certificate is signed by a private CA, add the CA certificate to the trust store of the external client and the OCI client before logging in. Verify the TLS chain from the external client:

openssl s_client \
  -connect "$REGISTRY_HOST:443" \
  -servername "$REGISTRY_HOST" \
  -verify_return_error </dev/null

Write credentials for the generated host:

ac registry login \
  --registry "$REGISTRY_HOST"

Expose a Custom Secure Registry Host

Create or provide a TLS Secret in image-registry-system, then configure Config.spec.routes[].

The TLS Secret must exist in image-registry-system when secretName is set.

The generated Ingress uses the registry service as the backend and sets the backend protocol to HTTPS.

Patch Config/cluster with the custom route. Use a merge patch so other Config/cluster.spec fields, such as storage and pull-secret settings, are not removed. The routes array in this patch replaces the current routes array, so include every custom route that must remain configured:

kubectl patch configs.imageregistry.operator.alauda.io cluster \
  --type=merge \
  -p '{
    "spec": {
      "managementState": "Managed",
      "defaultRoute": false,
      "routes": [
        {
          "name": "public-registry",
          "hostname": "registry.example.com",
          "secretName": "registry-tls"
        }
      ]
    }
  }'
ValueDescription
public-registryRoute name. The Operator uses it as the generated Ingress name.
registry.example.comRegistry hostname reachable by external clients. The DNS record must resolve to the Ingress controller.
registry-tlsTLS Secret in image-registry-system. The certificate Subject Alternative Name must match the Registry hostname.

Verify the configuration and generated Ingress:

kubectl get configs.imageregistry.operator.alauda.io cluster -o yaml
kubectl -n image-registry-system get ingress public-registry
kubectl -n image-registry-system describe ingress public-registry

Expected results:

  • Config/cluster.spec.routes[] contains public-registry.
  • The public-registry Ingress uses registry.example.com.
  • The Ingress references the registry-tls Secret.

Verify TLS trust and login:

openssl s_client \
  -connect registry.example.com:443 \
  -servername registry.example.com \
  -verify_return_error </dev/null

ac registry login \
  --registry registry.example.com

Configure Client Trust

If the Ingress certificate is signed by a private CA, add the CA to each external client's trust store before login and push or pull operations.

For a test client that uses an insecure registry option, scope the insecure setting to the registry host only:

ac registry login \
  --registry registry.example.com \
  --insecure

Configure the OCI client's trust or insecure-registry setting separately if that client also connects to an HTTP endpoint or an untrusted certificate.

Verify External Access

Check the Ingress:

kubectl -n image-registry-system get ingress
kubectl -n image-registry-system describe ingress public-registry

Write credentials from an external client:

ac registry login \
  --registry registry.example.com

Push and pull a test image:

nerdctl tag my-app:latest registry.example.com/team-a/my-app:external-test
nerdctl push registry.example.com/team-a/my-app:external-test
nerdctl pull registry.example.com/team-a/my-app:external-test

Troubleshooting

SymptomCheck
Ingress is missingConfig.spec.defaultRoute, Config.spec.routes[], and Operator logs.
Ingress has no addressIngress controller status, ALB project label, and Ingress events.
TLS handshake failsTLS Secret, client trust store, certificate SANs, and private CA configuration.
Login fails credentials, namespace RoleBinding, OIDC runtime discovery, and Registry logs.
Push or pull fails after loginImage namespace permissions, repository path, storage backend, and Registry readiness.