Ansible ๊ธฐ์ดˆ

Ansible ๊ธฐ์ดˆ

ํ•™์Šต ๋ชฉํ‘œ

์ด ๋ฌธ์„œ๋ฅผ ํ†ตํ•ด ๋‹ค์Œ์„ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค:

  • Ansible์˜ ๊ฐœ๋…๊ณผ ์•„ํ‚คํ…์ฒ˜
  • ์ธ๋ฒคํ† ๋ฆฌ์™€ Ad-hoc ๋ช…๋ น์–ด
  • Playbook ์ž‘์„ฑ ๋ฐ ์‹คํ–‰
  • Roles์™€ ๋ณ€์ˆ˜ ๊ด€๋ฆฌ

๋‚œ์ด๋„: โญโญโญ (์ค‘๊ธ‰-๊ณ ๊ธ‰)


๋ชฉ์ฐจ

  1. Ansible ๊ฐœ์š”
  2. ์„ค์น˜ ๋ฐ ์„ค์ •
  3. ์ธ๋ฒคํ† ๋ฆฌ
  4. Ad-hoc ๋ช…๋ น์–ด
  5. Playbook
  6. ๋ณ€์ˆ˜์™€ ํŒฉํŠธ
  7. Roles
  8. Ansible Vault

1. Ansible ๊ฐœ์š”

Ansible์ด๋ž€?

Ansible์€ ์—์ด์ „ํŠธ ์—†์ด SSH๋กœ ์ž‘๋™ํ•˜๋Š” IT ์ž๋™ํ™” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                     Control Node                            โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚  Ansible                                             โ”‚   โ”‚
โ”‚  โ”‚  โ”œโ”€โ”€ Playbooks (YAML)                                โ”‚   โ”‚
โ”‚  โ”‚  โ”œโ”€โ”€ Inventory                                       โ”‚   โ”‚
โ”‚  โ”‚  โ”œโ”€โ”€ Modules                                         โ”‚   โ”‚
โ”‚  โ”‚  โ””โ”€โ”€ Plugins                                         โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ”‚ SSH
        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        โ”‚                   โ”‚                   โ”‚
        โ–ผ                   โ–ผ                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Managed Node  โ”‚  โ”‚ Managed Node  โ”‚  โ”‚ Managed Node  โ”‚
โ”‚ (web-server1) โ”‚  โ”‚ (web-server2) โ”‚  โ”‚ (db-server)   โ”‚
โ”‚   No agent    โ”‚  โ”‚   No agent    โ”‚  โ”‚   No agent    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Ansible vs ๋‹ค๋ฅธ ๋„๊ตฌ

ํŠน์„ฑ Ansible Puppet Chef
์—์ด์ „ํŠธ ๋ถˆํ•„์š” ํ•„์š” ํ•„์š”
์–ธ์–ด YAML Ruby DSL Ruby
Push/Pull Push Pull Pull
ํ•™์Šต ๊ณก์„  ๋‚ฎ์Œ ์ค‘๊ฐ„ ๋†’์Œ

2. ์„ค์น˜ ๋ฐ ์„ค์ •

Ansible ์„ค์น˜

# Ubuntu/Debian
sudo apt update
sudo apt install ansible

# RHEL/CentOS
sudo yum install epel-release
sudo yum install ansible

# pip๋กœ ์„ค์น˜ (๊ถŒ์žฅ)
pip3 install ansible

# ๋ฒ„์ „ ํ™•์ธ
ansible --version

SSH ํ‚ค ์„ค์ •

# SSH ํ‚ค ์ƒ์„ฑ
ssh-keygen -t ed25519 -f ~/.ssh/ansible_key

# ๋Œ€์ƒ ์„œ๋ฒ„์— ํ‚ค ๋ณต์‚ฌ
ssh-copy-id -i ~/.ssh/ansible_key.pub user@target-server

