Cloud Formation Template을 이용해 네트워크(VPC) 준비하기
VPC 구성은 Public Subnet 2개 / Private Subnet 2개 / NAT Gateway 1개(비용 발생) 로 구성됩니다.
테스트할 VPC 가 있는 분은 따로 진행하지 않으셔도 됩니다.
초기에 EC2는 2대 생성 합니다.
1대는 ansible playbook을 작성하고 관리하는 ansible-server.
다른 1대는 ansible playbook을 이용해 provisioning 할 목적의 target-server.
- AWS Console 접속
- 서울 리전(ap-northeast-2)으로 이동
- AWS EC2 Console 로 이동
- EC2 생성하기 - Amazon Linux AMI 2018.03.0 으로 생성
- EC2 Type - t2.micro 로 선택
- 기 생성된 VPC 중 Public Subnet 에 위치하도록 선택
- Auto-assign Public IP 옵션 True
- Security Group 에 22번 포트 접속 가능하도록 설정
- Keypair 생성 후 다운로드 - 편의를 위해 2대 모두 같은 keypair로 선택.
- EC2 생성 완료
## {중괄호 부분은 여러분이 생성한 Key pair, EC2 IP에 맞게 변경하세요}
$ ssh -i {YOUR_KEY_PAIR.pem} ec2-user@{10.100.0.0}
# 예시
$ ssh -i aws-krug-handson.pem ec2-user@10.100.10.1
- Putty 다운로드
https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html - PuTTYgen을 이용하여 pem 키를 ppk (putty private key)로 변경하기
https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/putty.html#putty-private-key - Putty 를 이용해 ec2 에 접속하기
https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/putty.html#putty-ssh
Ansible 공식 설치 메뉴얼은 https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html 에서 확인 가능
apt-get, yum, pip, brew 등 다양한 방법으로 설치가 가능함.
## sudo 권한 필요
$ sudo pip install ansible
## 설치 확인
$ ansible --version
$ which ansible
# /usr/local/bin/ansible
Ad-hoc Command 에 대하여 알아보기
https://docs.ansible.com/ansible/latest/user_guide/intro_adhoc.html
- Ansible이 강력한 이유는 Playbook을 사용하기 때문
- ad-hoc 명령어는 한번 명령어를 사용하고 버려도 되는 경우에 사용함 (거의 쓸일이 없기는 함)
# ansible HOST -m MODULE_NAME
$ ansible localhost -m ping
Playbook 디렉토리를 생성하고 각 Role별 Tasks, Templates, files 등 디렉토리 구조를 만든다.
## Ansible Playbook 을 관리할 디렉토리로 이동.
$ cd {your directory}
$ mkdir -p playbook/roles/httpd/
$ cd playbook/roles/httpd/
$ mkdir files handlers defaults templates tasks
$ cd -
$ tree
.
└── playbook
└── roles
└── httpd
├── defaults
├── files
├── handlers
├── tasks
└── templates
ansible 을 수행할 directory에 ansible.cfg 파일을 생성한다.
[defaults]
host_key_checking = False
become_user = root
remote_user = ec2-user
timeout = 60000
callback_whitelist = profile_tasks
private_key_file = ~/.ssh/ansible-packer.pem
inventory = ./my-inventory
[ssh_connection]
pipelining = True
서버에 접속할 인증키를 ~/.ssh/ansible-packer.pem 에 위치한다.
ansible을 수행할 directory에 my-inventory 파일을 생성한다.
[target]
13.209.82.234
$ vim playbook/roles/httpd/tasks/main.yml
---
- name: install httpd with yum
yum: name={{ item.package }}
loop:
- { package: httpd }
- { package: mod_ssl }
# ansible-playbook --connection=local -i "127.0.0.1," playbook/httpd.yml
$ ansible-playbook -l target playbook/httpd.yml
---
service: awskrug
### 기존 작성 생략
### {{ 변수명 }} 으로 변수 처리
- name: create apache document root directory
file:
path: "/data/apache/{{ service }}/docroot"
state: directory
owner: apache
group: apache
mode: 0755
recurse: yes
# Ansible Playbook 실행해보기
$ ansible-playbook -l target playbook/httpd.yml
---
service: awskrug
http_port: 10180
<VirtualHost *:{{ http_port }}>
DocumentRoot /data/apache/{{ service }}/docroot
ErrorLog /log/apache/{{ service }}/{{ service }}.error_log
CustomLog /log/apache/{{ service }}/{{ service }}.access_log common
</VirtualHost>
### 기존 작성 생략
### template을 이용해 변수 적용
- name: copy apache virtual host configuration
template:
src: "http-{{ service }}-vhost.conf.j2"
dest: "/etc/httpd/conf.d/http-{{ service }}-vhost.conf"
owner: apache
group: apache
mode: 0644
### lineinfile 을 이용해 파일 내 특정 라인만 내용 변경
- name: change apache default listening port configuration
lineinfile:
dest: /etc/httpd/conf/httpd.conf
regexp: "^Listen"
line: "Listen {{ http_port }}"
# Ansible Playbook 실행해보기
$ ansible-playbook -l target playbook/httpd.yml
# Ansible Playbook 실행해보기
### -e http_port=20080 옵션 추가
$ ansible-playbook -l target playbook/httpd.yml -e http_port=20080
---
- name: restart apache webserver
service:
name: httpd
state: restarted
### 기존 아래 이름의 Task에 notify 추가
- name: copy apache virtual host configuration
template:
src: "http-{{ service }}-vhost.conf.j2"
dest: /etc/httpd/conf.d/http-vhost.conf
owner: apache
group: apache
mode: 0644
notify:
- restart apache webserver
# Ansible Playbook 실행해보기
$ ansible-playbook -l target playbook/httpd.yml
PLAY [all] ***************************************************************************
TASK [Gathering Facts] ***************************************************************
ok: [127.0.0.1]
TASK [httpd : install httpd] *********************************************************
ok: [127.0.0.1] => (item={u'package': u'httpd'})
ok: [127.0.0.1] => (item={u'package': u'mod_ssl'})
TASK [httpd : create apache document root directory] *********************************
ok: [127.0.0.1]
## TASK에 변경(changed)이 있으면,..
TASK [httpd : copy apache virtual host configuration] ********************************
changed: [127.0.0.1]
## HANDLER가 수행됨.
RUNNING HANDLER [httpd : restart apache webserver] ***********************************
changed: [127.0.0.1]
PLAY RECAP ***************************************************************************
127.0.0.1 : ok=5 changed=1 unreachable=0 failed=0
notify 코드 이후에 더 task 를 추가해 봅니다.
## 기존 코드 생략
- name: create apache log directory
file:
path: "/log/apache/{{ service }}/"
state: directory
owner: apache
group: apache
mode: 0755
recurse: yes
# Ansible Playbook 실행해보기
$ ansible-playbook -l target playbook/httpd.yml
PLAY [all] ***************************************************************************
TASK [Gathering Facts] ***************************************************************
ok: [127.0.0.1]
TASK [httpd : install httpd] *********************************************************
ok: [127.0.0.1] => (item={u'package': u'httpd'})
ok: [127.0.0.1] => (item={u'package': u'mod_ssl'})
TASK [httpd : create apache document root directory] *********************************
ok: [127.0.0.1]
TASK [httpd : copy apache virtual host configuration] ********************************
changed: [127.0.0.1]
TASK [httpd : change apache default listening port configuration] ********************
ok: [127.0.0.1]
TASK [httpd : create apache log directory] *******************************************
ok: [127.0.0.1]
## Handler가 가장 마지막에 실행 됨
RUNNING HANDLER [httpd : restart apache webserver] ***********************************
changed: [127.0.0.1]
PLAY RECAP ***************************************************************************
127.0.0.1 : ok=7 changed=2 unreachable=0 failed=0
notify에 등록된 handler는 바로 실행되지 않고, tasks 실행이 끝난 뒤 마지막에 수행 됨.
원하는 지점에서 실행하게 하려면 아래처럼 코드를 추가 해야 함.
### 기존 코드 notify 아래 - meta: flush_handlers 추가
- name: copy apache virtual host configuration
template:
src: "http-{{ service }}-vhost.conf.j2"
dest: /etc/httpd/conf.d/http-vhost.conf
owner: apache
group: apache
mode: 0644
notify:
- restart apache webserver
- meta: flush_handlers
# Ansible Playbook 실행해보기
$ ansible-playbook -l target playbook/httpd.yml
PLAY [all] ***************************************************************************
TASK [Gathering Facts] ***************************************************************
ok: [127.0.0.1]
TASK [httpd : install httpd] *********************************************************
ok: [127.0.0.1] => (item={u'package': u'httpd'})
ok: [127.0.0.1] => (item={u'package': u'mod_ssl'})
TASK [httpd : create apache document root directory] *********************************
ok: [127.0.0.1]
TASK [httpd : copy apache virtual host configuration] ********************************
changed: [127.0.0.1]
## flush 시점에 쌓여있던 handler trigger가 모두 수행됨.
RUNNING HANDLER [httpd : restart apache webserver] ***********************************
changed: [127.0.0.1]
TASK [httpd : change apache default listening port configuration] ********************
ok: [127.0.0.1]
TASK [httpd : create apache log directory] *******************************************
ok: [127.0.0.1]
PLAY RECAP ***************************************************************************
127.0.0.1 : ok=7 changed=2 unreachable=0 failed=0
Ansible 코드를 작성하여 packer를 설치해 봅니다.
role 추가하기
$ mkdir -p playbook/roles/packer/tasks/
---
- name: download packer binary
get_url:
url: https://releases.hashicorp.com/packer/1.3.2/packer_1.3.2_linux_amd64.zip
dest: /home/ec2-user/packer.zip
mode: 0644
- name: unzip packer binary
unarchive:
src: /home/ec2-user/packer.zip
dest: /usr/bin/
remote_src: yes
mode: 0755
become: yes
become_user: root
---
- hosts: all
roles:
- packer
$ ansible-playbook -l target playbook/packer.yml
packer를 수행할 폴더에서 template file을 생성한다.
{
"builders": [{
"type": "amazon-ebs",
"subnet_id": "{{user `aws_subnet_id`}}",
"vpc_id": "{{user `aws_vpc_id`}}",
"region": "{{user `aws_region`}}",
"security_group_id": "{{user `security_group_id`}}",
"ssh_keypair_name": "ansible-packer",
"ssh_username": "ec2-user",
"ssh_private_key_file": "ansible-packer.pem",
"ssh_pty": "false",
"ssh_interface": "private_ip",
"instance_type": "t2.micro",
"source_ami": "{{user `aws_source_ami`}}",
"ami_name": "{{user `aws_target_ami`}}",
"associate_public_ip_address": "true",
"tags": {"service": "{{user `service`}}"},
"run_tags": {
"Name": "{{user `ec2-name`}}",
"Cost-Center": "awskrug"
},
"ami_block_device_mappings": [
{
"device_name": "/dev/sda1",
"delete_on_termination": "true",
"volume_type": "gp2"
}
]
}],
"provisioners": [{
"type": "ansible",
"playbook_file": "/home/ec2-user/playbook/httpd.yml",
"user": "ec2-user",
"sftp_command": "/usr/libexec/openssh/sftp-server",
"extra_arguments": [
"--extra-vars",
"service={{user `service`}}"
]
}]
}
template에 변수 처리 할 내용을 variable로 작성할 수 있습니다.
여기서 변수 값은 여러분들이 생성하신 vpc 및 subnet 등의 정보롤 대체하시면 됩니다.
{
"aws_vpc_id": "vpc-c10536a9",
"aws_subnet_id": "subnet-65a6910d",
"security_group_id": "sg-0b26500a049ce59cb",
"aws_source_ami": "ami-0a10b2721688ce9d2",
"aws_target_ami": "my-first-ami",
"service": "awskrug",
"ec2-name": "now-baking"
}
packer 를 수행할 서버는 ec2 및 ami등 새로 생성할 수 있는 권한이 필요합니다.
AWS Console 에서 IAM으로 이동하여 ec2 role을 생성합니다.
IAM > Roles > Create Role 로 이동합니다.
- EC2 가 사용할 Role로 지정 후 다음으로 넘어갑니다.
- Attach permissions policies 에서 편의상 AmazonEC2FullAccess 를 선택하고 다음으로 넘어갑니다.
- Tag 지정은 무시하고 넘어갑니다.
- Role Name에는 packer-role 로 지정합니다.
- EC2 콘솔로 이동하여 ansible-packer 용 EC2에 조금 전에 생성한 role을 부여합니다.
$ packer build -var-file=var_file.json basic_template.json