terraform

构建基础结构时,我将其作为代码来完成。 朝着基础结构即代码的方向发展意味着无论是通过配置管理文件还是功能完善的GitOps ,每个更改都是可见的。

Terraform是用于以代码形式构建,升级和维护基础架构的工具。 如其GitHub页面所述

“ Terraform使您能够安全,可预测地创建,更改和改善基础结构。它是一个开放源代码工具,可将API编码为声明性配置文件,可以在团队成员之间共享,视为代码,进行编辑,审阅和版本控制。”

最好的部分是,您可以将现有基础结构导入Terraform配置状态,并且将跟踪所有将来的更改。 该跟踪可以全面了解您的生产环境(和任何其他环境),可以将其备份到本地或远程Git存储库中,以对整个基础架构进行版本控制。

在本文中,我将解释如何使用Terraform管理Minikube Kubernetes集群中的状态。

先决条件

Terraform与云无关,因此您可以使用关联的提供程序在任何云中运行任何类型的Kubernetes集群。 提供程序是Terraform插件体系结构的核心,每个提供程序“负责理解API交互并公开资源”,因此主要Terraform项目可以保持精简,但是该项目可以扩展到任何系统。

在此示例中,我将在Linux桌面上使用Terraform 11 。 要继续,您还需要Helm 2.16.7Minikubekubectl

在运行构建之前,请找出命令行实用程序提供的内容。 运行terraform ,输出将显示执行计划并应用命令。 底部有一个升级清单,如果您使用的是Terraform的较旧版本,它将很方便。 开发人员内置了一个很棒的命令来检查版本之间的兼容性。

入门

要在Terraform中构建内容,您需要创建modules ,这些模块是带有一组配置文件的文件夹,这些文件可以收集信息并执行您需要完成的操作。 Terraform文件始终以文件扩展名.tf 。 从一个main.tf文件开始,例如:

 jess@Athena:~/terraform_doc$ touch main.tf 

在开始在集群中进行任何操作之前,您还需要了解一些基本的Terraform命令和要求:

  • terraform init :初始化Terraform工作目录
    –它必须与.tf文件位于同一目录中, .tf将不会发生任何事情。
  • terraform validate :确认Terraform文件的语法正确
    –始终运行此命令以确认代码正确构建且不会出错。
  • terraform plan :生成并显示在运行terraform apply时将发生的变化
    –在apply之前运行此程序以确认结果是否符合您的预期。
  • terraform apply :构建或更改基础结构
    –它将显示执行计划,并且需要执行是或否,除非您使用--auto-approve标志,这将使其自动执行。
  • Terraform refresh :根据实际资源更新本地状态文件
    –这样可确保Terraform准确了解当前环境。
  • terraform destroy :删除和删除Terraform管理的基础架构
    –这将从群集中永久删除状态文件中创建和存储的所有内容。

对于此示例中的配置,Terraform控制的所有内容都保存在本地状态文件中。 根据Terraform的文档

“默认情况下,此状态存储在名为terraform.tfstate的本地文件中,但也可以远程存储,这在团队环境中效果更好。Terraform使用此本地状态来创建计划并更改基础架构。操作中,Terraform会进行刷新以使用实际的基础架构来更新状态。”

现在您已经有了这些背景信息,您可以继续并编辑main.tf文件,检查集群,并努力使用Terraform添加配置。

准备并构建Minikube

在开始使用Terraform之前,必须创建一个Minikube集群。 本示例使用Minikube版本1.9.2。 运行minikube start


   
   
jess@Athena:~/terraform_doc$ minikube start
🎉  minikube 1.11.0 is available! Download it
: https://github.com/kubernetes/minikube/releases/tag/v1.11.0
💡  To disable this notice, run
: 'minikube config set WantUpdateNotification false'

🙄  minikube v1.9.2 on Ubuntu 18.04
✨  Using the kvm2 driver based on existing profile
👍  Starting control plane node m01 in cluster minikube
🔄  Restarting existing kvm2 VM for "minikube" ...
🐳  Preparing Kubernetes v1.18.0 on Docker 19.03.8 ...
🌟  Enabling addons
: default-storageclass, storage-provisioner
🏄  Done! kubectl is now configured to use "minikube"

检查新集群并添加名称空间

