---
title: "Ansible"
description: "alpacax.alpacon 컬렉션으로 Alpacon에서 Ansible 플레이북을 실행합니다. 서비스 토큰과 애플리케이션의 서버 계정, 접근 규칙을 설정하세요. 연결 옵션과 파일 전송 조건, sudo 제한을 확인하고 승인 대기와 실행 결과에 따라 자동화 작업을 처리할 수 있습니다."
---

> Full documentation index: https://docs.alpacax.com/llms.ko.txt

# Ansible

`alpacax.alpacon` 컬렉션으로 Alpacon을 통해 플레이북을 실행할 수 있습니다. `alpacax.alpacon.exec` 연결은 API를 직접 사용하므로 Alpacon CLI가 필요하지 않습니다.

## 컨트롤러와 토큰 준비

컨트롤러에는 ansible-core 2.15 이상과 Python 3.11 이상이 필요합니다. 컬렉션을 설치하세요.

```bash
ansible-galaxy collection install alpacax.alpacon
```

macOS 컨트롤러에서는 Ansible 실행 전에 다음 값을 설정하세요.

```bash
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
```

[애플리케이션과 서비스 토큰](/use/iam/applications/service-tokens/)을 준비하세요.

1. 서버 계정을 애플리케이션에 연결하거나, 사용자 이름을 지정하고 프로비저닝을 켭니다. 최신 에이전트가 설치된 Linux 서버에서는 첫 명령어 실행 시 계정을 생성합니다. 이 계정을 `ansible_user`로 지정하세요.
2. 토큰의 scope를 허용하는 전역 역할을 애플리케이션에 부여합니다. 명령어에는 `command:create`와 `command:read`가 필요하고, 서버 이름으로 조회하려면 `server:read`도 필요합니다. 모듈 복사를 위한 파일 업로드 권한과 파일을 가져오는 작업에 필요한 다운로드 권한도 부여하세요.
3. `alpst-` 서비스 토큰을 요청하고 웹 콘솔에서 슈퍼유저나 해당 요청의 승인자에게 승인을 받습니다. 명령어와 파일 전송 scope는 항상 승인을 기다립니다. 토큰이 활성화되어 있고 사용 가능한 상태인지 확인하세요.
4. 승인 후 각 대상 서버에 대한 서버 ACL과 플레이북이 사용하는 경로·전송 방향에 맞는 파일 ACL을 추가합니다. 일반 모듈은 실행 전에 서버로 복사되므로 명령어 실행과 업로드 권한이 모두 필요합니다.
5. Alpacon Cloud에서는 **명령 ACL 관리자**에 등록된 관리자에게 토큰의 **사전 승인된 명령**에 명령어를 추가해 달라고 요청합니다. 이 권한은 워크스페이스 역할과 별개입니다. 연결을 요청하는 화면이 나오면 **연결하기**를 선택하세요. 자체 호스팅에서는 Ansible이 제출하는 문자열에 맞는 명령어 ACL 규칙을 추가합니다.

