当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"
}
}
}
}
}
}