LINE Corporation이 2023년 10월 1일부로 LY Corporation이 되었습니다. LY Corporation의 새로운 기술 블로그를 소개합니다. LY Corporation Tech Blog

Blog


프로비저닝 자동화를 위한 Ansible AWX, 설치부터 엔터프라이즈 환경 적용까지 - 1

이번 글에서 드리고 싶은 말씀

기업에서는 시스템을 운영하고 관리하기 위해 내부적으로 정의한 기술, 서비스 영역에 대해서 여러 정책과 기술 표준을 준비해 놓습니다. 이러한 정책을 인프라 환경(OS, 앱 설치, 튜닝 등)이나 개발 환경(코드 배포, 테스트 도구, 애플리케이션 설치 등)에 실질적으로 적용하기 위한 활동을 뭉뚱그려 프로비저닝(provisioning)이라고 표현하겠습니다. 프로비저닝을 실제로 구현하기 위해선 적절한 솔루션과, 인프라와 언어 등 다방면에서 확장 가능한 구조를 가지고 있어야 합니다. CI/CD(Continuous Integration and Continuous Delivery)를 프로비저닝하기 위해 많이 사용하는 Jenkins를 예로 들어보면, 개발자에게 익숙한 Tomcat WAS(인프라)에서 Jenkins(플랫폼)와 다양한 플러그인(확장)을 제공합니다. 

이때 영역에 따라 바라보는 시각이 조금 다릅니다. 영역을 DEV(development)와 OPS(information-technology operations)로 구분해 보면, DEV 입장에서 프로비저닝은 개발된 코드를 테스트하고 실제 서버에 배포한 후에 미들웨어(WAS 혹은 Node.js 등)를 재구동하고 서비스를 체크하는 일련의 과정으로 생각할 수 있겠습니다. OPS를 담당하는 엔지니어라면 OS 설치 후 네트워크 설정, 튜닝 적용, 필요한 인프라 소프트웨어 설치(각종 에이전트, JDK, NGINX, Tomcat 등)를 프로비저닝의 의미로 이해할 수 있습니다. 그런 면에서 Jenkins는 DEV의 시각에서 프로비저닝을 지원하는 플랫폼이라고 할 수 있습니다. Jenkins SSH 플러그인을 이용해 원격으로 셸(shell)을 수행하여 서비스를 재구동하는 것 같은 여러 작업을 구현할 수 있습니다. 하지만 여전히 셸 스크립트를 작성해야 하고, 각 OS에서 제공하는 여러 명령어에 대해 이해해야 합니다. 결국 언어 개발과 인프라 영역 사이에 간극이 존재하게 됩니다.  

이러한 간극을 좁히기 위해 정책적으로는 DevOps나 SRE(Service Reliability Engineering)라고 불리는 여러 활동이 시작되었고, 기술적으로는 셸보다 높은 수준의 언어(Python 등)를 적용하는 것과 같은 방법으로 '인프라가 어려운 개발 엔지니어'와 '언어가 어려운 인프라 엔지니어'의 음영 지역을 줄이기 위한 여러 가지 환경이 제안되었습니다. 그중에서 어느 정도 시장에 안착한 것으로 평가할 수 있는 게 Python 기반의 'Ansible'이라는 언어입니다.

이번 글에서는 이 Ansible이 주제인데요. 언어의 구문을 설명하고자 하는 것은 아닙니다. 언어 자체의 구현은 DEV 엔지니어 분들이 저보다 훨씬 잘합니다(고백하건대 저는 소프트웨어 엔지니어로 먹고살기에는 능력이 부족합니다. ㅠ.ㅠ). 대신 저는 이번 글에서 Ansible로 만들어진 프로비저닝 코드를 운영하기 위한 환경(플랫폼)을 지원하는 AWX(Ansible Worker)를 소개하고, 기업 환경에서 사용하기 위해 필요한 환경(권한 관리, 감사, 고가용성, 클러스터링 등)을 구축하면서 고민하고 공부했던 내용과, 진행중 겪었던 어려움을 여러분과 나누고자 합니다.

뜯어보기 

Ansible은 무엇인가요? 

