在 Kubernetes 集群中以 cronjobs 形式运行 kubectl 命令会导致连接被拒绝错误

在 Kubernetes 集群中以 cronjobs 形式运行 kubectl 命令会导致连接被拒绝错误

kubectl使用 kubernetes(基于 EKS)集群内部的映像运行命令时bitnami/kubectl,我希望该命令能够获取KUBERNETES_SERVICE_HOST环境KUBERNETES_SERVICE_PORT变量并连接到本地集群以运行命令。具体来说,我使用它来运行一些内部管理kubernetes cronjobs在集群上,但容器只是出错(并最终陷入 crashBackoff 循环)。

容器日志中的错误信息如下:

与服务器 localhost:8080 的连接被拒绝 - 您是否指定了正确的主机或端口?

localhost:8080尤其奇怪,因为这个命令从未被使用过,而且据我所知也没有在任何地方配置过——切换到一个简单的 shell 命令允许作业成功运行,但 kubectl 却拒绝工作。运行env确认KUBE变量确实被注入并正确设置。最近唯一的变化是将这些作业移至由terraform kubernetes cronjob 资源而不是直接通过 YAML 文件。每个 cronjob 都与一个具有适当权限的服务帐户相关联,并且该帐户仍在 cronjob 中正确配置。

作为参考,这里有一个稍微删减过的 cronjob 版本:

resource "kubernetes_cron_job" "test_cronjob" {
  provider = kubernetes.region

  metadata {
    name = "test-cronjob"
    namespace = "default"
  }
  spec {
    concurrency_policy = "Allow"
    failed_jobs_history_limit = 5
    schedule = "*/5 * * * *"
    job_template {
      metadata {}
      spec {
        backoff_limit = 2
        parallelism = 1
        completions = 1
        template {
          metadata {}
          spec {
            container {
              name    = "kubectl"
              image   = "bitnami/kubectl"
              command = ["/bin/sh", "-c", <<-EOT
                                            env && echo "test";    
                                            EOT
                                            ]            
                        }
            restart_policy = "OnFailure"
            service_account_name = "sa-test"
          }
        }
      }
    }
  }
}

答案1

这里的错误信息没有什么帮助,它意味着问题在于集群的主机和端口配置错误,但根本问题实际上是缺少凭据,尽管配置了服务帐户。

解释一下,作为作业一部分的 pod spec 包含自动挂载服务账户使用 Terraform 时,该设置默认为 false。我怀疑以前使用YAML文件管理这些文件时,默认设置为false true

出现这个神秘错误的原因是,在没有有效凭证的情况下,kubectl似乎只能尝试“不安全的选项”,因为文档中提到,默认为 localhost 和端口 8080。在尝试了不安全的选项作为最后的手段后,它会报告错误,而不是指出缺少凭据或给出更有帮助的未经授权的错误。经过一番挖掘,似乎这实际上是底层库的问题client-go,它已经以其他方式浮出水面,请参阅这个问题

为了修复这个问题,只需将返回设置automount_service_account_token为 true 即可,如下所示:

resource "kubernetes_cron_job" "test_cronjob" {
  provider = kubernetes.region

  metadata {
    name = "test-cronjob"
    namespace = "default"
  }
  spec {
    concurrency_policy = "Allow"
    failed_jobs_history_limit = 5
    schedule = "*/5 * * * *"
    job_template {
      metadata {}
      spec {
        backoff_limit = 2
        parallelism = 1
        completions = 1
        template {
          metadata {}
          spec {
            automount_service_account_token = true
            container {
              name    = "kubectl"
              image   = "bitnami/kubectl"
              command = ["/bin/sh", "-c", <<-EOT
                                            env && echo "test";    
                                            EOT
                                            ]            
                        }
            restart_policy = "OnFailure"
            service_account_name = "sa-test"
          }
        }
      }
    }
  }
}

相关内容