Project/개인 Project

[인프라 관리] Ansible을 이용한 소프트웨어 설정 변경 테스트

강_토발즈 2026. 8. 17. 23:52

 

 

 

미들웨어를 직접 설정하는 업무에서  대부분의 작업은 SSH로 서버에 접속하여 수동으로 명령어를 입력하고 설정 파일을 편집하는 방식으로 진행된다. 이번에는 반복적인 설정 작업을 자동화하기 위해 Ansible을 처음으로 학습하고, 테스트 서버의 Tomcat 포트를 변경하는 실습을 진행하였다.

오늘은 Ansible 설치부터 SSH 접속 문제 해결, Playbook 작성, 그리고 실제 포트 변경까지의 전 과정을 단계별로 정리한다.

<< Ansible이란? >>

Ansible은 서버 설정 작업을 자동화하는 오픈소스 도구이다. 별도의 에이전트 설치 없이 SSH만으로 대상 서버에 접속하여 작업을 수행한다는 점이 특징이다. 사람이 SSH로 접속하여 수행하던 명령어와 설정 변경 작업을 YAML 형식의 파일(Playbook)로 기술하고, 이를 실행하면 지정된 서버들에 동일한 작업이 일괄 적용되는 구조이다.

Ansible의 핵심 구성 요소는 다음과 같다.

  • Inventory: 작업 대상이 되는 서버 목록을 정의하는 파일
  • Playbook: 수행할 작업의 순서를 YAML로 기술한 파일
  • Module: 파일 편집, 서비스 제어 등 실제 작업을 수행하는 단위

 

 

1. 실습 환경

  • 제어 노드(Control Node): Ubuntu 로컬 PC
  • 대상 서버(Managed Node): PostgreSQL, Kafka, RabbitMQ, Redis, Tomcat이 설치된 테스트 서버 (192.168.139.76)
  • 테스트 대상: Tomcat 10.1.7, 설치 경로 /home/solink/software/apache-tomcat-10.1.7
  • 목표: Tomcat HTTP 커넥터 포트를 8080에서 9090으로 변경

2. Ansible 설치

제어 노드에 Ansible을 설치한다.

apt install ansible

 

설치 확인은 다음 명령어로 진행한다.

ansible --version

 

3. SSH 접속 환경 준비

Ansible은 SSH를 통해 대상 서버에 접속하므로, 비밀번호 없이 접속 가능한 SSH 키 인증 환경을 먼저 구성해야 한다.

 

3-1. SSH 포트가 기본값(22)이 아닌 경우

테스트 서버는 SSH 접속에 기본 포트가 아닌 별도 포트(*******)를 사용하고 있었다. 이 경우 Inventory 파일에 포트를 명시해야 한다.

 
Inventory.ini
[test]
192.168.139.76 ansible_user=kangsinwoong ansible_port=******

3-2. SSH 키 미등록으로 인한 접속 실패

처음 ping 모듈로 접속을 테스트했을 때 다음과 같은 오류가 발생하였다.

 
ansible test -i inventory.ini -m ping
 
192.168.139.76 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: kangsinwoong@192.168.139.76: Permission denied (publickey,password).",
    "unreachable": true
}

 

원인은 로컬 PC에 SSH 키가 아예 생성되어 있지 않았기 때문이었다. 다음 순서로 문제를 해결하였다.

 

키 생성

ssh-keygen -t ed25519

생성된 공개키를 대상 서버에 등록. 이때 SSH 포트가 기본값이 아니므로 -p 옵션을 반드시 지정해야 한다.

 
ssh-copy-id -p 1922 kangsinwoong@192.168.139.76

등록 후 다시 ping 모듈을 실행하여 정상 접속을 확인하였다.

 
ansible test -i inventory.ini -m ping

 

 
192.168.139.76 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

 

4. Tomcat 서버 환경 확인

Playbook 작성에 앞서 대상 서버의 Tomcat 설치 경로와 실행 방식을 확인하였다.

  • 설치 경로: /home/solink/software/apache-tomcat-10.1.7
  • 실행 방식: bin/startup.sh, bin/shutdown.sh 스크립트를 이용한 구동 (systemd 서비스 아님)
  • 파일 소유자: solink (SSH 접속 계정과는 다른 계정)

접속 계정은 sudo -i를 통해 root 권한 전환이 가능한 상태였다. 이 환경 조건에 맞추어 Playbook의 권한 구조를 설계하였다.

 

5. Playbook 작성

5-1. 권한 구조 설계 시 겪은 문제

