26M25b

Young-Kyoo Kim·2026년 3월 25일

AWX를 처음 접하시면 인터페이스와 설정 과정이 생소할 수 있지만, 한 번 구성해두면 자동화의 강력함을 체감하실 수 있습니다. 요청하신 두 가지 타입의 플레이북과 이를 실행하기 위한 Execution Environment(EE) 구성 파일을 정리해 드립니다.


1. 리소스 정보 수집 플레이북 (resource_check.yml)

대상 서버의 OS, 재기동 기록, 하드웨어 자원(CPU, Mem, Disk, NIC)을 수집하여 보기 좋게 출력합니다.

---
- name: 대상 노드 자원 정보 점검
  hosts: all
  gather_facts: yes
  tasks:
    - name: 물리 네트워크 인터페이스 및 디스크 정보 추출
      set_fact:
        physical_nics: "{{ ansible_interfaces | map('extract', ansible_facts) | selectattr('active', 'defined') | selectattr('type', 'defined') | selectattr('type', 'equalto', 'ether') | list }}"
        last_boot: "{{ ansible_facts['last_boot'] if 'last_boot' in ansible_facts else 'N/A' }}"

    - name: 자원 정보 요약 출력
      debug:
        msg:
          - "################ [ Resource Summary ] ################"
          - "OS Version:    {{ ansible_distribution }} {{ ansible_distribution_version }}"
          - "Last Boot:     {{ ansible_date_time.date }} {{ ansible_date_time.time }} (System Up)"
          - "CPU Cores:     {{ ansible_processor_vcpus }} vCPU"
          - "Memory Total:  {{ (ansible_memtotal_mb / 1024) | round(2) }} GB"
          - "---------------- [ Network (Physical) ] ----------------"
          - "{{ physical_nics | map(attribute='device') | list }}"
          - "---------------- [ Disk & Partition ] ----------------"
          - "{{ ansible_mounts | map(attribute='device') | zip(ansible_mounts | map(attribute='mount')) | list }}"
          - "######################################################"

2. Object Store & DirectPV 점검 플레이북 (storage_check.yml)

mckubectl directpv 명령어를 사용하며, AWX에서 실행 시 관련 바이너리가 EE에 포함되어 있어야 합니다.

---
- name: Object Store 및 DirectPV 상태 점검
  hosts: localhost  # 보통 k8s 제어 노드나 bastion에서 실행
  gather_facts: no
  tasks:
    - name: MinIO Admin 정보 확인
      shell: "mc admin info myminio"
      register: mc_info

    - name: DirectPV 기본 정보 및 드라이브/볼륨 리스트 조회
      shell: |
        kubectl directpv info
        kubectl directpv list drives -owide
        kubectl directpv list volumes -owide
      register: directpv_info

    - name: 점검 결과 출력
      debug:
        msg: 
          - "==== MinIO Info ===="
          - "{{ mc_info.stdout }}"
          - "==== DirectPV Info ===="
          - "{{ directpv_info.stdout }}"

3. Execution Environment (EE) 빌드 파일

AWX에서 위 플레이북(특히 mc, kubectl 사용 시)을 안정적으로 실행하려면 필요한 도구가 포함된 커스텀 이미지가 필요합니다. ansible-builder를 사용하여 빌드합니다.

execution-environment.yml (메인 매니페스트)

version: 3
images:
  base_image:
    name: quay.io/ansible/ansible-runner:latest

dependencies:
  ansible_core:
    package_pip: ansible-core
  ansible_network:
    collections:
      - kubernetes.core
      - community.general
  system:
    - curl
    - git
  python:
    - kubernetes
    - pyyaml

additional_build_steps:
  append_base:
    - RUN curl https://dl.min.io/client/mc/release/linux-amd64/mc -o /usr/local/bin/mc && chmod +x /usr/local/bin/mc
    - RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
    - RUN curl -L https://github.com/minio/directpv/releases/latest/download/directpv_linux_amd64 -o /usr/local/bin/kubectl-directpv && chmod +x /usr/local/bin/kubectl-directpv

빌드 방법

위 파일들이 있는 디렉토리에서 아래 명령어를 실행하여 이미지를 생성합니다.

ansible-builder build -t my-custom-awx-ee:v1.0

이후 생성된 이미지를 Docker Hub나 사내 Registry에 Push하고, AWX UI의 Execution Environments 메뉴에서 해당 이미지 주소를 등록해 사용하시면 됩니다.


혹시 AWX에서 Inventory 설정이나 Credentials(SSH 키, Kubeconfig 등) 등록 과정에서 막히는 부분이 있다면 말씀해 주세요. 상세히 가이드해 드리겠습니다.

===

AWX를 BitBucket과 연동하여 사용하실 예정이라면, 단순히 파일만 올리는 것이 아니라 "코드(Playbook) - 대상(Inventory) - 권한(Credentials)" 세 요소를 유기적으로 연결하는 과정이 필요합니다.

