Ansible DevOps 서버 자동화 완벽 가이드: Infrastructure as Code 시작하기
Ansible을 활용한 서버 자동화 입문 가이드. Docker, Kubernetes 환경에서의 실전 예제와 CI/CD 파이프라인 구축 방법을 상세히 설명합니다.
Ansible DevOps 서버 자동화 완벽 가이드: Infrastructure as Code 시작하기
현대 DevOps 환경에서 서버 자동화는 필수 요소가 되었습니다. 수십, 수백 대의 서버를 수동으로 관리하는 것은 비효율적이며 오류가 발생하기 쉽습니다. Ansible은 이러한 문제를 해결하는 강력한 Infrastructure as Code 도구로, 복잡한 서버 환경을 코드로 관리할 수 있게 해줍니다.
Ansible 핵심 개념과 아키텍처
Ansible은 에이전트가 없는(agentless) 구조로 설계되어 있어 관리 대상 서버에 별도 소프트웨어 설치가 불필요합니다. SSH 연결만으로 원격 서버를 제어할 수 있어 기존 인프라에 쉽게 도입할 수 있습니다.
핵심 구성 요소는 다음과 같습니다:
- Control Node: Ansible이 설치된 관리 서버
- Managed Node: 관리 대상이 되는 원격 서버들
- Inventory: 관리 대상 서버들의 목록과 그룹 정의
- Playbook: 자동화 작업을 정의한 YAML 파일
- Module: 실제 작업을 수행하는 기능 단위
Ansible 설치 및 초기 설정
Ansible을 도입하기 전에 먼저 기존 서버 관리 방식의 문제점을 이해해야 합니다. 수동으로 서버를 설정하면 설정 드리프트(configuration drift)가 발생하고, 문서화가 부실해지며, 장애 복구 시 동일한 환경을 재현하기 어렵습니다. Ansible은 이러한 문제를 선언적 코드로 해결합니다. 원하는 상태를 정의하면 Ansible이 현재 상태와 비교하여 필요한 변경만 수행하는 멱등성(idempotency) 원칙을 따릅니다. 이 덕분에 같은 Playbook을 여러 번 실행해도 결과가 항상 동일하게 보장됩니다.
Ubuntu/Debian 환경에서 Ansible을 설치하는 방법입니다:
# 패키지 저장소 업데이트
sudo apt update
# Ansible 설치
sudo apt install ansible -y
# 설치 확인
ansible --version
CentOS/RHEL 환경의 경우:
# EPEL 저장소 추가
sudo yum install epel-release -y
# Ansible 설치
sudo yum install ansible -y
Python pip를 통한 설치도 가능합니다:
pip3 install ansible
Inventory 파일 구성과 서버 그룹 관리
Inventory 파일은 Ansible이 어떤 서버를 관리할지 알려주는 핵심 설정입니다. 서버를 논리적인 그룹으로 분류하면 특정 역할의 서버들에만 선택적으로 작업을 실행할 수 있어 운영 효율성이 크게 향상됩니다. 예를 들어 웹 서버 그룹에는 Nginx 설정을 적용하고, 데이터베이스 그룹에는 백업 스크립트를 실행하는 식으로 분리할 수 있습니다. /etc/ansible/hosts 파일 또는 별도 파일로 관리할 수 있습니다:
# inventory.ini
[webservers]
web1.example.com ansible_host=192.168.1.10
web2.example.com ansible_host=192.168.1.11
web3.example.com ansible_host=192.168.1.12
[databases]
db1.example.com ansible_host=192.168.1.20
db2.example.com ansible_host=192.168.1.21
[kubernetes]
k8s-master ansible_host=192.168.1.30 ansible_user=ubuntu
k8s-worker1 ansible_host=192.168.1.31 ansible_user=ubuntu
k8s-worker2 ansible_host=192.168.1.32 ansible_user=ubuntu
[all:vars]
ansible_ssh_private_key_file=~/.ssh/id_rsa
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
연결 테스트를 통해 설정이 올바른지 확인할 수 있습니다:
# 모든 서버 연결 테스트
ansible all -i inventory.ini -m ping
# 특정 그룹만 테스트
ansible webservers -i inventory.ini -m ping
기본 Ad-hoc 명령어 활용
Ansible의 ad-hoc 명령어를 통해 간단한 작업을 즉시 수행할 수 있습니다:
# 시스템 정보 수집
ansible all -i inventory.ini -m setup
# 패키지 설치
ansible webservers -i inventory.ini -m apt -a "name=nginx state=present" --become
# 서비스 상태 확인
ansible webservers -i inventory.ini -m systemd -a "name=nginx state=started enabled=yes" --become
# 파일 복사
ansible databases -i inventory.ini -m copy -a "src=/local/file dest=/remote/path mode=0644"
# 명령어 실행
ansible all -i inventory.ini -m shell -a "df -h"
Playbook 작성과 실전 예제
Playbook은 Ansible의 핵심으로, 복잡한 자동화 작업을 체계적으로 정의할 수 있습니다. 웹 서버 설치 및 설정 예제입니다:
# webserver-setup.yml
- name: 웹서버 설치 및 설정
hosts: webservers
become: yes
vars:
nginx_port: 80
app_name: "myapp"
tasks:
- name: Nginx 패키지 설치
apt:
name: nginx
state: present
update_cache: yes
- name: 방화벽 포트 허용
ufw:
rule: allow
port: "{{ nginx_port }}"
proto: tcp
- name: 사용자 정의 index.html 생성
template:
src: templates/index.html.j2
dest: /var/www/html/index.html
mode: '0644'
notify: restart nginx
- name: Nginx 서비스 시작 및 활성화
systemd:
name: nginx
state: started
enabled: yes
handlers:
- name: restart nginx
systemd:
name: nginx
state: restarted
템플릿 파일 예제 (templates/index.html.j2):
<!DOCTYPE html>
<html>
<head>
<title>{{ app_name }} - {{ inventory_hostname }}</title>
</head>
<body>
<h1>Welcome to {{ app_name }}</h1>
<p>Server: {{ inventory_hostname }}</p>
<p>IP Address: {{ ansible_default_ipv4.address }}</p>
</body>
</html>
Playbook 실행:
ansible-playbook -i inventory.ini webserver-setup.yml
Docker 환경 자동화
컨테이너 기반 인프라가 보편화되면서 Docker 설치와 컨테이너 배포를 자동화하는 것은 DevOps 엔지니어의 핵심 역량이 되었습니다. Ansible의 Docker 모듈을 활용하면 Docker 엔진 설치부터 컨테이너 실행, 네트워크 설정까지 전체 과정을 코드로 관리할 수 있습니다. 특히 여러 서버에 동시에 동일한 컨테이너 환경을 구성해야 할 때 Ansible의 병렬 실행 능력이 빛을 발합니다.
Docker 컨테이너 관리를 위한 Playbook 예제입니다:
# docker-setup.yml
- name: Docker 환경 구성
hosts: webservers
become: yes
tasks:
- name: Docker 의존성 패키지 설치
apt:
name:
- apt-transport-https
- ca-certificates
- curl
- gnupg
- lsb-release
state: present
- name: Docker GPG 키 추가
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: Docker 저장소 추가
apt_repository:
repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
state: present
- name: Docker CE 설치
apt:
name: docker-ce
state: present
update_cache: yes
- name: Docker Compose 설치
pip:
name: docker-compose
state: present
- name: 애플리케이션 컨테이너 실행
docker_container:
name: webapp
image: nginx:latest
ports:
- "8080:80"
volumes:
- "/var/www/html:/usr/share/nginx/html:ro"
state: started
restart_policy: always
Kubernetes 클러스터 자동화
Kubernetes 환경에서의 Ansible 활용 예제입니다:
# k8s-deployment.yml
- name: Kubernetes 애플리케이션 배포
hosts: kubernetes
tasks:
- name: Namespace 생성
kubernetes.core.k8s:
name: myapp
api_version: v1
kind: Namespace
state: present
- name: ConfigMap 생성
kubernetes.core.k8s:
definition:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: myapp
data:
database_url: "postgresql://db:5432/myapp"
redis_url: "redis://redis:6379"
- name: Deployment 생성
kubernetes.core.k8s:
definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
namespace: myapp
spec:
replicas: 3
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: myapp:latest
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: app-config
CI/CD 파이프라인 통합
Jenkins와 Ansible을 연동한 CI/CD 파이프라인 구성 예제입니다:
# deploy-pipeline.yml
- name: CI/CD 파이프라인 배포
hosts: webservers
vars:
app_version: "{{ build_number | default('latest') }}"
deploy_path: "/opt/myapp"
tasks:
- name: 이전 버전 백업
archive:
path: "{{ deploy_path }}"
dest: "/backup/myapp-{{ ansible_date_time.epoch }}.tar.gz"
ignore_errors: yes
- name: 애플리케이션 다운로드
get_url:
url: "https://artifacts.company.com/myapp-{{ app_version }}.tar.gz"
dest: "/tmp/myapp-{{ app_version }}.tar.gz"
- name: 애플리케이션 압축 해제
unarchive:
src: "/tmp/myapp-{{ app_version }}.tar.gz"
dest: "{{ deploy_path }}"
remote_src: yes
- name: 애플리케이션 서비스 재시작
systemd:
name: myapp
state: restarted
- name: 헬스체크 수행
uri:
url: "http://{{ inventory_hostname }}:8080/health"
method: GET
status_code: 200
retries: 5
delay: 10
Ansible Vault로 보안 정보 관리
실무에서 Ansible을 사용할 때 가장 주의해야 할 부분 중 하나가 바로 보안 정보 관리입니다. 데이터베이스 비밀번호, API 키, SSL 인증서 같은 민감한 데이터를 평문으로 저장하면 Git 저장소를 통해 유출될 위험이 있습니다. Ansible Vault는 AES-256 암호화를 사용하여 이러한 비밀 정보를 안전하게 관리할 수 있는 내장 기능을 제공합니다. 암호화된 파일은 Git에 안전하게 커밋할 수 있어 팀원 간 협업에도 문제가 없습니다.
민감한 정보는 Ansible Vault로 암호화하여 관리할 수 있습니다:
# 새 vault 파일 생성
ansible-vault create secrets.yml
# 기존 파일 암호화
ansible-vault encrypt database-config.yml
# vault 파일 편집
ansible-vault edit secrets.yml
# 암호화된 파일과 함께 playbook 실행
ansible-playbook -i inventory.ini --ask-vault-pass deploy.yml
암호화된 변수 사용 예제:
# secrets.yml (암호화됨)
database_password: "super_secret_password"
api_key: "secret_api_key_12345"
# main-playbook.yml
- name: 보안 정보를 사용한 배포
hosts: databases
vars_files:
- secrets.yml
tasks:
- name: 데이터베이스 설정
template:
src: database.conf.j2
dest: /etc/database.conf
mode: '0600'
마무리
Ansible은 DevOps 환경에서 서버 자동화를 위한 강력하고 유연한 도구입니다. Infrastructure as Code 접근 방식을 통해 복잡한 인프라 환경을 체계적으로 관리할 수 있으며, Docker와 Kubernetes 같은 컨테이너 환경과도 완벽하게 통합됩니다. 이 가이드에서 제시한 실전 예제들을 바탕으로 점진적으로 자동화 범위를 확장해 나가면, 효율적이고 안정적인 DevOps 환경을 구축할 수 있을 것입니다.
관련 게시글
GitOps Workflow 설계 가이드: Kubernetes와 CI/CD를 활용한 자동화
GitOps는 선언적 인프라 및 애플리케이션 관리를 위한 강력한 패러다임입니다. 이 가이드에서는 Git을 Single Source of Truth로 활용하여 Kubernetes 환경에서 안정적이고 효율적인 GitOps 워크플로우를 설계하는 방법을 Docker, CI/CD 자동화 예시와 함께 상세히 설명합니다.
GitHub Actions Advanced Workflows: Docker, Kubernetes CI/CD
GitHub Actions를 활용한 Docker, Kubernetes 기반 CI/CD 파이프라인 구축 심화 가이드. DevOps 엔지니어링 관점에서 자동화 전략을 탐구합니다.
Terraform Infrastructure Automation: DevOps 엔지니어링 가이드
Terraform을 활용한 인프라 자동화의 핵심 개념부터 실제 AWS 환경에서의 배포 예시까지, DevOps 엔지니어링 관점에서 자세히 알아봅니다. IaC, Docker, Kubernetes, CI/CD 파이프라인 통합 전략을 다룹니다.