실습 설정 안내 및 요구사항
계정과 진행 상황을 보호하세요. 이 실습을 실행하려면 항상 시크릿 브라우저 창과 실습 사용자 인증 정보를 사용하세요.

Kubernetes Engine에서 역할 기반 액세스 제어 사용

실습 20분 universal_currency_alt 크레딧 5개 show_chart 중급
info 이 실습에는 학습을 지원하는 AI 도구가 통합되어 있을 수 있습니다.
이 콘텐츠는 아직 휴대기기에 최적화되지 않음
최상의 경험을 위해 데스크톱 컴퓨터에서 이메일로 전송된 링크를 사용하여 방문하세요.

GSP493

Google Cloud 사용자 주도형 실습 로고

개요

이 실습에서는 Kubernetes Engine 클러스터에서 역할 기반 액세스 제어(RBAC)의 사용 및 디버깅에 대해 다룹니다.

RBAC 리소스 정의는 모든 Kubernetes 플랫폼에서 표준으로 제공되지만, 클라우드 제공업체에서 빌드할 때는 기본 인증 및 승인 제공업체와의 상호작용을 이해해야 합니다.

RBAC는 클러스터 내에서 작업을 제한하는 방식에 있어 뛰어난 유연성을 제공하는 강력한 보안 메커니즘입니다. 이 실습에서는 RBAC의 두 가지 사용 사례를 다룹니다.

  1. 사용자 페르소나(소유자 및 감사자)에 서로 다른 권한을 할당합니다.
  2. 클러스터 내에서 실행되는 애플리케이션에 제한된 API 액세스 권한을 부여합니다.

RBAC의 유연성이 때때로 복잡한 규칙으로 이어질 수 있으므로 RBAC 문제 해결을 위한 일반적인 단계가 시나리오 2에 포함되어 있습니다.

아키텍처

이 실습에서는 Kubernetes Engine 클러스터 내에서 RBAC를 사용하는 데 중점을 둡니다. 다양한 사용자 페르소나에 대해 서로 다른 수준의 클러스터 권한을 부여할 수 있는 방법을 보여줍니다. 사용자 페르소나를 나타내는 2개의 서비스 계정과 3개의 네임스페이스(dev, test, prod)를 프로비저닝합니다. '소유자' 페르소나는 3개의 네임스페이스 모두에 대한 읽기/쓰기 액세스 권한을 가지며, '감사자' 페르소나는 dev 네임스페이스에만 제한된 읽기 전용 액세스 권한을 가집니다.

이 실습은 GKE Helmsman 엔지니어가 GKE에서 역할 기반 액세스 제어 사용에 대해 더 잘 이해할 수 있도록 제작되었습니다. 이 데모는 GitHub에서 확인할 수 있습니다. 누구나 Google의 애셋에 기여할 수 있습니다.

아키텍처 다이어그램

설정 및 요건

실습 시작 버튼을 클릭하기 전에

다음 안내를 확인하세요. 실습에는 시간 제한이 있으며 일시중지할 수 없습니다. 실습 시작을 클릭하면 타이머가 시작됩니다. 이 타이머는 Google Cloud 리소스를 사용할 수 있는 시간이 얼마나 남았는지를 표시합니다.

실무형 실습을 통해 시뮬레이션이나 데모 환경이 아닌 실제 클라우드 환경에서 실습 활동을 진행할 수 있습니다. 실습 시간 동안 Google Cloud에 로그인하고 액세스하는 데 사용할 수 있는 새로운 임시 사용자 인증 정보가 제공됩니다.

이 실습을 완료하려면 다음을 준비해야 합니다.

  • 표준 인터넷 브라우저 액세스 권한(Chrome 브라우저 권장)
참고: 이 실습을 실행하려면 시크릿 모드(권장) 또는 시크릿 브라우저 창을 사용하세요. 개인 계정과 학습자 계정 간의 충돌로 개인 계정에 추가 요금이 발생하는 일을 방지해 줍니다.
  • 실습을 완료하기에 충분한 시간(실습을 시작하고 나면 일시중지할 수 없음)
참고: 이 실습에는 학습자 계정만 사용하세요. 다른 Google Cloud 계정을 사용하는 경우 해당 계정에 비용이 청구될 수 있습니다.