Ansible은 셸과 같은 기존의 비정형 스크립트를 자동화 관점에서 기능을 모듈화(정형화)하여 쉽게 기능을 구현할 수 있도록 지원하는 언어로서, Python + YAML(YAML Ain't Markup Language) 포맷 기반으로 만들어진 자동화 언어입니다. 내부 구조가 Python이기는 하지만, Ansible 모듈을 직접 개발하지 않는 이상 Python 코딩을 할 필요는 없습니다. 구문이나 사용법은 인터넷에 훨씬 더 많은 정보가 있기 때문에 간략하게 정리하려고 합니다. 제가 말씀드리고 싶은 점은 두 가지 정도입니다. 

첫 번째로 쉽습니다. 보통 쉽다고 하는 언어들도 접근해 보면 난해한 부분과 마주치기 마련인데요. Ansible은 거의 스크립트 수준에서 작성할 수 있습니다. 물론 모듈의 종류나 기본적인 조건문, 권한 처리 등 기존에 없던 편의 기능을 사용하기 위한 기본적인 학습 비용은 발생합니다. 참고로, YAML의 들여쓰기 고통을 피하기 위해서는 IntelliJ, Eclipse 등의 IDE(Integrated Development Environment)에 Ansible 관련 플러그인을 추가해서 사용하는 것을 추천합니다.

두 번째로 직관적입니다. 이미 모듈화되어 있는 대부분의 기능을 사용하려고 할 때 입력 항목이 정의되어 있고 예제가 제공되기 때문에 큰 어려움 없이 사용할 수 있습니다. Ansible 모듈을 검색해 보면 이미 수많은 모듈이 준비되어 있는 걸 확인할 수 있습니다(참고). 또한 Ansible galaxy 사이트에는 우리가 일반적으로 상상할 수 있는 대부분의 시스템 작업에 대한 샘플이 존재합니다. 너무 많아서 나에게 맞는 것을 찾는 것이 일이 되곤 합니다만, 그래도 있는 게 훨씬 다행입니다.

Ansible을 사용하는 방법은?

처음 Ansible을 실행하기 위해 이해해야 하는 부분은 Ansible Ad-Hoc과 Playbook입니다. 단일 작업(task)을 수행하는 것을 Ad-Hoc Command라고 부르며, 예를 들어 아래와 같이 실행 가능합니다. 기본 옵션까지 다 표현해서 좀 길어 보입니다만, 실제 사용할 때는 생략할 수 있습니다. 다만 Ad-Hoc으로 여러 가지 작업을 수행하려면 여러 번 실행해야 합니다. 

#대상 서버의 서비스를 제어(재구동)하는 Ad-Hoc
Ansible testservers --check --inventory=hosts --user=normaluser --become --become-user="root" --become-method="sudo" --ask-become-pass --module-name=service --args="name=firewalld state=restarted"
#설명
 --check : test로 수행합니다. 실제 작업이 수행되지 않습니다
 --inventory=hosts : 작업 대상 서버의 목록이 들어 있는 파일의 위치입니다
 --user=normaluser --become --become-user="root" --become-method="sudo" --ask-become-pass  : 대상 서버에 normaluser 계정으로 SSH 접속을 합니다. become으로 root 권한을 획득하고, pasword를 물어봅니다.
 --args="name=firewalld state=restarted" : 방화벽 서비스(firewall)를 재구동합니다.

여러 가지 작업을 조합해서 실행해야 한다면 작업을 모아서 작성할 수도 있는데요. 이를 'playbook'이라고 부릅니다. 앞서 Ad-Hoc을 이용해서는 서비스만 재구동했다면, playbook을 이용하면 방화벽 정책을 반영한 뒤 재구동할 수 있습니다. 아래 예시를 보겠습니다.
Restart_Firewalld_Service.yml

# 작업 대상 서버를 지정하고, sudo를 사용하여 root로 권한을 승격합니다.
- hosts: target_list
  become: yes
  become_user: root
  become_method: sudo
 
#dns와 ntp 포트의 접속을 허용합니다.
  firewalld:
    service: {{ item }}
    permanent: yes
    state: enabled
  with_lines:
      - dns
      - ntp
 
#방화벽 서비스를 재구동합니다.
- name: Restart the firewalld daemon
  service:
    name: firewalld.service
    state: restarted

위 예시에서 'Role'에 대한 부분은 없으나, 하나의 작업을 위해 필요한 여러 작업(task)을 모아 놓은 playbook을 Role이라는 재사용 가능한 형태로 만든다고 이해하면 좋을 것 같습니다.

Playbook의 구조를 표현하면 아래 그림과 같습니다.

정리하면, Task로 이루어진 단일 yml 파일 또는 Role 구조(J2EE의 WAR와 같은 Ansible의 명세(specification))를 조합하여 만든 것을 playbook이라고 부릅니다. Playbook은 실행하는 명령어도 다릅니다.

# Restart_Firewalld_Service.yml  Playbook을 실행합니다.
Ansible-playbook --check --inventory=hosts Restart_Firewalld_Service.yml
 
 
#설명
 --check : test로 수행합니다. 실제 작업이 수행되지 않습니다
 --inventory=hosts : 작업 대상 서버의 목록이 들어 있는 파일의 위치입니다
Restart_Firewalld_Service.yml : 해당 playbook 파일을 실행합니다
 
 
!! 실행 user가 대상 서버들에 접속할 수 있도록 SSH pub key가 배포되어 있어야 하고, 실행하는 서버에 private key를 가지고 있어야 합니다. 옵션으로 SSH Key위치를 지정하거나 패스워드를 입력받을 수 있습니다.
!! 권한 변경을 위한 become이나 실행할 Inventory group 정보는 Playbook 내부에 정의되므로 별도로 옵션을 줄 필요는 없습니다

Ansible은 모듈을 조합하고 조건을 관리하는 언어일 뿐이고 작은 단위의 실행에서는 CLI(Command-line Interface) 형태(Ad-hoc)로 작업할 수 있지만, 기업에서 사용자 권한 설정, SCM(Source Control Management)도구 접속 관리, 병렬/분산 처리, 실행 결과 로그 등등의 필수적인 기능은 제공하지 않으므로 직접 구현해야 합니다. 기업에서 사용하기 위한 기능에서 일부는 안되고 일부는 번거롭게 구현해야 하는 형태라 이 부분을 지원하는 솔루션으로 Ansible Tower라는 제품을 Redhat에서 제공(판매)합니다.

AWX는 무엇인가요?

2015년에 앞서 이야기한 Ansible을 이끌던 Ansible, Inc(초기 회사명은 AnsibleWorks, Inc.)를 Red Hat에서 인수했습니다. Red Hat은 AnsibleWorks, Inc. 시절부터 개발된 Ansible Worker를 OSS(Open Source Software)로 공개하기로 하였고, 기존 소스의 패키지 이름인 awx를 사용하여 AWX Project가 시작되었습니다. 왜 이름이 'AWX'냐는 질문을 꽤 많이 접하는데요. 정확한 내용은 확인된 바 없습니다. 그저 기존의 회사 이름인 AnsibleWorks에서 모티브를 얻어 AWX로 정했다는 의견이 우세한 걸로 보입니다. 

단순하게 설명하면 Ansible Tower의 OSS(Open Source Software) 버전이 AWX입니다.

AWX 자체는 Ansible 언어를 운영하는 미들웨어의 성격입니다. Playbook이 없다면 할 수 있는 일은 거의 없습니다. 그래서 사실 중요한 것은 Ansible playbook을 개발하는 것입니다. AWX는 playbook을 관리하고 운영하는 데 필요한 여러 기능을 제공합니다.

JAVA를 예로 들면 CLI(Command Line Interface) 환경에서 바로 실행되도록 개발(독립 데몬(daemon) 형태)할 수도 있지만, 웹 서비스를 위해 WAR(Web Application Archive) 형태로 개발하여 Tomcat 등의 미들웨어 환경에서 운영할 수도 있습니다. Ansible 역시 CLI에서 직접 수행할 수 있지만, 여러 부가 기능과 권한 관리 등을 지원하기 위해 AWX에 Ansible 코드(playbook)를 등록하여 수행합니다.

기업에서 AWX를 사용해도 되나요? 

AWX는 Apache 2.0 라이선스를 따릅니다(참고). Apache 2.0에선 소스 수정 시 코드 공개를 강제하지 않습니다. 기업에서 사용하셔도 됩니다. 오히려 AWX를 이용하여 외부에 소스를 공개하거나 상용 솔루션 등을 만들 경우에 대해서 여러 조건 사항이 있으므로 그런 경우엔 확인할 필요가 있습니다. 특허와 관련해서 특허 보복 조항이 있기 때문에 소스를 대외에 공개하는 경우 라이선스에 주의해야 합니다.

AWX 프로젝트는 공개되어 있으며 Git에서 다운로드하여 설치한 뒤 사용할 수 있습니다. 다만 기업에서 사용하려면 일부 설치 코드를 직접 조정해야 할 수 있습니다. 이러한 부분은 고가용성(high availability) 등을 요구하는 환경에서 필요하며, 단순히 단일 노드로 운영하기 위한 설치는 어렵지 않습니다.  

씹어보기

AWX - Standalone 설치해보기

  • AWX 관련 참조 URL은 아래와 같습니다.
  • 요구 및 제한 사항 
    • 서버 자원은 CPU 4 코어 이상, 메모리 8GB 이상을 추천하며 OS는 CentOS 7을 기준으로 설명합니다.
    • AWX는 상용 버전인 Ansible Tower와 같은 단독 설치가 지원되지 않습니다. Docker 기반으로 설치되며 Docker Compose, Kubernetes, OpenShift 환경을 지원합니다. Ansible을 사용하기 위해 Kubernetes를 구축하거나 OpenShift를 구매하는 것은 뭔가 앞뒤가 맞지 않습니다. 따라서 이 글에서도 Docker Compose 환경에서 설치하는 것에 한하여 소개합니다.
    • Docker registry에 접속할 수 있도록 인터넷 연결이 가능해야 합니다. 인터넷이 차단된 환경이라면 AWX 위키를 참고하여 RPM 설치 버전을 사용하거나, Docker 이미지를 모두 다운로드해서 로컬 환경에 Docker Hub 같이 구성해서 설치할 수 있습니다. 참고로 인터넷 접속이 불가한 환경에선 이 문서에서 설명하는 항목 중 일부 내용이 다르거나, 추가 설정이 필요할 수 있습니다.
  • 개괄적인 설치 설명
    • Git에서 소스를 클론(clone)합니다. AWX 8.0.0 버전이 기준입니다. 이때 특정 버전을 지정할 수 있고, 지정하지 않으면 최신 버전을 설치하게 됩니다. 버전을 변경하는 경우 아래에서 설명할 설정에 차이가 있을 수 있습니다. 예를 들어 4.0.0 버전을 설치하려면 'dockerhub_version=4.0.0'을 inventory 파일에 명시적으로 정의해야 합니다. 8.0.0 버전은 클론한 소스에 있는 'VERSION' 파일의 내용을 읽어서 자동으로 설치합니다. 기타 등등 상용 소프트웨어에 비해 조금 불편할 수 있는 오픈소스의 특성 때문에 버전 변경에 따른 변수가 다수 있습니다.
    • 설치하기 전에 서버에 Ansible, Python, Docker Compose를 미리 설치해 놓아야 합니다.
    • Docker Compose를 이용해 Docker 이미지에 필요한 설정을 수정하고 추가하게 되는데요. 이 작업도 Ansible playbook으로 작성되어 있습니다.
    • WEB, TASK, MQ, Cache, DB로 구성된 총 5개의 Docker 컨테이너가 하나의 서버에서 구동됩니다. DB는 별도 서버에 구축하여 고가용성을 구성할 수 있으나 AWX에서 지원하지 않으므로 직접 구성해야 합니다. 이 글에서 AWX HA를 구성하기 위해 모든 항목과 DB(PostgreSQL) HA 구성을 자세하게 설명하기에는 어려움이 있는 점, 양해 부탁드립니다.
    • AWX의 PostgreSQL은 9.x 버전으로 설치되어 있으나, CentOS 7에서 10.9 버전(RPM 설치) 정상 동작이 확인되었습니다.
    • DB 고가용성 도구는 PGPOOL을 참고하세요.
  • 설치하기
    1. 1. yum 저장소 리포지터리 추가 
      # ADD EPEL Repository (root)
      yum -y install epel-release
       
      # ADD Docker-compose Repository
      yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    2. Ansible, Python PIP 설치
      # Install Ansible and python-pip
      yum -y install Ansible python-pip
      # PIP upgrade
      pip install --upgrade pip
    3. Docker 서비스 관련 설치
      # Install docker-compose  (root)
      yum -y install docker-ce
       
      # Auto start docker service
      systemctl enable docker
       
      # Start Docker service
      systemctl start docker
       
      # Install python docker-compose package 
      pip install docker-compose --ignore-installed
    4. AWX 소스 복제 및 설치(설정 변경이 필요한 경우 다음 항목을 먼저 확인)
      아래 명령어를 참고하여 실행하면 별다른 내용 없이 자동으로 설치되고 Docker 기동까지 마무리됩니다. 만약 특정 버전을 설치하고 싶거나, DB 데이터 저장 위치 변경 등이 필요한 경우 다음 항목(2.AWX 설치 구성 정보 변경)을 확인해서 필요한 부분을 수정한 다음 설치를 진행하기 바랍니다. 물론 설치 후에도 구성을 변경하여 다시 설치할 수 있습니다. DB 데이터만 유지된다면 여러 차례 재설치해도 AWX 설정은 유실되지 않습니다.
      # Make working directory  (root)
      mkdir /work
      cd /work
       
      # Source 복제 
      git clone https://github.com/Ansible/awx.git
       
      # Running Install Playbook
      cd /work/awx/installer
      Ansible-playbook -i inventory install.yml

      실행 시 아래 사항을 참고하시기 바랍니다.
      • playbook 실행 시 한참을 멈춰서 있을 수 있습니다. 설치 후 기동 중이므로 인내심을 갖고 기다려 주세요. 서버 성능에 따라 다릅니다.
        TASK [local_docker : Start the containers] ..........
      • 정상 완료되면 failed 항목이 0이어야 합니다(skipped는 무관합니다).
        ....
        PLAY RECAP **********************************************************************************************************************************
        localhost                  : ok=14   changed=3    unreachable=0    failed=0    skipped=83   rescued=0    ignored=0   
      • Docker 사용법이 익숙하지 않더라도 몇 가지 명령어는 익혀 놓는 것이 좋습니다.
        • 구동된 컨테이너 정보 확인 : docker ps
        • 컨테이너 중지 : docker stop ${container_name}
        • 컨테이너 시작 : docker start ${container_name}
        • 컨테이너 접속 : docker exec -it ${container_name} /bin/bash
          (bash 셸을 실행하여 내부에 접근)
        • container log : docker logs -f ${container_name}
          (log를 tail -f 형태로 보여줍니다. 실제 로그 파일은 /var/lib/docker/containers/ 아래 container ID 아래에 저장되어 있습니다.) /var/lib/docker/containers/ /lib/docker/containers/
      • 정상 설치되면 아래와 같이 확인 가능합니다.
        [root@server:/work]# docker ps
        CONTAINER ID        IMAGE                        COMMAND                  CREATED             STATUS              PORTS                                                 NAMES
        cd5dd1ad7313        Ansible/awx_task:8.0.0       "/tini -- /bin/sh -c…"   45 seconds ago      Up 43 seconds       8052/tcp                                              awx_task
        849ac1be4e0e        Ansible/awx_web:8.0.0        "/tini -- /bin/sh -c…"   46 seconds ago      Up 44 seconds       0.0.0.0:80->8052/tcp                                  awx_web
        f6c3f2425cc6        Ansible/awx_rabbitmq:3.7.4   "docker-entrypoint.s…"   48 seconds ago      Up 45 seconds       4369/tcp, 5671-5672/tcp, 15671-15672/tcp, 25672/tcp   awx_rabbitmq
        441286ffed88        postgres:10                  "docker-entrypoint.s…"   48 seconds ago      Up 45 seconds       5432/tcp                                              awx_postgres
        42c58bc7bc1b        memcached:alpine             "docker-entrypoint.s…"   48 seconds ago      Up 45 seconds       11211/tcp                                             awx_memcached
    1. 접속하여 확인하기
      설치가 완료되면 웹 브라우저로 접속합니다. 설치가 완료되어도 컨테이너 구동 시간과 초기 DB 구성을 위해 약 2~3분이 소요됩니다(서버 성능에 따라 다릅니다).

      • 접속 URL : http://SERVER_IP
      • 초기 계정 : admin / password
      • 정상 로그인 화면(설치 후 바로 접속하면 이 화면이 아니라 업그레이드 중이라는 화면이 나올 수 있는데 잠시 기다리시면 됩니다)
      • 메인 화면

AWX 설치 구성 정보 변경

AWX 설치 시 필요한 환경 정보는 install playbook이 위치한 디렉터리 내 inventory 파일 안에 정의되어 있습니다. 아래는 주요 환경 설정 항목의 의미와 설정 방법입니다. 해당 파일(/work/awx/installer/inventory)을 적절히 수정하면 됩니다.

  • Git 클론 시에 특정 버전 지정 
    !! 특정 버전을 설치하기 위해서는 git -b 옵션을 사용합니다. 지정하지 않으면 최신 버전으로 설치됩니다.
    !! AWX Git Project는 tag로 관리되므로 버전은 tag 명을 확인하세요.
    git clone -b 8.0.0 https://github.com/Ansible/awx.git
  • DB 저장 위치 변경
    AWX는 내부적으로 PostgreSQL을 DB로 사용합니다. 해당 DB가 컨테이너로 구동되기 때문에 내부에 저장할 수 없으므로 설치하는 서버의 로컬 디스크 어딘가에 저장하게 됩니다. 8.0.0 버전의 경우 기본 위치가 설치 계정 아래 생성된 숨김 폴더입니다. 테스트 설치 시에는 그냥 설치해도 별 문제가 없으나 지속적인 운영이 목적이라면 충분한 용량이 확보된 저장 위치를 지정해야 합니다.
    # Default DB data path
    postgres_data_dir="~/.awx/pgdocker"
     
    exam)
    postgres_data_dir=/work/pgdata
  • HTTP/HTTPS 포트 변경 
    AWX는 웹 기반의 GUI 환경입니다. HTTP와 HTTPS 접속을 지원합니다. 보안이나 여타 다른 이유로 포트 번호를 바꾸고 싶다면 해당 정보를 변경합니다. HTTPS는 'ssl_certificate' 설정이 활성화되어야 지원됩니다.
    # Default Port
    host_port=80
    host_port_ssl=443
  • SSL 접속 활성화와 SSL 인증서 파일 위치 지정  
    SSL 접속을 지원하기 위해서는 인증서(SSL Certification) 파일이 있어야 합니다. 인증서는 가능하면 각자 구입한 공인 인증서를 사용하면 좋겠지만, 테스트를 위해서는 사설 인증서를 생성하여 사용할 수도 있습니다. 기본적으로 해당 항목은 주석 처리되어 있는데요. 설정하지 않으면 SSL 포트를 지정해도 SSL 접속이 활성화되지 않습니다. 고급 사용자는 /work/awx/installer/roles/local_docker/templates/nginx.conf.j2에 위치한 템플릿 파일을 참고하면 어떻게 구성되어 있는지 이해하는 데 도움이 됩니다. 주석을 제거하고 SSL 인증서를 넣어둘 경로를 입력합니다.
    SSL 인증서 파일의 이름은 내부적으로 'awxweb.pem'으로 고정되어 있으므로 지정하지 않도록 주의하세요.

    # Default SSL Cert file path
    #ssl_certificate=
     
    exam)
    ssl_certificate=/work/ssl_cert
  • PEM 파일 만들기(인증서가 crt와 key로 분리되어 있을 경우) 
    일반적으로 SSL 인증서를 구입하면 확장자가 crt인 파일과 key인 파일을 받게 됩니다. AWX 설치 시 내부 웹 서버는 NGINX를 사용하며, 기본 구성이 각 파일을 등록하는 것이 아니라 pem(X.509) 파일 하나로 만들어서 사용하게 되어 있습니다. pem 파일은 crt와 key를 하나의 파일로 만들어서 확장자 이름만 pem으로 만들면 됩니다. AWX NGINX 구성 파일 안에 고정되어 있으므로 파일 명은 'awxweb.pem'으로 유지해야 합니다. 생성한 파일은 'ssl_certificate='에서 지정한 폴더에 넣습니다. 아래 내용을 참고하시기 바랍니다.
    yckwon@yckwon-Desktop /xxxx/yckwon/download/SSL_Cert/linecorp.com $ ls -lrt
    -rw------- 1 yckwon yckwon  xxxx  x월 28 04:52 *.linecorp.com_fullchain_cross.crt
    -rw------- 1 yckwon yckwon  xxxx  x월 28 04:52 *.linecorp.com_fullchain.crt
    -rw------- 1 yckwon yckwon  xxxx  x월 28 04:52 *.linecorp.com_chain_cross.crt
    -rw------- 1 yckwon yckwon  xxxx  x월 28 04:52 *.linecorp.com_chain.crt
    -rw------- 1 yckwon yckwon  xxxx  x월 28 04:52 *.linecorp.com.key
    -rw------- 1 yckwon yckwon  xxxx  x월 28 04:52 *.linecorp.com.crt
      
      
    cat *.linecorp.com.key *.linecorp.com.crt > awxweb.pem
    cp awxweb.pem ${ssl_certificate}
    chmod 644 ${ssl_certificate}/awxweb.pem
  • 프로젝트(Git에서 클론한 Ansbile 코드) 저장 위치
    AWX의 내부 동작을 조금 살펴보면, playbook을 수행하기 전에 첫 번째로 Git에서 Ansible 코드(Playbook)를 클론하여 로컬에 저장하고, 저장한 playbook을 수행합니다. 이때 클론한 파일의 저장 위치를 별도로 지정할 수 있습니다. Git을 사용하는 기업이라면 별도로 직접 수정할 필요가 없습니다. 하지만 Git이 없거나, 로컬에 직접 playbook을 작성하거나 업로드하려는 경우엔 기본 위치를 변경하기도 합니다. 저장소는 가능한 임시라도 GitHub에 계정을 만들어 작업하는 것을 권장합니다. 회사에 GitHub이 없다면 오픈소스인 GitLab을 설치해서 사용해도 됩니다.

    AWX의 프로젝트란?
    AWX 기능 중에 프로젝트라는 항목이 있습니다. AWX는 여러 가지의 SCM(Source Code Manager)을 지원합니다. SVN, Git 등이 대표적인데요. 이 글에서는 Git을 중심으로 설명하고 있습니다. 쉽게 설명하면 'Git의 프로젝트'와 같다고 생각하시면 됩니다. AWX는 playbook을 실행하기 전에 Git의 프로젝트를 다운로드하여 지정한 playbook을 실행하게 됩니다.

    # Default project store path
    #project_data_dir=/var/lib/awx/projects
     
    example) git에서 클론한 파일들이 임의의 번호를 부여받고 자동으로 생성됩니다.
    [user@server /work/awx/projects]$ ls
    _16__10line_square_server_project15104_pm       _30__hadoop_ops_gittasuku_okuda            _7__0square_project
    _16__10line_square_server_project15104_pm.lock  _30__hadoop_ops_gittasuku_okuda.lock       _7__0square_project.lock
    _19__iu_deploy_git                              _40__99nopd_project                        _78__yckwon_Ansible_pjt
    _19__iu_deploy_git.lock                         _40__99nopd_project.lock                   _78__yckwon_Ansible_pjt.lock
    ...
     
    ...

