等待条件时terraform helm释放超时

Posted

技术标签:

【中文标题】等待条件时terraform helm释放超时【英文标题】:terraform helm release timeout while waiting for condition 【发布时间】:2019-11-22 22:45:56 【问题描述】:

我正在使用 terraform 在 azure 中配置一些资源,但我似乎无法让 helm 安装 nginx-ingress,因为它等待条件超时

helm_release.nginx_ingress:发生 1 个错误:

helm_release.nginx_ingress: rpc error: code = Unknown desc = release nginx-ingress failed: timed out waiting for the condition

Terraform 在遇到错误时不会自动回滚。 相反,您的 Terraform 状态文件已部分更新为任何 成功完成的资源。请解决上面的错误 并再次申请以逐步更改您的基础架构。 main.tf

data "azurerm_public_ip" "nginx_ingress" 
    name                = "xxxx-public-ip"
    resource_group_name = "xxxx-public-ip"


resource "azurerm_resource_group" "xxxx_RG" 
  name     = "$var.name_prefix"
  location = "$var.location"


resource "azurerm_kubernetes_cluster" "k8s" 
    name                    = "$var.name_prefix-aks"
    kubernetes_version      = "$var.kubernetes_version"
    location                = "$azurerm_resource_group.xxxx_RG.location"
    resource_group_name     = "$azurerm_resource_group.xxxx_RG.name"
    dns_prefix              = "AKS-$var.dns_prefix"

    agent_pool_profile 
        name                = "$var.node_pool_name"
        count               = "$var.node_pool_size"
        vm_size             = "$var.node_pool_vmsize"
        os_type             = "$var.node_pool_os"
        os_disk_size_gb     = 30
    

    service_principal 
        client_id           = "$var.client_id"
        client_secret       = "$var.client_secret"
    

    tags = 
        environment = "$var.env_tag"
    


provider "helm" 
  install_tiller = true

  kubernetes 
    host                   = "$azurerm_kubernetes_cluster.k8s.kube_config.0.host"
    client_certificate     = "$base64decode(azurerm_kubernetes_cluster.k8s.kube_config.0.client_certificate)"
    client_key             = "$base64decode(azurerm_kubernetes_cluster.k8s.kube_config.0.client_key)"
    cluster_ca_certificate = "$base64decode(azurerm_kubernetes_cluster.k8s.kube_config.0.cluster_ca_certificate)"
  


# Add Kubernetes Stable Helm charts repo
resource "helm_repository" "stable" 
  name = "stable"
  url  = "https://kubernetes-charts.storage.googleapis.com"


# Install Nginx Ingress using Helm Chart
resource "helm_release" "nginx_ingress" 
  name       = "nginx-ingress"
  repository = "$helm_repository.stable.metadata.0.name"
  chart      = "nginx-ingress"
  wait       = "true"

  set 
    name  = "rbac.create"
    value = "false"
  

  set 
    name  = "controller.service.externalTrafficPolicy"
    value = "Local"
  

  set 
    name  = "controller.service.loadBalancerIP"
    value = "$data.azurerm_public_ip.nginx_ingress.ip_address"
  

然后用这个部署我的应用程序

provider "kubernetes" 
    host                    = "$azurerm_kubernetes_cluster.k8s.kube_config.0.host"
    username                = "$azurerm_kubernetes_cluster.k8s.kube_config.0.username"
    password                = "$azurerm_kubernetes_cluster.k8s.kube_config.0.password"
    client_certificate      = "$base64decode(azurerm_kubernetes_cluster.k8s.kube_config.0.client_certificate)"
    client_key              = "$base64decode(azurerm_kubernetes_cluster.k8s.kube_config.0.client_key)"
    cluster_ca_certificate  = "$base64decode(azurerm_kubernetes_cluster.k8s.kube_config.0.cluster_ca_certificate)"


resource "kubernetes_deployment" "flask_api_deployment" 
    metadata 
        name = "flask-api-deployment"
    

    spec 
        replicas = 1
        selector 
            match_labels 
                component = "api"
            
        

        template 
            metadata 
                labels = 
                    component = "api"
                
            

            spec 
                container 
                    image = "xxxx.azurecr.io/sampleflask:0.1.0"
                    name = "flask-api"
                    port 
                        container_port = 5000
                    
                
            
        
    


