Step 12-13. Provisioning & Configuration — 인프라 준비와 내부 세팅
이전 단계: 06-full-pipeline.md 돌아가기: 09-hands-on.md
용어 안내
이 문서에서 “슬롯”은 학습용 비유다. 실무 용어가 아니다. 각 슬롯 옆에 실무에서 실제로 쓰는 용어를 병기한다.
Step 12. Terraform으로 인프라를 코드로 만들기 — ⑥ Provisioning (인프라 준비)
왜 인프라를 코드로 만들어야 하는가? (WHY)
AWS 콘솔에서 클릭클릭으로 서버를 만들었다고 하자. 3개월 뒤, 그 서버를 어떻게 만들었는지 아무도 기억하지 못한다. 설정이 다르면? 처음부터 클릭을 다시 해야 한다.
코드로 인프라를 정의하면:
- git으로 이력 관리 — 누가, 언제, 왜 바꿨는지 추적 가능
- 동일한 환경을 반복 생성 — 개발/스테이징/운영이 같은 코드로 만들어짐
- 코드 리뷰 — 인프라 변경도 PR로 검토 가능
핵심 용어 3가지
Provisioning (프로비저닝)
- 영어 뜻: “미리 준비해두다, 공급하다” — 필요한 것을 사전에 마련하는 행위
- IT 뜻: 서버·네트워크·DB 같은 인프라 자원을 생성하는 것
- 비유: 빈 땅에 집을 짓는 것. 벽, 지붕, 수도관을 설치하는 단계
- 실무 용어: “인프라 프로비저닝”
IaC (Infrastructure as Code)
- 영어 뜻: “Infrastructure as Code” = “인프라를 코드로”
- IT 뜻: 콘솔에서 클릭 대신 코드 파일로 인프라를 정의하는 방법론
- 비유: 건축 설계도. 구두 지시가 아니라 도면을 보고 집을 짓는 것
- 실무 용어: “IaC”
Terraform (테라폼)
- 영어 뜻: “terra(땅) + form(형태를 만들다)” = 땅의 형태를 바꾸다
- IT 뜻: HashiCorp이 만든 IaC 도구. 코드를 작성하면 인프라를 자동으로 생성·변경·삭제
- 비유: 건축 시공 회사. 설계도(코드)를 주면 집(인프라)을 지어주는 업체
- 실무 용어: “Terraform”, “IaC 도구”
로컬 체험 방법
Terraform에는 Docker Provider가 있다. 클라우드 계정 없이, 로컬 Docker 컨테이너를 Terraform으로 관리할 수 있다.
AWS에서는
aws_instance(EC2 서버)를 만들고, 여기서는docker_container를 만든다. Terraform 사용법은 동일하다.
12-1. 사전 준비
# Mac: Homebrew로 Terraform 설치
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# 설치 확인 — 버전이 출력되면 성공
terraform --version
12-2. main.tf 작성
# 프로젝트 루트에서 terraform 디렉토리를 만들고 이동
mkdir -p terraform && cd terraform
# --- Terraform 설정 블록 ---
# 어떤 프로바이더(인프라 제공자)를 사용할지 선언한다
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker" # Docker 프로바이더의 출처
version = "~> 3.0" # 3.x 버전 사용 (~>는 "이 메이저 버전 내에서")
}
}
}
# --- 프로바이더 설정 ---
# Docker를 인프라 대상으로 사용한다 (로컬 Docker 데몬에 연결)
provider "docker" {}
# --- 리소스 1: Docker 이미지 ---
# docker pull nginx:alpine 과 같은 역할
resource "docker_image" "nginx" {
name = "nginx:alpine" # 가져올 이미지 이름과 태그
}
# --- 리소스 2: Docker 컨테이너 ---
# docker run --name tf-nginx -p 8080:80 nginx:alpine 과 같은 역할
resource "docker_container" "nginx" {
name = "tf-nginx" # 컨테이너 이름
image = docker_image.nginx.image_id # 위에서 가져온 이미지 참조
ports {
internal = 80 # 컨테이너 내부 포트 (nginx 기본 포트)
external = 8080 # 호스트에서 접근할 포트
}
}
12-3. Terraform 3단계 실행
Provisioning의 핵심 흐름은 딱 3단계다.
① init — 초기화
# 프로바이더 플러그인을 다운로드한다
# npm install이 node_modules를 받는 것과 같은 원리
terraform init
② plan — 미리보기
# "이런 것들이 만들어질 예정입니다"를 보여준다
# 실제로 만들지는 않는다 — 안전하게 확인만
terraform plan
출력에서 + resource가 보이면 “새로 만들 것”이라는 뜻이다.
③ apply — 실제 실행
# 실제로 인프라(컨테이너)를 생성한다
# "Do you want to perform these actions?" → yes 입력
terraform apply
12-4. 결과 확인 + 삭제
# nginx가 정상 작동하는지 확인
# "Welcome to nginx!" 페이지가 응답되면 성공
curl localhost:8080
# Docker로 직접 확인해도 된다
docker ps | grep tf-nginx
# 모든 리소스를 삭제한다
# Terraform이 만든 것만 정확히 삭제한다
terraform destroy
핵심 인사이트:
terraform plan → apply → destroy이 3단계가 Provisioning의 핵심 흐름이다. AWS에서도 똑같이 동작한다.docker_container대신aws_instance를 쓸 뿐이다.
선택 실습: 기존 Express 앱 이미지(
my-app:latest)도 main.tf에docker_image+docker_container리소스로 추가해보자.terraform apply하면 nginx와 Express 앱이 동시에 생성된다.
Step 13. Ansible로 컨테이너 내부 설정하기 — ⑦ Configuration (내부 세팅)
Provisioning vs Configuration — 왜 도구가 2개인가? (WHY)
Terraform으로 서버(컨테이너)를 만들었다. 하지만 빈 서버에는 아무것도 없다. 필요한 소프트웨어를 설치하고, 설정 파일을 넣고, 서비스를 시작해야 한다.
서버가 1대면 SSH로 들어가서 하면 된다. 10대면? 100대면? 하나하나 접속해서 같은 명령을 치는 건 비현실적이다.
- Terraform = 집을 짓는 것 (벽, 지붕, 배관)
- Ansible = 집 안에 가구를 넣는 것 (소파, 침대, 커튼)
- 이 두 도구는 경쟁이 아니라 보완 관계다
핵심 용어
Configuration (컨피규레이션)
- 영어 뜻: “설정, 구성” — 부품을 조합해서 원하는 상태로 맞추는 것
- IT 뜻: 이미 만들어진 서버 안에 소프트웨어를 깔고 설정하는 것
- 비유: 새 집에 가구 배치, 인터넷 개통, 벽지 도배를 하는 것
- 실무 용어: “구성 관리(Configuration Management)”
Ansible (앤서블)
- 영어 뜻: SF 소설에서 온 단어 — “초광속 통신 장치”
- IT 뜻: 여러 서버에 동시에 명령을 실행하는 자동화 도구. SSH로 접속해서 작업
- 비유: 인테리어 업체. 집 100채에 동시에 같은 가구를 배치해주는 회사
- 실무 용어: “Ansible”, “구성 관리 도구”
Docker 컨테이너를 **“미니 서버”**로 취급하고, Ansible이 SSH로 접속해서 내부를 설정한다.
13-1. 사전 준비
# Ansible 설치 (둘 중 하나 선택)
pip install ansible # Python pip으로 설치
# 또는
brew install ansible # Mac Homebrew로 설치
# 설치 확인
ansible --version
13-2. SSH 가능한 컨테이너 직접 빌드하기
최신 Ansible(2.20+)은 관리 대상(target) 서버에 Python 3.8 이상을 요구한다.
기성 SSH 이미지(rastasheep/ubuntu-sshd:18.04)는 Python 3.6이라 호환이 안 된다.
짧은 Dockerfile로 직접 만들어 쓰는 게 가장 확실하고, 실무에서 EC2 초기 세팅을 하는 흐름과도 가장 비슷하다.
# my-infra-lab 루트에서 ansible-target 디렉토리 생성
mkdir -p ansible-target
ansible-target/Dockerfile 작성:
# Ubuntu 22.04 기반 — Python 3.10 내장 (최신 Ansible 호환)
FROM ubuntu:22.04
# SSH 서버 + Python3 설치
# Ansible은 SSH로 접속해서 타겟의 Python으로 모듈을 실행한다
RUN apt-get update && apt-get install -y \
openssh-server \
python3 \
sudo \
&& mkdir /var/run/sshd \
&& echo 'root:root' | chpasswd \
&& sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config \
&& rm -rf /var/lib/apt/lists/*
EXPOSE 22
# 컨테이너 시작 시 SSH 데몬 실행 (-D: 포그라운드로 유지)
CMD ["/usr/sbin/sshd", "-D"]
# 이미지 빌드
docker build -t my-ansible-target ./ansible-target
# 컨테이너 실행
# -d: 백그라운드 실행
# -p 2222:22: 호스트 2222번 포트 → 컨테이너 22번(SSH) 포트
docker run -d --name ansible-target -p 2222:22 my-ansible-target
이 컨테이너가 “서버 1대” 역할을 한다. 실무에서는 AWS EC2 인스턴스가 이 자리에 들어간다.
SSH 접속이 되는지 먼저 확인(선택):
# 비밀번호는 root
ssh -p 2222 -o StrictHostKeyChecking=no root@localhost exit
# 오류 없이 끝나면 준비 완료
13-3. inventory.ini — 대상 서버 목록
# ansible 디렉토리를 만들고 이동
mkdir -p ansible && cd ansible
# [servers] = 그룹 이름. 여러 서버를 묶어서 관리할 수 있다
[servers]
# target = 별칭 (아무 이름이나 가능)
# ansible_host = 접속할 주소 (로컬이므로 localhost)
# ansible_port = SSH 포트 (위에서 2222로 매핑했으므로)
# ansible_user / ansible_password = SSH 접속 계정
target ansible_host=localhost ansible_port=2222 ansible_user=root ansible_password=root
13-4. playbook.yml — 실행할 작업 정의
# --- 플레이북: 서버 초기 설정 ---
- name: 서버 초기 설정 # 이 플레이북의 이름 (로그에 표시됨)
hosts: servers # inventory.ini에서 [servers] 그룹을 대상으로 실행
tasks:
# --- 작업 1: curl 설치 ---
- name: curl 설치 # 작업 이름 (로그에 표시됨)
apt: # apt 패키지 매니저 사용 (Ubuntu)
name: curl # 설치할 패키지 이름
state: present # present = "설치해라" / absent = "삭제해라"
update_cache: yes # apt update를 먼저 실행 (패키지 목록 갱신)
# --- 작업 2: 확인 파일 생성 ---
- name: 확인 파일 생성 # Ansible이 작업했다는 증거를 남긴다
copy: # 파일을 생성/복사하는 모듈
content: "Ansible이 이 파일을 만들었습니다 - {{ ansible_date_time.iso8601 }}"
dest: /tmp/ansible-was-here.txt # 파일이 생성될 경로
13-5. 실행 및 확인
# 플레이북 실행
# -i: inventory 파일 지정
# SSH 호스트 키 검증을 끄는 환경변수 추가 (로컬 실습용)
ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i inventory.ini playbook.yml
# 결과 확인 — 컨테이너 안의 파일을 직접 읽는다
docker exec ansible-target cat /tmp/ansible-was-here.txt
# 출력 예: "Ansible이 이 파일을 만들었습니다 - 2026-04-16T..."
TASK [curl 설치]와 TASK [확인 파일 생성] 옆에 changed가 표시되면 성공이다.
핵심 인사이트: Terraform이 컨테이너(서버)를 만들고, Ansible이 그 안을 세팅한다. 이 두 도구는 경쟁이 아니라 보완 관계다.
13-6. 정리
# 실습이 끝나면 컨테이너 + 빌드 이미지 정리
docker stop ansible-target && docker rm ansible-target
docker rmi my-ansible-target
체크리스트
- Terraform으로 컨테이너를 코드로 생성/삭제할 수 있다
-
terraform plan → apply → destroy3단계 흐름을 이해했다 - Ansible로 컨테이너 내부를 자동 설정할 수 있다
- Provisioning(인프라 생성)과 Configuration(내부 설정)의 차이를 체감했다
다음 단계: → 08-deploy-and-alerting.md
Comments
// admin login