ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Kubernetes] 보안 - Service Account, RBAC
    공부/쿠버네티스&헬름 2025. 2. 22. 18:15

    RBAC

    쿠버네티스 RBAC(Role-Based Access Control)는 클러스터 내의 리소스에 대한 접근 권한을 관리하는 메커니즘입니다. RBAC를 사용하면 사용자, 그룹 또는 서비스 계정(Service Account)에 특정 역할(Role)을 부여하여 클러스터 리소스에 대한 접근 권한을 제한할 수 있습니다.

    역할 (Role), 클러스터 역할 (ClusterRole)

    역할은 특정 네임스페이스 내에서 리소스에 대한 접근 권한을 정의합니다. 예를 들어 특정 네임스페이스의 파드를 읽기 권한을 가진 역할을 정의할 수 있습니다.

    클러스터 역할은 클러스터 전체 범위의 리소스에 대한 접근 권한을 정의합니다. 예를 들어 모든 네임스페이스의 파드를 읽기 권한을 가진 클러스터 역할을 정의할 수 있습니다.

    rules 필드를 통해 어떤 리소스에 대해 어떤 동작을 허용할지 정의하며 필드 내의 apiGroups, resources, verbs는 다음과 같은 종류를 갖습니다.

    Rules

    apiGroups

    API 그룹은 쿠버네티스 API를 논리적으로 그룹화한 것입니다. 각 리소스는 특정 API 그룹에 속합니다.

    • "" (빈 문자열): Core API 그룹. Pod, Service, Namespace 등 기본적인 리소스들
    • "apps": 애플리케이션 관련 리소스 (Deployment, ReplicaSet, StatefulSet 등)
    • "batch": 배치 작업 관련 리소스 (Job, CronJob 등)
    • "rbac.authorization.k8s.io": RBAC 관련 리소스 (Role, ClusterRole, RoleBinding, ClusterRoleBinding)
    • "networking.k8s.io": 네트워크 관련 리소스 (NetworkPolicy, Ingress 등)
    • "storage.k8s.io": 스토리지 관련 리소스 (PersistentVolume, PersistentVolumeClaim 등)
    • custom.metrics.k8s.io, metrics.k8s.io: 메트릭 관련 리소스
    • apiextensions.k8s.io: Custom Resource Definition 관련 리소스
    • 기타 사용자 정의 API 그룹

    resources

    리소스는 쿠버네티스 클러스터 내에서 관리되는 객체입니다. 각 API 그룹은 여러 종류의 리소스를 포함합니다.

    • Core API 그룹: pods, services, endpoints, nodes, namespaces, secrets, configmaps, persistentvolumeclaims, persistentvolumes, events
    • Apps API 그룹: deployments, replicasets, statefulsets, daemonsets
    • Batch API 그룹: jobs, cronjobs
    • RBAC API 그룹: roles, clusterroles, rolebindings, clusterrolebindings
    • Networking API 그룹: networkpolicies, ingresses
    • Storage API 그룹: storageclasses, persistentvolumes

    verbs

    동작은 리소스에 대해 수행할 수 있는 작업을 의미합니다.

    • * : 모든 동작을 의미
    • get: 리소스 정보를 조회
    • list: 리소스 목록을 조회
    • watch: 리소스 변경을 감시
    • create: 리소스를 생성
    • update: 리소스를 수정
    • patch: 리소스의 일부를 수정
    • delete: 리소스를 삭제
    • deletecollection: 리소스 컬렉션을 삭제
    • exec: Pod 내에서 명령을 실행
    • portforward: Pod의 포트를 로컬 포트로 포워딩
    • proxy: 다른 리소스에 대한 프록시 접근을 허용
    • use: 특정 리소스를 사용 (예: ServiceAccount의 토큰 사용)

    예시

    역할 (Role)

    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      namespace: my-namespace # 역할이 적용될 네임스페이스
      name: pod-reader # 역할 이름
    rules:
    - apiGroups: [""] # API 그룹 (core API 그룹은 "")
      resources: ["pods"] # 리소스 종류
      verbs: ["get", "list", "watch"] # 허용할 동작 (읽기, 목록 조회, 감시)

    클러스터 역할 (ClusterRole)

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: cluster-admin # 클러스터 역할 이름
    rules:
    - apiGroups: ["*"] # 모든 API 그룹
      resources: ["*"] # 모든 리소스
      verbs: ["*"] # 모든 동작

    역할 바인딩 (RoleBinding), 클러스터 역할 바인딩 (ClusterRoleBinding)

    역할 바인딩은 특정 네임스페이스 내에서 사용자, 그룹 또는 서비스 계정에 역할을 할당합니다. 예를 들어 my-namespacemy-user에게 pod-reader 역할을 할당할 수 있습니다.

    클러스터 역할 바인딩은 클러스터 전체 범위에서 사용자, 그룹 또는 서비스 계정에 클러스터 역할을 할당합니다. 예를 들어 my-group에게 cluster-admin 클러스터 역할을 할당할 수 있습니다.

    바인딩은 subjects와 roleRef 필드를 통해 대상과 역할을 연결합니다.

    subjects

    subjects 필드는 권한을 부여받을 대상을 지정합니다. 이 필드는 배열 형태이며, 각 요소는 다음과 같은 구조를 가집니다.

    kind

    • User: 쿠버네티스 사용자 계정. 일반적으로 클러스터 외부에서 인증된 사용자를 의미
    • Group: 쿠버네티스 그룹. 여러 사용자를 그룹으로 묶어 관리할 때 유용
    • ServiceAccount: 쿠버네티스 서비스 계정. 파드 내에서 실행되는 애플리케이션에 ID를 제공

    name

    • 사용자, 그룹 또는 서비스 계정의 이름

    apiGroup

    • rbac.authorization.k8s.io: RBAC 관련 API 그룹. User, Group, ServiceAccount를 사용할 때 필요합니다.

    roleRef

    roleRef 필드는 권한을 정의하는 역할(Role 또는 ClusterRole)을 지정합니다. 이 필드는 다음과 같은 구조를 가집니다.

    kind

    • Role: 특정 네임스페이스 내에서 리소스에 대한 권한을 정의하는 역할. RoleBinding에서 사용됩니다.
    • ClusterRole: 클러스터 전체 범위의 리소스에 대한 권한을 정의하는 클러스터 역할. ClusterRoleBinding에서 사용됩니다.

    name

    • 역할 또는 클러스터 역할의 이름.

    apiGroup

    • rbac.authorization.k8s.io: RBAC 관련 API 그룹. Role, ClusterRole을 사용할 때 필요합니다.

    예시

    역할 바인딩 (RoleBinding)

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: read-pods # 역할 바인딩 이름
      namespace: my-namespace # 역할 바인딩이 적용될 네임스페이스
    subjects:
    - kind: User # 사용자 종류
      name: my-user # 사용자 이름
      apiGroup: rbac.authorization.k8s.io # API 그룹
    roleRef:
      kind: Role # 역할 종류
      name: pod-reader # 역할 이름
      apiGroup: rbac.authorization.k8s.io # API 그룹

    클러스터 역할 바인딩 (ClusterRoleBinding)

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: cluster-admin-binding # 클러스터 역할 바인딩 이름
    subjects:
    - kind: Group # 그룹 종류
      name: my-group # 그룹 이름
      apiGroup: rbac.authorization.k8s.io # API 그룹
    roleRef:
      kind: ClusterRole # 클러스터 역할 종류
      name: cluster-admin # 클러스터 역할 이름
      apiGroup: rbac.authorization.k8s.io # API 그룹

    Service Account

    Kubernetes에서 서비스 계정은 사람이 아닌 계정 유형으로 Kubernetes 클러스터 내에서 고유한 ID를 제공합니다. 애플리케이션 파드, 시스템 구성 요소 및 클러스터 내부 및 외부의 엔터티는 특정 ServiceAccount의 자격 증명을 사용하여 해당 ServiceAccount로 식별할 수 있습니다. 이 ID는 API 서버에 인증하거나 ID 기반 보안 정책을 구현하는 등 다양한 상황에서 유용합니다.

    서비스 계정은 API 서버의 ServiceAccount 객체로 존재합니다. 서비스 계정은 다음과 같은 속성을 가집니다.

    • Namespaced: 각 서비스 계정은 Kubernetes 네임스페이스에 바인딩됩니다. 모든 네임스페이스는 생성 시 default ServiceAccount를 갖습니다.
    • Lightweight: ****서비스 계정은 클러스터에 존재하며 Kubernetes API에 정의됩니다. 특정 작업을 활성화하기 위해 서비스 계정을 빠르게 생성할 수 있습니다.
    • Portable: 복잡한 컨테이너화된 워크로드에 대한 구성 번들에는 시스템 구성 요소에 대한 서비스 계정 정의가 포함될 수 있습니다. 서비스 계정의 경량성과 네임스페이스 ID는 구성을 이식 가능하게 만듭니다.

    서비스 계정은 클러스터의 인증된 사람 사용자인 사용자 계정과 다릅니다. 기본적으로 사용자 계정은 Kubernetes API 서버에 존재하지 않습니다. 대신 API 서버는 사용자 ID를 불투명한 데이터로 취급합니다. 여러 방법을 사용하여 사용자 계정으로 인증할 수 있습니다. 일부 Kubernetes 배포판은 사용자 계정을 API 서버에 나타내기 위해 사용자 지정 확장 API를 추가할 수 있습니다.

    설명 ServiceAccount User 또는 group
    위치 Kubernetes API (ServiceAccount 객체) 외부
    접근제어 Kubernetes RBAC or 권한 부여 메커니즘 Kubernetes RBAC 또는 기타 ID 및 접근 관리 메커니즘
    사용용도 워크로드, 자동화 사람

    특징

    네임스페이스 소속

    각 서비스 계정은 특정 네임스페이스에 속합니다. 즉, 동일한 이름의 서비스 계정이 다른 네임스페이스에 존재할 수 있습니다.

    토큰 기반 인증

    서비스 계정은 토큰을 사용하여 API 서버에 인증합니다. 이 토큰은 Secret으로 저장되며 파드 내에서 접근할 수 있습니다.

    권한 관리

    서비스 계정은 Role 및 ClusterRole을 통해 특정 리소스에 대한 접근 권한을 부여받을 수 있습니다.

    Kubernetes 서비스 계정의 사용 사례

    파드의 API 서버 접근

    파드 내에서 실행되는 애플리케이션이 쿠버네티스 API 서버와 통신해야 할 때 서비스 계정을 사용합니다. 예를 들어, 파드가 ConfigMap 또는 Secret에 접근해야 하는 경우 해당 리소스에 대한 권한을 가진 서비스 계정을 파드에 할당하여 접근할 수 있습니다.

    외부 서비스 인증

    파드가 외부 서비스(예: 클라우드 API)에 인증해야 할 때 서비스 계정을 사용할 수 있습니다. 이 경우, 서비스 계정에 외부 서비스에 대한 인증 정보를 저장하고 파드에서 해당 정보를 사용하여 인증합니다.

    CI/CD 파이프라인

    CI/CD 파이프라인에서 쿠버네티스 클러스터에 접근해야 할 때 서비스 계정을 사용할 수 있습니다. 파이프라인에서 사용할 서비스 계정에 필요한 권한을 부여하고 파이프라인에서 해당 서비스 계정의 토큰을 사용하여 클러스터에 인증합니다.

    사용법

    1. service account 생성

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: my-service-account # 서비스 계정 이름
      namespace: my-namespace # 서비스 계정이 속할 네임스페이스

    Secret은 서비스 계정 생성 시 자동으로 생성되지만 수동으로 지정하기를 원한다면 다음과 같이 secret과 service account를 지정하면 됩니다.

    apiVersion: v1
    kind: Secret
    metadata:
      name: my-secret # Secret 이름
      namespace: my-namespaceㅈ
    type: kubernetes.io/service-account-token # Secret 유형
    stringData:
      token: <토큰 내용> # 토큰 내용 (일반적으로 자동으로 생성되지만, 필요에 따라 수동으로 지정 가능)
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: my-service-account
      namespace: my-namespace
    secrets:
    - name: my-secret # Secret을 서비스 계정에 연결

    2. 서비스 계정 할당

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-deployment
      namespace: my-namespace
    spec:
      replicas: 3 # 레플리카 수
      selector:
        matchLabels:
          app: my-app
      template:
        metadata:
          labels:
            app: my-app
        spec:
          serviceAccountName: my-service-account # Deployment에 속한 Pod에 할당할 서비스 계정
          containers:
          - name: my-container
            image: my-image
            # ... (컨테이너 설정)
          volumes:
                  - name: token-volume
                    secret:
                      secretName: my-secret # Secret 볼륨 마운트 (자동이면 생략 가능)

    궁금증

    GCP나 AWS의 서비스를 파드에서 어떻게 접근할 수 있을까?

    예를 들어, GKE의 파드에서 빅쿼리나 cloudSQL에 접근하거나 EKS의 파드에서 RDS나 open search에 접근한다고 할 때, 다음과 같은 방식으로 접근할 수 있습니다.

    1. AWS 환경 (EKS)

    IAM 역할 (IAM Role)

    • 원리: AWS IAM(Identity and Access Management) 역할을 Kubernetes 서비스 계정에 연결하여 파드가 AWS 리소스에 접근할 수 있는 권한을 부여합니다.
    • 프로세스
      1. AWS IAM 콘솔에서 필요한 권한을 가진 IAM 역할을 생성합니다.
      2. EKS 클러스터에서 Kubernetes 서비스 계정을 생성합니다.
      3. IAM 역할과 Kubernetes 서비스 계정을 연결합니다 (eksctl, AWS IAM Authenticator 등을 사용).
      4. 파드는 서비스 계정과 연결된 IAM 역할의 자격 증명을 사용하여 AWS 리소스에 접근합니다.
    • 예시: EKS의 파드가 RDS에 접근하는 경우, RDS 접근 권한을 가진 IAM 역할을 생성하고 해당 역할을 파드의 서비스 계정에 연결합니다. 파드는 연결된 IAM 역할의 자격 증명을 사용하여 RDS에 접근합니다.

    2. GCP 환경 (GKE)

    Workload Identity

    • 원리: GKE 파드가 Google Cloud 서비스 계정으로 인증하도록 구성하여 Google Cloud 리소스에 접근 권한을 부여합니다.
    • 프로세스:
      1. Google Cloud 콘솔에서 필요한 권한을 가진 Google Cloud 서비스 계정을 생성합니다.
      2. GKE 클러스터에서 Kubernetes 서비스 계정을 생성합니다.
      3. Google Cloud 서비스 계정과 Kubernetes 서비스 계정을 연결합니다 (gcloud 명령어를 사용).
      4. 파드는 연결된 Google Cloud 서비스 계정의 자격 증명을 사용하여 Google Cloud 리소스에 접근합니다.
    • 예시: GKE의 Pod가 BigQuery에 접근하는 경우, BigQuery 접근 권한을 가진 Google Cloud 서비스 계정을 생성하고 해당 계정을 파드의 서비스 계정에 연결합니다. 파드는 연결된 Google Cloud 서비스 계정의 자격 증명을 사용하여 BigQuery에 접근합니다.

    쿠버네티스의 서비스 계정에 ClusterRoleBinding을 주어서 1개의 서비스 계정으로 여러 서비스에서 사용해도 되는지?

    하나의 쿠버네티스 서비스 계정으로 여러 클라우드 서비스를 사용하는 것은 고려할 사항이 있습니다.

    클라우드 서비스 계정 권한

    쿠버네티스 서비스 계정과 연결된 클라우드 서비스 계정은 접근하려는 모든 클라우드 서비스에 대한 권한을 가지고 있어야 합니다. 예를 들어, BigQuery와 Cloud SQL에 모두 접근해야 한다면 연결된 클라우드 서비스 계정은 BigQuery와 Cloud SQL에 대한 권한을 모두 가지고 있어야 합니다.

    최소 권한 원칙

    보안을 위해 클라우드 서비스 계정에는 필요한 최소한의 권한만 부여하는 것이 좋습니다. 하나의 클라우드 서비스 계정으로 여러 서비스에 접근하는 경우, 각 서비스에 필요한 권한을 모두 포함해야 하므로 권한 범위가 넓어질 수 있습니다.

    쿠버네티스 서비스 계정 관리

    하나의 쿠버네티스 서비스 계정으로 여러 클라우드 서비스를 사용하는 경우, 해당 서비스 계정에 대한 관리가 중요해집니다. 서비스 계정의 토큰이 유출될 경우 모든 클라우드 서비스에 대한 접근 권한이 노출될 수 있으므로 주의해야 합니다.

    서비스 계정을 생성하고 RoleBinding이나 ClusterRoleBinding을 설정하지 않으면 해당 서비스 계정의 rbac은 어떤걸까?

    만약 서비스 계정을 생성하고 RoleBinding이나 ClusterRoleBinding을 설정하지 않으면 해당 서비스 계정은 아무런 권한도 가지지 않습니다.

    쿠버네티스 RBAC는 기본적으로 모든 접근을 거부합니다. 즉, 명시적으로 권한을 부여하지 않으면 어떤 리소스에도 접근할 수 없습니다. 특정 리소스에 대한 접근을 허용하려면 Role 또는 ClusterRole을 정의하고 RoleBinding 또는 ClusterRoleBinding을 통해 서비스 계정에 해당 역할을 할당해야 합니다.

    따라서 서비스 계정을 생성하면 해당 계정은 클러스터 내의 어떤 리소스에도 접근할 수 없는 상태로 시작합니다. RoleBinding이나 ClusterRoleBinding을 통해 권한을 부여해야만 특정 리소스에 대한 접근이 가능해집니다.

    예를 들어, 서비스 계정 my-service-account를 생성했지만 어떤 RoleBinding이나 ClusterRoleBinding도 설정하지 않은 경우, 해당 서비스 계정은 Pod, Service, Deployment 등 어떤 리소스에도 접근할 수 없습니다. 파드에 my-service-account 서비스 계정을 할당하고 파드를 실행하더라도 파드 내의 컨테이너는 API 서버와 통신하여 어떤 작업도 수행할 수 없습니다.

    레퍼런스

    https://kubernetes.io/docs/concepts/security/service-accounts/

    댓글