ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 오픈소스로 구성하는 데브옵스 시스템 - Ansible의 Dynamic Inventory
    DevOps 2018. 6. 5. 20:26

    제 블로그를 보시고 Ansible & AWX를 구축하시는 분들이 계신데요...

    사용하시면서 Host를 등록하는 번거로움이 많으신 듯 합니다.


    저희는 150대 정도 밖에(?) 안되서 일일이 한땀한땀 등록하기는 했는데....

    생각해보니 수백, 수천대를 관리하는 회사에서는 Inventory 마다 서버를 등록하는 것도 여간 노다가성의 업무가 아닌가 싶습니다.


    그래서 해당 문의를 받고 방법을 찾아보니 Ansible에서 제공하는 Dynamic Inventory 라는 기능으로 Inventory와 Host의 관리가 가능하다는 것을 찾았습니다.


    관련 문서는 Ansible Documentaion의 Working With Dynamic Inventory 라는 chapter를 봐주세요. ^^

    문서를 보면 Cloud VM 리스트, LDAP, CMDB 등에서 Inventory를 가져오는 방법이 있는 듯 합니다.


    하지만 저나 이글을 보고 계시는 분들은 어디까지나 모든 관리를 AWX에서 하고 싶어 하실꺼라 생각이 듭니다.

    그래서 관련 방법을 찾아 보았습니다.


    바로 Inventory Script를 이용해서 관련 호스트를 찾고, Dynamic Inventory를 통해 해당 Host를 자동으로 등록하는 방법 입니다.


    우선 왼쪽 메뉴의 Inventory Scripts에 관련 Script를 등록 합니다.


    관련 Script는 아래와 같습니다.

    #!/usr/bin/env python


    from __future__ import (print_function, absolute_import, division, unicode_literals)


    import socket

    import subprocess

    import ipaddress


    # json is not alway default installed, if json is not installed simplejson is installed

    # for this reason python will check is json is installed or it will fallback to simplejson

    try:

        import json

    except ImportError:

        import simplejson as json


    def inventory():

        """ function: create a dynamicly generated inventory for ansible """

        ipaddres = find_nodes()

        return {

                'all': {

                    'hosts': ipaddres,

                    }

            }


    def find_nodes():

        """ function: return ipaddress in you local network where port 22 is open """

        ipaddres = list()

        for ip in all_local_ipaddrs():

            if port_22_is_open(str(ip)):

                ipaddres.append(str(ip))


        return ipaddres

    def all_local_ipaddrs():

        """ function: find all active ipaddress in your local network """

        my_net = ipaddress.ip_network(u'192.168.10.0/24')

        for ipaddr in my_net.hosts():

            yield ipaddr


    def port_22_is_open(ipaddr):

        """ function: check if port 22 is open """

        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        sock.settimeout(1)

        result = sock.connect_ex((ipaddr, 22))

        sock.close()

        

        return result == 0


    def main():

        """ function: main function for returning the dynamic inventory """

        print('{}' .format(json.dumps(inventory(), sort_keys=True, indent=2)))


    if __name__ == "__main__":

        main()


    스크립트에 대해 설명을 드리면...특정 IP 대역에서 특정포트(22번)를 사용하는 Host를 찾아서 JSON 형식으로 return 해주는 python 스크립트 입니다. IP나 Port 정보들을 각자의 환경에 맞게 편집을 해주셔야 합니다.


    참고로 원본 스크립트에서는 Host를 등록할 때 각 호스트를 그룹핑 한다던지, 사용자 변수나 매직 변수를 등록하는 설정이 들어 있었습니다. (저는 필요치 않아 뺐지만....ㅎㅎ)

    def inventory():

        """ function: create a dynamicly generated inventory for ansible """

        ipaddrs = find_nodes()

        

        return {

                'all': {

                    'hosts': [ipaddrs],

                    'vars': {},

                    },

                '_meta': {

                    'hostvars': {

                        ipaddrs: {

                            'ansible_ssh_user': 'ansible',

                            }

                        },

                    },

                'nodes': [ipaddrs]

            }


    위 스크립트를 등록해 주시고, Inventories 메뉴에서 Dynamic Inventory로 만들 새로운 Inventory를 생성 합니다.


    SAVE 버튼을 누르면 아래 메뉴들이 활성화가 됩니다. 그중에 Sources 버튼을 클릭하고 Add Source를 클릭 합니다.

    Create Source 항목에서 Source 부분을 Custom Script로 변경 합니다. 그리고 앞서 등록한 Inventory Scripts의 Custom Script를 불러 옵니다.


    여기까지 하시면 해당 Dynamic Inventory 등록이 모두 완료 되었습니다.

    등록된 항목에서 sync process를 시작하시면 script가 진행되면서 22번 포트로 서비스 하는 서버들을 일괄 등록하게 해줍니다.


    참고로 제가 C클래스 대역을 Scan하면서 64대의 서버를 등록하는데 대략 3시간이 소요가 되었습니다.


    시간이 많이 소요되는 분들께서는 아래와 같이 Schedule로 등록을 하셔서 자동으로 갱신되게 해놓으셔도 좋을 듯 합니다.


    마지막으로 위에서 이야기 했던 것과 같이 다른 솔루션과의 연동을 통해 Dynamic Inventory 구성을 원하시는 분들은 관련 github의 예제 스크립트를 참고해 주세요~

Designed by Tistory.