클라우드 자동화 및 Ansible 시리즈: 동적 인벤토리

사소스탄노프닉이라면
만약 클라우드에 상당한 수의 서버가 있다면, 자동화로 그것을 만들고 관리해야 한다.비록 아주 적은 서버만 있어도 인프라 시설을 코드로 지정하면 절실하게 필요한 이중 목적을 실현할 수 있다. 즉, 설정에 필요한 내용을 정확하게 기록하고 창고를 신속하고 믿음직스럽게 배치하고 재배치할 수 있다.
Ansible은 아주 좋은 도구입니다!인프라를 동시에 설정한 다음 하나의 도구를 사용하여 응용 프로그램을 인프라에 배치할 수 있습니다.a previous post에서는 Ansible을 사용하여 AWS에 인프라를 구성하는 방법을 보여줍니다.이 기사는 Ansible 클라우드 자동화 시리즈의 첫 번째 기사입니다. 우리는 자원 조달과 배치 간의 관계를 탐구할 것입니다.이것이 바로 Ansible의 동적 재고입니다.

동적 재고란?
응용 프로그램을 배치하는 데는 보통 두 가지 절차가 있다. 응용 프로그램에 필요한 모든 자원을 제공한 다음에 그 위에 응용 프로그램을 배치하고 설정하는 것이다.이 두 단계를 결합한 것은 자원의 매거진으로 Ansible에서 재고라고 부른다.
Ansible의 리소스 인벤토리는 동적이며 이는 Ansible 자체가 런타임 시 어떤 리소스가 존재하는지 확인할 수 있음을 의미합니다.이것은 정적 리스트(때로는 국부적 상태라고도 부른다)와 대비된다. 국부적 상태는 인프라 시설과 관련된 모든 사물의 유일한 진실의 원천이다. 그렇지 않으면 진실이 아니다.
이것은 우리 거미를 찌르는 통증을 느끼게 할 것이다.만약 우리가 통제할 수 없는 변화가 발생하면 어떻게 합니까?그래, 우리는 이러한 변화를 허용해서는 안 된다고 말할 수 있다. 왜냐하면 인프라 시설 자원을 창설하는 명확한 과정이 있어야 하기 때문이다.그러나 현실 세계에서 이런 우호적이고 의외의 일이 계속 발생하는 경우는 드물다.
동적 재고가 정적 재고만큼 실용적인지 봅시다.물론 정적 분석에 대한 경고는 사용할 수 없다.
이 블로그에서는 Digital Ocean의 기계 그룹을 어떻게 해석하고, 배치할 기계 서브집합을 동적 자원 정리 설정을 어떻게 사용하는지 이해할 것이다.우리는 무에서 유로 모든 일을 완성할 것이니, 언제든지 우리를 따라 다른 매개 변수를 가지고 놀아라.

뭘 시작해야 돼요?
먼저 ansible-core을 새로운 가상 환경에 설치하여 깔끔한 환경을 유지할 것입니다.그런 다음 community.digitalocean 컬렉션을 설치하여 컨텐츠에 액세스할 수 있습니다.마지막으로 우리는 DO_API_TOKEN 환경 변수를 내보내서 플레이북스는 hardcoding secrets into our playbooks이 아니라 API에 따라 신분 검증을 할 수 있다.
# this makes things easy to clean up
mkdir steampunk-trials && cd steampunk-trials/
python3 -m venv .venv && source .venv/bin/activate

pip install -U pip wheel
pip install ansible-core==2.11.0
ansible-galaxy collection install community.digitalocean

export DO_API_TOKEN=<YOUR API TOKEN>
이것만 있으면 우리는 시작할 수 있다!

약간의 기계를 창조하다
재고에 대해 의미 있는 일을 하기 위해 두 개의 액체를 만들어 봅시다.물론 시나리오를 통해 이를 실현할 것이다.이것은 간단한 방식의 하나다.
- hosts: localhost
  vars:
    your_pubkey: YOUR_PUBKEY
  tasks:
    - community.digitalocean.digital_ocean_sshkey:
        name: stempunk-pubkey
        state: present
        ssh_pub_key: "{{ your_pubkey }}"
      register: pubkey

    - community.digitalocean.digital_ocean_droplet:
        name: "steampunk-{{ item.type }}-{{ item.index }}"
        tags: "{{ item.tags }}"
        unique_name: true
        ssh_keys:
          - "{{ pubkey.data.ssh_key.fingerprint }}"
        size: s-1vcpu-1gb
        region: fra1
        image: centos-8-x64
        state: present
      loop:
        - type: appserver
          index: 1
          tags:
            - steampunk-test
            - app
        - type: dbserver
          index: 1
          tags:
            - steampunk-test
            - db
