<p>We have had image pull issues at one time or another with all of our possible docker registries including Artifactory, AWS ECR, and GitLab.   Even DockerHub occasionally has issues.</p>
<p>Is there a way in a Kubernetes deployment to specify that a pod can get an image from multiple different repositories so it can fall back if one is down?</p>
<p>If not, what other solutions are there to maintain stability?  I've seen things like Harbor and Trow, but it seems like a heavy handed solution to a simple problem.</p>

<blockquote>
<p>Is there a way in a Kubernetes deployment to specify that a pod can get an image from multiple different repositories so it can fall back if one is down?</p>
</blockquote>
<p>Not really, not natively 😔. You could probably trick a K8s node to pull images from different image registries (one at a time) if you place them behind something like a TCP load balancer that directs traffic to multiple registries. But this might take a lot of testing and work.</p>
<blockquote>
<p>If not, what other solutions are there to maintain stability? I've seen things like Harbor and Trow, but it seems like a heavy handed solution to a simple problem.</p>
</blockquote>
<p>I'd say either <a href="https://goharbor.io/" rel="noreferrer">Harbor</a>, <a href="https://quay.io/" rel="noreferrer">Quay</a>, and <a href="https://github.com/ContainerSolutions/trow" rel="noreferrer">Trow</a> is the way to go if you want something more redundant.</p>
<p>Kubernetes has the <a href="https://kubernetes.io/docs/concepts/containers/images/#updating-images" rel="noreferrer">ability</a> to set <code>ImagePullPolicy</code> and you can set it for example to <code>Never</code> if you'd like to pre-pull all your critical images on all the K8s nodes. You can tie this to some automation to pre-pull your images across your clusters and nodes.</p>
<p>I've actually opened a K8s <a href="https://github.com/kubernetes/kubernetes/issues/93736" rel="noreferrer">feature request</a> to see 👀 if this idea gains traction.</p>
<p><em>Update:</em></p>
<p>If you're using <a href="https://containerd.io/" rel="noreferrer">containerd</a> or <a href="https://cri-o.io/" rel="noreferrer">cri-o</a> (or even <a href="https://stackoverflow.com/questions/28557384/docker-private-registry-with-mirror">Docker</a> has registry mirrors). You have the ability to configure mirror registries:</p>
<p><code>containerd.toml</code> example</p>
<pre><code>...
    [plugins.cri.registry]
      [plugins.cri.registry.mirrors]
        [plugins.cri.registry.mirrors.&quot;docker.io&quot;]
          endpoint = [&quot;https://registry-1.docker.io&quot;]
        [plugins.cri.registry.mirrors.&quot;local.insecure-registry.io&quot;]
          endpoint = [&quot;http://localhost:32000&quot;]
        [plugins.cri.registry.mirrors.&quot;gcr.io&quot;]
          endpoint = [&quot;https://gcr.io&quot;]
      [plugins.cri.registry.configs]
        [plugins.cri.registry.configs.auths]
          [plugins.cri.registry.configs.auths.&quot;https://gcr.io&quot;]
            auth = &quot;xxxxx....&quot;
...
</code></pre>
<p><a href="https://medium.com/cri-o/default-container-registry-revisited-50b32dd808fe" rel="noreferrer"><code>cri-o.conf</code> example</a></p>
<pre><code>...
# registries is used to specify a comma separated list of registries to be used
# when pulling an unqualified image (e.g. fedora:rawhide).
registries = [
“registry.example.xyz”,
“registry.fedoraproject.org”
]
...
</code></pre>
<p>✌️</p>
