2018년 1월 11일 목요일

[Ansible] plugin 중에서 python을 이용한 filter에 대한 짧은 이야기

- 0 개의 댓글
민망한 하하하 짤에 대한 이미지 검색결과

하하하~!
하하하~;;;;

페이스북에 Ansible user 커뮤니티가 있는데, 거기에 ansible filter에 관련하여
인자 값을 두개만 넘겼는데, 3개가 처리되는 것에 대해서
모르겠다고 답변했는데, 나중에 알게 된 사실을 정리해서 올립니다.

답변은 김용기부장님께서 해주셨고, 저는 그걸 그냥 이해하고 정리한 정도입니다 :)

음...나중에 필터 관련해서 글을 정리할때 도움이 될꺼 같기도하고....누군가는 이게 또 그런저런 도움이 될꺼 같기도 해서 :)

참 그리고 여기에 있는 기본적인 filters.py는 다음의 github에서 참조하여 작성하였습니다.
https://gist.github.com/viesti/1febe79938c09cc29501#file-filters-py-L4


============ 파이썬 커뮤니티 사람들을 위해서 ============
들어가기에 앞서 python 커뮤니티에서 들어오신 분들을 위해서 약간 아주 약간 첨언하자면, 순순하게 filter가 위치한 디렉터리 /usr/lib/python2.7/site-packages/ansible/plugins/filter에 아래에 filters.py에 준하는 문법 수준으로만 작성한다면, 어떤 종류의 앤서블에서 실행되는 데이터 값에 관여 및 조정할수 있습니다.

여기서 재미있는 것은 모듈의 개념처럼 동작하는데 import는 없으며, reload의 concept도 없습니다. 그냥 여기 있는거 다 읽고 자동으로 모두 넣습니다..하하하;;;; 무거워질수도 있는 우려가 있습니다만....현재 filter에 위치하고 있는 py들이 얼마 없기 때문에 한동안은 큰 무리가 없을 것 같습니다. 사용자가 임의로 쓰기 좋은 환경이라는거죠 :)

이 얼마나 개발자 친화적인...(장난감)? 하하하;;

[vagrant@ansible-server filter]$ ll
total 228
-rw-r--r--. 1 root root 15859 Nov 29 21:08 core.py
-rw-r--r--. 2 root root 16706 Nov 29 22:40 core.pyc
-rw-r--r--. 2 root root 16706 Nov 29 22:40 core.pyo
-rw-r--r--. 1 root root   400 Jan 11 12:00 filters.py
-rw-r--r--. 1 root root   119 Nov 29 21:08 __init__.py
-rw-r--r--. 2 root root   309 Nov 29 22:40 __init__.pyc
-rw-r--r--. 2 root root   309 Nov 29 22:40 __init__.pyo
-rw-r--r--. 1 root root 28268 Nov 29 21:08 ipaddr.py
-rw-r--r--. 2 root root 28218 Nov 29 22:40 ipaddr.pyc
-rw-r--r--. 2 root root 28218 Nov 29 22:40 ipaddr.pyo
-rw-r--r--. 1 root root  1857 Nov 29 21:08 json_query.py
-rw-r--r--. 2 root root  1757 Nov 29 22:40 json_query.pyc
-rw-r--r--. 2 root root  1757 Nov 29 22:40 json_query.pyo
-rw-r--r--. 1 root root  4383 Nov 29 21:08 mathstuff.py
-rw-r--r--. 2 root root  5452 Nov 29 22:40 mathstuff.pyc
-rw-r--r--. 2 root root  5452 Nov 29 22:40 mathstuff.pyo
-rw-r--r--. 1 root root  7487 Nov 29 21:08 network.py
-rw-r--r--. 2 root root  5740 Nov 29 22:40 network.pyc
-rw-r--r--. 2 root root  5740 Nov 29 22:40 network.pyo
-rw-r--r--. 1 root root  1136 Nov 29 21:08 urlsplit.py
-rw-r--r--. 2 root root  1567 Nov 29 22:40 urlsplit.pyc
-rw-r--r--. 2 root root  1567 Nov 29 22:40 urlsplit.pyo
================================================

그러면,  질문 사항을 보겠습니다.




여기에 저는...아직 공부를 안해서!!! 입니다. 혹은 플러그인중에 필터를 쓸일이...그닥.-_-
없었다고나 할까요?
진짜 짤에 대한 이미지 검색결과
진짜입니다.!!

