为 Docker Registry 创建 Kubernetes Secret - Terraform

5
使用kubectl,我们可以按照以下步骤创建docker registry身份验证秘钥
kubectl create secret docker-registry regsecret \
--docker-server=docker.example.com \
--docker-username=kube \
--docker-password=PW_STRING \
--docker-email=my@email.com \

如何使用terraform创建此secret,我看到了这个链接,其中有data。在terraform流程中,kubernetes实例正在azure中创建,并且我从那里获取所需的数据并创建了如下内容:

resource "kubernetes_secret" "docker-registry" {
  metadata {
    name = "registry-credentials"
  }

  data = {
    docker-server = data.azurerm_container_registry.docker_registry_data.login_server
    docker-username = data.azurerm_container_registry.docker_registry_data.admin_username
    docker-password = data.azurerm_container_registry.docker_registry_data.admin_password
  }


}

看起来有问题,因为图片没有显示出来。我错过了什么吗?


1
你的 ACR 中的“以管理员身份登录”标志是否设置为 true?为什么不使用服务主体并为 AKS 创建 Pull 权限。这是推荐的配置。 - Chris
抱歉,我从未使用过它,请问您能否指导我一下。 - doc_noob
1
我添加了一个答案来描述如何使用terraform授予访问权限。 - Chris
2个回答

26

如果您运行以下命令

kubectl create secret docker-registry regsecret \
--docker-server=docker.example.com \
--docker-username=kube \
--docker-password=PW_STRING \
--docker-email=my@email.com 

它将创建像下面这样的秘密

$ kubectl get secrets regsecret -o yaml
apiVersion: v1
data:
  .dockerconfigjson: eyJhdXRocyI6eyJkb2NrZXIuZXhhbXBsZS5jb20iOnsidXNlcm5hbWUiOiJrdWJlIiwicGFzc3dvcmQiOiJQV19TVFJJTkciLCJlbWFpbCI6Im15QGVtYWlsLmNvbSIsImF1dGgiOiJhM1ZpWlRwUVYxOVRWRkpKVGtjPSJ9fX0=
kind: Secret
metadata:
  creationTimestamp: "2020-06-01T18:31:07Z"
  name: regsecret
  namespace: default
  resourceVersion: "42304"
  selfLink: /api/v1/namespaces/default/secrets/regsecret
  uid: 59054483-2789-4dd2-9321-74d911eef610
type: kubernetes.io/dockerconfigjson

如果我们解码.dockerconfigjson,我们将获得

{"auths":{"docker.example.com":{"username":"kube","password":"PW_STRING","email":"my@email.com","auth":"a3ViZTpQV19TVFJJTkc="}}}

那么,我们如何使用terraform来做到这一点呢?

我创建了一个名为config.json的文件,其中包含以下数据。

{"auths":{"${docker-server}":{"username":"${docker-username}","password":"${docker-password}","email":"${docker-email}","auth":"${auth}"}}}

然后在main.tf文件中

resource "kubernetes_secret" "docker-registry" {
  metadata {
    name = "regsecret"
  }

  data = {
    ".dockerconfigjson" = "${data.template_file.docker_config_script.rendered}"
  }

  type = "kubernetes.io/dockerconfigjson"
}


data "template_file" "docker_config_script" {
  template = "${file("${path.module}/config.json")}"
  vars = {
    docker-username           = "${var.docker-username}"
    docker-password           = "${var.docker-password}"
    docker-server             = "${var.docker-server}"
    docker-email              = "${var.docker-email}"
    auth                      = base64encode("${var.docker-username}:${var.docker-password}")
  }
}

然后运行

$ terraform apply

这将生成相同的秘密。希望它能帮助。


感谢您的努力和回复,这也是一个正确的答案。 - doc_noob

3
我建议创建一个 azurerm_role_assignement 来给 aks 授予对 acr 的访问权限:
resource "azurerm_role_assignment" "aks_sp_acr" {
  scope                = azurerm_container_registry.acr.id
  role_definition_name = "AcrPull"
  principal_id         = var.service_principal_obj_id

  depends_on = [
    azurerm_kubernetes_cluster.aks,
    azurerm_container_registry.acr
  ]
}

更新

您可以在Azure门户中创建服务主体,也可以使用az cli,并在terraform中使用client_id、client_secret和object-id。

通过运行az ad sp list --filter "displayName eq '<name>'"获取Client_id和Object_id. 密钥必须在服务主体的“证书和密码”选项卡中创建。请参阅此指南:https://pixelrobots.co.uk/2018/11/first-look-at-terraform-and-the-azure-cloud-shell/

只需将这三个设置为变量,例如obj_id:

variable "service_principal_obj_id" {
   default = "<object-id>"
}

现在可以使用凭据与aks:

resource "azurerm_kubernetes_cluster" "aks" {

  ...

  service_principal {
    client_id     = var.service_principal_app_id
    client_secret = var.service_principal_password
  }

  ...

}

按照上述描述,在acr中设置对象id。

替代方案

您可以使用terraform创建服务主体(仅在您拥有必要权限时才有效)。结合random_password资源,可参考https://www.terraform.io/docs/providers/azuread/r/service_principal.html

resource "azuread_application" "aks_sp" {
  name                       = "somename"
  available_to_other_tenants = false
  oauth2_allow_implicit_flow = false
}

resource "azuread_service_principal" "aks_sp" {
  application_id = azuread_application.aks_sp.application_id

  depends_on = [
    azuread_application.aks_sp
  ]
}

resource "azuread_service_principal_password" "aks_sp_pwd" {
  service_principal_id = azuread_service_principal.aks_sp.id
  value                = random_password.aks_sp_pwd.result
  end_date             = "2099-01-01T01:02:03Z"

  depends_on = [
    azuread_service_principal.aks_sp
  ]
}

你需要给sp分配"贡献者"的角色,并可以直接在aks/acr中使用。
resource "azurerm_role_assignment" "aks_sp_role_assignment" {
  scope                = var.subscription_id
  role_definition_name = "Contributor"
  principal_id         = azuread_service_principal.aks_sp.id

  depends_on = [
    azuread_service_principal_password.aks_sp_pwd
  ]
}

与 aks 一起使用:

resource "azurerm_kubernetes_cluster" "aks" {

  ...

  service_principal {
    client_id     = azuread_service_principal.aks_sp.app_id
    client_secret = azuread_service_principal_password.aks_sp_pwd.value
  }

  ...

}

以及角色分配:

resource "azurerm_role_assignment" "aks_sp_acr" {
  scope                = azurerm_container_registry.acr.id
  role_definition_name = "AcrPull"
  principal_id         = azuread_service_principal.aks_sp.object_id

  depends_on = [
    azurerm_kubernetes_cluster.aks,
    azurerm_container_registry.acr
  ]
}

更新密钥示例

resource "random_password" "aks_sp_pwd" {
  length = 32
  special = true
}

Kubernetes中,我该如何处理密钥? - doc_noob
1
如果您需要进一步的帮助,请随时提问。如果我的回答对您有帮助,请考虑点赞/接受 :) - Chris
1
客户端密钥是使用 Terraform 和资源随机密码 https://www.terraform.io/docs/providers/random/r/password.html 创建的,只需将其命名为“aks_sp_pwd”。Terraform 会创建并管理该密钥。您不需要知道 Kubernetes 本身的值。不确定这是否是您确切的问题。 - Chris
1
我添加了一个例子,希望这解决了所有问题。 - Chris
1
好的,但请确保为每个资源创建一个新的以防止安全问题。 - Chris
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接