같은 가상 머신을 만드는 두 가지 작업이 있습니다.이것은 재고 개념의 증명이기 때문에 우리는 그것들에서 어떤 것도 운행할 수 없기 때문에 우리는 어떤 특수한 일을 할 필요가 없다. 우리는 기계만 방문할 수 있다.이 두 임무 사이의 유일한 차이는 라벨이다.우리는 첫 번째는 응용 서버이고, 두 번째는 데이터베이스 서버라고 가정한다.이렇게 하면 우리는 이후에 조를 나누는 기능을 보여줄 수 있다.이 두 항목은 나중에 더 쉽게 식별하고 삭제할 수 있도록 '프로젝트 이름' 으로 표시됩니다.일반적인 방법으로 실행하려면 다음과 같이 하십시오.
$ ansible-playbook playbook.yml

드디어 리스트를 하나 얻었어요.
Ansible에서 동적 목록을 사용하려면 공급자를 위한 목록 플러그인을 작성해야 합니다.다행히도 커뮤니티 디지털Ocean collection은 community.digitalocean.digitalocean 재고 플러그인을 가지고 있습니다!
Ansible이 무엇을 사용하고 그것을 어떻게 사용하는지 알려주기 위해 프로필을 사용해야 합니다.이것은 우리가 사용할 프로필입니다. 이름은 digitalocean.yml입니다.
plugin: community.digitalocean.digitalocean
내용이 간단하다.첫 번째 줄은 plugin을 지정하여 Ansible이 어떤 목록 플러그인을 불러오고 사용하는지 표시합니다.모든 후속 행(뒤에 추가) DigitalOcean-specific plugin options.모든 것을 기본 설정으로 유지할 것입니다.
우리는 DO_API_TOKEN 변수를 내보냈기 때문에, inventory 플러그인에서 이 변수를 가져오고 사용할 수 있습니다.

Inventory configuration files choose inventory plugins using a combination of the filename and the plugin variable. For the community.digitalocean.digitalocean inventory plugin, the configuration file name must end with (do_hosts|digitalocean|digital_ocean).(yaml|yml).


시나리오를 실행하지 않은 상태에서 목록을 얻기 위해서 우리는 ansible-inventory을 사용합니다.
$ ansible-inventory -i digitalocean.yml --graph --vars

