9 min to read
[Ansible for Kubespray] 1. Getting Started with Ansible
Cloudnet@ K8S Deploy — Week2
Introduction
Kubernetes 클러스터를 프로덕션 환경에 배포하는 것은 복잡한 작업입니다. 여러 노드에 걸쳐 컨테이너 런타임을 설치하고, Kubernetes 컴포넌트를 구성하며, 네트워크 플러그인을 설정하고, 보안 인증서를 생성하는 등 수많은 단계가 필요합니다. 이러한 작업을 수작업으로 진행하면 시간이 오래 걸릴 뿐만 아니라 설정 오류가 발생하기 쉽습니다.
Kubespray는 바로 이러한 문제를 해결하기 위한 프로젝트입니다. Kubernetes 공식 프로젝트의 일부로, Ansible을 활용하여 Kubernetes 클러스터를 자동으로 배포하고 관리합니다. Kubespray의 내부를 들여다보면 수많은 Ansible Playbook과 Role로 구성되어 있으며, 이들이 체계적으로 조합되어 복잡한 Kubernetes 설치 과정을 자동화합니다. 따라서 Kubespray를 효과적으로 활용하고 커스터마이징하려면 Ansible에 대한 이해가 필수적입니다.
이 글은 Ansible 학습 시리즈의 첫 번째로, Kubespray 실습을 위한 기초를 다집니다. Ansible의 핵심 개념을 이해하고, 실습 환경을 구축하며, 기본적인 연결 테스트까지 진행합니다. 이후 시리즈에서는 Inventory 관리, Variables, Handlers, Roles 등 Ansible에서 사용되는 기능들을 단계적으로 학습할 예정입니다.
What is Ansible?
Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy and maintain.
위와 같이 공식 홈페이지에서는 Ansible을 오픈소스 IT 자동화 플랫폼으로, 시스템 구성 관리, 애플리케이션 배포, 작업 오케스트레이션 등을 코드로 정의하고 실행할 수 있게 해주는 도구로 정의합니다. 2012년 마이클 데한(Michael DeHaan)이 개발했으며, 2015년 Red Hat에 인수된 후, 현재는 엔터프라이즈급 자동화 솔루션으로 발전했습니다.
Ansible 프로젝트는 GitHub에서 활발하게 개발되고 있으며, 아래의 공식 저장소를 통해 관리됩니다.
Ansible은 완전한 오픈소스 프로젝트로, GPL-3.0 라이센스 하에 배포되며, 누구나 소스 코드에 기여할 수 있습니다.
How Ansible Works
Ansible의 각 구성요소를 살펴보기 전에, 전체 실행 흐름을 이해하는 것이 중요합니다. Ansible은 Control Node에서 명령을 실행하면 SSH를 통해 Managed Node에 접속하여 필요한 작업을 수행하고 결과를 반환하는 방식으로 작동합니다.
전형적인 Ansible 실행 흐름은 다음과 같습니다. 먼저 관리자가 Control Node에서 ansible-playbook 명령어를 실행합니다. Ansible은 지정된 Playbook 파일을 파싱하여 어떤 작업을 수행해야 하는지 파악하고, Inventory 파일을 읽어 작업 대상이 되는 Managed Node들의 목록을 확인합니다. 그 다음 각 Managed Node에 SSH 프로토콜을 통해 연결을 시도하며, 이때 비밀번호 또는 SSH 키 기반 인증을 사용합니다.
https://www.liquidweb.com/blog/what-is-ansible/)
연결이 성공하면 Ansible은 해당 Task에서 지정한 Module을 Managed Node로 전송합니다. Module은 Python으로 작성된 코드로, Managed Node의 임시 디렉터리에 저장됩니다. 이후 Managed Node의 Python 인터프리터가 이 Module을 실행하는데, 이 과정에서 Module은 현재 시스템 상태를 확인하고 원하는 상태와 비교합니다. 만약 변경이 필요하다면 실제 작업을 수행하고, 이미 원하는 상태라면 아무 작업도 하지 않습니다. 이처럼 Ansible의 모든 모듈은 멱등성을 염두에 두고 설계되었기 때문에 동일한 작업을 여러 번 수행하더라도 결과가 항상 같습니다.
작업이 완료되면 Module은 실행 결과를 JSON 형태로 Control Node에 반환합니다. 이 결과에는 작업의 성공 여부, 시스템 상태가 변경되었는지, 에러 메시지 등이 포함됩니다. Ansible은 모든 작업이 끝난 후, Managed Node에서 임시 파일을 삭제하여 흔적을 남기지 않습니다. 마지막으로 Control Node는 모든 Managed Node로부터 받은 결과를 수집하고 집계하여 콘솔에 출력합니다.
이러한 방식의 가장 큰 특징은 Agentless Architecture입니다. Puppet이나 Chef 같은 전통적인 구성 관리 도구들은 각 Managed Node에 에이전트 프로그램을 설치하고 이를 데몬으로 상시 실행해야 합니다. 에이전트는 지속적으로 메모리를 사용하며, 정기적으로 중앙 서버와 통신하고, 자체적으로 보안 업데이트가 필요합니다. 반면 Ansible은 필요할 때만 SSH로 연결하고 작업이 끝나면 연결을 종료합니다. Managed Node에는 SSH 데몬과 Python만 있으면 되므로 추가적인 프로세스나 관리 오버헤드가 없습니다.
Core Concepts
Control Node
Control Node는 Ansible CLI 도구를 실행하는 머신입니다. ansible-playbook, ansible, ansible-vault, ansible-galaxy 등의 명령어를 여기서 실행합니다.
Python이 설치된 거의 모든 시스템이 Control Node가 될 수 있습니다. Linux, macOS, BSD 등 Unix-like 운영체제를 지원하며, WSL도 Control Node로 사용 가능합니다. 다만 네이티브 Windows는 지원하지 않습니다.
Managed Nodes
Managed Nodes는 Ansible로 관리하는 대상 장치입니다. “Hosts”라고도 부르며, 서버, 네트워크 장비, 클라우드 인스턴스 등 모든 컴퓨터가 될 수 있습니다.
Linux 서버는 SSH를 통해, Windows 서버는 WinRM을 통해 관리합니다. 네트워크 장비도 Managed Node가 될 수 있으며, Cisco, Juniper, Arista 등 주요 벤더들이 자체 Ansible Collection을 제공합니다.
Inventory
Inventory는 Managed Nodes의 목록입니다. 단순히 호스트를 나열하는 것을 넘어, 그룹으로 조직하고 변수를 할당하며 인프라 구조를 표현합니다.
기본 위치는 /etc/ansible/hosts이지만, -i 옵션으로 다른 파일을 지정할 수 있습니다. INI 형식과 YAML 형식을 모두 지원합니다.
정적 Inventory 파일 외에도 Dynamic Inventory를 지원합니다. 클라우드 환경에서는 인스턴스가 자주 생성되고 삭제되므로, AWS, GCP, Azure 등의 API를 통해 실시간으로 인스턴스 목록을 가져올 수 있습니다.
Playbooks and Plays
Playbook은 Ansible 자동화를 정의하는 최상위 단위로, YAML 형식의 설계도입니다. 하나 이상의 Play로 구성되며, ansible-playbook 명령을 통해 실행됩니다.
Play는 Ansible 실행의 핵심 컨텍스트로, 특정 Managed Node 그룹에 대해 어떤 실행 환경과 작업 흐름을 적용할지를 정의합니다. 각 Play는 hosts, vars, Role, 그리고 순서가 보장된 Task들의 순서를 포함합니다. 하나의 Playbook에는 서로 다른 호스트 그룹을 대상으로 하는 여러 Play를 정의할 수 있습니다.
실행 관점에서 Play는 이중 루프 구조로 동작합니다. 먼저 Play에 지정된 모든 호스트를 대상으로 하며, 각 호스트에 대해 정의된 Task를 위에서 아래 순서대로 실행합니다. 기본적으로 Task는 여러 호스트에서 병렬 실행되며, serial 파라미터를 사용해 한 번에 처리할 호스트 수를 제한함으로써 배포 전략(롤링 업데이트 등)을 제어할 수 있습니다.
Tasks and Modules
Play가 어떤 호스트에서 어떤 작업 흐름을 실행할지를 정의하면, Task는 그 컨텍스트 안에서 실제로 수행되는 최소 실행 단위입니다.
각 Task는 하나의 Module을 호출하고, 해당 Module에 필요한 파라미터를 전달합니다. Task에는 사람이 읽기 쉬운 설명을 위해 name 필드를 포함하며, 조건부 실행(when), 실행 결과 저장(register), 변경 시 Handler 트리거(notify) 등 실행 제어 기능을 함께 정의할 수 있습니다.
Module은 Ansible이 Managed Node에 전송하고 실행하는 Python 코드입니다. 패키지 설치, 파일 복사, 서비스 관리, 사용자 생성, 데이터베이스 조작, 클라우드 리소스 프로비저닝 등 거의 모든 IT 작업을 Module로 수행합니다.
Module의 실행 과정은 아래와 같습니다.
- Control Node에서 선택된 Module이 Managed Node로 전송
- Managed Node의 임시 디렉터리에 저장 후, Python으로 실행
- 현재 상태를 점검하고, 필요한 경우에만 변경 수행
- 실행 결과를 JSON 형태로 Control Node에 반환
- 임시 파일 정리
Ansible은 수천 개의 내장 Module을 제공합니다. 가장 기본적인 Module들은 ansible.builtin Collection에 포함되어 있으며, 클라우드 프로바이더들은 자체 Collection을 통해 추가 Module을 제공합니다.
Playbook 없이 단일 Task만 실행할 때는 Ad-hoc Command를 사용합니다. 빠른 확인이나 간단한 작업에 유용하지만, 복잡한 자동화는 Playbook 사용이 권장됩니다.
Plugins and Collections
Plugin은 Ansible의 실행 동작 자체를 확장하거나 변경하는 구성 요소입니다. Module이 무엇을 할지를 정의한다면, Plugin은 그 작업이 어떻게 수행될지를 제어합니다.
Ansible은 다양한 유형의 Plugin을 제공합니다. 예를 들어, Connection Plugin은 Control Node와 Managed Node 간의 연결 방식을 결정하고, Callback Plugin은 Playbook 실행 결과의 출력 형식을 제어합니다. 이 외에도 Lookup, Inventory, Cache Plugin 등 실행 전반에 관여하는 여러 Plugin 유형이 존재합니다.
Collection은 Ansible 콘텐츠를 배포하고 관리하기 위한 패키징 단위입니다. Playbook, Role, Module, Plugin을 하나의 Collection으로 묶어 버전 관리하고 배포할 수 있습니다. Ansible 2.10 이후부터 대부분의 Module과 Plugin은 코어에서 분리되어 개별 Collection 형태로 제공되며, ansible-galaxy를 통해 설치됩니다.
Collection 구조를 통해 특정 벤더나 기술 스택에 특화된 자동화 코드를 Ansible 코어와 독립적으로 개발·배포할 수 있습니다. 사용자는 필요한 기능에 해당하는 Collection만 선택적으로 설치함으로써, 환경에 맞는 자동화 구성을 유지할 수 있습니다.
Ansible Configuration
Ansible의 동작 방식은 ansible.cfg 파일로 전체적으로 제어할 수 있습니다. 프로젝트별로 다른 설정을 적용할 때 유용합니다.
Configuration Priority
Ansible은 여러 위치에서 설정을 읽으며, 명확한 우선순위가 있습니다.
- 환경변수
ANSIBLE_CONFIG - 현재 디렉터리의
ansible.cfg(프로젝트별 설정) - 사용자 홈 디렉터리의
~/.ansible.cfg(사용자 설정) /etc/ansible/ansible.cfg(시스템 전역 설정)
ansible --version 출력의 config file 항목으로 현재 사용 중인 설정 파일 경로를 확인할 수 있습니다.
Environment
실습 환경은 다음과 같이 구성됩니다.
| Node | OS | Kernel | CPU | Memory | IP | Role |
|---|---|---|---|---|---|---|
| server | Ubuntu 24.04 | 6.8.0 | 2 vCPU | 1.5GB | 10.10.1.10 | Ansible Control Node |
| tnode1 | Ubuntu 24.04 | 6.8.0 | 2 vCPU | 1.5GB | 10.10.1.11 | Managed Node |
| tnode2 | Ubuntu 24.04 | 6.8.0 | 2 vCPU | 1.5GB | 10.10.1.12 | Managed Node |
| tnode3 | Rocky Linux 9 | 5.14.0 | 2 vCPU | 1.5GB | 10.10.1.13 | Managed Node |
서로 다른 Linux 배포판을 혼합한 이유는 Ansible이 다양한 환경에서 어떻게 동작하는지 경험하기 위함입니다. 실제 프로덕션 환경에서도 레거시 시스템과 최신 시스템이 혼재할 수 있으며, Ansible은 이러한 이질적 환경을 통합 관리할 수 있습니다.
환경 구축은 Vagrant를 사용하여 자동화됩니다. Vagrant는 가상 머신의 생성과 구성을 코드로 관리할 수 있게 해주는 도구입니다. 다음 명령어로 실습 환경을 배포합니다.
mkdir ansible
cd ansible
curl -O https://raw.githubusercontent.com/gasida/vagrant-lab/refs/heads/main/ansible/Vagrantfile
curl -O https://raw.githubusercontent.com/gasida/vagrant-lab/refs/heads/main/ansible/init_cfg.sh
curl -O https://raw.githubusercontent.com/gasida/vagrant-lab/refs/heads/main/ansible/init_cfg2.sh
vagrant up
vagrant up 명령이 실행되면 VMWare에 4개의 가상 머신이 생성되고, 각 머신에서 초기화 스크립트가 자동으로 실행됩니다. 이 스크립트들은 시스템 시간대 설정, 방화벽 비활성화, 필요한 패키지 설치, 사용자 계정 구성, /etc/hosts 파일 업데이트 등을 수행합니다. 모든 과정이 자동화되어 있어 5-10분 정도면 전체 환경이 준비됩니다.
Verification
환경이 정상적으로 구축되었는지 확인하기 위해 vagrant ssh server를 통해 server 노드에 접속 후에 아래와 같이 명령을 날립니다.
for i in {1..3}; do ping -c 1 tnode$i; done
이는 tnode1, tnode2, tnode3 각각에 ping을 1회씩 보내 네트워크 연결을 확인합니다. 모든 노드에서 응답이 오면 네트워크가 정상적으로 구성된 것입니다.
Installing Ansible
이제 공식 문서를 참고하여 server 노드에 Ansible을 설치하겠습니다.
Ansible은 공식 PPA(Personal Package Archive)를 통해 설치합니다.
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible
설치가 완료되면 ansible --version을 통해 버전을 확인합니다.