실습을 시작하고 Google Cloud 콘솔에 로그인하는 방법

  1. 실습 시작 버튼을 클릭합니다. 실습 비용을 결제해야 하는 경우 결제 수단을 선택할 수 있는 대화상자가 열립니다. 왼쪽에는 다음과 같은 항목이 포함된 실습 세부정보 창이 있습니다.

    • Google Cloud 콘솔 열기 버튼
    • 남은 시간
    • 이 실습에 사용해야 하는 임시 사용자 인증 정보
    • 필요한 경우 실습 진행을 위한 기타 정보
  2. Google Cloud 콘솔 열기를 클릭합니다(Chrome 브라우저를 실행 중인 경우 마우스 오른쪽 버튼으로 클릭하고 시크릿 창에서 링크 열기를 선택합니다).

    실습에서 리소스가 가동되면 다른 탭이 열리고 로그인 페이지가 표시됩니다.

    팁: 두 개의 탭을 각각 별도의 창으로 나란히 정렬하세요.

    참고: 계정 선택 대화상자가 표시되면 다른 계정 사용을 클릭합니다.
  3. 필요한 경우 아래의 사용자 이름을 복사하여 로그인 대화상자에 붙여넣습니다.

    {{{user_0.username | "Username"}}}

    실습 세부정보 창에서도 사용자 이름을 확인할 수 있습니다.

  4. 다음을 클릭합니다.

  5. 아래의 비밀번호를 복사하여 시작하기 대화상자에 붙여넣습니다.

    {{{user_0.password | "Password"}}}

    실습 세부정보 창에서도 비밀번호를 확인할 수 있습니다.

  6. 다음을 클릭합니다.

    중요: 실습에서 제공하는 사용자 인증 정보를 사용해야 합니다. Google Cloud 계정 사용자 인증 정보를 사용하지 마세요. 참고: 이 실습에 자신의 Google Cloud 계정을 사용하면 추가 요금이 발생할 수 있습니다.
  7. 이후에 표시되는 페이지를 클릭하여 넘깁니다.

    • 이용약관에 동의합니다.
    • 임시 계정이므로 복구 옵션이나 2단계 인증을 추가하지 않습니다.
    • 무료 체험판을 신청하지 않습니다.

잠시 후 Google Cloud 콘솔이 이 탭에서 열립니다.

참고: Google Cloud 제품 및 서비스에 액세스하려면 탐색 메뉴를 클릭하거나 검색창에 제품 또는 서비스 이름을 입력합니다. 탐색 메뉴 아이콘 및 검색창

Cloud Shell 활성화

Cloud Shell은 다양한 개발 도구가 탑재된 가상 머신으로, 5GB의 영구 홈 디렉터리를 제공하며 Google Cloud에서 실행됩니다. Cloud Shell을 사용하면 명령줄을 통해 Google Cloud 리소스에 액세스할 수 있습니다.

  1. Google Cloud 콘솔 상단에서 Cloud Shell 활성화 Cloud Shell 활성화 아이콘를 클릭합니다.

  2. 다음 창을 클릭합니다.

    • Cloud Shell 정보 창을 통해 계속 진행합니다.
    • 사용자 인증 정보를 사용하여 Google Cloud API를 호출할 수 있도록 Cloud Shell을 승인합니다.

연결되면 사용자 인증이 이미 처리된 것이며 프로젝트가 학습자의 PROJECT_ID, (으)로 설정됩니다. 출력에 이 세션의 PROJECT_ID를 선언하는 줄이 포함됩니다.

Your Cloud Platform project in this session is set to {{{project_0.project_id | "PROJECT_ID"}}}

gcloud는 Google Cloud의 명령줄 도구입니다. Cloud Shell에 사전 설치되어 있으며 명령줄 자동 완성을 지원합니다.

  1. (선택사항) 다음 명령어를 사용하여 활성 계정 이름 목록을 표시할 수 있습니다.
gcloud auth list
  1. 승인을 클릭합니다.

출력:

ACTIVE: * ACCOUNT: {{{user_0.username | "ACCOUNT"}}} To set the active account, run: $ gcloud config set account `ACCOUNT`
  1. (선택사항) 다음 명령어를 사용하여 프로젝트 ID 목록을 표시할 수 있습니다.
gcloud config list project

출력:

[core] project = {{{project_0.project_id | "PROJECT_ID"}}} 참고: gcloud 전체 문서는 Google Cloud에서 gcloud CLI 개요 가이드를 참고하세요.

리전 및 영역 설정

특정 Compute Engine 리소스는 여러 리전과 영역에 위치합니다. 리전은 리소스를 실행할 수 있는 특정한 지리적 위치로, 각 리전에는 영역이 하나 이상 있습니다.

리전 및 영역 문서에서 리전과 영역에 관해 자세히 알아보고 전체 목록을 확인하세요.

실습에서 리전과 영역을 설정하려면 다음을 실행하세요(사용자에게 가장 적합한 리전/영역을 사용할 수 있음).

gcloud config set compute/region {{{project_0.default_region|REGION}}} gcloud config set compute/zone {{{project_0.default_zone|ZONE}}}

작업 1. 클러스터 확인

콘솔에서 사전 생성된 클러스터를 확인합니다. 탐색 메뉴 > Kubernetes Engine > 클러스터로 이동하여 'rbac-demo-cluster' 클러스터를 클릭합니다. 새 클러스터에서 기존 승인이 사용 중지되어 있는지 확인합니다.

