이쿠의 슬기로운 개발생활

함께 성장하기 위한 보안 개발자 EverNote 내용 공유

클라우드/Ansible

Ansible dynamic inventory란?

이쿠우우 2022. 5. 5. 16:49
반응형
 
 

Ansible dynamic inventory란?

 
 

문제 상황

 
ansible 사용 시 inventory를 작성할 때
host가 수가 매우 많거나
autoscaling 이나 외부 application들에 의해 관리되어서
host 수가 유동적인 경우
inventory를 작성하기 어려움.
이를 해결하기 위한 방법을 찾아보던 중 Dynamic inventory를 찾아서
사용법을 알아보기로 함.
 
 

Ansible Dynamic inventory란?

 
Ansible은 Inventory를 통해 정보를 아주 편하게 playbook으로 넘길 수 있음
하지만 이 inventory의 단점은 정보가 정적이라는 것임.
즉 inventory에 있는 정보는 사용자가 직접 수정하지 않은 이상 변하지 않음.
이 단점이 host가 적은 경우에는 치명적이지 않지만
AWS, GCP, Azure, vSphere와 같은 환경에서는 host가 굉장히 많이 생성되고 삭제되는
유동적인 환경이기 때문에 이런 inventory의 정적인 부분이 큰 단점이 됨.
이때 필요한 것이 바로 Dynamic inventory임.
상황을 예로 들자면 
ansible 사용 시 aws에 있는 모든 ec2 instance, kubernetes 모든 node, virtualbox의 모든 vm들을
inventory host 목록으로 사용하고 싶은 경우가 있음.
이런 경우 dynamic inventory 기능을 사용할 수 있음.
dynamic inventory는 ansible의 plugin으로 다양한 sub application tool의 기능과 연동해서 
필요한 host 목록을 가져올 수 있음.
이 기능을 사용하면 host 목록에 ip를 고정적으로 입력하지 않아도 되고 host의 autoscaling도 대처할 수 있음.
 
 

inventory plugin 항목 확인

 
ansible에서는 inventory plugin을 지원하고 있음
항목은 아래와 같음.
(아래 명령은 python2 ansible의 결과임. python3의 경우 더 많은 항목이 나옴.)
 
 
[명령어]
ansible-doc -t inventory -l
 
(ansible python2 의 경우 아래와 같음)

 
(ansible python3.8 의 경우 아래와 같음)

 
 

inventory plugin 항목 설정

 
vi /etc/ansible/ansible.cfg
파일에서 아래 부분을 확인함
[inventory]
# enable inventory plugins, default: 'host_list', 'script', 'auto', 'yaml', 'ini', 'toml'
#enable_plugins = host_list, virtualbox, yaml, constructed
 
default 설정으로는 enalbe_plugins 항목이 주석처리 되어있는데
위에서 확인했던 inventory plugin 항목 중에 사용하고자 하는 것을
해당 enalbe_plugins 설정에 추가해야함.
 
 

 

 

 
 

Ansible dynamic inventory k8s 

 
dynamic inventory k8s plugin을 사용해봄
 

환경

 
[kubernetes cluster]

 
[ansible]

 
[python]
3.8.12
 
 
 

관련 tool 설치

Kubernetes 동적 인벤토리 플러그인을 사용하려면 Ansible을 실행하는 호스트에 
Kubernetes Python Client, 
kubectl,
OpenShift Python Client를 설치해야함.
 
[OpenShift Python Client를 설치 명령어]
pip install kubernetes openshift
 
 

k8s plugin 활성화

 
vi /etc/ansible/ansible.cfg
파일에서 enable_plugins 설정에  kubernetes.core.k8s 추가
ini도 제외되어 있어서 ini도 추가함
enable_plugins = kubernetes.core.k8s

 
 
[참고 python2의 ansible은 아래와 같이 설정해야함.]
enable_plugins = k8s

 
[참고]
ansible.cfg 파일 인식 우선 순위는 아래와 같음
ANSIBLE_CONFIG (environment variable if set)
ansible.cfg (in the current directory)
~/.ansible.cfg (in the home directory)
/etc/ansible/ansible.cfg
 
 

k8s plugin 활성화

 
test.k8s.yaml 파일 생성 (inventory 파일임)

plugin: kubernetes.core.k8s
 
[참고 python2의 ansible은 아래와 같이 설정해야함.]
plugin: k8s
 
[결과 확인]
ansible-inventory -i test.k8s.yaml  --list
ansible all -i test.k8s.yaml  --list

 
 
[특정 host의 옵션을 확인]
ansible-inventory -i test.k8s.yaml  --host kube-dns

 
 
위 명령을 사용하면 ansible에 내장되어있는 k8s plugin을 통해
kubernetes 정보를 가져옴.
 
 

 
 