그래서 이거에 대해서 음 모르겠는데요? 라는게 주된 내용으로 답변하였는데,
김용기 부장님께서 아래와 같이 답변 주셨습니다.



그래서 해당 내용을 확인하려고 바인딩 되는 인자를 찍어보는 랩을 할 것입니다.

1) 필터에 사용할 코드와 인자 값을 찍기 위한 구성을 추가합니다.
 - 필터에 사용할 코드 : filters.py
 - 샘플 코드 : test.yml

2) 해당코드를 /usr/lib/python2.7/site-packages/ansible/plugins/filter에 저장합니다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def make_rules(hosts, ports, proto):
    print "*"*50; print "  Binding IP is " + str([i for i in hosts]); print "*"*50+"\n"
    return [{"proto": proto,
             "from_port": port,
             "to_port": port,
             "cidr_ip": host} for host in hosts for port in map(int, ports.split(","))]

class FilterModule(object):
     def filters(self):
         return {'make_rules': make_rules}

3)아무런 생각 없이 샘플 코드를 실행합니다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
---
- name: Test
  hosts: localhost
  vars:
    random_hosts:
      - 192.168.1.2
      - 192.168.1.3

  tasks:

    - name: debug message for traceback
      debug:
        msg: "{{ random_hosts | make_rules('22,8080', 'tcp') }}"

4) 짜잔 내용을 확인합니다.


신기하게도 맨 앞에 기입된 내용이 정말 바인딩이 되는군요!!

제가 이걸 초반에 헷깔린게..테스트는 ...안/못 하고..그냥 코드만 봤을때는 아무리 봐도 안 돌아가는 코드인데다가..ipaddr.py 코드의 경우에는 중간에 usage를 넣습니다.



그런데 이 작성자분은 filters.py라는 것에다가 코멘트(#)도 없이 그냥 usage라고 넣고 이와 같이 함께 그냥 작성하셨더라고요..그래서..아 그냥 오타인가? 했더랬죠 -_-

실행을 만약에 전부다 넣고(git에 있는 filters.py처럼)



 실행한다면, 당연히 에러가 납니다.



그냥 실행해도 마찬가지이고요..문법적으로 다가;;;;




반성합니다.!!! 역시 테스트를 해야죠~! 개발자/엔지니어 기타등 우리는 말로 하는게 아니라 다 테스트를 해보는 겁니다~!!!!
가즈아 짤에 대한 이미지 검색결과


[ 참고사항 ]
좀더 쉽게 확인하는 부분을 변경한 것도 첨부합니다.
저와 같이 비개발자분들이 쉽게 이해하도록 수정한 부분입니다.
밑에 for문과 print문만 보시면 되요~!
(다만 약간 결과물이 달라집니다 ~~ 참고하시고요~!!)
성투! 아 아니...다들 성공적인 한주가 되세요~!!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def make_rules(hosts, ports, proto):
    print "*"*30
    for i in hosts:
      print "  Binding IP is " + i
    print "*"*30+"\n"
    return [{"proto": proto,
             "from_port": port,
             "to_port": port,
             "cidr_ip": host} for host in hosts for port in map(int, ports.split(","))]

class FilterModule(object):
     def filters(self):
         return {'make_rules': make_rules}





[Continue reading...]

2018년 1월 5일 금요일

[Ansible] Plugin 살펴 보기 4편 (inventory)

- 0 개의 댓글


inventory에 대한 이미지 검색결과

인벤토리 plugin 과연 이건 어떨까요?
이것을 이해하려면, 과거로 돌아가야 합니다. 신경도 잘 안 썼던 그때로 말이죠
타임머신에 대한 이미지 검색결과



inventory는 기본적으로 /etc/ansible/hosts에 위치해 있고, 여기를 수정해서 작성합니다.



하지만, 꼭 항상 언제나 여기를 써야 할까요?
아니죠 ansible, 또는 ansible-playbook은 -i 또는 --inventory라는 옵션이 있습니다.

즉 우리가 원하는 곳에 inventory를 끌어다 쓸수 있는거죠.

예제를 볼까요?

m_hosts라는 파일을 읽어서 해당 부분에 대한 그룹을 볼 것입니다.

[vagrant@ansible-server inventory]$ cat m_hosts
node01
node02
node03
node04

이렇게 하면, 그냥 그룹소속과 아닌 것만 보이게 되죠


원래 /etc/ansible/hosts에 있던 파일을 이렇게 나오고 결과 값은 이렇습니다.

# BEGIN ANSIBLE MANAGED BLOCK
[CentOS]
node01
node02
[Ubuntu]
node03
node04
[Win]
node05
# END ANSIBLE MANAGED BLOCK





이건 그룹이 좀 되어 있는 편이죠 :)

