테라폼으로 EBS CSI Driver 설치 & 트러블 슈팅 정리

이숭늉·2025년 7월 16일
0

DevOps

목록 보기
17/19
post-thumbnail

🖇️ EBS CSI Driver 설치 & 트러블 슈팅 정리

이전 글 Kubernetes ServiceAccount와 IRSA : EKS에서의 권한 관리 에서 EBS CSI Driver를 잠깐 설치해봤는데 이때 발생한 트러블 슈팅 과정을 정리해보려 한다.


설치 과정

OIDC 신뢰 정책 구성

Kubernetes에서 SA가 IAM Role을 사용하려면, AWS에서는 해당 SA가 신뢰할 수 있는 주체인지 검증해야 한다. 이를 위해 EKS는 OIDC 기반의 ID 토큰을 사용한다.

검증 흐름
1. Pod가 실행될 때 K8s는 SA에 대한 ID 토큰을 발급한다. 이 토큰에는 "나는 ~~라는 SA를 사용하는 Pod야" 같은 정보가 담겨 있다.
2. 해당 Pod에서 AWS 리소스에 접근하기 위해 ID 토큰과 연결된 IAM Role ARN을 함께 사용하여 AssumeRoleWithWebIdentity API를 호출한다.
3. AWS STS는 IAM과 연동하여, 해당 JWT의 발급자가 IAM에 등록된 OIDC 공급자와 일치하는지를 확인한다.
4. IAM은 JWT의 sub 값이 해당 Role의 신뢰 정책 조건과 일치하는지 확인한다. 이를 통해 명시된 SA만 해당 Role을 사용할 수 있도록 제한할 수 있다.
5. 검증 성공 시, AWS STS는 Pod에 대해 IAM Role에 상응하는 임시 자격 증명을 발급한다.
6. Pod는 이 자격 증명을 통해 AWS 리소스에 접근할 수 있다.

# EBS CSI Role 
resource "aws_iam_role" "ebs_csi_role" {
  name = "ebs-csi-controller-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRoleWithWebIdentity"
      Effect = "Allow"
      Principal = {
        "Federated": var.oidc_provider_arn
      }
      Condition = {
        StringEquals = {
          "${replace(var.oidc_issuer_url, "https://", "")}:sub" = "system:serviceaccount:kube-system:ebs-csi-controller-sa"
        }
      }
    }]
  })
}

나의 경우는 모듈을 기능 단위로 분리했기 때문에, EKS 모듈에서 OIDC URL을 output 변수로 내보내고, 이를 통해 메인 모듈의 data 블록으로 OIDC 발급자 ARN을 찾아오도록 구성했다.

# modules/eks-cluster/outputs.tf
output "cluster_oidc_issuer_url" {
  value = aws_eks_cluster.eks.identity[0].oidc[0].issuer
}

# main.tf
data "aws_iam_openid_connect_provider" "eks_oidc" {
  arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${replace(module.eks.cluster_oidc_issuer_url, "https://", "")}"
}

🔥 트러블 슈팅

설정이 모두 끝났다고 생각하고 terraform apply를 했는데 이런 에러가 발생했다.

EKS 콘솔에서 OIDC 발급자 URL도 확인이 됐고, 에러 문구의 URL과도 정확히 일치했다. 지피티를 닦달하며 원인을 찾아내려 했지만 계속 같은 말만 반복했고, 인터넷을 찾아보다 IAM 콘솔에서 ID 공급자를 찾아보라는 말을 봤다.
그런데 잘 생성된 줄 알았던 공급자가 IAM 콘솔의 ID 공급업체 메뉴에서는 찾을 수가 없었다.

원인

원인은 EKS에서 OIDC 발급자 URL은 자동으로 생성됐지만, 해당 발급자를 IAM의 OIDC 공급자로 등록하는 작업은 자동으로 이루어지지 않는다는 점이었다. 이 작업은 사용자가 수동으로 하거나, 테라폼 등을 통해 명시적으로 해주어야 했다. 즉, 내가 별도로 등록을 해주기 전까지는 IAM에서 해당 OIDC 공급자를 신뢰할 수 없는 상태였다.

해결책