使用可信赖的kubectl命令检查新的Minikube集群:


   
   
jess@Athena:~/terraform_doc$ kubectl get nodes
NAME    STATUS   ROLES  AGE     VERSION
minikube   Ready        master   4m5s   v1.18.0

集群已启动并正在运行,因此请将配置添加到您的main.tf文件中。 首先,您需要一个provider ,它“负责理解API交互并公开资源”。 此示例中的提供者将(适当地)命名为Kubernetes 。 编辑main.tf文件并添加提供程序:


   
   
provider "kubernetes" {
  config_context_cluster   = "minikube"
}

该语法告诉Terraform集群在Minikube中运行。

现在,您将需要一个资源块的定义。 资源块描述一个或多个基础结构对象,例如虚拟网络,计算实例或更高级别的组件(例如DNS记录)。

向集群添加一个Kubernetes命名空间:


   
   
resource "kubernetes_namespace" "1-minikube-namespace" {
  metadata {
        name = "my-first-terraform-namespace"
  }
}

接下来,运行terraform init命令检查您的提供程序版本并初始化Terraform:


   
   
jess@Athena:~/terraform_doc$ terraform init

Initializing provider plugins ...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.kubernetes
: version = "~> 1.11"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

运行您的计划以查看将执行的操作:


   
   
jess@Athena:~/terraform_doc$ terraform plan
Refreshing Terraform state in-memory prior to plan ...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols
:
 + create

Terraform will perform the following actions
:

  + kubernetes_namespace.1-minikube-namespace
        id
:                            <computed >
        metadata. #:                     "1"
        metadata.0.generation
:         <computed>
        metadata.0.name
:               "my-first-terraform-namespace"
        metadata.0.resource_version
: <computed>
        metadata.0.self_link
:          <computed>
        metadata.0.uid
:                <computed >


Plan
: 1 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note
: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

现在您知道Terraform会做什么,请应用您的配置:


   
   
jess@Athena:~/terraform_doc$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols
:
 + create

Terraform will perform the following actions
:

  + kubernetes_namespace.1-minikube-namespace
        id
:                            <computed >
        metadata. #:                     "1"
        metadata.0.generation
:         <computed>
        metadata.0.name
:               "my-first-terraform-namespace"
        metadata.0.resource_version
: <computed>
        metadata.0.self_link
:          <computed>
        metadata.0.uid
:                <computed >


Plan
: 1 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.1-minikube-namespace
: Creating ...
  metadata. #:                   "" => "1"
  metadata.0.generation
:       "" => "<computed>"
  metadata.0.name
:             "" => "my-first-terraform-namespace"
  metadata.0.resource_version
: "" => "<computed>"
  metadata.0.self_link
:         "" => "<computed>"
  metadata.0.uid
:               "" => "<computed>"
kubernetes_namespace.1-minikube-namespace
: Creation complete after 0s ( ID : my-first-terraform-namespace )

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

最后,通过运行kubectl get ns确认您的新名称空间存在:


   
   
jess@Athena:~/terraform_doc$ kubectl get ns
NAME                            STATUS   AGE
default                         Active   28d
kube-node-lease                 Active   28d
kube-public                     Active   28d
kube-system                     Active   28d
my-first-terraform-namespace   Active   2m19s

通过舵图运行

手动编写Terraform配置文件,运行该文件并在Kubernetes中查看结果的功能非常不错。 还有什么更好的? 能够通过Helm图表重新运行相同的命令。

运行helm create <name>命令以生成图表:


   
   
$ helm create buildachart
Creating buildachart

您需要另一个提供者块来进行此练习。 有一个特定的Helm提供程序,它需要一个Kubernetes集群名称,以便Helm知道在何处安装其图表。 将新的提供程序(如下所示)添加到现有的main.tf文件中:


   
   
provider "helm" {
  kubernetes {
        config_context_cluster   = "minikube"
       
  }
}

现在已经配置了Helm,您需要为该terraform 模块添加Helm图表以进行安装。 为简单起见,请将Helm图表保持在与Terraform状态相同的文件夹中:


   
   
jess@Athena:~/terraform_doc$ ls
buildachart  main.tf  terraform.tfstate

添加新的Helm资源,以便可以通过使用helm_release资源安装并跟踪Terraform状态中的helm_release 。 我将此资源命名为local并导入了我的图表名称和图表位置:


   
   
resource "helm_release" "local" {
  name          = "buildachart"
  chart         = "./buildachart"
}

现在,您已经添加了这些片段,再次运行Terraform的初始化命令。 它将根据您的更改来更新状态,包括下载新的提供程序:


   
   
jess@Athena:~/terraform_doc$ terraform init

Initializing provider plugins ...
- Checking for available provider plugins on https://releases.hashicorp.com ...
- Downloading plugin for provider "helm" ( 1.2.2 ) ...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.helm
: version = "~> 1.2"
* provider.kubernetes
: version = "~> 1.11"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

然后计划新配置:


   
   
jess@Athena : ~ / terraform_doc$ terraform plan
Refreshing Terraform state in - memory prior to plan...
The refreshed state will be used to calculate this plan , but will not be
persisted to local or remote state storage.

kubernetes_namespace .1 - minikube - namespace : Refreshing state... ( ID : my - first - terraform - namespace )

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols :
  + create

Terraform will perform the following actions :

  + helm_release. local
        id :                             < computed >
        atomic :                         "false"
        chart :                          "./buildachart"
        cleanup_on_fail :                "false"
        create_namespace :               "false"
        dependency_update :              "false"
        disable_crd_hooks :              "false"
        disable_openapi_validation : "false"
        disable_webhooks :               "false"
        force_update :                   "false"
        lint :                           "false"
        max_history :                    "0"
        metadata. #:                     <computed>
        name :                           "buildachart"
        namespace :                      "default"
        recreate_pods :                  "false"
        render_subchart_notes :          "true"
        replace :                        "false"
        reset_values :                   "false"
        reuse_values :                   "false"
        skip_crds :                      "false"
        status :                         "deployed"
        timeout :                        "300"
        verify :                         "false"
        version :                        "0.1.0"
        wait :                           "true"


Plan : 1 to add , 0 to change , 0 to destroy.

------------------------------------------------------------------------

Note : You didn 't specify an "-out" parameter to save this plan, so Terraform
can'
t guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

应用您的配置,仅这次添加--auto-approve标志,这样它将无需确认即可执行:


   
   
jess@Athena:~/terraform_doc$ terraform apply --auto-approve
kubernetes_namespace.1-minikube-namespace
: Refreshing state ... ( ID : my-first-terraform-namespace )
helm_release.local
: Creating ...
  atomic
:                      "" => "false"
  chart
:                       "" => "./buildachart"
  cleanup_on_fail
:             "" => "false"
  create_namespace
:            "" => "false"
  dependency_update
:           "" => "false"
  disable_crd_hooks
:           "" => "false"
  disable_openapi_validation
: "" => "false"
  disable_webhooks
:            "" => "false"
  force_update
:                "" => "false"
  lint
:                        "" => "false"
  max_history
:                 "" => "0"
  metadata. #:                   "" => "<computed>"
  name
:                        "" => "buildachart"
  namespace
:                   "" => "default"
  recreate_pods
:               "" => "false"
  render_subchart_notes
:       "" => "true"
  replace
:                     "" => "false"
  reset_values
:                "" => "false"
  reuse_values
:                "" => "false"
  skip_crds
:                   "" => "false"
  status
:                      "" => "deployed"
  timeout
:                     "" => "300"
  verify
:                      "" => "false"
  version
:                     "" => "0.1.0"
  wait
:                        "" => "true"
helm_release.local
: Creation complete after 8s ( ID : buildachart )

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

尽管它说图表已部署,但再次检查并确认新的Helm图表始终很不错。 使用kubectl命令检查您的吊舱是否kubectl


   
   
jess@Athena:~/terraform_doc$ kubectl get pods
NAME                            READY   STATUS  RESTARTS   AGE
buildachart-68c86ccf5f-lchc5   1/1      Running   0             43s

这确认您的Pod正在运行,这意味着您的图表已部署! 您还有一个新的备份状态文件:


   
   
jess@Athena:~/terraform_doc$ ls
buildachart  main.tf  terraform.tfstate  terraform.tfstate.backup

地形保护状态,这是一个很大的功能。 每次更新后,它会自动生成一个先前状态的文件。 这允许对基础结构进行版本控制,并且您始终可以保存当前状态和最新状态。 由于这是本地版本,因此请保持当前状态和以前的状态,而无需版本控制。