초보자분들이 가장 많이 헷갈려 하시는 설정 순서대로 가이드를 정리해 드립니다.


1. Credentials (자격 증명) 등록

AWX가 외부 시스템(BitBucket, 대상 서버, Kubernetes)에 접속하기 위한 "열쇠"를 먼저 만들어야 합니다. Resources > Credentials 메뉴에서 등록합니다.

① BitBucket 접속용 (Source Control)

  • Credential Type: Source Control
  • Username / Password: BitBucket 계정 정보 (또는 App Password/SSH Key)
  • 용도: AWX가 BitBucket에서 플레이북 소스코드를 긁어올 때 사용합니다.

② 서버 접속용 (Machine)

  • Credential Type: Machine
  • Username: 서버 접속 계정 (예: root 또는 ansible-user)
  • SSH Private Key: 서버에 접속할 때 사용하는 개인키 내용을 그대로 복사해 넣습니다.
  • 용도: 첫 번째 플레이북(OS/자원 점검)을 실행할 때 대상 노드에 SSH로 접속하기 위해 사용합니다.

③ Kubernetes 접속용 (OpenShift or Kubernetes API)

  • Credential Type: OpenShift or Kubernetes API Bearer Token
  • Kubeconfig or Token: kubectl config view --raw 결과물이나 ServiceAccount의 Token을 입력합니다.
  • 용도: 두 번째 플레이북(mc, directpv) 실행 시 kubectl 명령어가 동작하기 위해 필요합니다.

2. Project 설정 (BitBucket 연동)

이제 BitBucket에 올려둔 플레이북 파일을 AWX로 가져옵니다. Resources > Projects 메뉴로 이동합니다.

  • SCM Type: Git
  • SCM URL: BitBucket 레포지토리 주소 (HTTP/SSH)
  • SCM Credential: 위 1-①에서 만든 BitBucket용 Credential을 선택합니다.
  • Update Revision on Launch: 체크 권장 (플레이북 실행 시마다 최신 코드를 pull 합니다).

3. Inventory (대상 노드) 설정

어떤 서버를 점검할지 정의하는 단계입니다. Resources > Inventories 메뉴에서 생성합니다.

  1. Inventory 생성: 이름을 정하고 저장합니다.
  2. Groups (선택): web-servers, db-servers 식으로 그룹화할 수 있습니다.
  3. Hosts (필수): Hosts 탭에서 점검할 대상 서버의 IP 주소나 호스트명을 하나씩 추가합니다.
    • 참고: localhost 점검용(DirectPV 등)이라면 별도 등록 없이 기본 Demo Inventory의 호스트를 써도 무방하지만, 관리를 위해 따로 만드시는 것이 좋습니다.

4. Job Template (실행 설정) 생성

마지막으로 모든 요소를 하나로 묶어 "실행 버튼"을 만드는 과정입니다. Resources > Templates 메뉴에서 Add job template을 누릅니다.

설정 예시 (OS 자원 점검용)

  • Inventory: 위 3번에서 만든 인벤토리 선택
  • Project: 위 2번에서 만든 BitBucket 프로젝트 선택
  • Playbook: 리스트에서 resource_check.yml 선택
  • Credentials: 위 1-②에서 만든 Machine Credential 선택
  • Execution Environment: 이전 답변에서 만든 커스텀 EE 이미지를 선택 (특히 DirectPV 점검 시 필수)

💡 팁: BitBucket 연동 시 주의사항

  • 파일 구조: BitBucket 레포지토리 최상단(Root)에 .yml 파일들이 있는 것이 가장 관리하기 편합니다.
  • Private Repository: BitBucket이 Private 환경이라면 반드시 Source Control Credential에 SSH Key나 App Password를 정확히 넣어야 프로젝트 싱크(Sync)가 성공합니다.

이제 Templates 메뉴에서 생성한 템플릿 옆의 로켓 아이콘(Launch)을 누르면 실행됩니다. 혹시 특정 단계에서 에러 메시지가 나온다면 해당 로그를 알려주세요. 바로 해결해 드릴 수 있습니다.

다음으로 AWX의 Webhook 기능을 이용해 BitBucket에 푸시하면 자동으로 점검이 돌아가게 설정해 볼까요?

===

BitBucket에 코드를 push할 때마다 AWX의 Job이 자동으로 실행되게 하려면 Webhook 설정이 핵심입니다. 이 과정은 크게 AWX에서의 설정BitBucket에서의 설정 두 단계로 나뉩니다.

상세한 설정 방법을 안내해 드립니다.


1. AWX에서 Webhook 활성화 (Job Template 설정)