Ansible dynamic inventory 직접 구현

 
Python을 사용해서 dynamic inventory plugin을 직접 구현 해보겠음.
 
inventory는 host에 대한 정보를 return해줘야함.
host별 return 되는 data 의 structure가 있음.
python, golang 등으로 구현해서 inventory에 해당하는 data structure 형식을 리턴하면
inventory 파일을 대체할 수 있음.
 

Inventory 파일 Data structure 확인

 
[ 예제 inventory 파일  : host.ini ]
[linux1]
10.0.2.11
 
[linux2]
10.0.2.10
 
[linux1:vars]
ansible_ssh_user=centos
ansible_become=yes
ansible_become_method=sudo
ansible_become_pass='qwer1234'
 
[linux2:vars]
ansible_ssh_user=root
 
[all:vars]
ansible_ssh_private_key_file=~/.ssh/id_rsa
 
data structure 확인
 
[명령어]
ansible-inventory -i host.ini  --list

 
[결과]
"_meta" {"hostvars": {} }
항목에 host 정보가 있고
host에 적용된 ansible 변수들이 저장되어있음.
 
all 항목은 
host.ini 파일의 [all] 부분이고
aws, linux 항목또한 각각 [linux], [aws] 항목과 매칭됨.
 
inventory의 data structure는 이와 같이 
"_meta" 항목에 검사 대상의 정보가 오면 됨.
 
 
 

 

ansible.cfg에 python 인식 가능 옵션 추가

 

ansible.cfg default 경로 : /etc/ansible/ansible.cfg
해당 파일에서 enable_plugins가 활성화 되어있다면 script 옵션을 추가해줘야함
enable_plugins가 주석처리되어있다면 
default로 script 옵션이 추가되어있음으로 별도로 enable_plugins를 추가할 필요없음.

 

파이썬으로 Dynamic Inventory 구현해보기

 
위에서 확인했던 예제 inventory 파일과 동일한 결과를  return 하는 python코드를 작성해봄.
 
파이썬 이외에 golang, php등 다양한 언어 사용가능
return 만 inventory data structure에 맞춰주면 됨.
 
[코드 필수 사항1]
dynamic inventory로 사용하는 python 코드의 경우
상단에 python을 명시하는 Shebang이 추가되어야함.
#!/usr/bin/env python
문구가 추가되어야함.
Shebang 이란 코드는 스크립트를 실행시켜줄 프로그램의 경로를 지정하는 역할을 담당함.
'Sharp(#)' + 'Bang(!)'의 합성어임
 
[코드 필수 사항2]
args는 --list가 필수로 들어가줘야함
--list 결과로 inventory data structure를 리턴해야함.
 
 
[예제 python 코드]
#!/usr/bin/env python3.8

import os
import sys
import argparse

try:
    import json
except ImportError:
    import simplejson as json


class ExampleInventory(object):

    def __init__(self):
        self.inventory = {}
        self.read_cli_args()

        # Called with `--list`.
        if self.args.list:
            self.inventory = self.example_inventory()
        # If no groups or vars are present, return an empty inventory.
        else:
            self.inventory = self.empty_inventory()


        print(json.dumps(self.inventory));


    # Example inventory for testing.
    def example_inventory(self):
        return {
            '_meta': {
                'hostvars': {
                    '10.0.2.10': {},
                    '10.0.2.11': {}
                }
            },
            'all': {
                'vars': {
                    'ansible_ssh_private_key_file': '~/.ssh/id_rsa'
                }
            },
            'linux1': {
                'hosts': [
                    '10.0.2.11'
                ],
                'vars': {
                    'ansible_ssh_user': 'centos',
                    'ansible_become': 'yes',
                    'ansible_become_method': 'sudo',
                    'ansible_become_pass': 'qwer1234'
                }
            },
            'linux2': {
                'hosts': [
                    '10.0.2.10'
                ],
                'vars': {
                    'ansible_ssh_user': 'root'
                }
            }
        }

    # Empty inventory for testing.
    def empty_inventory(self):
        return {'_meta': {'hostvars': {}}}


    # Read the command line args passed to the script.
    def read_cli_args(self):
        parser = argparse.ArgumentParser()
        parser.add_argument('--list', action = 'store_true')
        self.args = parser.parse_args()


# Get the inventory.
ExampleInventory()

 

 
 
각종 library(aws boto와 같은..)를 사용해서 host 정보를 가져와서
해당코드와 같이 inventory data structure 형태로 host 정보를 넘기면 됨.
 
 
 

결과 확인

정상적으로 host정보를 확인할 수 있음

 
 
[host 조회 명령 확인]
ansible-inventory -i dynamic.py  --host 10.0.2.11

 
 
[playbook이 정상동작하는지 확인 : 결과 정상]

 
 

 
 
참고

 

반응형