Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.

Terraform으로 Digital Ocean의 Droplet 생성하기

Digital Ocean을 쓴지 5년 정도 되었지만 잘 관리하고 있지는 않다. 이번에 AWS에 올렸던 리소스를 다시 Digital Ocean으로 이사할 준비를 하면서 기존에 운영하던 블로그도 새로 세팅해 보려고 하고 있다.

Digital Ocean에서는 서버를 Droplet이라고 부르는데 요즘 Infrastructure as Code에 꽂혀 있어서 Digital Ocean도 Terraform에서 지원하므로 Terraform을 그대로 이용하기로 했다. 그 이전에는 거의 AWS에서만 Terraform을 사용해 봤다.

개인 서버는 회사에서처럼 다수를 띄우는 것도 아니고 누군가와 협업해야 할 필요는 없지만 Infrastructure as Code로 서버를 구성했을 때 가장 좋은 점 중 하나는 재현할 수 있다는 것이다. 서버 설정을 직접 다 했다고 하더라도 항상 외우고 있는 것도 아니므로 이후 변경하거나 개선하기도 쉬워지고 처음 설정할 때는 한 번에 끝까지 설정하기가 어려워서 틈틈이 하게 되는데 Terraform으로 다 관리하고 있으면 Droplet을 띄워서 설정 테스트를 한 후 다음 작업할 때까지 내려놓으면 과금도 안 되고 좋다. 이후 작업할 때도 다시 실행만 하면 되니까... 이렇게 안 하면 Image를 매번 만들어서 띄워두어야 한다.

Digital Ocean 프로바이더 설정

Digital Ocean을 이용하려면 API 토큰을 발급받아야 한다.

Digital Ocean의 API 토큰 생성 화면

위 화면에서 토큰을 생성한 뒤 아래처럼 프로바이더 설정을 한다.

variable "do_token" {}

provider "digitalocean" {
  version = "~> 0.1"
  token   = "${var.do_token}"
}

여기서 API 토큰을 tf 파일에 하드 코딩할 수는 없으므로 환경변수로 설정해 두는 것이 편하다. 위에서 변수 이름이 do_token이므로 TF_VAR_do_token이라는 환경변수로 지정하면 Terraform 변수에 할당된다.

프로바이더 설정이 끝났으므로 terraform init로 초기화한다.(여기서는 Terraform v0.11.1을 사용했다.)

$ terraform init

Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "digitalocean" (0.1.3)...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.


Droplet 구성

AWS에 비해 Digital Ocean은 훨씬 간단하므로 문서를 보면 금방 작성할 수 있다. 아래는 Ubuntu 17.04로 싱가포르 서버에 Droplet을 띄우는 설정이다.

resource "digitalocean_droplet" "demo" {
  image      = "ubuntu-17-04-x64"
  name       = "demo"
  region     = "sgp1"
  size       = "512mb"
  monitoring = true
  ipv6       = true
  ssh_keys   = ["aa:bb:cc:dd:ee"]
}

여기서 지정하는 region이나 size의 이름은 API 문서를 참고해서 여기서 사용하는 값을 쓰면 된다. ssh_keys 키 같은 경우는 이미 Digital Ocean에 등록해 놓은 SSH 키의 핑거프린트(혹은 id)를 지정하면 되는데 이는 SSH 키 조회 API에서 찾을 수 있다. 발급받은 API 키로 아래처럼 조회하면 SSH 키의 핑커프린트나 ID를 확인할 수 있다.

$ curl -X GET \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  "https://api.digitalocean.com/v2/account/keys" | \
  jq .ssh_keys

[
  {
    "id": 1234,
    "fingerprint": "aa:bb:cc:dd:ee",
    "public_key": "ssh-rsa xxxxxxx your-email-address",
    "name": "my key"
  }
]


Droplet 프로비저닝

Droplet을 실행하는 게 끝이 아니므로 서버를 프로비저닝해야 한다. 서버에 환경 설정을 해야 하는데 여기에는 Ansible같은 도구가 더 적합하므로 Terraform에서는 SSH 계정을 추가하는 기본적인 프로비저닝만 하기로 했다.

variable "do_private_key" {}
variable "do_public_key" {}

variable "do_username" {
  default = "demo"
}
variable "do_password" {}

