카샤의 만개시기

앤서블 1.9.x에서 2.x.x버전으로 본문

DevOps/Ansible

앤서블 1.9.x에서 2.x.x버전으로

SKaSha 2019. 9. 3. 07:02

사내에서 배포 자동화를 앤서블을 이용하여 사용하고 있어, 서둘러 앤서블 서적을 구매하여 공부하기 시작하였습니다. 서적을 구매하고 몇일 뒤 현재 사내에서 1.9.x버전을 사용하고 있는데 최신버전으로 업그레이드했을때, 어떤 이슈가 있을지 기술 발표를 맡게되어 대표적인 변경사항들을 정리해보았습니다.

자세한 변경사항 내용은 앤서블 공식 도큐먼트의 Ansible Porting Guide에서 확인 할 수 있습니다.

1.9.x에서 2.0.x로!

During this entire process, one of the fundamental goals was to maintain backwards compatibility with existing playbooks. In terms of parsing and running playbooks, we believe we have hit that goal. However, there are some incompatibilities related to certain features which users need to be aware of and which we will discuss below.

앤서블이 2.0으로 major 업그레이드를 하면서 기본적인 목표는 기존의 플레이북과의 호환성을 유지하는 것이었습니다.
그리고 플레이북을 파싱하고 운영하는 면에서 이 목표를 이루었다고 생각하지만, 비호환적인 특정 특징들이 있습니다.

Playbook Parsing, Error Reporting Improvements

플레이북 및 기타 YAML 파일의 구분 분석을 담당하는 많은 코드들이 처음부터 다시 작성되었습니다.
그로인해 보다 오류를 명확하게 식별하고 단순한 YAML syntax 오류를 어떻게 수정하면되는지 제안된 수정을 제공합니다.

Task block

블록을 통하여 플레이북에 예외 처리 개념을 도입하였으며 파이썬의 try / expect / finally 구조를 기반으로 모델링 되었습니다.
그로인해 블록에 많은작업 특성(설정, 위임 등)이 추가되어 관련 작업을 그룹화 할 수 있습니다.

New Module

OpenStack , AWS, VMWare, Docker 등과의 연결 플러그인을 포함하여 수많은 모듈들이 추가되었습니다.

New Execution Strategy Plugins

Classic 앤서블은 단일 작업을 모든 호스트에서 수행하고 다음 작업으로 넘어갑니다.
하지만 2.0에서는 Linear Strategy Plugins를 이용하여 다른 모든 호스트를 기다리지 않고 가능한 빨리 Task list를 처리할 수 있습니다.

Callback Plugins

2.0에서는 새로운 콜백 API를 제공하지만, 2.0 이전의 거의 모든 콜백 플러그인도 계속 지원합니다.
하지만 self.playbook, self.play, self.task을 이용하여 콜백 플러그인을 만들경우 더 이상 콜백을 자동으로 채우지 않기 때문에 이 값을 직접 저장해야 한다.

import os
from ansible.plugins.callback import CallbackBase

class CallbackModule(CallbackBase):
    def __init__(self):
        self.playbook = None
        self.playbook_name = None
        self.play = None
        self.task = None

    def v2_playbook_on_start(self, playbook):
        self.playbook = playbook
        self.playbook_name = os.path.basename(self.playbook._file_name)

    def v2_playbook_on_play_start(self, play):
        self.play = play

    def v2_playbook_on_task_start(self, task, is_conditional):
        self.task = task

    def v2_on_any(self, *args, **kwargs):
        self._display.display('%s: %s: %s' % (self.playbook_name,
        self.play.name, self.task))

Dynamic Includes

include task가 동적으로 실행됨.
1.9.x 와 그 이전버전에서는 인벤토리 데이터를 이용하기전에 전처리자가 task를 In-line으로 즉시 include하였습니다.
하지만 루프를 포함하려할때 문제가 발생되어 1.6버전에서 remove되었습니다.
앤서블 2.0 이상에서는 include task을 실행할때 동적으로 이루어지게하여 이 기능을 다시 제공하게 되었으며 훨씬 더 flexible해졌습니다.
또한 동적 include에서는 변수를 사용하는 것도 가능합니다.

- include: "{{inventory_hostname}}.yml"

하지만 동적 include는 다음과 같은 제약이 있습니다.

  • 동적 include에 존재하는 핸들러 이름을 이용하여 notify 할 수 없다
  • 동적 include에 있는 태스크를 --start-at-task 를 사용하여 수행할 수 없다
  • 동적 include에 있는 태그는 -list-tags 결과에 나오지 않는다
  • 동적 include에 있는 태스크는 -list-tags 결과에 나오지 않는다

2.1.x 버전부터...!

static 옵션 추가

2.0버전에서 동적 include가 추가되며 생겼던 제약들을 해결하기 위하여 버전 2.1 이후에 정적(static) 옵션이 추가되었습니다.
이를 이용하여 외부 include에 정의된 핸들러를 호출할 수 있습니다.

- include: foo.yml
  static: <yes|no|true|false>

Ansible 2.1 이후 버전부터는 다음과 같은 조건을 만족하는 한 자동으로 동적(dynamic)이 아닌 정적(static) include를 합니다.

  • include 가 loop을 이용하지 않음
  • include 파일 이름이 변수를 사용하지 않음
  • static 옵션이 no 인 경우
  • ansible.cfg 옵션에서 static include가 비활성화 되어 있음

