AWS EKS - Service Account 와 IAM Role 연결하기

2020. 2. 8. 18:01Kubernetes

이번 글에서는 간단하게 사용법만 설명하고 다음 글에서 이론을 자세히 다루도록 하겠습니다.

 

1. 왜 필요한가요?

일반적으로 AWS SDK사용 시 환경변수, EC2 IAM Role 등을 통해 인증을 합니다. 하지만, K8S환경에서는 EC2 IAM Role은 적합하지 않습니다. 예로 DynamoDB 권한이 필요한 주문처리 앱, SQS 권한이 필요한 메세징 앱이 같은 클러스터에서 동작 시 모든 워커노드가 공유하는 IAM Role에 두 권한을 모두 부여해야 합니다. 이는 Least Privilege Principle에 맞지 않기에 권장되지 않습니다. 

 

그렇다고 환경변수가 답은 아닙니다. AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY 이 두 환경변수를 K8S Secret 을 통해 마운팅 하면 작동은 잘 됩니다. 하지만, 해당 키들의 수명주기는 매우 깁니다. 유출 시 피해기간이 길어지며 키 관리또한 어렵습니다.

 

이런 문제에 대한 기존 해결책은 kube2iam 같은 프로젝트 였으나 AWS Metadata call 프록시 등 다소 설치하기 까다롭습니다. 

 

이렇기에, EKS 공식 기능인 "IAM roles for service accounts" 을 추천 합니다. 이를 통해 IAM Role을 ServiceAccount와 연관시키고 그 ServiceAccount를 Pod과 연결시켜 세분화되고 안전한 권한 부여를 하는 것 입니다. 

  • Pod 마다 별도 Role 부여 가능
  • STS Token 활용하여 키 관리 필요 X
  • 1~12시간 길이의 STS Token 사용하여 키 노출 시에도 노출 범위/기간 최소화

2. 요구조건

3. 적용하기

eksctl을 이용하면 보다 간편하게 적용할 수 있으나 GUI가 보다 직관적이기에 AWS 콘솔에서 진행하겠습니다.

3.1. IAM <-> EKS Cluster 연결

  1. EKS에서 원하는 Cluster 클릭시 아래와 같은 화면이 나오면 "OpenID Connect provider URL" 값을 복사한다
  2. IAM > Identity providers > "Create Provider" 버튼 클릭
  3. 다음과 같이 설정 값 입력
    • Provider Type: OpenID Connect
    • Provider URL: 1번에서 복사한 값
    • Audience: sts.amazonaws.com

EKS 대시보드
IAM > Identity providers 화면

3.2 K8S Service Account 생성

나중에 Pod에 붙일 Service Account 를 생성합니다

3.3 IAM Role 생성

IAM 에서 Role 생성 시 다음 설정을 가져갑니다

  • Trusted entity: Web identity
  • Identity provider: 3.1 에서 추가한 EKS 클러스터 (같은 리전에 있는 클러스터들을 IAM에 등록 한 경우 같은 이름으로 보이니 마지막 'Review' step에서 확인이 필요합니다.
  • Audience: sts.amazonaws.com

IAM Role 생성 화면

Role 생성 후 해당 Role의 'Trust relationshps' 탭 > 'Edit trust relationship' 버튼 클릭 후 다음과 같이 수정합니다.

여기서 바꿔야 할것은 총 2개입니다.

IAM Edit Trust Relationsips 버튼

  1. Statement > Condition > StringEquals 에 있는 클러스터 OIDC URL뒤에 ":aud"를 ":sub"로 변경
    • 예) oidc.eks.ap-northeast-1.amazonaws.com/id/AAAAAAAAAAAAAAAAAAAAAAAAAAAA:sub
  2. 1번에서 바꾼 Key의 값이 "system:serviceaccount:{Service Account 네임스페이스}:{ServiceAccount 이름}"
    • 예) system:serviceaccount:default:sample-svc-ac

3.4 Pod에 Service Account 연결

3.4.1 Service Account에 IAM Role 정보 주입

Service Account가 어떤 IAM Role과 연결되기 알려주기 위해 다음과 같이 Service Account에 annotation을 추가해줍니다. Annotation에 들어갈 role-arn은 3.3에서 생성한 IAM Role의 ARN을 넣어줍니다.

3.4.2 Pod에 Service Account 정의

다음 YAML은 AWS ALB Controller Deployment를 우리가 만든 Service Account를 사용하도록 바꾼 것입니다. 이와같이 Pod에 Service Account를 정의해주면 됩니다.

* 주의사항 - Container Image 안 AWS 서비스를 사용할 주체가 최신 AWS SDK/CLI를 사용하는지 꼭 확인하세요. 

4. 확인하기

4.1 YAML get Pod

Service Account를 연결한 Pod를 yaml get을 이용해서 들여다 보면 아래와 같이 되어있습니다.

새로운 readonly volume이 하나 마운트 되서 STS Token 을 제공합니다. 이런 볼륨이 마운트 되어있다면 거의 모든게 끝난겁니다.

4.2 환경변수 확인

kubectl -n {네임스페이스} exec {Pod 이름} printenv | grep AWS 명령어로 AWS_WEB_IDENTITY_TOKEN_FILE, AWS_ROLE_ARN 환경변수가 주입되어있는지 확인이 가능합니다.

  • AWS_WEB_IDENTITY_TOKEN_FILE - STS Token의 위치
  • AWS_ROLE_ARN - Assume 하고자 하는 IAM Role의 ARN

여기까지 확인하였으면 인프라 입장에서는 끝났습니다. 여기서부터는 SDK/CLI가 Web identity token을 받아 사용하기만 하면 됩니다. 

 

다음 포스팅에서는 이 것이 어떻게 가능한것인지 내부 구조를 살펴보고 샘플 Spring Boot 프로젝트를 만들어 보도록 하겠습니다.