@all:
  |--@ungrouped:
  |  |--steampunk-appserver-1
  |  |  |--{do_id = 243276125}
  |  |  |--{do_name = steampunk-appserver-1}
  |  |  |--{do_networks = {'v4': [{'ip_add [...] ': []}}
  |  |  |--{do_region = {'name': 'Frankfur [...] 6gb']}}
  |  |  |--{do_size_slug = s-1vcpu-1gb}
  |  |--steampunk-dbserver-1
  |  |  |--{do_id = 249985641}
  |  |  |--{do_name = steampunk-dbserver-1}
  |  |  |--{do_networks = {'v4': [{'ip_add [...] ': []}}
  |  |  |--{do_region = {'name': 'Frankfur [...] 6gb']}}
  |  |  |--{do_size_slug = s-1vcpu-1gb}
--graph--vars 로고는 간단한 목록이 아니라 호스트 옆에 호스트 변수를 표시하는 데 사용됩니다.우리가 사용하는 계정은 두 개의 액체만 포함하기 때문에, 우리는 출력에서 두 개의 호스트만 얻을 수 있다.
호스트에 추가된 탭과 이름을 볼 수 있습니다.여기서 주의해야 할 가장 중요한 것은 이 재고는 거의 사용할 수 없다는 것이다.왜?이것은 우리가 기계에 연결할 수 없기 때문이다!우리는 기계의 실제 생활 위치를 가리키는 ansible_host 변수가 부족하다.
언뜻 보기에는 좀 복잡하지만, 우리는 이것이 일을 명확하게 하기에 매우 적합하다고 생각한다.우리의 예는 매우 간단하다. 왜냐하면 우리는 두 개의 외부 IP 정의를 가진 기계가 있기 때문이다. 그러나 항상 그렇지는 않다. Ansible (또는 집합 개발자) 는 사용자가 이 기계에 어떻게 연결할지 결정하도록 한다.이 두 기계는 외부에서 접근할 수 있는 IP 주소가 없지만 클라우드 네트워크에 VPN을 설정했기 때문에 직접 사용할 수 있다고 상상해 보세요.목록 플러그인은 이 세부 사항을 알 수 없습니다.예를 들어 호스트를 뛰어넘거나 클라우드 컴퓨터에서 직접 실행하는 경우 어떻게 연결하는지 결정할 수 있습니다.

기계에 연결
그래서 우리가 해야 할 일은 inventory 플러그인이 우리가 만든 외부 IP 정의 ansible_host을 표시하는 것이다.연결할 사용자와 원하는 다른 내용을 지정할 수 있습니다.유연성을 위해 compose 부분은 상당히 지루하다.우리는 또한 attributes의 기본값을 어느 정도 제한하여 우리의 인쇄 출력을 더욱 읽을 수 있도록 한다.
plugin: community.digitalocean.digitalocean

attributes:
  - id
  - name
  - tags
  - networks

compose:
  ansible_host: do_networks.v4 | selectattr('type','eq','public') | map(attribute='ip_address') | first
  ansible_user: "'centos'"
  ansible_ssh_common_args: "'-o StrictHostKeyChecking=no'"
compose 키를 눌러 각 호스트에 변수를 추가합니다.키 이름은 변수 이름이고 값은 Jinja2 표현식입니다.여기서 우리는 여러 변수와 필터를 사용하여 순서대로
  • IPv4 주소 정의 선택,
  • type public
  • 만 포함하여 필터링
  • 은 전체 정의에서 실제 IPv4 주소를 추출한 후
  • 선택 그룹의 첫 번째 주소입니다.
  • 너는 이것이 얼마나 유연한지 볼 수 있고, 너는 그것을 네가 원하는 어떤 것에 적합하게 할 수 있다.다른 변수가 필요하면 compose 부분에서 같은 방식으로 설정할 수 있습니다.우리가 이렇게 하는 것은 호스트 키 검사를 비활성화하기 위해서이다.이것은 실제 작업 부하에 사용해서는 안 되지만, 우리는 단지 놀고 있기 때문에 충분히 할 수 있다.
    연결을 시도해 봅시다.
    $ ansible -m ping -i digitalocean.yml all
    
    steampunk-dbserver-1 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/libexec/platform-python"
        },
        "changed": false,
        "ping": "pong"
    }
    steampunk-appserver-1 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/libexec/platform-python"
        },
        "changed": false,
        "ping": "pong"
    }
    
    정말 쓸모가 있다!
    응용 프로그램과 데이터베이스 서버를 어떻게 배치했는지 기억하십니까?우리는 탭에 따라 이 서버들을 그룹으로 나눌 수 있다.
    plugin: community.digitalocean.digitalocean
    
    attributes:
      - id
      - name
      - tags
      - networks
    
    keyed_groups:
      - key: do_tags | lower
        prefix: ""
        separator: ""
    
    compose:
      ansible_host: do_networks.v4 | selectattr('type','eq','public') | map(attribute='ip_address') | first
      ansible_user: "'centos'"
      ansible_ssh_common_args: "'-o StrictHostKeyChecking=no'"
    
    현재, ansible-inventory을 실행하면 약간 다른 출력이 발생하는데, 그 중에서 호스트는 그룹으로 나뉜다.
    $ ansible-inventory -i digitalocean.yml --graph --vars
    
    @all:
      |--@app:
      |  |--steampunk-appserver-1
      |  |  |--{ansible_host = 207.154.233.128}
      |  |  |--{ansible_ssh_common_args = -o StrictHostKeyChecking=no}
      |  |  |--{do_id = 243296785}
      |  |  |--{do_name = steampunk-appserver-1}
      |  |  |--{do_networks = {'v4': [{'ip_add [...] ': []}}
      |  |  |--{do_tags = ['steampunk-test', 'app']}
      |--@db:
      |  |--steampunk-dbserver-1
      |  |  |--{ansible_host = 46.101.215.219}
      |  |  |--{ansible_ssh_common_args = -o StrictHostKeyChecking=no}
      |  |  |--{do_id = 243296841}
      |  |  |--{do_name = steampunk-dbserver-1}
      |  |  |--{do_networks = {'v4': [{'ip_add [...] ': []}}
      |  |  |--{do_tags = ['steampunk-test', 'db']}
      |--@steampunk_test:
      |  |--steampunk-appserver-1
      |  |  |--{ansible_host = 207.154.233.128}
      |  |  |--{ansible_ssh_common_args = -o StrictHostKeyChecking=no}
      |  |  |--{do_id = 243296785}
      |  |  |--{do_name = steampunk-appserver-1}
      |  |  |--{do_networks = {'v4': [{'ip_add [...] ': []}}
      |  |  |--{do_tags = ['steampunk-test', 'app']}
      |  |--steampunk-dbserver-1
      |  |  |--{ansible_host = 46.101.215.219}
      |  |  |--{ansible_ssh_common_args = -o StrictHostKeyChecking=no}
      |  |  |--{do_id = 243296841}
      |  |  |--{do_name = steampunk-dbserver-1}
      |  |  |--{do_networks = {'v4': [{'ip_add [...] ': []}}
      |  |  |--{do_tags = ['steampunk-test', 'db']}
      |--@ungrouped:
    
    경탄할 만한!이제 호스트 레이블로 완전히 정의된 호스트 서브셋에서 Ansible 명령이나 Playbook을 실행할 수 있습니다.Ping 응용 서버만 사용하도록 하겠습니다.우리는 간단한 ping을 사용합니다. 왜냐하면 이곳의 중점은 응용 프로그램을 배치하는 것이 아니라 재고이기 때문입니다.
    $ ansible -m ping -i digitalocean.yml app
    
    steampunk-appserver-1 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/libexec/platform-python"
        },
        "changed": false,
        "ping": "pong"
    }
    
    이제 응용 서버를 포함하는 최초의 시나리오를 수정합시다.
    ...
          loop:
            - type: appserver
              index: 1
              tags:
                - steampunk-test
                - app
            - type: appserver
              index: 2
              tags:
                - steampunk-test
                - app
            - type: dbserver
              index: 1
              tags:
                - steampunk-test
                - db
    ...
    
    
    이제 새로운droplet을 만들고 모든 응용 서버에서 같은ping 명령을 실행합니다.
    $ ansible-playbook playbook.yml
    $ ansible -m ping -i digitalocean.yml app
    
    steampunk-appserver-1 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/libexec/platform-python"
        },
        "changed": false,
        "ping": "pong"
    }
    steampunk-appserver-2 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/libexec/platform-python"
        },
        "changed": false,
        "ping": "pong"
    }
    
    이 명령은 두 서버에 대해 실행되며 어떠한 재고 수정도 필요 없습니다!

    깨끗이 정리하다
    Ansible로 우리 자신을 정리하는 것은 매우 간단하다.시나리오에 나오는 모든 state: presentstate: absent으로 변경하고 다시 실행합니다!우리의 예에서, 우리는 ssh_keys의 정의를 삭제해야 한다. 왜냐하면 이것은 이전 작업에서 유래한 변수를 포함하기 때문에, 삭제할 때 사용할 수 없기 때문이다.이렇게!

    Ansible의 동적 인벤토리는 무상태입니다.
    Ansible의 동적 인벤토리는 상태별로 실행됩니다.이런 상태는 아득히 멀고 실제로는 존재한다.로컬 캐시를 제외하고는 이것이 시종 기본적인 사실이다.인스턴스를 생성, 수정 또는 삭제하는 방법에 관계없이 Ansible 목록 스크립트는 동기화를 잃지 않습니다.
    우리는 동적 재고를 사용하는 매우 간단한 예를 보여 주었다.더 많은 기계가 있을 때, 복잡한 장면을 만들 수 있기 때문에 새로운 가능성이 나타날 것이다.프레임워크와 무관한 표시를 사용하여 인프라 시설 설정과 응용 프로그램 배치를 연결할 수 있으며, 이 두 가지 도구를 혼합하고 일치시킬 수도 있습니다.
    Ansible은 인프라 관리뿐만 아니라!더 많은 것에 관심이 있다면, why cloud automation is its forte에 관한 이 게시물을 보십시오.
    이것은 Ansible의 클라우드 자동화에 관한 여러 부분의 시리즈의 첫 부분이다.재고 캐시에 대한 writeup을 계속 주목해 주십시오. 이것은 많은 노드의 복잡한 작업 흐름에 매우 유용합니다

    좋은 웹페이지 즐겨찾기