Private image scanning

Set up access to private or managed container image registries.

This guide explains how to configure Kvisor to scan images from private registries, providing you with comprehensive vulnerability assessments across all container images in your environment.

Overview

By default, the Kvisor agent can scan both public and private images running on nodes managed by the Cast AI cluster controller. You'll need to configure access to your private registries to get a complete picture of vulnerabilities across your entire environment.

Kvisor supports scanning images from any private registry using image pull secrets, as well as directly integrating with managed registry services from major cloud providers:

  • Amazon Elastic Container Registry (ECR) for AWS EKS clusters
  • Google Container Registry (GCR) and Artifact Registry for GKE clusters
  • Azure Container Registry (ACR) for AKS clusters

Configuration methods

Private registries with image pull secret

To enable scanning of images from a private registry using an image pull secret:

  1. Create an image pull secret in the castai-agent namespace:
kubectl -n castai-agent create secret docker-registry [secret-name] \
  --docker-server=[registry-server] \
  --docker-username=[registry-username] \
  --docker-password=[registry-password]

The [registry-server] can be specified in one of these formats:

  • {registry} (e.g., docker.io)
  • {registry}/{namespace} (e.g., docker.io/castai)
  • {registry}/{namespace}/{repository} (e.g., docker.io/castai/agent)

Example for GitLab private images:

kubectl -n castai-agent create secret docker-registry [secret-name] \
  --docker-server=https://registry.gitlab.com \
  --docker-username=registry-user \
  --docker-password=registry-password
  1. Configure Kvisor to use this image pull secret:
helm upgrade castai-kvisor castai-helm/castai-kvisor -n castai-agent \
  --reset-then-reuse-values --set controller.extraArgs.image-private-registry-pull-secret=[secret-name]

Working with multiple registries

You can configure a single image pull secret to scan images from multiple registries:

cat <<EOF | kubectl apply -n castai-agent -f -
apiVersion: v1
kind: Secret
metadata:
  name: <secret-name>
type: kubernetes.io/dockerconfigjson
stringData:
  .dockerconfigjson: |
    {
      "auths":
        {
          "docker.io": {
            "username":"user1",
            "password":"password1",
            "auth":"auth1=="
          },
          "docker.io/my-repository": {
            "username":"user2",
            "password":"password2",
            "auth":"auth2=="
          },
          "registry.gitlab.com": {
            "username":"user3",
            "password":"password3",
            "auth":"auth3=="
          }
        }
    }
EOF

To generate a configuration for individual registries, use:

kubectl -n castai-agent create secret docker-registry [secret-name] \
  --docker-server=[registry-server] \
  --docker-username=[registry-username] \
  --docker-password=[registry-password] \
  --dry-run=client \
  --output go-template='{{ index .data ".dockerconfigjson" | base64decode }}' | jq '.auths'

Cloud provider registry integration

Amazon Elastic Container Registry (ECR)

For AWS environments, Kvisor can authenticate directly with ECR:

  1. Enable OIDC provider for your EKS cluster:
eksctl utils associate-iam-oidc-provider \
  --cluster <cluster_name> \
  --approve
  1. Create a service account:
kubectl create serviceaccount castai-kvisor-ecr -n castai-agent
  1. Attach an IAM policy for ECR access:
eksctl create iamserviceaccount \
  --name castai-kvisor-ecr \
  --namespace castai-agent \
  --cluster <cluster_name> \
  --attach-policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly \
  --approve \
  --override-existing-serviceaccounts
  1. Configure Kvisor to use this service account:
helm upgrade castai-kvisor castai-helm/castai-kvisor -n castai-agent \
  --reuse-values --set controller.extraArgs.image-scan-service-account=castai-kvisor-ecr

Microsoft Azure Container Registry (ACR)

For Azure environments:

  1. Enable OIDC provider and Workload Identity:
az aks update -g <resource_group> -n <cluster_name> --enable-oidc-issuer --enable-workload-identity
  1. Create a Managed Identity:
az identity create --name <identity_name> --resource-group <resource_group> --location <location> --subscription <subscription>
export IDENTITY_CLIENT_ID="$(az identity show --resource-group <resource_group> --name <identity_name> --query 'clientId' -o tsv)"
  1. Assign ACR permissions:
ACR_ID=$(az acr show --name <acr_name> --resource-group <resource_group> --query "id" --output tsv)
az role assignment create --assignee $IDENTITY_CLIENT_ID --role "AcrPull" --scope $ACR_ID
  1. Create a Kubernetes service account linked to this identity:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    azure.workload.identity/client-id: "${IDENTITY_CLIENT_ID}"
  name: castai-kvisor-aks
  namespace: castai-agent
EOF
  1. Create a federated identity credential:
export AKS_OIDC_ISSUER="$(az aks show -n <cluster_name> -g <resource_group> --query "oidcIssuerProfile.issuerUrl" -o tsv)"

az identity federated-credential create --name <federated_identity_name> \
  --identity-name <identity_name> \
  --resource-group <resource_group> \
  --issuer "${AKS_OIDC_ISSUER}" \
  --subject system:serviceaccount:castai-agent:castai-kvisor-aks \
  --audience api://AzureADTokenExchange
  1. Configure Kvisor to use this service account:
helm upgrade castai-kvisor castai-helm/castai-kvisor -n castai-agent \
  --reset-then-reuse-values --set controller.extraArgs.image-scan-service-account=castai-kvisor-aks

Google Container Registry/Artifact Registry

No additional configuration is required for GKE clusters to scan images from Google Container Registry or Artifact Registry.

Troubleshooting

If you encounter issues with private image scanning:

Check for authentication errors in the Kvisor logs

kubectl logs -l app.kubernetes.io/name=castai-kvisor-controller -n castai-agent | grep -i "authentication\|auth\|registry"

Verify your secrets

Ensure your image pull secrets contain the correct credentials:

kubectl get secret <secret-name> -n castai-agent -o jsonpath='{.data.\.dockerconfigjson}' | base64 --decode

Check service account configuration

For cloud provider registry integration, verify that the service account is correctly configured:

kubectl get serviceaccount <service-account-name> -n castai-agent -o yaml

Manually test registry access

You can test registry access using a temporary pod:

kubectl run registry-test --image=busybox --rm -it --command -- /bin/sh -c "echo 'Registry access test'"

If the image pulls successfully, your credentials are likely configured correctly.

Next Steps

After configuring private image scanning: