经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
Terraform管理云资源实践
来源:cnblogs  作者:leason001  时间:2024/8/26 10:25:46  对本文有异议

背景

Terraform是一款开源的Cli工具,网上的很多文章都是单机安装一个然后创建个目录就去操作云资源;如果在高可用的前提,如何将Terraform cli变成一个嵌入运维流程的一个组件?不仅仅是人编写tf模板然后去apply?

自动化的驱动Terraform,无非包含这几个步骤:

  • 初始化Terraform
  • 填充资源模板
  • apply资源
  • show资源

初始化Terraform

创建一个云资源目录,如cloudxxx-test001
云资源的目录下需要有Terrafor的Provider信息,以及实例声明信息。
创建好了模板文件,就需要初始化Terraform,以及下载Provider插件,建议提前下载好插件到指定的目录,使用容器可以直接打到镜像里
这样初始化直接指定plugin地址:

  1. /usr/local/bin/terraform init -plugin-dir=/Users/lixiangli/.terraform.d/plugins

注意:确保插件地址内有你声明的插件版本

由于Terraform apply是不支持选择apply哪个资源,因此上面的实现方式可以发现,一个目录是放一个云资源。为了让每次操作的影响范围是可控的。这种方式会带来一个问题,就是state的文件存储也必须是隔离的,否则出现的情况是apply 资源cloudxxx-test001时 cloudxxx-test002会被直接删除。

模板文件生成

通过代码的方式去驱动Terraform, 无法避免的一步就是生成所对应的云资源的模板文件,我们这边使用golang,所以找到需要对接的云的Provider的文档然后定义成如下:

  1. resource "ucloud_disk" "ucloud_disk_{{ .ObjectMeta.UID }}" {
  2. availability_zone = "{{ .Spec.Zone }}"
  3. name = "{{ .Spec.InstanceName }}"
  4. disk_size = "{{ .Spec.InstanceSize }}"
  5. disk_type = "{{ .Spec.InstanceType }}"
  6. charge_type = "{{ .Spec.ChargeType }}"
  7. }

在程序运行时动态填充这些模板即可

选择合适的状态存储

Terraform是个有状态的组件,如果部署多个实例的话,官方默认的state文件的模式必然是无法满足需求的。
所以我们这边选择的是etcdv3
配置如下:

  1. terraform {
  2. required_providers {
  3. ucloud = {
  4. source = "ucloud/ucloud"
  5. version = "~>1.23.0"
  6. }
  7. }
  8. backend "etcdv3" {
  9. endpoints = ["http://127.0.0.1:2379/"]
  10. lock = true
  11. prefix = "/terraform-state/clouddisk/77c2d636-7a59-11eb-9d32-12caef3c0b88"
  12. cacert_path = ""
  13. cert_path = ""
  14. key_path = ""
  15. }
  16. }
  17. provider "ucloud" {
  18. public_key = "xxxxxxx"
  19. private_key = "xxxxxx"
  20. region = "cn-bj2"
  21. project_id = ""
  22. }

backend的prefix资源加了uuid,实际上是为了解决上面一个目录是放一个云资源锁带来的问题,也就是说那个uuid实际上是对应的单独资源id,每个资源都有单独的state文件

如何支持多云

支持多云是Terraform的强项,支持多云依然需要在上次软件做好一定的屏蔽工作。
Terraform需要做的就是准备好多套云的tf模板去填充
如腾讯云:

  1. resource "tencentcloud_cbs_storage" "tencentcloud_disk_{{ .ObjectMeta.UID }}" {
  2. storage_type = "{{ .Spec.InstanceType }}"
  3. storage_name = "{{ .Spec.InstanceName }}"
  4. storage_size = "{{ .Spec.InstanceSize }}"
  5. availability_zone = "{{ .Spec.Zone }}"
  6. project_id = "{{ .Spec.ProjectID }}"
  7. }

如优刻得:

  1. resource "ucloud_disk" "ucloud_disk_{{ .ObjectMeta.UID }}" {
  2. availability_zone = "{{ .Spec.Zone }}"
  3. name = "{{ .Spec.InstanceName }}"
  4. disk_size = "{{ .Spec.InstanceSize }}"
  5. disk_type = "{{ .Spec.InstanceType }}"
  6. charge_type = "{{ .Spec.ChargeType }}"
  7. }

上层的数据结构可以声明成一样的,所有的差异由tf模板来屏蔽

原文链接:https://www.cnblogs.com/leason001/p/18380421

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号