hashicorp / terraform-provider-kubernetes-alpha

A Terraform provider for Kubernetes that uses dynamic resource types and server-side apply. Supports all Kubernetes resources.
https://registry.terraform.io/providers/hashicorp/kubernetes-alpha/latest
Mozilla Public License 2.0
490 stars 63 forks source link

failed to create typed patch object #152

Open ggolub opened 3 years ago

ggolub commented 3 years ago

Terraform, Provider, Kubernetes versions

Terraform version: v0.14.7
Provider version: 0.2.1/windows_amd64
Kubernetes version: Client Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.3", GitCommit:"1e11e4a2108024935ecfcb2912226cedeafd99df", GitTreeState:"clean", BuildDate:"2020-10-14T12:50:19Z", GoVersion:"go1.15.2", Compiler:"gc", Platform:"windows/amd64"}
Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.10", GitCommit:"41d24ec9c736cf0bdb0de3549d30c676e98eebaf", GitTreeState:"clean", BuildDate:"2021-01-18T09:12:27Z", GoVersion:"go1.13.15", Compiler:"gc", Platform:"linux/amd64"}

Affected Resource(s)

kubernetes_manifest

Terraform Configuration Files

# Copy-paste your Terraform configurations here - for large Terraform configs,
# please use a service like Dropbox and share a link to the ZIP file. For
# security, you can also encrypt the files using our GPG public key.

resource "kubernetes_manifest" "deployment_jaeger" { provider = kubernetes-alpha

manifest = { "apiVersion" = "apps/v1" "kind" = "Deployment" "metadata" = { "labels" = { "app" = "jaeger" } "name" = "jaeger" "namespace" = "istio-system" } "spec" = { "selector" = { "matchLabels" = { "app" = "jaeger" } } "template" = { "metadata" = { "annotations" = { "prometheus.io/port" = "14269" "prometheus.io/scrape" = "true" "sidecar.istio.io/inject" = "false" } "labels" = { "app" = "jaeger" } } "spec" = { "containers" = [ { "env" = [ { "name" = "BADGER_EPHEMERAL" "value" = "false" }, { "name" = "SPAN_STORAGE_TYPE" "value" = "badger" }, { "name" = "BADGER_DIRECTORY_VALUE" "value" = "/badger/data" }, { "name" = "BADGER_DIRECTORY_KEY" "value" = "/badger/key" }, { "name" = "COLLECTOR_ZIPKIN_HTTP_PORT" "value" = "9411" }, { "name" = "MEMORY_MAX_TRACES" "value" = "50000" }, { "name" = "QUERY_BASE_PATH" "value" = "/jaeger" }, ] "image" = "docker.io/jaegertracing/all-in-one:1.20" "livenessProbe" = { "httpGet" = { "path" = "/" "port" = 14269 } } "name" = "jaeger" "readinessProbe" = { "httpGet" = { "path" = "/" "port" = 14269 } } "resources" = { "requests" = { "cpu" = "10m" } } "volumeMounts" = [ { "mountPath" = "/badger" "name" = "data" }, ] }, ] "volumes" = [ { "emptyDir" = {} "name" = "data" }, ] } } } } }

resource "kubernetes_manifest" "service_tracing" { provider = kubernetes-alpha

manifest = { "apiVersion" = "v1" "kind" = "Service" "metadata" = { "labels" = { "app" = "jaeger" } "name" = "tracing" "namespace" = "istio-system" } "spec" = { "ports" = [ { "name" = "http-query" "port" = 80 "protocol" = "TCP" "targetPort" = 16686 }, ] "selector" = { "app" = "jaeger" } "type" = "ClusterIP" } } }

resource "kubernetes_manifest" "service_zipkin" { provider = kubernetes-alpha

manifest = { "apiVersion" = "v1" "kind" = "Service" "metadata" = { "labels" = { "name" = "zipkin" } "name" = "zipkin" "namespace" = "istio-system" } "spec" = { "ports" = [ { "name" = "http-query" "port" = 9411 "targetPort" = 9411 }, ] "selector" = { "app" = "jaeger" } } } }

