ansible playbook은 task를 실행하는 ansible의 실행 모듈이다. 플레이모듈은 YAML파일 형태로 포매팅되어 playbook의 collection 내부 모듈의 실행 로직과 문법에 따라 피제어노드에 명령을 전달한다.

playbook은 모듈 단위 작업인 task와 task의 집합 작업인 play로 구분된다. play는 하위 task들이 실행될 노드, 사용자 등등 큰 프레임을 고정시키고, 하위 task에서 상세한 작업을 실행하는 것이다.

ansible-playbook의 기초 문법은 다음과 같다.

ansible-playbook -i INVENTORY [optional] PLAYBOOK

INVENTORY: 미리 정의해놓은 인벤토리 파일
PLAYBOOK: 이제 알게 될 업무 지시 파일

 

PLAYBOOK 작성

---
- name: practice
  become: true
  hosts: all
  tasks:
          - name: practice playbook
            module: value

위에서 보는 것이 playbook의 기초 모형이다. name, become, hosts, tasks의 4개가 리스트로 묶여 playbook을 형성한다. name은 해당 play의 이름, become은 특정 사용자로 로그인할것인지, 아닌지를 결정한다. 만약 다른 유저로 로그인하고싶다면 become과 같은 depth에서 become_user: USER를 정의해주면 된다. hosts는 해당 tasks 이하가 실행될 노드들을 결정하는데, all이면 인벤토리에서 정의된 모든 노드들을 의미하고, 저번 포스트에 작성했던 것처럼 group을 참조하면([group]: node1 node2) node1 node2에서만 실행된다.

tasks의 하위 리스트인 name은 해당 모듈이 실행될 때 task의 이름을, module 및 value에는 실행할 모듈과 모듈에 넣을 값들을 집어넣어준다.

이제 기초는 알았으니 직접 playbook을 작성해보자.

개발환경

- Container with docker 19.06.3
- ansible 2.11.0
- python 3.8.0
- SSH
- pip3 install flask

제어 노드
ansible

피제어 노드
node1
node2
node3
node4
- name: practice
  become: false
  hosts: all
  tasks:
          - name: create folder
            ansible.builtin.command:
                    cmd: mkdir /root/from-ansible
                    creates: /root/from-ansible
          - name: config file
            ansible.builtin.shell: |-
                  cat << EOF > /root/config.file
                  this is configuration file
                  EOF

그렇게 복잡하지 않은 playbook이다. play의 이름은 practice(name: practice)고 모든 호스트에서 실행(hosts: all)한다. 하위 tasks들의 이름은 create folder와 config file이고, ansible.builtin.command 모듈과 ansible.builtin.shell 모듈을 사용한다.(둘다 builtin 모듈이므로 그냥 command, shell만 써도 동작하지만, 처음이니까 그냥 풀네임으로 작성했다)

command 모듈은 cmd: 에 적힌 명령을 실행하는데, 만약 /root/from-ansible 경로가 이미 존재할 경우 해당 페이즈를 스킵한다(만약 creates를 주지 않고 cmd 값만 부여한 상태로 /root/from-ansible경로가 존재하면 에러가 나며 playbook이 중단된다)

shell 모듈은 아래에 적힌 모듈을 shell(/bin/sh) 모듈로 실행하는데, command와 유사하다. 다만 차이점은 command는 각종 shell 연산자들(<, >, |, ||, && 등)을 수행할 수 없지만, shell 모듈은 수행할 수 있다는 것이다. 어쨌든, shell cat ~으로 config.file에 "this is configuration file"이란 내용을 작성하는 task다.

그럼 직접 실행해보자.

# vim hosts.ini
node1   ansible_host=172.31.0.21 ansible_user=root
node2   ansible_host=172.31.0.22 ansible_user=root
node3   ansible_host=172.31.0.23 ansible_user=root
node4   ansible_host=172.31.0.24 ansible_user=root

[server]
node1
node3

[client]
node2
node4

실행은 잘 됐는데...WARNING이 떴다.

실행은 순조롭다. 다만 WARNING이 하나 등장했는데, 보니 command 모듈로 mkdir을 실행하지 말고 file 모듈의 state=directory의 사용을 권장하는 이야기다. 뭔가 내부 모듈의 호환성이나 곧 DESCRETE될 수도 있는 기능인가보다. 뭐 WARNING이므로 실행 및 결과에는 문제가 없으므로 일단 패스.

