在 Terraform 的本地 Kubernetes 集群中使用 public ECR 映像

Using a public ECR image in local Kubernetes cluster in Terraform

我已经设置了一个非常简单的本地 kubernetes 集群 用于开发目的,为此我打算为我的 pods 提取一个 docker 图像来自 ECR。

这是代码

   terraform {
      required_providers {
        kubernetes = {
          source  = "hashicorp/kubernetes"
          version = ">= 2.0.0"
        }
      }
    }

    provider "kubernetes" {
        config_path = "~/.kube/config"
    } 

    resource "kubernetes_deployment" "test" {
      metadata {
        name      = "test-deployment"
        namespace = kubernetes_namespace.test.metadata.0.name
      }

      spec {
        replicas = 2
        selector {
          match_labels = {
            app = "MyTestApp"
          }
        }

        template {
          metadata {
            labels = {
              app = "MyTestApp"
            }
          }

          spec {
            container {
              image = "public ECR URL"  <--- this times out
              name  = "myTestPod"
    
              port {
                container_port = 4000
              }
            }
          }
        }
      }
    }

我已将 ECR 存储库设置为 public 并确保它可以访问。我的挑战是,在正常情况下 您必须登录 ECR 才能检索图像,我不知道 如何在 Terraform[=29] 中实现这一点=].所以在 'terraform apply' 上,它超时并失败。

我阅读了关于 aws_ecr_repository, aws_ecr_authorization_token,Terraform EKS module and local-exec 的文档,但其中 none 似乎对此有解决方案。

在 Gitlab 管道中实现这一目标相当容易,但如何在 Terraform 中实现这一目标呢?我如何从 public ECR 存储库中为我的本地 Kubernetes 集群提取镜像?

一段时间后,我找到了实现此目的的最简洁方法;

首先 检索您的 ECR 授权令牌 数据;

data "aws_ecr_authorization_token" "token" {
}

其次,为您的 kubernetes 集群创建一个 secret**:

resource "kubernetes_secret" "docker" {
  metadata {
    name      = "docker-cfg"
    namespace = kubernetes_namespace.test.metadata.0.name
  }

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

  type = "kubernetes.io/dockerconfigjson"
}

请记住,docs base64 中的示例对用户名和密码进行了编码。导出的属性 authorization_token 做同样的事情。

第三个,一旦创建了秘密,您就可以让您的pods将其用作image_pull_secrets:

resource "kubernetes_deployment" "test" {
  metadata {
    name      = "MyTestApp"
    namespace = kubernetes_namespace.test.metadata.0.name
  }
  spec {
    replicas = 2

    selector {
      match_labels = {
        app = "MyTestApp"
      }
    }

    template {
      metadata {
        labels = {
          app = "MyTestApp"
        }
      }


      spec {

        image_pull_secrets {
          name = "docker-cfg"
        }

        container {
          image             = "test-image-URL"
          name              = "test-image-name"
          image_pull_policy = "Always"


          port {
            container_port = 4000
          }
        }

      }
    }
  }
  depends_on = [
      kubernetes_secret.docker,
  ]
}

陷阱:令牌 12 小时后过期,因此您应该编写一个 bash 脚本来更新您的秘密在相应的命名空间中,或者你应该写一个 Terraform provisioner 每次令牌过期时都会触发。

希望对您有所帮助。