# Terraform模块Module管理,聚合资源的抽取与复用

# 1 简介

最近工作中用到了Terraform,权当学习记录一下,希望能帮助到其它人。

Terraform系列文章如下:

Terraform入门教程,示例展示管理Docker和Kubernetes资源 (opens new window)

Terraform插件Provider管理,搜索、定义、下载 (opens new window)

Terraform状态State管理,让变更有记录 (opens new window)

Terraform模块Module管理,聚合资源的抽取与复用 (opens new window)

Terraform常用命令 (opens new window)

模块是为了便为管理与复用,就跟函数是一样的。一个模块大概有以下文件:

  • main.tf:就像是函数入口;
  • README.md:如函数的声明;
  • variables.tf: 变量说明,就像函数的入参;
  • outputs.tf: 输出,如函数的返回值;
  • examples: 使用示例;

另外,模块也是可以嵌套的,即模块里有子模块,但不建议嵌套太深。

# 2 创建及使用自定义模块

# 2.1 创建模块

我们来通过一个简单示例讲解如何自己创建一个模块。这个模块的功能是在Kubernetes上部署一个nginx,就是创建一个Deployment和一个Service。

这个模块共有两个文件,一个是main.tf,用来定义Resource,即Deployment和Service。另一个文件是variables.tf,用来定义这个模块所需要的输入变量。这两个文件都放在当前目录的nginx-kubernetes文件夹下。目录结果如下:

main.tf文件如下:

resource "kubernetes_deployment" "test" {
  metadata {
    name      = var.applicationName
    namespace = var.namespace
  }
  spec {
    replicas = var.replicas
    selector {
      match_labels = {
        app = var.applicationName
      }
    }
    template {
      metadata {
        labels = {
          app = var.applicationName
        }
      }
      spec {
        container {
          image = var.image
          name  = "nginx-container"
          port {
            container_port = 80
          }
        }
      }
    }
  }
}

resource "kubernetes_service" "test" {
  metadata {
    name      = var.applicationName
    namespace = var.namespace
  }
  spec {
    selector = {
      app = var.applicationName
    }
    type = "NodePort"
    port {
      node_port   = var.nodePort
      port        = 80
      target_port = 80
    }
  }

  depends_on = [kubernetes_deployment.test]
}

它就是资源定义,然后把一些变量用var.xxx的形式替换,这样Terraform解析的时候就会找对应的变量进行赋值。

variables.tf文件如下:

variable "namespace" {
    description = "k8s namespace"
}

variable "applicationName" {
    description = "applicationName"
}

variable "image" {
    description = "image"
}

variable "replicas" {
    description = "deployment replicas"
}

variable "nodePort" {
    description = "nodePort"
}

main.tf文件使用的变量,都在这里有定义。

# 2.2 使用模块

现在我们已经创建好了模块,接下来要引用它。我们就在当前目录引用即可。代码如下:

provider "kubernetes" {
  config_path = "~/.kube/config"
}

module "pkslow-nginx" {
    source = "./nginx-kubernetes"
    namespace = "pkslow"
    applicationName = "pkslow-nginx"
    image = "nginx:1.19.5"
    replicas = 3
    nodePort = 30301
}
  • source: 模块来源的地址;
  • namespace: 命令空间,模块定义的入参;
  • applicationName: 应用名,模块定义的入参;
  • image: 镜像,模块定义的入参;
  • replicas: Pod的数目,模块定义的入参;
  • nodePort: 端口,模块定义的入参;

引用模块还是很简单的,跟调用函数差不多,就是告诉别人名字和入参。

# 3 使用外部模块

模块的source支持多种类型,如本地路径、Terraform官方仓库、GitHub等。

本地路径:

module "pkslow" {
  source = "./pkslow"
}

Terraform仓库:

module "consul" {
  source = "hashicorp/consul/aws"
  version = "0.1.0"
}

GitHub地址:

module "pkslow" {
  source = "github.com/larrydpk/pkslow"
}

如果是用SSH,如下:

module "pkslow" {
  source = "git@github.com:larrydpk/pkslow.git"
}

压缩包:

module "vpc" {
  source = "https://pkslow.com/vpc-module?archive=zip"
}

# 4 总结

代码请查看:https://github.com/LarryDpk/pkslow-samples


参考:

Terraform Module (opens new window)

Module Sources (opens new window)

上次更新: 2023/8/18 23:39:36