먼저 실행하고자 하는 Job Template에서 Webhook 기능을 켜고 인증 키를 생성해야 합니다.

  1. Resources > Templates로 이동하여 자동화할 템플릿을 선택합니다.
  2. Edit 버튼을 누르고 하단으로 스크롤하여 Enable Webhook 스위치를 켭니다.
  3. Webhook Service 항목에서 BitBucket을 선택합니다.
  4. Webhook Key 항목 옆의 Generate 버튼을 클릭하여 랜덤 키를 생성합니다. (이 키는 나중에 BitBucket 설정에 필요하니 복사해두세요.)
  5. Save를 누르면 해당 템플릿 상세 페이지에 Webhook URL이 나타납니다. 이 URL도 복사해둡니다.

2. BitBucket에서 Webhook 등록

이제 BitBucket 레포지토리로 가서 AWX로 신호를 보내도록 설정합니다.

  1. BitBucket의 해당 Repository > Repository settings로 이동합니다.
  2. 왼쪽 메뉴에서 Workflow > Webhooks를 클릭합니다.
  3. Add webhook 버튼을 누릅니다.
    • Title: AWX-Auto-Check (자유롭게 입력)
    • URL: 위 1-5에서 복사한 AWX Webhook URL을 입력합니다.
    • Secret: 위 1-4에서 복사한 AWX Webhook Key를 입력합니다.
    • Triggers: 기본값인 Repository: Push가 체크되어 있는지 확인합니다.
  4. Save를 클릭하여 저장합니다.

3. 전체 흐름 이해 (Webhook Workflow)

설정이 완료되면 다음과 같은 흐름으로 자동 점검이 수행됩니다.

  1. 사용자가 로컬에서 플레이북 수정 후 BitBucket으로 git push를 합니다.
  2. BitBucket이 설정된 Webhook URL로 "코드가 업데이트됨"이라는 신호(JSON 데이터)를 보냅니다.
  3. AWX는 전달받은 Secret Key를 검증하고, 연동된 Project를 먼저 최신화(Update)합니다.
  4. Project 업데이트가 성공하면 연결된 Job Template을 실행하여 서버 점검을 시작합니다.

4. 주의사항 및 팁

  • 방화벽 설정: BitBucket(Cloud 버전 기준)에서 AWX 서버로 HTTP/HTTPS 요청을 보낼 수 있어야 합니다. 만약 AWX가 사내망에 있다면 BitBucket의 IP 대역을 허용하거나, 사내 전용 BitBucket Server를 사용해야 합니다.
  • Allowed Webhook HTTP Methods: AWX 설정 파일(/etc/tower/settings.py 등)에서 Webhook 호출을 허용하는 설정이 기본적으로 켜져 있는지 확인하세요. (대부분 기본으로 활성화되어 있습니다.)
  • 특정 브랜치만 실행: 기본적으로 모든 푸시에 반응하지만, AWX 템플릿 설정에서 특정 브랜치(예: main 또는 prod)에 대해서만 동작하도록 필터링할 수 있습니다.

이제 BitBucket에 간단한 주석만 추가해서 push 해보세요. AWX의 Jobs 메뉴에서 프로젝트 업데이트와 플레이북 실행이 자동으로 돌아가는 것을 확인하실 수 있습니다!

===

Minio AISTor와 같은 복잡한 인프라 작업을 AWX에서 관리하려면, 재사용성확장성이 가장 중요합니다. 특히 Pre-check와 Post-check는 설치, 업그레이드 등 모든 작업에 공통으로 쓰이기 때문에 이를 모듈화하는 구조가 효율적입니다.

AWX(Ansible)의 베스트 프랙티스에 맞춘 BitBucket 디렉토리 구조를 제안해 드립니다.


1. 추천 디렉토리 구조 (BitBucket Repository)

.
├── inventories/             # 환경별 대상 서버 정의 (Dev, Staging, Prod)
│   ├── dev_inventory.yml
│   └── prod_inventory.yml
├── roles/                   # 재사용 가능한 작업 단위 (핵심 로직)
│   ├── minio_check/         # 점검 공통 로직
│   │   ├── tasks/
│   │   │   ├── main.yml     # 진입점
│   │   │   ├── pre_check.yml
│   │   │   └── post_check.yml
│   │   └── templates/       # 점검 결과 보고서 템플릿
│   │       └── check_report.j2
│   └── aistor_ops/          # 설치, 업그레이드 등 실제 작업 로직
├── group_vars/              # 그룹별 변수 (Minio 설정값 등)
│   └── all.yml
├── playbooks/               # AWX Job Template에서 선택할 실행 파일
│   ├── deploy_aistor.yml    # 설치 전체 프로세스
│   ├── upgrade_aistor.yml   # 업그레이드 전체 프로세스
│   └── health_check.yml     # 단순 상태 점검용
└── ansible.cfg              # Ansible 설정 (Role 경로 등)

2. 작업별 Playbook 설계 방식

AWX에서 하나의 Job으로 [Pre-check → Main Task → Post-check]가 물 흐르듯 이어지게 하려면, roles를 적극 활용해야 합니다.