콘솔의 클러스터 설정

작업 2. 시나리오 1: 사용자 페르소나별 권한 할당

IAM - 역할

iam.tf에서 Terraform 구성의 일부로 아래 권한이 있는 kube-api-ro-xxxxxxxx(xxxxxxxx는 임의의 문자열)라는 역할이 생성되었습니다. 이러한 권한은 Kubernetes API에 액세스해야 하는 모든 사용자에게 필요한 최소 권한입니다.

  • container.apiServices.get
  • container.apiServices.list
  • container.clusters.get
  • container.clusters.getCredentials

사용자 시뮬레이션

테스트 사용자로 활동할 3개의 서비스 계정이 생성되었습니다.

  • 관리자: 클러스터 및 모든 리소스에 대한 관리자 권한을 보유합니다.
  • 소유자: 일반 클러스터 리소스에 대한 읽기/쓰기 권한을 보유합니다.
  • 감사자: dev 네임스페이스 내에서만 읽기 전용 권한을 보유합니다.
  1. 다음을 실행합니다.
gcloud iam service-accounts list

Terraform 스크립트에 의해 3개의 테스트 호스트가 프로비저닝되었습니다. 각 노드에는 kubectlgcloud가 설치 및 구성되어 서로 다른 사용자 페르소나를 시뮬레이션합니다.

  • gke-tutorial-admin: kubectl 및 gcloud는 클러스터 관리자로 인증됩니다.
  • gke-tutorial-owner: owner 계정을 시뮬레이션합니다.
  • gke-tutorial-auditor: auditor 계정을 시뮬레이션합니다.
  1. 다음을 실행합니다.
gcloud compute instances list

출력:

NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS rbac-demo-cluster-default-pool-a9cd3468-4vpc {{{project_0.default_zone|ZONE}}} n1-standard-1 10.0.96.5 RUNNING rbac-demo-cluster-default-pool-a9cd3468-b47f {{{project_0.default_zone|ZONE}}} n1-standard-1 10.0.96.6 RUNNING rbac-demo-cluster-default-pool-a9cd3468-rt5p {{{project_0.default_zone|ZONE}}} n1-standard-1 10.0.96.7 RUNNING gke-tutorial-auditor {{{project_0.default_zone|ZONE}}} f1-micro 10.0.96.4 35.224.148.28 RUNNING gke-tutorial-admin {{{project_0.default_zone|ZONE}}} f1-micro 10.0.96.3 35.226.237.142 RUNNING gke-tutorial-owner {{{project_0.default_zone|pZONE}}} f1-micro 10.0.96.2 35.194.58.130 RUNNING

RBAC 규칙 만들기

관리 인스턴스에 로그인하고 rbac.yaml 매니페스트를 적용하여 네임스페이스, 역할, RoleBinding을 만듭니다.

  1. SSH를 통해 관리자에 연결합니다.
gcloud compute ssh gke-tutorial-admin 참고: gcp 인증 플러그인과 관련된 오류는 무시하세요.

kubectl 및 커스텀 Kubernetes 클라이언트의 기존 버전에는 클라이언트와 Google Kubernetes Engine 간의 인증을 관리하는 제공업체별 코드가 포함되어 있습니다. v1.26부터는 이 코드가 더 이상 OSS kubectl에 포함되지 않습니다. GKE 사용자는 별도의 인증 플러그인을 다운로드하고 사용하여 GKE별 토큰을 생성해야 합니다. 새로운 바이너리인 gke-gcloud-auth-plugin은 GKE를 지원하는 kubectl 인증을 확장하는 데 Kubernetes Client-go 사용자 인증 정보 플러그인 메커니즘을 사용합니다. 자세한 내용은 다음 문서를 참조하세요.

kubectl에서 기본 제공업체별 코드를 사용하는 대신 새로운 인증용 바이너리 플러그인을 사용하도록 하려면 다음 단계를 사용합니다.

  1. 연결되면 다음 명령어를 실행하여 VM에 gke-gcloud-auth-plugin을 설치합니다.
sudo apt-get install google-cloud-sdk-gke-gcloud-auth-plugin
  1. ~/.bashrc에서 export USE_GKE_GCLOUD_AUTH_PLUGIN=True를 설정합니다.
echo "export USE_GKE_GCLOUD_AUTH_PLUGIN=True" >> ~/.bashrc
  1. 다음 명령어를 실행합니다.
source ~/.bashrc
  1. 다음 명령어를 실행하여 이 클러스터의 구성이 Client-go 사용자 인증 정보 플러그인 구성으로 업데이트되도록 합니다.
gcloud container clusters get-credentials rbac-demo-cluster --zone {{{project_0.default_zone|ZONE}}}

성공하면 다음 메시지가 표시됩니다.

