태스크 역할과 실행 역할, 같은 컨테이너의 서로 다른 주체
컨테이너를 준비하는 권한과 앱 코드가 쓰는 권한은 달라요. ECS 실행 역할과 태스크 역할을 사용 주체에 따라 구별해 봐요.
이 글의 목차두 주체가 있다4
택배 기사가 문 앞까지 물건을 가져다 놓는 일과, 집주인이 그 물건을 쓰는 일은 다른 권한을 필요로 해요. 기사에게는 건물 현관을 열 자격이 필요하고 집 안 금고를 열 자격은 필요 없어요. 두 자격을 하나로 묶어 두면 편하지만, 기사가 바뀔 때마다 금고까지 함께 넘기는 셈이 돼요.
ECS에서 가장 자주 헷갈리는 것이 이 구분이에요. 이름이 비슷해서가 아니라 둘 다 이 컨테이너의 권한처럼 들리기 때문이에요. 실제로 갈리는 기준은 하나예요. 그 권한을 누가 쓰는가.
두 주체가 있다
AWS 문서는 두 역할을 이렇게 나눠요. 실행 역할은 ECS가 나를 대신해 다른 AWS 서비스를 쓰도록 허용하는 역할이에요. 태스크 역할은 컨테이너 위의 애플리케이션 코드가 다른 AWS 서비스를 쓰도록 허용하는 역할이에요.
예를 들어 이미지를 내려받고 설정에 적힌 비밀 값을 넣어 주는 일에는 실행 역할이 쓰여요. 실행 중 로그 전송에도 쓰이므로 ‘시작 전 권한’으로만 외우면 틀려요. 앱 코드가 직접 파일 저장소나 다른 API를 부를 때 쓰는 것은 태스크 역할이에요. 시점보다 권한을 쓰는 주체를 구별하는 것이 정확해요.
앱의 파일 읽기 권한과 에이전트의 로그 전송 권한을 맞춰 보세요.
앱 · 태스크 역할
로그 전송 권한파일 읽기 실패
에이전트 · 실행 역할
파일 읽기 권한로그 전송 실패
앱 · 태스크 역할
파일 읽기 권한파일 읽기 가능
에이전트 · 실행 역할
로그 전송 권한로그 전송 가능
앱이 읽는 파일은 태스크 역할, 에이전트가 보내는 로그는 실행 역할의 권한을 사용해요.
필요한 권한이 서로 반대 역할에 있어요. 컨테이너 안에 있다는 이유로 권한을 함께 쓰지 않아요.
서버 관리를 맡기는 Fargate에서 앱의 파일 읽기와 awslogs 방식의 로그 전송만 비교해요. 다른 시작 조건은 갖췄다고 가정해요.
같은 문서는 표에 있는 역할들을 공유하지 말고 따로 만들라고 권해요. 그 이유가 다음 이야기예요.
합치면 무슨 일이 생기나
두 역할을 하나로 합치면 동작은 해요. 그래서 처음에는 문제가 드러나지 않아요.
문제는 권한이 합쳐진 방향에 있어요. 실행 역할에는 이미지 저장소를 읽고 비밀 값을 꺼내는 권한이 들어 있는데, 이 권한이 태스크 역할과 합쳐지면 애플리케이션 코드가 그 권한을 함께 가져요. 앱은 비밀 값을 이미 환경에 받아 들고 있으므로 저장소를 직접 읽을 이유가 없는데도 읽을 수 있는 상태가 돼요.
이 차이는 평소에 보이지 않다가 앱에 문제가 생겼을 때 드러나요. 코드에 취약점이 있거나 의존성이 오염됐을 때, 공격자가 그 프로세스의 자격 증명으로 무엇까지 할 수 있느냐가 피해 범위를 정해요. 앞 시리즈에서 다룬 폭발 반경이 여기서도 같은 방식으로 작동해요. 권한을 나누는 일은 사고를 막는 일이 아니라 사고의 크기를 정해 두는 일이에요.
자격 증명은 어디서 오나
태스크에 역할을 붙이면 컨테이너 에이전트가 그 태스크 전용의 자격 증명을 만들어 줘요. 오래 사는 키를 이미지 안에 넣거나 환경 변수에 적어 둘 필요가 없다는 뜻이고, 앞 시리즈에서 다룬 단기 자격 증명이 여기서도 같은 원리로 쓰여요.
여기에 실무에서 사람을 오래 붙잡는 함정이 하나 있어요. AWS를 부르는 라이브러리들은 자격 증명을 정해진 순서로 찾는데, 환경 변수에 적힌 고정 키가 컨테이너에 부여된 임시 자격 증명보다 먼저 발견되는 경우가 있어요. 그러면 역할을 정성껏 붙여 놓고도 실제로는 예전 키가 쓰여요. 권한 오류가 나서 확인해 보면 역할에는 분명히 그 권한이 있고, 정작 쓰이고 있는 것은 다른 자격 증명인 상황이에요.
역할로 옮기는 작업이 키를 지우는 작업과 별개라는 뜻이기도 해요. 역할을 붙였다고 옛 키가 사라지지는 않아요. 환경 변수와 이미지와 설정 저장소를 각각 뒤져 지워야 그 전환이 끝나요.
| 역할 | 권한을 쓰는 주체 | 부족하거나 합쳐지면 |
|---|---|---|
| 실행 역할 | ECS 에이전트의 이미지·비밀 값·로그 작업 | 시작이나 로그 전달에 문제 |
| 태스크 역할 | 실행 중인 앱의 AWS 요청 | 앱의 해당 기능에 권한 오류 |
| 둘을 하나로 합침 | 양쪽이 넓어진 권한을 가짐 | 앱에 불필요한 접근 권한이 생김 |
첫 줄과 둘째 줄의 증상이 다르다는 점이 진단에 도움이 돼요. 태스크가 아예 뜨지 못하면 대개 앞쪽이고, 뜨긴 떴는데 일부 동작만 실패하면 대개 뒤쪽이에요.
저는 무엇을 나눴나
제가 만드는 앱의 AI 서버도 두 역할을 따로 두었어요. 처음부터 그렇게 한 것은 아니고, 문서가 권하니까 따랐다가 나중에 이유를 이해한 쪽에 가까워요.
이해하게 된 계기는 이 컨테이너가 실제로 하는 일을 적어 봤을 때였어요. 이 프로세스는 모델을 올려 답을 만드는 일만 해요. 다른 AWS 서비스를 부를 이유가 사실상 없고, 그렇다면 태스크 역할에 담을 것도 거의 없다는 뜻이었어요. 반면 실행 역할에는 이미지를 내려받고 로그를 보낼 권한이 필요해요. 나눠 놓고 보니 한쪽은 거의 비어 있고 다른 한쪽만 채워져 있었는데, 합쳐 두었다면 그 비어 있어야 할 쪽이 채워진 상태로 돌고 있었을 것이에요.
무엇을 줄지 정하는 일보다 누가 쓰는지 먼저 적어 보는 일이 실제로 답을 정해 줬어요. 주체를 나누고 나면 각자에게 필요한 것은 대체로 짧은 목록이었어요.