回滚更改并导入某些内容

在运行Terraform命令时,将生成并更新备份状态文件,这意味着您可以只回滚一次以前的更改,除非您将状态文件保存在其他位置(例如数据库)中的其他配置中以管理文件。

在此示例中,您需要回滚Helm图表部署。 为什么? 好吧,因为可以。

在执行任何操作之前,请花一点时间运行terraform refresh命令,以查看集群和当前状态之间是否存在任何差异:


   
   
jess@Athena:~/terraform_doc$ terraform refresh
helm_release.local
: Refreshing state ... ( ID : buildachart )
kubernetes_namespace.1-minikube-namespace
: Refreshing state ... ( ID : my-first-terraform-namespace )

有一种怪异的变通方法来回滚更改:您可以用备份文件覆盖状态文件,或者可以注释通过Terraform文件进行的代码更改,并允许Terraform销毁它们。

在此示例中,我将注释掉代码并重新运行Terraform,因此将删除Helm图表。 注释以//开头在Terraform文件中:


   
   
jess@Athena:~/terraform_doc$ cat main.tf
provider "kubernetes" {
  config_context_cluster   = "minikube"
}

resource "kubernetes_namespace" "1-minikube-namespace" {
  metadata {
        name = "my-first-terraform-namespace"
  }
}

//provider "helm" {
//  kubernetes {
//      config_context_cluster   = "minikube"
//   }
// }
//resource "helm_release" "local" {
//  name        = "buildachart"
//  chart       = "./buildachart"
// }

注释掉所有内容后,运行terraform apply


   
   
jess@Athena:~/terraform_doc$ terraform apply
helm_release.local
: Refreshing state ... ( ID : buildachart )
null_resource.minikube
: Refreshing state ... ( ID : 4797320155365789412 )
kubernetes_namespace.1-minikube-namespace
: Refreshing state ... ( ID : my-terraform-namespace )

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols
:
 - destroy

Terraform will perform the following actions
:

  - helm_release.local


Plan
: 0 to add, 0 to change, 1 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

helm_release.local
: Destroying ... ( ID : buildachart )
helm_release.local
: Destruction complete after 0s

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

要查看覆盖文件的外观,请重新应用Helm图表并覆盖状态文件。 这是正在重新创建的图表的片段(此文本输出可能很长):


   
   
helm_release.local : Still creating ... ( 10s elapsed )
helm_release.local
: Creation complete after 15s ( ID : buildachart )

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

Here’s the file overwrite and the plan showing that the helm chart needs to be rerun.
jess@Athena:~/terraform_doc$ cp terraform.tfstate.backup terraform.tfstate
jess@Athena:~/terraform_doc$ terraform plan
Refreshing Terraform state in-memory prior to plan ...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

null_resource.minikube
: Refreshing state ... ( ID : 4797320155365789412 )
kubernetes_namespace.1-minikube-namespace
: Refreshing state ... ( ID : my-terraform-namespace )

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols
:
 + create

Terraform will perform the following actions
:

  + helm_release.local
        id
:                            <computed>
        atomic
:                        "false"
        chart
:                         "./buildachart"
        cleanup_on_fail
:               "false"
        create_namespace
:              "false"
        dependency_update
:             "false"
        disable_crd_hooks
:             "false"
        disable_openapi_validation
: "false"
        disable_webhooks
:              "false"
        force_update
:                  "false"
        max_history
:                   "0"
        metadata. #:                     <computed>
        name
:                          "buildachart"
        namespace
:                     "default"
        recreate_pods
:                 "false"
        render_subchart_notes
:         "true"
        replace
:                       "false"
        reset_values
:                  "false"
        reuse_values
:                  "false"
        skip_crds
:                     "false"
        status
:                        "deployed"
        timeout
:                       "300"
        verify
:                        "false"
        version
:                       "0.1.0"
        wait
:                          "true"


Plan
: 1 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note
: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

请注意,如果在覆盖状态文件时不清理环境,将会遇到问题。 该问题出现在名称用法中:


   
   
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

helm_release.local
: Creating ...
  atomic
:                      "" => "false"
  chart
:                       "" => "./buildachart"
  cleanup_on_fail
:             "" => "false"
  create_namespace
