보안
서비스 어카운트
사용자 어카운트(UserAccount): EKS에서는 IAM과 연결되어 있어 쿠버네티스 관리 대상이 아니고, 네임스페이스의 영향을 받지 않음
서비스 어카운트(ServiceAccount): 쿠버네티스에서만 사용, 파드에서 실행되는 프로세스를 위해 할당. 네임스페이스와 연결된 리소스
파드 기동 시 반드시 서비스 어카운트 한 개를 할당해야 하며, 서비스 어카운트 기반 인증/인가를 하고 있음
지정하지 않을 시 기본 서비스 어카운트가 할당
서비스 어카운트 생성
1
2
## 서비스 어카운트 생성
$ kubectl create serviceaccount sample-serviceaccount
인증이 필요한 개인 저장소에 저장된 이미지를 가져오기 위해 시크릿인 imagePullSecrets를 설정하는 경우 kubectl patch 명령어를 사용하거나 생성할 때 매니페스트를 사용하여 서비스 어카운트 생성
1
2
3
## 생성 후 kubectl patch 명령어로 적용
$ kubectl patch serviceaccount sample-serviceaccount \
-p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'
서비스 어카운트와 토큰
생성할 때는 지정하지 않은 시크릿 항목이 존재
kubernetes.io/service-account-token 타입의 시크릿으로 자동 생성
토큰을 변경하고 싶을 떄는 해당 시크릿을 삭제하면 자동으로 재생성됨
1
2
3
4
5
## 서비스 어카운트 정보 확인
$ kubectl get serviceaccounts sample-serviceaccount -o yaml
## 연결된 시크릿
$ kubectl get secrets sample-serviceaccount-token-nmmb9 -o yaml
서비스 어카운트는 이 토큰으로 쿠버네티스 API에 대한 인증 정보로 사용가능
파드에 할당된 서비스 어카운트의 할당된 권한이 그대로 파드에 할당되는 권한이 됨
파드의 서비스 어카운트를 명시적으로 지정하려면 spec.serviceAccountName 지정
서비스 어카운트를 지정한 컨테이너를 생성 후 기동된 파드 정보를 확인하면 토큰이 볼륨으로 자동으로 포함되어 있는 것을 알 수 있음
1
2
3
4
5
## 토큰이 볼륨으로 마운트 된 것을 확인
$ kubectl get pods sample-serviceaccount-pod -o yaml
## API 서버 인증에 사용되는 토큰과 인증서 등의 파일 확인
$ kubectl exec -it sample-serviceaccount-pod -- ls /var/run/secrets/kubernetes.io/serviceaccount/
서비스 어카운트에 적절한 RBAC 설정을 한 후 컨테이너에서 다음과 같이 실행하면 API 접근을 위한 인증/인가가 성공하고 기본 네임스페이스로 동작하고 있는 파드 목록 확인 가능
1
2
3
4
5
6
7
8
9
10
11
12
13
## 컨테이너에서 bash 실행
$ kubectl exec -it sample-serviceaccount-pod -- bash
## curl 명령어 설치
root@sample-serviceaccount-pod:/## apt update && apt -y install curl
## 토큰을 환경변수로 정의
root@sample-serviceaccount-pod:/## TOKEN = ` cat /var/run/secrets/kubernetes.io/serviceaccount/token`
## 쿠버네티스 API 서버에서 파드 목록 확인
root@sample-serviceaccount-pod:/## curl -H "Authorization: Bearer ${ TOKEN } " \
--cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
https://kubernetes/api/v1/namespaces/default/pods
토큰 자동 마운트
설정을 비활성화 하려면 automountServiceAccountToken을 false로 설정
해당 서비스 어카운트로 기동하는 파드는 토큰을 볼륨으로 마운트 하지 않음
토큰을 사용할 때는 명시적으로 spec.automountServiceAccountToken을 true로 설정하면 마운트 가능
도커 레지스트리 인증 정보 자동 설정
imagePullSecret이 지정된 서비스 어카운트를 할당한 파드가 기동한 경우 자동으로 파드의 서비스 어카운트을 사용하여 도커 이미지를 가져온다.
1
2
## spec.imagePullSecrets가 자동으로 포함된 것을 확인
$ kubectl get pods sample-sa-pullsecret-pod -o yaml
spec.imagePullSecrets는 서비스 어카운트에 복수로 지정이 가능하므로 자동으로 여러 인증 정보 설정 가능
RBAC(Role Based Access Control)
어떤 조작을 허용하는지를 결정하는 롤을 생성하고 서비스 어카운트 등의 사용자에게 롤을 연결(롤바인딩)하여 권한을 부여
AggregationRule을 사용해 여러 롤을 집약한 롤을 생성하여 관리성을 향상할 수 있음
롤과 롤바인딩에는 네임스페이스 수준의 리소스와 클러스터 수준의 리소스 두 가지 존재
네임스페이스 수준의 리소스: 롤, 롤바인딩
클러스터 수준의 리소스: 클러스터롤, 클러스터롤바인딩
롤과 클러스터롤
네임스페이스 범위의 리소스를 대상으로 인가 설정 가능
클러스터롤의 경우 노드/네임스페이스/영구볼륨과 같은 클러스터 범위의 리소스나 쿠버네티스 API 정보를 가져오는 nonResourceURL에 대한 권한도 설정 가능
주로 apiGroups, resources, verbs 세 가지 지정
apiGroups와 resources로 지정된 리소스에 대해 verbs 권한 인가
롤에 지정할 수 있는 실행 가능한 조작(verbs)
종류
개요
*
모두 처리
create
생성
delete
삭제
get
조회
list
목록 조회
patch
일부 업데이트
update
업데이트
watch
변경 감시
주의 사항
디플로이먼트 리소스에 대해 롤을 기술할 때 여러 apiGroups가 존재
extensions/v1beta1, extensions/v1beta2, apps/v1으로 변경되어 왔음
모든 디플로이먼트 리소스를 대상으로 롤을 생성하는 경우에 주의
deployment 리소스와 deployment/scale 서브 리소스는 개별적으로 지정
deployment/scale이 지정되어 있지 않으면 레플리카 수를 변경하는 스케일 처리 불가
롤 생성
rules는 여러 개 설정 가능
네임스페이스 지정
클러스터롤 생성
rules에 noneResourceURLs 지정 가능
헬스 체크용 엔드포인트나 버전 정보 표시용 엔드포인트의 URL
metadata.namespace 지정 불가
클러스터롤의 Aggregation
여러 클러스터롤의 정의를 읽는 기능
클러스터롤에 정의된 레이블 기반, 집계되는 쪽 클러스터롤에 정의된 롤은 반영되지 않음
1
2
## 집계된 클러스터롤 확인
$ kubectl get clusterroles sample-aggregated-clusterrole -o yaml
나중에 집계되는 측의 클러스터롤을 변경하는 경우에도 집계되는 측의 클러스터롤에 자동으로 반영
쿠버네티스가 생성하는 클러스터롤
클러스터롤명
내용
cluster-admin
모든 리소스 관리 가능
admin
클러스터롤 편집 + 네임스페이스 수준의 RBAC
edit
읽기 쓰기
view
읽기 전용
롤바인딩과 클러스터롤바인딩
roleRef에서 연결하는 롤과 subjects에 연결하는 사용자나 서비스 어카운트 지정
하나의 롤바인딩당 하나의 롤만 가능, subjects에는 여러 사용자나 서비스 어카운트 지정 가능
롤바인딩: 특정 네임스페이스에 롤 또는 클러스터 롤에서 정의된 권한 부여
네임스페이스 새로 생성시 그 네임스페이스에도 같은 롤바인딩 추가해야 함
클러스터롤바인딩: 모든 네임스페이스에 클러스터롤에서 정의한 권한 부여
네임스페이스 새로 생성해도 네임스페이스 간에 같은 권한 부여 가능
롤바인딩 생성
사용자에 대해 특정 네임스페이스에서 롤 또는 클러스터롤에 정의한 권한 부여
클러스터롤바인딩 생성
사용자에 대해 모든 네임스페이스에서 클러스터롤로 정의된 권한 부여
보안 컨텍스트
설정 가능 항목
종류
개요
privileged
특수 권한을 가진 컨테이너로 실행
capabilities
Capabilities 추가와 삭제
allopPrivilegeEscalation
컨테이너 실행 시 상위 프로세스보다 많은 권한을 부여할지 여부
readOnlyRootFileSystem
root 파일 시스템을 읽기 전용으로 할지 여부
runAsUser
실행 사용자
runAsGroup
실행 그룹
runAsNonRoot
root에서 실행 거부
seLinuxOptions
SELinux 옵션
특수 권한 컨테이너 생성
spec.containers[].securityContext.privileged를 true로 설정
컨테이너 내부에서 기동하는 프로세스의 리눅스 Capabilities가 호스트와 동등한 권한을 가짐
Capabilities 부여
더 세분화된 특정 Capabilities 부여/제거 가능
1
2
## Capabilities 확인
$ kubectl exec -it sample-capabilities -- capsh --print | grep Current
root 파일 시스템의 읽기 전용 설정
컨테이너 이미지에 포함된 파일 등을 읽기 전용으로 설정 가능
root 파일 시스템을 읽기 전용으로 설정하면 커널 관련 파일 등을 변경할 수 없어 보안성 향상
1
2
## 파일 시스템을 읽기 전용으로 마운트
$ kubectl exec -it sample-rootfile-readonly -- touch /etc/os-release
네트워크 정책
클러스터 내부에서 파드 간에 통신할 경우 트래픽 룰을 규정
네트워크 정책을 사용하지 않을 경우 모든 파드는 서로 통신이 가능
네트워크 정책을 사용한다면 네임스페이스별로 트래픽을 전송하지 못하게 하거나 모든 파드 간 통신을 차단하고 특정 파드 간 통신을 허용하는 화이트리스트 방식 사용 가능
네트워크 정책 생성
네트워크 정책은 인그레스(수신)과 이그레스(송신)로 구성
인그레스: 인바운드 방향의 트래픽 룰을 설정
이그레스: 아웃바운드 방향의 트래픽 룰 설정
설정 범위를 podSelector로 지정
네트워크 정책은 네임스페이스별로 생성해야 함
네트워크 정책 종류와 통신 제한 범위
정책 종류
인그레스 룰의 경우
이그레스 룰의 경우
podSelector
특정 파드에서 들어오는 통신 허가
특정 파드로 나가는 통신 허가
namespaceSelector
특정 네임스페이스상에 있는 파드에서 들어오는 통신 허가
특정 네임스페이스상에 있는 파드로 나가는 통신 허가
ipBlock
특정 CIDR(IP 주소)에서 들어오는 통신 허용
특정 CIDR(IP 주소)로 나가는 통신 허용
화이트리스트 방식과 블랙리스트 방식
화이트리스트 방식: 모든 트래픽을 차단해 두고 특정 트래픽만 허가
블랙리스트 방식: 모든 트래픽 허가해 두고 특정 트래픽만 차단
클라우드의 네트워크 기본 설정에서 인바운드는 전체를 차단하고 아웃바운드는 전체를 허용하는 것이 일반적
시크릿 리소스 암호화
시크릿 리소스는 base64로 인코드되어 있을 뿐으로 깃 저장소에 업로드하는 것은 보안상 위험할 수 있음
별도의 암호화 필요
kubesec
오픈 소스 소프트웨어
KMS를 사용해 암호화 가능
파일 전체를 암호화하지 않고 시크릿 구조를 유지한 채 값만 암호화하므로 가독성 높음
시크릿 매니페스트를 암호화하기 때문에 깃 저장소에도 업로드 가능
SealedSecret
오픈 소스 소프트웨어
암호화된 SealedSecret이라는 커스텀 리소스 생성 후 클러스터에 등록하면 클러스터 내부에서 SealedSecret에서 시크릿 리소스로 변환되는 구조
생성된 SealedSecret 리소스는 암호화되어 있기 때문에 깃 저장소에 배치 가능
ExternalSecret
오픈 소스 소프트웨어
SealedSecret과 유사한 구조
Licensed under CC BY-NC-SA 4.0