본문 바로가기
데이터 엔지니어링

Ansible Inventory와 variables 설정 방법

by 내기록 2023. 3. 16.
반응형

목차 LIST

     

     

    Ansible 공식 문서를 통해 Inventory에 대한 전반적인 내용과 variables 설정 방법까지 확인해보겠습니다.

     

    How to build your inventory

    Inventory basics: formats, hosts, and groups

    inventory 파일의 default는 hosts(.ini)입니다. * ini : initialization

     

    sample)

    mail.example.com
    
    [webservers]
    foo.example.com
    bar.example.com
    
    [dbservers]
    one.example.com
    two.example.com
    three.example.com

     

    Default groups

    inventory file에 그룹을 아무것도 지정하지 않아도, Ansible은 `all`, `ungrouped`라는 두 개의 default 그룹을 생성합니다.

    `all`은 모든 호스트를 포함하고, `ungrouped`는 `all`을 제외한 다른 그룹에 속하지 않은 호스트를 가집니다.

    즉, 모든 호스트들은 ['all','ungrouped'] 또는 ['all','other group']에 속하게 되는 것입니다.

     

    Hosts in multiple groups

    한 호스트를 여러 그룹으로 나눴을 때, 아래와 같은 그룹들을 생성할 수 있습니다.

     

    What: An application, stack or microservice (for example, database servers, web servers, and so on).

    Where - A datacenter or region, to talk to local DNS, storage, and so on (for example, east, west).

    When - The development stage, to avoid testing on production resources (for example, prod, test).

     

    공식 홈페이지의 예시를 보면 위 3가지 내용이 모두 반영된 것을 확인할 수 있습니다.

    한 호스트가 여러 그룹에 속해있습니다.

    all:
      hosts:
        mail.example.com:
      children:
        webservers:
          hosts:
            foo.example.com:
            bar.example.com:
        dbservers:
          hosts:
            one.example.com:
            two.example.com:
            three.example.com:
        east:
          hosts:
            foo.example.com:
            one.example.com:
            two.example.com:
        west:
          hosts:
            bar.example.com:
            three.example.com:
        prod:
          hosts:
            foo.example.com:
            one.example.com:
            two.example.com:
        test:
          hosts:
            bar.example.com:
            three.example.com:

     

    Grouping groups: parent/child group relationships

    그룹 간의 parent/child 관계를 형성할 수 있습니다. Parent 그룹은 중첩된 그룹이나 그룹들의 그룹으로 알려져 있습니다.

    예를 들어보면, 만약에 모든 prod hosts들이 atlanta_prod와 denver_prod에 속해있다면, production 그룹을 생성하여 작은 그룹들을 포함시킬 수 있습니다.

     

    production

    ㄴatlanta_prod

    ㄴdenver_prod

     

    그룹 간의 parent/child 관계를 생성하는 방법

    - INI format은 `:children`을 사용 

    [east]
    foo.example.com:
    one.example.com:
    two.example.com:
    
    [prod:children]
    east

    - YAML format은 `children:`을 사용

    ...
    east:
      hosts:
        foo.example.com:
        one.example.com:
        two.example.com:
    ...
    
    prod:
      children:
        east:

     

    child 그룹에는 몇 가지 주목해야 하는 속성이 있습니다.

    1. child 그룹의 멤버가 되는 호스트는 자동적으로 parent group의 멤버가 된다.
    2. 그룹들은 여러 parents/children이 있지만, 순환 관계(circular relationships)는 불가능합니다.
    3. 호스트는 여러 그룹에 속할 수 있지만, 런타임에는 호스트가 하나만 존재합니다.
      Ansible이 여러 그룹들의 데이터를 병합(merge)하기 때문입니다.

     

    Organizing inventory in a directory

    많은 inventory 파일을 하나의 디렉토리에 통합할 수 있습니다. 하나의 파일이 너무 길어지면 관리가 어렵기 때문에 많은 팀이나 프로젝트가 있는 곳에서는 팀이나 프로젝트별로 하나의 인벤토리 파일을 가지는 것이 좋습니다. 이렇게 하면 모든 사람들이 쉽게 본인에게 필요한 호스트나 그룹을 쉽게 찾을 수 있습니다.

     

    인벤토리 디렉터리에서 여러 인벤토리 소스 유형을 결합할 수도 있습니다. 이는 정적 호스트와 동적 호스트를 결합하여 하나의 인벤토리로 관리할 때 유용할 수 있습니다. 다음 인벤토리 디렉터리에는 인벤토리 플러그인 소스, 동적 인벤토리 스크립트, 정적 호스트가 있는 파일이 결합되어 있습니다.

    inventory/
      openstack.yml          # configure inventory plugin to get hosts from OpenStack cloud
      dynamic-inventory.py   # add additional hosts with dynamic inventory script
      on-prem                # add static hosts and groups
      parent-groups          # add static hosts and groups
      
     
    # 사용
    ansible-playbook example.yml -i inventory

     

    Managing inventory load order

    Ansible은 파일 이름으로 정렬해서 인벤토리 소스를 로드합니다. 만약 parent group의 정의와 child 그룹의 정의가 다른 파일이나 디렉토리에 있다면, child 그룹을 정의한 파일은 가장 먼저 로드되어야만 합니다. 만약 parent 그룹이 먼저 로드된다면 `Unable to parse /path/to/source_of_parent_groups as an inventory source` 에러가 발생합니다.

     

    이러한 상황에선 아래 예제처럼 파일에 prefix를 붙여서 로드 순서를 컨트롤 할 수 있습니다.

    inventory/
      01-openstack.yml          # configure inventory plugin to get hosts from OpenStack cloud
      02-dynamic-inventory.py   # add additional hosts with dynamic inventory script
      03-on-prem                # add static hosts and groups
      04-groups-of-groups       # add parent groups

     

    Adding variables to inventory

    variables를 메인 인벤토리 파일에 간단하게 저장할 수 있습니다. 하지만, 변수를 별도의 호스트와 그룹 변수 파일에 저장하는 것을 권장합니다. 기본 인벤토리 파일에서 변수를 설정하는 것은 임시방편일 뿐입니다.

    Ansible에서는 `host_vars` 디렉토리에 개별 파일로 변수를 저장하는 것으로 가이드합니다. Organizing host and group variables

     

     

    Defining variables in INI format

    `key=value` 구문으로 INI 형식으로 전달된 값은 선언된 위치에 따라 다르게 해석됩니다. 

    • host와 inline에서 선언된 경우, INI 값은 파이썬 literal structures(string, numbers, tuples, list,..)로 해석됩니다.
      여러 `key=value` 파라미터를 여러 줄로 받을 수 있습니다.
      따라서 공백이 구분 기호가 아닌 값의 일부임을 나타내기 위해 값에 공백이 포함된 경우 single or double quoted를 사용합니다.
      ex) 'a b', "a b"
    • `:vars` 섹션으로 선언하는 경우, INI 값은 string으로 해석됩니다.
      예를 들어, `var=FALSE`는 'FALSE' string으로 생성됩니다.
      호스트 라인과 달리, `:vars` 섹션은 한 줄당 하나의 항목만 허용합니다. 따라서 `=` 뒤에 있는 모든 값들은 value로 인식됩니다.

     

    Assigning a variable to many machines: group variables

    In INI:

    [atlanta]
    host1
    host2
    
    [atlanta:vars]
    ntp_server=ntp.atlanta.example.com
    proxy=proxy.atlanta.example.com

    Group variables는 여러 호스트에 한 번에 변수를 적용할 수 있는 편리한 방법입니다. 하지만, 실행 전에 Ansible은 항상 인벤토리 변수를 포함한 변수들을 호스트레벨로 펼칩니다.(flatten)

    만약 호스트가 여러 그룹의 멤버라면, Ansible은 해당 그룹에서 모두 변수를 읽습니다. 만약 다른 그룹에서 동일한 변수에 다른 값을 할당하는 경우, Ansible은 내부 rules for merging에 따라 사용할 값을 선택합니다.

     

    Inheriting variable values: group variables for groups of groups

    parent group 뿐 아니라 child group에도 변수를 지정할 수 있습니다. INI 포맷에서는 `:vars` 구문을 사용합니다.

    * child 그룹의 변수는 parent 그룹의 변수보다 우선순위가 높습니다.

     

    In INI:

    [atlanta]
    host1
    host2
    
    [raleigh]
    host2
    host3
    
    [southeast:children]
    atlanta
    raleigh
    
    [southeast:vars]
    some_server=foo.southeast.example.com
    halon_system_timeout=30
    self_destruct_countdown=60
    escape_pods=2
    
    [usa:children]
    southeast
    northeast
    southwest
    northwest

     

    Organizing host and group variables

    메인 인벤토리 파일에 변수를 저장해도 되지만, 호스트와 그룹의 변수파일을 별도로 저장하면 값을 더 쉽게 관리할 수 있습니다. 또한, 호스트나 그룹 변수 파일에서는 list와 hash data를 사용할 수 있지만 메인 인벤토리 파일에서는 사용할 수 없습니다.

     

    호스트와 그룹 변수 파일은 무조건 YAML 구문으로 작성해야 합니다. '.yml', '.yaml', '.json' 그리고 no file extension까지 허용됩니다.

     

    Ansible은 인벤토리 파일 또는 플레이북 파일을 기준으로 경로를 검색하여 호스트 및 그룹 변수 파일을 로드합니다. 예를 들어, etc/ansible/hosts라는 인벤토리 파일에 'raleigh', 'webservers' 두 그룹에 속하는 'foosball'이라는 호스트가 포함된 경우, 해당 호스트는 다음 위치의 YAML파일에 있는 변수를 사용합니다.

    /etc/ansible/group_vars/raleigh # can optionally end in '.yml', '.yaml', or '.json'
    /etc/ansible/group_vars/webservers
    /etc/ansible/host_vars/foosball

     

    만약 인벤토리에 있는 호스트를 자체 NTP서버와 데이터베이스를 사용하는 데이터 센터별로 그룹핑 한다면, /etc/ansible/group_vars/raleigh 라는 raleigh 그룹의 변수들을 저장하는 파일을 생성할 수 있습니다.

    ---
    ntp_server: acme.example.org
    database_server: storage.example.org

     

    디렉토리로도 생성이 가능합니다. Ansible은 디렉토리에 있는 모든 파일을 사전순으로 읽습니다.

    /etc/ansible/group_vars/raleigh/db_settings
    /etc/ansible/group_vars/raleigh/cluster_settings

     

    이러한 방법들은 단일 파일의 크기가 매우 커졌을 때나, Ansible Vault를 일부 그룹 변수에 사용하려는 경우에 좋습니다.

    ansible-playbook은 `group_vars/`와 `host_vars/` 디렉토리를 플레이북 디렉토리에 추가할 수 있습니다. 하지만 다른 ansible이나 ansible-console 같은 경우는 인벤토리 디렉토리에만 추가가 가능합니다. (우리플젝은 ansible-playbook을 쓰지만 인벤토리 디렉토리에 group_vars/ 만들어서 쓰고있음)

     

    만약 다른 커맨드로 playbook 디렉토리로부터 그룹이나 호스트 변수를 로드하려면 `--playbook-dir` 옵션을 사용해야 합니다. 만약 playbook 디렉토리와 inventory 디렉토리 둘 다에서 inventory 파일을 업로드 한다면, playbook 디렉토리의 변수가 inventory 디렉토리에 설정된 변수를 재정의(Override)합니다. 즉, playbook 디렉토리에 있는 변수로 사용됩니다.

     

    inventory 파일과 변수를 git repo에서 관리하면 inventory 및 호스트 변수의 변경 사항을 추적하는 데 유용합니다. (당연히 사용중)

     

    How variables are merged

    기본적으로 변수를 플레이가 실행되기 전에 특정 호스트에 merge/flatten 됩니다. 기본적으로 Ansible은 우선순위에 따라 정의된 변수를 덮어쓰기도 합니다. 아래 리스트에서 우선순위는 아래로 갈 수록 높아집니다.

     

    all group (because it is the ‘parent’ of all other groups)
    parent group
    child group
    host

    기본적으로 Ansible은 동일한 parent/child 레벨의 그룹을 ASCII 순서로 병합하며, 마지막으로 로드된 그룹의 변수가 이전 그룹의 변수를 덮어씁니다. 예를 들어, a_group과 b_group이 병합될 때 일치하는 변수가 있다면 b_group의 값으로 덮어쓰게 됩니다.

     

    `ansible_group_priority`를 설정해서 동일 레벨에서의 병합 우선순위를 결정할 수 있습니다. (parent/child 정렬이 끝난 이후에).

    기본값은 1이기 때문에, 10으로 설정하지 않았으면 testvar=b 였겠지만, 아래 예제에선 testvar=a 입니다.

    a_group:
      vars:
        testvar: a
        ansible_group_priority: 10
    b_group:
      vars:
        testvar: b

    ! `ansible_group_priority`는 group_vars에서 사용되므로 인벤토리 소스에서만 설정할 수 있고, group_vars에서는 설정할 수 없음

     

     

    Managing inventory variable load order

    커멘드라인에서 여러 인벤토리 소스를 입력할 때, Ansible은 입력받은 파라미터 순서대로 변수를 병합합니다.

    예를 들어, staging inventory의 `[all:vars]`에 myvar=1 이고, production inventory에는 `myvar=2` 라 정의되어 있을 때

    • Pass `-i staging -i production` to run the playbook with myvar = 2.
    • Pass `-i production -i staging` to run the playbook with myvar = 1.

     

    한 디렉토리에 여러 inventory 소스가 있을 때, Ansible은 파일명을 ASCII로 정렬해서 사용합니다. 따라서 prefix를 사용해서 순서를 지정할 수 있습니다. <위에서도 한번 언급됐던 내용>

    inventory/
      01-openstack.yml          # configure inventory plugin to get hosts from Openstack cloud
      02-dynamic-inventory.py   # add additional hosts with dynamic inventory script
      03-static-inventory       # add static hosts
      group_vars/
        all.yml                 # assign variables to all hosts

    If `01-openstack.yml` defines `myvar = 1` for the group `all`, `02-dynamic-inventory.py` defines `myvar = 2`, and `03-static-inventory` defines `myvar = 3`, the playbook will be run with myvar = 3.

     

     

    References

    https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html

    반응형

    댓글