Helm chart

The ocync Helm chart supports three deployment modes, selected via the mode value.

Installation

helm install ocync oci://public.ecr.aws/clowdhaus/ocync --version 0.1.0

Deployment modes

ModeK8s resourceUse case
watch (default)DeploymentContinuous sync with health endpoints
cronjobCronJobScheduled sync every N minutes
jobJobOne-shot sync for CI or seeding

CronJob mode

# values.yaml
mode: cronjob
cronjob:
  schedule: "*/15 * * * *"
  concurrencyPolicy: Forbid

image:
  repository: public.ecr.aws/clowdhaus/ocync
  tag: latest-fips

serviceAccount:
  create: true
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/ocync

resources:
  requests:
    cpu: 500m
    memory: 128Mi
    ephemeral-storage: 1Gi
  limits:
    memory: 256Mi
    ephemeral-storage: 2Gi

config:
  registries:
    chainguard:
      url: cgr.dev
    ecr:
      url: 123456789012.dkr.ecr.us-east-1.amazonaws.com
  target_groups:
    default: [ecr]
  defaults:
    source: chainguard
    targets: default
    tags:
      glob: "*"
      latest: 20
      sort: semver
  mappings:
    - from: chainguard/nginx
      to: nginx

The process is I/O-bound (single-threaded tokio runtime), not compute-bound. The cpu: 500m request gives the pod enough scheduling weight for Karpenter to steer toward network-optimized instances.

Watch mode

mode: watch
watch:
  interval: 300
  healthPort: 8080

Exposes /healthz (liveness) and /readyz (readiness) endpoints. See observability for logging configuration.

watch.healthBind defaults to 0.0.0.0 so kubelet probes (which target the pod IP) succeed without user override. Set watch.healthBind: "::" on IPv6-only clusters.

Job mode

mode: job

Runs a single sync and exits. Useful for CI pipelines or initial registry seeding.

Authentication

The ocync container uses ambient credentials from the pod’s environment, so there are no secrets to manage. The method depends on the Kubernetes platform.

Amazon EKS

EKS supports two mechanisms for granting IAM credentials to pods. Both work with ocync — choose based on your cluster’s configuration.

EKS Pod Identity (recommended for new clusters):

serviceAccount:
  create: true

Associate the service account with an IAM role using the EKS Pod Identity Agent:

aws eks create-pod-identity-association \
  --cluster-name my-cluster \
  --namespace default \
  --service-account ocync \
  --role-arn arn:aws:iam::123456789012:role/ocync

IAM Roles for Service Accounts (IRSA):

serviceAccount:
  create: true
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/ocync

In both cases, the IAM role needs permissions to pull from source and push to target repositories:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "EcrAuth",
      "Effect": "Allow",
      "Action": "ecr:GetAuthorizationToken",
      "Resource": "*"
    },
    {
      "Sid": "EcrPull",
      "Effect": "Allow",
      "Action": [
        "ecr:BatchGetImage",
        "ecr:GetDownloadUrlForLayer",
        "ecr:BatchCheckLayerAvailability"
      ],
      "Resource": "arn:aws:ecr:*:123456789012:repository/*"
    },
    {
      "Sid": "EcrPush",
      "Effect": "Allow",
      "Action": [
        "ecr:PutImage",
        "ecr:InitiateLayerUpload",
        "ecr:UploadLayerPart",
        "ecr:CompleteLayerUpload"
      ],
      "Resource": "arn:aws:ecr:*:123456789012:repository/*"
    }
  ]
}

Scope the Resource ARNs to specific repositories in production.

Google GKE

GKE uses Workload Identity Federation to bind a Kubernetes service account to a Google Cloud service account:

serviceAccount:
  create: true
  annotations:
    iam.gke.io/gcp-service-account: ocync@my-project.iam.gserviceaccount.com

Bind the Kubernetes service account to the GCP service account:

gcloud iam service-accounts add-iam-policy-binding \
  ocync@my-project.iam.gserviceaccount.com \
  --role roles/iam.workloadIdentityUser \
  --member "serviceAccount:my-project.svc.id.goog[default/ocync]"

The GCP service account needs roles/artifactregistry.reader on source repositories and roles/artifactregistry.writer on targets.

Azure AKS

AKS uses Workload Identity to federate a Kubernetes service account with an Azure managed identity:

serviceAccount:
  create: true
  annotations:
    azure.workload.identity/client-id: <managed-identity-client-id>
  labels:
    azure.workload.identity/use: "true"

Create the federated credential:

az identity federated-credential create \
  --name ocync-federated \
  --identity-name ocync-identity \
  --resource-group my-rg \
  --issuer "$(az aks show -n my-cluster -g my-rg --query oidcIssuerProfile.issuerUrl -o tsv)" \
  --subject system:serviceaccount:default:ocync

Grant AcrPush on the target ACR and AcrPull on source ACR instances.

Values reference

See the chart’s values.yaml for the full set of configurable values.