개요
다수의 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의 동작 원리는 다음과 같다.
- Bastion에서 접근 시도할 VM들에 대한 정보가 있어야 한다. ( 인증 정보, 인증 정보를 사용할 수 있는 유저의 이름)
- 위의 정보를 이용하여 SSH 접속을 Ansible이 시도한다.
- 인증 완료 후 각종 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 디렉터리에 생성되게 된다. 이 말은 즉 /etc/ansible 디렉터리에 생성이 안되기 때문에 해당 유저만 사용할 수 있다는 뜻임)
⇒ root 유저인 상태에서 설치했을 경우 ec2-user를 사용할 수 없다는 뜻임.. 왜냐만 /root/.ansible 디렉터리에 설치되어 있기 때문
ansible-galaxy collection install amazon.aws
3. ansible.cfg 및 aws_ec2.yml 설정
- ansible.cfg
아래의 공식 문서를 보면서 작성하였다.
[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
'AWS' 카테고리의 다른 글
[CICD] Terraform을 통한 AWS 3 Tier 구성 및 CI/CD 파이프라인 배포 #1 - 아키텍처 및 CICD 흐름 소개 (0) | 2021.08.11 |
---|---|
[Packer] Packer를 이용한 EC2 AMI 생성 (1) | 2021.08.06 |
AWS IAM을 통한 인증, 인가 (0) | 2021.07.24 |
[AWS] IAM Policy JSON 알아보기 (0) | 2021.07.24 |
[AWS] Root Volume을 다른 EC2 Instance에 붙이기 (2) | 2021.07.21 |