:            "" => "false"
  dependency_update
:           "" => "false"
  disable_crd_hooks
:           "" => "false"
  disable_openapi_validation
: "" => "false"
  disable_webhooks
:            "" => "false"
  force_update
:                "" => "false"
  max_history
:                 "" => "0"
  metadata. #:                   "" => "<computed>"
  name
:                        "" => "buildachart"
  namespace
:                   "" => "default"
  recreate_pods
:               "" => "false"
  render_subchart_notes
:       "" => "true"
  replace
:                     "" => "false"
  reset_values
:                "" => "false"
  reuse_values
:                "" => "false"
  skip_crds
:                   "" => "false"
  status
:                      "" => "deployed"
  timeout
:                     "" => "300"
  verify
:                      "" => "false"
  version
:                     "" => "0.1.0"
  wait
:                        "" => "true"

Error
: Error applying plan :

1 error occurred
:
    * helm_release.local
: 1 error occurred:
    * helm_release.local
: cannot re-use a name that is still in use

Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.

由于注释掉并带回资源,这会造成重用问题。 要解决此问题,请执行状态导入,该操作可以让您取出环境中已经存在的某些东西,并使Terraform重新开始对其进行跟踪。

为此,您需要要导入的名称空间和图表名称以及要导入的模块名称。 在这种情况下,模块是helm.local ,它是从您的资源代码中以"helm_release" "local"开头的资源代码中生成的。

对于重新导入,您将需要当前部署资源的名称空间,因此导入将看起来像default/buildachart 。 涉及名称空间的所有内容都需要这种格式:


   
   
jess@Athena:~/terraform_doc$ terraform import helm_release.local default/buildachart
helm_release.local
: Importing from ID "default/buildachart" ...
helm_release.local
: Import complete!
  Imported helm_release (ID
: buildachart )
helm_release.local
: Refreshing state ... ( ID : buildachart )

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

重新导入的过程可能很棘手,但是对于状态管理来说很重要。

清理

Terraform的优点在于,您可以在测试后Swift清理自己。 如果您不小心在哪里运行,那么follow命令是破坏一天的另一种好方法:


   
   
jess@Athena:~/terraform_doc$ terraform destroy
helm_release.local
: Refreshing state ... ( ID : buildachart )
kubernetes_namespace.1-minikube-namespace
: Refreshing state ... ( ID : my-first-terraform-namespace )

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols
:
 - destroy

Terraform will perform the following actions
:

  - helm_release.local
  - kubernetes_namespace.1-minikube-namespace

Plan
: 0 to add, 0 to change, 2 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only ' yes ' will be accepted to confirm.

  Enter a value
: yes

helm_release.local
: Destroying ... ( ID : buildachart )
kubernetes_namespace.1-minikube-namespace
: Destroying ... ( ID : my-first-terraform-namespace )
helm_release.local
: Destruction complete after 1s
kubernetes_namespace.1-minikube-namespace
: Destruction complete after 7s

Destroy complete! Resources
: 2 destroyed.

一连串的terraform destroy删除了您的pod和名称空间,但是您的集群仍然存在。 回到第一个方框:


   
   
jess@Athena:~/terraform_doc$ kubectl get pods
No resources found in default namespace.

jess@Athena:~/terraform_doc$ kubectl get ns
NAME            STATUS   AGE
default         Active   28d
kube-node-lease   Active   28d
kube-public     Active   28d
kube-system     Active   28d

jess@Athena:~/terraform_doc$ minikube status
m01
host
: Running
kubelet
: Running
apiserver
: Running
kubeconfig
: Configured

最后的笔记

但是,如果您不小心,则此工具可能会令人难以原谅。 如果您正在移动状态文件而没有注意,则可能会导致Terraform认为需要管理的内容出现问题。 使用此工具时,请注意不要过度扩展或一次写太多,因为如果您不注意,可以将自己编码在角落。

Terraform用于基础结构配置时是最好的。 它最大程度地减少了在管理状态时发生的问题,并允许为配置和部署而设计的工具可以补充其功能。

您对Terraform和Kubernetes做了什么? 在下面的评论中分享您的经验。

翻译自: https://opensource.com/article/20/7/terraform-kubernetes

terraform

Logo

开源、云原生的融合云平台

更多推荐