Kubeconfig entry generated for dev-cluster.

이제 새로 만든 클러스터를 배스천에서 표준 kubectl 명령어에 사용할 수 있습니다.

  1. 네임스페이스, 역할, 바인딩을 만듭니다.
kubectl apply -f ./manifests/rbac.yaml

출력:

namespace/dev created namespace/prod created namespace/test created role.rbac.authorization.k8s.io/dev-ro created clusterrole.rbac.authorization.k8s.io/all-rw created clusterrolebinding.rbac.authorization.k8s.io/owner-binding created rolebinding.rbac.authorization.k8s.io/auditor-binding created

내 진행 상황 확인하기를 클릭하여 목표를 확인합니다. RBAC 규칙 만들기

소유자로 리소스 관리

  1. 터미널 창 상단의 +를 클릭하여 새 Cloud Shell 터미널을 엽니다.

이제 SSH를 통해 소유자 인스턴스에 연결하고 각 네임스페이스에 간단한 배포를 만듭니다.

  1. SSH를 통해 '소유자' 인스턴스에 연결합니다.
gcloud compute ssh gke-tutorial-owner 참고: gcp 인증 플러그인과 관련된 오류는 무시하세요.
  1. 영역에 대한 메시지가 표시되면 n을 입력하여 기본 영역을 사용합니다.

  2. gke-gcloud-auth-plugin을 설치합니다.

sudo apt-get install google-cloud-sdk-gke-gcloud-auth-plugin echo "export USE_GKE_GCLOUD_AUTH_PLUGIN=True" >> ~/.bashrc source ~/.bashrc gcloud container clusters get-credentials rbac-demo-cluster --zone {{{project_0.default_zone|ZONE}}}
  1. dev를 시작으로 각 네임스페이스에 서버를 만듭니다.
kubectl create -n dev -f ./manifests/hello-server.yaml

출력:

service/hello-server created deployment.apps/hello-server created
  1. 그런 다음 prod에 대해 다음을 실행합니다.
kubectl create -n prod -f ./manifests/hello-server.yaml

출력:

service/hello-server created deployment.apps/hello-server created
  1. 그런 다음 test에 대해 다음을 실행합니다.
kubectl create -n test -f ./manifests/hello-server.yaml

출력:

service/hello-server created deployment.apps/hello-server created

내 진행 상황 확인하기를 클릭하여 목표를 확인합니다. 각 네임스페이스에 서버 만들기

소유자로서 모든 포드를 확인할 수도 있습니다.

  • '소유자' 인스턴스에서 다음을 실행하여 모든 네임스페이스의 모든 hello-server 포드를 나열합니다.
kubectl get pods -l app=hello-server --all-namespaces

출력:

NAMESPACE NAME READY STATUS RESTARTS AGE dev hello-server-6c6fd59cc9-h6zg9 1/1 Running 0 6m prod hello-server-6c6fd59cc9-mw2zt 1/1 Running 0 44s test hello-server-6c6fd59cc9-sm6bs 1/1 Running 0 39s

감사자로서 리소스 보기

이제 새 터미널을 열고 SSH를 통해 감사자 인스턴스에 연결하여 모든 네임스페이스를 확인해 보겠습니다.

  1. 터미널 창 상단의 +를 클릭하여 새 Cloud Shell 터미널을 엽니다.

  2. SSH를 통해 '감사자' 인스턴스에 연결합니다.

gcloud compute ssh gke-tutorial-auditor 참고: gcp 인증 플러그인과 관련된 오류는 무시하세요.
  1. 영역에 대한 메시지가 표시되면 n을 입력하여 기본 영역을 사용합니다.

  2. gke-gcloud-auth-plugin을 설치합니다.

sudo apt-get install google-cloud-sdk-gke-gcloud-auth-plugin echo "export USE_GKE_GCLOUD_AUTH_PLUGIN=True" >> ~/.bashrc source ~/.bashrc gcloud container clusters get-credentials rbac-demo-cluster --zone {{{project_0.default_zone|ZONE}}}
  1. '감사자' 인스턴스에서 다음을 실행하여 모든 네임스페이스의 모든 hello-server 포드를 나열합니다.
kubectl get pods -l app=hello-server --all-namespaces

다음과 같은 오류가 표시됩니다.

Error from server (Forbidden): pods is forbidden: User "gke-tutorial-auditor@myproject.iam.gserviceaccount.com" cannot list pods at the cluster scope: Required "container.pods.list" permission

이 오류는 권한이 부족함을 나타냅니다. 감사자 역할은 dev 네임스페이스의 리소스만 볼 수 있도록 제한되어 있으므로 리소스를 볼 때 네임스페이스를 지정해야 합니다.

이제 dev 네임스페이스에서 포드를 확인해 보세요.

  1. '감사자' 인스턴스에서 다음을 실행합니다.
