cloudwithbass

[Kubernetes] ★ Service Account, Role, RoleBinding 본문

카테고리 없음

[Kubernetes] ★ Service Account, Role, RoleBinding

여영클 2024. 8. 12. 23:40

목차

    이번 포스팅에선 AWS IAM, Cluster와 관련한 Kubernetes 리소스들에 대해 정리하겠습니다.

    다룰 내용은 다음과 같습니다: Service Account, IRSA, Role, ClusterRole, RoleBinding, ClsuterRoleBinding

     

     


    1. EC2가 AWS Resource에 접근하려면

    • 우선 이해를 돕기 위해 k8s를 고려하지 않고, EC2가 AWS 리소스에 접근하는 상황을 가정하겠습니다.
    • 예를 들어, EC2가 ALB를 프로비저닝할 수도 있고, EC2 내에서 S3 bucket을 조회하는 등의 상황이 있을 것입니다.
    • 이러한 일들을 수행하기 위해선, 적절한 policy가 연결되어 있는 Role을 EC2에 부여해야 합니다.

    2. Pod도 같은 방식일까?

    이제 같은 방식으로 Kubernetes의 Pod에 대해 생각해 보겠습니다. 

    Pod도 EC2와 마찬가지로 AWS 리소스에 접근하는 경우가 있을 것입니다.

    그렇다면 EC2에서 했던 방식처럼 AWS IAM Role을 Pod에 부여해도 될까요?

     

    Pod는 언제든지 다운될 수 있고, 새로 생성될 수 있기 때문에 Pod에 AWS IAM Role을 부여하는 것은 적절하지 않습니다.

    따라서 Pod life가 시작하는 Deployment에 IAM Role을 부여해야 합니다.

     

    하지만 Kubernetes의 특성과 IAM Role의 구조적인 차이로 인해 문제가 발생합니다

    Deployment의 매니페스트 파일은 쿠버네티스 구조이기 때문에, Cloud concept인 IAM Role을 설정할 수 없습니다.

    # Deployment Manifest 파일의 예시
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
      labels:
        app: nginx
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:1.14.2
            ports:
            - containerPort: 80

     


    3. Service Account와 IRSA

    따라서 Kubernetes가 AWS resource에 접근할 수 있는 다른 방법이 필요합니다. 

    바로 Service Account(SA) 리소스를 활용하는 것입니다.

     

    SA와 IAM Role을 연동할 수 있는데, 이 방법을 IAM Role for Service Accounts (IRSA)라고 합니다.

    Service Account는 Kubernetes 리소스이기 때문에, Deployment의 Manifest 파일에 사용할 수 있습니다.

     

    Service Account를 Deployment와 연결하고,

    AWS IAM Role을 Service Account와 연결하면 Deployment에서 AWS IAm Role을 사용할 수 있습니다. 

    코드를 통해 예를 들어 알아보겠습니다.

     

     Service Account를 Deployment와 연결: 

    위와 같이 my-serviceaccount라는 Service Account를 만들고 annotation에 IAM Role ARN을 작성합니다.

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      annotations:
        eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/my-role #이곳
      name: my-serviceaccount
      namespace: my-namespace

     

     AWS IAM Role을 Service Account와 연결:

    아래처럼 Deployment의 spec.template.spec.seviceAccountName을 작성합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
      labels:
        app: nginx
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          serviceAccountName: my-serviceaccount #이곳
          containers:
          - name: nginx
            image: nginx:1.14.2
            ports:
            - containerPort: 80

     


    4. Role과 ClusterRole

    AWS의 IAM Policy는 AWS 리소스들에 대한 접근 허용 권한을 부여합니다.

    Kubernetes에도 이와 같은 기능을 하는 리소스가 있는데, ClusterRole과 Role입니다.

    이들은 리소스에 대해 '접근을 허용하는' 규칙을 나타내며, '접근을 거부하는' 규칙은 없습니다.

     

    Role 특정 네임스페이스의 리소스에 대한 접근 권한을 제어합니다. 

    ClusterRole전체 클러스터의 리소스에 대한 접근 권한을 관리합니다.

     

    둘의 차이점은 권한 제어의 범위밖에 없습니다.

     

    그리고 이 Role에 기반해서 권한을 제어하는 행동을 RBAC(Role-Based Access Control)이라고 합니다.

     

    예를 들어, 아래 코드의 Role은 'pod-reader' 네임 스페이스에서 pod의 get, watch, list 작업만을 허용합니다.

    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      namespace: default
      name: pod-reader
    rules:
    - apiGroups: [""] # "" indicates the core API group
      resources: ["pods"]
      verbs: ["get", "watch", "list"]

     

    만약 Role이 아닌 ClusterRole을 사용할 경우, 네임 스페이스를 지정할 필요는 없습니다.

     

    아래 코드는 ClusterRole의 예시 코드입니다.

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      # "namespace" omitted since ClusterRoles are not namespaced
      name: secret-reader
    rules:
    - apiGroups: [""]
      resources: ["secrets"]
      verbs: ["get", "watch", "list"]

     

    5.  RoleBinding과 ClusterRoleBinding

    RoleBinding은 subjects(User, Group, Service Account)에게 Role을 부여하는 역할을 합니다.

    아래 RoleBinding 리소스는 jane 사용자에게 pod-reader Role을 부여합니다.

    apiVersion: rbac.authorization.k8s.io/v1
    # This role binding allows "jane" to read pods in the "default" namespace.
    # You need to already have a Role named "pod-reader" in that namespace.
    kind: RoleBinding
    metadata:
      name: read-pods
      namespace: default
    subjects:
    # You can specify more than one "subject"
    - kind: User
      name: jane # "name" is case sensitive
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      # "roleRef" specifies the binding to a Role / ClusterRole
      kind: Role #this must be Role or ClusterRole
      name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
      apiGroup: rbac.authorization.k8s.io

     

    RoleBinding의 roleRef에 ClusterRole을 사용할 수 있습니다.

    이 경우, RoleBinding의 namespace에만 ClusterRole을 적용합니다.

     

    만약 전체 클러스터에 대한 권한을 부여하고 싶은 경우 ClusterRoleBinding을 사용하면 됩니다.


    6. 실습

    이번 실습에선 eks-user IAM user로 클러스터를 구성하고, terraform-user IAM user에게 클러스터 접근 권한을 줄 것입니다.

     

    실습을 위해 t3.micro 워커 노드를 사용해 클러스터를 구성합니다.

    eksctl create cluster --name my-cluster --region ap-northeast-2 --node-type t3.micro

     

    kubeconfig 업데이트

    aws eks update-kubeconfig --region ap-northeast-2 --name my-cluster

     

     

    현재 현재 eks-user로 로그인되어 있고, kubectl get all 명령이 잘 수행됩니다.

     

    aws configure 명령을 통해 terraform-user로 변경했습니다.

    terraform-user 사용자는 Cluster 접근 권한이 없으므로  kubectl get all 명령이 수행되지 않습니다.

     

    따라서 terraform-user 사용자에게 Cluster 접근 권한을 추가하겠습니다.

    kubectl edit -n kube-system configmap/aws-auth 명령을 실행하고, map Users에 terraform-user의 arn을 추가합니다.

    aws-auth configmap은 Amazon EKS Cluster에 IAM 보안 주체를 관리하는 방법입니다.

    이제 terraform-user 사용자는 Cluster에 접근할 수 있습니다.

     

    Q. 엥?? eks-user는 aws-auth ConfigMap에 없는데, 어떻게 클러스터에 접근할 수 있나요?

    A. 클러스터를 생성하는 IAM 보안 주체에게는 Amazon EKS 제어 영역의 클러스터 역할 기반 액세스 제어(RBAC) 구성에 system:masters 권한이 자동으로 부여됩니다.  system:masters 그룹은 클러스터의 Admin 역할을 합니다.

     

     

    terraform-user가  kubectl get pod 명령을 실행한 결과, terraform-user는 pod를 list할 수 없다는 에러 메시지가 나옵니다.

    terraform-user에겐, 클러스터에 대해 허용한 권한이 없기 때문입니다.

    따라서 role과 rolebinding을 배포해야 합니다.

     

    위에서 사용했던 예제에서 name만 terraform-user로 변경해서 배포하겠습니다.

    # role-pod-readOnly.yaml
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      namespace: default
      name: pod-reader
    rules:
    - apiGroups: [""] # "" indicates the core API group
      resources: ["pods"]
      verbs: ["get", "watch", "list"]
    # roleBinding-pod-readOnly.yaml
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: read-pods
      namespace: default
    subjects:
    - kind: User
      name: terraform-user # "name" is case sensitive
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: Role #this must be Role or ClusterRole
      name: pod-reader
      apiGroup: rbac.authorization.k8s.io

     

    eks-user로 Role과 RoleBinding을 배포하고, nginx를 배포하겠습니다.

     

    이제 다음 사진처럼 terraform-user는 kubectl get pod로 default namespace에서 pod를 조회(list)할 수 있지만,  kubectl run 명령은 Forbidden 에러가 발생합니다.

    roleBinding에서 role이 pod의 get, watch, list만 허용했기 때문입니다.


    aws-auth configmap은 더이상 사용되지 않습니다.

    이걸 실습을 끝낸 후에 발견했네요..

    https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/auth-configmap.html

    따라서 다음 문서를 참조해서 aws-auth ConfigMap이 아닌, AWS CLI나 Amazon EKS Console을 이용해 IAM 사용자에게 액세스 권한을 부여하시길 바랍니다.

     

    EKS 액세스 항목을 사용한 IAM 사용자에게 Kubernetes에 대한 액세스 권한 부여


    참조 문서

    Kubernetes 서비스 계정을 사용하도록 Pods 구성

    교차 계정 IAM 권한

    Using RBAC Authorization

    ConfigMap을 사용한 IAM 사용자에게 Kubernetes에 대한 액세스 권한 부여