kubectl Terraform Provider

repository·master·Indexed 42 days ago

https://github.com/alekc/terraform-provider-kubectl

A Terraform provider that allows users to manage Kubernetes resources using raw YAML manifests. It features lifecycle management, drift detection, and the ability to handle sensitive data via ephemeral kubectl_manifest resources (requiring Terraform 1.10+). The provider supports coexistence with the standard kubernetes provider and offers migration paths from gavinbunney/kubectl using moved blocks or state replace-provider.

Tokens
19.6K
Snippets
51
Records
70
Agent score
54%

What's inside kubectl

  1. Overview of the kubectl provider

    master

    The terraform-provider-kubectl is a Terraform provider designed to manage Kubernetes resources using raw YAML manifests. Its core component is the kubectl_manifest resource, which allows you to apply free-form YAML to a cluster while providing full lifecycle management (create, update, delete) and drift detection.

    Key capabilities include:

    • Resource Management: Apply raw YAML manifests via kubectl_manifest.
    • Data Discovery: Use data sources to read objects from the cluster, glob YAML files in directories, or split multi-document YAML strings.
    • Server Information: Read API-server version information.
    • Ephemeral Resources: Use kubectl_manifest as an ephemeral resource (Terraform 1.10+) to fetch values without persisting them to the Terraform state.
  2. Manage Kubernetes resources with kubectl_manifest

    master

    The kubectl_manifest resource allows you to manage the complete lifecycle (creation, deletion, and updates) of Kubernetes resources using raw YAML manifests. It behaves similarly to kubectl apply, enabling in-place updates when the YAML is modified.

    Important Limitation: This resource only supports a single YAML document. If your file contains multiple documents, use the kubectl_path_documents data source to split them into individual resources.

    Automatic Rollout Waiting: When the kind is a Deployment, the provider automatically waits for the deployment to roll out by default.

    resource "kubectl_manifest" "test" {
        yaml_body = <<YAML
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: test-ingress
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /
        azure/frontdoor: enabled
    spec:
      rules:
      - http:
          paths:
          - path: /testpath
            pathType: "Prefix"
            backend:
              serviceName: test
              servicePort: 80
    YAML
    }
  3. Use retry support for flaky operations

    master

    The apply_retry_count argument allows the provider to retry Kubernetes commands if the initial apply fails. This is useful for handling flaky CRDs or waiting for a cluster to reach quorum.

    • Behavior: apply_retry_count = N performs the initial attempt and then retries up to N additional times (totaling N + 1 attempts).
    • Backoff: Uses exponential backoff starting at 3 seconds, capped at 30 seconds.
    • Configuration: Can be set in the provider block or via the KUBECTL_PROVIDER_APPLY_RETRY_COUNT environment variable.
    • Disabling: Set apply_retry_count = 0 to disable retries and perform a single-shot apply.
    provider "kubectl" {
      apply_retry_count = 15
    }
  4. Use the kubectl_manifest ephemeral resource for sensitive data

    master

    The kubectl_manifest ephemeral resource reads a single Kubernetes object from the cluster using api_version, kind, name, and optionally namespace.

    Key distinction: Unlike the kubectl_manifest data source, values produced by this resource are never written to Terraform state or plan files. It re-fetches the data on every plan and apply and then discards it. Use this specifically for data that must not be persisted at rest, such as Secret payloads, private keys, or freshly-minted tokens.

    Requirements: Requires Terraform 1.10 or later.

    ephemeral "kubectl_manifest" "example" {
      api_version = "v1"
      kind        = "Secret"
      name        = "my-secret"
      namespace   = "default"
    }
  5. Behavioral constraints of kubectl_manifest ephemeral resource

    master

    When using kubectl_manifest as an ephemeral resource, be aware of the following behaviors:

    • No Exports: Ephemeral values cannot be exported via output. Terraform forbids this to prevent accidental leakage into state.
    • Automatic Re-fetching: The resource is re-fetched on every plan/apply that references it. Changes in the live cluster are picked up automatically.
    • State Protection: The values never appear in terraform.tfstate or in terraform plan -out files.
    • Error Handling: Errors such as 'object not found', unresolved fields paths, or malformed path syntax will abort the open and propagate as Terraform diagnostics.
  6. Use the kubectl_path_documents data source to load YAML manifests

    master

    The kubectl_path_documents data source allows you to find and split multi-document YAML files matching a specific glob pattern. It combines the functionality of finding files and parsing their individual YAML documents. It also supports Terraform template rendering, allowing you to parameterize your manifests using variables.

    data "kubectl_path_documents" "example" {
      pattern = "./manifests/*.yaml"
    }
  7. Choose a drift detection engine

    master

    The drift_engine argument determines how the provider compares your manifest to the live cluster state. Both engines output the same drift attribute format.

    client (default)

    Flattens the manifest and live object into dotted paths and compares them per-key. It does not make extra API calls. It ignores fields added by the apiserver (status, defaults, etc.). Use when: You want standard behavior or have existing ignore_fields configurations. It may report false drift on objects mutated by admission webhooks or those undergoing normalization (e.g., memory units).

    server (opt-in)

    Calls the apiserver using a Patch(ApplyPatchType, body, DryRun: All) request. The response from this dry-run is used as the 'desired' side of the comparison. Use when: The client engine reports false drift (common with operator-managed objects, CRDs with server-side defaulting, or admission webhooks).

    Trade-offs for server engine:

    • ✅ Handles strategic-merge on arrays (no false drift from reordering).
    • ✅ Absorbs server-side defaulting and type coercion (e.g., 2048Mi vs 2Gi).
    • ✅ Shows actual changes that a real apply would make.
    • ⚠ One extra API call per Read (can increase plan time).
    • ⚠ Requires PATCH verb permissions on the resource.
    • ⚠ Warning: Ensure custom admission webhooks honor ?dryRun=All to avoid side effects (like sending Slack messages) during a Terraform plan.
    # Using the server engine for high-fidelity drift detection
    resource "kubectl_manifest" "example" {
      yaml_body    = local.manifest_yaml
      drift_engine = "server"
    }
  8. Understand the impact of upgrading to alekc/kubectl v3.0.0

    master

    Upgrading to v3.0.0 involves a migration from the Terraform SDK v2 to the terraform-plugin-framework. While HCL syntax, schema attribute names, and the provider configuration block remain unchanged, users should be aware of the following potential behavioral shifts:

    • Plan Output Formatting: Diffs may be more precise, including better attribute paths in errors. CI scripts that grep terraform plan text may need updates.
    • Error Timing: Errors may surface at different lifecycle points (e.g., during plan vs apply) due to changes in how plan modifiers fire.
    • kubectl_manifest Diff Behavior: On the very first terraform plan after upgrading, you might see an unexpected one-time diff. If the provider is working correctly, this diff should converge (become a no-op) after the first apply.
    • Sensitive Marking: Outputs referencing sensitive resource attributes may trigger new "value will be marked as sensitive" notices due to improved sensitive propagation.
    • Empty vs Null: The framework distinguishes between "" (empty string) and null more strictly than SDK v2. If you explicitly set foo = "", ensure this is the intended behavior.
    • Diagnostic Messages: Error messages are now structured (summary + detail + attribute path) rather than flat strings. Pattern-matching logic in monitoring tools may break.
  9. Read sensitive data without persisting it using ephemeral kubectl_manifest

    master

    To handle sensitive data like Secret payloads, tokens, or private keys without writing them to terraform.tfstate or the plan file, use the ephemeral "kubectl_manifest" resource. This requires Terraform 1.10+.

    Key Behaviors:

    • Values are re-fetched on every plan/apply.
    • Ephemeral values cannot flow through output blocks.
    • They must be consumed during apply via a resource's write-only attribute (requires Terraform 1.11+), a provisioner, or a check block.

    In the example below, content_wo is used to write a password to a local file. The value is forgotten by Terraform immediately after the file is written and is never stored in state.

    ephemeral "kubectl_manifest" "db_creds" {
      api_version = "v1"
      kind        = "Secret"
      name        = "postgres-credentials"
      namespace   = "data"
    
      fields = {
        password = "data.password"
      }
    }
    
    # Example consumer: stage the password into a sibling tool's config
    # during apply, never to state. `content_wo` is a write-only attribute
    # (Terraform 1.11+); the value is forgotten after the file is written.
    resource "local_file" "db_password" {
      filename            = "${path.module}/.db-password"
      content_wo          = ephemeral.kubectl_manifest.db_creds.results["password"]
      content_wo_revision = 1
    }
  10. Use wait_for to ensure resource readiness

    master

    The kubectl_manifest resource can be configured to wait for specific conditions to be met in the cluster before completing the Terraform operation. This is controlled via the wait_for block.

    Arguments within wait_for:

    • field: The specific field in the resource to monitor.
    • condition: The condition that must be met (e.g., checking if a field matches a specific value).
  11. Split multi-document YAML files with kubectl_file_documents

    master

    The kubectl_file_documents data source allows you to split a single YAML file containing multiple documents (separated by ---) into individual components that can be managed as separate Terraform resources. This is useful for processing large Kubernetes manifest files.

    data "kubectl_file_documents" "docs" {
        content = file("multi-doc-manifest.yaml")
    }
  12. Use single-file Terraform configurations for examples

    master
    When using or adapting examples from the _examples directory, ensure that each .tf file is treated as a standalone configuration. The examples are designed and tested as single-file units; do not attempt to use multi-file Terraform configurations when referencing these specific examples.