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...]
 
Copyright © . 엔지니어를 위한 파이썬 및 기술 블로그 - Posts · Comments
Theme Template by BTDesigner · Powered by Blogger