kubectl get pods -l app=hello-server --namespace=dev

출력:

NAME READY STATUS RESTARTS AGE hello-server-6c6fd59cc9-h6zg9 1/1 Running 0 13m
  1. test 네임스페이스에서 포드를 확인해 보세요.
kubectl get pods -l app=hello-server --namespace=test

출력:

Error from server (Forbidden): pods is forbidden: User "gke-tutorial-auditor@myproject.iam.gserviceaccount.com" cannot list pods in the namespace "test": Required "container.pods.list" permission.
  1. prod 네임스페이스에서 포드를 보려고 시도합니다.
kubectl get pods -l app=hello-server --namespace=prod

출력:

Error from server (Forbidden): pods is forbidden: User "gke-tutorial-auditor@myproject.iam.gserviceaccount.com" cannot list pods in the namespace "prod": Required "container.pods.list" permission.

마지막으로 dev 네임스페이스에서 배포를 만들고 삭제해 보면서 감사자에게 읽기 전용 액세스 권한이 있는지 확인합니다.

  1. '감사자' 인스턴스에서 배포 생성을 시도합니다.
kubectl create -n dev -f manifests/hello-server.yaml

출력:

Error from server (Forbidden): error when creating "manifests/hello-server.yaml": services is forbidden: User "gke-tutorial-auditor@myproject.iam.gserviceaccount.com" cannot create services in the namespace "dev": Required "container.services.create" permission. Error from server (Forbidden): error when creating "manifests/hello-server.yaml": deployments.extensions is forbidden: User "gke-tutorial-auditor@myproject.iam.gserviceaccount.com" cannot create deployments.extensions in the namespace "dev": Required "container.deployments.create" permission.
  1. '감사자' 인스턴스에서 배포를 삭제해 보세요.
kubectl delete deployment -n dev -l app=hello-server

출력:

Error from server (Forbidden): deployments.extensions "hello-server" is forbidden: User "gke-tutorial-auditor@myproject.iam.gserviceaccount.com" cannot update deployments.extensions in the namespace "dev": Required "container.deployments.update" permission.

작업 3. 시나리오 2: 클러스터 애플리케이션에 API 권한 할당

이 시나리오에서는 Kubernetes API에 대한 액세스가 필요한 애플리케이션을 배포하고 일반적인 사용 사례를 문제 해결하면서 RBAC 규칙을 구성하는 과정을 살펴봅니다.

샘플 애플리케이션 배포

샘플 애플리케이션은 단일 포드로 실행되며, 주기적으로 API 서버에서 기본 네임스페이스의 모든 포드를 검색한 후 각 포드에 타임스탬프 라벨을 적용합니다.

  1. 첫 번째 Cloud Shell 탭에 있는 관리자 인스턴스에서 pod-labeler 애플리케이션을 배포합니다. 그러면 포드의 역할, ServiceAccount, RoleBinding도 배포됩니다.
kubectl apply -f manifests/pod-labeler.yaml

출력:

role.rbac.authorization.k8s.io/pod-labeler created serviceaccount/pod-labeler created rolebinding.rbac.authorization.k8s.io/pod-labeler created deployment.apps/pod-labeler created

내 진행 상황 확인하기를 클릭하여 목표를 확인합니다. 샘플 애플리케이션 배포

RBAC 잘못된 구성 진단

이제 포드의 상태를 확인합니다. 컨테이너 생성이 완료되면 오류가 표시됩니다. 포드의 이벤트와 로그를 검사하여 오류를 조사합니다.

  1. 관리자 인스턴스에서 포드 상태를 확인합니다.
kubectl get pods -l app=pod-labeler

출력:

NAME READY STATUS RESTARTS AGE pod-labeler-6d9757c488-tk6sp 0/1 Error 1 1m
  1. 관리자 인스턴스에서 다음을 실행하여 포드 이벤트 스트림을 확인합니다.
kubectl describe pod -l app=pod-labeler | tail -n 20

다음과 같이 표시됩니다.

Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 7m35s default-scheduler Successfully assigned default/pod-labeler-5b4bd6cf9-w66jd to gke-rbac-demo-cluster-default-pool-3d348201-x0pk Normal Pulling 7m34s kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk pulling image "gcr.io/pso-examples/pod-labeler:0.1.5" Normal Pulled 6m56s kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk Successfully pulled image "gcr.io/pso-examples/pod-labeler:0.1.5" Normal Created 5m29s (x5 over 6m56s) kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk Created container Normal Pulled 5m29s (x4 over 6m54s) kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk Container image "gcr.io/pso-examples/pod-labeler:0.1.5" already present on machine Normal Started 5m28s (x5 over 6m56s) kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk Started container Warning BackOff 2m25s (x23 over 6m52s) kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk Back-off restarting failed container
  1. 관리자 인스턴스에서 다음을 실행하여 포드의 로그를 확인합니다.
