赞
踩
当虚拟服务器创建完成后,通常需要执行一些初始化的操作。例如:安装软件,配置系统,服务等。
在前面的案例中使用云商的 user_data 用户数据来执行 shell 脚本来安装 nginx 服务器。
Terraform 也提供了 Provisioner 来完成这种场景。通过 Provisioner 可以在基础设施资源创建或销毁时,执行定制化的操作。 Provisioner 可以于 ansible,puppet,saltstack 配置管理工具结合使用,利用现有的配置管理工具管理资源。
使用 Provisioner 购买基础设施并搭建一个服务。使用3个文件
- /*
- 创建 AWS EC2 实例
- 运行 Docker 容器
- */
-
- # 供应商
- provider "aws" { // 云供应商
- region = var.region // 地域
- }
-
- // 数据源
- data "aws_security_groups" "default" { // 数据源为"aws_security_groups",数据源名称"default"
- filter {
- name = "group-name" // 过滤 group_name = default 的安全组
- values = ["default"]
- }
- }
-
- // 创建 EC2 实例,运行 docker 容器
- resource "aws_instance" "ss" {
- ami = lookup(var.amis, var.region) # 配置参数,ami的id。
- instance_type = var.instance_type # 配置参数,启动的ec2的类型,t2.micro是免费的
- key_name = aws_key_pair.ssh.key_name # 引用了 aws_key_pair ssh 中的 key_name。于EC2实例绑定,实现可以ssh的目的。
- tags = { # 将EC2 实例命名为 "ss-server"
- Name = "ss-server"
- }
-
- # 连接远程服务器
- connection {
- type = "ssh"
- user = "ubuntu"
- private_key = file("id_rsa")
- host = aws_instance.ss.public_ip
- }
-
- # 安装 docker 并运行 ss 容器
- provisioner "remote-exec" {
- inline = [
- "sudo apt update",
- "sudo apt install -y docker.io",
- "sudo docker run -e PASSWORD=${var.ss_password} -p 8388:8388 -p 8388:8388/udp -d shadowsocks/shadowsocks-libev",
- ]
- }
- }
-
- # 添加SSH登陆密钥
- resource "aws_key_pair" "ssh" {
- key_name = "admin"
- public_key = file(var.public_key)
- }
-
- // 开放22端口,允许SSH登陆
- resource "aws_security_group_rule" "ssh" {
- type = "ingress"
- from_port = 22
- to_port = 22
- protocol = "tcp"
- cidr_blocks = ["0.0.0.0/0"]
- security_group_id = data.aws_security_groups.default.ids[0] // 调用数据源的信息,列表的第一个值
- }
-
- // 开放80端口,允许WEB访问
- resource "aws_security_group_rule" "web" {
- type = "ingress"
- from_port = 8388
- to_port = 8388
- protocol = "all"
- cidr_blocks = ["0.0.0.0/0"]
- security_group_id = data.aws_security_groups.default.ids[0]
- }
- # variables.tf
-
- variable "region" { // 变量名 region,不可用重复。花括号里面是参数
- type = string // 输入变量的类型
- default = "us-west-2" // 变量的默认值
- description = "AWS region" // 变量的描述
- }
-
- variable "amis" {
- type = map
- default = {
- us-west-2 = "ami-03f65b8614a860c29" // ubuntu ami
- }
- description = "AWS ID"
- }
-
- variable "instance_type" {
- type = string
- default = "t2.micro"
- description = "EC2 instance type"
- }
-
- variable "public_key" {
- type = string
- default = "id_rsa.pub"
- description = "SSH public key"
- }
-
- variable "ss_password" {
- type = string
- description = "ss password"
- }
- output "IP" {
- value = aws_instance.ss.public_ip
- description = "AWS EC2 public IP"
- }
connection 块告诉 Terraform 用什么方式与远端机器进行通讯。
- # 连接远程服务器
- connection {
- type = "ssh" # 连接方式
- user = "ec2-user" # 远程服务器的服务名
- private_key = file("id_rsa") # 配置使用ssh密钥登陆。也可以使用password登陆
- host = aws_instanc.ss.public_ip # 远端服务器的IP地址
- }
登陆到服务器上之后,要关注 Terraform 执行的操作。本案例是在服务器上安装 docker,在docker上运行一个镜像服务。
inline参数支持接受一个命令列表。EC2实例创建完成后,按顺序执行命令列表中的命令。
# 安装 docker 并运行 ss 容器
- provisioner "remote-exec" {
- inline = [
- "sudo apt update",
- "sudo apt install -y docker.io",
- "sudo docker run -e PASSWORD=${var.ss_password} -p 8388:8388 -p 8388:8388/udp -d shadowsocks/shadowsocks-libev",
- ]
- }
除了inline参数,provisioner还支持 script 和 scripts 参数,后两者支持执行脚本,这三个参数是互斥的只能使用一个参数。
- $ cp ~/.ssh/id_rsa* .
-
- $ terraform plan
-
- $ terraform apply
- var.ss_password
- ss password
-
- Enter a value: Wsj@123456
-
- ...
-
- 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
-
- ...
提交代码
- git add .
- git commit -m "using remote-exec"
使用 Provisioner file 完成服务的定制化配置。
其中${server} 和 ${password} 是变量,由 terraform apply 的时候渲染。
- $ cat ss-config.json
-
- {
- "server": "${server}",
- "server_port": 8388,
- "local_port": 1080,
- "password": "${password}",
- "timeout": 600,
- "method": "chacha20-ietf-poly1305",
- "fast_open": true
- }
新增了 provisioner "file" {} 代码块。可以将文件上传到服务器上。分别定义了文件内容和文件保存路径。
修改了 docker run 命令,运行 docker 的时候将本地路径挂载到 docker 容器里面。
- # main.tf
- ...
-
- // 创建 EC2 实例,运行 docker 容器
- resource "aws_instance" "ss" {
- ami = lookup(var.amis, var.region) # 配置参数,ami的id。
- instance_type = var.instance_type # 配置参数,启动的ec2的类型,t2.micro是免费的
- key_name = aws_key_pair.ssh.key_name # 引用了 aws_key_pair ssh 中的 key_name。于EC2实例绑定,实现可以ssh的目的。
- tags = { # 将EC2 实例命名为 "ss-server"
- Name = "ss-server"
- }
-
- # 连接远程服务器
- connection {
- type = "ssh"
- user = "ubuntu"
- private_key = file("id_rsa")
- host = aws_instance.ss.public_ip
- }
-
- # 上传文件到服务器
- provisioner "file" {
- content = templatefile("ss-config.json", { server = aws_instance.ss.public_ip, password = var.ss_password }) // 文件内容
- destination = "/var/tmp/ss-config.json" // 远端服务器的文件路径
- }
-
- # 安装 docker 并运行 ss 容器
- provisioner "remote-exec" {
- inline = [
- "sudo apt update",
- "sudo apt install -y docker.io",
- "sudo docker run -v /var/tmp:/var/tmp -e ARGS='-c /var/tmp/ss-config.json' -p 8388:8388 -p 8388:8388/udp -d shadowsocks/shadowsocks-libev",
- ]
- }
- }
- ...
- % terraform apply
- var.ss_password
- ss password
-
- Enter a value: Wsj@123456
- % ssh ubuntu@18.237.89.77 sudo docker ps
-
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- ab71ac7234fd shadowsocks/shadowsocks-libev "/bin/sh -c 'exec ss…" 36 seconds ago Up 34 seconds 0.0.0.0:8388->8388/tcp, 0.0.0.0:8388->8388/udp, :::8388->8388/tcp, :::8388->8388/udp trusting_nobel
- git add .
- git commit -m "using file provisioner"
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。