1. Application Deployment를 위한,
Fabric의 SSH Streamlining
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
박 병진 (Posquit0) | POSTECH CSE 10 | Jul. 2013
posquit0.bj@gmail.com
“Must be the change that you want to see in the world!”
포스텍 개발자 네트워크 PoApper
2. No Content
1 Intro
2 Deployment with Fabric
3 Tips
포스텍 개발자 네트워크 PoApper
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
3. Fabric
“System Administration 혹은 Application Deployment를 위해 SSH의 사용을 간소화 시켜주는 도구"
파이썬(Python)으로 작성된 도구로, 사용자가 작성한 임의의 파이썬 코드를 fab 명령어로 호출.
=> fabfile.py 작성
Fabric이 제공하는 주요 기능
1) 로컬 혹은 원격의 명령어 실행
2) 원격의 sudo 명령어 실행 가능
3) 파일 업로드 / 다운로드
Intro: Fabric
from fabric.api import run
def host_info():
run(‘uname –a’)
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~# fab –H localhost host_info
[localhost] Executing task ‘host_info’
[localhost] run: uname –a
[localhost] Login password for ‘posquit0’:
※ 비슷한 도구로 루비(Ruby)로 작성된 Capistrano가 있다. (Ruby 프로젝트의 경우, 이를 고려할 것.)
4. Fabric 설치하기
다음은 sudo 권한이 없는 서버를 이용하고 있다고 가정.
1) sudo 권한이 없는 경우 fabric을 설치하기 위한 가상환경을 생성한다.
2) 파이썬 패키지 관리자인 pip를 이용하여 fabric을 설치한다.
Intro: Fabric 설치하기
※ sudo 권한이 있을 경우 가상환경이 아닌 서버에 fabric을 설치하도록 한다.
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~# mkvirtualenv --no-site-packages --distribute myenv
New python executable in myenv/bin/python
Installing distribute………………done.
Installing pip………………………done.
posquit0:~ (myenv) #
posquit0:~ (myenv) # pip install fabric
Downloading/unpacking fabric
…
5. Fabric 시작해보기(1) – Hello, Fabric!
1) 현재 폴더에 fabfile.py를 아래와 같이 작성한다.
2) Fab 명령어를 통해 자신이 작성한 모듈을 호출해본다.
Intro: Fabric 시작해보기(1)
from fabric.api import run
def hello():
“”” Hello Fabric! “””
print “Hello, Fabric!”
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~# fab hello
Hello, Fabric!
Done.
6. Fabric 시작해보기(2) – 명령에 인자 주기
1) 현재 폴더에 fabfile.py를 아래의 내용을 추가한다.
2) Fab 명령어를 통해 자신이 작성한 모듈을 호출해본다.
Intro: Fabric 시작해보기(2)
# ... (생략)
def helloTo(name=“world”):
“”” Hello to {name} “””
print “Hello, %s” % name
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~# fab helloTo:Posquit0
Hello, Posquit0
posquit0:~# fab helloTo:name=LasVegas
Hello, LasVegas
7. Fabric 시작해보기(3) – 로컬 명령 실행
1) 현재 폴더에 fabfile.py를 아래의 내용을 추가한다.
2) Fab 명령어를 통해 자신이 작성한 모듈을 호출해본다.
Intro: Fabric 시작해보기(3)
# ... (생략)
def restartServices(name=None):
“”” Restart services as apache2, nginx, mysql, etc. “””
if name is None:
local(“sudo service apache2 restart”)
local(“sudo service nginx restart”)
local(“sudo service mysql restart”)
else:
local(“sudo service %s restart” % name)
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~# fab restartServices
posquit0:~# fab restartServices:mysql
8. Fabric 시작해보기(4) – 원격 명령 실행
1) 현재 폴더에 fabfile.py를 아래의 내용을 추가한다.
2) Fab 명령어를 통해 자신이 작성한 모듈을 호출해본다.
Intro: Fabric 시작해보기(4)
# ... (생략)
def host_info():
“”” Check host information “””
run(‘uname –a’)
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~# fab –H localhost host_info
[localhost] Executing task ‘host_info’
[localhost] run: uname –a
[localhost] Login password for ‘posquit0’:
9. Fabric 시작해보기(5) – 원격 sudo 명령 실행
1) 현재 폴더에 fabfile.py를 아래의 내용을 추가한다.
2) Fab 명령어를 통해 자신이 작성한 모듈을 호출해본다.
Intro: Fabric 시작해보기(5)
# ... (생략)
def reboot():
“”” Reboot remote server. “””
sudo(‘reboot’)
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~# fab –H ubuntu.poapper.com:2222 reboot
블롸뷁복꿸뛣뿌르구꼬흔따르리뽀꾸라릐뉘구존즤규
…
Bye…
10. Fabric 시작해보기(6) – 파일 전송
1) 현재 폴더에 fabfile.py를 아래의 내용을 추가한다.
2) Fab 명령어를 통해 자신이 작성한 모듈을 호출해본다.
Intro: Fabric 시작해보기(6)
# ... (생략)
def copyVimConfigTo():
“”” Copy Vim Config to remote server: .vim/, .vimrc “””
run(‘rm –rf ~/.vim;rm .vimrc’)
put(‘~/.vim’, ‘~/’)
run(‘ln –s ~/.vim/.vimrc ~/.vimrc’)
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~# fab –H ubuntu.poapper.com:2222 copyVimConfigTo
[Ubuntu.poapper.com] put: ~/.vim/……
…
…
11. Fabric 시작해보기(7) – 파일 다운로드
1) 현재 폴더에 fabfile.py를 아래의 내용을 추가한다.
2) Fab 명령어를 통해 자신이 작성한 모듈을 호출해본다.
Intro: Fabric 시작해보기(7)
# ... (생략)
def copyVimConfigFrom():
“”” Copy Vim Config from remote server: .vim/, .vimrc “””
local(‘rm –rf ~/.vim;rm .vimrc’)
get(‘~/.vim’, ‘~/’)
local(‘ln –s ~/.vim/.vimrc ~/.vimrc’)
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~# fab –H ubuntu.poapper.com:2222 copyVimConfigFrom
[Ubuntu.poapper.com] get: ~/.vim/……
…
…
12. Fabric의 원리
“현재 위치에서 상위 폴더로 이동해가며, fabfile.py를 검색한다. 하위 폴더는 찾지 않는다.“
Example : Podori 프로젝트
- 프로젝트의 최상위(root) 폴더에 fabfile.py 작성
- 하위폴더(nginx, podori, diet 등)에서 fab 호출 가능.
- 상위폴더(Podori 프로젝트 폴더 외부)에서 호출 불가능.
=> 프로젝트 단위의 fabfile.py 작성을 위한 설계
Intro: Fabric의 원리
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
Project/podori.poapper.com/
ㅁ apache2/
ㅁ log/
ㅁ nginx/
ㅁ podori/
ㅁ main/
ㅁ diet/
AUTHORS
fabfile.py
INSTALL
pip-requirements
README.md
robot.txt
13. Core Functionality
- Run() : 원격 서버에서 명령어를 수행한다.
- Local() : 로컬 서버에서 명령을 수행한다.
- Sudo() : 원격 서버에서 루트권한으로 명령을 수행한다.
- Reboot() : 원격의 시스템을 재시작(Reboot)한다.
- Put() : 로컬 서버에서 원격 서버로 파일을 전송한다.
- Get() : 원격 서버에서 로컬 서버로 파일을 전송한다.
- Require() : 다양한 함수들 간의 의존성을 만든다.
=> 전제조건 없이 함수가 실행되는 것을 방지한다.
Intro: Core Functionality
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
def run(
command, shell=True, pty=True, combine_stderr=None,
quit=False, warn_only=False, stdout=None, stderr=None,
timeout=None
)
def local(command, capture=False, shell=None)
def sudo(
command, shell=True, pty=True, combine_stderr=None,
quit=False, user=None, warn_only=False, stdout=None,
stderr=None, group=None, timeout=None
)
14. Configuration (1) – Fabric Environment (env)
Fabric API의 env 변수에 설정들을 보관하며, 이는 Python Dictionary의 Wrapper Class이다.
- Hosts & Roles
- Code Repositories
- Shell
- User & Password
- etc.
Intro: Configuration (1)
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
from fabric.api import env
env.roledefs = {
‘develop’ : [‘ubuntu.poapper.com’, ‘work.posquit0.com’],
‘product’ : [‘pou.poapper.com],
}
env.user = ‘posquit0’
# … 생략
15. Configuration (2) – Global Settings (~/.fabricrc)
~/.fabricrc는 Fabric의 전역 설정 파일로, Fabric이 실행 전에 우선 실행된다. (Python 코드 작성)
Intro: Configuration (2)
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
from fabric.api import env
env.roledefs = {
‘develop’ : [‘ubuntu.poapper.com’, ‘work.posquit0.com’],
‘product’ : [‘pou.poapper.com],
}
env.passwords = {
‘posquit0@posquit0.com’ : ‘skRtldhkd><’,
‘root@ubuntu.poapper.com’ : ‘dlrjf2013alesi’
}
16. 모듈확인
- 현재 Fabric이 인식한 fabfile의 명령어를 Docstring과 함께 출력한다.
Intro: 모듈 확인
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~/develop# fab –l
Available commands:
all Use all servers
applyChanges push to remote repository, pull to product server
commit Commit your changes
dev Use development server settings
hello Hello Fabric!
helloTo Hello To {name}
host_info Print Host’s Information
prod Use production server settings
reboot Reboot remote server.
restartServices Restart Services as Apache2, Nginx, MySQL, etc.
※ 파이썬 프로그래밍을 할 때는, Docstring을 작성하는 습관을 들이도록 합시다 :D
17. No Content
1 Intro
2 Deployment with Fabric
3 Tips
포스텍 개발자 네트워크 PoApper
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
18. Git Repository 생성
1) 프로젝트 폴더를 생성 후, Git Repository로 등록한다.
2) Remote Repository를 생성한 후, 기존의 프로젝트 폴더는 제거한다.
Deployment with Fabric: Git Repository 생성
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~# mkdir myproject
posquit0:~# cd myproject/
posquit0:~/myproject# git init
Initialized empty Git repository in myproject/.git/
posquit0:~/myproject# touch README; git add .
posquit0:~/myproject# git commit –m “First Commit”
posquit0:~# git clone --bare myproject myproject.git
posquit0:~# touch myproject.git/git-daemon-export-ok
posquit0:~# rm –rf myproject
posquit0:~# cd myproject.git
posquit0:~/myproject# git --bare update-server-info
posquit0:~/myproject# mv hooks/post-update.sample hooks/post-update
19. 프로젝트 복제
1) 실제 서비스 운영을 위한 위치(가정)에서 이전 단계에서 만든 Remote Repository를 복제한다.
git clone ssh://{사용자 계정}@{Host 이름}:{Port}/{Repository 경로} {{생성 폴더이름}}
2) 개발을 위한 위치(외부 서버라 가정)에서 또 다시 Remote Repository를 복제한다.
Deployment with Fabric: 프로젝트 복제
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~# git clone ssh://posquit0@posquit0.com:22/~/myproject.git product
posquit0:~# git clone ssh://posquit0@posquit0.com:22/~/myproject.git develop
20. 변경사항 적용(1) – Without Fabric
1) 개발 서버에서 변경사항을 저장하고 Commit 한다.
2) 개발서버의 내용을 Remote Repository에 적용한다. (Push)
3) Remote Repository의 내용을 운영 서버에 적용한다. (Pull)
Deployment with Fabric: 변경사항 적용(1)
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~/develop# git add .
posquit0:~/develop# git commit –m “Several Changes! May be…”
posquit0:~/develop# git push
posquit0:~# cd product
posquit0:~/product# git pull
21. 변경사항 적용(2) – With Fabric
1) fabfile.py를 프로젝트의 최상위 폴더에 작성한다.
2) 개발서버의 변경 사항을 커밋하고 fab 명령을 통해 Remote Repository 및 운영 서버에 적용한다.
Deployment with Fabric: 변경사항 적용(2)
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~/develop# vim fabfile.py
# ... (생략)
def applyChanges():
local(‘git push’)
run(‘cd product/; git pull’)
posquit0:~/develop# git add .
posquit0:~/develop# git commit –m “Several Changes! May be…”
posquit0:~/develop# fab applyChanges
※ 호스트 정보가 Fabric에 등록되어 있지 않아, 호스트 정보를 물어 볼 것이다.
22. Host 정보 입력(1) – 전역 Host
1) fabfile.py의 내용에 다음을 추가한다.
2) 다시 한 번 fab 명령을 통해 applyChanges를 호출해보자.
Deployment with Fabric: Host 정보 입력(1)
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~/develop# vim fabfile.py
# ... (생략)
env.hosts = [
‘posquit0@posquit0.com:22’,
]
# ... (생략)
posquit0:~/develop# git add .
posquit0:~/develop# git commit –m “Added Host Information”
posquit0:~/develop# fab applyChanges
※ 호스트 정보가 Fabric에 등록되어 있어, 호스트 정보를 물어 보지 않고 진행된다.
23. Host 정보 입력(2) – 개별 Host 관리
- fabfile.py의 내용에 env.hosts에 관한 내용을 다음과 같이 변경한다.
Deployment with Fabric: Host 정보 입력(2)
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
def dev():
“”” Use development server settings “””
env.hosts = [
‘posquit0@develop.posquit0.com:22’,
]
def prod():
“”” Use production server settings “””
env.hosts = [
‘posquit0@prod.posquit0.com:22’,
]
def all():
“”” Use all servers “””
env.hosts = [
‘posquit0@develop.posquit0.com:22’,
‘posquit0@prod.posquit0.com:22’,
]
24. Host 정보 입력(2) – 개별 Host 관리
- 다음과 같이 목표 서버를 지정하여 명령을 수행할 수 있다.
Deployment with Fabric: Host 정보 입력(2)
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~/develop# git add .
posquit0:~/develop# git commit –m “Divided host information”
posquit0:~/develop# fab dev applyChanges
posquit0:~/develop# fab prod applyChanges
posquit0:~/develop# fab all applyChanges
※ 각 호스트 별로 프로젝트 폴더의 위치를 env에 저장하여, 이를 참조하도록 applyChanges 모듈을 수정한다.
25. No Content
1 Intro
2 Deployment with Fabric
3 Tips
포스텍 개발자 네트워크 PoApper
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
26. Roles (1) – 역할 별 모듈 수행
- Roles는 Host를 역할 별로 분류하여 파이썬 태그를 이용하여 모듈을 수행 할 Role을 지정할 수 있다.
- 두 개 이상의 Role을 지정할 수도 있다.
Tips:Roles (1)
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
※ get_version() 모듈은 ‘develop’ 그룹의 Hosts들에서 수행 될 것이다.
from fabric.api import env, roles, run
env.roledefs = {
‘develop’ : [‘ubuntu.poapper.com’, ‘work.posquit0.com’],
‘product’ : [‘pou.poapper.com],
}
@roles(‘develop’)
def get_version():
run(‘cat /etc/issue’)
@roles(‘develop’, ‘product’)
def get_version():
run(‘cat /etc/issue’)
27. Roles (2) – 문제 해결
- 기본으로 제공되는 Fabric의 roles 태그는 명령어 --roles 옵션으로 오버라이드가 안된다.
=> 사용자 정의 태그를 작성하여 roles 태그를 교체하여 문제를 해결할 수 있다.
Tips:Roles (2)
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
※ get_version() 모듈은 ‘test’ 그룹의 Hosts들에서 수행 될 것이다.
# ... (생략)
def default_roles(*role_list):
def selectively_attach(func):
if not env.roles and not env.hosts:
return roles(*role_list)(func)
else:
if env.hosts:
func = hosts(*env.hosts)(func)
if env.roles:
func = roles(*env.roles)(func)
return func
return selectively_attach
@default_roles(‘develop’, ‘product’)
def get_version():
run(‘cat /etc/issue’)
posquit0:~/develop# fab get_version --roles test
28. Dealing with Failures – With 문 사용
- 기본적으로 Task가 실패할 경우(에러가 발생할 경우), Fabric은 종료된다.
=> Failure가 예상되는 경우, Context Manager를 통해 경고문만 출력하도록 한다.
Tips: Dealing with Failures
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
from __future__ import with_statement
from fabric.api import local, settings, run
def symlinkTo(src, dst):
“”” Make a symbolic link “””
with settings(warn_only=True):
run(‘rm %s’ % dst)
run(‘ln –s %s %s’ % (src, dst))
※ Python 2.5 버전의 경우 with문 사용을 위해서는 __future__를 import 하여야 한다.
29. Invoke 구현 – 임의의 원격 sudo 명령 수행
- 다음과 fabfile에 invoke를 구현한다.
Tips: Invoke 구현
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
@roles(‘all’)
def invoke(command):
“”” Invoke arbitrary commands to remote server “””
sudo(command)
30. Server Package Updates
- 다음과 같이 fabfile에 서버 패키지 업데이트를 위한 모듈을 작성한다.
- Fab 명령을 통해 원격 서버의 패키지 업데이트를 수행한다.
Tips: Server Package Updates
커뮤니티 팀 내부 세미나 – Fabric을 이용한 SSH Streamlining
posquit0:~/develop# fab update
def update():
“”” Update Packages on server “””
sudo(‘aptitude update; aptitude safe-upgrade’)