사용자 정의, Git 및 시스템 역할을 사용하여 플레이북 조립 및 실행
이 단계에서는 준비한 모든 구성 요소, 즉 사용자 정의 역할, Git 의 종속성 및 RHEL 시스템 역할을 통합합니다. 이러한 역할을 오케스트레이션하여 개발 웹 서버를 완전히 구성하는 메인 플레이북을 생성합니다.
이 단계를 다양한 부품으로 복잡한 기계를 조립하는 것으로 생각하십시오. 각 역할은 특정 목적을 수행하며 함께 작동하여 완전한 웹 서버 환경을 만듭니다. 이를 관리 가능한 조각으로 나누어 보겠습니다.
먼저 메인 프로젝트 디렉토리에 있는지 확인하십시오.
cd ~/project
구성에 들어가기 전에 무엇을 만들고 있는지 이해해 봅시다.
- Ansible 구성: Ansible 의 동작 방식과 파일 위치를 설정합니다.
- 인벤토리: 관리할 서버를 정의합니다 (이 경우 localhost).
- 변수: 역할에서 사용할 데이터를 저장합니다 (개발자 정보, SELinux 설정).
- 사용자 정의 역할 콘텐츠: 개발자 환경을 구성할 실제 작업입니다.
- 메인 플레이북: 모든 것을 올바른 순서로 실행하는 오케스트레이터입니다.
1. Ansible 구성 및 인벤토리 생성
ansible.cfg 파일은 Ansible 의 동작 방식을 알려주는 구성 파일과 같습니다. 이 파일이 없으면 모든 명령에서 경로와 옵션을 지정해야 합니다. 이 파일을 사용하면 Ansible 은 역할, 컬렉션 및 인벤토리의 위치를 자동으로 알게 됩니다.
nano를 사용하여 ansible.cfg 파일을 생성합니다. 이 파일은 Ansible 에 역할, 컬렉션 및 인벤토리의 위치를 알려줍니다.
nano ansible.cfg
다음 내용을 추가하십시오. 각 줄을 이해해 봅시다.
[defaults]
inventory = inventory
roles_path = roles
collections_paths = collections
host_key_checking = False
[privilege_escalation]
become = True
각 설정의 기능:
inventory = inventory: 매번 -i inventory를 입력하는 대신 Ansible 이 이 파일을 자동으로 사용합니다.
roles_path = roles: Ansible 은 roles 디렉토리에서 역할을 찾습니다.
collections_paths = collections: Ansible 은 설치된 컬렉션을 여기서 찾습니다.
host_key_checking = False: 실험실 환경에서 SSH 키 확인 오류를 방지합니다.
become = True: 필요한 경우 권한이 상승된 상태로 작업을 자동으로 실행합니다.
nano를 저장하고 종료합니다 (Ctrl+X를 누른 다음 Y를 누르고 Enter를 누릅니다).
인벤토리 파일은 Ansible 이 관리할 머신을 알려줍니다. 이 경우 로컬 머신을 구성합니다.
nano inventory
다음 줄을 추가하십시오.
localhost ansible_connection=local
이것의 의미:
localhost: 대상 호스트의 이름입니다.
ansible_connection=local: SSH 대신 로컬 연결을 사용합니다 (Ansible 을 실행하는 동일한 머신을 관리하는 경우).
nano를 저장하고 종료합니다.
2. 역할 변수 정의
Ansible 의 변수는 역할에서 사용할 수 있는 설정과 같습니다. 작업에 사용자 이름이나 포트 번호와 같은 값을 하드코딩하는 대신 변수 파일에 정의합니다. 이렇게 하면 자동화가 유연하고 재사용 가능해집니다.
group_vars/all 디렉토리는 모든 호스트에 적용되는 변수를 Ansible 이 자동으로 로드하는 특별한 위치입니다. 이 디렉토리의 모든 YAML 파일은 플레이북 및 역할에서 사용할 수 있습니다.
모든 호스트에 적용되는 변수에 대한 디렉토리 구조를 생성합니다.
mkdir -p group_vars/all
이제 개발자 정보를 정의하는 파일을 생성합니다. 이 데이터는 사용자 정의 역할에서 사용자 계정 및 웹 구성을 만드는 데 사용됩니다.
nano group_vars/all/developers.yml
다음 내용을 추가하십시오.
---
web_developers:
- username: jdoe ## 첫 번째 개발자
port: 9081 ## 이 개발자의 웹사이트에 대한 사용자 정의 포트
- username: jdoe2 ## 두 번째 개발자
port: 9082 ## 이 개발자의 웹사이트에 대한 사용자 정의 포트
이 데이터 구조의 의미:
web_developers: 개발자 정보를 포함하는 목록입니다.
- 각 개발자에는
username과 port가 있습니다.
- 사용자 정의 역할은 이 목록을 반복하여 각 개발자에 대한 구성을 생성합니다.
저장하고 종료합니다.
다음으로 SELinux 구성에 대한 변수 파일을 생성합니다. SELinux (Security-Enhanced Linux) 는 애플리케이션이 수행할 수 있는 작업을 제어하는 보안 모듈입니다.
nano group_vars/all/selinux.yml
다음 내용을 추가하십시오.
---
selinux_state: enforcing ## SELinux 를 enforcing 모드로 설정 (최고 보안)
selinux_ports: ## Apache 가 사용할 수 있도록 허용할 포트 목록
- ports: "9081" ## 포트 9081 허용
proto: "tcp" ## 프로토콜: TCP
setype: "http_port_t" ## SELinux 유형: HTTP 포트
state: "present" ## 이 규칙 추가
- ports: "9082" ## 포트 9082 허용
proto: "tcp" ## 프로토콜: TCP
setype: "http_port_t" ## SELinux 유형: HTTP 포트
state: "present" ## 이 규칙 추가
SELinux 설정 이해:
selinux_state: enforcing: SELinux 는 승인되지 않은 작업을 적극적으로 차단합니다.
selinux_ports: 포트 구성 목록입니다.
http_port_t: Apache 가 포트에 바인딩할 수 있도록 허용하는 SELinux 유형입니다.
- 기본적으로 Apache 는 포트 80 및 443 만 사용할 수 있습니다. 9081 및 9082 를 명시적으로 허용해야 합니다.
저장하고 종료합니다.
3. 사용자 정의 역할 채우기
apache.developer_configs 역할에는 현재 디렉토리 구조는 있지만 실제 콘텐츠는 없습니다. 다음을 추가해야 합니다.
- 템플릿: 변수를 포함할 수 있는 파일 (Jinja2 구문 사용).
- 작업: Ansible 이 수행할 실제 작업입니다.
- 핸들러: 알림을 받을 때만 실행되는 특수 작업입니다 (서비스 다시 시작 등).
- 메타데이터: 역할 종속성에 대한 정보입니다.
템플릿을 사용하면 변수에 따라 조정되는 구성 파일을 만들 수 있습니다. .j2 확장자는 Jinja2 템플릿임을 나타냅니다.
nano roles/apache.developer_configs/templates/developer.conf.j2
다음 내용을 추가하십시오.
{% for dev in web_developers %}
Listen {{ dev.port }}
<VirtualHost *:{{ dev.port }}>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/{{ dev.username }}
<Directory /var/www/{{ dev.username }}>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
</VirtualHost>
{% endfor %}
템플릿 구문 이해:
{% for dev in web_developers %}: 개발자 목록을 반복합니다.
{{ dev.port }}: 이 개발자의 포트 번호를 삽입합니다.
{{ dev.username }}: 이 개발자의 사용자 이름을 삽입합니다.
{% endfor %}: 루프를 종료합니다.
- 결과는 각 개발자에 대한 별도의 가상 호스트 구성이 됩니다.
이것이 만드는 것: 두 개발자의 경우 이 템플릿은 다음과 같은 Apache 구성을 생성합니다.
- Apache 가 포트 9081 및 9082 에서 수신 대기하도록 합니다.
/var/www/jdoe 및 /var/www/jdoe2에서 콘텐츠를 제공하는 가상 호스트를 생성합니다.
- 각 디렉토리에 대한 적절한 권한을 설정합니다.
저장하고 종료합니다.
작업은 Ansible 이 수행하는 실제 작업입니다. 각 작업은 특정 작업을 수행하기 위해 Ansible 모듈을 사용합니다.
nano roles/apache.developer_configs/tasks/main.yml
다음 내용을 추가하고 각 작업을 이해해 봅시다.
---
## 작업 1: 각 개발자에 대한 사용자 계정 생성
- name: Create developer user accounts
ansible.builtin.user: ## 'user' 모듈 사용
name: "{{ item.username }}" ## 이 이름으로 사용자 생성
state: present ## 사용자가 존재하는지 확인
loop: "{{ web_developers }}" ## 목록의 각 개발자에 대해 이 작업 수행
## 작업 2: 각 개발자에 대한 웹 디렉토리 생성
- name: Create developer web root directories
ansible.builtin.file: ## 'file' 모듈 사용
path: "/var/www/{{ item.username }}" ## 이 디렉토리 생성
state: directory ## 디렉토리인지 확인
owner: "{{ item.username }}" ## 소유자 설정
group: "{{ item.username }}" ## 그룹 설정
mode: "0755" ## 권한 설정 (rwxr-xr-x)
loop: "{{ web_developers }}"
## 작업 3: 각 개발자에 대한 샘플 웹페이지 생성
- name: Create a sample index.html for each developer
ansible.builtin.copy: ## 'copy' 모듈 사용
content: "Welcome to {{ item.username }}'s dev space\n" ## 파일 내용
dest: "/var/www/{{ item.username }}/index.html" ## 파일 위치
owner: "{{ item.username }}" ## 파일 소유자
group: "{{ item.username }}" ## 파일 그룹
mode: "0644" ## 파일 권한 (rw-r--r--)
loop: "{{ web_developers }}"
## 작업 4: Apache 구성 파일 배포
- name: Deploy developer apache configs
ansible.builtin.template: ## 'template' 모듈 사용
src: developer.conf.j2 ## 소스 템플릿 파일
dest: /etc/httpd/conf.d/developer.conf ## 서버의 대상
mode: "0644" ## 파일 권한
notify: restart apache ## 변경 시 restart apache 핸들러 트리거
주요 개념 이해:
loop: 목록의 각 항목에 대해 작업을 반복합니다.
{{ item.username }}: 루프에서 현재 항목의 사용자 이름을 참조합니다.
notify: restart apache: 이 작업이 변경되면 "restart apache"라는 핸들러를 트리거합니다.
- 파일 권한:
0755는 소유자가 읽기/쓰기/실행 가능하고 다른 사용자는 읽기/실행 가능함을 의미합니다. 0644는 소유자가 읽기/쓰기 가능하고 다른 사용자는 읽기만 가능함을 의미합니다.
저장하고 종료합니다.
핸들러는 다른 작업에서 알림을 받을 때만 실행되는 특수 작업입니다. 일반적으로 서비스 다시 시작과 같은 작업에 사용됩니다.
nano roles/apache.developer_configs/handlers/main.yml
다음 내용을 추가하십시오.
---
- name: restart apache ## 이 이름은 notify: 문과 일치해야 합니다.
ansible.builtin.service: ## 'service' 모듈 사용
name: httpd ## 서비스 이름 (Apache 는 RHEL 에서 'httpd'라고 합니다)
state: restarted ## 서비스 다시 시작
핸들러를 사용하는 이유:
- 효율성: 구성이 실제로 변경된 경우에만 서비스가 다시 시작됩니다.
- 순서: 모든 작업이 먼저 실행된 다음 모든 핸들러가 마지막에 실행됩니다.
- 멱등성: 여러 작업이 동일한 핸들러를 알릴 수 있지만 한 번만 실행됩니다.
저장하고 종료합니다.
마지막으로 사용자 정의 역할이 이전에 설치한 infra.apache 역할에 종속된다는 것을 Ansible 에 알려야 합니다.
nano roles/apache.developer_configs/meta/main.yml
파일의 내용을 다음으로 바꾸십시오.
---
dependencies:
- role: infra.apache ## 이 역할은 사용자 정의 역할보다 먼저 실행되어야 합니다.
이것이 하는 일:
- Ansible 이
apache.developer_configs를 실행하면 infra.apache를 먼저 자동으로 실행합니다.
- 이렇게 하면 사용자 정의 구성을 추가하기 전에 Apache 가 설치되고 구성됩니다.
- 종속성은 나열된 순서대로 실행됩니다.
저장하고 종료합니다.
4. 메인 플레이북 조립 및 실행
플레이북은 Ansible 에 무엇을 해야 하는지, 어떤 순서로 해야 하는지를 알려주는 레시피와 같습니다. 플레이북은 다음을 수행합니다.
- SELinux 설정 구성 (pre_tasks).
- 역할 실행 (종속성 체인 포함).
메인 플레이북 파일을 생성합니다.
nano web_dev_server.yml
자세한 설명과 함께 다음 내용을 추가하십시오.
---
- name: Configure Dev Web Server ## 플레이북 이름
hosts: localhost ## localhost 에서 실행
pre_tasks: ## 역할 전에 실행되는 작업
## 작업 1: SELinux 모드 구성
- name: Set SELinux to enforcing mode
ansible.posix.selinux: ## ansible.posix 컬렉션의 모듈
policy: targeted ## 'targeted' SELinux 정책 사용
state: "{{ selinux_state }}" ## 정의한 변수 사용
when: selinux_state is defined ## 변수가 정의된 경우에만 실행
## 작업 2: SELinux 포트 구성
- name: Configure SELinux ports for Apache
community.general.seport: ## community.general 컬렉션의 모듈
ports: "{{ item.ports }}" ## 포트 번호
proto: "{{ item.proto }}" ## 프로토콜 (tcp)
setype: "{{ item.setype }}" ## SELinux 유형 (http_port_t)
state: "{{ item.state }}" ## present 또는 absent
loop: "{{ selinux_ports }}" ## 포트 목록 반복
when: selinux_ports is defined ## 변수가 정의된 경우에만 실행
roles: ## 실행할 역할
- apache.developer_configs ## 사용자 정의 역할 (infra.apache 트리거)
실행 순서 이해:
pre_tasks: SELinux 구성이 먼저 실행됩니다.
roles: 역할 종속성이 실행되고 (infra.apache), 사용자 정의 역할이 실행됩니다.
handlers: 알림을 받은 핸들러가 마지막에 실행됩니다.
이 순서가 중요한 이유:
- Apache 가 사용자 정의 포트에 바인딩을 시도하기 전에 SELinux 를 구성해야 합니다.
- 가상 호스트를 구성하기 전에 Apache 를 설치해야 합니다.
- 모든 구성이 완료된 후에 서비스 다시 시작이 발생합니다.
저장하고 종료합니다.
이제 완전한 자동화를 실행할 준비가 되었습니다.
ansible-playbook web_dev_server.yml
플레이북이 실행되고 자세한 출력이 표시됩니다. 예상되는 내용은 다음과 같습니다 (예시).
PLAY [Configure Dev Web Server] *************************************************
TASK [Gathering Facts] **********************************************************
ok: [localhost] ## Ansible이 시스템 정보를 수집합니다.
TASK [Set SELinux to enforcing mode] *******************************************
changed: [localhost] ## SELinux 모드가 변경되었습니다.
TASK [Configure SELinux ports for Apache] **************************************
changed: [localhost] => (item={'ports': '9081', 'proto': 'tcp', 'setype': 'http_port_t', 'state': 'present'})
changed: [localhost] => (item={'ports': '9082', 'proto': 'tcp', 'setype': 'http_port_t', 'state': 'present'})
TASK [infra.apache : Ensure Apache is installed.] *******************************
changed: [localhost] ## Apache 패키지가 설치되었습니다.
TASK [apache.developer_configs : Create developer user accounts] ****************
changed: [localhost] => (item={'username': 'jdoe', 'port': 9081})
changed: [localhost] => (item={'username': 'jdoe2', 'port': 9082})
TASK [apache.developer_configs : Create developer web root directories] *********
changed: [localhost] => (item={'username': 'jdoe', 'port': 9081})
changed: [localhost] => (item={'username': 'jdoe2', 'port': 9082})
TASK [apache.developer_configs : Create a sample index.html for each developer] *
changed: [localhost] => (item={'username': 'jdoe', 'port': 9081})
changed: [localhost] => (item={'username': 'jdoe2', 'port': 9082})
TASK [apache.developer_configs : Deploy developer apache configs] ***************
changed: [localhost] ## 구성 파일이 생성되었습니다.
RUNNING HANDLER [apache.developer_configs : restart apache] *********************
changed: [localhost] ## Apache가 다시 시작되었습니다.
PLAY RECAP **********************************************************************
localhost : ok=17 changed=12 unreachable=0 failed=0 skipped=3 rescued=0 ignored=0
다양한 소스의 여러 역할을 결합하여 완전한 웹 개발 환경을 만들기 위해 복잡한 플레이북을 성공적으로 조립하고 실행했습니다!