파일 전송에는 S3 기반 스토리지가 필요합니다. 작업 대상 경로뿐 아니라 모듈 업로드에 쓰는 임시 경로도 허용하세요. 이 토큰 작업에는 작업 세션이 필요하지 않습니다. 계정, 역할, ACL 설정은 [설정 및 API 참조](/reference/api/#서비스-토큰으로-자동화하기)를 참고하세요.

`ansible_user`를 반드시 지정하세요. 기본값은 서비스 토큰으로 사용할 수 없는 `root`입니다. `ci-deploy`처럼 애플리케이션이 소유한 서버 계정으로 설정하세요.

## 최소 플레이북 실행

서버 UUID와 계정을 실제 값으로 바꾸고 다음 내용을 `inventory.ini`로 저장하세요.

```ini
[web]
web-01 alpacon_server_id=<server-uuid>

[web:vars]
ansible_connection=alpacax.alpacon.exec
ansible_user=ci-deploy
```

워크스페이스 URL을 설정하고 시크릿 저장소에서 승인된 서비스 토큰 키를 주입하세요. 아래 키는 예시 값입니다.

```bash
export ALPACON_URL=https://your-workspace.ap1.alpacon.io
export ALPACON_TOKEN='alpst-REPLACE_WITH_SERVICE_TOKEN'
```

다음 내용을 `playbook.yml`로 저장하세요.

```yaml
- hosts: web
  gather_facts: false
  tasks:
    - name: Who am I
      ansible.builtin.raw: whoami
```

플레이북을 실행하세요.

```bash
ansible-playbook -i inventory.ini playbook.yml
```

명령어는 `ci-deploy` 계정으로 실행됩니다. `raw` 작업은 모듈을 업로드하지 않고 `whoami`를 제출하므로 이 확인에는 `whoami` 명령어 규칙 하나면 됩니다. root 직접 접근은 기본적으로 꺼져 있습니다. `ansible_user`를 기본값으로 두면 `"code": "workspace_direct_root_disabled"`가 포함된 `400` 응답을 받습니다. 오류 본문은 다음 형태입니다(`...`는 입력 검증 메시지를 뜻합니다).

```text
{"code": "workspace_direct_root_disabled", "field_errors": {"non_field_errors": [...]}}
```

root 직접 접근을 허용한 워크스페이스에서만 이 요청이 `application_system_user_not_found` 검사까지 도달합니다. ACL에서 `root`를 허용해도 애플리케이션이 소유한 계정이 되지는 않습니다.

### Ansible의 모듈 실행 방식

일반 모듈 작업은 계정의 홈 디렉터리 확인, `~/.ansible/tmp/` 아래 임의의 임시 디렉터리 생성, Python 탐색, 권한 설정, 업로드한 모듈 실행, 임시 파일 삭제를 위한 래퍼 명령어를 제출합니다. 예를 들어 command 모듈은 `AnsiballZ_command.py`를 업로드합니다. 제출되는 래퍼 명령어마다 일치하는 명령어 규칙이 필요하고, 모듈 업로드에는 임시 경로를 허용하는 파일 ACL이 필요합니다. `whoami`만 허용하는 좁은 규칙으로는 이런 모듈 작업을 실행할 수 없습니다. 래퍼 명령어는 Ansible과 대상 서버에 따라 달라지므로 운영에 사용하기 전에 통제된 환경에서 한 번 실행하고 실제 문자열을 확인하세요.

## 연결 옵션

지원하는 항목에 따라 인벤토리 변수, 환경 변수 또는 `ansible.cfg`에서 설정할 수 있습니다. 아래 INI 항목은 `[alpacon_connection]`에 넣습니다. `remote_user`만 `[defaults]`에 넣습니다.

| 인벤토리 변수 | 환경 변수 | INI 항목 | 기본값 또는 용도 |
| --- | --- | --- | --- |
| `alpacon_url` | `ALPACON_URL` | `url` | 워크스페이스 URL, 필수 |
| `alpacon_token` | `ALPACON_TOKEN` | `token` | `alpst-` 서비스 토큰, 필수 |
| `alpacon_server_id` | — | — | 서버 UUID. 이름보다 우선 적용 |
| `alpacon_server_name` | — | — | 생략하면 `ansible_host`, 이 값도 없으면 인벤토리 호스트 이름 |
| `alpacon_approval_timeout` | `ALPACON_APPROVAL_TIMEOUT` | `approval_timeout` | `300`초. `0` 이하면 승인이 필요할 때 즉시 실패 |
| `alpacon_ssl_verify` | `ALPACON_SSL_VERIFY` | `ssl_verify` | `true` |
| `alpacon_ca_cert` | `ALPACON_CA_CERT` | `ca_cert` | CA 인증서 경로 |
| `ansible_user` 또는 `ansible_ssh_user` | — | `remote_user` | 기본값은 `root`. 애플리케이션 계정으로 지정 필요 |

서버 ID가 없으면 이름으로 조회합니다. 여러 서버가 일치하면 `Multiple servers match name ...`, 조회 가능한 서버가 없으면 `Server '<name>' not found in alpacon.`이 표시됩니다. 이름이 겹치면 서버 ID를 지정하고, 대상이 조회되지 않으면 토큰의 서버 접근 규칙을 확인하세요.

## become으로 권한 상승

`become`을 사용해도 Ansible은 애플리케이션 계정으로 접속한 뒤 sudo 명령어를 제출합니다. Alpacon Cloud에서는 서비스 토큰의 sudo 위험도가 심각(Critical)보다 낮거나 평가되지 않았으면 허용하고, 심각이면 거부합니다. 단, Advisory 워크스페이스에서는 위험도를 이유로 거부하지 않고 판단을 기록합니다. Advisory가 아니면 워크스페이스의 `token_exec` 규칙으로 위험도 기준을 더 엄격하게 정할 수 있습니다. 워크스페이스의 sudo 설정도 켜져 있어야 하며, 꺼져 있으면 `workspace_sudo_with_mfa_disabled`로 거부됩니다. 기본 설정의 자체 호스팅에서는 모든 서비스 토큰 sudo가 `sudo_command_not_authorized`로 거부됩니다. sudo 정책은 서비스 토큰에 적용되지 않으며 sudo는 사람의 승인을 기다리지 않습니다.

명령어 항목은 sudo 접두사를 포함한 제출 문자열을 허용해야 합니다. Ansible은 임시 경로와 실행마다 생성하는 식별자를 추가하므로 접근 규칙을 설정할 때 실제 문자열을 확인하세요. 플레이북을 통과시키기 위해 `sudo *`처럼 넓은 항목을 허용하지 마세요. 이 연결은 토큰만 사용하므로 기본 설정의 자체 호스팅에서는 `become`을 사용할 수 없습니다.

## 승인 대기와 결과

명령어가 승인을 기다리면 다음 메시지가 표시됩니다.

```text
alpacax.alpacon.exec: command <id> is awaiting approval in the alpacon console; waiting up to <n>s for a decision
```

웹 콘솔에서 승인자에게 검토를 요청하세요. `alpacon_approval_timeout`은 승인 대기 시간을 정하며, 300초의 실행 제한 시간과는 별개입니다.

| 결과 | 반환 코드와 출력 |
| --- | --- |
| 성공 | `rc: 0` |
| 실행 시간 초과 | `rc: 124`, stderr에 `Command execution timed out` |
| 그 밖의 실패 | `rc: 1`, stderr에 `denied`, `rejected`, `awaiting_approval` 등의 상태 |
| 거부 또는 반려 | `rc: 1`, stdout에 `Command was rejected by the approval policy` |
| 승인 대기 시간 초과 | `rc: 1`, stderr에 `awaiting_approval`; stdout에 `do not resubmit, that would queue a duplicate run` 경고 |

Cloud에서 `Command was rejected by the approval policy`는 명령어 규칙이 없다는 뜻일 수도 있습니다. API는 명령어를 `201`로 접수한 뒤 `rejected`로 종료하며, `rejection_cause`는 `command_acl_denied` 또는 `command_acl_unavailable`입니다. 승인 설정을 바꾸기 전에 명령어의 `rejection_cause`를 확인하세요. 자체 호스팅에서 명령어 ACL로 거부되면 `403 api_token_acl_not_allowed`가 반환됩니다.

승인 대기 시간이 초과되어도 다시 제출하지 마세요. 원래 명령어는 대기 중이므로 다시 제출하면 두 번 실행될 수 있습니다. 콘솔에서 기존 명령어를 확인하세요.

모듈 작업은 여러 명령어를 제출하며 결과 조회도 요청 수에 포함됩니다. 서버 수가 적어도 서비스 토큰의 기본 한도인 `1000/hour`에 도달할 수 있습니다. 연결 플러그인은 HTTP `429`를 재시도하지 않습니다. 동시 실행 수를 줄이고 `Retry-After`만큼 기다리세요. 작업을 재시도하기 전에 명령어가 이미 접수되었는지 확인하세요. 상태 조회에 실패했다고 명령어가 실패한 것은 아니며, 다시 제출하면 중복 실행될 수 있습니다.

HTTP 오류, 자격 증명 만료, 계정 거부는 [자동화 오류 해결](/integrate/automation-failure-modes/)을 참고하세요.

Source: https://docs.alpacax.com/ko/integrate/ansible/
