Skip to content

Instantly share code, notes, and snippets.

@priyanka-ravi
Last active April 27, 2022 18:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save priyanka-ravi/c27296569d5dd91da51f978af80f6ca1 to your computer and use it in GitHub Desktop.
Save priyanka-ravi/c27296569d5dd91da51f978af80f6ca1 to your computer and use it in GitHub Desktop.

This demo will walk you through some of the features of the Terraform Controller for Flux

Set up local cluster, Flux CLI, and tfctl CLI

  1. Install Flux CLI and Kind (If not using a mac you can find installation instructions on both project's getting started guides)

    $ brew reinstall flux kind
    $ kind --version
    kind version 0.11.1
    $ flux --version
    flux version 0.16.2
  2. Install tfctl CLI

    You can download the tfctl binary via the GitHub releases page: https://github.com/weaveworks/tf-controller/releases

  3. Create local demo cluster

    $ kind create cluster --name flux
    (took 37s)

Set up for Flux with GitHub as source

  1. Make Personal Access Token for creating repositories

    1. Check all permissions under repo
    2. Copy PAT to buffer
  2. Export env vars locally

    $ read -s GITHUB_TOKEN
    [paste PAT]
    $ export GITHUB_TOKEN=$GITHUB_TOKEN
    

Bootstrap Flux both for your source and in cluster

  1. Simple bootstrap:

    $ flux bootstrap github \
    --owner priyanka-ravi \
    --personal \
    --private \
    --repository tf-controller-demo \
    --path=clusters
    ► connecting to github.com
    ✔ repository "https://github.com/priyanka-ravi/tf-controller-demo" created
    ► cloning branch "main" from Git repository "https://github.com/priyanka-ravi/tf-controller-demo.git"
    ✔ cloned repository
    ► generating component manifests
    ✔ generated component manifests
    ✔ committed sync manifests to "main" ("8122eb8f6cd0c520a757aafde01462946e2b07e8")
    ► pushing component manifests to "https://github.com/priyanka-ravi/tf-controller-demo.git"
    ► installing components in "flux-system" namespace
    ✔ installed components
    ✔ reconciled components
    ► determining if source secret "flux-system/flux-system" exists
    ► generating source secret
    ✔ public key: ssh-rsa ****
    ✔ configured deploy key "flux-system-main-flux-system-./clusters" for "https://github.com/priyanka-ravi/tf-controller-demo"
    ► applying source secret "flux-system/flux-system"
    ✔ reconciled source secret
    ► generating sync manifests
    ✔ generated sync manifests
    ✔ committed sync manifests to "main" ("06360186166df1ebbba33b5be07bea60b77e39f1")
    ► pushing sync manifests to "https://github.com/priyanka-ravi/tf-controller-demo.git"
    ► applying sync manifests
    ✔ reconciled sync configuration
    ◎ waiting for Kustomization "flux-system/flux-system" to be reconciled
    ✔ Kustomization reconciled successfully
    ► confirming components are healthy
    ✔ source-controller: deployment ready
    ✔ kustomize-controller: deployment ready
    ✔ helm-controller: deployment ready
    ✔ notification-controller: deployment ready
    ✔ all components are healthy
    (took 1m12s)

Install the Terraform Controller helm chart

  1. Clone the newly created git repo to your local workspace

    $ git clone git@github.com:priyanka-ravi/tf-controller-demo.git
    $ cd flux-demo
  2. Make directory for the terraform controller files

    $ mkdir -p clusters/my-cluster/tf-controller
  3. Add a new file in this new folder called tf-controller-helm.yaml with the following code:

    apiVersion: source.toolkit.fluxcd.io/v1beta1
    kind: HelmRepository
    metadata:
      name: tf-controller
      namespace: flux-system
    spec:
      interval: 1h0s
      url: https://weaveworks.github.io/tf-controller/
    ---
    apiVersion: helm.toolkit.fluxcd.io/v2beta1
    kind: HelmRelease
    metadata:
      name: tf-controller
      namespace: flux-system
    spec:
      chart:
        spec:
          chart: tf-controller
          sourceRef:
            kind: HelmRepository
            name: tf-controller
          version: '>=0.2.5'
      interval: 1h0s
      releaseName: tf-controller
      targetNamespace: flux-system
      install:
        crds: Create
      upgrade:
        crds: CreateReplace
      values:
        replicaCount: 1
        image:
          tag: v0.9.3
        runner:
          image:
            tag: v0.9.3
  4. Reconcile the flux-system source and kustomization

    $ flux reconcile ks flux-system --with-source
    ► annotating GitRepository flux-system in flux-system namespace
    ✔ GitRepository annotated
    ◎ waiting for GitRepository reconciliation
    ✔ fetched revision main/c3c1f17d548afa8f6f083973c39088e621abb018
    ► annotating Kustomization flux-system in flux-system namespace
    ✔ Kustomization annotated
    ◎ waiting for Kustomization reconciliation
    ✔ applied revision main/c3c1f17d548afa8f6f083973c39088e621abb018
  5. Verify that the terraform controller is now deployed

    $ kubectl -n flux-system get pods
    NAME                                       READY   STATUS    RESTARTS   AGE
    helm-controller-845959fb9f-46x9t           1/1     Running   0          48m
    kustomize-controller-6f44c8d499-vpvvt      1/1     Running   0          48m
    notification-controller-5c7b759c64-kvcp5   1/1     Running   0          48m
    source-controller-6b6c7bc4bb-74tfz         1/1     Running   0          48m
    tf-controller-f65f5f4f5-h979s              1/1     Running   0          43m

Set up a separate repository with a terraform main.tf file such as:

terraform {
  required_version = ">= 0.12.26"
}

variable "subject" {
   type = string
   default = "World"
   description = "Subject to hello"
}

output "hello_world" {
  value = "Hello, ${var.subject}!"
}

Set up a source and terraform resource pointing to that new repository

  1. Under the tf-controller-demo repo (the bootstrapped repo) add a file called helloworld-sync.yaml with the following code:

    apiVersion: source.toolkit.fluxcd.io/v1beta1
    kind: GitRepository
    metadata:
      name: helloworld
      namespace: flux-system
    spec:
      interval: 30s
      url: https://github.com/priyanka-ravi/hello-world-terraform
      ref:
        branch: main
    ---
    apiVersion: infra.contrib.fluxcd.io/v1alpha1
    kind: Terraform
    metadata:
      name: helloworld
      namespace: flux-system
    spec:
      approvePlan: ""
      interval: 1m
      path: ./
      sourceRef:
        kind: GitRepository
        name: helloworld
        namespace: flux-system

    Note that approvePlan under the spec is set to an empty string. This means that plans will have to be manually approved.

  2. Reconcile the flux-system source and kustomization and verify the new helloworld source and terraform resource are created

    $ flux reconcile kustomization flux-system --with-source
    $ kubectl get terraform -n flux-system
    NAME         READY     STATUS                                                                          AGE
    helloworld   Unknown   Plan generated: set approvePlan: "plan-main-155d95d1aa" to approve this plan.   49m
    $ tfctl get
    NAME      	READY  	MESSAGE                                                                      	PLAN PENDING	SUSPENDED 
    helloworld	Unknown	Plan generated: set approvePlan: "plan-main-155d95d1aa" to approve this plan.	true        	false  

    Note the two different ways you can get the terraform resource. One is through the kubectl CLI and one is using the tfctl CLI.

  3. View and approve the plan

    tfctl --terraform=/usr/local/bin/terraform plan show helloworld

    Note: Currently the tfctl CLI is hardcoded to look for the terraform binary in the /usr/bin. You can point it to your terraform location with the --terraform flag.

    Add "plan-main-155d95d1aa" to the approvePlan value in the helloworld-sync.yaml file and push changes to git.

  4. Reconcile flux-system

    $ flux reconcile kustomization flux-system --with-source
    $ tfctl get                            
    NAME      	READY	MESSAGE                                                            	PLAN PENDING	SUSPENDED 
    helloworld	True 	Applied successfully: main/155d95d1aad0b24942b97b82375d022dcc17b46d	false       	false 

Show auto apply and how to output to a Kubernetes secret

  1. In the helloworld.yaml file change the approvePlan value to auto

  2. Add this snippet under spec:

    writeOutputsToSecret:
      name: helloworld-output
  3. Reconcile flux-system

    $ flux reconcile kustomization flux-system --with-source
  4. View the secret output

    $ kubectl -n flux-system get secrets
    $ kubectl -n flux-system get secret helloworld-output -o yaml
  5. Take the value from the data of the secret and base64 decode it

    $ echo "SGVsbG8sIERlbW8h" | base64 -D
    Hello, World!%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment