PYY0715's Tech Blog v3.1.0

Search the Post!

[Ansible for Kubespray] 2. Inventory Managements

Cloudnet@ K8S Deploy — Week2

Introduction

첫 번째 글에서 IP 주소 몇 개를 나열한 간단한 Inventory로 Ansible의 기본 동작을 확인했습니다. 하지만 실제 환경에서는 수십 개 이상의 호스트를 관리해야 하며, 각 호스트는 서로 다른 역할과 설정을 가집니다. 웹 서버, 데이터베이스 서버, 로드 밸런서가 각각 다른 설정을 필요로 하고, 개발 환경과 프로덕션 환경은 분리되어야 합니다. Inventory는 단순히 호스트 목록을 나열하는 것을 넘어, Variables를 통해 각 호스트의 연결 설정과 고유 속성을 정의합니다.

Understanding Inventory Structure

Ansible Inventory는 관리 대상 호스트의 목록과 설정을 담은 파일입니다. 기본 위치는 /etc/ansible/hosts이지만 프로젝트별로 별도의 Inventory 파일을 만드는 것이 권장됩니다.

blog ui https://kimalarm.tistory.com/78

Inventory는 INI와 YAML 두 가지 형식을 지원합니다. Kubespray를 포함한 많은 프로젝트들이 INI 형식을 사용하기 때문에, 이 글에서도 INI 형식을 사용합니다.

가장 간단한 형태는 호스트를 한 줄에 하나씩 나열하는 것입니다.

첫 번째 글에서 사용한 단순한 IP 목록은 실제 환경에서 관리하기 어렵습니다. 호스트 별칭(alias)을 사용하면 가독성이 크게 향상됩니다.

[web]
tnode1 ansible_host=10.10.1.11
tnode2 ansible_host=10.10.1.12

[db]
tnode3 ansible_host=10.10.1.13

[all:children]
web
db

호스트 별칭을 사용하면 서버의 IP가 변경되어도 Playbook을 수정할 필요 없이 Inventory만 업데이트하면 됩니다.

Inventory Variables

Inventory에서 사용할 수 있는 변수들은 Ansible이 호스트에 어떻게 연결하고 동작할지를 제어합니다. 공식 문서에서는 이를 Behavioral Inventory Parameters라고 부르며, 용도에 따라 네 가지로 분류됩니다.

Connection Parameters

모든 연결 유형에 적용되는 기본 연결 파라미터입니다.

Variables Description Default
ansible_connection 연결 플러그인 타입 (ssh, paramiko, local, docker 등) smart (ssh)
ansible_host 실제 연결할 IP 주소 또는 FQDN inventory_hostname
ansible_port 연결 포트 번호 22 (SSH)
ansible_user 로그인 사용자명 현재 사용자
[web]
tnode1 ansible_host=10.10.1.11 ansible_user=ubuntu
tnode2 ansible_host=10.10.1.12 ansible_user=ubuntu

[db]
tnode3 ansible_host=10.10.1.13 ansible_user=centos

SSH connection plugin Parameters

SSH는 Ansible의 기본 연결 방식으로 SSH 연결 플러그인에서만 사용하는 파라미터들입니다.

Variables Description
ansible_ssh_private_key_file SSH 개인키 파일 경로
ansible_password 인증 비밀번호 (Vault 사용 권장)
ansible_ssh_common_args sftp, scp, ssh 명령에 추가할 공통 인자
ansible_sftp_extra_args sftp 명령에 추가할 인자

ansible_password는 평문 비밀번호를 저장하므로 보안상 권장되지 않습니다. 가능하면 SSH 키 인증을 사용하고, 불가피하게 비밀번호를 저장해야 한다면 Ansible Vault를 사용해야 합니다.

Privilege Escalation (Become) Parameters

Linux 시스템에서 패키지 설치, 서비스 재시작 등 관리 작업을 수행하려면 root 권한이 필요합니다. Become 파라미터가 이를 제어합니다.

Variables Description Default
ansible_become 권한 상승 사용 여부 false
ansible_become_method 권한 상승 방법 (sudo, su, pbrun, pfexec 등) sudo
ansible_become_user 권한 상승 대상 사용자 root
ansible_become_password 권한 상승 비밀번호 (Vault 사용 권장) -

일반적으로 운영 서버는 보안상의 이유로 root 직접 로그인을 막고, 일반 사용자로 로그인한 후 sudo로 권한을 상승시킵니다. 이런 환경에서는 ansible_become: true를 설정해야 합니다.

