參考了前面文章的介紹的功能,我們要試著讓組態檔更有可用性。
今天來試著製作一台網頁伺服器。
一台簡單的網頁伺服器需要的工作:
要安裝 nginx,的方法有很多,可以登入伺服器,下指令安裝。但是這樣不符合,IaC 的精神。
我們來試試 Terraform 的佈建器 (provisioner)
用佈建器來完成在伺服器上安裝 nginx 這件工作。我們會用到兩個區塊,connction
跟 provisioner
區塊,兩個都要放在 aws_instance
裡面。
首先是 connection
區塊,常用的引數 (Arguments) 有:
ssh
跟 winrm
再來是 provisioner
區塊,有分 file
, local-exec
跟 remote-exec
三種。
我們要在伺服器執行一些指令,使用的是 remote-exec
,主要的引數:
把輸入變數 (Input Variables) 跟輸出值 (Output Values) 加入組態檔,並使用佈建器 (provisioner) 來安裝服務。
完成的檔案清單:
variables.tf
variable "aws_region" {
type = string
description = "AWS region to launch servers."
default = "ap-northeast-1"
}
variable "cidr" {
type = string
description = "vpc cidr block"
}
variable "public_subnet" {
type = string
description = "public subnet cidr block"
}
variable "public_key_path" {
type = string
description = "Path to SSH public key"
default = "~/.ssh/id_rsa.pub"
}
variable "private_key_path" {
type = string
description = "Path to SSH private key"
default = "~/.ssh/id_rsa"
}
variable "ami" {
type = string
description = "ami id"
}
variable "my_ip" {
type = string
description = "my ip to allow ssh connection"
}
main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "3.5.0"
}
}
}
provider "aws" {
profile = "default"
region = "ap-northeast-1"
}
resource "aws_vpc" "this" {
cidr_block = var.cidr
}
resource "aws_internet_gateway" "this" {
vpc_id = aws_vpc.this.id
}
resource "aws_route" "internet_access" {
route_table_id = aws_vpc.this.main_route_table_id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.this.id
}
resource "aws_subnet" "this" {
vpc_id = aws_vpc.this.id
cidr_block = var.public_subnet
map_public_ip_on_launch = true
}
resource "aws_security_group" "ssh" {
name = "ssh"
description = "sg for ssh incoming"
vpc_id = aws_vpc.this.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [format("%s/32", var.my_ip)]
}
}
resource "aws_security_group" "web" {
name = "web"
description = "sg for web incoming"
vpc_id = aws_vpc.this.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# outbound internet access
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_key_pair" "practice" {
key_name = "practice"
public_key = file(var.public_key_path)
}
resource "aws_instance" "web" {
ami = var.ami
instance_type = "t2.micro"
key_name = aws_key_pair.practice.id
vpc_security_group_ids = [
aws_security_group.ssh.id,
aws_security_group.web.id,
]
subnet_id = aws_subnet.this.id
connection {
type = "ssh"
user = "ubuntu"
host = self.public_ip
private_key = file(var.private_key_path)
}
provisioner "remote-exec" {
inline = [
"sudo apt-get update",
"sudo apt-get install -y nginx",
]
}
}
output.tf
output "vpc_id" {
description = "ID of VPC"
value = aws_vpc.this.id
}
output "web_instance_id" {
description = "ID of web instance"
value = aws_instance.web.id
}
output "web_public_ip" {
description = "Public IP of web server"
value = aws_instance.web.public_ip
}
terraform.tfvars
cidr = "10.0.0.0/16"
public_subnet = "10.0.1.0/24"
public_key_path = "~/.ssh/id_rsa.pub"
# Ubuntu Server 20.04 LTS (HVM), SSD Volume Type, 64-bit x86
ami = "ami-0461b11e2fad8c14a"
先查詢你目前的 public ip,接著執行 apply
指令並帶入變數
$ terraform apply -var="my_ip=xxx.xxx.xxx.xxx"
...
Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
Outputs:
vpc_id = vpc-03fa104e06a386d5d
web_instance_id = i-02726dce6cb801181
web_public_ip = 123.123.123.123
完成了就可以開啟 http://123.123.123.123
驗收一下網頁服務。
佈建器 (provisioner) 這個方法並不是 Terraform 推薦的方法,在測試的過程中我有遇到幾次的失敗。
後面我們再找其他的辦法來試試。