Registry access
The registry is yours. AstroPulse never stores registry logins and never pushes images, by design: we want every cluster to pull keyless, with the identity it already has in its cloud. A pull Secret is the fully supported fallback for any registry or cluster with no keyless path.
Where your cluster runs decides how it pulls. Find yours below. How keyless access works, and access for your app to buckets and queues, is on Keyless cloud access.
The node pulls the image, not your application
Kubernetes pulls an image with the node's identity, or with a pull Secret named on the pod or its service account. Your application's own cloud identity, bound to its ServiceAccount, lets the running app call your cloud, but it never pulls the app's image. So for a private registry, give the nodes read access, or use a pull Secret.
Vulnerability Scanning is the exception: it reads images through the registry's API as its own ServiceAccount, so it needs its own grant (EKS, GKE, AKS).
When you need it
- Your images live in your cloud's registry and you want to know whether the cluster can already pull them.
- Your images live in a registry the cluster can't reach on its own: Docker Hub, GitHub (
ghcr.io), Quay, Harbor, or a registry in another account or cloud. - An application is stuck pulling its image and you want to know which way of pulling applies.
Local kind cluster
Three ways, simplest first.
Load the image, no registry
Load the image you built straight into the kind nodes, then deploy it with an Image source and a pinned tag:
kind load docker-image acme/latency-local:v1.0.0 --name <kind-cluster-name>
Use a fixed tag, never latest. With a fixed tag the node uses the image it already has. With latest, Kubernetes always tries to pull it from a registry. The pod's events show it:
Container image "acme/latency-local:v1.0.0" already present on machine and can be accessed by the pod
If kind load fails with content digest ... not found, the image is a multi-platform image pulled from a registry. Build it locally, or rebuild it FROM that image, and load the result.
A registry login on the nodes
To pull a private registry from every namespace, give the kind nodes a registry login once, when you create the cluster. Mount a Docker config.json into the kubelet:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraMounts:
- containerPath: /var/lib/kubelet/config.json
hostPath: /path/to/config.json
The file needs the login itself, base64 in auths. A config.json that uses credsStore or credHelpers doesn't work inside the node. The kind guide shows how to make a plain one: Private registries.
With the login on the node, a new namespace with no Secret pulls the image on the first try:
Successfully pulled image "localhost:31500/acme/latency:v1.0.0" in 796ms (796ms including waiting). Image size: 4772337 bytes.
A pull Secret
Works on an existing kind cluster too. See Any registry, any cluster: a pull Secret.
A cluster AstroPulse creates
It pulls keyless from its own cloud's registry, with nothing to connect:
- Amazon EKS: ECR in the cluster's own AWS account. For ECR in other accounts, list them under Image registries in other AWS accounts (ECR) on the wizard's network step, then allow the cluster's node roles in each account's repository policy. See Let EKS nodes pull from an ECR repository in another AWS account.
- Google GKE: Artifact Registry in the cluster's own project. For another project, see Let GKE nodes pull from an Artifact Registry repository in another project.
- Azure AKS: the registries listed under Container registries (ACR) on the wizard's network step. AstroPulse grants the cluster AcrPull on each. See Let AKS nodes pull from an Azure Container Registry.
Any other registry, such as Docker Hub or GitHub: a pull Secret, with the namespace named first.
On a cluster with private nodes, every new node pulls its images through the NAT gateway, which the cloud bills per GB. Docker Hub, GitHub (ghcr.io) and any registry outside your account go that way. On an EKS cluster AstroPulse creates, ECR in the cluster's region skips the NAT gateway through the S3 gateway endpoint. The numbers are in Cut model download cost.
Your own cluster, registered with the agent
- On a cloud: pull keyless with the identity its nodes already have. Give it read access to your registry: the node role on ECR, the node service account on Artifact Registry, or the kubelet identity with AcrPull on ACR.
- Anywhere else, such as on-premises or self-managed Kubernetes, or any registry outside your cloud: a pull Secret.
Any registry, any cluster: a pull Secret
Put the Secret on the namespace's service account, so every pod there pulls with it and no chart has to name it.
Name the namespace first. If you leave the application's Namespace empty, AstroPulse creates one named after the application with a generated suffix, so you only learn its name after the first pull has already failed.
-
In Deploy application, set Namespace (or
namespacein the application YAML), for exampleteam-a. -
Create that namespace and a Secret in it, with a token from your registry that can only read, and put the Secret on the namespace's
defaultservice account:Terminalkubectl create namespace team-akubectl create secret docker-registry regcred \--docker-server=<registry> \--docker-username=<username> \--docker-password=<read-only-token> \--namespace=team-akubectl patch serviceaccount default -n team-a \-p '{"imagePullSecrets":[{"name":"regcred"}]}' -
Deploy. AstroPulse deploys into the namespace you named, beside what is already there, and never deletes it.
Kubernetes copies the service account's pull Secrets into each new pod, so the first pull succeeds:
kubectl get pod <pod> -n team-a -o jsonpath='{.spec.imagePullSecrets}'
[{"name":"regcred"}]
The default service account covers only pods that run as default. Many Helm charts create their own service account: for those, name the Secret in the chart's values instead.
imagePullSecrets:
- name: regcred
If the first pull already failed
With no namespace named and no Secret, the deploy stops at the pull. astroctl app get <name> says so, and shows the namespace AstroPulse created as targetNamespace:
status: Provisioning
statusReason: The image localhost:31500/acme/latency:v1.0.0 could not be pulled. Check
the image name and tag, and that the cluster can reach the registry. Its events
say why.
targetNamespace: registry-docs-b-987575
Warning: The application isn't serving
Nothing serves yet because container astropulse-app cannot pull image localhost:31500/acme/latency:v1.0.0 (ErrImagePull): no basic auth credentials.
-
Create the Secret in that
targetNamespaceand put it on itsdefaultservice account, as in step 2 above. -
Restart the pods, because a pod takes its service account's Secrets only when it's created:
Terminalkubectl delete pods --all -n <targetNamespace>
The new pods pull with the Secret and the application reaches Running.
Nova reads the app's events and the cluster, tells you which way of pulling applies, and writes the steps.
Push images from a build in the cluster
AstroPulse never pushes images. A build that runs in your cluster, such as kpack, pushes with access you give it. That holds on every cluster, whether AstroPulse created it on AWS, Google Cloud or Azure, or you registered it with the agent.
There are many ways to give that access. Use the one your team already uses:
- The cluster's cloud identity (recommended, keyless). Give the service account the build runs as push rights on your registry, the same way your cloud's page gives an app access to a bucket: an IAM role for Amazon ECR, a Google principal for Artifact Registry, or a managed identity for Azure Container Registry (AWS, Google Cloud, Azure). Clusters AstroPulse creates can pull only, so push rights are always yours to grant.
- A registry Secret. Works for any registry on any cluster, including Docker Hub and GitHub (
ghcr.io), and on a cluster with no cloud identity, such as on-premises. Create it in the build's namespace with a token that can push, and name it on the build's service account. For kpack:
kubectl create secret docker-registry registry-credentials \
--docker-server=ghcr.io \
--docker-username=<username> \
--docker-password=<token-with-push-access> \
--namespace=kpack
Grant push only to the build's service account, never to the nodes, so the apps running on the cluster keep read-only access.
How the credential is kept safe
AstroPulse stores no registry credential. A pull secret you create is a Kubernetes Secret in that namespace of that cluster, and only pods whose spec or service account names it use it. Use a read-only token for pulls and a push token only in the build's namespace, and delete the Secret to stop it.
Pulling from your cloud's registry uses the cluster's own identity, so no registry password exists to leak.
Other ways in
- astroctl: none for registries. Registries a cluster pulls from in other AWS accounts, or from Azure, are part of the cluster's spec:
ecrAccountIdson EKS andacrResourceIdson AKS. See Amazon EKS and Azure AKS.
If it's refused
az acr show --name <registry-name> --query id --output tsv and paste what it prints.A pod stuck in ImagePullBackOff with pull access denied or unauthorized is covered under If the first pull already failed.
Next
- Keyless cloud access: how your apps and add-ons reach the rest of your cloud.
- Image: deploy an application from a container image.
- Vault: every credential your organization has given AstroPulse.