본문 바로가기

AWS

[Ansible] AWS EC2 Dynamic Inventory 사용하기

반응형

개요

다수의 VM에 동일한 명령어를 수행하기 위해서 Configuration Management 툴인 Ansible을 많이 사용하게 된다. Ansible에서 접속 정보와 관련된 정보들은 보통 Inventory라고 하는 파일에 저장하게 된다. 접속 호스트, 접속 계정 정보, 그룹 설정, 그룹 간 별도의 변수 설정 등이 가능하다.

하지만 수십 ~ 수백대의 VM Host의 IP Address 및 Password, Key 파일 등을 설정하는 것도 많은 시간이 소요되기 마련이다.

 

그런데 잘 생각해보면 클라우드와 같은 서버 관련 정보를 API 형식으로 제공할 경우 일일이 호스트 정보를 파일로 수작업 저장할 필요가 없다.

 

⇒ 프로그래밍 관점으로 접근하여 서버 관련 정보를 동적으로 얻어올 수 있다

 

⇒ Ansible에서는 Dynamic Inventory를 사용하여 EC2의 정보를 동적으로 받아올 수 있다.

 

⇒ Python Library인 Boto3를 활용하여 EC2의 정보를 받아올 수 있으며, key-name, SG Name, Tag 값 등을 필터링하여 본인이 원하는 EC2에만 SSH를 통해 Ansible을 사용할 수도 있다.

 

환경 셋팅

환경은 아래와 같다고 가정하겠다.

 

Bastion 서버가 Public Subnet에 있고, Private Subnet 내에 web, was, - 3대의 EC2가 존재한다.

모든 서버가 Amazon-Linux2 이므로 default user는 ec2-user이며 sudo 권한이 존재하고 key 파일을 통하여 SSH 접근을 할 수 있을 것이다.

 

간단한 Ansible의 동작 원리는 다음과 같다.

  1. Bastion에서 접근 시도할 VM들에 대한 정보가 있어야 한다. ( 인증 정보, 인증 정보를 사용할 수 있는 유저의 이름)
  2. 위의 정보를 이용하여 SSH 접속을 Ansible이 시도한다.
  3. 인증 완료 후 각종 Ansible Module들을 사용하여 명령어를 실행한다.

 

설치 및 사용법

 

1. Ansible 설치

amazon-linux-extras enable ansible2

 

yum clean all

 

yum install ansible -y

 

2. boto3 설치 및 amazon.aws 설치

EC2 호스트들의 정보를 가져오기 위해서는 Python Boto3 라이브러리가 설치되어 있어야 한다.

⇒ 해당 라이브러리를 통해 EC2 API에 접근하여 정보를 가져오게 된다.

# 파일 생성 후 기입
vim boto3_install.yml

---
- hosts: localhost
  become: yes

  tasks:
    - name: install pip
      yum:
        name:
          - python-pip
          - python3-pip
        state: latest

    - name: install boto
      pip:
        name:
          - boto
          - boto3


# 앤서블 플레이북 실행
ansible-playbook install.yml

 

아래 ansible galaxy 페이지 참고

https://galaxy.ansible.com/amazon/aws?extIdCarryOver=true&sc_cid=701f2000001OH7YAAW

 

Ansible Galaxy

 

galaxy.ansible.com

(참고로 해당 명령어를 사용하게 되면 ~/.ansible 디렉터리에 생성되게 된다. 이 말은 즉 /etc/ansible 디렉터리에 생성이 안되기 때문에 해당 유저만 사용할 수 있다는 뜻임)

⇒ root 유저인 상태에서 설치했을 경우 ec2-user를 사용할 수 없다는 뜻임.. 왜냐만 /root/.ansible 디렉터리에 설치되어 있기 때문

 

ansible-galaxy collection install amazon.aws

 

3. ansible.cfg 및 aws_ec2.yml 설정

- ansible.cfg

 

아래의 공식 문서를 보면서 작성하였다.

https://docs.ansible.com/ansible/latest/reference_appendices/config.html#envvar-ANSIBLE_PYTHON_INTERPRETER

 

Ansible Configuration Settings — Ansible Documentation

[‘bud-frogs’, ‘bunny’, ‘cheese’, ‘daemon’, ‘default’, ‘dragon’, ‘elephant-in-snake’, ‘elephant’, ‘eyes’, ‘hellokitty’, ‘kitty’, ‘luke-koala’, ‘meow’, ‘milk’, ‘moofasa’, ‘moose’, ‘ren’, ‘

docs.ansible.com

 

[defaults] 섹션에 여러가지 설정값을 기입해주었다.

inventory 파일은 어디에 있는 것을 사용할 건지, key 인증 방식을 사용할 때 yes를 물어보도록 할 것인지 (False로 주었음), 원격 유저는 누구로 할 것인지 (ec2-user), private_key_file은 어떤것을 사용할 것인지 등을 설정할 수 있다.

 

[inventory] 섹션에는 사용 가능한 plugin으로 aws_ec2를 지정해주었다.

 

그 외, 권한 관련 설정 또한 기입해주었다.

 

[defaults]
inventory = ./aws_ec2.yml
host_key_checking = False
pipelining = True
roles_path = ./roles
# forks = 1000
remote_user = ec2-user
private_key_file = /home/ec2-user/pingping95-key.pem

[inventory]
enable_plugins = aws_ec2

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false

 

- aws_ec2.yml

참고 사이트

https://docs.ansible.com/ansible/latest/collections/amazon/aws/aws_ec2_inventory.html#examples

여러가지 설정 값을 기입해줄 수 있다.

필수 값은 2개이다.

1) plguin

