IaC

Ansible - Playbook Tutorial(1/3)

Operation CWAL 2021. 3. 6. 16:23

설치

Ubuntu 환경에서 다음 명령어로 Ansible을 손쉽게 설치할 수 있다. Ansible Controller로 사용할 Machine에서 실행한다.

sudo apt update
sudo apt install software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt install ansible

 

테스트

제대로 설치되었는지 확인해보기 위해 아래와 같은 테스트 코드를 작성해보자. 우선 inventory.txt에 관리할 서버에 대한 정보를 추가한다. 각 Host는 SSH 서버가 실행중인 상태로, Ansible Controller와 연결이 가능해야 한다.

 

[test-servers]
test-server-1 ansible_host=172.30.1.45 ansible_ssh_user=tester
test-server-2 ansible_host=172.30.1.49 ansible_ssh_user=tester

사전에 SSH Key를 등록한 테스트를 서버를 Inventory에 추가하였다. 해당 계정(tester)는 sudo 권한 요청시 별도의 비밀번호를 입력하지 않도록 /etc/sudoers 파일도 수정한 상태이다. 그리고 [test-servers]를 통해 두 Host를 하나의 그룹으로 묶었다.

 

Host  서버(test-server-1, test-server-2)에 Ping 테스트를 수행할 Ansible Playbook(playbook.yaml)을 아래와 같이 작성하였다.

- name: Deploy a web application
  hosts: test-server-1, test-server-2
  tasks:
  - name: Try Ping
    ping:

 

현재 과정을 따라했다면 현재 디렉토리의 파일 구성은 다음과 같다.

Ansible 명령어를 실행하기 전, SSH Strict Host Key Checking 기능을 비활성화(실제 환경에선 사용하지 말것)하도록 한다. ~/.ssh/config 파일에 아래 내용을 추가한다.

Host *
    StrictHostKeyChecking no

 

이제 모든 준비가 끝났으니, 아래 명령어로 Ansible Playbook을 수행할 차례다.

ansible-playbook playbook.yaml -i inventory.txt

Ansible Controller와 두 Host가 정상적으로 연결됐음을 확인할 수 있다.

 

Web Application 배포

이번엔 각 Host에 Web App을 배포하는 과정을 Ansible Playbook으로 자동화해보자. 해당 App은 Python Flask 기반의 간단한 웹서버와 DB(MySQL)로 구성되어 있다. 우선 아래와 같이 Flask 앱 app.py를 작성해보자.

import os
from flask import Flask
from flaskext.mysql import MySQL      # For newer versions of flask-mysql 
# from flask.ext.mysql import MySQL   # For older versions of flask-mysql
app = Flask(__name__)

mysql = MySQL()

mysql_database_host = 'MYSQL_DATABASE_HOST' in os.environ and os.environ['MYSQL_DATABASE_HOST'] or  'localhost'

# MySQL configurations
app.config['MYSQL_DATABASE_USER'] = 'db_user'
app.config['MYSQL_DATABASE_PASSWORD'] = 'Passw0rd'
app.config['MYSQL_DATABASE_DB'] = 'employee_db'
app.config['MYSQL_DATABASE_HOST'] = mysql_database_host
mysql.init_app(app)

conn = mysql.connect()

cursor = conn.cursor()

@app.route("/")
def main():
    return "Welcome!"

@app.route('/how are you')
def hello():
    return 'I am good, how about you?'

@app.route('/read from database')
def read():
    cursor.execute("SELECT * FROM employees")
    row = cursor.fetchone()
    result = []
    while row is not None:
      result.append(row[0])
      row = cursor.fetchone()

    return ",".join(result)

if __name__ == "__main__":
    app.run()

 

다음은 playbook.yaml 파일을 아래와 같이 수정한다.

- name: Deploy a web application
  hosts: test-server-1, test-server-2
  become: true
  vars:
    db_name: employee_db
    db_user: db_user
    db_password: Passw0rd

  tasks:
  - name: Install all required dependencies
    apt:  
      name:
      - python
      - python-setuptools
      - python-dev
      - build-essential
      - python-pip
      - python-mysqldb
      state: present

  - name: Install MySQL database
    apt:
      name:
      - mysql-server
      - mysql-client
      state: present

  - name: Start Mysql Service
    service:
      name: mysql
      state: started
      enabled: yes

  - name: Create Application Database
    mysql_db:
      login_unix_socket: /var/run/mysqld/mysqld.sock
      name: "{{ db_name }}"
      state: present

  - name: Create Database user
    mysql_user:
      login_unix_socket: /var/run/mysqld/mysqld.sock
      name: "{{ db_user }}"
      password: "{{ db_password }}"
      priv: '*.*:ALL'
      state: present
      host: '%'
  
  - name: Upgrade pip
    pip:
      name: pip==20.3.4

  - name: Install Python Flask dependency
    pip:
      name:
      - flask
      - flask-mysql
      state: present
    
  - name: Copy source code
    copy: src=app.py dest=/opt/app.py

  - name: Start Web Server
    shell: FLASK_APP=/opt/app.py nohup flask run --host=0.0.0.0 &

위 Playbook은 아래 Task를 순서대로 수행할 수 있게 작성하였다.

  1. Python 관련 패키지 설치
  2. MySQL 관련 패키지 설치
  3. MySQL 서비스 실행
  4. Database 'employee_db' 생성
  5. Database 사용자 'db_user' 생성
  6. PIP 최신버전 업데이트(수행하지 않으면 Flask를 정상적으로 받아오지 못함)
  7. Python Flask 설치
  8. app.py 소스코드 복사(Ansible Controller -> Host)
  9. 웹서버 실행

become 키워드를 통해 해당 Host의 root 또는 다른 계정으로 로그인할 수도 있다. 이번엔 패키지 설치 등의 Task를 수행해야 하므로, root 권한이 필요한 상황이다. 

vars 필드에 Playbook에서 사용할 변수를 Key:Value 형식으로 미리 정의해둔다. 이후 "{{ VAR_NAME }}" 과 같은 방식으로 Templating 할 수 있다.

 

이제 Playbook이 제대로 작성되었는지 확인하기 위해 ansible-playbook 명령어를 실행한다.

ansible-playbook playbook.yaml -i inventory.txt

위 명령어 실행시 아래와 같은 로그를 확인할 수 있다.

 

두 Host에 웹서버가 정상적으로 실행중인지 확인해볼 시간이다.

 

다음번엔 Ansible Playbook을 조금 더 세련된 구조로 바꿔보는 방법에 대해서 알아보겠다.

 

참고

Ansible Advanced - Hands-on - Devops

'IaC' 카테고리의 다른 글

Terraform - (3) Variables  (0) 2021.06.07
Terraform - (2) 기본 사용법  (0) 2021.06.06
Terraform - (1) 소개 및 설치  (0) 2021.03.29
Ansible - Playbook Tutorial(3/3)  (0) 2021.03.07
Ansible - Playbook Tutorial(2/3)  (0) 2021.03.06