아래 리소스를 추가하여 EKS의 OIDC 발급자를 신뢰할 수 있도록 명시적으로 IAM에 등록했다.

# modules/eks-irsa/main.tf
resource "aws_iam_openid_connect_provider" "eks" {
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = ["9e99a48a9960b14926bb7f3b02e22da0afd40b86"] # AWS가 사용하는 루트 CA
  url             = var.oidc_issuer_url
}

처음에는 이 공급자를 기존 코드대로 data 블록으로 가져오려고 했는데 apply를 하자 여전히 해당 OIDC 공급자가 존재하지 않는다는 오류가 발생했다.

이유는 간단했다.
data 블록은 이미 존재하는 기존의 리소스를 조회할 때 사용하는 것이지, 같은 시점에 생성될 리소스를 참조할 수는 없다.
즉, resource 블록으로 OIDC 공급자를 아직 만들지도 않았는데 data 블록으로 먼저 가져오려다 보니 에러가 난 것이었고, 사실상 처음부터 data 블록을 쓴 접근 자체가 잘못된 선택이었다.

그래서 기존의 data 블록이 아닌 eks-irsa 모듈에서 output 변수로 OIDC 공급자 ARN을 가져오도록 수정했다.

# main.tf
module "eks_addons_ebs" {
  source                 = "./modules/eks-addons-ebs"
  region                 = "ap-northeast-2"
  cluster_name           = module.eks.cluster_name
  oidc_provider_arn      = module.eks_irsa.oidc_provider_arn
  oidc_issuer_url        = module.eks.cluster_oidc_issuer_url
  ebs_csi_driver_version = "v1.44.0-eksbuild.1" 
}

이렇게 하면, 테라폼이 의존 관계를 자동으로 인식하고, OIDC 등록 후에 그 ARN 값을 참조하게 된다.

모든 리소스의 프로비저닝이 완료된 후, 바스천에서 EBS CSI Driver의 SA에 Role이 IRSA를 통해 잘 연결된 것을 확인할 수 있다.


확인 : EBS CSI Driver 정상 동작 검증

EBS CSI Driver가 정상적으로 잘 설치됐는지 확인하기 위해 EBS 스토리지를 사용하는 Pod를 생성해보았다.

1. StorageClass & PVC 생성
우선 먼저 SC와 PVC를 생성한다.

  • SC는 EBS를 어떻게 만들 것인가에 대한 정책을 정의한 객체이고,
  • PVC는 EBS를 요청하는 객체이다. 자신이 지정한 SC를 참고해서 EBS를 얼마나, 어떤 방식으로 사용할 것인지 요청한다.
# ebs-sc.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer

# pvc-sc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-test-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: ebs-sc
  resources:
    requests:
      storage: 4Gi

위 리소스를 적용한 뒤 잘 생성됐는지 kubectl get sc,pvc로 확인한다.

2. PVC를 사용하는 Pod 배포
이제 위에서 만든 PVC를 사용하는 테스트용 Pod를 생성한다.

apiVersion: v1
kind: Pod
metadata:
  name: ebs-test-pod
spec:
  containers:
    - name: app
      image: amazonlinux
      command: [ "sleep", "3600" ]
      volumeMounts:
        - mountPath: "/data"
          name: data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: ebs-test-pvc

Pod가 생성되고 일정 시간이 지나면, Pod도 정상적으로 Running 상태이고, pvc도 잘 바운드된 걸 확인할 수 있다.

EBS 콘솔에서도 바스천이나 노드 그룹에서 사용하는 볼륨이 아닌 Pod용 볼륨이 새로 생성된 것을 확인할 수 있다.

해당 볼륨이 확인되면, EBS CSI Driver가 잘 설치되었고, IAM Role 및 IRSA 연동도 정상적으로 작동하고 있음을 의미한다. (전에 Role 연결이 되지 않은 상태에서 같은 과정을 수행했을 때 Pod가 계속 Pending 상태로 정상적으로 실행되지 않았었다)


이번 기회를 통해 K8s의 ServiceAccount가 AWS 리소스에 접근할 때 어떤 방식으로 인증을 수행하는지 좀 더 깊이 이해할 수 있었고, 테라폼 문법도 더 알게 되었다.

profile
부지런히 살자

0개의 댓글