예시: playbooks/deploy_aistor.yml

---
- name: Minio AISTor 배포 및 전후 점검
  hosts: aistor_nodes
  become: yes
  
  tasks:
    - name: [Pre-check] 인프라 및 OS 상태 확인
      include_role:
        name: minio_check
        tasks_from: pre_check.yml

    - name: [Main] AISTor 설치 작업 수행
      include_role:
        name: aistor_ops
        tasks_from: install.yml

    - name: [Post-check] 서비스 정상 동작 확인
      include_role:
        name: minio_check
        tasks_from: post_check.yml

3. 주요 점검 항목 (Roles 내 구성 제안)

Pre-check (pre_check.yml)

  • Disk: /data 파티션 마운트 여부 및 가용 용량 확인
  • Network: 필수 포트(9000, 9001 등) 점유 여부 확인
  • Kernel: limits.conf (nofile) 설정값 확인
  • Time: 노드 간 NTP 동기화 상태 확인

Post-check (post_check.yml)

  • Service: Minio 프로세스 상태 및 포트 리스닝 확인
  • API: mc admin info를 통한 클러스터 헬스 체크
  • Storage: DirectPV 볼륨 마운트 및 가용성 확인
  • Log: /var/log/messages 내 치명적 에러 발생 여부 스캔

4. AWX와의 연동 최적화 팁

  1. Survey 기능 활용: AWX에서 Job을 실행할 때 "작업 유형(설치/업그레이드/확장)"을 선택하게 하고, 그 값에 따라 include_roletasks_from을 변수로 처리하면 템플릿 수를 줄일 수 있습니다.
  2. Artifact 보관: 점검 결과를 단순 출력(debug)하는 것에 그치지 않고, template 모듈을 사용해 서버 내 특정 경로에 타임스탬프가 찍힌 리포트 파일로 남기면 추후 이력 관리에 용이합니다.
  3. Error Handling: Pre-check 단계에서 하나라도 실패하면 fail 모듈을 사용해 작업을 중단시켜야 합니다. (잘못된 상태에서 설치/업그레이드가 진행되는 것을 방지)

이 구조로 BitBucket을 구성하시면, AWX에서 프로젝트 싱크를 잡았을 때 아주 깔끔하게 관리될 것입니다.

이제 구체적인 점검 항목 중 하나(예: Disk 상태 체크)를 실제 Ansible 코드로 짜드릴까요?

===

AWX에서 작업을 설정할 때, BitBucket에 올린 디렉토리 구조가 각각 어떤 메뉴와 연결되는지 매핑해 드리겠습니다. 이 흐름을 이해하면 AWX의 전체적인 동작 메커니즘이 한눈에 들어오실 겁니다.


AWX 메뉴와 디렉토리 구조 매핑