또한 더 많은 모듈에 대한 정보는 ansible의 공식 Docs에 있다.
https://docs.ansible.com/ansible/latest/collections/ansible/index.html

 

Collections in the Ansible Namespace — Ansible Documentation

© Copyright Ansible project contributors. Last updated on May 19, 2021.

docs.ansible.com

이것으로 ansible의 기초중의 기초를 마쳤다. 다음엔 좀 더 본격적인 ansible 활용으로 들어가보자.

'DevOps > ansible' 카테고리의 다른 글

ansible 기초/설치하기  (0) 2021.05.31

ansible은 terraform과 함께 대표적인 DevOps 툴이다. 하지만 terraform이 많은 서버들을 Orchestration 하기 위한 도구라면, ansible은 서버마다 대상 및 변수를 지정해 configuration을 하기에 적합하다. 물론 terraform으로 서버 management가 불가능한 것은 아니고, ansible로 서버 orcehstration을 못하는 것도 아니지만(필자는 두 경우 모두 앤서블을 더 애용한다) 각자의 본래 용도에 맞게 쓰는 것이 더 편하고 좋은 효과를 낼 뿐이다.

reference_from: https://npd-58.tistory.com/28
* ansible 및 terraform에 대해 비교한, 아주 좋은 article이다. ansible을 시작하려는 초보자에게 정말 유용한 글이니, 꼭 읽어보는 것을 추천.

 

[기사 번역]Terraform vs Ansible?? 어떤 것을 써야할까?

Terraform vs Ansible, Ansible vs Terrafom- 구글에서 자주 검색되는 질문들입니다. 그러나 이게 맞는 말일까요? Terraform과 ansible이 경쟁 관계에 있고 우리는 둘 중 하나만 사용할 수 있을까요? 아니면 사실..

npd-58.tistory.com

 

ansible은 python3로 작동한다. 2021년 5월 31일 기준 ansible-core 2.11이 최신 버전인데, 파이썬 3.8 버전을 요구한다.

이게 무슨 뜻을 의미하느냐? 우리가 개인 프로젝트 및 프로덕션 레벨에서 호환성이 좋아 많이들 사용하는 Ubuntu:18.04 버전에서는 따로 python을 설치해야만 한다는 뜻이다.(Ubuntu 18.04에서 제공하는 기본 파이썬은 3.6.9버전)

ansible 구조

- server-client 형태
- SSH 데몬이 각 노드간 통신을 담당하는 agent역할

ansible의 구성 요소

ansible은 inventory, playbook의 2가지로 구성된다. inventory는 ansible의 명령이 향하는 제어 대상을 정의한 *.ini 파일이고, playbook은 ansible의 명령이 담긴 *.yaml 파일이다. YAML파일에 대해서는 아래의 링크에 기초 문법이 잘 설명되어있으므로 꼭!!! 참고하도록 하자. XML, JSON같은 기존의 데이터 템플릿보다는 작성이 편하지만, 그만큼 헷갈리는 부분이 많으니 주의가 필요하다
https://subicura.com/k8s/prepare/yaml.html#%E1%84%80%E1%85%B5%E1%84%87%E1%85%A9%E1%86%AB%E1%84%86%E1%85%AE%E1%86%AB%E1%84%87%E1%85%A5%E1%86%B8

 

YAML 문법

YAML 문법에 대해 전반적으로 알아봅니다.

subicura.com

그럼 ansible 인스톨을 시작하도록 하자.

 

개발 환경

Host
- container with Docker 19.03.6

Master node
- ip: 172.31.0.10
- ssh
- python3.8
- vim, iputils-ping, net-tools, software-properties-common
- ansible

Worker node(node 1~4)
- ip: 172.31.0.11~14
- ssh

 

컨테이너 생성

먼저 호스트에서 컨테이너를 생성한다.

docker run \
-dit
--hostname ansible \
--name ansible \
--network ansible \
--ip 172.31.0.10 \
-w /root \
ubuntu:18.04

위의 형식에서 ip 및 name, hostname만 바꿔주는 형태로 나머지 제어 대상 노드들(node 1~4)까지 생성해준다.

