使用 Terraform 部署时 GKE Autopilot 无法调度

Posted

技术标签:

【中文标题】使用 Terraform 部署时 GKE Autopilot 无法调度【英文标题】:GKE Autopilot unschedulable when deploying with Terraform 【发布时间】:2022-01-11 05:19:06 【问题描述】:

首先,我使用浏览器中的 GCP GUI 控制台创建了一个 GKE Autopilot 集群,并使用默认设置,因此我尝试使用 kubectl apply -f thisfile.yaml 应用我的部署:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      run: my-app
  template:
    metadata:
      labels:
        run: my-app
    spec:
      containers:
      - name: hello-app
        image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0

之后,我一直将其重写为 Terraform 文件,结果如下:

resource "google_container_cluster" "my_gke" 
  name             = "my-gke"
  enable_autopilot = "true"
  location         = "southamerica-east1"


data "google_client_config" "default" 

provider "kubernetes" 
  host                   = "https://$google_container_cluster.my_gke.endpoint"
  token                  = data.google_client_config.default.access_token
  cluster_ca_certificate = base64decode(google_container_cluster.my_gke.master_auth[0].cluster_ca_certificate)


resource "kubernetes_deployment" "my_deployment" 
  metadata 
    name = "my-app"
  
  spec 
    replicas = 2
    selector 
      match_labels = 
        run = "my-app"
      
    
    template 
      metadata 
        labels = 
          run = "my-app"
        
      
      spec 
        container 
          image = "us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0"
          name  = "hello-app"
        
      
    
  


  lifecycle 
    ignore_changes = [
      metadata[0].annotations,
      metadata[0].resource_version,
      spec[0].template[0].spec[0].container[0].security_context
    ]
  

问题如下:

当我将它与kubectl apply -f thisfile.yaml 一起应用时,使用 YAML 表示法,一切都可以正常部署。 当我删除集群并使用 Terraform 应用所有内容时,第一个修订版在一段时间后可以正常应用,但部署的下一个修订版继续导致 GCP 控制台打印“不可调度”错误,声称“cpu 不足”和/或“内存不足”

PS。我之前已经尝试在 PodSpec 中设置资源的限制和请求,但没有任何改变。

我是 GKE 的新手,现在对我来说一切看起来都很不可靠。我做错了什么?

【问题讨论】:

也许你必须先删除旧的部署。 kubectl get deployment --all-namespaces 或 kubectl get pods --all-namespaces #获取概览,然后删除不需要的。 【参考方案1】:

我可以确认这是一个持续存在的问题。我们向 GCP 开具了支持票证,以调查相同的行为。

第一次部署工作正常,但新修订版的部署失败。 Pod 的创建和删除速度很快(每秒几个),而 ReplicaSet 很快达到数百个。

从日志中我们可以看到相同的 Unschedulable 错误,有时我们会看到 Pod 因节点中缺少卷而无法启动(大部分时间是我们自己的卷,但也有“kube-api-access”卷)。

日志中也有这样的错误:

message: "Operation cannot be fulfilled on replicasets.apps "deploytest-747c54b87d": the object has been modified; please apply your changes to the latest version and try again"

只有当我们尝试通过 terraform 重新部署时才会发生这种情况。如果我们直接用 kubectl 给 yaml 打补丁,新版本通过替换策略可以正常运行,没有错误。

完全相同的 terraform 代码适用于 GKE 常规集群。问题似乎仅限于自动驾驶仪。已经在一个全新的项目中进行了测试,一切都是开箱即用的默认设置。

Google 目前正在通过内部工单调查此问题。我会尝试在这里报告我们还能弄清楚的其他内容。

--编辑:

Pod 似乎需要 pod.securityContext.seccompProfile 参数,但 Terraform 尚不支持该参数。出于某种原因,相同的 terraform 代码可以实例化一个新的部署,如果它还不存在的话。但它无法更新部署。

下面的补丁添加了缺失的配置,但这不是解决方案。我想我们需要等待 securityContext 被添加到 TF 中。 (ps.有一个不推荐的注解方法来添加这个配置,但我没有尝试)。

kubectl patch deployment deploy-test -p='["op": "replace", "path": "/spec/template/spec/securityContext", "value":"seccompProfile":"type":"RuntimeDefault"]' --type='json'

我们刚刚决定从 TF 迁移到 K8S 部署。我们的 TF 只上升到集群创建。工作负载将在其他地方进行管理。

【讨论】:

【参考方案2】:

可能 Kubernetes 集群没有可用资源的节点。尝试将 Kubernetes 应用程序的部署和集群的部署分开。 通常,发生像您这样的错误是因为节点尚未准备好,并且 Kubernetes 无法为 Deployment 分配资源。

【讨论】:

这是 GKE Autopilot,Google 管理集群的节点。

以上是关于使用 Terraform 部署时 GKE Autopilot 无法调度的主要内容,如果未能解决你的问题,请参考以下文章

在 terraform 中禁用时默认启用 GKE 屏蔽节点

需要帮助 GKE 入口与 terraform 进行 n8n 部署

在 GKE 集群上使用 Terraform 部署 Helm 工作负载

将现有 GKE 集群添加到 terraform stat 文件

将谷歌云盔甲添加到 Terraform gke 和 kubernetes

GKE terraform 的标签更改导致整个集群崩溃