Terraform은 Infrastructure as Code 도구라서 AWS를 사용하는 경우 VPC나 EC2 인스턴스, 시큐리티 그룹 등을 Terraform으로 관리할 수 있다. 이런 요소들은 직접 웹 콘솔에서 만들거나(API를 써도 되지만...) Terraform 도구를 사용하면 되지만 서버의 환경 설정 등의 프로비저닝 작업을 모두 Terraform으로 관리하는 것은 고민되는 접근이다.
여기서 환경 설정이란 것은 Python이나 Node.js를 설치한다거나 apt-get 업데이트를 한다거나 nginx를 설치한다거나 하는 등의 일이다. 사실 이런 작업은 Ansible이나 Chef 등이 더 적합하다고 보지만 어디까지를 Terraform으로 하고 어디까지를 Ansible이나 Chef로 할지는 각 조직에서 결정할 일이다.
이전에 Terraform을 사용할 때는 AWS에서 주로 썼기에 Packer로 프로비저닝한 머신 이미지를 AMI로 만들어서 Terraform에서 사용했기에 Terraform에서는 프로비저닝을 직접 사용하지는 않았고 잘 살펴보지도 않았다. Terraform에서도 Provisioner를 제공하고 있어서 여기서 직접 프로비저닝하거나 다른 도구와 연결해서 사용할 수 있다. 얼마 전에 Terraform으로 Digital Ocean의 Droplet 생성하면서 provisioner
를 처음 사용해 보고 사용방법을 좀 더 정리해 보게 되었다. 여기서 사용한 Terraform 버전은 v0.11.2다.
Provisioner
Provisioner는 Terraform으로 리소스를 생성하거나 제거할 때 로컬이나 원격에서 스크립트를 실행할 수 있는 기능으로 0.8부터 추가되었다. 기본적으로 provisioner
는 생성할 때만 실행되고 그 뒤에 업데이트되거나 하진 않는다. 그래서 provisioner
가 실패하면 리소스가 잘못되었다고 판단하고 다음 terraform apply
할 때 제거하거나 다시 생성한다. provisioner
에서 when = "destroy"
를 지정하면 해당 프로비저너는 리소스를 제거하기 전에 실행되고 프로비저너가 실패한다면 다음 terraform apply
할 때 다시 실행하게 된다. 문서에 따르면 이 때문에 제거 프로비저너는 여러 번 실행해도 괜찮도록 작성해야 한다고 한다.
local-exec
프로비저너
local-exec 프로비저너는 이름 그대로 로컬에서 실행하는 프로비저너다. 여기서 로컬은 terraform apply
를 실행하는 현재 머신을 의미한다.
위처럼 .tf
파일을 작성했다. null_resource는 말 그대로 빈 리소스를 의미한다. 그래서 하나의 리소스와 묶이지 않은 프로비저닝 등을 사용하거나 할 때 사용할 수 있는데 여기서는 데모용으로 사용했다. 다른 리소스와 크게 다른 부분은 없고 provisioner "local-exec"
를 지정해서 echo hello world
를 실행하도록 했다.
terraform apply
를 실행하면 리소스를 생성하고 나서 프로비저너를 실행하면서 hello world
가 출력된 것을 볼 수 있다.
provisioner
는 한 리소스 안에서 여러 번 정의해도 상관없고 작성한 순서대로 실행된다.
이를 실행하면 아까처럼 hello world
가 출력되고 내 로컬 머신의 Python 버전이 출력된 것을 볼 수 있다. 이 결과는 앞에 생성한 리소스를 다 지우고 다시 실행한 것이다. 생성 시에만 프로비저너가 실행되므로 이미 생성한 리소스에 프로비저너를 추가하더라도 실행되지 않는다. 더 정확히는 리소스가 변경된 것이 아니므로 이미 최신 상태라고 나오므로 실행이 되지 않는다.
아직 사용 사례는 다 모르지만 local-exec
는 주로 로컬에 스크립트나 프로그램을 실행하거나 클라우드에 실행한 IP나 ID 같은 정보를 로컬 파일로 만들 때 사용하는 것으로 보인다.
remote-exec
프로비저너
remote-exec 프로비저너는 Terraform으로 Digital Ocean의 Droplet 생성하기에서 사용해서 실제 사용방법은 이전 글을 보아도 되긴 한다. local-exec
와는 달리 remote-exec
는 리소스를 생성한 후 타겟 머신에서 실행된다.
remote-exec
는 inline
, script
, scripts
가 있는데 셋 중 한 번에 하나만 사용해야 한다. inline
을 살펴보기 위해 아래처럼 AWS에 EC2 인스턴스를 실행하는 tf 파일을 작성해보자.
원격에 접속해서 실행하려면 어떻게 접속할지를 알아야 하므로 connection을 지정해야 한다. 지금은 ssh
와 winrm
를 지원한다는데 winrm
은 안 써봐서 모르겠고 보통은 ssh
를 쓸 것으로 생각한다. connection
은 resource
아래 선언할 수도 있고 provisioner
아래 선언할 수도 있는데 resource
아래 선언하면 해당 리소스의 모든 프로비저너가 선언한 커넥션을 사용하게 된다. 여기서는 inline
으로 호스트 명과 Ubuntu의 버전 정보를 출력했다.
EC2 인스턴스를 생성하면 SSH 접속에 성공한 뒤에 호스트 명과 Ubuntu 버전을 출력한 것을 볼 수 있다. inline
대신 script
를 사용하면 로컬에 있는 파일을 원격 서버에 복사한 뒤에 실행한다. 복잡한 스크립트의 경우 유용하고 scripts
는 여러 파일을 실행해야 할 때 사용한다.
앞에서 본 파일을 위처럼 수정한 뒤 bootstrap.sh
파일에 똑같은 명령어를 입력한 뒤에 실행하면 아까와 똑같은 결과가 나오는 것을 확인할 수 있다.
그 밖의 프로비저너
위에서 본 프로비저너가 가장 간단하게 사용할 수 있는 프로비저너고 프로비저너 문서를 보면 다양한 프로비저너가 있는 걸 볼 수 있다. 단순히 파일을 복사하거나 Chef, Salt와 연결할 수 있는 프로비저너도 존재한다.
앞에서도 얘기했듯이 어디까지를 테라폼의 영역으로 가져가고 어디서부터 프로비저닝 도구를 사용할지는 상황에 맞게 고민해 보아야 할 문제이다.
Comments