kubectl logs -l app=pod-labeler

출력:

Attempting to list pods Traceback (most recent call last): File "label_pods.py", line 13, in ret = v1.list_namespaced_pod("default",watch=False) File "build/bdist.linux-x86_64/egg/kubernetes/client/apis/core_v1_api.py", line 12310, in list_namespaced_pod File "build/bdist.linux-x86_64/egg/kubernetes/client/apis/core_v1_api.py", line 12413, in list_namespaced_pod_with_http_info File "build/bdist.linux-x86_64/egg/kubernetes/client/api_client.py", line 321, in call_api File "build/bdist.linux-x86_64/egg/kubernetes/client/api_client.py", line 155, in __call_api File "build/bdist.linux-x86_64/egg/kubernetes/client/api_client.py", line 342, in request File "build/bdist.linux-x86_64/egg/kubernetes/client/rest.py", line 231, in GET File "build/bdist.linux-x86_64/egg/kubernetes/client/rest.py", line 222, in request kubernetes.client.rest.ApiException: (403) Reason: Forbidden HTTP response headers: HTTPHeaderDict({'Date': 'Fri, 25 May 2018 15:33:15 GMT', 'Audit-Id': 'ae2a0d7c-2ab0-4f1f-bd0f-24107d3c144e', 'Content-Length': '307', 'Content-Type': 'application/json', 'X-Content-Type-Options': 'nosniff'}) HTTP response body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"pods is forbidden: User \"system:serviceaccount:default:default\" cannot list pods in the namespace \"default\": Unknown user \"system:serviceaccount:default:default\"","reason":"Forbidden","details":{"kind":"pods"},"code":403}

이 오류에 따라 API를 통해 포드를 나열하려고 할 때 권한 오류가 표시될 수 있습니다.

  1. 다음 단계는 올바른 ServiceAccount를 사용 중인지 확인하는 것입니다.

serviceAccountName 수정

포드의 구성을 검사하면 커스텀 서비스 계정이 아닌 기본 ServiceAccount를 사용 중임을 알 수 있습니다.

  1. 관리자 인스턴스에서 다음을 실행합니다.
kubectl get pod -oyaml -l app=pod-labeler

출력:

restartPolicy: Always schedulerName: default-scheduler securityContext: fsGroup: 9999 runAsGroup: 9999 runAsUser: 9999 serviceAccount: default

pod-labeler-fix-1.yaml 파일에는 배포의 템플릿 사양에 수정사항이 포함되어 있습니다.

# Fix 1, set the serviceAccount so RBAC rules apply serviceAccount: pod-labeler

다음으로 수정사항을 적용하고 결과를 확인합니다.

  1. 관리자 인스턴스에서 다음을 실행하여 수정 1을 적용합니다.
kubectl apply -f manifests/pod-labeler-fix-1.yaml

출력:

role.rbac.authorization.k8s.io/pod-labeler unchanged serviceaccount/pod-labeler unchanged rolebinding.rbac.authorization.k8s.io/pod-labeler unchanged deployment.apps/pod-labeler configured
  1. 배포 구성의 변경사항을 확인합니다.
kubectl get deployment pod-labeler -oyaml

출력의 변경사항:

... restartPolicy: Always schedulerName: default-scheduler securityContext: {} serviceAccount: pod-labeler ...

내 진행 상황 확인하기를 클릭하여 목표를 확인합니다. 서비스 계정 이름 수정

권한 부족 진단

다시 포드의 상태를 확인하면 이번에는 다른 메시지와 함께 여전히 오류가 발생합니다.

  1. 관리자 인스턴스에서 포드 상태를 확인합니다.
kubectl get pods -l app=pod-labeler

출력:

NAME READY STATUS RESTARTS AGE pod-labeler-c7b4fd44d-mr8qh 0/1 CrashLoopBackOff 3 1m

이 출력을 보려면 이전 명령어를 다시 실행해야 할 수 있습니다.

  1. 관리자 인스턴스에서 포드의 로그를 확인합니다.
kubectl logs -l app=pod-labeler

출력:

File "/usr/local/lib/python3.8/site-packages/kubernetes/client/rest.py", line 292, in PATCH return self.request("PATCH", url, File "/usr/local/lib/python3.8/site-packages/kubernetes/client/rest.py", line 231, in request raise ApiException(http_resp=r) kubernetes.client.rest.ApiException: (403) Reason: Forbidden HTTP response headers: HTTPHeaderDict({'Audit-Id': 'f6c67c34-171f-42f3-b1c9-833e00cedd5e', 'Content-Type': 'application/json', 'X-Content-Type-Options': 'nosniff', 'Date': 'Mon, 23 Mar 2020 16:35:18 GMT', 'Content-Length': '358'}) HTTP response body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"pods \"pod-labeler-659c8c99d5-t96pw\" is forbidden: User \"system:serviceaccount:default:pod-labeler\" cannot patch resource \"pods\" in API group \"\" in the namespace \"default\"","reason":"Forbidden","details":{"name":"pod-labeler-659c8c99d5-t96pw","kind":"pods"},"code":403}