여튼 우리는 인벤토리를 임의로 할수 있다는 것을 확인했습니다.


5. Inventory (tag : 과연 내가 널 쓸까?)


그렇습니다. 이 인벤토리를 좀 더 자유롭게 쓸수 있는게 인벤토리 plugin입니다.
예시를 한번 봅시다.

특히 inventory plugin은 예시가 아니면 이해가 잘 안됩니다. ㅠㅠ

[vagrant@ansible-server inventory]$ cat m_hosts
node01
node02
node03 Prod=Ubuntu
node04 Test=Ubuntu
node05 Prod=CentOS
node06 Test=Win
node07 Prod=Win


기존에 이렇게 작성된 hosts  파일이 있다고 가정합시다.
어디에도 group이 되어 있지가 않죠?

아리송 짤에 대한 이미지 검색결과

아니아니 -_-; 이게 아니고요...

이것을 plugin을 통해서 자동으로 그룹해 보도록 하겠습니다.
자동화를 위해서 constructed 를 사용하겠습니다.

아리송 짤에 대한 이미지 검색결과

아니....제 마음이 계속 표시가....-_-; 집에 가고 싶어서....
여튼...다시 잠시만요..;;;;

[vagrant@ansible-server inventory]$ cat cons.config
plugin: constructed
strict: False
keyed_groups:
  - prefix: Prod
    key: Prod|default('none')
  - prefix: Test
    key: Test|default('none')

이런식으로 나는 플러그인으로 constructed를 쓸꺼고 심각하게는 안 볼꺼고 그룹은 이렇게 할꺼라구! 라고 정리해서 꼭꼭꼭 확장자를 config로 줍니다. 또는 yaml로요.
(이거 틀려서 몇시간 까먹었습니다. 하하하하 conf로 주니까 동작을 안 하더라고요 ㅎㅎㅎ)

그러면 한번 실행해 볼까요?


엄머! -_- 이건 무슨 일일까요?
엄마 놀람 짤에 대한 이미지 검색결과



이게 왜 이렇게 되었냐면 말이죠...
기본적인 inventory 플러그인은 'host_list', 'script', 'yaml', 'ini' 를 받아 들입니다. 
근데 쌩판 본적도 없는 contru...머시기가 들어오니 난 모르겠다라고 하는거죠. 
그래도 출력물이 나오는걸 보면 양반입니다. 

그래서 enable_plugins 자체를 수정해 줍니다. 
이때, 순서 같은 것은 상관 없습니다. 내가 허용해 주는 것들을 whitelist처럼 정리하는 거라서요.



해당 내용을 저장하고 다시 실행하면, 아래와 같이 그룹을 자동으로 정리되어 있는 것을 확인할 수 있습니다.



이와 같은 inventory 관련 plugin은 다음과 같습니다.


그런데 말이죠 가장 중요한 포인트...이걸 어디다가 쓸까요 -_-?

가장....사용에 필요한 것은 자동으로 VM들이 관리되는 환경...즉 AWS, Azure와 같은 VM들이 동적으로 할당되고 삭제되는 환경내에서 CI/CD환경을 만들기 위해서 적용이 필요한 경우가 있습니다.

또는 대형 IDC환경에서 CMDB에 정확하게 값들이 들어가도록 input을 규정화 하고 정확하게 들어가게 해줘야 할때도 관리의 편의성이 좋아질 것 같습니다. 이 역시 동적으로 운영되는 걸 mapping해주는 것이겠죠.

아래는 inventory plugin을 새로 개발해서 쓴 경우입니다. 참고로 보시면 될 것 같아요 :)
http://willthames.github.io/2017/11/01/generating-inventory.html

그러면 이만 빠잉~! 얼릉 집에 가서 잘껍니다 ㅠㅠ
빠잉에 대한 이미지 검색결과

[Continue reading...]

2018년 1월 1일 월요일

[Ansible] Plugin 살펴 보기 3편 (Connection)

- 0 개의 댓글

connection에 대한 이미지 검색결과
생각보다 다루는데 오래오래 걸리네요 :)
하하하;; 이걸 하루만에 다 하려고 했다니~!


4. Connection (tag : 누구나 쓸수 있지만, 필요할 때만 쓰게됨)

