Terraform的使用

1. 安装terraform

mac

brew tap hashicorp/tap
brew install hashicorp/tap/terraform

linux: centos

sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install terraform

2. terraform命令

编写terraform的部署文本,常用命令:

  1. terraform init:项目初始化

  2. terraform plan:预览

  3. terraform apply:部署

  4. terraform destroy:销毁

terraform --help
Usage: terraform [global options] <subcommand> [args]

The available commands for execution are listed below.
The primary workflow commands are given first, followed by
less common or more advanced commands.

Main commands:
  init          Prepare your working directory for other commands
  validate      Check whether the configuration is valid
  plan          Show changes required by the current configuration
  apply         Create or update infrastructure
  destroy       Destroy previously-created infrastructure

All other commands:
  console       Try Terraform expressions at an interactive command prompt
  fmt           Reformat your configuration in the standard style
  force-unlock  Release a stuck lock on the current workspace
  get           Install or upgrade remote Terraform modules
  graph         Generate a Graphviz graph of the steps in an operation
  import        Associate existing infrastructure with a Terraform resource
  login         Obtain and save credentials for a remote host
  logout        Remove locally-stored credentials for a remote host
  metadata      Metadata related commands
  modules       Show all declared modules in a working directory
  output        Show output values from your root module
  providers     Show the providers required for this configuration
  refresh       Update the state to match remote systems
  show          Show the current state or a saved plan
  stacks        Manage HCP Terraform stack operations
  state         Advanced state management
  taint         Mark a resource instance as not fully functional
  test          Execute integration tests for Terraform modules
  untaint       Remove the 'tainted' state from a resource instance
  version       Show the current Terraform version
  workspace     Workspace management

3. 通过terraform部署k8s应用

3.1. 创建部署文件

创建应用目录,并在本地创建main.tf文件。

terraform {
  required_providers {
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = ">= 2.0.0"
    }
  }
}
provider "kubernetes" {
  config_path = "~/.kube/config"
}
resource "kubernetes_namespace" "test" {
  metadata {
    name = "nginx"
  }
}
resource "kubernetes_deployment" "test" {
  metadata {
    name      = "nginx"
    namespace = kubernetes_namespace.test.metadata.0.name
  }
  spec {
    replicas = 2
    selector {
      match_labels = {
        app = "MyTestApp"
      }
    }
    template {
      metadata {
        labels = {
          app = "MyTestApp"
        }
      }
      spec {
        container {
          image = "nginx"
          name  = "nginx-container"
          port {
            container_port = 80
          }
        }
      }
    }
  }
}
resource "kubernetes_service" "test" {
  metadata {
    name      = "nginx"
    namespace = kubernetes_namespace.test.metadata.0.name
  }
  spec {
    selector = {
      app = kubernetes_deployment.test.spec.0.template.0.metadata.0.labels.app
    }
    type = "NodePort"
    port {
      node_port   = 30201
      port        = 80
      target_port = 80
    }
  }
}

3.2. 执行部署命令

  • terraform init

初始化terraform provider数据。

  • terraform plan

部署之前预览diff数据。

# terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # kubernetes_deployment.test will be created
  + resource "kubernetes_deployment" "test" {
      + id               = (known after apply)
      + wait_for_rollout = true

      + metadata {
          + generation       = (known after apply)
          + name             = "nginx"
          + namespace        = "nginx"
          + resource_version = (known after apply)
          + uid              = (known after apply)
        }

      + spec {
          + min_ready_seconds         = 0
          + paused                    = false
          + progress_deadline_seconds = 600
          + replicas                  = "2"
          + revision_history_limit    = 10
....
Plan: 3 to add, 0 to change, 0 to destroy.
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
  • terraform apply

执行部署的操作。

# terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # kubernetes_deployment.test will be created
  + resource "kubernetes_deployment" "test" {
      + id               = (known after apply)
      + wait_for_rollout = true
...
Plan: 3 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

kubernetes_namespace.test: Creating...
kubernetes_namespace.test: Creation complete after 0s [id=nginx]
kubernetes_deployment.test: Creating...
kubernetes_deployment.test: Creation complete after 4s [id=nginx/nginx]
kubernetes_service.test: Creating...
kubernetes_service.test: Creation complete after 0s [id=nginx/nginx]

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

查看部署结果

terraform共创建了三个资源,即对应k8s的三个对象:namespace,deployment,service。

# kubectl get all -n nginx
NAME                        READY   STATUS    RESTARTS   AGE
pod/nginx-658c56bc8-djhrx   1/1     Running   0          30m
pod/nginx-658c56bc8-mh67k   1/1     Running   0          30m

NAME            TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
service/nginx   NodePort   10.96.65.155   <none>        80:30201/TCP   30m

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   2/2     2            2           30m

NAME                              DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-658c56bc8   2         2         2       30m

部署后会生成terraform.tfstate本地状态记录文件。

  • terraform destroy

如果需要清理数据,则可以使用destroy命令清理。

4. 总结

本文以k8s平台为例展示了terraform的基本使用步骤,相比于kubectl和helm的k8s部署工具,terraform无根本区别。

  • terraform的优势在于以IaC(基础设施即代码)和GitOps的思想把将基础设施相关的运维部署操作以声明式的方式记录在代码中,通过Git去管理期望的最终状态和版本迭代

  • 同时terraform可以对接绝大部分的基础设施,例如MySQL,Redis等,可以对接各个不同的部署平台和系统,例如阿里云,aws等,也可以针对公司内部的平台,单独写内部平台对接的provider,从而实现一套工具管理所有的基础设施

参考: