iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 16
0
DevOps

今晚我想來點 Terraform 佐 AWS系列 第 16

今晚我想用 Packer 跟 Terraform 打造網頁服務

完整範例: https://github.com/nyogjtrc/practice-terraform/tree/master/web-packer-terraform

準備 Packer 模版

首先準備腳本 script.sh 放入要執行的工作,今天只要安裝 nginx 而已。

如果腳本有問題的話,不用擔心 Packer 突然中斷工作。它會關閉正在使用的資源再停止,不會留下半成品。

#!/bin/bash

lsb_release -a

sudo apt-get install -y nginx

接著準備 web.json

provisioners 區塊裡,我們做了以下幾件事

  • file 佈建器上傳 html 檔
  • shell 佈建器執行腳本安裝 nginx
  • shell 佈建器執行指令複製檔案
{
  "variables": {
    "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}",
    "aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}",
    "region": "ap-northeast-1"
  },
  "builders": [
    {
      "type": "amazon-ebs",
      "access_key": "{{user `aws_access_key`}}",
      "secret_key": "{{user `aws_secret_key`}}",
      "region": "{{user `region`}}",
      "ami_name": "packer-ubuntu-web-{{timestamp}}",
      "source_ami_filter": {
        "filters": {
          "virtualization-type": "hvm",
          "name": "ubuntu/images/*ubuntu-focal-20.04-amd64-server-*",
          "root-device-type": "ebs"
        },
        "owners": ["099720109477"],
        "most_recent": true
      },
      "instance_type": "t2.micro",
      "ssh_username": "ubuntu"
    }
  ],
  "provisioners": [
    {
      "type": "file",
      "source": "./index.html",
      "destination": "/home/ubuntu/"
    },
    {
      "type": "shell",
      "script": "script.sh"
    },
    {
      "type": "shell",
      "inline": [
        "sudo cp /home/ubuntu/index.html /var/www/html/index.html"
      ]
    }
  ]
}

執行 Packer

$ packer build web.json
amazon-ebs: output will be in this color.

==> amazon-ebs: Prevalidating any provided VPC information
==> amazon-ebs: Prevalidating AMI Name: packer-ubuntu-web-1600356640
    amazon-ebs: Found Image ID: ami-09b86f9709b3c33d4
==> amazon-ebs: Creating temporary keypair: packer_5f638121-50f9-a89a-36ce-e5958d9007cf
==> amazon-ebs: Creating temporary security group for this instance: packer_5f638123-2388-0772-a51a-b01f4c2ca2cc
==> amazon-ebs: Authorizing access to port 22 from [0.0.0.0/0] in the temporary security groups...
==> amazon-ebs: Launching a source AWS instance...
==> amazon-ebs: Adding tags to source instance
    amazon-ebs: Adding tag: "Name": "Packer Builder"
    amazon-ebs: Instance ID: i-09a2c6675e3fe9e7f
==> amazon-ebs: Waiting for instance (i-09a2c6675e3fe9e7f) to become ready...
==> amazon-ebs: Using ssh communicator to connect: 52.194.251.155
==> amazon-ebs: Waiting for SSH to become available...
==> amazon-ebs: Connected to SSH!
==> amazon-ebs: Uploading ./index.html => /home/ubuntu/
    amazon-ebs: index.html 290 B / 290 B [===========================================================================================] 100.00% 0s
==> amazon-ebs: Provisioning with shell script: script.sh
    amazon-ebs: Distributor ID: Ubuntu
==> amazon-ebs: No LSB modules are available.
    amazon-ebs: Description:    Ubuntu 20.04.1 LTS
    amazon-ebs: Release:        20.04
    amazon-ebs: Codename:       focal
    amazon-ebs: Reading package lists...
    amazon-ebs: Building dependency tree...
    amazon-ebs: Reading state information...
    amazon-ebs: The following additional packages will be installed:
...
==> amazon-ebs: Provisioning with shell script: /var/folders/qc/26b601512_lcvbbb8qg8vrfm0000gp/T/packer-shell382611512
==> amazon-ebs: Stopping the source instance...
    amazon-ebs: Stopping instance
==> amazon-ebs: Waiting for the instance to stop...
==> amazon-ebs: Creating AMI packer-ubuntu-web-1600356640 from instance i-09a2c6675e3fe9e7f
    amazon-ebs: AMI: ami-03b20ac44de8dc56a
==> amazon-ebs: Waiting for AMI to become ready...
==> amazon-ebs: Terminating the source AWS instance...
==> amazon-ebs: Cleaning up any extra volumes...
==> amazon-ebs: No volumes to clean up, skipping
==> amazon-ebs: Deleting temporary security group...
==> amazon-ebs: Deleting temporary keypair...
Build 'amazon-ebs' finished after 2 minutes 52 seconds.

==> Wait completed after 2 minutes 52 seconds

==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs: AMIs were created:
ap-northeast-1: ami-03b20ac44de8dc56a

成功的話,會看到 ami id

準備 Terraform

準備檔案 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 = "10.0.0.0/16"
}

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              = "10.0.1.0/24"
  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)
}

data "aws_ami" "web" {
  filter {
    name   = "state"
    values = ["available"]
  }
  owners = ["self"]

  filter {
    name   = "name"
    values = ["packer-ubuntu-web-*"]
  }

  most_recent = true
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.web.id
  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

  tags = {
    Name  = "web-packer-terraform"
    topic = "web-packer"
  }
}

這次多使用了一個 data 區塊 aws_ami

aws_ami 來搜尋剛剛建立的映像檔

  • 擁有者 (owner): 自己
  • 過濾器 (filter): 映像檔名稱是用 Packer 建立的
  • 最近的 (most_recent): 打開

執行 Terraform

執行 terraform apply

$ terraform apply

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

Outputs:

vpc_id = vpc-020b696d702910188
web_instance_id = i-0585626b7f287e116
web_public_ip = 18.183.103.41

成功之後會看到建立的 instance id 跟服務的 IP

在瀏覽器開啟 http://18.183.103.41/ ,可以看到我們放進去的首頁文字。

This service install via Packer and Terraform

上一篇
今晚我想多認識一點 Packer 的模版
下一篇
今晚我想用 Terraform 來畫圖
系列文
今晚我想來點 Terraform 佐 AWS30

尚未有邦友留言

立即登入留言