resource "digitalocean_droplet" "demo" {
  # 앞에서 설정한 부분 생략

  connection {
    user        = "root"
    type        = "ssh"
    private_key = "${file(var.do_private_key)}"
    timeout     = "2m"
  }

  provisioner "remote-exec" {
    inline = [
      "export PATH=$PATH:/usr/bin",
      "adduser --disabled-password --gecos '' ${var.do_username}",
      "echo ${var.do_username}:${var.do_password} | chpasswd",
      "echo '${var.do_username} ALL=(ALL:ALL) ALL' | sudo EDITOR='tee -a' visudo",
      "mkdir /home/${var.do_username}/.ssh",
      "chown ${var.do_username}:${var.do_username} /home/${var.do_username}/.ssh",
      "echo '${file(var.do_public_key)}' > /home/${var.do_username}/.ssh/authorized_keys",
    ]
  }
}

4개의 변수를 추가하고 connectionremote-exec 프로비저너를 추가했다. connection 설정으로 SSH 접속한 뒤에 remote-exec에 지정한 명령어를 실행한다.

do_public_keydo_private_key 환경변수에 사용할 퍼블릭/프라이빗 키의 경로를 지정한다.

export TF_VAR_do_public_key=$HOME/.ssh/id_rsa.pub
export TF_VAR_do_private_key=$HOME/.ssh/id_rsa

${file(var.do_private_key)}처럼 terraform에서 사용하므로 이 파일의 내용을 읽어서 사용하게 된다.

remote-exec에서 지정한 명령어는 SSH 접속 뒤 차례대로 실행되는데 root 계정 대신 새로 만든 계정을 사용하도록 do_username에 지정한 계정을 만들고 /etc/sudoers 파일에 추가하고 퍼블릭 SSH 키를 ~/.ssh/authorized_keys에 추가해서 접속할 수 있게 한 것이다. 인터렉티프 모드로 입력하도록 하면 여기서 프로비저닝을 할 수 없으므로 한 번에 실행되도록 하다 보니 명령어가 좀 복잡해졌다.

이를 실행하면 Droplet 생성 후 프로비저닝까지 하는 것을 볼 수 있다.

$ terraform apply

digitalocean_droplet.demo: Creating...
  disk:                 "" => "<computed>"
  image:                "" => "ubuntu-17-04-x64"
  ipv4_address:         "" => "<computed>"
  ipv4_address_private: "" => "<computed>"
  ipv6:                 "" => "true"
  ipv6_address:         "" => "<computed>"
  ipv6_address_private: "" => "<computed>"
  locked:               "" => "<computed>"
  monitoring:           "" => "true"
  name:                 "" => "demo"
  price_hourly:         "" => "<computed>"
  price_monthly:        "" => "<computed>"
  region:               "" => "sgp1"
  resize_disk:          "" => "true"
  size:                 "" => "512mb"
  ssh_keys.#:           "" => "1"
  ssh_keys.0:           "" => "5c:62:af:d8:28:72:d7:36:eb:29:47:ec:7d:90:8d:28"
  status:               "" => "<computed>"
  vcpus:                "" => "<computed>"
digitalocean_droplet.demo: Still creating... (10s elapsed)
digitalocean_droplet.demo: Provisioning with 'remote-exec'...
digitalocean_droplet.demo (remote-exec): Connecting to remote host via SSH...
digitalocean_droplet.demo (remote-exec):   Host: 174.138.20.103
digitalocean_droplet.demo (remote-exec):   User: root
digitalocean_droplet.demo (remote-exec):   Password: false
digitalocean_droplet.demo (remote-exec):   Private key: true
digitalocean_droplet.demo (remote-exec):   SSH Agent: true
digitalocean_droplet.demo (remote-exec): Connected!
digitalocean_droplet.demo (remote-exec): Adding user `demo' ...
digitalocean_droplet.demo (remote-exec): Adding new group `demo' (1000) ...
digitalocean_droplet.demo (remote-exec): Adding new user `demo' (1000) with group `demo' ...
digitalocean_droplet.demo (remote-exec): Creating home directory `/home/demo' ...
digitalocean_droplet.demo (remote-exec): Copying files from `/etc/skel' ...
digitalocean_droplet.demo (remote-exec): demo ALL=(ALL:ALL) ALL
digitalocean_droplet.demo: Creation complete after 1m4s (ID: 76374504)

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


Digital Ocean에서 생성된 droplet

Digital Ocean에서 생성된 것을 확인할 수 있다.