그러면 다음 주제 Connection 을 다루어 볼까요?
기본적으로 Connection 자체를 수정할 일은 거의 없습니다.
( 쓸 곳이 별로 없다 ??)
쓸모가 없다에 대한 이미지 검색결과

왜냐하면, 기본으로 제공하는 connection은 ssh로 (옛날 옛날에는 paramiko) 를 그대로 이용하여 22번 포트로 현재의 계정 정보를 들고 접속하기 때문입니다.

network port number에 대한 이미지 검색결과

보통 이 구성으로 수행하면 아무런 문제가 없기 때문이죠

다만 특수한 환경 (windows, 네트워크 장비, 통신 장비)에서는 특수한 프로토콜을 사용하는 경우가 있습니다. 이때 개별 호스트 별로 세팅을 해주는 것으로 충분합니다.

수정하는 방법은 크게..


#1. 실행에 옵션으로 넣기  

해당 내용들은 ansible-playbook --help 를 참조하면 볼수 있습니다 :)

  Connection Options:
    control as whom and how to connect to hosts
    -k, --ask-pass      ask for connection password
    --private-key=PRIVATE_KEY_FILE, --key-file=PRIVATE_KEY_FILE
                        use this file to authenticate the connection
    -u REMOTE_USER, --user=REMOTE_USER                        connect as this user (default=None) 
    -c CONNECTION, --connection=CONNECTION                        connection type to use (default=smart)
< 생략 >

그러면 현재 계정으로 touch를 실행해서 흔적을 남기는 코드를 사용해서 remote_user가 잘 되는지 확인해 보겠습니다.~!

[ 테스트 코드 ]

1
2
3
4
5
6
7
8
---
- name: Touch file
  hosts: nodes
  gather_facts: no

  tasks:
    - name: Touch per hosts
      command: 'touch $LOGNAME'

우선 기본 계정(vagrant)에서 실행해 보겠습니다.





실행이 끝나고 나면, 107번에 접속해서 vagrant 파일이 생성되었는지 확인해 봅니다 :)



잘 되었네요~!!

그러면 유저를 변경해서 'root'로 실행해 볼까요?




root로 잘 생성된 것을 확인할 수 있습니다.
이처럼 실행에서 인자를 변경해서 실행해 볼수 있습니다. 다른 방법으로는 파일 자체에 입력하는 방법이 있습니다.


#2. 파일에 적용해 놓기 

 1) /etc/ansible/hosts
   - 한줄에 그대로 입력
      192.168.1.10 ansible_connection = ssh         ansible_user = root 

   - var로 따로 작성해서 넣기
       [nodes]
       192.168.1.[101:110]

       [nodes:var]
       ansible_connection = ssh         ansible_user = root   

 2) 플레이북 자체에 입력하기
    remote_user : root
    connection : ssh 

한번 플레이북에 자체에 입력해서 돌려 볼까요?

[ 변경된 테스트 코드 ]

1
2
3
4
5
6
7
8
9
---
- name: Touch file
  hosts: nodes
  gather_facts: no
  remote_user: root << 추가함 

  tasks:
    - name: Touch per hosts
      command: 'touch $LOGNAME'

리모트 유저를 root로 입력했으니, 그대로 실행해 봅니다.



현재 유저는 vagrant인데 리모트에는 root로 작성된 것을 확인할 수 있습니다 :)



추가정보
Connection에 사용할 수 있는 플러그인은 다음과 같습니다..그러나 과연 자주 쓸만한게 있는지 모르겠네요. winrm이랑 docker말고는 하하하;;아 saltstack 연결용도 쓸수도 있겠네요.
뻘쭘에 대한 이미지 검색결과

이번 주말까지 하면, 아마도 plugin을 마무리 할수 있겠네요~! :)
<<< 이건 희망사항입니다~!

빠잉에 대한 이미지 검색결과



[Continue reading...]

2017년 12월 31일 일요일

[Ansible] Plugin 살펴 보기 2편 (Callback)

- 0 개의 댓글


callback에 대한 이미지 검색결과

시작하기에 앞서 지난 글에서 redis를 썼었는데요
이걸 왜 쓴다고 하는걸 안 쓴거 같더라고요.

예제를 볼까요~? 이해를 위해서는 예제가 제일 편합니다.

/etc/ansible/ansible.cfg에 fact_caching을 주석으로 없앴습니다.
이렇게 하면 default인 memcache를 사용하게 됩니다.
그러면 어떻게 동작할까요?

두번 실행해 보겠습니다.


대략 10초 후에~!