2) boto_profile 혹은 access_key, secrey_key 혹은 iam_role_arn

⇒ ~/.aws/configure에 access key, secret key가 기입되어 있거나 해당 ec2에 IAM Role이 설정되어 있어야 하며, 그 해당 자격 증명이 EC2에 대한 describe:* 권한이 있어야 한다.

 

필자는 IAM User에서의 Access Key, Access Key를 AWS Configure 명령어를 통해 기입한 후, Profile name으로 자격 증명을 설정하였다.

ex) aws configure --profile default

 

아래는 IAM Role을 EC2에 붙일 경우의 예시이다.

- IAM Policy 설정 예시
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:Describe*",
                "elasticache:Describe*",
                "rds:Describe*",
                "route53:ListHostedZones",
                "route53:ListResourceRecordSets"
            ],
            "Resource": "*"
        }
    ]
}

 

그 외에 Region을 제한할 수 있고 filters를 통해 특정 EC2 리스트만 동적으로 받아온다던지, keyed_groups를 통해 어떤 기준으로 그룹핑을 만들 것인지, hostnames를 통해 출력되는 hostname을 어떻게 할 것인지 모두 설정할 수 있다.

 

참고로 filters는 아래 AWS 공식 문서를 확인하면서 필터링을 걸어줄 수 있다.

https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instances.html#options

 

# aws_ec2.yml

plugin: aws_ec2

boto_profile: default

regions:
  - ap-northeast-2
filters:
  instance-state-name: running
#  key-name: pingping95-key

compose:
  ansible_host: private_ip_address

hostnames:
  - private-ip-address

keyed_groups:
  # Add e.g. x86_64 hosts to an arch_x86_64 group
  - prefix: arch
    key: 'architecture'
  # Add hosts to tag_Name_Value groups for each Name/Value tag pair
  - prefix: tag
    key: tags
  # Add hosts to e.g. instance_type_z3_tiny
  - prefix: instance_type
    key: instance_type
  # Create security_groups_sg_abcd1234 group for each SG
  - key: 'security_groups|json_query("[].group_name")'
    prefix: 'security_groups'
  # Create a group for each value of the Application tag
  - key: tags.Application
    separator: ''
  # Create a group per region e.g. aws_region_us_east_2
  - key: placement.region
    prefix: aws_region
  # Create a group (or groups) based on the value of a custom tag "Role" and add them to a metagroup called "project"
  - key: tags['Role']
    prefix: foo
    parent_group: "project"

 

4. 확인

기 설정한 keyed_groups대로 그루핑이 된 것을 볼 수 있다. 이렇게 동적으로 생성된 그룹은 ansible ad-hoc이나 ansible playbook에서 사용할 수 있다.

 

[root@ip-10-0-0-182 ec2-user]# ansible-inventory -i aws_ec2.yml --graph
@all:
  |--@arch_x86_64:
  |  |--10.0.0.182
  |  |--10.0.10.106
  |  |--10.0.10.239
  |  |--172.31.0.216
  |--@aws_ec2:
  |  |--10.0.0.182
  |  |--10.0.10.106
  |  |--10.0.10.239
  |  |--172.31.0.216
  |--@aws_region_ap_northeast_2:
  |  |--10.0.0.182
  |  |--10.0.10.106
  |  |--10.0.10.239
  |  |--172.31.0.216
  |--@instance_type_t2_micro:
  |  |--10.0.0.182
  |  |--10.0.10.106
  |  |--10.0.10.239
  |  |--172.31.0.216
  |--@security_groups_launch_wizard_1:
  |  |--172.31.0.216
  |--@security_groups_test_common_ssh:
  |  |--10.0.10.106
  |  |--10.0.10.239
  |--@security_groups_test_public_ec2_sg:
  |  |--10.0.0.182
  |--@security_groups_test_was_sg:
  |  |--10.0.10.239
  |--@security_groups_test_web_sg:
  |  |--10.0.10.106
  |--@tag_Environment_test:
  |  |--10.0.0.182
  |  |--10.0.10.106
  |  |--10.0.10.239
  |--@tag_Name_test_bastion:
  |  |--10.0.0.182
  |--@tag_Name_test_was:
  |  |--10.0.10.239
  |--@tag_Name_test_web:
  |  |--10.0.10.106
  |--@ungrouped:

 

aws_ec2.yml을 아래과 같이 설정해서 사용해보자.

 

filters 기능을 통해 running 중이며, key 이름이 pingping95-key를 가진 EC2만 동적 인벤터리에 추가될 것으로 예상할 수 있다.

 

 

 

결과

예상했던 대로 결과가 출력되었다.

[root@ip-10-0-0-182 ec2-user]# ansible-inventory -i aws_ec2.yml --graph
@all:
  |--@aws_ec2:
  |  |--10.0.0.182
  |  |--10.0.10.106
  |  |--10.0.10.239
  |--@ungrouped

 

 

aws_ec2 그룹으로 설정된 EC2에 대해 ping 모듈을 사용하는 ad-hoc 명령어 수행 결과 3대의 EC2에게만 ping 모듈을 사용한 것을 확인할 수 있다.

 

 

 

 

 

 

 

Ref

https://honglab.tistory.com/44

https://linux.systemv.pe.kr/ansible-ec2-py-를-이용한-dynamic-inventory-활용/

https://faun.pub/learning-the-ansible-aws-ec2-dynamic-inventory-plugin-59dd6a929c7f

반응형