ACL 정책 만들기
ACL 정책 만들기 (Create ACL policies)
이 가이드에서는 Nomad 클러스터에 대한 제어된 접근을 두 가지 서로 다른 페르소나(persona)에게 제공하는 Nomad ACL 정책을 만들 거예요. nomad init -short 명령으로 만든 샘플 작업을 샘플 작업으로 사용할 거예요.
출처: 문서
본문
이 가이드를 완료하려면 다음이 필요해요:
- ACL 시스템이 부트스트랩된 Nomad 클러스터.
- 관리 토큰(management token). bootstrap 토큰을 사용할 수 있지만, 프로덕션 시스템에서는 사용자별 토큰을 사용해야 해요.
페르소나 소개 (Meet the personas)
이 가이드에서는 두 가지 서로 다른 사용자 페르소나에 대한 클러스터 접근을 관리하는 정책을 만들 거예요. 이들은 시나리오에 맞게 만들어진 것이며, ACL 정책은 조직의 특정 요구에 맞게 설계해야 해요.
모범 사례로서, 접근은 사용자 역할의 필요에 비추어 가능한 한 제한되어야 해요.
도전 과제: 이 시나리오를 네임스페이스를 포함하도록 확장하는 것을 고려해 보세요.
애플리케이션 개발자 (Application Developer)
애플리케이션 개발자는 애플리케이션을 Nomad 클러스터에 배포하고 그 수명주기를 제어할 수 있어야 해요. 다른 노드 작업은 수행할 수 없어야 해요.
애플리케이션 개발자는 실행 중인 컨테이너의 로그를 가져올 수 있지만, 컨테이너 내부에서 명령을 실행하거나 실행 중인 워크로드의 파일시스템에 접근할 수 없어야 해요.
프로덕션 운영 (Production Operations)
프로덕션 운영 팀은 클러스터 유지보수를 수행하고, 볼륨 같은 연결된 리소스를 포함한 실행 중인 클러스터의 워크로드를 볼 수 있어야 해요. 다만 애플리케이션 개발자가 실행 중인 워크로드의 소유자이므로, 프로덕션 운영자는 클러스터에서 작업을 실행하거나 중지할 수 없어야 해요.
정책 규칙 작성
애플리케이션 개발자 정책
위의 요구 사항을 고려할 때 정책에 어떤 규칙을 추가해야 할까요? Nomad는 명시적으로 허용되지 않은 모든 요청을 거부하므로, 허용하고 싶은 정책과 기능에 집중해야 해요. 다만 namespace 규칙의 거친 수준의 권한에 유의하세요 — 사용 사례에 필요한 것보다 더 많은 권한을 부여할 수 있거든요.
애플리케이션 개발자는 애플리케이션을 Nomad 클러스터에 배포하고 그 수명주기를 제어할 수 있어야 해요. 다른 노드 작업은 수행할 수 없어야 해요.
애플리케이션 개발자는 실행 중인 컨테이너의 로그를 가져올 수 있지만, 컨테이너 내부에서 명령을 실행하거나 실행 중인 워크로드의 파일시스템에 접근할 수 없어야 해요.
namespace 규칙이 Nomad 클러스터의 작업 애플리케이션 배포 동작과 내부 검사(introspection) 기능을 관리한다는 점을 기억해요.
먼저 필수 기능의 관점에서 정책을 정의해요. 이 정책이 애플리케이션 개발자에게 제공해야 하는 기능은 사용 가능한 옵션 중 무엇일까요?
| 기능 | 필요 여부 |
|---|---|
| deny — 여러 정책이 토큰과 연관될 때 deny가 우선하고 모든 기능을 방지해요. | 해당 없음 |
| list-jobs — 작업을 나열하고 거친 수준의 상태를 볼 수 있게 해요. | ✅ |
| read-job — 작업을 검사하고 세분화된 상태를 볼 수 있게 해요. | ✅ |
| submit-job — 작업을 제출하거나 수정할 수 있게 해요. | ✅ |
| dispatch-job — 작업을 디스패치할 수 있게 해요. | ✅ |
| read-logs — 작업과 연관된 로그를 볼 수 있게 해요. | ✅ |
| read-fs — 연관된 할당의 파일시스템을 볼 수 있게 해요. | 🚫 |
| alloc-exec — 운영자가 실행 중인 할당에 연결해 명령을 실행할 수 있게 해요. | 🚫 |
| alloc-node-exec — 운영자가 raw_exec 작업과 같이 파일시스템 격리 없이 실행되는 할당에 연결해 명령을 실행할 수 있게 해요. | 🚫 |
| alloc-lifecycle — 운영자가 개별 할당을 수동으로 중지할 수 있게 해요. | 🚫 |
| csi-register-plugin — 자신을 CSI 플러그인으로 등록하는 작업을 제출할 수 있게 해요. | 🚫 |
| csi-write-volume — CSI 볼륨을 등록하거나 등록 해제할 수 있게 해요. | 🚫 |
| csi-read-volume — CSI 볼륨을 검사하고 세분화된 상태를 볼 수 있게 해요. | 🚫 |
| csi-list-volume — CSI 볼륨을 나열하고 거친 수준의 상태를 볼 수 있게 해요. | 🚫 |
| csi-mount-volume — CSI 볼륨을 요구하는 작업을 제출할 수 있게 해요. | 🚫 |
| list-scaling-policies — 스케일링 정책을 나열할 수 있게 해요. | 🚫 |
| read-scaling-policy — 스케일링 정책을 검사할 수 있게 해요. | 🚫 |
| read-job-scaling — 작업의 현재 스케일링을 검사할 수 있게 해요. | 🚫 |
| scale-job — 작업을 위아래로 스케일링할 수 있게 해요. | 🚫 |
| sentinel-override — soft mandatory 정책을 재정의할 수 있게 해요. | 🚫 |
네임스페이스 규칙의 거친 수준의 policy 값이 기능 목록이라는 점을 기억해요.
| 정책 값 | 기능 |
|---|---|
deny |
deny |
read |
list-jobs, read-job, csi-list-volume, csi-read-volume, list-scaling-policies, read-scaling-policy, read-job-scaling |
write |
list-jobs, read-job, submit-job, dispatch-job, read-logs, read-fs, alloc-exec, alloc-lifecycle, csi-write-volume, csi-mount-volume, list-scaling-policies, read-scaling-policy, read-job-scaling, scale-job |
scale |
list-scaling-policies, read-scaling-policy, read-job-scaling, scale-job |
list |
(플러그인 메타데이터 나열만 부여) |
이를 정책 형태로 표현해요. app-dev.policy.hcl 파일을 만들어 정책을 작성해요.
policy = "read"
capabilities = ["submit-job","dispatch-job","read-logs"]
}
네임스페이스 규칙에 policy = "read"가 있다는 점에 유의해요. write 정책은 "read-fs", "alloc-exec", "alloc-lifecycle"을 부여하는 과도하게 관대한 정책이므로 적합하지 않아요.
프로덕션 운영 정책
위의 요구 사항을 고려할 때 정책에 어떤 규칙을 추가해야 할까요? Nomad는 명시적으로 제공되지 않은 모든 요청을 거부하므로, 허용하고 싶은 정책에 집중해야 해요.
프로덕션 운영 팀은 클러스터 유지보수를 수행하고, 볼륨 같은 연결된 리소스를 포함한 실행 중인 클러스터의 워크로드를 볼 수 있어야 해요. 다만 애플리케이션 개발자가 실행 중인 워크로드의 소유자이므로, 프로덕션 운영자는 클러스터에서 작업을 실행하거나 중지할 수 없어야 해요.
namespace 규칙이 Nomad 클러스터의 작업 애플리케이션 배포 동작과 내부 검사 기능을 관리한다는 점을 기억해요.
먼저 필수 기능의 관점에서 정책을 정의해요. 이 정책이 프로덕션 운영자에게 제공해야 하는 기능은 사용 가능한 옵션 중 무엇일까요?
| 기능 | 필요 여부 |
|---|---|
| deny — 여러 정책이 토큰과 연관될 때 deny가 우선하고 모든 기능을 방지해요. | 해당 없음 |
| list-jobs — 작업을 나열하고 거친 수준의 상태를 볼 수 있게 해요. | ✅ |
| read-job — 작업을 검사하고 세분화된 상태를 볼 수 있게 해요. | ✅ |
| submit-job — 작업을 제출하거나 수정할 수 있게 해요. | 🚫 |
| dispatch-job — 작업을 디스패치할 수 있게 해요. | 🚫 |
| read-logs — 작업과 연관된 로그를 볼 수 있게 해요. | 🚫 |
| read-fs — 연관된 할당의 파일시스템을 볼 수 있게 해요. | 🚫 |
| alloc-exec — 운영자가 실행 중인 할당에 연결해 명령을 실행할 수 있게 해요. | 🚫 |
| alloc-node-exec — 운영자가 raw_exec 작업과 같이 파일시스템 격리 없이 실행되는 할당에 연결해 명령을 실행할 수 있게 해요. | 🚫 |
| alloc-lifecycle — 운영자가 개별 할당을 수동으로 중지할 수 있게 해요. | 🚫 |
| csi-register-plugin — 자신을 CSI 플러그인으로 등록하는 작업을 제출할 수 있게 해요. | 🚫 |
| csi-write-volume — CSI 볼륨을 등록하거나 등록 해제할 수 있게 해요. | 🚫 |
| csi-read-volume — CSI 볼륨을 검사하고 세분화된 상태를 볼 수 있게 해요. | ✅ |
| csi-list-volume — CSI 볼륨을 나열하고 거친 수준의 상태를 볼 수 있게 해요. | ✅ |
| csi-mount-volume — CSI 볼륨을 요구하는 작업을 제출할 수 있게 해요. | 🚫 |
| list-scaling-policies — 스케일링 정책을 나열할 수 있게 해요. | 🚫 |
| read-scaling-policy — 스케일링 정책을 검사할 수 있게 해요. | 🚫 |
| read-job-scaling — 작업의 현재 스케일링을 검사할 수 있게 해요. | 🚫 |
| scale-job — 작업을 위아래로 스케일링할 수 있게 해요. | 🚫 |
| sentinel-override — soft mandatory 정책을 재정의할 수 있게 해요. | 🚫 |
다시 한번, 네임스페이스 규칙의 거친 수준의 policy 값은 기능 목록이에요.
| 정책 값 | 기능 |
|---|---|
deny |
deny |
read |
list-jobs, read-job, csi-list-volume, csi-read-volume, list-scaling-policies, read-scaling-policy, read-job-scaling |
write |
list-jobs, read-job, submit-job, dispatch-job, read-logs, read-fs, alloc-exec, alloc-lifecycle, csi-write-volume, csi-mount-volume, list-scaling-policies, read-scaling-policy, read-job-scaling, scale-job |
scale |
list-scaling-policies, read-scaling-policy, read-job-scaling, scale-job |
list |
(플러그인 메타데이터 나열만 부여) |
이를 정책 형태로 표현해요. prod-ops.policy.hcl 파일을 만들어 정책을 작성해요. Namespace API에 필요한 기능은 read 정책 값으로 포착돼요.
policy = "read"
}
운영자는 node, agent, operator 등 몇 가지 다른 API 엔드포인트에도 접근해야 해요. 엔드포인트에 대한 자세한 내용은 개별 API 문서를 참고해요.
policy = "write"
}
agent {
policy = "write"
}
operator {
policy = "write"
}
plugin {
policy = "list"
}
이 모든 정책 요소를 prod-ops.policy.hcl 파일에 추가하고 저장해요.
정책 업로드
nomad acl policy apply 명령으로 정책 명세를 업로드해요. NOMAD_TOKEN 환경 변수나 -token 플래그로 관리 토큰을 제공하는 것을 잊지 마세요. 연습으로 이번에는 -token 플래그를 사용해요.
"Application Developer policy"를 업로드해요.
Successfully wrote "app-dev" ACL policy!
"Production Operations policy"를 업로드해요.
Successfully wrote "prod-ops" ACL policy!
정책 검증
정책이 제대로 작동하는지 검증하려면 토큰을 만들고 성공 사례와 실패 사례를 확인해야 해요.
app-dev 토큰을 만들어요. 이 가이드에서는 출력을 tee 명령으로 파이프하여 app-dev.token으로 저장해요.
Accessor ID = b8c67cb8-cc3b-2a7c-182a-0bc5dfc3a6ff
Secret ID = 17cadb8b-e8a8-2f47-db62-fea0c6a19602
Name = Test app-dev token
Type = client
Global = false
Policies = [app-dev]
Create Time = 2020-02-10 18:41:43.049735 +0000 UTC
Create Index = 14
Modify Index = 14
다음으로 prod-ops 토큰을 만들고, 출력을 tee 명령으로 파이프하여 prod-ops.token으로 저장해요.
Accessor ID = 4e3c1ac7-52d0-6c68-94a2-5e75f17e657e
Secret ID = 0be3c623-cc90-3645-c29d-5f0629084f68
Name = Test prod-ops token
Type = client
Global = false
Policies = [prod-ops]
Create Time = 2020-02-10 18:41:53.851133 +0000 UTC
Create Index = 15
Modify Index = 15
각 토큰으로 작업 제출
먼저 활성 토큰을 테스트 app-dev 토큰으로 설정해요. 위에서 만든 파일에서 추출할 수 있어요.
nomad init으로 샘플 작업을 만들어요.
샘플 작업을 Nomad 클러스터에 제출해요.
==> Monitoring evaluation "0acad62d"
Evaluation triggered by job "example"
Allocation "8b54bf75" created: node "afcb4e20", group "cache"
Evaluation within deployment: "63bbb604"
Allocation "8b54bf75" status changed: "pending" -> "running" (Tasks are running)
Evaluation status changed: "pending" -> "complete"
==> Evaluation "0acad62d" finished with status "complete"
nomad job status 명령으로 작업이 완전히 시작되는지 확인해요.
ID = example
Name = example
Submit Date = 2020-02-10T13:42:17-05:00
Type = service
Priority = 50
Datacenters = dc1
Status = running
Periodic = false
Parameterized = false
Summary
Task Group Queued Starting Running Failed Complete Lost
cache 0 0 1 0 0 0
Latest Deployment
ID = 63bbb604
Status = running
Description = Deployment is running
Deployed
Task Group Desired Placed Healthy Unhealthy Progress Deadline
cache 1 1 0 0 2020-02-10T13:52:17-05:00
Allocations
ID Node ID Task Group Version Desired Status Created Modified
8b54bf75 afcb4e20 cache 0 run running 26s ago 25s ago
prod-ops 토큰으로 전환해요.
작업을 중지해 보세요. 중지할 수 없다는 점에 유의하세요.
Error deregistering job: Unexpected response code: 403 (Permission denied)
app-dev 토큰으로 다시 전환해요.
$ nomad stop example
==> Monitoring evaluation "2571f9f9"
Evaluation triggered by job "example"
Evaluation within deployment: "63bbb604"
Evaluation status changed: "pending" -> "complete"
==> Evaluation "2571f9f9" finished with status "complete"
다시 작업을 중지해 보세요. 이번에는 성공한다는 점에 유의하세요.
==> Monitoring evaluation "2571f9f9"
Evaluation triggered by job "example"
Evaluation within deployment: "63bbb604"
Evaluation status changed: "pending" -> "complete"
==> Evaluation "2571f9f9" finished with status "complete"
클러스터에서 GC 자극
app-dev 토큰이 여전히 활성화된 상태에서 클러스터 주소를 변수로 내보내 편의를 제공해요.
Nodes API를 사용해 클러스터의 Nomad 클라이언트를 나열해 보세요.
Permission denied
활성 토큰을 테스트 prod-ops 토큰으로 설정해요.
Nodes API 쿼리를 다시 제출해요. 화면에 상당한 양의 JSON이 반환되어 API 호출이 성공했음을 나타낼 것으로 기대해요.
도전 과제: 익명 사용자 제한 (Restrict anonymous users)
부트스트랩 가이드는 Nomad의 기본 deny-all 정책으로 인한 사용자·워크로드 영향을 최소화하기 위해 매우 관대한 익명 사용자 정책을 제공해요. 이는 토큰이 생성·배포되는 동안 클러스터 사용자와 기타 제출 에이전트가 계속 작업할 수 있게 해줘요.
도전 과제로, 조직의 익명 사용자를 위한 최소 실행 가능한 권한 집합을 고려해 보세요. 사용자의 중요 경로(critical path)에 없는 기능에 대한 사용자 접근을 방지하는 정책을 만들어 보세요.
정리 (Clean up)
이 가이드에서 만든 객체를 제거하려면 관리 토큰으로 다시 전환하고 위에서 만든 토큰을 파일의 accessor를 사용해 취소해요.
삭제 명령 실행 시 "Permission denied" 오류가 발생하면 관리 토큰을 NOMAD_TOKEN 환경 변수에 다시 로드했는지 확인해요.
Token 4e3c1ac7-52d0-6c68-94a2-5e75f17e657e successfully deleted
Token b8c67cb8-cc3b-2a7c-182a-0bc5dfc3a6ff successfully deleted
다음으로 만든 prod-ops 및 app-dev 정책을 제거해요.
Successfully deleted prod-ops policy!
Successfully deleted app-dev policy!
다음 단계 (Next steps)
이제 클러스터에 자체 정책을 배포했으니 Nomad 접근 토큰에 대해 배우게 될 거예요. Nomad 사용자는 익명이 아닌 요청을 위해 토큰을 제공해야 해요. 이러한 토큰은 해당 요청에 대해 접근 가능한 Nomad 객체를 정의하는 하나 이상의 ACL 정책에 매핑돼요.