같은 점과 차이 점이 보이시나요?
아니아니 이렇게 생긴 것도 아닌데...-_-; 금방 다 찾으셨겠죠?
숨은그림 찾기 짤에 대한 이미지 검색결과

같은 점
Gathering FACT 즉, 인자 값을 또 수집합니다. -_-
redis에 저장했을때는 안 했었죠!!

차이 점
인자 값인 시간이 변경되었습니다.
memcache이기 때문에, playbook이 생성되고, 실행되는 동안에 유지하고, playbook을 다시 실행할때는 FACT를 다시 생성하고 저장합니다.

이런 것들로 비추어봤을때 redis를 쓰면 어떤게 유리할까요?

여러번의 playbook을 반복 실행할때 소요시간을 줄여 줄수 있습니다.
또한, 사용자원이 적을 야간에 해당 작업을 수행해서 (변경이 없다는 가정하에...)
FACT를 저장해 놓고, 해당 부분을 이용해서, 주간에 작업을 수행하면서 검토합니다.

그렇다면 어떤 단점이 있을까요?
오히려 저장된다는게 단점이 될수 있습니다.

저장되니...변경되는 데이터에 반응이 안됩니다. -_-
또한 메모리의 일정 공간을 점유하고, 리소스를 놓아주지 않습니다.

해당 부분을 잘 고려해서 쓴다면, 유용하게 사용할수 있을 것 같습니다. :)

3. Callback (tag : 관리자외 대부분이 쓰면 좋음 )

그러면 다음으로


콜백을 알아볼까요?
콜백은 아주 짧게 정의하자면, 플레이북 실행 시에 나오는 내용을 세부적으로 확인할 수 있게 해주는 것입니다.

이를 통해서 debug도 하고, 성능도 점검하고, 내용이 잘 진행되었는지 추후에 확인도 하고 그런 여러가지 목적으로 쓰이는 거죠 :)

콜백으로 쓰일수 있는 아이템들은 어떤게 있을까요?

단순히 로그의 내용을 더 자세하게 보여주는 애들부터, 기록해주는 log_plays, 슬랙으로 전달해주는 slack, jabber까지 다채롭습니다. 추후에는 계속 더 추가되겠죠~!

세부 아이템의 코드는 아래의 링크에서 확인 가능합니다.
https://github.com/ansible/ansible/tree/devel/lib/ansible/plugins/callback

해당 내용들이 어떻게 동작하는지 간단하게 살펴 볼까요?
기존에 현재 시간을 보는 플레이북을 그대로 사용하겠습니다.

callback_whitelist 설정을 profile_tasks, timer 했을때는?


callback_whitelist 설정을 profile_roles, timer 했을때는?

성능을 테스트할 수 있겠죠?

그렇다면, 엄청 많은 내용을 돌려놓고 나중에 보려면? 어떻게 할까요?
물론 대부분의 셸프로그램은 화면에 출력되는 내용을 표시해 주지만요
그런거 말고 log_plays로도 가능합니다.

log_plays를 그냥 추가합니다.


해당 실행 내용이 '/var/log/ansible/hosts/호스트이름' 에 기록됩니다. :) 자동으로요~!



그리고 현재 화면에 출력되는 (stdout)을 조정할 수 있습니다.
두가지 정도 살펴 볼까요?

dense (조밀한, 촘촘한?) 으로 변경해 보겠습니다.

그리고 실행하면 어떻게 될까요?

화면에 출력되는 내용이 촘촘하게 변경되었죠?
그렇다면 selective는 어떨까요?

휠씬 더 ...-_-; 이건 보이는게 거의 없는 수준이네요..
여튼...화면에 출력되는건 상황에 맞게 조정하여 볼수 있습니다~!!


[ 참고사항 ]
Whitelist라는건 블랙리스트 반대말로 허용하는 리스트 같은 겁니다. :)
위트있게 기억하게 쉽게 callback을 허용하는 리스트라고 적어 둔거네요 ~!!
이래서 개발자들이 좋습니다~!
whitelist에 대한 이미지 검색결과

플러그인에 대해서는 갈 길에 생각보다 머네요~~ 하하하;;;;

먼길에 대한 이미지 검색결과

저 길의 끝은 어디려나...ㅎㅎㅎㅎㅎㅎ 내일 다시 돌아옵니다 :)
2018년에 보아요~!





[Continue reading...]
 
Copyright © . 엔지니어를 위한 파이썬 및 기술 블로그 - Posts · Comments
Theme Template by BTDesigner · Powered by Blogger