Ansible Notes

Automation
환경설정, 배포를 가능하게 하는 언어이며, 리모트 서버에 접속해서 무언가를 시행시키는 정책을 만들어 실행한다. 정책은 yaml 문법으로 설정 한다.

 

💡
ansible 장점
➡️
멱등성이란?
➡️
선언형 언어란?
➡️
Jinja2 란? Python에서 가장 많이 사용하는 template 엔진이다.

 

Ansible 구조
➡️
Inventory 란
➡️
Playbook 이란

 

ansible module 이란 python의 pip 처럼 ansible tasks 를 수행 할때 도움을 주는 plugin 이다. 예를 들어 linux에서 ansible로 파일을 만드는 방법은 대표적으로 2가지가 있다. ex) shell, file
--- ## shell moduel
- name: Ansible Module Test1
  gather_facts: no
  hosts: test
  tasks:
   - name: shell Module
     shell: touch /home/node/Test_Module.txt && chown app:app /home/node/Test_Module.txt && chmod 644 /home/node/Test_Module.txt

--- ## file module
- name: Ansible Module Test2
  gather_facts: no
  hosts: test
  tasks:
   - name: File Module
     file:
      path: /home/node/Test_Module.txt
      state: file
      owner: app
      group: app
      mode: 0644

 

💡
Plugin 과 차이점
💡
module 설치 방법 기본적으로 ansible core 를 설치하면 default module은 설치되며 python으로만 모듈을 제공하기 때문에 pip 를 설치해도 사용 가능하다. ex) kubernetes.core.k8s module ansible-galaxy collection install kubernetes.core or pip install kubernetes

 

Ansible의 role(롤)은 Playbook(플레이북)을 여러 파일로 분할하는 메커니즘이다.

 

 

 

 

 

ansible role 구성 시 directory 구조

 

Example Code for Ansible

 

Parsing module
# 1. lineinfile
- name: Test Delete Marker Line
  lineinfile:
     dest: "/tmp/test.txt"
     regexp: '#'          
     state: absent
  register: result
  until: result is succeeded

# /tmp/test.txt file에서 '#' 문구가 들어가있는 라인들은 전부 삭제 하고,
# 결과를 result라는 변수에 저장 후 조건이 충족될때까지 loop

# 2. blockinfile
- name: Test Insert Marker Line
  blockinfile:
     path: "/tmp/test.txt"
     marker: '# Ansible Marker'
     block:>
       test1
       test2: ok
     state: present
  register: result
  until: result is succeeded

# /tmp/test.txt 에서 #ansibkle maker 마커를 남기고 block 밑에있는 문구를 insert 한다.

# 3. replcae
- name: replace test
  replace:
    path: '/tmp/test.txt'
    regexp: '\r'
    replace: ''

# /tmp/test.txt 에서 ₩r 문자를 빈공간으로 대채한다.


# 4. vars parsing
# ansible에서는 vars값을 받아와 split 할수도 있고 regex를 사용하여 condition을 사용 할 수 있다.
- name: test split
  set_fact:
    file_content: "{{ file_content_line.split('\n') }}"
- debug:
    msg: "{{ file_content }}"

# file_content_line 변수를 줄띄우기 부분을 제거하여 file_content 변수에 넣기

- name: test regex, when condition
  set_fact:
    content_set "{{ content_set | default([]) + [item] }}"
  loop: "{{ content_line }}"
  when: item | regex_search '\w*test(aa|bb|cc)\w*d+')

# content_line 에 설정된 변수만큼 루프를 돌면서 content_set 변수에 list 형태로 변수를 선언
# 이때 content_set은 content line에서 처음에 아무문자가 오고 중간에 test가 있으며
# test 뒤에는 aa또는 bb 또는 cc가 있고 그 뒤에는 아무 문자가 오며 마지막에 숫자로 끝나야 변수 선언

 

template
- name: test template
  blockinfile:
    path: "/tmp/test.txt"
    block: "{{ lookup('template', 'test.j2') }}"
    state: present