맛보기

AWX Playbook 실행 구조

AWX는 자체적으로는 자동화를 하는 도구가 아닙니다. 자동화를 위해 개발된 Ansible 코드를 기업에서 사용할 수 있도록 도와주는 환경(플랫폼)을 제공하는 개념입니다. 그래서 AWX가 제공하는 기능들은 개발된 Ansible 코드를 실행하기 위해 목록을 관리하거나, 계정을 등록하고, SCM 정보를 등록하여 마지막에는 작업을 실제로 수행하는 템플릿(template)을 생성하는 데 그 목적이 있습니다. 

AWX UI 소개

Playbook을 등록하고 수행하기 위해서는 몇 가지 자원(템플릿을 구성하기 위한 설정들)을 추가해야 합니다. UI에선 Ansible playbook을 실행하기 위한 기능 말고도 로깅과 로그인 통합, 권한 관리, 작업 연결(pipelining), 일정에 따른 작업 수행(cron job 같은) 등의 여러 가지 부수적인 기능을 수행할 수 있으나, 여기서는 playbook을 수행하기 위한 몇 가지 필수 항목만 설명하겠습니다. 

  • Credentials
    • 대상에 접근하기 위한 권한을 등록합니다.
    • 접근의 대상은 서버가 될 수도 있고, GitHub이 될 수도 있습니다. 일반적으로 서버 접근을 위한 SSH private key나 비밀번호를 등록해서 내용은 노출하지 않으면서 권한이 있는 사용자가 사용할 수 있도록 합니다.
    • 지원하는 접근 대상의 전체 목록은 Ansible Tower 매뉴얼에서 확인할 수 있습니다(AWX는 별도 매뉴얼이 없습니다).
  • Projects
    • SCM, 즉 Git이나 SVN에서 보통 서비스 단위로 사용되는 프로젝트를 관리합니다. 
    • Git을 예로 들면, Git에 로그인하기 위한 credential을 만들고 프로젝트와 연결하여 Git에서 소스를 클론합니다.

  • Inventories
    • 작업할 대상 서버의 목록입니다. IP나 IP 룩업(lookup)이 가능한 호스트 명을 목록으로 관리합니다.
    • 서버를 하나하나 나열할 수도 있고, 그룹 단위로도 관리할 수 있으며, 그룹 안에 그룹을 포함할 수도 있습니다. 
    • 서버 이름이 연속으로 이어지는 것과 같은 경우엔 패턴을 사용하여 등록할 수 있습니다(참고).
    • Ansible을 직접 사용할 때는 hosts 파일을 만들어서 관리하지만, AWX에서 여러 가지 소스를 사용하여 목록 작성을 지원합니다. 예를 들어 Python 코드를 사용하여 json이나 yaml을 파싱할 수 있습니다(서버 목록을 관리하는 서버가 있다면 API로 호출해서 인벤토리로 작성할 수 있습니다). 그 외에도 소스로 사용할 수 있는 다양한 형식이 있습니다(참고).
  • Templates
    • Inventories 목록의 서버에 대해 credential로 접근 권한을 얻어서 프로젝트에 있는 playbook을 실행합니다.
    • 템플릿을 만들기 위해서는 앞서 말씀드린 3개 항목을 먼저 등록해야 하는데요. 그 때문에 AWX를 처음 접하게 되면 어떻게 사용해야 하는지 많이 고민하게 됩니다.
    • 순서대로 각 항목을 작성했다면 템플릿에서 해당 정보를 조합하여 동작합니다. 