ansible.cfg 설정파일에 정적 include 를 위한 다음과 같은 두 가지 옵션이 있습니다.

  • task_includes_static - 태스크 섹션에 있는 모든 include는 정적(static)
  • handler_includes_static - 핸들러 섹션에 있는 모든 include는 정적(static)

loop

버전 2.1이후부터 loop_control 옵션을 이용하여 반복문에 사용되는 변수 이름을 지정하는데 사용 가능합니다.
버전 2.5이후부터 정적 루프 키워드 추가되었으며 루프를 수행하는 with_X 스타일의 루프는 전부 loop키워드로 권장 됩니다.

CI Performance

2.2 버전에서 CI의 성능 부담을 줄이고 테스트 커버리지가 향상되었습니다.

async

2.3버전부터는 service와 같은 action plugin에서도 async를 지원합니다

- name: Install nginx asynchronously
  service:
    name: nginx
    state: restarted
  async: 45

block name

2.3버전부터 task의 block에도 이름을 선언할수 있으므로, #을 통한 주석으로 내용을 적지 않아도 됩니다.

New Connection Framework

2.3버전부터 cli transport를 위해 사용되었던 delegate_to 지시자가 더이상 지원되지 않습니다.
cli transport를 통해 네트워크 장치에 연결하는데 있어,
bastion(침입 차단 소프트웨어가 설치되어 내부와 외부 네트워크 사이에서 일종의 게이트 역할을 수행하는 호스트) or _intermediate jump host_를 사용하는데
이를 위해 네트워크 모듈은 ProxyCommand라는 지시자를 지원합니다.
ProxyCommand를 통해 프록시 호스트를 지정하기 위해서는 인벤토리 파일에서 ansible_ssh_common_args를 통해 프록시 호스트를 지정해야합니다.

ansible-config

2.4버전부터 ansible-config 커멘드를 이용하여 현재 시스템의 config를 확장하고 관리할 수 있습니다.

  • 기존에 존재하는 config settings를 덤프 (working, fine tuning)
  • config entry의 update / write (pushed to future roadmap)
  • 사용 가능한 옵션 표기 (ini entry, yaml, env var, etc) (working, fine tuning)

fact namespacing

앤서블 facts는 지금까지 ansible_*와 같은 형태로 사용되어 왔으나, 2.5버전부터 ansible_facts.*와 같은 namespace로 변경됩니다.
예를 들어 ansible_distribution라는 facts 변수는 ansible_facts.distribution라는 변수 구조로 호출되어야 최적으로 작동합니다.
ansible.cfg파일에 inject_facts_as_vars config 변수가 추가가 되며, True일 경우 ansible_*형식을 유지하며 False일 경우 ansible_facts.* 형식으로 변경됩니다. 디폴트 값은 True입니다.

filter로 사용되는 Jinja tests

2.5버전부터 jinja 테스트를 필터로 사용하면 deprecated가 표시되고, 2.9버전부터 removed됩니다.

2.4버전까지

when:
    - result | failed
    - not result | success

2.5버전부터

when:
    - result is failed
    - results is not successful

file 모듈의 follow 속성 default 값 변경

file 모듈의 task 적용 범위가 dest 경로에 존재하는 심볼릭 링크의 원본 파일까지 미치게 하고 싶을수가 있는데,
2.5버전 이전에서는 기본적으로 이 심볼릭 링크의 원본 파일에는 영향이 가지 않았습니다.
그 이유는 follow 속성의 default 값이 no였기 때문입니다.
하지만 2.5버전부터는 follow 속성의 기본 값이 yes로 변경되었고,
dest 경로에 존재하는 심볼릭 링크의 원본 파일까지 기본적으로 영향이 미치도록 변경되었습니다.
이를 피하기 위해서는 follow=no 속성을 입력해줘야 합니다.

Python version

버전 2.4부터 python2.6이상 버전만을 지원합니다.
버전 2.5부터 파이썬3를 지원합니다.
버전 2.7부터 파이썬 2.7 혹은 3.5이상 버전을 지원합니다.

결론은....?

1.9.x -> 2.0.0으로 업그레이드 하면서 앤서블은 최대한 호환성을 유지하였지만,
그 상위 버전으로 가면서 꾸준히 replaced, deprecated, removed, 그리고 새로운 것들이 생성되었습니다.
그렇기 때문에 호환성이 맞지 않는 부분들이 분명 존재할 것이고, 이는 야크쉐이빙을 야기할수도 있습니다.

하지만 앤서블의 버전이 올라가면서,
Dynamic Include, static 등의 옵션이 추가되었고 이는 보다 사용자가 ansible을 flexible하게 사용 할 수 있게 되었으며,
CI Performance가 향상되고, action plugin에서 비동기를 지원하는 등 성능적인 측면에서도 많은 향상이 이루어졌습니다.

또한 다양하고 편리한 모듈들을 사용할수 있다는 점은 생산성과 품질에 시너지를 줄것이고,
여러 장점들로 근래 많이 사용되는 컨테이너 환경(도커)을 사용하고, 시대의 흐름을 따라가기 위해서는
언젠가 앤서블의 버전을 올리는 것은 선택이 아닌 필수가 아닐까 생각합니다.

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

Ansible 개념과 구조  (0) 2019.09.01
Comments