<p>I've setup a very <strong>simple local kubernetes cluster</strong> for development purposes, and for that I aim to pull a docker image for my pods from ECR.</p>
<p>Here's the code</p>
<pre><code>   terraform {
      required_providers {
        kubernetes = {
          source  = &quot;hashicorp/kubernetes&quot;
          version = &quot;&gt;= 2.0.0&quot;
        }
      }
    }

    provider &quot;kubernetes&quot; {
        config_path = &quot;~/.kube/config&quot;
    } 

    resource &quot;kubernetes_deployment&quot; &quot;test&quot; {
      metadata {
        name      = &quot;test-deployment&quot;
        namespace = kubernetes_namespace.test.metadata.0.name
      }

      spec {
        replicas = 2
        selector {
          match_labels = {
            app = &quot;MyTestApp&quot;
          }
        }

        template {
          metadata {
            labels = {
              app = &quot;MyTestApp&quot;
            }
          }

          spec {
            container {
              image = &quot;public ECR URL&quot;  &lt;--- this times out
              name  = &quot;myTestPod&quot;
    
              port {
                container_port = 4000
              }
            }
          }
        }
      }
    }
</code></pre>
<p>I've set that <strong>ECR repo to public</strong> and made sure that <strong>it's accessible</strong>. My challenge is that in a normal scenario <strong>you have to login to ECR</strong> in order to retrieve the image, and I do not know <strong>how to achieve that in Terraform</strong>. So on 'terraform apply', it times out and fails.</p>
<p>I read the documentation on <a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository" rel="nofollow noreferrer">aws_ecr_repository</a>, <a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecr_authorization_token" rel="nofollow noreferrer">aws_ecr_authorization_token</a>,<a href="https://registry.terraform.io/modules/terraform-aws-modules/eks/aws/latest" rel="nofollow noreferrer">Terraform EKS module</a> and <a href="https://www.terraform.io/language/resources/provisioners/local-exec" rel="nofollow noreferrer">local-exec</a>, but none of them seem to have a solution for this.</p>
<p>Achieving this in a Gitlab pipeline is fairly easy, but how can one achieve this in Terraform? how can I pull an image from a public <strong>ECR repo for my local Kubernetes</strong> cluster?</p>

Pouya Ataei
<p>After a while, I figured out the cleanest way to achieve this;</p>
<p><strong>First</strong> retrieve your <strong>ECR authorization token</strong> data;</p>
<pre><code>data &quot;aws_ecr_authorization_token&quot; &quot;token&quot; {
}
</code></pre>
<p><strong>Second</strong>, create a <strong>secret for your kubernetes</strong> cluster**:</p>
<pre><code>resource &quot;kubernetes_secret&quot; &quot;docker&quot; {
  metadata {
    name      = &quot;docker-cfg&quot;
    namespace = kubernetes_namespace.test.metadata.0.name
  }

  data = {
    &quot;.dockerconfigjson&quot; = jsonencode({
      auths = {
        &quot;${data.aws_ecr_authorization_token.token.proxy_endpoint}&quot; = {
          auth = &quot;${data.aws_ecr_authorization_token.token.authorization_token}&quot;
        }
      }
    })
  }

  type = &quot;kubernetes.io/dockerconfigjson&quot;
}
</code></pre>
<p>Bear in mind that the example in the <a href="https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret" rel="nofollow noreferrer">docs</a> base64 encodes the username and password. The exported attribute <strong>authorization_token</strong> does the same thing.</p>
<p><strong>Third</strong>, once the secret is created, you can then have your pods use it as the <strong>image_pull_secrets</strong>:</p>
<pre><code>resource &quot;kubernetes_deployment&quot; &quot;test&quot; {
  metadata {
    name      = &quot;MyTestApp&quot;
    namespace = kubernetes_namespace.test.metadata.0.name
  }
  spec {
    replicas = 2

    selector {
      match_labels = {
        app = &quot;MyTestApp&quot;
      }
    }

    template {
      metadata {
        labels = {
          app = &quot;MyTestApp&quot;
        }
      }


      spec {

        image_pull_secrets {
          name = &quot;docker-cfg&quot;
        }

        container {
          image             = &quot;test-image-URL&quot;
          name              = &quot;test-image-name&quot;
          image_pull_policy = &quot;Always&quot;


          port {
            container_port = 4000
          }
        }

      }
    }
  }
  depends_on = [
      kubernetes_secret.docker,
  ]
}
</code></pre>
<p><strong>Gotcha</strong>: the token <strong>expires after 12 hours</strong>, so you should either write a bash script that updates your secret in the corresponding namespace, or you should write a <a href="https://www.terraform.io/language/resources/provisioners/syntax" rel="nofollow noreferrer">Terraform provisioner</a> that gets triggered every time the token expires.</p>
<p>I hope this was helpful.</p>