AWX에 프로젝트 등록해서 실행하기: 기본 사용법 

Credential 등록(SSH private key 등록)

  1. Credentials 메뉴 → + 버튼 클릭 → CREDENTIAL TYPE에서 Machine 선택 → USERNAME에 접속 계정 입력 → SSH PRIVATE KEY에 붙여 넣기 → 저장 
  2. SSH 키로 접속하는 경우 비밀번호 입력은 필요 없습니다(키 또는 비밀번호 중에서 하나를 선택해서 사용합니다).

SSH private key와 비밀번호는 한 번 저장하면 암호화되어 다시 확인할 수 없습니다. 키 관리에 주의하시기 바랍니다. 

  1. 프로젝트 등록(Git 등록)
    1. Projects 메뉴 → + 버튼 클릭 → SCM TYPE에서 Git 선택 → SCM URL 입력 → SCM BRANCH/TAG/COMMIT에 브랜치/태그 입력 → 저장 → 동기화(Git 클론)
    2. 프로젝트를 생성하면 반드시 우측의 화살표 마크를 클릭하여 정상적으로 동기화되는지 확인합니다. 동기화되지 않으면 AWX 서버에 playbook 파일이 생성되지 않고, 템플릿 작성 시 playbook을 등록할 수 없습니다.
  2. 인벤토리 등록(GUI 수동 등록 예)
    1. Inventories 메뉴 → + 버튼 클릭 → NAME 입력 →  HOSTS 버튼 클릭 → + 버튼 클릭 → HOST NAME에 IP 또는 룩업 가능한 호스트 명 입력 → 저장
  3. 템플릿 작성
    1. Templates 메뉴 →  + 버튼 클릭 → Job Template 선택 → 앞서 작성한 인벤토리, 프로젝트, Credential 선택 → PLAYBOOK에서 앞서 작성한 playbook 선택 → 저장
    2. 여러 항목이 있지만 입력하지 않으면 자동으로 기본 설정이 반영되므로 필수 항목만 설명하였습니다.
    3. Playbook 선택 목록이 나오지 않는다면 프로젝트가 잘못 생성되었거나 동기화가 안 된 경우입니다.

