后来还用到了Python Terraform package, 结合Python Click 以及其他custom Python package 去构造glue code.
Introduction
To alter a planet for the purpose of sustaining life.
This article from IBM can give you a good overview:
- Terraform vs Kubernetes
- Terraform vs Ansible
Removing manual build process, adopting declarative approach to deploy infrastructure as code, reusable, idempotent and consistent repeatable deployment.
Use gcloud API or client binary can do the same work as Terraform, so what are the benefits
:
- cloud agnostic, multi-cloud portable.
- Unified workflow: If you are already deploying infrastructure to Google Cloud with Terraform, your resources can fit into that workflow.
- Full lifecycle management: Terraform doesn’t only create resources, it updates, and deletes tracked resources without requiring you to inspect the API to identify those resources.
- Graph of relationships: Terraform understands dependency relationships between resources.
Terraform 文档非常informative,结构清晰: Terraform之于cloud infra on public cloud 就相当于 helm之于application on k8s, 大大简化了操作复杂性,自动快速部署,同时做到了复用,versioning等特性。但得去了解cloud provider中提供的resources 的用途,搭配。
Github Repo
resource files in github: https://github.com/ned1313/Getting-Started-Terraform
Composition
Terraform executable: download from web (or build terraform docker image) Terraform files: using hashicorp configure language DSL Terraform plugin: interact with provider: AWS, GCP, Azure, etc Terraform state file: json and don’t touch it but you can view it to get deployment detial
You can have multiple terraform files: .tf
, when run terraform it will stitch them together to form a single configuration. 比如把variables, outputs, resources, tfvars分开。
tfvars file by default named as terraform.tfvars
, otherwise when run plan
you need to specify the file path. This tfvars
file is usually generated from some meta-data configuration, then combining with variable declaration file.
Commands
To execute terraform command, build a docker image and mount cloud auth credentials when start container. BTW, if you run on google compute VM, the SDK will inject the host auth automatucally in container.
If you update the terraform file with different configuration, rerun init
, plan
and apply
.
1 | # list all commands |
Syntax
Hashicorp configuration language, basic block syntax:
1 | block_type label_one [label_two] { |
怎么知道resource的名称呢? find the provider, then search the resources: https://www.terraform.io/docs/configuration/resources.html 还有random provider,比如产生随机数.
Provider
Support mutliple providers, all written in Go. https://www.terraform.io/docs/providers/index.html
Provisioner
在deploy infrastructure 之后的配置操作,比如使用ansible or shell script as privisioners.
Provisioner can be ran in creation or destruction stage, you can also have multi-provisioner in one resources and they execute in order in resource.
Provisioner can be local or remote:
- file: copy file from local to remove VM instance.
- local-exec: executes a command locally on the machine running Terraform, not the VM instance itself.
- remote-exec: executes on remote VM instance.
Terraform treats provisioners differently from other arguments. Provisioners only run when a resource is created, adding a provisioner does not force that resource to be destroyed and recreated. Use terraform taint
to tell Terraform to recreate the instance.
Functions
https://www.terraform.io/docs/configuration/functions.html
You can experiment with functions in Terraform console, this can help with troubleshooting.
1 | # first run terraform init |
For example:
1 | variable network_info { |
Resource arguments
https://www.terraform.io/docs/configuration/resources.html#meta-arguments common ones:
- depends_on: make sure terraform creates things in right order
- count: create similar resources
- for_each: create resources not similar
- provider: which provider should create the resource
For example:
1 | resource "aws_instance" "web" { |
Variables
Other way to use variables rather than specifying in single .tf
file.
The scenario, we need development, QA(Quality Assurance)/UAT(User Acceptance Testing), production environment, how to implement with one configuration and multiple inputs?
The variable values can be from, precedence from low to high:
- environment variable:
TF_VAR_<var name>
. - file:
terraform.tfvars
or specify by-var-file
in terraform command. - terraform command flags
-var
.
You can override variables and precedence, select value based on environment, for example:
1 | # specify default value in tf file |
Variable types:
- string, the default type if no explicitly specified
- bool: true, false
- number (integer/decimal)
- list (index start from 0)
- map, value type can be number, string and bool
For example:
1 | variable "project" { |
In terraform, the same syntax ${}
for interpolation as in bash:
1 | # local variable definition |
Workspace
Workspace is the recommended way to working with multiple environments, for example:
- state management
- variables data
- credentials management
State file example, we have dev, QA, prod three environments, put them each into separate folder, when run command, specify the input and output:
1 | # for dev environment |
Workspace example, there is a terraform.workspace
built-in variable can be used to indicate the workspace currently in, then use it in map variable to select right value for different environment. (不用再去分别创建不同的folder for different environment了)
1 | # create dev workspace and switch to it |
Special terraform variable to get workspace name
1 | locals { |
Managing secrets
Hashicorp Vault is for this purpose. it can hand over credentials from cloud provider to terraform and set ttl for the secrets.
Or you can use environment variable to specify the credentials, terraform will pick it automatically, but bear in mind to use the right env var name. For example:
1 | # 注意这个和前面的TF_VAR_<var name> 不一样,这里是secret |
Module
Make code reuse eaiser: https://www.terraform.io/docs/configuration/modules.html
Terraform registry, similar concept with Helm, Docker: https://registry.terraform.io/ Using module block to invoke local or remote modules.
- root module
- support versioning
- provider inheritance
Module components:
- variables input
- resources
- output values (calling part will take this in)
Google Cloud Platform
Good tutorial: https://learn.hashicorp.com/tutorials/terraform/google-cloud-platform-build
If run terraform apply
get permission issues, add the service account used to IAM, than grant it roles. Then retry the apply command.
用Terraform 建造的VM instance network 没有ssh allow firewall rule, 要自己添加: https://cloud.google.com/compute/docs/troubleshooting/troubleshooting-ssh
Terrafrom provisions GKE
with additional node pool:
https://learn.hashicorp.com/terraform/kubernetes/provision-gke-cluster
Resources
Commonly use reource types for terraform resource
block:
- google_compute_network
- google_compute_instance
- google_compute_address
- google_storage_bucket
- google_container_cluster
- google_container_node_pool