출력에서는 아래와 같은 정보들을 확인할 수 있습니다.
- ansible-core: 현재 설치된 Ansible 버전
- config file: 기본 설정 파일 위치
- python version: Ansible이 사용하는 Python 버전 및 경로
- jinja version: 템플릿 엔진 버전
SSH Key-based Authentication
Ansible은 SSH를 통해 Managed Node에 접속하므로, 비밀번호 없이 자동으로 인증할 수 있는 SSH 키 기반 인증을 설정해야 합니다.
먼저 ssh-keygen 명령어를 이용하여 SSH 키를 생성합니다.
ssh-keygen -t rsa -N "" -f /root/.ssh/id_rsa
이제 생성된 Public Key를 모든 Managed Node에 배포합니다:
for i in {1..3}; do
sshpass -p 'qwe123' ssh-copy-id -o StrictHostKeyChecking=no root@tnode$i
done
이제 Ansible을 사용하여 Managed Node에 접속할 때 비밀번호 없이 SSH 키를 사용하여 인증할 수 있습니다.
Connection Test
Ansible 설치와 SSH 구성이 완료되었으므로, ping 모듈을 사용하여 Ansible이 Managed Node와 정상적으로 통신할 수 있는지 확인합니다.
먼저 가장 간단한 형태의 Inventory 파일을 생성합니다.
cat <<EOT > inventory
10.10.1.11
10.10.1.12
10.10.1.13
EOT
이제 ansible 명령어로 ping 테스트를 실행합니다.
Ansible의
ping모듈은 단순 네트워크 응답(ICMP)이 아닌 SSH 연결과 대상 서버 내 파이썬 환경의 정상 작동 여부를 확인하는 도구입니다. 이는 Python 기반의 테스트 모듈로 실제 작업을 수행할 수 있는 상태인지 검증하며, 성공 시pong이라는 결과값을 반환합니다.
ansible all -i inventory -m ping | jq
각 호스트마다 SUCCESS 메시지와 함께 JSON 형식의 결과가 출력됩니다. “discovered_interpreter_python” 필드는 Ansible이 자동으로 발견한 Python 인터프리터의 경로를 보여주며, “changed”는 시스템 상태가 변경되었는지를 나타냅니다. ping Module은 상태를 변경하지 않으므로 항상 false입니다.
Ansible 명령어에 ‘-v’ 옵션을 추가하면 더 자세한 실행 정보를 볼 수 있습니다. ‘v’의 개수를 늘릴수록 상세도가 증가하며, ‘-vvvv’까지 사용하면 SSH 연결의 모든 디버그 정보를 확인할 수 있습니다.
Comments