ansible-사용법

kiyeon·2023년 1월 25일
0

공식문서:https://docs.ansible.com/ansible/latest

멱등성이란?

멱등성이란 여러번 수행해도 같은 결과를 뱉는 성질을 말합니다.
앤서블은 YAML로 관리되는 명령집을 여러번 수행하더라도 언제나 같은 결과가 나올 수 있도록 여러가지 관리를 합니다.

인벤토리(Inventory)

  • 대상서버 호스트를 관리하는 파일
  • 파일안에 서버들 목록 정의 / 그룹기능 지원
test.inv 따로 확장자 명이 없기때문에 편한 네임 사용
[test]
192.168.1.1
192.168.1.2

[alias]
test1 ansible_host=192.168.1.1
test2 ansible_host=192.168.1.2

[vars]
test1 ansible_host=192.168.1.1 ansible_user=centos
test2 ansible_host=192.168.1.2 ansible_user=centos

애드혹 명령어(Ad-hoc Command)

  • 명령어 통해 실행되어 간단하지만 재사용은 불가
  • 주로 테스트 목적으로 사용
#순서는 지킬필요는 없다.
ansible [그룹명] -m[모듈] [-a 모듈 옵션] -i[인벤토리 지정]
ansible -i test.ivh -m ping test
ansible -i test.ivh -m command -a "uptime" test #해당 커맨드 명령어 실행
ansible localhost -m setup #리무트 호스트 정보수집
ansible -i test.ivh -m yum -a "name=git state=latest update_cache=yes" test --become #git 설치 및 --become 옵션을 사용하요 root 계정 변환 후 설치 진행
ansible -i test.ivh -m yum -a "name=git state=absent update_cache=yes" test --become #git 삭제

플레이북(Playbook)
yaml 문법으로 스크립트 처럼 작성하여 팀원 간 공유 및 코드 재사용

---
# This is Ansible Playbook
#
# 플레이북 (Playbook): YAML로 정의. 순서대로 정렬된 플레이(작업 목록) 절차.
# 플레이 (Play): 작업 목록(Tasks). 특정 호스트 목록에 대하여 수행
# 작업 (Task): 앤서블의 수행 단위. 애드혹 명령어는 한 번에 단일 작업 수행.
# 모듈 (Module): 앤서블이 실행하는 코드 단위. 작업에서 모듈을 호출함.
# 콜렉션 (Collection): 모듈의 집합.

- name: Play 1
  hosts: centos
  become: true #루트 권한으로 실행
  tasks:
  - name: "Task 1: Execute command"
    command: uptime

  - name: "Task 2: Execute script"
    script: task2.sh

  - name: "Task 3: Install package"
    yum:
      name: nginx
      state: present
      update_cache: true

  - name: "Task 4: Start nginx service"
    service:
      name: nginx
      state: started

- name: Play 2
  hosts: localhost
  tasks:
  - name: "Task 1: Execute command"
    command: whoami

  - name: "Task 2: Execute script"
    script: task2.sh
ansible-playbook -i[인벤토리 지정] [playbook-yaml 파일지정]
ansible-playbook -i test.ivn test.yaml

모듈(Module)

---

- name: Example
  hosts: centos
  become: true
  tasks:
  # Docs: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/user_module.html
  - name: "Create a user"
    user: "name=test shell=/bin/bash" #사용자관리 모듈

  - name: "Hello World"
    command: "echo 'Hello World!'"

  # Docs: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/lineinfile_module.html
  - name: "Add DNS server to resolv.conf"
    lineinfile: #설정 파일 확인해서 해당라인이 있는지 확인 후 없으면 추가
      path: /etc/resolv.conf
      line: 'nameserver 8.8.8.8'

  # Docs: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/apt_module.html
  - name: "Install Nginx"
    yum:
      name: nginx
      state: present
      update_cache: true

  # Docs: https://docs.ansible.com/ansible/latest/collections/ansible/posix/synchronize_module.html
  - name: "Upload web directory"
    synchronize: #싱크 동기화 모듈 rsync 랑 유사하다
      src: files/html/
      dest: /var/www/html
      archive: true
      checksum: true
      recursive: true
      delete: true

  # Docs: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/copy_module.html
  - name: "Copy nginx configuration file"
    copy:
      src: files/default
      dest: /etc/nginx/sites-enabled/default
      owner: "{{ ansible_user }}"
      group: "{{ ansible_user }}"
      mode: '0644'

  # Docs: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/service_module.html
  - name: "Ensure nginx service started"
    service:
      name: nginx
      state: started