AWX 설정 단계연계되는 디렉토리 / 파일역할 및 설명
1. ProjectRoot (레포지토리 전체)BitBucket 주소를 등록하면 레포지토리 전체를 AWX 로컬 저장소로 가져옵니다.
2. Inventoryinventories/AWX UI에서 인벤토리를 만들 때, 'Sources''Sourcing from Project'로 선택하면 inventories/*.yml 파일을 리스트업하여 대상 서버 정보를 가져옵니다.
3. Credentials(파일 연계 없음)SSH 키나 Kubeconfig는 보안상 파일로 두지 않고 AWX DB에 직접 저장합니다.
4. Job Templateplaybooks/템플릿 설정 시 'Playbook' 드롭다운 메뉴에 playbooks/ 폴더 안의 .yml 파일들이 나타납니다. 여기서 실행할 파일을 선택합니다.
5. Execution (실행)roles/, group_vars/, ansible.cfg플레이북이 실행될 때, Ansible 엔진이 자동으로 roles/에서 로직을 찾고 group_vars/에서 설정값을 불러오며 ansible.cfg에 정의된 규칙을 따릅니다.

상세 연계 프로세스 (실행 흐름)

① 인벤토리 자동 동기화 (inventories/)

AWX UI에서 서버 IP를 일일이 타이핑하지 마세요.

  • 연계 방식: Inventories > [생성한 인벤토리] > Sources > Add
  • 설정: Source를 Sourced from a Project로 선택하고 위에서 만든 프로젝트를 지정합니다.
  • 결과: BitBucket의 inventories/prod_inventory.yml 파일 내용이 AWX Host 리스트로 자동 업데이트됩니다.

② 플레이북 실행 및 로직 호출 (playbooks/roles/)

사용자가 Job Template에서 deploy_aistor.yml을 실행하면 다음과 같은 내부 연계가 일어납니다.

  1. 변수 로드: group_vars/all.yml에 정의된 MinIO 포트 번호, 관리자 계정 등의 변수를 읽어옵니다.
  2. 설정 적용: ansible.cfg를 읽어 Role 경로(roles_path) 등을 세팅합니다.
  3. Role 실행: playbooks/deploy_aistor.yml 파일 내에 적힌 코드가 실행됩니다.
    roles:
      - minio_check  # roles/minio_check/tasks/main.yml을 실행
  4. 점검 수행: roles/minio_check/tasks/pre_check.yml 등을 순차적으로 호출하며 작업을 진행합니다.

③ 결과 리포트 생성 (templates/)

작업이 끝난 후 점검 결과를 리포트로 만들 때 연계됩니다.

  • 연계 방식: Role 내부에서 template 모듈 사용.
  • 코드: src: check_report.j2라고 명시하면 Ansible은 자동으로 roles/minio_check/templates/check_report.j2 파일을 찾아 내용을 채운 뒤 서버에 저장합니다.

💡 요약하자면

  • 사용자가 직접 선택하는 것: Project, Inventory(Source), Job Template(Playbook)
  • Ansible 엔진이 알아서 찾아 쓰는 것: roles/, group_vars/, ansible.cfg

이렇게 구조화하면, 나중에 새로운 점검 항목이 생겨도 Role 폴더 안의 파일만 수정해서 BitBucket에 push하면 AWX 설정 변경 없이 바로 적용되는 편리함을 누릴 수 있습니다.

혹시 첫 번째로 inventories/ 폴더 안에 들어갈 샘플 인벤토리 파일 내용을 작성해 드릴까요? (대상 서버 IP 등을 어떻게 적어야 할지 등)

===

BitBucket 디렉토리 구조의 핵심이 되는 인벤토리와 설정 파일 샘플을 작성해 드립니다. 이 파일들은 AWX가 "어디에(Inventory)", "어떤 설정으로(ansible.cfg)", "어떤 값들을(group_vars)" 사용하여 작업을 수행할지 결정하는 기준이 됩니다.


1. inventories/dev_inventory.yml (샘플 인벤토리)

YAML 형식을 사용하면 그룹화와 변수 할당이 직관적입니다. MinIO 노드들과 관리용 로컬 호스트를 구분하여 작성합니다.

---
all:
  children:
    # MinIO AISTor가 설치될 대상 서버 그룹
    aistor_nodes:
      hosts:
        minio-node-01:
          ansible_host: 192.168.1.10
        minio-node-02:
          ansible_host: 192.168.1.11
        minio-node-03:
          ansible_host: 192.168.1.12
      vars:
        node_type: storage

    # mc 명령어 및 kubectl을 실행할 관리 노드 (보통 bastion 또는 localhost)
    management_nodes:
      hosts:
        localhost:
          ansible_connection: local

2. ansible.cfg (Ansible 설정 파일)

레포지토리 최상단(Root)에 위치하며, AWX가 실행될 때 Role의 경로와 실행 옵션을 정의합니다.

[defaults]
# Role이 위치한 경로를 지정 (AWX가 roles 폴더를 인식하게 함)
roles_path = ./roles

# SSH 연결 시 호스트 키 검사를 건너뜀 (처음 접속하는 서버 대응)
host_key_checking = False

# 결과 출력 시 가독성을 높이기 위한 설정
stdout_callback = yaml
bin_ansible_callbacks = True

# 작업 병렬 실행 개수
forks = 10

[privilege_escalation]
# 모든 작업에서 sudo 권한 사용 여부
become = True
become_method = sudo
become_user = root
become_ask_pass = False

3. group_vars/all.yml (공통 변수 설정)

모든 플레이북에서 공통으로 참조할 MinIO 설정값들을 정의합니다. 여기에 적힌 변수들은 {{ minio_port }}와 같은 방식으로 플레이북 내에서 사용됩니다.

---
# MinIO 서비스 관련 설정
minio_port: 9000
minio_console_port: 9001
minio_root_user: "admin"
# 실제 운영 시 password는 AWX의 'Survey'나 'Vault'를 사용하는 것이 안전합니다.
minio_root_password: "password123"

# 점검(Check) 관련 임계치 설정
check_disk_usage_threshold: 80  # 디스크 사용량 80% 이상 시 경고
min_memory_gb: 16               # 최소 필요 메모리 16GB

# DirectPV 및 가상화 관련 설정
directpv_namespace: "directpv"
storage_class_name: "directpv-minio"

# 결과 리포트 저장 경로 (대상 서버 내)
check_report_path: "/tmp/minio_check_reports"

AWX 연동 가이드 (흐름도)

이 파일들이 BitBucket에 업로드되면 AWX는 다음과 같이 작동합니다:

  1. Project Sync: BitBucket의 모든 파일(위 3개 포함)을 AWX 서버로 복사합니다.
  2. Inventory Source: inventories/dev_inventory.yml을 읽어 AWX UI 상에 minio-node-01 등의 호스트 리스트를 자동으로 생성합니다.
  3. Job Launch: 사용자가 실행 버튼을 누르면 ansible.cfg를 참고하여 roles/ 폴더 안의 로직을 찾고, group_vars/all.yml의 변수들을 메모리에 로드한 뒤 대상 서버로 접속합니다.

이제 Role 구조(roles/minio_check/tasks/main.yml 등)를 실제로 어떻게 작성하여 Pre-check와 Post-check를 구분할지 구체적인 코드가 필요하신가요?

===

Minio AISTor의 상태를 점검하는 가장 핵심적인 Role 구조를 작성해 드립니다. 이 코드는 앞서 설계한 roles/minio_check/ 디렉토리에 위치하게 됩니다.


1. roles/minio_check/tasks/main.yml (진입점)

Pre-check와 Post-check를 구분하여 호출할 수 있도록 분기 처리를 해둡니다.

---
- name: "점검 모드 확인: {{ check_mode | default('pre') }}"
  include_tasks: "{{ check_mode | default('pre') }}_check.yml"

2. roles/minio_check/tasks/pre_check.yml (설치 전 점검)

작업 전 인프라 환경이 적절한지 확인합니다. 하나라도 실패하면 전체 프로세스를 중단(fail)시킵니다.

---
- name: "[Pre] OS 파라미터 확인 (Max Open Files)"
  shell: ulimit -n
  register: ulimit_info
  failed_when: ulimit_info.stdout | int < 65535

- name: "[Pre] 디스크 가용 공간 확인 (/data)"
  assert:
    that:
      - item.mount == '/data'
      - (item.size_available / item.size_total) > 0.2  # 20% 이상 여유
    fail_msg: "/data 디스크 용량이 부족하거나 마운트되지 않았습니다."
  loop: "{{ ansible_mounts }}"
  when: item.mount == '/data'

- name: "[Pre] 필수 포트 점유 여부 확인 (9000, 9001)"
  wait_for:
    port: "{{ item }}"
    state: stopped
    timeout: 5
  loop:
    - "{{ minio_port }}"
    - "{{ minio_console_port }}"

3. roles/minio_check/tasks/post_check.yml (설치/변경 후 점검)

서비스가 정상적으로 올라왔는지, 클러스터 구성에 문제가 없는지 확인합니다.

---
- name: "[Post] Minio 서비스 상태 확인"
  systemd:
    name: minio
    state: started
  register: minio_service

- name: "[Post] Minio API 응답 대기"
  wait_for:
    port: "{{ minio_port }}"
    delay: 5
    timeout: 30

- name: "[Post] mc admin info를 통한 클러스터 헬스 체크"
  shell: "mc admin info myminio --json"
  register: mc_admin_info
  changed_when: false

- name: "[Post] 클러스터 상태 파싱 및 검증"
  set_fact:
    minio_status: "{{ mc_admin_info.stdout | from_json }}"

- name: "[Post] 오프라인 드라이브 존재 여부 확인"
  fail:
    msg: "오프라인 상태의 드라이브가 감지되었습니다!"
  when: minio_status.info.backend.offline_disks > 0

- name: "[Post] 최종 상태 요약 출력"
  debug:
    msg: 
      - "Minio Version: {{ minio_status.info.version }}"
      - "Uptime: {{ minio_status.info.uptime }}"
      - "Total Storage: {{ (minio_status.info.usage.size / 1024**4) | round(2) }} TB"

4. AWX에서 활용하는 방법 (Job Template 설정)

이 Role을 실제 작업에 적용할 때는 AWX의 Job Template에서 Extra Variables를 활용합니다.

  1. 설치 작업 시: check_mode: pre 변수를 넘겨서 사전 점검만 수행하거나, 플레이북 상단에 pre_check를 포함합니다.
  2. 단순 점검 시:
    AWX Survey 기능을 이용해 사용자가 pre 또는 post를 선택하게 만들면, 하나의 템플릿으로 상황에 맞는 점검이 가능합니다.

💡 다음 단계 제안

이제 기본적인 점검 로직까지 완성되었습니다!
"혹시 점검 결과를 이메일이나 Slack으로 전송하는 알림(Notification) 기능을 추가해 드릴까요?" 아니면 "DirectPV 관련 상세 점검 로직을 추가해 드릴까요?"

===

DirectPV 환경에서는 데이터 디스크가 호스트 OS에 직접 마운트되지 않고 DirectPV 드라이버에 의해 관리되므로, 일반적인 dfmount 명령으로는 상태를 확인하기 어렵습니다.

따라서 Pre-check 단계에서는 "DirectPV가 사용할 수 있는 깨끗한 상태의 디스크(Raw Disk/Partition)인가?"를 확인하는 것이 핵심입니다. 이를 위해 lsblkblkid를 조합하여 LVM, 파일시스템(XFS 등), 파티션 정보를 구분하는 로직을 구성해 드립니다.


roles/minio_check/tasks/pre_check.yml (업데이트 버전)

이 코드는 /dev/sdb, /dev/sdc와 같이 특정 장치들이 DirectPV에 할당되기 적합한 상태(파일시스템이 없고, LVM에 속하지 않은 상태)인지 점검합니다.

---
- name: "[Pre] 대상 디스크 리스트 정의"
  set_fact:
    target_disks: ["sdb", "sdc", "sdd"]  # 점검할 디스크 명칭 (환경에 맞게 수정)

- name: "[Pre] 디스크 상세 정보 수집 (lsblk)"
  shell: "lsblk /dev/{{ item }} --json"
  loop: "{{ target_disks }}"
  register: disk_lsblk_raw
  changed_when: false

- name: "[Pre] 디스크 파일시스템 및 시그니처 확인 (blkid)"
  shell: "blkid /dev/{{ item }} || true"
  loop: "{{ target_disks }}"
  register: disk_blkid_raw
  changed_when: false

- name: "[Pre] 디스크 상태 분석 및 미할당 여부 검증"
  vars:
    # lsblk 결과 파싱
    disk_info: "{{ item.0.stdout | from_json }}"
    # blkid 결과가 비어있으면 파일시스템이나 LVM 시그니처가 없는 'Clean' 상태로 간주
    has_signature: "{{ item.1.stdout != '' }}"
  assert:
    that:
      - disk_info.blockdevices[0].mountpoint == null  # 마운트되지 않아야 함
      - not has_signature                              # 파일시스템(XFS, LVM 등)이 없어야 함
      - disk_info.blockdevices[0].children is not defined # 하위 파티션이 없는 Raw 상태 권장
    fail_msg: |
      디스크 /dev/{{ item.0.item }} 상태가 적절하지 않습니다.
      - 마운트 여부: {{ disk_info.blockdevices[0].mountpoint | default('No') }}
      - 기존 데이터/LVM 존재 여부: {{ 'Yes' if has_signature else 'No' }}
      - 상세 정보: {{ item.1.stdout }}
  loop: "{{ disk_lsblk_raw.results | zip(disk_blkid_raw.results) | list }}"

- name: "[Pre] 최소 가용 용량 확인 (개별 디스크 100GB 이상)"
  assert:
    that:
      - (item.stdout | from_json).blockdevices[0].size | human_to_bytes >= 107374182400
    fail_msg: "/dev/{{ item.item }} 의 용량이 최소 요구사항(100GB)에 미달합니다."
  loop: "{{ disk_lsblk_raw.results }}"

코드 설명 및 DirectPV 연계 포인트

  1. lsblk --json 활용: JSON 형태로 결과를 받아 mountpoint가 있는지, children(파티션)이 이미 나누어져 있는지 프로그래밍 방식으로 정확하게 체크합니다.
  2. blkid 검증:
    • 결과값이 있다면 이미 TYPE="xfs", TYPE="LVM2_member" 등의 정보가 출력됩니다.
    • DirectPV는 보통 Wipe 되지 않은 디스크(이미 데이터나 파일시스템이 있는 디스크)를 드라이브로 추가하려고 하면 에러가 발생하므로, blkid 결과가 비어있는(Clean) 상태인지를 확인하는 것이 매우 중요한 Pre-check 항목입니다.
  3. assert 모듈: 조건에 맞지 않을 경우 AWX 화면에 어떤 디스크가 왜 부적합한지(fail_msg) 명확하게 노출하여 작업자가 조치할 수 있게 합니다.

DirectPV 전용 Post-check 로직 추가 제안

설치 후에는 노드에서 디스크를 보는 게 아니라 kubectl directpv 명령어로 상태를 확인해야 합니다.

roles/minio_check/tasks/post_check.yml (추가분)

---
- name: "[Post] DirectPV 드라이브 상태 확인 (Ready 상태 여부)"
  shell: "kubectl directpv list drives --format json"
  register: directpv_drives_raw
  delegate_to: localhost  # k8s 컨트롤러 권한이 있는 곳에서 실행

- name: "[Post] 드라이브 에러 및 오프라인 체크"
  vars:
    drives: "{{ directpv_drives_raw.stdout | from_json }}"
  assert:
    that:
      - item.status == 'Ready'
    fail_msg: "DirectPV 드라이브 {{ item.path }} 가 Ready 상태가 아닙니다! (현재 상태: {{ item.status }})"
  loop: "{{ drives }}"
  when: drives | length > 0

이렇게 구성하면 AWX에서 설치 전에는 물리적인 디스크의 순수성을 점검하고, 설치 후에는 DirectPV 소프트웨어 레벨에서의 정상 가동 여부를 모두 자동화하여 관리할 수 있습니다.

이 코드를 BitBucket의 roles/minio_check/tasks/ 아래에 덮어쓰기 하시면 바로 적용 가능합니다. 더 궁금하신 세부 점검 조건이 있으신가요?

===

네, 가능합니다. 노드마다 디스크 컨트롤러 순서가 바뀌거나 /dev/sdb, /dev/sdc 등으로 이름이 가변적인 환경에서는 Ansible FactsShell 필터링을 조합하여 "DirectPV가 사용 가능한 빈 디스크"만 자동으로 스캔하도록 구성하는 것이 훨씬 안정적입니다.

set_fact 부분을 아래와 같이 동적 스캔 로직으로 교체하면 됩니다.


1. 동적 디스크 스캔 및 필터링 로직 (pre_check.yml 상단)

이 로직은 시스템의 모든 블록 장치를 훑어서 OS 영역이 아니고, 파티션이 없으며, 마운트되지 않은 'Raw' 디스크만 골라냅니다.

---
- name: "[Scan] 사용 가능한 가용 디스크 자동 검색"
  shell: |
    lsblk -no NAME,MOUNTPOINT,TYPE,FSTYPE,SIZE | \
    awk '$2 == "" && $3 == "disk" && $4 == "" {print $1}'
  register: scanned_disks
  changed_when: false

- name: "[Scan] 스캔된 디스크 목록을 target_disks 변수에 할당"
  set_fact:
    target_disks: "{{ scanned_disks.stdout_lines }}"

- name: "[Scan] 검색 결과 출력"
  debug:
    msg: "노드 {{ inventory_hostname }}에서 발견된 가용 디스크: {{ target_disks }}"

- name: "[Scan] 가용 디스크가 없는 경우 중단 (선택 사항)"
  fail:
    msg: "DirectPV로 사용할 수 있는 빈 디스크가 이 노드에 없습니다."
  when: target_disks | length == 0

2. 스캔 로직 상세 설명

  • lsblk -no ...:
    • NAME: 디스크 이름 (예: sdb)
    • MOUNTPOINT: 마운트 여부 확인용
    • TYPE: part(파티션)가 아닌 disk(물리 장치)만 골라내기 위함
    • FSTYPE: 파일시스템(xfs, ext4, LVM 등)이 이미 생성된 디스크 제외
  • awk 필터링:
    • $2 == "": 마운트 포인트가 비어 있어야 함 (사용 중인 디스크 제외)
    • $3 == "disk": 파티션 조각이 아닌 전체 디스크 단위여야 함
    • $4 == "": 파일시스템 포맷이 되어 있지 않아야 함 (DirectPV는 Raw 디스크 선호)

3. 전체 Pre-check 통합 예시

이제 수동으로 이름을 적을 필요 없이, 스캔된 target_disks를 사용하여 이후 검증 과정을 이어갑니다.

---
- name: "[Scan] 가용 디스크 자동 검색"
  shell: "lsblk -no NAME,MOUNTPOINT,TYPE,FSTYPE | awk '$2 == \"\" && $3 == \"disk\" && $4 == \"\" {print $1}'"
  register: scanned_disks
  changed_when: false

- name: "[Scan] target_disks 변수 생성"
  set_fact:
    target_disks: "{{ scanned_disks.stdout_lines }}"

- name: "[Pre] 스캔된 각 디스크의 상세 정밀 검증 (lsblk JSON)"
  shell: "lsblk /dev/{{ item }} --json"
  loop: "{{ target_disks }}"
  register: disk_lsblk_raw
  when: target_disks | length > 0

- name: "[Pre] 디스크 용량 필터링 (예: 100GB 이상만 사용)"
  assert:
    that:
      - (item.stdout | from_json).blockdevices[0].size | human_to_bytes >= 107374182400
    fail_msg: "/dev/{{ item.item }} 의 용량이 부족합니다."
  loop: "{{ disk_lsblk_raw.results }}"
  when: disk_lsblk_raw.results is defined

💡 운영 팁

  1. OS 디스크 제외: 위 awk 로직은 마운트된 디스크를 제외하므로 //boot가 있는 디스크는 자동으로 걸러집니다.
  2. 안전 장치: 만약 특정 노드에서 실수로 데이터가 있는 디스크의 마운트를 해제했을 경우, FSTYPE이 비어있지 않다면($4 == "") 스캔 대상에서 제외되므로 2중 안전 장치가 됩니다.
  3. AWX 로그 확인: AWX의 Jobs 상세 화면에서 debug 메시지를 통해 각 노드별로 어떤 디스크(sdb, nvme0n1 등)가 선택되었는지 한눈에 확인할 수 있습니다.

이렇게 구성하면 컨트롤러 재기동으로 인해 디스크 이름이 sdb에서 sdc로 바뀌더라도, AWX는 실행 시점의 상태를 다시 스캔하므로 문제없이 동작합니다.

다음으로 이 스캔 결과를 바탕으로 자동으로 kubectl directpv add drives 명령까지 생성하는 작업이 필요하실까요?

0개의 댓글