resource "kubernetes_manifest" "service_jaeger_collector" { provider = kubernetes-alpha

manifest = { "apiVersion" = "v1" "kind" = "Service" "metadata" = { "labels" = { "app" = "jaeger" } "name" = "jaeger-collector" "namespace" = "istio-system" } "spec" = { "ports" = [ { "name" = "jaeger-collector-http" "port" = 14268 "protocol" = "TCP" "targetPort" = 14268 }, { "name" = "jaeger-collector-grpc" "port" = 14250 "protocol" = "TCP" "targetPort" = 14250 }, ] "selector" = { "app" = "jaeger" } "type" = "ClusterIP" } } }

Debug Output

Panic Output

Steps to Reproduce

terraform plan -out config.plan

Expected Behavior

What should have happened? Jaeger deployed to Kubernetes cluster

Actual Behavior

What actually happened? Got error during plan: Error: rpc error: code = Unknown desc = update dry-run for 'istio-system/zipkin' failed: failed to create typed patch object: .spec.ports: element 0: associative list with keys has an element that omits key field "protocol"

Important Factoids

References

Community Note

alexsomesan commented 3 years ago

@ggolub I just tried your configuration with the new v0.3.0 and I can apply it successfully.

Be aware of that you currently need to specify a value for the protocol attribute in the ports list of Service and Container. This is due to a bug in Kubernetes https://github.com/kubernetes-sigs/structured-merge-diff/issues/130

Once you add the protocol attribute your configuration should work fine.

alexsomesan commented 3 years ago

For reference, this is the configuration that worked for me:

resource "kubernetes_manifest" "namespace_istio" {
  provider = kubernetes-alpha

  manifest = {
    "apiVersion" = "v1"
    "kind"       = "Namespace"
    "metadata" = {
      "name" = "istio-system"
    }
  }
}

resource "kubernetes_manifest" "deployment_jaeger" {
  provider = kubernetes-alpha

  manifest = {
    "apiVersion" = "apps/v1"
    "kind"       = "Deployment"
    "metadata" = {
      "labels" = {
        "app" = "jaeger"
      }
      "name"      = "jaeger"
      "namespace" = kubernetes_manifest.namespace_istio.object.metadata.name
    }
    "spec" = {
      "selector" = {
        "matchLabels" = {
          "app" = "jaeger"
        }
      }
      "template" = {
        "metadata" = {
          "annotations" = {
            "prometheus.io/port"      = "14269"
            "prometheus.io/scrape"    = "true"
            "sidecar.istio.io/inject" = "false"
          }
          "labels" = {
            "app" = "jaeger"
          }
        }
        "spec" = {
          "containers" = [
            {
              "env" = [
                {
                  "name"  = "BADGER_EPHEMERAL"
                  "value" = "false"
                },
                {
                  "name"  = "SPAN_STORAGE_TYPE"
                  "value" = "badger"
                },
                {
                  "name"  = "BADGER_DIRECTORY_VALUE"
                  "value" = "/badger/data"
                },
                {
                  "name"  = "BADGER_DIRECTORY_KEY"
                  "value" = "/badger/key"
                },
                {
                  "name"  = "COLLECTOR_ZIPKIN_HTTP_PORT"
                  "value" = "9411"
                },
                {
                  "name"  = "MEMORY_MAX_TRACES"
                  "value" = "50000"
                },
                {
                  "name"  = "QUERY_BASE_PATH"
                  "value" = "/jaeger"
                },
              ]
              "image" = "docker.io/jaegertracing/all-in-one:1.20"
              "livenessProbe" = {
                "httpGet" = {
                  "path" = "/"
                  "port" = 14269
                }
              }
              "name" = "jaeger"
              "readinessProbe" = {
                "httpGet" = {
                  "path" = "/"
                  "port" = 14269
                }
              }
              "resources" = {
                "requests" = {
                  "cpu" = "10m"
                }
              }
              "volumeMounts" = [
                {
                  "mountPath" = "/badger"
                  "name"      = "data"
                },
              ]
            },
          ]
          "volumes" = [
            {
              "emptyDir" = {}
              "name"     = "data"
            },
          ]
        }
      }
    }
  }
}