production:
  hosts:
    app1.example.com:
      ansible_user: deploy
      ansible_become: true
      ansible_become_method: sudo
      ansible_become_user: root

Remote Environment Parameters

원격 호스트의 실행 환경과 관련된 파라미터들입니다.

Variables Description Default
ansible_shell_type Shell 타입 (sh, bash, zsh, csh, fish 등) sh
ansible_shell_executable 셸 실행 파일 경로 /bin/sh
ansible_python_interpreter Python 인터프리터 경로 자동 탐지

Host and Groups

Inventory의 호스트를 그룹으로 조직하고 변수를 계층적으로 관리할 수 있습니다

Organizing Hosts with Groups

그룹은 유사한 역할이나 특성을 가진 호스트들을 묶는 논리적 단위입니다. 하나의 호스트는 여러 그룹에 동시에 속할 수 있으며, 그룹 간에도 계층 구조를 만들 수 있습니다.

[webservers]
web1 ansible_host=10.10.1.11
web2 ansible_host=10.10.1.12

[databases]
db1 ansible_host=10.10.1.13
db2 ansible_host=10.10.1.14

[production:children]
webservers
databases

[all:children]
production
monitoring

이 구조에서 production 그룹은 webserversdatabases 그룹을 포함하는 상위 그룹입니다. Playbook에서 hosts: production으로 지정하면 웹 서버와 데이터베이스 서버 모두에서 작업이 실행됩니다.

Host Variables

호스트 변수는 특정 호스트에만 적용되는 설정을 정의합니다. Inventory 파일에서 호스트명 옆에 key=value 형식으로 정의합니다.

[webservers]
web1 ansible_host=10.10.1.11 ansible_port=2222 max_connections=100
web2 ansible_host=10.10.1.12 ansible_user=centos max_connections=200

이 예제에서는 두 가지 유형의 변수를 정의합니다.

Group Variables

그룹 변수는 그룹에 속한 모든 호스트에 공통으로 적용되는 설정을 정의합니다. Inventory 파일에서 [groupname:vars] 섹션을 사용할 수 있습니다.

[webservers]
web1 ansible_host=10.10.1.11
web2 ansible_host=10.10.1.12

[webservers:vars]
ansible_user=ubuntu
ansible_python_interpreter=/usr/bin/python3
http_port=8080

[webservers:vars] 섹션의 변수는 web1web2 모두에 적용됩니다. 이렇게 하면 동일한 설정을 각 호스트마다 반복해서 입력할 필요가 없습니다.

그룹 [all:vars]는 모든 호스트에 적용되는 전역 변수를 정의합니다.

[webservers]
web1 ansible_host=10.10.1.11
web2 ansible_host=10.10.1.12

[databases]
db1 ansible_host=10.10.1.13