사용팁 

  • 각 선택 항목 위에 PROMPT ON LAUNCH 체크 박스가 있습니다. 이 체크 박스를 선택하면 템플릿 실행 시 다시 선택할 수 있는 팝업 창이 나타납니다.
  • JOB TYPE 
    • Run: 템플릿을 실행하면 실제 서버에 작업을 수행합니다.
    • Check: 실제 작업을 수행하지 않고 playbook을 테스트합니다. 
  • VERBOSITY
    • 로그의 상세 정도를 변경합니다.
    • 1(Verbose) 정도가 적당합니다. 디버그를 위해서 3 또는 4를 선택하면 Ansible의 내부 수행 내용 전체가 출력되는데요. 출력되는 내용이 너무 많아서 보기가 조금 어렵습니다. 
  • FORKS
    • 인벤토리에 저장된 여러 대의 서버에 동시에 작업을 실행하므로 이때 몇 개의 프로세스를 구동해서 작업할 것인지 숫자로 입력합니다.
    • 프로세스가 많을수록 동시에 여러 대의 서버에 작업이 가능하므로 작업 시간이 빨라집니다.
    • 기본적으로 5 fork이며, 4 CPU 서버에서 30 fork 정도까지 가능합니다. CPU를 얼마나 점유하느냐는 playbook 작업의 복잡도에 따라 달라서 숫자를 정확하게 정의하는 건 어렵습니다. 적당한 숫자로 설정해서 AWX 서버의 CPU 사용량을 보면서 조정하면 됩니다. 
    • 더 큰 FORKS를 설정하기 위해선 아래와 같은 방법을 사용합니다.
      • Scale up: 서버의 CPU 개수를 늘립니다.
      • Scale down: AWX 서버를 여러 개 설치하여 클러스터를 구성합니다.  
  • Instance Groups(클러스터) 
    • 수백에서 수천 대의 서버에 동시에 작업하기 위해서는 다수의 fork가 가능해야 합니다.
    • AWX는 내부 MQ를 사용하여 여러 AWX 서버에 작업을 분배하여 동시에 다수의 서버에 병렬로 작업을 실행할 수 있도록 클러스터 구성을 지원합니다. 
    • 다만, 기본 AWX 설치에서는 클러스터 구성을 지원하지 않습니다. 내용이 길어져서 좀 더 상세한 내용은 다음 편에 추가로 설명을 드리도록 하겠습니다.  
    • 아래는 실제 클러스터 구성 화면입니다.
      • Instance Group이라고 부릅니다.
      • Instance Group에는 여러 대의 AWX 서버가 등록됩니다.
      • 템플릿 작성 시 Instance Group을 선택하면 해당 작업은 Instance Group 내의 AWX 서버들이 1/N로 작업을 나누어 수행합니다.

2부로 이어집니다!

1부에서는 Ansible 과 AWX를 소개하고 기본적인 설치와 설치 시 설정 항목에 대해 설명했습니다. 인터넷에 설치 정보가 있기는 하지만 설명이 너무 간략하고 실제 구성을 하기 위한 정보가 부족하다고 생각해서 중복되는 내용이지만 좀 길게 설명을 드리게 되었습니다. 2부에서는 LINE에서 실제 운영하기 위해 구성한 고가용성 환경에 대한 소개와 구축 시 참고할 만한 내용에 대해 좀 더 소개하겠습니다. 기대해 주시기 바랍니다.