PATCH 작업에서 실패하므로 Stackdriver에서도 해당 오류를 확인할 수 있습니다. 이는 애플리케이션 로그가 충분히 상세하지 않은 경우에 유용합니다.

  1. 콘솔에서 탐색 메뉴를 선택하고 작업 섹션에서 로깅을 클릭합니다.

  2. 쿼리 빌더 대화상자에서 다음 코드를 붙여넣고 쿼리 실행을 클릭합니다.

protoPayload.methodName="io.k8s.core.v1.pods.patch"
  1. 로그 기록 옆에 있는 아래쪽 화살표를 클릭하여 세부정보를 살펴봅니다.

애플리케이션의 역할 및 권한 식별

ClusterRoleBinding을 사용하여 ServiceAccount의 역할과 권한을 찾습니다.

  1. 관리자 인스턴스에서 rolebinding 정의를 검사합니다.
kubectl get rolebinding pod-labeler -oyaml

출력:

apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"rbac.authorization.k8s.io/v1","kind":"RoleBinding","metadata":{"annotations":{},"name":"pod-labeler","namespace":"default"},"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"Role","name":"pod-labeler"},"subjects":[{"kind":"ServiceAccount","name":"pod-labeler"}]} creationTimestamp: "2020-03-23T16:29:05Z" name: pod-labeler namespace: default resourceVersion: "2886" selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/default/rolebindings/pod-labeler uid: 0e4d5be7-d986-40d0-af1d-a660f9aa4336 roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: pod-labeler subjects: - kind: ServiceAccount name: pod-labeler

RoleBinding은 기본 네임스페이스에서 pod-labeler 역할을 검사해야 함을 보여줍니다. 여기서 볼 수 있듯이, 이 역할에는 포드 목록을 작성할 수 있는 권한만 부여됩니다.

  1. 관리자 인스턴스에서 pod-labeler 역할 정의를 검사합니다.
kubectl get role pod-labeler -oyaml

출력:

apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"rbac.authorization.k8s.io/v1","kind":"Role","metadata":{"annotations":{},"name":"pod-labeler","namespace":"default"},"rules":[{"apiGroups":[""],"resources":["pods"],"verbs":["list"]}]} creationTimestamp: "2020-03-23T16:29:05Z" name: pod-labeler namespace: default resourceVersion: "2883" selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/default/roles/pod-labeler uid: c8191869-c7de-42c6-98fc-79a91d9b02a1 rules: - apiGroups: - "" resources: - pods verbs: - list

애플리케이션에 PATCH 권한이 필요하므로 지금 수행할 작업은 해당 권한을 역할의 'verbs' 목록에 추가하는 것입니다.

pod-labeler-fix-2.yaml 파일의 rules/verbs 섹션에는 수정사항이 포함되어 있습니다.

rules: - apiGroups: [""] # "" refers to the core API group resources: ["pods"] verbs: ["list","patch"] # Fix 2: adding permission to patch (update) pods

수정사항을 적용하고 결과 구성을 확인합니다.

  1. 관리자 인스턴스에서 fix-2를 적용합니다.
kubectl apply -f manifests/pod-labeler-fix-2.yaml

출력:

role.rbac.authorization.k8s.io/pod-labeler configured serviceaccount/pod-labeler unchanged rolebinding.rbac.authorization.k8s.io/pod-labeler unchanged deployment.apps/pod-labeler unchanged

내 진행 상황 확인하기를 클릭하여 목표를 확인합니다. 애플리케이션의 역할 및 권한 식별

  1. 관리자 인스턴스에서 변경사항을 확인합니다.
kubectl get role pod-labeler -oyaml

출력:

apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"rbac.authorization.k8s.io/v1","kind":"Role","metadata":{"annotations":{},"name":"pod-labeler","namespace":"default"},"rules":[{"apiGroups":[""],"resources":["pods"],"verbs":["list","patch"]}]} creationTimestamp: "2020-03-23T16:29:05Z" name: pod-labeler namespace: default resourceVersion: "8802" selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/default/roles/pod-labeler uid: c8191869-c7de-42c6-98fc-79a91d9b02a1 rules: - apiGroups: - "" resources: - pods verbs: - list - patch

pod-labeler가 백오프 루프에 있을 수 있으므로 수정사항을 테스트하는 가장 빠른 방법은 기존 포드를 강제 종료하고 새 포드가 이를 대체하도록 하는 것입니다.

  1. 관리자 인스턴스에서 다음을 실행하여 기존 포드를 종료하고 배포 컨트롤러가 이를 대체하도록 합니다.