처음에는 become_user: solink를 태스크 전체에 지정하는 방식으로 작성하였으나, 다음과 같은 오류가 발생하였다.

 
fatal: [192.168.139.76]: FAILED! => {"msg": "Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user (rc: 1, err: chown: changing ownership of '/var/tmp/ansible-tmp-...': Operation not permitted\n...

접속 계정에서 곧바로 solink 계정으로 전환을 시도하면서 임시 파일의 소유권 변경이 거부되는 문제였다. 이를 해결하기 위해 become: true로 root 권한을 확보한 뒤, Tomcat 프로세스를 구동해야 하는 작업에 한해서만 runuser 명령어로 solink 계정 전환을 처리하는 방식으로 변경하였다.

 

5-2. 최종 Playbook

 
yaml
---
- name: Tomcat 포트를 8080에서 9090으로 변경 (script 기반)
  hosts: test
  become: true

  vars:
    catalina_home: /home/solink/software/apache-tomcat-10.1.7
    server_xml: "{{ catalina_home }}/conf/server.xml"
    tomcat_user: solink

  tasks:
    - name: 변경 전 server.xml 백업
      copy:
        src: "{{ server_xml }}"
        dest: "{{ server_xml }}.bak"
        remote_src: true
        owner: "{{ tomcat_user }}"
        group: "{{ tomcat_user }}"

    - name: Tomcat 종료 (root가 solink로 runuser 전환하여 실행)
      command: "runuser -l {{ tomcat_user }} -c '{{ catalina_home }}/bin/shutdown.sh'"

    - name: 잠시 대기 (프로세스 정상 종료 시간 확보)
      pause:
        seconds: 5

    - name: server.xml에서 8080 포트를 9090으로 교체
      lineinfile:
        path: "{{ server_xml }}"
        regexp: '(<Connector port=")8080("\s+protocol="HTTP/1.1")'
        line: '\g<1>9090\g<2>'
        backrefs: true

    - name: Tomcat 시작 (root가 solink로 runuser 전환하여 실행)
      command: "runuser -l {{ tomcat_user }} -c '{{ catalina_home }}/bin/startup.sh'"

    - name: 기동 대기
      pause:
        seconds: 8

    - name: 9090 포트 리스닝 확인
      shell: "ss -tlnp | grep 9090"
      register: port_check
      changed_when: false

    - name: 결과 출력
      debug:
        var: port_check.stdout

6. Dry-run으로 사전 검증

실제 서버에 반영하기 전, --check --diff 옵션으로 변경 내용을 미리 확인하였다. 이 옵션은 실제로 파일을 수정하지 않고 변경될 내용만 보여주는 시뮬레이션 기능이다.

 
ansible-playbook -i inventory.ini change_tomcat_port.yml --check --diff

첫 번째 dry-run 결과에서 정규식 치환 과정에 공백이 포함되는 실수를 발견하였다.

 

-    <Connector port="8080" protocol="HTTP/1.1"
+<Connector port=" 9090" protocol="HTTP/1.1"

port=" 9090"과 같이 따옴표 안에 불필요한 공백이 포함된 것을 확인하고, Playbook의 치환 표현식을 다음과 같이 수정하였다.

 

line: '\g<1>9090\g<2>'

수정 후 다시 dry-run을 실행하여 공백 없이 정상적으로 치환되는 것을 확인하였다.

 
-    <Connector port="8080" protocol="HTTP/1.1"
+<Connector port="9090" protocol="HTTP/1.1"

 

7. 실제 적용 및 결과 확인

Dry-run 검증을 마친 후 --check 옵션 없이 Playbook을 실행하여 실제로 변경 사항을 적용하였다.

ansible-playbook -i inventory.ini change_tomcat_port.yml

 

Playbook 실행이 완료된 후 서버의 server.xml 파일을 직접 열어 포트가 9090으로 정상 변경된 것을 확인하였다.

 

 

 

마무리

이번 실습을 통해 평소 수동으로 진행하던 설정 변경 작업을 Ansible Playbook으로 코드화하는 과정을 경험하였다. 단순히 명령어를 자동으로 실행하는 것을 넘어, 다음과 같은 점들을 새롭게 인지하게 되었다.

  • SSH 접속 계정과 파일 소유 계정이 다른 환경에서는 권한 전환 방식을 신중하게 설계해야 한다는 점
  • --check --diff 옵션을 통한 사전 검증이 실수를 미리 발견하는 데 매우 유용하다는 점
  • 정규식 기반 치환 작업은 공백 등 세부 표현까지 정확하게 검증해야 한다는 점

앞으로는 이번에 다룬 단일 서버, 단일 작업 수준을 넘어 여러 서버와 여러 미들웨어를 대상으로 Playbook을 확장해 나갈 예정이다.