# SSH ์—ฐ๊ฒฐ ํ…Œ์ŠคํŠธ
ssh -i ~/.ssh/ansible_key user@target-server

ansible.cfg ์„ค์ •

# /etc/ansible/ansible.cfg (์ „์—ญ)
# ~/.ansible.cfg (์‚ฌ์šฉ์ž)
# ./ansible.cfg (ํ”„๋กœ์ ํŠธ)
# ansible.cfg
[defaults]
inventory = ./inventory
remote_user = ansible
private_key_file = ~/.ssh/ansible_key
host_key_checking = False
retry_files_enabled = False
forks = 20
timeout = 30

[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False

[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=60s

3. ์ธ๋ฒคํ† ๋ฆฌ

INI ํ˜•์‹

# inventory/hosts
[webservers]
web1.example.com
web2.example.com ansible_host=192.168.1.11

[dbservers]
db1.example.com ansible_host=192.168.1.21 ansible_port=2222
db2.example.com ansible_user=dbadmin

[loadbalancers]
lb1.example.com

# ๊ทธ๋ฃน์˜ ๊ทธ๋ฃน
[production:children]
webservers
dbservers
loadbalancers

# ๊ทธ๋ฃน ๋ณ€์ˆ˜
[webservers:vars]
http_port=80
max_clients=200

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

YAML ํ˜•์‹

# inventory/hosts.yml
all:
  children:
    webservers:
      hosts:
        web1.example.com:
        web2.example.com:
          ansible_host: 192.168.1.11
      vars:
        http_port: 80
        max_clients: 200

    dbservers:
      hosts:
        db1.example.com:
          ansible_host: 192.168.1.21
          ansible_port: 2222
        db2.example.com:
          ansible_user: dbadmin

    production:
      children:
        webservers:
        dbservers:

  vars:
    ansible_python_interpreter: /usr/bin/python3

๋™์  ์ธ๋ฒคํ† ๋ฆฌ

# AWS EC2 ๋™์  ์ธ๋ฒคํ† ๋ฆฌ
pip install boto3 botocore

# ansible.cfg
[defaults]
inventory = aws_ec2.yml
# aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
  - ap-northeast-2
keyed_groups:
  - key: tags.Environment
    prefix: env
  - key: instance_type
    prefix: type
compose:
  ansible_host: public_ip_address

์ธ๋ฒคํ† ๋ฆฌ ํ™•์ธ

# ํ˜ธ์ŠคํŠธ ๋ชฉ๋ก
ansible-inventory --list
ansible-inventory --graph

# ํŠน์ • ๊ทธ๋ฃน
ansible webservers --list-hosts

# ํ˜ธ์ŠคํŠธ ๋ณ€์ˆ˜ ํ™•์ธ
ansible-inventory --host web1.example.com

4. Ad-hoc ๋ช…๋ น์–ด

๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

ansible <pattern> -m <module> -a "<arguments>"

# ์˜ˆ์‹œ
ansible all -m ping
ansible webservers -m command -a "uptime"
ansible dbservers -m shell -a "df -h | grep /dev/sda"

์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“ˆ

# ping (์—ฐ๊ฒฐ ํ…Œ์ŠคํŠธ)
ansible all -m ping

# command (๊ธฐ๋ณธ ๋ช…๋ น ์‹คํ–‰)
ansible all -m command -a "hostname"

# shell (์‰˜ ๊ธฐ๋Šฅ ์‚ฌ์šฉ)
ansible all -m shell -a "cat /etc/os-release | grep VERSION"

# copy (ํŒŒ์ผ ๋ณต์‚ฌ)
ansible all -m copy -a "src=/local/file dest=/remote/path mode=0644"

# file (ํŒŒ์ผ/๋””๋ ‰ํ† ๋ฆฌ ๊ด€๋ฆฌ)
ansible all -m file -a "path=/tmp/testdir state=directory mode=0755"

# yum/apt (ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ)
ansible webservers -m yum -a "name=httpd state=present"
ansible webservers -m apt -a "name=nginx state=present update_cache=yes"

# service (์„œ๋น„์Šค ๊ด€๋ฆฌ)
ansible webservers -m service -a "name=nginx state=started enabled=yes"

# user (์‚ฌ์šฉ์ž ๊ด€๋ฆฌ)
ansible all -m user -a "name=deploy state=present groups=sudo"

# setup (์‹œ์Šคํ…œ ์ •๋ณด ์ˆ˜์ง‘)
ansible web1 -m setup
ansible web1 -m setup -a "filter=ansible_distribution*"

๊ถŒํ•œ ์ƒ์Šน

# sudo ์‚ฌ์šฉ
ansible all -m apt -a "name=vim state=present" --become

# ํŠน์ • ์‚ฌ์šฉ์ž๋กœ
ansible all -m command -a "whoami" --become --become-user=postgres

๋ณ‘๋ ฌ ์‹คํ–‰

# ๋™์‹œ ์‹คํ–‰ ํ˜ธ์ŠคํŠธ ์ˆ˜ ์กฐ์ ˆ
ansible all -m ping -f 50  # 50๊ฐœ ๋™์‹œ ์‹คํ–‰

# ์ˆœ์ฐจ ์‹คํ–‰
ansible all -m ping -f 1

5. Playbook

๊ธฐ๋ณธ ๊ตฌ์กฐ

# site.yml
---
- name: Configure webservers
  hosts: webservers
  become: yes
  vars:
    http_port: 80

  tasks:
    - name: Install nginx
      apt:
        name: nginx
        state: present
        update_cache: yes

    - name: Start nginx service
      service:
        name: nginx
        state: started
        enabled: yes

- name: Configure databases
  hosts: dbservers
  become: yes

  tasks:
    - name: Install PostgreSQL
      apt:
        name: postgresql
        state: present

Playbook ์‹คํ–‰

# ๊ธฐ๋ณธ ์‹คํ–‰
ansible-playbook site.yml

# ์ธ๋ฒคํ† ๋ฆฌ ์ง€์ •
ansible-playbook -i inventory/production site.yml

# ๋“œ๋ผ์ด๋Ÿฐ (๋ณ€๊ฒฝ ์—†์ด ํ™•์ธ)
ansible-playbook site.yml --check

# ์ฐจ์ด์  ํ‘œ์‹œ
ansible-playbook site.yml --diff

# ์ƒ์„ธ ์ถœ๋ ฅ
ansible-playbook site.yml -v    # ์ƒ์„ธ
ansible-playbook site.yml -vvv  # ๋งค์šฐ ์ƒ์„ธ

# ํŠน์ • ํ˜ธ์ŠคํŠธ๋งŒ
ansible-playbook site.yml --limit web1.example.com

# ํƒœ๊ทธ ์‚ฌ์šฉ
ansible-playbook site.yml --tags "install,configure"
ansible-playbook site.yml --skip-tags "debug"

# ์‹œ์ž‘ ํƒœ์Šคํฌ ์ง€์ •
ansible-playbook site.yml --start-at-task "Start nginx service"

์กฐ๊ฑด๋ฌธ (when)

tasks:
  - name: Install Apache (RHEL)
    yum:
      name: httpd
      state: present
    when: ansible_os_family == "RedHat"

  - name: Install Apache (Debian)
    apt:
      name: apache2
      state: present
    when: ansible_os_family == "Debian"

  - name: Check if file exists
    stat:
      path: /etc/myapp.conf
    register: config_file

  - name: Create config if not exists
    template:
      src: myapp.conf.j2
      dest: /etc/myapp.conf
    when: not config_file.stat.exists

๋ฐ˜๋ณต๋ฌธ (loop)

tasks:
  - name: Install multiple packages
    apt:
      name: "{{ item }}"
      state: present
    loop:
      - nginx
      - vim
      - git
      - curl

  - name: Create users
    user:
      name: "{{ item.name }}"
      groups: "{{ item.groups }}"
      state: present
    loop:
      - { name: 'alice', groups: 'sudo' }
      - { name: 'bob', groups: 'developers' }

  - name: Install packages with apt
    apt:
      name: "{{ packages }}"
      state: present
    vars:
      packages:
        - nginx
        - postgresql
        - redis

ํ•ธ๋“ค๋Ÿฌ (handlers)

tasks:
  - name: Copy nginx config
    template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify: Restart nginx

  - name: Copy site config
    template:
      src: site.conf.j2
      dest: /etc/nginx/sites-available/mysite
    notify:
      - Reload nginx
      - Clear cache

handlers:
  - name: Restart nginx
    service:
      name: nginx
      state: restarted

  - name: Reload nginx
    service:
      name: nginx
      state: reloaded

  - name: Clear cache
    file:
      path: /var/cache/nginx
      state: absent

๋ธ”๋ก (block)

tasks:
  - name: Install and configure app
    block:
      - name: Install package
        apt:
          name: myapp
          state: present

      - name: Configure app
        template:
          src: myapp.conf.j2
          dest: /etc/myapp/config.yml

    rescue:
      - name: Rollback on failure
        apt:
          name: myapp
          state: absent

    always:
      - name: Always run cleanup
        file:
          path: /tmp/install_temp
          state: absent

    when: install_myapp | default(true)
    become: yes

6. ๋ณ€์ˆ˜์™€ ํŒฉํŠธ

๋ณ€์ˆ˜ ์ •์˜ ์œ„์น˜

์šฐ์„ ์ˆœ์œ„ (๋‚ฎ์Œ โ†’ ๋†’์Œ):
1. role defaults
2. inventory file vars
3. inventory group_vars
4. inventory host_vars
5. playbook group_vars
6. playbook host_vars
7. host facts
8. play vars
9. play vars_prompt
10. play vars_files
11. role vars
12. block vars
13. task vars
14. include_vars
15. set_facts / registered vars
16. role parameters
17. extra vars (-e)

๋ณ€์ˆ˜ ํŒŒ์ผ ๊ตฌ์กฐ

project/
โ”œโ”€โ”€ ansible.cfg
โ”œโ”€โ”€ inventory/
โ”‚   โ”œโ”€โ”€ hosts
โ”‚   โ”œโ”€โ”€ group_vars/
โ”‚   โ”‚   โ”œโ”€โ”€ all.yml
โ”‚   โ”‚   โ”œโ”€โ”€ webservers.yml
โ”‚   โ”‚   โ””โ”€โ”€ dbservers.yml
โ”‚   โ””โ”€โ”€ host_vars/
โ”‚       โ”œโ”€โ”€ web1.example.com.yml
โ”‚       โ””โ”€โ”€ db1.example.com.yml
โ”œโ”€โ”€ playbooks/
โ”‚   โ””โ”€โ”€ site.yml
โ””โ”€โ”€ roles/

group_vars/host_vars ์˜ˆ์‹œ

# inventory/group_vars/all.yml
---
ansible_user: deploy
ntp_servers:
  - 0.pool.ntp.org
  - 1.pool.ntp.org

# inventory/group_vars/webservers.yml
---
http_port: 80
nginx_worker_processes: auto

# inventory/host_vars/web1.example.com.yml
---
nginx_worker_processes: 4
custom_config: true

Playbook์—์„œ ๋ณ€์ˆ˜ ์‚ฌ์šฉ

---
- name: Configure web servers
  hosts: webservers
  vars:
    app_name: myapp
    app_version: "1.2.3"
    app_env: production

  vars_files:
    - vars/common.yml
    - "vars/{{ ansible_os_family }}.yml"

  tasks:
    - name: Deploy application
      template:
        src: app.conf.j2
        dest: "/etc/{{ app_name }}/config.yml"

    - name: Set runtime variable
      set_fact:
        runtime_var: "{{ ansible_hostname }}-{{ app_version }}"

ํŒฉํŠธ (Facts)

tasks:
  # ์ž๋™ ์ˆ˜์ง‘๋œ ํŒฉํŠธ ์‚ฌ์šฉ
  - name: Print OS info
    debug:
      msg: "OS: {{ ansible_distribution }} {{ ansible_distribution_version }}"

  # ์ปค์Šคํ…€ ํŒฉํŠธ (๋Œ€์ƒ ํ˜ธ์ŠคํŠธ์— ์ €์žฅ)
  # /etc/ansible/facts.d/custom.fact
  - name: Create custom fact
    copy:
      content: |
        [app]
        version=1.2.3
        environment=production
      dest: /etc/ansible/facts.d/custom.fact
      mode: '0644'

  # ํŒฉํŠธ ์ƒˆ๋กœ๊ณ ์นจ
  - name: Refresh facts
    setup:
      filter: ansible_local

  - name: Use custom fact
    debug:
      msg: "App version: {{ ansible_local.custom.app.version }}"

Jinja2 ํ…œํ”Œ๋ฆฟ

{# templates/nginx.conf.j2 #}
worker_processes {{ nginx_worker_processes | default('auto') }};

events {
    worker_connections {{ nginx_worker_connections | default(1024) }};
}

http {
    server {
        listen {{ http_port }};
        server_name {{ ansible_fqdn }};

        {% for location in nginx_locations | default([]) %}
        location {{ location.path }} {
            proxy_pass {{ location.proxy }};
        }
        {% endfor %}

        {% if enable_ssl | default(false) %}
        ssl_certificate {{ ssl_cert_path }};
        ssl_certificate_key {{ ssl_key_path }};
        {% endif %}
    }
}

7. Roles

Role ๊ตฌ์กฐ

roles/
โ””โ”€โ”€ webserver/
    โ”œโ”€โ”€ defaults/
    โ”‚   โ””โ”€โ”€ main.yml      # ๊ธฐ๋ณธ ๋ณ€์ˆ˜ (๋‚ฎ์€ ์šฐ์„ ์ˆœ์œ„)
    โ”œโ”€โ”€ files/
    โ”‚   โ””โ”€โ”€ static.conf   # ์ •์  ํŒŒ์ผ
    โ”œโ”€โ”€ handlers/
    โ”‚   โ””โ”€โ”€ main.yml      # ํ•ธ๋“ค๋Ÿฌ
    โ”œโ”€โ”€ meta/
    โ”‚   โ””โ”€โ”€ main.yml      # ์˜์กด์„ฑ, ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ
    โ”œโ”€โ”€ tasks/
    โ”‚   โ””โ”€โ”€ main.yml      # ํƒœ์Šคํฌ
    โ”œโ”€โ”€ templates/
    โ”‚   โ””โ”€โ”€ nginx.conf.j2 # Jinja2 ํ…œํ”Œ๋ฆฟ
    โ””โ”€โ”€ vars/
        โ””โ”€โ”€ main.yml      # ๋ณ€์ˆ˜ (๋†’์€ ์šฐ์„ ์ˆœ์œ„)

Role ์ƒ์„ฑ

# ๊ธฐ๋ณธ ๊ตฌ์กฐ ์ƒ์„ฑ
ansible-galaxy init roles/webserver

Role ์˜ˆ์‹œ

# roles/webserver/defaults/main.yml
---
nginx_port: 80
nginx_worker_processes: auto
nginx_sites: []
# roles/webserver/tasks/main.yml
---
- name: Install nginx
  apt:
    name: nginx
    state: present
    update_cache: yes
  tags: install

- name: Configure nginx
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: Restart nginx
  tags: configure

- name: Configure sites
  template:
    src: site.conf.j2
    dest: "/etc/nginx/sites-available/{{ item.name }}"
  loop: "{{ nginx_sites }}"
  notify: Reload nginx
  tags: configure

- name: Enable sites
  file:
    src: "/etc/nginx/sites-available/{{ item.name }}"
    dest: "/etc/nginx/sites-enabled/{{ item.name }}"
    state: link
  loop: "{{ nginx_sites }}"
  notify: Reload nginx
  tags: configure

- name: Start nginx
  service:
    name: nginx
    state: started
    enabled: yes
  tags: service
# roles/webserver/handlers/main.yml
---
- name: Restart nginx
  service:
    name: nginx
    state: restarted

- name: Reload nginx
  service:
    name: nginx
    state: reloaded
# roles/webserver/meta/main.yml
---
dependencies:
  - role: common
  - role: firewall
    vars:
      firewall_allowed_ports:
        - "{{ nginx_port }}"

Role ์‚ฌ์šฉ

# site.yml
---
- name: Configure web servers
  hosts: webservers
  become: yes
  roles:
    - common
    - role: webserver
      vars:
        nginx_port: 8080
        nginx_sites:
          - name: mysite
            domain: example.com
            root: /var/www/mysite

- name: Configure databases
  hosts: dbservers
  become: yes
  roles:
    - common
    - postgresql

Ansible Galaxy

# Role ๊ฒ€์ƒ‰
ansible-galaxy search nginx

# Role ์„ค์น˜
ansible-galaxy install geerlingguy.nginx

# ์ปฌ๋ ‰์…˜ ์„ค์น˜
ansible-galaxy collection install community.general

# requirements.yml๋กœ ์„ค์น˜
ansible-galaxy install -r requirements.yml
# requirements.yml
---
roles:
  - name: geerlingguy.nginx
    version: "3.1.0"
  - name: geerlingguy.postgresql
    version: "3.3.1"

collections:
  - name: community.general
    version: ">=6.0.0"
  - name: amazon.aws
    version: "5.0.0"

8. Ansible Vault

Vault ๊ธฐ๋ณธ ์‚ฌ์šฉ

# ์ƒˆ ์•”ํ˜ธํ™” ํŒŒ์ผ ์ƒ์„ฑ
ansible-vault create secrets.yml

# ๊ธฐ์กด ํŒŒ์ผ ์•”ํ˜ธํ™”
ansible-vault encrypt vars/secrets.yml

# ํŒŒ์ผ ๋ณตํ˜ธํ™”
ansible-vault decrypt vars/secrets.yml

# ํŒŒ์ผ ํŽธ์ง‘
ansible-vault edit secrets.yml

# ํŒŒ์ผ ๋‚ด์šฉ ๋ณด๊ธฐ
ansible-vault view secrets.yml

# ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ
ansible-vault rekey secrets.yml

Vault ์‚ฌ์šฉ ์˜ˆ์‹œ

# vars/secrets.yml (์•”ํ˜ธํ™”๋จ)
---
db_password: "SuperSecretPassword123"
api_key: "sk-1234567890abcdef"
# playbook.yml
---
- name: Deploy application
  hosts: webservers
  vars_files:
    - vars/secrets.yml

  tasks:
    - name: Configure database
      template:
        src: db.conf.j2
        dest: /etc/app/db.conf
      # {{ db_password }} ์‚ฌ์šฉ ๊ฐ€๋Šฅ

Playbook ์‹คํ–‰

# ๋น„๋ฐ€๋ฒˆํ˜ธ ํ”„๋กฌํ”„ํŠธ
ansible-playbook site.yml --ask-vault-pass

# ๋น„๋ฐ€๋ฒˆํ˜ธ ํŒŒ์ผ ์‚ฌ์šฉ
ansible-playbook site.yml --vault-password-file ~/.vault_pass

# ํ™˜๊ฒฝ ๋ณ€์ˆ˜
export ANSIBLE_VAULT_PASSWORD_FILE=~/.vault_pass
ansible-playbook site.yml

๋ฌธ์ž์—ด ์•”ํ˜ธํ™”

# ๋ฌธ์ž์—ด๋งŒ ์•”ํ˜ธํ™”
ansible-vault encrypt_string 'MySecretPassword' --name 'db_password'

# ์ถœ๋ ฅ (YAML์— ์ง์ ‘ ์‚ฌ์šฉ)
db_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          66386439653236...

์—ฐ์Šต ๋ฌธ์ œ

๋ฌธ์ œ 1: ์ธ๋ฒคํ† ๋ฆฌ ์ž‘์„ฑ

๋‹ค์Œ ์„œ๋ฒ„๋“ค์˜ ์ธ๋ฒคํ† ๋ฆฌ๋ฅผ YAML ํ˜•์‹์œผ๋กœ ์ž‘์„ฑํ•˜์„ธ์š”: - app1, app2 (webservers ๊ทธ๋ฃน) - db1 (dbservers ๊ทธ๋ฃน) - ๋ชจ๋“  ์„œ๋ฒ„: ansible_user=deploy - webservers: http_port=8080

๋ฌธ์ œ 2: Playbook ์ž‘์„ฑ

nginx๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์‹œ์ž‘ํ•˜๋Š” Playbook์„ ์ž‘์„ฑํ•˜์„ธ์š”: - RedHat๊ณผ Debian ๊ณ„์—ด ๋ชจ๋‘ ์ง€์› - ํ•ธ๋“ค๋Ÿฌ๋กœ ์„œ๋น„์Šค ์žฌ์‹œ์ž‘ - ํƒœ๊ทธ ์‚ฌ์šฉ (install, configure)

๋ฌธ์ œ 3: Role ์ž‘์„ฑ

PostgreSQL์„ ์„ค์น˜ํ•˜๋Š” Role์˜ tasks/main.yml์„ ์ž‘์„ฑํ•˜์„ธ์š”: - ํŒจํ‚ค์ง€ ์„ค์น˜ - ์„œ๋น„์Šค ์‹œ์ž‘ - ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒ์„ฑ


์ •๋‹ต

๋ฌธ์ œ 1 ์ •๋‹ต

# inventory/hosts.yml
all:
  vars:
    ansible_user: deploy
  children:
    webservers:
      hosts:
        app1:
        app2:
      vars:
        http_port: 8080
    dbservers:
      hosts:
        db1:

๋ฌธ์ œ 2 ์ •๋‹ต

---
- name: Install and configure nginx
  hosts: webservers
  become: yes

  tasks:
    - name: Install nginx (RedHat)
      yum:
        name: nginx
        state: present
      when: ansible_os_family == "RedHat"
      tags: install

    - name: Install nginx (Debian)
      apt:
        name: nginx
        state: present
        update_cache: yes
      when: ansible_os_family == "Debian"
      tags: install

    - name: Copy nginx config
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: Restart nginx
      tags: configure

    - name: Start nginx
      service:
        name: nginx
        state: started
        enabled: yes
      tags: install

  handlers:
    - name: Restart nginx
      service:
        name: nginx
        state: restarted

๋ฌธ์ œ 3 ์ •๋‹ต

# roles/postgresql/tasks/main.yml
---
- name: Install PostgreSQL
  apt:
    name:
      - postgresql
      - postgresql-contrib
      - python3-psycopg2
    state: present
    update_cache: yes

- name: Start PostgreSQL service
  service:
    name: postgresql
    state: started
    enabled: yes

- name: Create application database
  become_user: postgres
  postgresql_db:
    name: "{{ pg_database | default('appdb') }}"
    state: present

- name: Create database user
  become_user: postgres
  postgresql_user:
    name: "{{ pg_user | default('appuser') }}"
    password: "{{ pg_password }}"
    db: "{{ pg_database | default('appdb') }}"
    priv: ALL
    state: present

๋‹ค์Œ ๋‹จ๊ณ„


์ฐธ๊ณ  ์ž๋ฃŒ

to navigate between lessons