kubectl delete pod -l app=pod-labeler

출력:

pod 'pod-labeler-659c8c99d5-t96pw' deleted

구성 성공 확인

마지막으로 새 pod-labeler가 실행 중인지 확인하고 'updated' 라벨이 적용되었는지 확인합니다.

  1. 관리자 인스턴스에서 모든 포드를 나열하고 라벨을 표시합니다.
kubectl get pods --show-labels

출력:

NAME READY STATUS RESTARTS NAME READY STATUS RESTARTS AGE LABELS pod-labeler-659c8c99d5-5qsmw 1/1 Running 0 31s app=pod-labeler,pod-template-hash=659c8c99d5,updated=1584982487.6428008
  1. 포드의 로그를 확인하여 더 이상 오류가 없는지 확인합니다.
kubectl logs -l app=pod-labeler

출력:

Attempting to list pods labeling pod pod-labeler-659c8c99d5-5qsmw labeling pod pod-labeler-659c8c99d5-t96pw ...

핵심 내용

  • 컨테이너 및 API 서버 로그는 RBAC 문제를 진단하는 데 가장 유용한 단서가 됩니다.
  • RoleBinding 또는 ClusterRoleBinding을 사용하여 포드의 권한을 지정하는 역할을 확인합니다.
  • API 서버 로그는 Kubernetes 리소스 아래의 Stackdriver에서 확인할 수 있습니다.
  • 모든 API 호출이 Stackdriver에 로깅되는 것은 아닙니다. Kubernetes Engine에서 사용되는 Kubernetes 감사 정책에 따라 빈번하거나 상세한 페이로드가 생략됩니다. 정확한 정책은 Kubernetes 버전에 따라 다르지만 오픈소스 코드베이스에서 확인할 수 있습니다.

수고하셨습니다

사용자 페르소나에 다양한 권한을 할당하고 클러스터에서 실행되는 애플리케이션에 제한된 API 액세스를 부여하여 역할 기반 액세스(RBAC) 제어에 대해 살펴봤습니다.

다음 단계/더 학습하기

Google Cloud 교육 및 자격증

Google Cloud 기술을 최대한 활용하는 데 도움이 됩니다. Google 강의에는 빠른 습득과 지속적인 학습을 지원하는 기술적인 지식과 권장사항이 포함되어 있습니다. 기초에서 고급까지 수준별 학습을 제공하며 바쁜 일정에 알맞은 주문형, 실시간, 가상 옵션이 포함되어 있습니다. 인증은 Google Cloud 기술에 대한 역량과 전문성을 검증하고 입증하는 데 도움이 됩니다.

설명서 최종 업데이트: 2025년 2월 24일

실습 최종 테스트: 2025년 2월 24일

Copyright 2026 Google LLC. 이 소프트웨어는 사용 또는 목적에 대한 보증이나 진술 없이 있는 그대로 제공됩니다. 이 소프트웨어를 사용하는 경우 Google과의 계약이 적용됩니다.

시작하기 전에

  1. 실습에서는 정해진 기간 동안 Google Cloud 프로젝트와 리소스를 만듭니다.
  2. 실습에는 시간 제한이 있으며 일시중지 기능이 없습니다. 실습을 종료하면 처음부터 다시 시작해야 합니다.
  3. 화면 왼쪽 상단에서 실습 시작을 클릭하여 시작합니다.

시크릿 브라우징 사용

  1. 실습에 입력한 사용자 이름비밀번호를 복사합니다.
  2. 비공개 모드에서 콘솔 열기를 클릭합니다.

콘솔에 로그인

    실습 사용자 인증 정보를 사용하여
  1. 로그인합니다. 다른 사용자 인증 정보를 사용하면 오류가 발생하거나 요금이 부과될 수 있습니다.
  2. 약관에 동의하고 리소스 복구 페이지를 건너뜁니다.
  3. 실습을 완료했거나 다시 시작하려고 하는 경우가 아니면 실습 종료를 클릭하지 마세요. 이 버튼을 클릭하면 작업 내용이 지워지고 프로젝트가 삭제됩니다.

현재 이 콘텐츠를 이용할 수 없습니다

이용할 수 있게 되면 이메일로 알려드리겠습니다.

감사합니다

이용할 수 있게 되면 이메일로 알려드리겠습니다.

한 번에 실습 1개만 가능

모든 기존 실습을 종료하고 이 실습을 시작할지 확인하세요.

시크릿 브라우징을 사용하여 실습 실행하기

이 실습을 실행하려면 시크릿 모드 또는 시크릿 브라우저 창을 사용하세요. 개인 계정과 학생 계정 간의 충돌로 개인 계정에 추가 요금이 발생하는 일을 방지해 줍니다.