resource "kubernetes_ingress" "flask_api_ingress_service" 
    metadata 
        name = "flask-api-ingress-service"
    

    spec 
        backend 
            service_name = "flask-api-cluster-ip-service"
            service_port = 5000
        
    


resource "kubernetes_service" "flask_api_cluster_ip-service" 
    metadata 
        name = "flask-api-cluster-ip-service"
    

    spec 
        selector 
            component = "api"
        

        port 
            port = 5000
            target_port = 5000
        
    

我不确定它在等待什么条件。我可以将超时设置得更大,但这似乎没有帮助。我也可以在 helm release 中设置 wait = false ,但似乎没有配置资源。

编辑:从我所做的一些测试中,我发现在 helm 版本中指定 loadbalancerIP 时存在问题。如果我注释掉它就可以了。

编辑:通过更多测试,我发现创建的负载均衡器无法创建。控制器:在资源组 MC_xxxxxxxx 中找不到用户提供的 IP 地址 52.xxx.x.xx

所以我想问题是如何允许指定来自不同资源组的 IP?

【问题讨论】:

我怀疑它正在等待服务完成设置并没有这样做,您能否确认已提供服务并且公共 ip 可用? 如果你尝试重新运行terraform apply?,你会得到同样的错误吗 您是否有意关闭 RBAC?你最好启用它。 这个问题有什么更新吗?对你起作用吗?如果您还有其他问题,请告诉我。 不要保持沉默。请让我知道它是否有帮助! 【参考方案1】:

要通过 Terraform 中的 helm 在 AKS 集群中安装 nginx-ingress,我在这里展示了一种可用的方法。这样,您需要在要运行 terraform 脚本的机器上安装 helm。然后,您还需要将 helm 配置到您的 AKS 群集。 Configure the helm to AKS 中的步骤。您可以通过向 AKS 安装一些东西来检查 helm 是否配置为 AKS。

当一切准备就绪时。您只需要设置 helm 提供程序并使用资源 helm_release。安装 nginx-ingress 的 Terraform 脚本显示在这里:

provider "helm" 
  version = "~> 0.9"


resource "helm_release" "ingress" 
    name = "application1"
    chart = "stable/nginx-ingress"
    version = "1.10.2"
    namespace = "ingress-basic"

    set 
        name = "controller.replicaCount"
        value = "1"
    

    ...


流程如下:

这只是为了在 Terraform 中通过 helm 安装 nginx-ingress。如果你想创建 Kubernetes 的资源。您可以在 Terraform 中使用 kubernetes。

更新

好的,要将另一个资源组中的静态公共 IP 用于您的入口,您需要再执行两个步骤。

    AKS 群集使用的服务主体必须将权限委派给公共 IP 所在的其他资源组。权限至少应为“网络参与者”。 将入口服务注解设置为公网IP所在资源组的值。

yaml 文件中的注解是这样的:

annotations:
    service.beta.kubernetes.io/azure-load-balancer-resource-group: myResourceGroup

更多详情请见Use a static IP address outside of the node resource group。

更新1:

“helm_release”中的代码:

resource "helm_release" "ingress" 
    name = "application1223"
    chart = "stable/nginx-ingress"
        version = "1.10.2"
    namespace = "ingress-basic"

    set 
        name = "controller.replicaCount"
        value = "1"
    

    set 
      name = "controller.service.annotations.\"service\\.beta\\.kubernetes\\.io/azure-load-balancer-resource-group\""
      value = "v-chaxu-xxxx"
    

    set 
      name = "controller.service.loadBalancerIP"
      value = "13.68.175.40"
    


部署成功后,入口服务显示如下:

另一个资源组中的公网IP信息:

【讨论】:

【参考方案2】:

最好在集群中启用 RBAC。如何使用 Terraform 并随后安装 Helm 的示例如下:

…
resource "azurerm_kubernetes_cluster" "k8s" 
…

  role_based_access_control 
    enabled = "true"
  



provider "kubernetes" 
  host                   = "$azurerm_kubernetes_cluster.k8s.kube_config.0.host"
  client_certificate     = "$base64decode(azurerm_kubernetes_cluster.k8s.kube_config.0.client_certificate)"
  client_key             = "$base64decode(azurerm_kubernetes_cluster.k8s.kube_config.0.client_key)"
  cluster_ca_certificate = "$base64decode(azurerm_kubernetes_cluster.k8s.kube_config.0.cluster_ca_certificate)"