[all:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_become=yes

Using group_vars and host_vars

변수가 많아지거나 복잡해지면 Inventory 파일에 모두 담기 어렵습니다. Ansible은 group_varshost_vars 디렉토리를 통해 변수를 별도 파일로 분리하는 기능을 제공합니다.

my-ansible/
├── inventory
├── ansible.cfg
├── group_vars/
│   ├── all.yml
│   ├── webservers.yml
│   └── databases.yml
└── host_vars/
    ├── web1.yml
    └── db1.yml

Ansible은 Playbook을 실행할 때, 자동으로 이 디렉토리들을 검색하여 변수를 로드합니다. Inventory 파일은 간결하게 유지하고, 변수는 별도 파일로 관리하는 것이 모범 사례입니다.

Tips for building Groups

Ansible 공식 문서에서 그룹을 구성할 때 What, Where, When 세 가지 관점을 고려할 것을 권장합니다.

또한 그룹명은 아래와 같은 Naming Conventions를 가집니다.

Dynamic Inventory

정적 Inventory는 모든 호스트를 수동으로 관리합니다. 클라우드 환경에서는 Auto Scaling으로 인스턴스가 자주 생성되고 삭제되므로 정적 Inventory 유지가 어렵습니다.

Dynamic Inventory는 Cloud Provider API를 실시간으로 호출하여 인스턴스 목록을 가져옵니다. Ansible은 두 가지 방법을 지원합니다.

  1. Inventory Script(Legacy)
  2. Inventory Plugin(Recommended)

AWS EC2 Dynamic Inventory

AWS 환경에서 가장 많이 사용되는 aws_ec2 플러그인을 실습합니다.

Prerequisites

이를 위해서는 필수 패키지가 설치되어야 합니다.

pip install boto3 botocore

ansible-galaxy collection install amazon.aws

Authentication

AWS 인증은 다양한 방법을 지원합니다.

Configuration

Inventory Plugin을 사용하여 AWS EC2 인스턴스를 동적으로 관리합니다.이 때의 Inventory 파일명은 aws_ec2.yml 또는 aws_ec2.yaml로 정의되어야 합니다.

The inventory file is a YAML configuration file and must end with aws_ec2.{yml | yaml}

plugin: amazon.aws.aws_ec2
regions:
  - ap-northeast-2
filters:
  instance-state-name: running

필터를 사용하여 특정 조건의 인스턴스만 Inventory에 포함할 수 있습니다.

keyed_groups를 사용하면 EC2 태그를 기반으로 자동으로 그룹을 생성할 수 있습니다.

plugin: amazon.aws.aws_ec2
regions:
  - ap-northeast-2
filters:
  instance-state-name: running
keyed_groups:
  # 모든 태그로 그룹 생성: tag_<태그키>_<태그값>` 형식의 그룹으로 만듭니다.
  - prefix: tag
    key: tags
  # 특정 태그값으로 그룹 생성: e.g., Environment_dev, Environment_prod
  - key: tags.Environment
    separator: ''
  # 인스턴스 유형별 그룹 e.g., instance_type_t3_small
  - prefix: instance_type
    key: instance_type

Practice

이제 배운 내용을 실습으로 확인해보겠습니다. 실제로 Inventory를 구성하고 변수를 정의한 후, 간단한 Playbook으로 변수가 올바르게 적용되는지 테스트합니다.

Environment Setup

실습을 위한 디렉토리 구조를 만듭니다.

mkdir -p ~/my-ansible
cd ~/my-ansible

아래와 같이 ansible.cfg 파일을 생성합니다.

cat <<EOT > ansible.cfg
[defaults]
inventory = ./inventory
remote_user = root
ask_pass = false

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
EOT

Creating Inventory

inventory 파일을 생성합니다.

cat <<EOT > inventory
[web]
tnode1 ansible_python_interpreter=/usr/bin/python3
tnode2 ansible_python_interpreter=/usr/bin/python3

[db]
tnode3 ansible_python_interpreter=/usr/bin/python3

[all:children]
web
db
EOT

연결을 테스트합니다.

ansible all -m ping

성공적으로 연결되면 다음과 같은 출력을 볼 수 있습니다.

ping

Using group_vars and host_vars

이제 group_varshost_vars를 사용하여 변수를 계층적으로 관리하고, 변수 우선순위를 확인해보겠습니다.

먼저 필요한 디렉토리를 생성합니다.

mkdir -p group_vars host_vars

group_vars/all.yml에 모든 호스트에 적용될 변수를 정의합니다.

cat <<EOT > group_vars/all.yml
---
message: "Hello from all group"
priority: 1
EOT

group_vars/web.yml에서 web 그룹에 적용될 변수를 정의합니다. all 그룹에서 정의한 messagepriority 변수를 오버라이드합니다.

cat <<EOT > group_vars/web.yml
---
message: "Hello from web group"
priority: 2
EOT

host_vars/tnode1.yml에서 tnode1 호스트에만 적용될 변수를 정의합니다. allweb 그룹에서 정의한 변수를 오버라이드합니다.

cat <<EOT > host_vars/tnode1.yml
---
message: "Hello from tnode1 host"
priority: 3
EOT

Verifying Variable Priority

ad-hoc 명령으로 각 호스트에 적용된 변수를 확인해보겠습니다. ad-hoc 명령은 Playbook 없이 단일 명령으로 빠르게 작업을 수행할 때 사용합니다.

변수별로 결과를 확인합니다.

Ansible은 호스트 실행 순서를 보장하지 않습니다.

ansible all -m debug -a "var=message"
ansible all -m debug -a "var=priority"

result

이 결과를 통해 변수 우선순위를 확인할 수 있습니다. all group < specific group < host variables

Why don't you read something next?
[Ansible for Kubespray] 3. Playbooks, Variables and Facts

[Ansible for Kubespray] 3. Playbooks, Variables and Facts

Share

Comments