← Back to list

[PKOS] 쿠버네티스 실무실습 스터디 7주차 메모

마지막으로 보안에 대해서 다룬다.

Curry Lee · 2023-03-02 15:16 · 1 claps · 10.4 min read
#k8s #pko
Open on Medium ↗
Wiki topics: ☁️ · DevOps & Cloud

[PKOS] 쿠버네티스 실무실습 스터디 7주차 메모

마지막으로 보안에 대해서 다룬다.

실습을 위해서 AWS Python SDK인 Boto3를 사용한다. Boto3가 동작하기 위해서는 필요한 권한을 가지는 자격증명이 필요한데, 다음의 순서로 자격증명을 확인하여 동작한다. (참고)

1. boto3.client, resource, session 함수에 자격증명을 매개 변수로 직접 전달
2. 환경 변수(Environment variables)
3. 공유 자격증명 파일 [ ~/.aws/credentials ]
4. AWS 구성 파일 [ ~/.aws/config ]
5. AssumeRole(임시 자격증명) 호출 [ ~/.aws/config ]
6. Boto2 구성 파일 [ /etc/boto.cfg 또는 ~/.boto ]
7. IAM 역할이 구성된 Amazon EC2 인스턴스의 인스턴스 메타 데이터 서비스

처음에는 7번에 해당되는 EC2의 인스턴스의 권한을 사용하는 방식으로 실습을 하였는데, 이는 해당 인스턴스에서 실행되는 파드들이 모두 권한을 가지게 되어서 세세하게 권한을 제어하는 것이 어렵다. 따라서 이를 해결하기 위하여 AWS IRSA를 사용한다.

AWS IRSA (IAM Roles for Service Accounts)는 kubernetes의 service account를 사용하여 pod의 권한을 IAM Role로 제어할 수 있도록 하는 기능이다. 서비스 계정을 위한 IAM 역할 기능은 Amazon EKS 버전 1.14 이상과 2019년 9월 3일 이후에 버전 1.13 이상으로 업데이트된 EKS 클러스터에서 사용할 수 있다. 용서비스 어카운트(Service Account) 는 Kubernetes 의 파드에서 API 서버에 요청을 보냈을 때 이 “파드”를 식별하기 위한 리소스 입니다. 파드에서 API 서버에 요청을 보내면 이 파드가 무엇인지 알아야 어떤 권한을 가지고 있는지도 알아내어 파드의 요청이 권한에 맞는지를 확인하여 요청을 처리해줄지 말지를 결정할 수 있게된다. 실제로 권한을 정의하고, 설정하는 부분은 Role, ClusterRole, RoleBinding, ClusterRoleBinding의 역할이고, ServiceAccount 는 권한을 적용할 수 있는 주체로서, Pod에게는 인증서 역할을 한다.

**kubescape**는 오픈소스 kubernetes 보안 플랫폼으로 CNCF sandbox 프로젝트이다. 위험 분석, 잘못된 설정 검색 등을 제공하며 cluster, yaml파일, helm chart의 스캔기능을 제공한다. 기본은 CLI로 스캔결과를 보여주나 ARMO 웹사이트에 Scan결과를 업로드하여 Web UI를 통해서 분석할 수 있다. (자세한 것은 아래 실습 참조)

**polaris** (helm)는 Kubernetes용 오픈 소스 정책 엔진으로 Kubernetes 리소스를 검증하고 수정하여 구성 모범 사례를 따르도록 도와주는 도구이다.

  • Live Dashboard: kubescape와 유사하게 취약점을 보여준다.
  • Validating Webhook: kubernetes 동작시에 이를 검사하고 대응을 하는 것이 가능하다. 예를 들어, 배포시 스캔을 하고 취약점이 발견되면 배포를 차단하는 것도 가능
  • IaC Auditor: IaC의 코드들을 검사한다. 예를 들어, git repo의 IaC 코드에 취약점이 있는 경우 PR 머지를 차단하는 것도 가능

대시보드에서 취약점뿐 아니라 수정방법도 알려주어서 쉽게 수정이 가능하다.

Kubernetes의 Admission

Kubernetes의 클라이언트들이 클러스터내에 실행되거나 API 서버에 인증을 받기 위해서 클러스터의 control plane과 relationship을 가지고 위한 2가지 방법을 제공합니다.

‘Service account’는 파드에서 실행되는 프로세스의 ID를 제공하며 ServiceAccount 객체에 매핑됩니다. API 서버에 인증할때 자신을 특정 사용자로 식별합니다. Kubernetes는 사용자 개념을 인식하지만 사실 Kubernetes 자체는 User API란 것을 가지고 있지 않습니다.

서비스 어카운트는 파드에서 실행되는 프로세스를 위한 것이며 네임스페이스에 할당됩니다. 서비스 어카운트는 클러스터 사용자가 최소 권한 원칙에 따라서 특정 작업을 위한 서비스 어카운트를 쉽게 만들 수 있도록 가볍게 만들어졌습니다. 이러한 이유로 서비스 어카운트는 이식성이 좋습니다. 서비스 어카운트는 다음 3가지 개별 요소가 협력하여 동작합니다.

  • ServiceAccount Admission Controller
  • Token Controller
  • ServiceAccount Controller

Kubernetes는 Certification을 사용해서 Authentication, 그리고 RBAC(Role RoleBinding)을 사용해서 Authorization을 모두 제공한다.