핸들러

  • 이벤트 기반으로 동작하는 Task
  # Docs: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/copy_module.html
  - name: "Copy nginx configuration file"
    copy:
      src: files/default
      dest: /etc/nginx/sites-enabled/default
      owner: "{{ ansible_user }}"
      group: "{{ ansible_user }}"
      mode: '0644'
    notify:
    - Restart Nginx

  # Docs: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/service_module.html
  - name: "Ensure nginx service started"
    service:
      name: nginx
      state: started

  handlers:
  - name: Restart Nginx
    service:
      name: nginx
      state: restarted

변수(Variables)

---
#vars1
- name: Example
  hosts: centos
  become: true
  vars:
    user_name: "test"
    user_comment: "from playbook vars"
    user_shell: /bin/bash
    user_uid: "7777"
  tasks:
  - name: "Create a user"
    user:
      name: "{{ user_name }}"
      comment: "{{ user_comment }}"
      shell: "{{ user_shell }}"
      uid: "{{ user_uid }}"

#vars2 
# vars.yaml 파일을 vars1 변수처럼 지정하여 파일로 관리한다
---

- name: Example
  hosts: centos
  become: true
  vars_files:
  - vars.yaml
  tasks:
  - name: "Create a user"
    user:
      name: "{{ user_name }}"
      comment: "{{ user_comment }}"
      shell: "{{ user_shell }}"
      uid: "{{ user_uid }}"

반복문(loops)

  • 반복문 같은 경우 loops with_items 두 가지 방식이 있으나 with_items 는 없어질 가능성이 있다
  tasks: #with_items 방식
  # Docs: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/group_module.html
  - name: "Create groups"
    group:
      name: "{{ item }}"
      state: "present"
    with_items:
    - backend
    - frontend
    - devops
---------------------------------------------------------------
  tasks: #loop 방식
  # Docs: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/user_module.html
   - name: "Create a user"
     user:
       name: "{{ item }}"
       comment: "test"
       state: "test"
     loop:
     - john
     - alice
     - claud
---------------------------------------------------------------
반복하기 위해 변수 users 추가한다
- name: Example
  hosts: centos
  become: true
  vars:
    tags:
      Name: "Debug"
      Environment: "Test"
      Owner: "test"
    users:
      - john
      - alice
      - claud
  - name: "Create a user"
    user:
      name: "{{ item }}"
      comment: "test"
      state: "present"
    loop: "{{ users }}"
---------------------------------------------------------------    
---
- name: Example
  hosts: centos
  become: true
  vars:
    tags:
      Name: "Debug"
      Environment: "Test"
      Owner: "test"
    users:
    - name: john
      shell: /bin/bash
    - name: alice
      shell: /bin/sh
    - name: claud
      shell: /bin/bash
    - name: henry
      shell: /bin/sh
    - name: jeremy
      shell: /bin/bash
    - name: may
      shell: /bin/sh
  tasks:
    # Docs: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/user_module.html
  - name: "Create a user"
    user:
      name: "{{ item.name }}"
      shell: "{{ item.shell }}"
      comment: "test"
      state: "present"
    loop: "{{ users }}"

  - name: "Debug data"
    debug:
      msg: "{{ item.key }}: {{ item.value }}"
    loop: "{{ tags | dict2items }}"

조건문(Conditionals)

---