컨테이너 내부 환경 구성

# in master
apt update && apt install -y vim ssh
apt install -y software-properties-common
add-apt-repository --yes --update ppa:ansible/ansible
apt update
apt install -y python3.8

# in worker
apt update && apt install -y ssh vim

 

한가지 주의할 점은, SSH를 설치하기 전 미리 python3.8을 설치할 경우, SSH가 설치되지 않는다(컨테이너 환경 기준).

아까 ansible은 SSH를 Agent로 삼아 통신을 한다고 했었다. 그럼 당연히 각 서버의 DNS도 찾아서 설정해줘야 한다.

# vim /etc/hosts
172.31.0.10 ansible
172.31.0.11 node1
172.31.0.12 node2
172.31.0.13 node3
172.31.0.14 node4

어차피 이 모든 서버들의 ip를 알아야 하는 건 서버 노드 뿐이므로 클라이언트 노드들에서까지 이 작업을 해줄 필요는 없다(만약 클라이언트끼리의 통신이 필요하지 않은 어플리케이션이라면).

DNS 설정이 끝났으면 클라이언트 노드에서 SSH 설정을 바꿔준다. 컨테이너 환경에서 실행시 기본 사용자는 root로 설정되어 있는데, SSH 통신의 경우 아무런 설정을 해주지 않으면 root 사용자로 로그인은 금지되어있으므로 root로그인을 풀어주면서 덤으로 22번 포트도 공식적으로 개방해준다.

# vim /etc/ssh/sshd_config
Port 22
PermitRootLogin yes
service ssh start

이대로 끝나면 참 좋은데, ansible은 스스로 priority가 1로 설정된 로컬 인터프리터를 찾아가므로 따로 설정을 해줘야 한다.

로컬 default 파이썬 버전을 3.8로 변경

which python3
# example: /usr/bin/python3

which python3.8
# example: /usr/bin/python3.8

update-alternatives --config python3
# 여기서 python3가 가리키는 대상을 찾는다.
# 아마 아무것도 설정되어있지 않거나, python3.6을 대상으로 가리킬 것이다.
# example: update-alternatives: error: no alternatives for python3

update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8
# 이 명령을 실행하면 기준 python3 -> python3.6으로 지정된 파이썬의 대상 경로가
# python 3.8로 변경된다.

python3 --version
# python 3.8.0

이제 ansible을 설치하면 끝.

apt install -y ansible

 

이제 ansible이 제대로 실행되는지 테스트를 시작하기 위한 준비를 시작해보자.

# vim hosts.ini
node1 ansible_host=172.31.0.11 ansible_user=root
node2 ansible_host=172.31.0.12 ansible_user=root
node3 ansible_host=172.31.0.13 ansible_user=root
node4 ansible_host=172.31.0.14 ansible_user=root

[group]
node1
node2

hosts.ini 파일이 바로 인벤토리 파일이다. 가장 윗줄에 ansible이 제어할 모든 대상 노드를 집어넣는다. 가장 앞에는 각 노드의 alias를 적는데, alias는 hosts.ini 파일 내부와 playbook에서 참조하는 파일명이므로 되도록이면 DNS와 같게 설정해주자. ansible_host는 대상 노드의 ip를, ansible_user는 대상 사용자의 계정명을 적어주는데, 컨테이너 내부에선 어차피 모두 root 사용자여서 빼버려도 연결은 가능했었다.

아래의 group에 대해서는 playbook을 설명하면서 다시 설명.

이제 inventory를 만들었으니 ansible-core에 내장된 builtin 모듈을 사용해 모든 노드가 잘 연결이 되었는지 테스트를 해보자.

ansible -m ping -i hosts.ini all

ansible 내장 모듈은 playbook으로 task.yaml을 선언하지 않고도 바로 실행할 수 있다. 종류는 무척 적으니, 내장 모듈은 테스트 용으로만 사용하도록 하자.

ansible_facts를 보면 /usr/bin/python3를 자동으로 찾아가는 것을 볼 수 있다.

성공! 이제 ansible을 사용하기 위한 기본 바탕은 마련되었다.

'DevOps > ansible' 카테고리의 다른 글

ansible playbook 기초  (0) 2021.05.31

+ Recent posts