$ ssh demo@174.138.20.103
Welcome to Ubuntu 17.04 (GNU/Linux 4.10.0-40-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

31 packages can be updated.
18 updates are security updates.

New release '17.10' available.
Run 'do-release-upgrade' to upgrade to it.


Last login: Mon Dec 25 10:29:36 2017 from 183.98.70.31
demo@demo:~$ sudo -s
[sudo] password for demo:
root@demo:~#

확인한 IP로 접속해 보면 프로비저닝한 계정이 잘 동작하는 것을 확인할 수 있다.

2017/12/25 19:40 2017/12/25 19:40

기술 뉴스 #92 : 17-12-16

웹개발 관련

  • A recap of front-end development in 2017 : 2017년에 주목받은 기술들을 정리한 글로 React 16, PWA, CSS Grid 레이아웃, 서버리스 등을 꼽았다. 주목받았다는 객관적인 기준은 없지만 올 한해의 기술들을 한번 둘러보면서 놓친 내용을 살펴보기 좋은 글이다. 마지막에 자사의 서비스 광고를 슬쩍 넣었지만...(영어)
  • JAMstack : JavaScript, API, Markup만을 이용해서 웹사이트를 만드는 스택을 의미한다.(영어)
  • A revamped SEO Starter Guide : 구글에서 SEO 스타터 문서를 업데이트했다.(영어)
  • 11 things I learned reading the CSS Grid Specification : CSS Grid의 스펙을 읽고 그 동작 방식의 주요 부분을 상세하게 정리한 글이다. 아직 CSS Grid를 사용하지 않아서 세부내용을 다 이해하기 힘들지만, CSS Grid를 사용할 때 참고해서 보면 제대로 사용하기 좋은 글이다.(영어)

그 밖의 프로그래밍 관련

  • 올해(2017년)의 오픈소스 프로젝트 기여, 행사 참석 회고(回顧,Retrospection) : 성대현 님이 한글과 관련해서 오픈소스에 참여하면서 GNOME Foundation Member가 된 과정까지를 설명한 글이다. 내가 유니코드나 CJKV에 관련한 지식이 많지 않지만 CJKV에 관심을 가진 과정부터 몇 년에 걸쳐서 지속해서 관심을 가지고 참여하게 된 과정을 다 나와 있어서 재미있다. 따라 할 수 있을지는 잘 모르겠지만...(한국어)
  • Introducing electron-toolkit: The Electron app to build and launch Electron apps : Electron으로 앱을 만들 때 불편한 부분을 해결하기 위해서 만든 툴킷이다. 여기서 아이콘을 플랫폼별로 변환해주고 스크린샷을 관리할 수 있게 해주고 앱의 배포 및 웹사이트 생성까지 지원해주고 있다.(영어)
  • HTTPS 전환 과정에서 read timeout 오류 해결 과정 : 네이버 서비스에서 HTTPS로 전환하면서 read timeout 오류의 원인을 추적하는 과정을 설명하고 있다. 꽤 고생해서 찾았을 거로 생각하는데 의심하는 부분과 확인하는 방법, 그리고 원인이 왜 아닌지를 설명하면서 찾아가는 과정이 그대로 다 적혀 있어서 고통이 느껴지면서도 재미있다.(한국어)
  • TECHNOLOGY RADAR VOL.17 : 소트웍스에서 분야별로 기술이 업계에서 도입된 상태를 정리하는 TECHNOLOGY RADAR의 2017년 11월 버전이다. 기술, 도구, 플랫폼, 언어/프레임워크 별로 나누고 각 분야에서 Adopt, Trial, Assess, Hold로 나누어서(Adopt가 안정성이 확인된 상태) 각 기술의 도입 여부를 보여주고 있다.(영어)

볼만한 링크

  • 스타트업 인턴 개발자 3달간의 고군분투기 : 스타트업 인턴 개발자가 팀장이 뒤이어 들어온 뒤 django와 vue를 접하고 개발 흐름을 따라가는 의식의 흐름을 정리한 글이다. 발표자료가 길지만 발표센스가 좋다고 느껴질 정도로 정리가 잘 되어 있어서 자료가 긴지도 모른 채 재미있게 있었다. 내용 파악하고 정리하는 능력이 뛰어나신 느낌이라 발표자료만 보았는데도 재미있었다.(한국어)

IT 업계 뉴스

프로젝트

  • Parcel : 웹 애플리케이션 번들러로 기존 webpack 등의 번들러보다 설정이 간단하고 빠르다고 한다.
  • Turi Create : Apple에서 공개한 Python 라이브러리로 머신러닝 모델을 쉽게 개발할 수 있게 도와준다.
  • critical : CSS 파일에서 웹페이지 로딩 속도를 높이기 위해서 초기 렌더링에 필요한 부분을 추출해 주는 도구.
  • Gatsby : React를 이용한 정적 웹사이트 생성기.
  • Muuri : JavaScript 반응형 그리드 레이아웃 엔진.
  • Superstruct : JavaScript 데이터 형식 정의 및 유효성 검사 라이브러리.
  • pup : HTML 파싱 커맨드라인 도구

버전 업데이트

2017/12/16 04:24 2017/12/16 04:24