- name: Example
  hosts: all
  become: true
  vars:
    users:
    - name: john
      shell: /bin/bash
      enabled: true
    - name: alice
      shell: /bin/sh
      enabled: false
    - name: claud
      shell: /bin/bash
      enabled: true
    - name: henry
      shell: /bin/sh
      enabled: false
    - name: jeremy
      shell: /bin/bash
      enabled: true
    - name: may
      shell: /bin/sh
      enabled: false
  tasks:
  # Docs: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/user_module.html
  - name: "Create a user if enabled in Amazon Linux"
    user:
      name: "{{ item.name }}"
      shell: "{{ item.shell }}"
      comment: "test"
      state: "present"
    loop: "{{ users }}"
    when: item.enabled and (ansible_facts["distribution"] == "Amazon")

  - name: "Show items between 10 and 100"
    debug:
      var: item
    loop: [ 0, 192, 154, 456, 7, 2, -1, 55, 234]
    when:
    - item >= 10
    - item <= 100
--------------------------------------------------------------- 
  - name: "Show items not between 10 and 100"
    debug:
      var: item
    loop: [ 0, 192, 154, 456, 7, 2, -1, 55, 234]
    when:
    - (item < 10) or (item > 100)

  - name: "Install Packages on Ubuntu"
    apt:
      name: "{{ item }}"
      update_cache: true
      state: "present"
    loop:
    - git
    - curl
    - htop
    when:
    - ansible_facts['distribution'] == 'Ubuntu'
--------------------------------------------------------------- 

  - name: "Install Packages on Amazon Linux"
    yum:
      name: "{{ item }}"
      state: "present"
    loop:
    - git
    - curl
    - htop
    when:
    - ansible_facts['distribution'] == 'Amazon'
--------------------------------------------------------------- 
  - name: "Print users"
    #앞에있는 컬럼내용(유저정보) 만 가져온다
    command: "cut -d: -f1 /etc/passwd" 
    register: users # 가져온 정보를 users 변수에 등록

  - name: "Is there claud"
    debug:
      msg: "There is no claud"
    #유저정보에서 (claud) 찾는다 없어면 -1 리턴하여 msg 메세지 출력
    when: users.stdout.find('claud') == -1

ansible facts(상세)

#facts 란?
원격서버 등에 대해서 운영체제 정보, IP정보, 파일시스템를 가져온다
기본적으로 정보를 가져오나 대규모 시스템 관리시 성능향상을 위해 끄기도 한다.
gather_facts: false 

기타

  • ssh-keygen -t rsa # public_key 생성
  • ssh-copy-id -i ~/.ssh/id_rsa.pub centos@192.168.1.1
  • ssh-agent 사용시 ssh-add -K [경로] 에이전트에 키 등록
ansible ssh 장애
"Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password)
ansible 서버의 ~/.ssh/id_rsa.pub 값을 에러가난 원격지 서버의 ~/.ssh/authorized_keys 파일에 저장한다
ansible -i <inv> -m ping all -vvv 통해 애러부분확인
ex:) STABLISH SSH CONNECTION FOR USER: None
user 가 지정되지 않았음으로 인벤토리에 "ansible_host=centos" 등록이 필요하다
~/.ssh/authorized_keys 파일 권한이 600, 소유권확인
명령어 실행자 확인(root, user)
ansible ssh 장애2
playbook error : SSH password instand of ... 해결방법
ansible을 인벤토리 설정 후 playbook실행 시 ssh host key에러가 발생되는 경우가 있다.
이 부분은 처음 접속하기 때문에 fingerprint접속오류라고 할수 있다.

이때는 아래와 같이 해결하길 바란다.
*환경변수 지정
export ANSIBLE_HOST_KEY_CHECKING=False
* ansible.cfg 설정
~/.ansible.cfg 

[defaults]
host_key_checking = False

*ansible.cfg 생성
ansible-config init --disabled > ansible.cfg
장애3
become 모듈과 connection: local 같이 사용시 "sudo: a password is required\n", "module_stdout" 에러가난다
처음엔 폴더를 만들어야된다는 생각에 become 모듈을 추가하였는데 생각해보니 폴더가 root 로 만들어져서 어차피 사용자 계정에서
파일 복사나 다른것들이 안됐다. 결론은 become 을 빼고 진행하니 정상 작동한다.

0개의 댓글