Skaffold’s image pull policy is a surprisingly powerful lever for controlling how your development environment interacts with your Kubernetes cluster’s image registry.

Let’s see it in action. Imagine you’re developing a microservice, my-service, and you’ve configured Skaffold to build and deploy it.

apiVersion: skaffold.dev/v2beta10
kind: Config
build:
  artifacts:
    my-service:
      docker:
        image: my-registry/my-service
deploy:
  kubectl:
    manifests:
      - k8s/deployment.yaml

Now, let’s say k8s/deployment.yaml references my-registry/my-service:latest.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-service
spec:
  selector:
    matchLabels:
      app: my-service
  template:
    metadata:
      labels:
        app: my-service
    spec:
      containers:
      - name: my-service
        image: my-registry/my-service:latest # This is what we're controlling
        ports:
        - containerPort: 8080

When you run skaffold dev, Skaffold typically builds your image, tags it (often with a git commit or timestamp), and pushes it. Then, it updates your Kubernetes manifest to use this new image tag and applies it. The imagePullPolicy in your Kubernetes manifest, usually IfNotPresent or Always, dictates how the kubelet on your worker nodes fetches the image. Skaffold’s imagePullPolicy setting influences this, but it’s not a direct one-to-one mapping.

The core problem Skaffold’s imagePullPolicy solves is managing the trade-off between development speed and ensuring you’re running the exact code you just built. By default, Skaffold might try to be clever and avoid pulling images if it thinks it already has the right one. But what if the registry has a newer version you didn’t build, or what if your local Docker daemon is lying to you?

Here’s how you can explicitly control this in your skaffold.yaml:

apiVersion: skaffold.dev/v2beta10
kind: Config
build:
  artifacts:
    my-service:
      docker:
        image: my-registry/my-service
      # Add this section to control image pull behavior
      imagePullPolicy:
        # Options:
        # - "IfNotPresent" (default): Only pull if the image is not locally cached.
        # - "Always": Always attempt to pull the image, even if cached.
        # - "Never": Never pull the image; rely solely on local cache.
        value: "Always"
deploy:
  kubectl:
    manifests:
      - k8s/deployment.yaml

Setting imagePullPolicy.value: "Always" tells Skaffold that before it deploys, it should ensure the image is pulled from the registry. This is crucial when you want to be absolutely certain that the image running in your cluster is the one Skaffold just built and pushed, regardless of what might be sitting in the local Docker cache on your worker nodes. It forces a fresh fetch, guaranteeing you’re testing the latest iteration.

Conversely, imagePullPolicy.value: "IfNotPresent" is the default and the most performant for development loops. If the image digest exists on the node, Kubernetes won’t pull it again. This is usually fine because Skaffold’s build process generates a unique tag for each build (e.g., using git commit SHA), so even if the tag is the same, the underlying image content is different. However, in rare scenarios with misconfigured registries or local cache corruption, IfNotPresent might lead to older image versions being used.

The Never policy is rarely used in active development but can be useful in environments where network access to the registry is restricted or for specific testing scenarios where you must use a locally built image without any external dependency.

What many people miss is how Skaffold’s imagePullPolicy interacts with Kubernetes’ own imagePullPolicy. Skaffold’s setting primarily influences the deployment step. When Skaffold updates your Kubernetes manifest, it can optionally inject an imagePullPolicy into the spec.template.spec.containers section of your deployment. If you don’t explicitly set imagePullPolicy in your Kubernetes manifest, Skaffold’s imagePullPolicy setting will often translate to Always being added to your container spec for that deployment. If you do set it in your manifest, Skaffold’s setting might be ignored or have a different effect depending on the exact configuration. For development, it’s often best to let Skaffold manage it by leaving it out of your Kubernetes manifests.

The next hurdle you’ll likely encounter is managing image tag collision when multiple developers are working on the same service and pushing to a shared registry.

Want structured learning?

Take the full Skaffold course →