나의 삽질 저장소!

Packer로 프로비저닝하기 - 4편

by softPine

이전 튜토리얼에서는 Packer로 첫번째 이미지를 만들어봤다. 그러나 생성한 이미지는 그냥 기존에 있던 이미지를 다시 패키징하기만 한 이미지이다. Pakcer의 진정한 장점은 소프트웨어를 이미지로 변환하기 전에 소프트웨어를 설치하고 구성하기 위한 자동화된 프로비저닝에서 비롯된다.

이미 알고 있듯이, 이미 구워진 이미지를 바꾸는 것은 매우 귀찮고 느린일이다. 그러나 Pakcer를 사용하게되면 프로비저닝을 자동화하면서 이미지를 빠르게 변경할 수 있고 Chef, Pupper 과 같은 최신 구성 관리툴과 통합할 수 있다.

이번 튜토리얼에서는 Redis를 설치하여 이미지를 완성해본다. 간단한 예제이지만 Packer 프로비저닝 도구가 어떤 일을 할 수 있는지에 대한 아이디어를 볼 수 있다.

 

사전 준비 사항

이전에 튜토리얼을 따라왔다면 준비 사항은 없는것과 마찬가지지만 진행을 위해서 일단 써놓는다.

  • Packer 설치 -  Link
 

Packer 설치 - 2편

먼저 Packer를 설치부터 진행하려고 한다. 설치에 대한 문서는 Link를 확인해 보면 설치에 대한 방법을 볼 수 있다. 나는 AWS 머신 이미지를 만들기 위해서 AWS의 Amazon Linux 2 를 사용하여 돈을 최대한

blog.softpine.dev

  • 홈 디렉토리에 packer_tutorial 디렉토리 생성 후 해당 디렉토리 내에 aws-ubuntu.pkr.hcl 템플릿 파일 준비.
packer {
  required_plugins {
    amazon = {
      version = ">= 0.0.1"
      source   = "github.com/hashicorp/amazon"
    }
  }
}

source "amazon-ebs" "ubuntu" {
  ami_name      = "learn-packer-linux-aws"
  instance_type = "t2.micro"
  region        = "ap-northeast-2"
  source_ami_filter {
    filters = {
      name                = "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*"
      root-device-type    = "ebs"
      virtualization-type = "hvm"
    }
    most_recent = true
    owners      = ["099720109477"]
  }
  ssh_username = "ubuntu"
}

build {
  sources = [
    "source.amazon-ebs.ubuntu"
  ]
}
  • Packer 템플릿 초기화 진행
pk init .

템플릿을 성공적으로 초기화가 되었다면 이제 나머지 부분을 진행할 수 있다.

 

템플릿에 Provisioner 추가

Provisioner를 추가하게 되면 이미지 수정을 자동화할 수 있다. 쉘 스크립트, 파일 업로드, 최신 구성 관리 도구와의 통합등이 가능하다.

먼저 source.amazon-ebs.ubuntu를 찾고 ssh communicator를 사용하는지 확인한다. ssh_username 속성을 지정하면 Packer는 인스턴스의 프로비저닝을 하기 위해 임시로 key pair, securiy group을 생성하여 사용한다. 

source "amazon-ebs" "ubuntu" {
  ## ...
  ssh_username = "ubuntu"
}

첫번째 provisioner를 작성하려면 아래의 블록을 Packer 템플릿의 build 블록 내부 및 sources 블록 아래에 할당한다.

provisioner "shell" {
  environment_vars = [
    "FOO=hello world",
  ]
  inline = [
    "echo Installing Redis",
    "sleep 30",
    "sudo apt-get update",
    "sudo apt-get install -y redis-server",
    "echo \"FOO is $FOO\" > example.txt",
  ]
}

이 블록은 쉘 실행 환경에서 FOO라는 환경 변수를 설정하고 인라인 속성에서 명령을 실행하는 쉘 provisioner를 정의한다. 이 provisioner는 redis를 설치하기 전에 30초 동안 기다린 다음 FOO is hello world가 포함된 example.txt 파일을 만든다.

build 블록은 다음과 같다.

build {
  sources = [
    "source.amazon-ebs.ubuntu"
  ]

  provisioner "shell" {
    environment_vars = [
      "FOO=hello world",
    ]
    inline = [
      "echo Installing Redis",
      "sleep 30",
      "sudo apt-get update",
      "sudo apt-get install -y redis-server",
      "echo \"FOO is $FOO\" > example.txt",
    ]
  }
}

 

