Tofu Controller

repository·main·Indexed 23 days ago

https://github.com/flux-iac/tofu-controller

An IaC controller for Flux that enables GitOps workflows for OpenTofu and Terraform resources. It provides Kubernetes-native reconciliation for infrastructure management, supporting four GitOps models: GitOps Automation, Hybrid GitOps Automation, State Enforcement, and Drift Detection.

Tokens
40.3K
Snippets
93
Records
183
Agent score
82%

What's inside tofu-controller

  1. What is Tofu Controller and how can it be used?

    main

    Tofu Controller (formerly Weave TF-Controller) is a controller for Flux designed to reconcile OpenTofu and Terraform resources using GitOps principles. It allows you to manage infrastructure and application resources within the Kubernetes and IaC universe at different levels of automation.

    Depending on your needs, you can adopt one of four GitOps models:

    1. GitOps Automation Model: Full automation from provisioning to enforcement (e.g., managing an entire EKS cluster).
    2. Hybrid GitOps Automation Model: Partial automation of existing infrastructure (e.g., managing only specific nodegroups or security groups within an existing cluster).
    3. State Enforcement Model: Using GitOps to enforce an existing TFSTATE file without modifying other aspects of the infrastructure.
    4. Drift Detection Model: Using GitOps solely to detect drift against an existing TFSTATE file, allowing for manual intervention when changes occur.
  2. Use Tofu Controller for various IaC workflows

    main

    Tofu Controller supports a wide range of Infrastructure as Code (IaC) workflows using OpenTofu/Terraform. You can use it to:

    • Provision resources with auto-approval: Automatically apply changes when a plan is generated.
    • Plan and manually apply: Generate a plan for review before performing a manual application.
    • Detect drifts only: Run drift detection without triggering a plan or apply cycle.
    • Manage resource lifecycles: Provision resources, obtain outputs, and automatically destroy resources when the corresponding Terraform object is deleted.
    • Configure advanced settings: Set variables, use custom backends, utilize OCI artifacts as sources, and manage GitOps dependencies.
    • Integrate with external systems: Work with Terraform Enterprise/Cloud, private registries, and external webhooks.
    • Customize execution: Use customized Runner Pods, control init -upgrade behavior, and configure plan-only options (e.g., -lock=false).
    • Handle specialized environments: Run on AWS (including EKS IRSA) or Azure Kubernetes Service (AKS).

    For specific implementation details, refer to the individual guide for your required workflow.

  3. Overview of the Branch Planner

    main

    The Branch Planner is a component of TF-Controller designed to facilitate GitOps-driven infrastructure planning. It allows developers to plan Terraform configurations on branches separate from the main branch, enabling impact review before merging.

    Key Workflow:

    1. Detection: When enabled via Helm, it watches repositories for Terraform resources and polls for Pull Requests (GitHub) or Merge Requests (GitLab) using a provider's API and a provided token.
    2. Automated Planning: When changes are proposed on a new branch, the Branch Planner runs a terraform plan within the cluster.
    3. Feedback Loop: The plan results are posted directly as comments on the PR/MR.
    4. Reconciliation: Once the branch is merged into main, TF-Controller reconciles the updated code.

    Supported Providers:

    • GitHub (including GitHub Enterprise)
    • GitLab (including self-hosted)
    • Bitbucket Cloud
    • Bitbucket Server
    • Gitea
    • Azure DevOps (experimental)

    Note: The provider is automatically detected based on the GitRepository source URL.

  4. What is a primitive module?

    main

    A primitive module is a specific type of Terraform module designed for use with Tofu Controller. It follows these requirements:

    • Single Resource: It must contain only one single resource.
    • Required Variable: It must contain a variable named values.
    • Variable Type: The values variable must be an object with fields of optional types.
    • Directory Structure: The module must be located in a directory named after the resource it manages.
    • Bundling: A collection of primitive modules bundled into an OCI image is referred to as a package.

    Note: This pattern requires Tofu Controller v0.13 or later.

  5. Overview of Tofu Controller GitOps Models

    main

    Tofu Controller is a controller for Flux that allows you to reconcile Terraform resources using GitOps principles. It supports four primary operational models depending on your existing infrastructure state:

    1. GitOps Automation Model: Full automation from provisioning to enforcement (e.g., managing an entire EKS cluster).
    2. Hybrid GitOps Automation Model: Automating specific parts of existing infrastructure (e.g., managing only a specific nodegroup or security group within an existing cluster).
    3. State Enforcement Model: Using an existing TFSTATE file and applying GitOps to enforce that state without modifying other components.
    4. Drift Detection Model: Using an existing TFSTATE file for read-only drift detection to identify discrepancies between live systems and Terraform resources.
  6. What is a Tofu Controller package?

    main

    A package is a collection of primitive Terraform modules bundled into an OCI image. It acts as a thin wrapper around a Terraform module provider.

    Currently, Tofu Controller ships a ready-to-use AWS Package by default. This package is lightweight and does not add significant burden to your cluster. You can verify its installation by running flux get sources oci, where it should appear as aws-package.

    flux get sources oci
  7. What is GitOps Automation mode?

    main

    GitOps Automation mode allows Tofu Controller to automatically apply Terraform changes without manual intervention. This is enabled by setting the approvePlan field to auto in the Terraform resource specification.

    In this mode, the controller will:

    1. Detect changes in the source.
    2. Run a Terraform plan.
    3. Automatically apply the plan if it succeeds.
  8. Understand the polling mechanism for the branch-based planner

    main

    The branch-based planner uses a polling mechanism instead of webhooks to track changes in Git providers (like GitHub). This approach is chosen for two main reasons:

    1. Security: Unlike webhooks, which require exposing a publicly accessible endpoint in the Kubernetes cluster, polling allows the cluster to initiate outbound requests to the Git provider. This reduces the attack surface by not exposing the cluster to the internet.
    2. Portability: Polling provides a standardized way to interact with different Git providers (GitHub, GitLab, Bitbucket) via their RESTful APIs, avoiding the need to implement and maintain custom webhook parsing logic for each provider's specific message format.

    Trade-offs to consider:

    • Latency: There is an inherent delay between an event occurring in Git and the next scheduled poll.
    • Load: Frequent polling increases the load on the Git provider's API.
    • Rate Limits: High-frequency polling can exhaust API rate limits.
  9. How the polling mechanism handles pod restarts

    main

    The polling mechanism for the branch-based planner uses in-memory state management to track changes in Pull Requests (PRs) and PR comments efficiently. Because the state is stored in memory, it is lost if a pod restarts.

    To ensure reliability, the system follows these principles:

    • Statelessness and Idempotency: The system is designed to be stateless. Upon restart, it does not rely on previous local state.
    • Single Source of Truth: The system treats the GitHub API as the single source of truth.
    • State Regeneration: When a pod restarts, it regenerates the necessary state by querying the GitHub API. It retrieves the current state from GitHub, compares it with the results of the subsequent poll, and resumes tracking changes effectively.

    This design avoids dependencies on external storage systems while maintaining the ability to track changes between consecutive polls.

  10. How Workspace BLOB caching works in Tofu Controller

    main

    To resolve issues with deleting Terraform resources (single objects, dependent resources, or namespaces), the Tofu Controller uses a Workspace BLOB caching mechanism.

    The Workflow

    1. Generation: The tf-runner processes a Source BLOB, generating a Workspace file system (including backend configurations, variable files, and data from Secrets/ConfigMaps). This file system is compressed into a tar.gz BLOB.
    2. Storage: The Tofu Controller retrieves this BLOB and stores it on its local disk. The filename is based on the Terraform object's UUID: ${uuid}.tar.gz.
    3. Lifecycle: The caching mechanism is triggered immediately before the Terraform Initialization step. To prevent unauthorized access and collisions, the cache file is deleted once the finalization process is complete.

    Security and Encryption

    • Encryption: The tf-runner handles both encryption and decryption. The Tofu Controller only stores the encrypted BLOBs.
    • Key Management: Each namespace should have a service account (recommended name: tf-runner). The Kubernetes service account token is used as the encryption key, allowing for RBAC-controlled access and key rotation via Secrets.
    • Integrity: Checksums are used for integrity verification, and local disk storage uses 0600 permissions to ensure write protection.
  11. How cross-namespace references work in Tofu Controller

    main

    By default, Tofu Controller enforces namespace isolation for security. Terraform objects and Branch Planner configurations can only reference other objects (such as Flux sources, dependencies, or secrets) if they reside in the same namespace or if the namespace field is omitted.

    If a reference points to an object in a different namespace, Tofu Controller will stop processing that Terraform object and mark it in a non-Ready state.

    Supported cross-namespace reference fields include:

    Terraform CRD (.spec):

    • .spec.sourceRef: Refers to a Flux source.
    • .spec.dependsOn[*]: Refers to dependencies.
    • .spec.cliConfigSecretRef: Refers to a Secret containing tf configuration.

    Branch Planner configuration:

    • .secretNamespace: The namespace of the secret containing a GitHub token.
    • .resources[*]: Refers to Terraform objects to include in branch planning.