날려먹은 레거시 시스템 배포 스크립트는 배포 목록 디렉토리에 업로드 된 tar.gz 파일을 각 서버로 전송하고, 서버에서 스크립트를 실행하여 목표 시스템에 배포하는 구조로 되어있었다. 각 서버에 있는 스크립트는 보존하였기 때문에 그 이전 과정까지만 Ansible로 변경했다. Ansible Playbook을 작성하는 건 처음이라 문법을 익히면서 주석으로 달아놨다.

---
- name: 레거시 시스템 배포 # 작업 제목
  hosts: all # 작업 대상 서버 지정으로 인벤토리(hosts.ini) 내부의 모든 서버가 대상
  gather_facts: no # 서버 정보 수집 여부

  vars:
    local_dir: "/home/jboss/deploy" # 단순 변수
    remote_dir: "/home/jboss/deploy"
    remote_script: "deploy.sh"
    system_map: # 복합 변수
      - { key: "foo", group: "foo" }
      - { key: "bar", group: "bar" }
      - { key: "baz", group: "baz" }

  tasks:
    - name: 1. 배포 파일 찾기
      delegate_to: localhost # Ansible을 실행하는 서버에서 실행 
      run_once: true # 딱 한 번만 실행
      find:
        paths: "{{ local_dir }}" # 찾을 위치로 하위 디렉토리까지 찾으려면 recurse: yes 추가 필요
        patterns: # 찾을 패턴
          - "*foo*.tar.gz"
          - "*bar*.tar.gz"
          - "*baz*.tar.gz"
      register: found_files # 파일을 찾으면 path, mode, size 등 ls -l 수준의 정보가 저장

    - name: 2. 파일이 없으면 종료
      fail:
        msg: "오류: 배포할 파일이 없습니다."
      when: found_files.matched == 0 # 위에서 found_files에 아무것도 안 들어가면 matched 값이 0

#    - name: 2-1. found_files 출력
#      debug:
#        var: found_files

    - name: 3-1. 파일 전송 여부 확인 플래그 초기화
      set_fact:
        file_copied: false

    - name: 3-2. 파일 전송
      include_tasks: task_upload_batch.yml # 해당 Task를 반복 실행
      loop: "{{ system_map }}" # system_map을 기준으로 반복
      loop_control:
        loop_var: map_item # 기본적으로 item이라는 편수에 담는데, 겹치면 안 되니까 변수명 변경

    - name: 4. 배포 스크립트 실행
      shell: "cd {{ remote_dir }} && ./{{ remote_script }}"
      register: script_result
      # hostvars[inventory_hostname]은 작업 중인 서버이고 'file_copied'가 정의 되어 있고 그 값이 true이면 스크립트 실행
      when: hostvars[inventory_hostname]['file_copied'] is defined and hostvars[inventory_hostname]['file_copied']

    - name: 5. 실행 결과 확인
      debug:
        msg: "{{ script_result.stdout_lines }}"
      when: script_result is not skipped # 실행했으면 결과 확인

    - name: 6. 배포 파일 정리
      delegate_to: localhost
      run_once: true
      shell: "mv {{ local_dir }}/*.tar.gz {{ local_dir }}/success/"
      when: found_files.matched > 0

 

이건 3-2에서 사용한 include task의 내용이다.

---
- name: 3-2-1. 파일 전송
  copy: # when 조건에 부합하면(AND) 파일 전송
    src: "{{ item.path }}" 
    dest: "{{ remote_dir }}/{{ item.path | basename }}"
  when:
    - map_item.group in group_names # 실행 서버가 해당 group에 포함되는지
    - map_item.key in (item.path | basename) # 대상 파일 이름에 해당 key가포함되는지
  loop: "{{ found_files.files }}"
  register: copy_result # 전송 결과 저장
- name: 3-2-2. 파일 전송 여부 확인 플래그 설정
  set_fact:
    file_copied: true
  # copy_result를 목록으로 받아서 results를 보고, 이 중에changed가 true인 결과만 list로 만들고, 
  # 이게 1개라도 있으면 플래그를 true로 설정
  when: copy_result.results | selectattr('changed', 'equalto', true) | list | length > 0

delegate_to: localhost가 없으면 기본적으로 모든 대상서버에서 작업을 수행한다.

'DevOps' 카테고리의 다른 글

[Ansible] RHEL 7.8 폐쇄망 설치  (0) 2026.01.30

+ Recent posts