이미지 빌드

AMI의 이름은 고유해야한다. 따라서 이미지를 빌드하기 전에 AMI 이름을 업데이트 해줘야 한다. 기존에 learn-packer-linux-aws 이름의 AMI가 있으니 변경을 한다.

Tip: 아래의 snippet은 변경해야 하는 구성 부분에 대한 컨텍스트를 제공하기 위해 diff 형식으로 보여진다. - 기호와 빨간색으로 표시된 컨텐츠를 + 기호와 녹색으로 표시된 내용으로 바꾼다.
source "amazon-ebs" "ubuntu" {
-  ami_name      = "learn-packer-linux-aws"
+  ami_name      = "learn-packer-linux-aws-redis"
   ## ...
}

provisioner로 이미지를 빌드한다.

pk build .
amazon-ebs.ubuntu: output will be in this color.

==> amazon-ebs.ubuntu: Prevalidating any provided VPC information
==> amazon-ebs.ubuntu: Prevalidating AMI Name: learn-packer-linux-aws-redis
    amazon-ebs.ubuntu: Found Image ID: ami-08508144e576d5b64
==> amazon-ebs.ubuntu: Creating temporary keypair: packer_60bdce7b-f28c-e220-888c-9fa4a5ee5d44
==> amazon-ebs.ubuntu: Creating temporary security group for this instance: packer_60bdce7c-e0cf-ff64-88a8-d9e5fb25f9d9
==> amazon-ebs.ubuntu: Authorizing access to port 22 from [0.0.0.0/0] in the temporary security groups...
==> amazon-ebs.ubuntu: Launching a source AWS instance...
==> amazon-ebs.ubuntu: Adding tags to source instance
    amazon-ebs.ubuntu: Adding tag: "Name": "Packer Builder"
    amazon-ebs.ubuntu: Instance ID: i-002b1191b7fb4edef
==> amazon-ebs.ubuntu: Waiting for instance (i-002b1191b7fb4edef) to become ready...
==> amazon-ebs.ubuntu: Using ssh communicator to connect: 15.164.250.17
==> amazon-ebs.ubuntu: Waiting for SSH to become available...
==> amazon-ebs.ubuntu: Connected to SSH!
==> amazon-ebs.ubuntu: Provisioning with shell script: /tmp/packer-shell081291499
....
==> amazon-ebs.ubuntu: Stopping the source instance...
    amazon-ebs.ubuntu: Stopping instance
==> amazon-ebs.ubuntu: Waiting for the instance to stop...
==> amazon-ebs.ubuntu: Creating AMI learn-packer-linux-aws-redis from instance i-002b1191b7fb4edef
    amazon-ebs.ubuntu: AMI: ami-0d82348d17708f246
==> amazon-ebs.ubuntu: Waiting for AMI to become ready...
==> amazon-ebs.ubuntu: Terminating the source AWS instance...
==> amazon-ebs.ubuntu: Cleaning up any extra volumes...
==> amazon-ebs.ubuntu: No volumes to clean up, skipping
==> amazon-ebs.ubuntu: Deleting temporary security group...
==> amazon-ebs.ubuntu: Deleting temporary keypair...
Build 'amazon-ebs.ubuntu' finished after 4 minutes 14 seconds.

==> Wait completed after 4 minutes 14 seconds

==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs.ubuntu: AMIs were created:
ap-northeast-2: ami-0d82348d17708f246

위 출력에서 Packer가 프로비저닝 단계를 실행했음을 확인하는 쉘 스크립트를 확인할 수 있다. 추가로 Redis 설치에 대한 내용도 확인이 가능하다.

AWS Console로 가서 실제 AMI가 정상적으로 빌드가 되었는지 확인을 해보면 된다.

Redis AMI 확인

 

Provisioners 추가하기

위에서 진행한 쉘 provisioners도 충분히 강력하고 유연하지만, 복잡한 프로비저닝의 경우 인라인 대신 쉘 스크립트 자체를 전달할 수도 있다.

또한 원하는 만큼 provisioners를 선언할 수 잇으며 선언한 순서대로 진행을 한다.

기존 build 블록을 아래처럼 바꾼다. 그러면 build 블록 끝에 쉘 실행 환경에서 메시지를 보여주는 provisioner가 추가된다.

