[ pycon korea 2017 ] infrastructure as code를위한 ansible 활용
TRANSCRIPT
Infrastructure as Code를 위한Ansible 활용
송지형 ([email protected])
발표자
• KT – uCloud IaaS• SK Planet - Openstack, AWS, Saltstack..• ncsoft – Cloud Platform 개발
리니지M 켄라우헬8 서버에거주
• Cloud Engineer : Cloudstack, Openstack, AWS, VDIPython을만나Cloud Platform 개발자로 : Django 사랑합니다
발표내용
• Infrastructure as Code (IaC) ?
• CM tool – Ansible
• Ansible을자동화해보자
• IaC 를위한 Ansible 활용방법
• Dynamic inventory
• Variable 관리
• Vault를활용한계정정보관리
• Result Callback
• Async
Infrastructure as Code ?
Infrastructure as code (IaC) is the process of managing and provisioning computer data
centers through machine-readable definition files, rather than physical hardware
configuration or interactive configuration
Interactive한 구성(ex. CLI ) 이나
물리적인 하드웨어 구성 방식 대신에
Machine-readable 정의 파일을 이용해
데이터 센터를 관리하는 프로세스
Infrastructure as code describes the idea of using a high-level programming language to
control IT systems.
(Amazon Web Service in Action, 2015)
IT System을
high-level 프로그래밍 언어를 이용해 제어하는
아이디어에서 출발
(Amazon Web Service in Action, 2015)
예전엔 말이야..
- 구전으로 전해 내려오는 서버 구성 히스토리
10년전 내 사수가 쓰던 Script 인데..
이것만 돌리면 다 됨. ㅋ
- 어떤 내용인지 파악 조차 하기 힘든 script 들
파일(File)과 기록(Code)을 통해
서버의 구성 정보를 체계적으로 관리
스파게티 Script 에서 벗어나자!
Hardware 입고
RackMount
CablingOS
InstallOS
ConfigureApplicationDeployment
Server
Switch입고
RackMount
Cabling InitializeRouting
ConfigureManagement
Network
인프라 구축 단계
Hardware 입고
RackMount
CablingOS
InstallOS
ConfigureApplicationDeployment
Server
Switch입고
RackMount
Cabling InitializeRouting
ConfigureManagement
Network
자동화 하기 어려운 영역이었죠
Hardware 입고
RackMount
CablingOS
InstallOS
ConfigureApplicationDeployment
Switch입고
RackMount
Cabling InitializeRouting
ConfigureManagement
Cloud / Container / SDN
Server
Network
Cloud / Container / SDN 등
H/W 를 S/W로 제어하는 기술들이 발전하면서,
IaC 방식의 인프라 관리 방법도 점점 발전
IaC 에 대해서 진지하게 이야기 하려면..
Cloud
SDN
CMDB
Configuration Management
Version Control
CI (Continueous Integration)
CD (Continueous Delivery)
오늘은 이중에서
배포/설정 자동화에 대하여(만)
이야기해 보아요
CM Tool 4대장
그 중에서도 오늘은 이 녀석에 대해 알아보아요
Python
Github
star ranking
Ansible 장점?
1. 간편한 사용don’t need to run server
No DB
Playbook 이라는정의 파일을 이용해
인프라를 원하는 대로 설정!
Playbook 만들기도
매우매우 쉬움친숙한 YAML 포맷에
문서 조금만 읽어 보면 누구나 손쉽게 작성 가능
이번 시간은
Playbook 에 대한 자세한
내용은 skip
Ansible 장점?
2. Agentless기존 운영 중인 서버에
도입하기 쉬움
운영자는 agent 싫어해요
Ansible 장점?
3. 멱등성(idempotence)
ansible을 여러 번 실행해도 그 결과는 동일!
사실 이건 모든 CM tool이 가지고 있는 장점이죠
Infrastructure as Code 를
달성하기 위해
Ansible을 어떻게 이용하면 좋을까?
Ansible 을
Interactive 한 CLI 만 사용하기 보다는
최대한 Programmable 형태로 운영해야 한다.
But,
community에 공개된 것은
Ansible Core
Core에는 API가 없어요 ㅠㅠ
쓰고 싶으면 Ansible Tower 사세요. (from Redhat)
but..
만들면 됩니다.
Python만 가능합니다.
어떻게?
Ansible core가
Python으로 구현되어 있어요
Ansible module을 import 해서
사용하면 가능해요
API 구현은
Django Restframework 이나
Flask RESTful 로
여기서 Django와 Flask 사용법은
굳이 설명하지 않을께요.
여기 계신 분들이
저보다 잘 하시는거 다 알아요.
# ansible
from ansible.parsing.dataloader import DataLoaderfrom ansible.vars import VariableManagerfrom ansible.vars.hostvars import HostVarsfrom ansible.inventory import Inventoryfrom ansible.inventory.host import Hostfrom ansible.inventory.script import InventoryScriptfrom ansible.playbook.play import Playfrom ansible.executor.task_queue_manager import TaskQueueManagerfrom ansible.executor.playbook_executor import PlaybookExecutor
# initialize needed objectsvariable_manager = VariableManager()loader = DataLoader()options=Options(connection=‘ssh’,
module_path=None, forks=100, become=None, become_method=None, become_user=None, check=False)
# create inventory and set to variable managerinventory = Inventory(loader=loader, variable_manager=variable_manager)variable_manager.set_inventory(inventory)
# create play with tasks
play_source = dict(name = ‘Ansible Play’,hosts = host_list,gather_facts = ‘no’,tasks = [
dict(action=dict(module=‘shell’, args=‘ls’), register=‘shell_out’),dict(action=dict(module=‘debug’ args=dict(msg=‘{{shell_out.stdout}}’)))
])
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
# actually run it
tqm = Nonetry:
tqm = TaskQueueManager(inventory=inventory,variable_manager=variable_manager,loader=loader,options=options,passwords=None
)
result = tqm.run(play)
finally:if tqm is not None:
tqm.cleanup()
이렇게
Ansible module들을
직접 import 해서 구현 가능합니다.
IaC 에 맞게
좀 더 멋지게 Ansible을 사용해 봅시다.
그 중 첫번째,
Dynamic inventory
Ansible의 host 관리 (=inventory)
보통 /etc/ansible/hosts
파일로 관리
[webservers]
192.168.0.10192.168.0.11
[dbservers]
192.168.1.11192.168.1.12
Ansible에서 관리하는 host 정보를
외부 시스템에 위임하는 것
Dynamic Inventory
host 관리를 누구에게 위임하면 좋을까?
Infrastructure as Code 의 기본
CMDB
모든 인프라 정보를 담는 DB
정보의 중앙 집중화
모든 자동화 코드의 Data Source 역할
CMDB는 반드시 API 와 같은
External interface 가 필요
# get Host List from CMDBhost_list = getHostListFromCMDB(params)
# initialize needed objectsvariable_manager = VariableManager()loader = DataLoader()options=Options(connection=‘ssh’,
module_path=None, forks=100, become=None, become_method=None, become_user=None, check=False)
# create inventory and set to variable managerinventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=host_list)variable_manager.set_inventory(inventory)
CMDB가 없나요?
이 참에 하나 장만해 보시는게..
Variable
Ansible은
host 별로 variable 설정 가능
이것도 inventory와 마찬가지로
/etc/ansible/hosts 에서 관리
[webservers]
webserver01 ansible_ssh_user=ansible ansible_password=XXXXX desc=board1webserver02 ansible_ssh_user=ansible ansible_password=XXXXX desc=board2
from ansible.inventory.host import Hostfrom ansible.vars import VariableManager
# get host info from CMDBhost_dic = getHostFromCMDB(name=‘webserver-01’)host = Host(name=host_dic[‘name’])
# set variable to hostvar_mgr = VaraibleManager()attr_tag = dict(host=host, varname=‘desc’, value=‘board1’)
var_mgr.set_host_variable(**attr_tag)
Ansible은 target host에 SSH 통신
host 에 접속하는 계정 정보도 Variable 로 관리
각별한 주의 필요
보안팀이 이 글을 싫어합니다
Variable의 계정 정보만이라도
따로 관리하자
Data, File, API키, 토큰 등을 암호화하여 저장하는 tool
API도 잘 되어있고, python client도 있어서
연동하고 매우 쉬워요
from ansible.inventory.host import Hostfrom ansible.vars import VariableManagerfrom vaultClient import VaultClient
# get host info from CMDBhost_dic = getHostFromCMDB(name=‘webserver-01’)host = Host(name=host_dic[‘name’])
# set variable to hostvar_mgr = VaraibleManager()
# set credential from Vaultvclient = VaultClient(vault_endpoint, token)credential_data = vclient.getData(host_dic[‘name’])
for key, val in credential_data.iteritems():attr_tag = dict(host=host, varname=key, value=val)var_mgr.set_host_variable(**attr_tag)
Playbook관리
Playbook 은
인프라 구성 정보를 담은 파일 이예요.
Ansible의 핵심이죠.
보통 Ansible 을 CLI로 실행하면..
ansible@ ~:/ansible# ansible-playbook playbook01.yml
보통 Playbook은
Ansible server의 local에 있어야 해요.
But,
Playbook 도
Code 입니다.
Version 관리가 필요합니다.
GitPython 을 이용하여
Playbook 파일을 Ansible server 로 받아와 수행
# create play with tasks from Git…playbook = self.getPlaybookFromGit(playbook_name)
with open(playbook) as fp:yaml_data = yaml.load(fp)
play_source = dict(name = yaml_data.get(‘name’, ‘Execute %s’%(playbook_name)),hosts = host_list,gather_facts = yaml_data.get(‘gather_facts’, False),tasks = self.getTaskFromPlaybook(yaml_data)
)
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
Result Callback
Ansible이 열심히 수행한 내용의
결과를 받는 방법
Callback
Class CallbackBase:
‘ ‘ ‘ This is a base ansible callback class that does nothing. New callbacks shoulduse this class as a base and override any callback methods they wish to executecustom actions.‘ ’ ’
Ansible의 plugins 에는
callback 을 커스터마이징해서 쓰려면
CallbackBase 를 override 해서 사용하라고 가이드 되어 있음
# override Callback class for IaCfrom ansible.plugins.callback import CallbackBase
Class ResultCallback(CallbackBase):
def v2_runner_on_ok(self, result, **kwargs):host = result._host.nameprint json.dumps({host: result._result})
def v2_runner_on_failed(self, result, ignore_errors=False):host = result._host.nameprint json.dumps({host: result._result.get(‘msg’, ‘’))
def v2_playbook_on_play_start(self, play):….
def v2_playbook_on_task_start(self, task, is_conditional):….
results_callback = ResultCallback()
tqm = Nonetry:
tqm = TaskQueueManager(inventory=inventory,variable_manager=variable_manager,loader=loader,options=options,passwords=None,stdout_callback=results_callback
)
Async
Ansible은 기본적으로
sync 형태로 동작해요.
task 가 완료될 때까지
SSH 세션을 유지하며
결과를 기다려요.
오래걸리는 작업
기다리고 싶지 않다면?
Async 모드로 동작하면 되요.
# create play with tasks (async mode)
play_source = dict(name = ‘Ansible Play’,hosts = host_list,gather_facts = ‘no’,tasks = [
dict(yum=dict(name=‘httpd’, state=‘latest’), async=100, poll=0)]
)
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
# override Callback class for IaCfrom ansible.plugins.callback import CallbackBase
Class ResultCallback(CallbackBase):
def __init__(self, **kwargs):self.result = []
def v2_runner_on_ok(self, result, **kwargs):host = result._host.name
if kwargs[‘async_mode’]:self.result.append(result._result[‘ansible_job_id’])
self.result.append(result._result)
# create play to check async job
play_source = dict(name = ‘Check Async Job status’,hosts = host_list,gather_facts = ‘no’,tasks = [
dict(async_status=dict(jid=async_job_id))]
)
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
Q&A
감사합니다
송지형 ([email protected])