가온미르님의 Kubernetes Secrets에 대해서 추가 발표가 있었던 내용 중 일부를 정리합니다.

kubernetes cluster의 etcd와 secret을 보호하기 위해서는 다음 사항을 준수해야 한다.

1. ETCD 클러스터를 위한 별도의 네트워크 세그멘트를 만든다. 클러스터 내부와 외부 간의 통신을 차단한다.
2. ETCD에 대한 액세스를 Kubernetes API 서버로만 허용한다. 다른 서비스나 애플리케이션이 직접 ETCD에 접근하지 않도록 한다.
3. ETCD 데이터의 백업을 수행하고, 백업 파일은 암호화된 스토리지에 저장한다.
4. Secret은 최소 권한으로 제한되어야 한다. 해당 Secret을 사용하는 애플리케이션만 해당 Secret에 접근할 수 있도록 한다.
5. TLS 인증서를 사용하여 ETCD와 API 서버 간의 통신을 보호한다.
6. ETCD에 대한 보안 패치를 지속적으로 적용한다.
7. ETCD의 보안 설정을 최소 권한 원칙에 따라 구성한다.

EncryptionConfiguration 으로 etcd가 어떤 방식으로 암호화를 할지 설정한다.

# /etc/kubernetes/etcd/etcd.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
    - secrets
    providers:    # key1으로 aescbc알고리즘으로 암호화한다.
    - aescbc:
        keys:
        - name: key1
          secret: cGFzc3dvcmRwYXNzd29yZA==
    - identity: {} # 기존의 평문으로 저장된 값도 읽을 수 있다. 이것만 있는 경우 암호화하지 않고 저장함.

SealedSecret 는 개발자가 secret을 암호화해서 git repo에서 넣고 kubernetes에 반영될때에는 kubernetes에서 자동으로 복호화해서 일반적인 secret으로 만든다. 이를 통해서 git repo에서 secret data가 유출되는 것을 막는다.

지금까지 참여해본 스터디 중에서 가장 완벽하게 준비를 해서 세미나를 해주신 스터디장 ‘가시다'님 덕분에 단기간에 혼자서는 도저히 할 수 없는 많은 것을 해볼 수 있었다. 여기에 최근에 개인적으로 본 ‘따라하며 배우는 AWS 네트워크 입문’ 책과 시너지를 내서 AWS와 k8s가 조금은 익숙해진 것 같네요. 혹시라도 추후 PKOS 세미나에 참여해볼 기회가 있다면 도전해볼 것을 추천한다. :-)

Reference

= = = = = = = =

  1. 파드에서 EC2 메타데이터의 IAM Role 토큰 정보를 활용하여(boto3), 스터디에서 소개한 것 이외의 다른 AWS 서비스(혹은 Action)를 사용해보기 이 과제는 AllowExternalDNSUpdates 를 사용해서 route53의 hosted zone 목록을 얻어봤다.
import boto3

route53 = boto3.client('route53')
response = route53.list_hosted_zones()
print(response)

route53.list_hosted_zones() 의 결과

route53.list_hosted_zones() 의 결과

  1. kubescape armo 웹 사용

ARMO 웹사이트의 계정 정보를 kubescape 실행시 넣어주면 스캔 결과가 웹에 업로드되고 Web UI를 통해서 볼 수도 있어서 매우 편하다.

  1. polaris 관련 실습

dashboard

dashboard

initial state of netshoot-pod

initial state of netshoot-pod

after fixing image tag issue

after fixing image tag issue

after fixing replica and memory request/limit issue

after fixing replica and memory request/limit issue

almost perfact. :-)

almost perfact. :-)

Polaris prevented this deployment due to configuration problems

Polaris prevented this deployment due to configuration problems

code audit

code audit

4 . 신규 서비스 어카운트(SA) 생성 후 ‘클러스터 수준(모든 네임스페이스 포함)에서 읽기 전용’의 권한을 주고 테스트

# cluster-role.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: role-cluster-ro-sa
  namespace: sa-test
rules:
- apiGroups: [""]
  resources: ["*"]
  verbs: ["get", "watch", "list"]
# role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: role-binding-cluster-ro-sa
  namespace: sa-test
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: role-cluster-ro-sa
subjects:
- kind: ServiceAccount
  name: cluster-ro-sa
  namespace: sa-test

can-i test

can-i test

run nginx and get pods/nodes

run nginx and get pods/nodes

describe clusterrole and clusterrolebinding

describe clusterrole and clusterrolebinding


메타데이터
post_id
2148fe8aadd
slug
pkos-쿠버네티스-실무실습-스터디-7주차-메모-2148fe8aadd
url
https://medium.com/@recursivecurry/pkos-%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-%EC%8B%A4%EB%AC%B4%EC%8B%A4%EC%8A%B5-%EC%8A%A4%ED%84%B0%EB%94%94-7%EC%A3%BC%EC%B0%A8-%EB%A9%94%EB%AA%A8-2148fe8aadd
canonical_url
https://medium.com/@recursivecurry/pkos-%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-%EC%8B%A4%EB%AC%B4%EC%8B%A4%EC%8A%B5-%EC%8A%A4%ED%84%B0%EB%94%94-7%EC%A3%BC%EC%B0%A8-%EB%A9%94%EB%AA%A8-2148fe8aadd
author_url
https://medium.com/@recursivecurry
status
ok
fetched_at
2026-09-08 12:59:03