build {
  sources = [
    "source.amazon-ebs.ubuntu"
  ]

  provisioner "shell" {
    environment_vars = [
      "FOO=hello world",
    ]
    inline = [
      "echo Installing Redis",
      "sleep 30",
      "sudo apt-get update",
      "sudo apt-get install -y redis-server",
      "echo \"FOO is $FOO\" > example.txt",
    ]
  }

  provisioner "shell" {
    inline = ["echo This provisioner runs last"]
  }
}

 

업데이트 된 이미지 빌드 및 확인

이전에도 이야기했다 싶이 AMI의 이름은 고유해야 하기 때문에 이미지 이름을 업데이트 해준다.

source "amazon-ebs" "ubuntu" {
-  ami_name      = "learn-packer-linux-aws-redis"
+  ami_name      = "learn-packer-linux-aws-redis-msg"
   ## ...
}

다시 이미지를 빌드한다.

pk build .
amazon-ebs.ubuntu: output will be in this color.

==> amazon-ebs.ubuntu: Prevalidating any provided VPC information
==> amazon-ebs.ubuntu: Prevalidating AMI Name: learn-packer-linux-aws-redis-msg
    amazon-ebs.ubuntu: Found Image ID: ami-08508144e576d5b64
==> amazon-ebs.ubuntu: Creating temporary keypair: packer_60bddba2-9778-f8d1-6903-b83391032e39
==> amazon-ebs.ubuntu: Creating temporary security group for this instance: packer_60bddba3-cb00-ded7-d044-83bd45e10df9
==> amazon-ebs.ubuntu: Authorizing access to port 22 from [0.0.0.0/0] in the temporary security groups...
==> amazon-ebs.ubuntu: Launching a source AWS instance...
==> amazon-ebs.ubuntu: Adding tags to source instance
    amazon-ebs.ubuntu: Adding tag: "Name": "Packer Builder"
    amazon-ebs.ubuntu: Instance ID: i-03d3a0ce69a7ff51d
==> amazon-ebs.ubuntu: Waiting for instance (i-03d3a0ce69a7ff51d) to become ready...
==> amazon-ebs.ubuntu: Using ssh communicator to connect: 15.164.48.51
==> amazon-ebs.ubuntu: Waiting for SSH to become available...
==> amazon-ebs.ubuntu: Connected to SSH!
==> amazon-ebs.ubuntu: Provisioning with shell script: /tmp/packer-shell266108390
    amazon-ebs.ubuntu: Installing Redis
==> amazon-ebs.ubuntu: Provisioning with shell script: /tmp/packer-shell029562415
    amazon-ebs.ubuntu: This provisioner runs last
==> amazon-ebs.ubuntu: Stopping the source instance...
    amazon-ebs.ubuntu: Stopping instance
==> amazon-ebs.ubuntu: Waiting for the instance to stop...
==> amazon-ebs.ubuntu: Creating AMI learn-packer-linux-aws-redis-msg from instance i-03d3a0ce69a7ff51d
    amazon-ebs.ubuntu: AMI: ami-0fed624d614209c07
==> amazon-ebs.ubuntu: Waiting for AMI to become ready...
==> amazon-ebs.ubuntu: Terminating the source AWS instance...
==> amazon-ebs.ubuntu: Cleaning up any extra volumes...
==> amazon-ebs.ubuntu: No volumes to clean up, skipping
==> amazon-ebs.ubuntu: Deleting temporary security group...
==> amazon-ebs.ubuntu: Deleting temporary keypair...
Build 'amazon-ebs.ubuntu' finished after 3 minutes 37 seconds.

==> Wait completed after 3 minutes 37 seconds

==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs.ubuntu: AMIs were created:
ap-northeast-2: ami-0fed624d614209c07

위 메시지 예제를 보면 shell-script 실행을 하는 두 가지의 프로비저닝을 확인할 수 있다.

이후 AWS AMI에서 생성된 AMI를 확인해 본다.

생성된 Packer AMI 확인

'OpenSource > Packer' 카테고리의 다른 글

Packer 병렬 빌드 - 6편  (0) 2021.06.09
Packer 변수 - 5편  (0) 2021.06.08
Packer로 이미지 만들어보기 - 3편  (0) 2021.06.06
Packer 설치 - 2편  (0) 2021.06.04
Packer란? - 1편  (0) 2021.06.04

블로그의 정보

나의 삽질저장소

softPine

활동하기