resource "kubernetes_manifest" "service_tracing" {
  provider = kubernetes-alpha

  manifest = {
    "apiVersion" = "v1"
    "kind"       = "Service"
    "metadata" = {
      "labels" = {
        "app" = "jaeger"
      }
      "name"      = "tracing"
      "namespace" = kubernetes_manifest.namespace_istio.object.metadata.name
    }
    "spec" = {
      "ports" = [
        {
          "name"       = "http-query"
          "port"       = 80
          "protocol"   = "TCP"
          "targetPort" = 16686
        },
      ]
      "selector" = {
        "app" = "jaeger"
      }
      "type" = "ClusterIP"
    }
  }
}

resource "kubernetes_manifest" "service_zipkin" {
  provider = kubernetes-alpha

  manifest = {
    "apiVersion" = "v1"
    "kind"       = "Service"
    "metadata" = {
      "labels" = {
        "name" = "zipkin"
      }
      "name"      = "zipkin"
      "namespace" = kubernetes_manifest.namespace_istio.object.metadata.name
    }
    "spec" = {
      "ports" = [
        {
          "name"       = "http-query"
          "port"       = 9411
          "targetPort" = 9411
          "protocol"   = "TCP"
        },
      ]
      "selector" = {
        "app" = "jaeger"
      }
    }
  }
}

resource "kubernetes_manifest" "service_jaeger_collector" {
  provider = kubernetes-alpha

  manifest = {
    "apiVersion" = "v1"
    "kind"       = "Service"
    "metadata" = {
      "labels" = {
        "app" = "jaeger"
      }
      "name"      = "jaeger-collector"
      "namespace" = kubernetes_manifest.namespace_istio.object.metadata.name
    }
    "spec" = {
      "ports" = [
        {
          "name"       = "jaeger-collector-http"
          "port"       = 14268
          "protocol"   = "TCP"
          "targetPort" = 14268
        },
        {
          "name"       = "jaeger-collector-grpc"
          "port"       = 14250
          "protocol"   = "TCP"
          "targetPort" = 14250
        },
      ]
      "selector" = {
        "app" = "jaeger"
      }
      "type" = "ClusterIP"
    }
  }
}
ggolub commented 3 years ago

@alexsomesan Thanks for the update. I upgraded to 3.0 and, using your configuration, was able to get past the original error. However, I've since changed path to use jaeger-operator and am running into a similar issue:

Error: rpc error: code = Unavailable desc = transport is closing

Here's the code:

resource "kubernetes_namespace" "jaeger-operator" {
  metadata {
    labels = {
      name = "observability"
    }

    name = "observability"
  }
}

# recommendation is to deploy using 'operator'
resource "helm_release" "jaeger-operator" {
  depends_on = [kubernetes_namespace.jaeger-operator]

  name       = "jaeger-operator"
  chart      = "jaeger-operator"
  repository = var.chart_repository
  version    = var.chart_version
  namespace  = kubernetes_namespace.jaeger-operator.metadata[0].name

  set {
    name  = "rbac.clusterRole"
    value = "true"
  }

  set {
    name  = "jaeger.env.WATCH_NAMESPACE"
    value = ""
  }
}

resource "kubernetes_manifest" "jaeger-instance" {
  # count = 0
  provider = kubernetes-alpha

  manifest = {
    "apiVersion" = "jaegertracing.io/v1"
    "kind"       = "Jaeger"

    "metadata" = {
      "name"      = "jaeger-prod"
      "namespace" = kubernetes_namespace.jaeger-operator.metadata[0].name
    }

    "spec" = {
      "strategy" = "production"
      "collector" = {
        "maxReplicas" = 5
        "resources" = {
          "limits" = {
            "cpu"    = "100m"
            "memory" = "128Mi"
          }
        }
        "storage" = {
          "type" = "elasticsearch"
          "options" = {
            "es" = {
              "server-urls" = "http://elasticsearch-master.elastic-system.svc.cluster.local:9200"
            }
          }
        }
      }
    }
  }
}

Removing resource kubernetes_manifest.jaeger-instance allows the plan to complete successfully.