resource "kubernetes_service_account" "tiller_sa" 
  metadata 
    name      = "tiller"
    namespace = "kube-system"
  


resource "kubernetes_cluster_role_binding" "tiller_sa_cluster_admin_rb" 
  metadata 
    name = "tiller-cluster-role"
  
  role_ref 
    kind      = "ClusterRole"
    name      = "cluster-admin"
    api_group = "rbac.authorization.k8s.io"
  
  subject 
    kind      = "ServiceAccount"
    name      = "$kubernetes_service_account.tiller_sa.metadata.0.name"
    namespace = "kube-system"
    api_group = ""
  


# helm provider
provider "helm" 
  debug           = true
  namespace       = "kube-system"
  service_account = "tiller"
  install_tiller  = "true"
  tiller_image    = "gcr.io/kubernetes-helm/tiller:v$var.TILLER_VER"
  kubernetes 
    host                   = "$azurerm_kubernetes_cluster.k8s.kube_config.0.host"
    client_certificate     = "$base64decode(azurerm_kubernetes_cluster.k8s.kube_config.0.client_certificate)"
    client_key             = "$base64decode(azurerm_kubernetes_cluster.k8s.kube_config.0.client_key)"
    cluster_ca_certificate = "$base64decode(azurerm_kubernetes_cluster.k8s.kube_config.0.cluster_ca_certificate)"
  


data "helm_repository" "stable" 
  name = "stable"
  url  = "https://kubernetes-charts.storage.googleapis.com"


resource "helm_release" "datadog" 
  name       = "datadog"
  namespace  = "datadog"
  repository = "$data.helm_repository.stable.metadata.0.name"
  chart      = "stable/datadog"

  set 
    name  = "datadog.apiKey"
    value = "$var.datadog_apikey"
  


【讨论】:

很酷,这有助于更好地与最佳实践保持一致,但我仍然遇到我所写的超时问题。 实际上这给了我一个更好的错误。我现在得到 helm_release.nginx_ingress: timeout while waiting state to become 'Running' 表示图表安装失败并超时。您是否看到 Pod 处于运行状态? 我看到我的 pod 正在运行,当我获得该 kube-system 命名空间的 pod 时,我看到以下内容:coredns-7fbf4847b6-6mcx8、coredns-7fbf4847b6-fxfxs、coredns-autoscaler-657d77ffbf-78rww、kube -proxy-79v7w,kube-proxy-dgrsk,kubernetes-dashboard-6f697bd9f5-76x8n,metrics-server-58699455bc-pf6lq,tiller-deploy-8485766469-hbqmw,tunnelfront-bb9b87486-6rtm8。所有这些 pod 都在运行。我不确定我还要寻找哪些其他 pod?【参考方案3】:

我遇到了同样的问题(helm_release 超时)。经过进一步调查,我发现公共 IP 没有被分配给负载均衡器(kubectl describe svc nginx-ingress -n ingress-basic),因为 RBAC 权限不正确。

我使用的是 Azure AKS 托管标识功能,Azure 通过该功能自动创建一个托管标识服务主体,该主体只有非常有限的权限(对由 AKS 自动创建的托管集群资源组的只读权限)。我的公共 IP 位于另一个资源组中,负载均衡器位于 AKS 群集的托管资源组中。

最后,我能够通过使用“服务主体”选项而不是 AKS 群集中的托管标识以及“参与者”访问服务主体的订阅来解决此问题。

因此,如果有人在托管身份方面遇到问题,请尝试使用具有订阅者访问权限的服务主体,这将解决问题

【讨论】:

我投了赞成票,因为 IMO 这最直接地回答了原始问题。人们似乎遇到的普遍问题是 helm 提供者需要将公共 IP 分配给入口控制器才能成功完成。

以上是关于等待条件时terraform helm释放超时的主要内容,如果未能解决你的问题,请参考以下文章

使用 Helm 而不是 Terraform 的困惑

卡在 Terraform 到 Kubernetes 的部分 helm 版本中

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

通过 helm / terraform 安装自定义 grafana 数据源

通过 Terraform Helm 提供程序和 Azure DevOps 部署 helm 图表,同时从 ACR 获取 helm 图表

通过 Terraform Helm 提供程序设置 grafana.ini