# role 구조에서 test.j2라는 jinja2 template내용을 /tmp/test.txt에 기입하겠다.
# test.j2
register: test.com
files_repo: "{{ test_repo }}"
{% raw %}
kube_image_repo: "{{ registry_host }}"
{% endraw %}
{% if test_vars is defined %}
test: "{{ test2_vars }}"
{% endif %}
{% for item in test_name %}
{{ item }} is ok
ansible_hosts={{ test_ip[loop.index0] }}
{% endfor %}

# 위와 같은 형태로 템플릿을 만들 때 raw는 endraw 까지 템플릿에 있는 문자 그대로를 사용
# if 문을 사용하여 condition 사용 가능
# for문을 사용하여 loop 사용 가능
# test_ip[loop.index0] 의미는 test_ip가 list 형태 일때 순서대로 값을 불러오는 것

# jinja2 문법이라 jinja2 문법으로 기입해야한다.

 

 

Kubernetes
- name: Create cluster role
  k8s:
    staste: present
    definition:
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: test-role
      rules:
        - apiGroups: ["*"]
          resources: ["*"]
          verbs: ["*"]
        - nonResourceURLs: ["*"]
          verbs: ["*"]

 

openssh_keypair
- name: Generate ssh key fair test
  openssh_keypair:
    path: /home/test/.ssh/id_rsa
    force: no
    type: rsa
    onwer: test
    group: test 

 

Copy
- name: Get File test (remote)
  slurp:
    src: /home/test/.ssh/id_rsa.pub
  
# slurp 는 원격에서 host server로 file을 가져올때 사용 함.
# 이때 파일의 내용을 vars로 넣을 수 있는데 slurp 특성상 base64 로 인코딩 되있기 때문에 보려면 디코딩 해야함.

- name: copy test
  copy:
    src: "/tmp/test1"
    dest: "/tmp/test2"
    owner: test
    group: test
    mode: 0644

# copy 모듈은 hosts에서 remote server로 file copy 할수 있고, 실행 시 localhost면
# localhost에 dest로 file 복사 됨.

 

다른 hosts 및 tasks에서 선언한 동적 변수를 다른 tasks에 넘기고 싶을 때
# inventroy
test:
  ip1_test 10.x.x.x
  ip2_test 10.x.x.x
  ip3_test 10.x.x.x

- name: Find vars test
  hosts: "{{ groups['test'][0] }}"
  gather_facts: false
  tasks: 
    - name: find cert file
      find:
        paths: "/etc/ssl/etcd/ssl"
        file_type: file
        use_regex: yes
        patterns:
        - '(?=node.*ket.pem)'
      become: yes
      register: cert_path
    
    - name: set fact1
      set_fact:
         cert_path_1: "{{ cert_path.files[0].path }}"
 
- name: othere hosts vars connection
  hosts: localhost
  gather_facts: false
  vars:
    cert_path: "{{ hostvars[groups['test'][0]]['cert_path_1'] }}
  tasks:
     - debug:
         msg: "{{ cert_path }}"

 

role play에서 inventory file 안에 있는 특정 group 만 호출 하고 싶을때
# role main playbook
- name: test tasks in test1 test2
  hosts: test1, test2
  roles:
    - { role: bastion_job, become: yes }

# role play main.yaml
- name: test1 tasks
  import_tasks: set_test1.yaml
  when "'test1' in group_names"

- name: test2 tasks
  import_tasks: set_test2.yaml
  when "'test2' in group_names"

# bastion job role에서 test1 play는 test1 group들만 실행하고
# test2 play는 test2 group들만 실행된다.

 

 

참조:

https://palyoung.tistory.com/24

https://watch-n-learn.tistory.com/92

https://sunrise-min.tistory.com/entry/Ansible

https://docs.ansible.com/ansible/2.9/modules/list_of_all_modules.html

https://docs.ansible.com/ansible/latest/dev_guide/developing_locally.html

https://only-won.tistory.com/13

https://iborymagic.tistory.com/73

https://velog.io/@chl4651/Ansible이란

https://chanchan-father.tistory.com/517#google_vignette

 

← back