kubernetes CKA study (21) - Cluster Roles and Role Bindings, Service Accounts, Image Security

이동명·2023년 12월 29일
0

kubernetes CKA study

목록 보기
21/37
post-thumbnail
post-custom-banner

Cluster Roles and Role Bindings

Role과 RoleBinding은 네임스페이스 내에 생성된다. 네임스페이스를 지정하지 않으면 default 네임스페이스에서 생성되고 그 네임스페이스 안에서만 접근을 제어할 수 있다.

노드는 네임스페이스에 의해 그룹화, 격리될 수 없다. 노드는 클러스터 와이드 범위에 해당하는 리소스이다.
그래서 리소스는 Namespace나 Cluster Scope에 의해 분류된다.
Cluster Scope의 리소스는 생성 시 네임스페이스를 지정하지 않는다.

네임스페이스 리소스 목록을 보려면 kubectl api-resources --namespaced=true 명령어를 실행하면 된다.
비네임스페이스 리소스 목록을 보려면 kubectl api-resources --namespaced=false 명령어를 실행하면 된다.

네임스페이스 리소스의 경우, Authorization을 위해 role과 rolebinding을 사용했다.

비네임스페이스 리소스의 경우, Authrization을 위해 clusterrole과 clusterrolebinding을 사용한다.

clusterrole은 resource의 범위가 cluster scope인 것만 제외하면 role과 유사하다.
clusterrole 정의 파일을 생성하고 rules 영역에 apiGroups, resources, verbs 필드를 지정하면 된다.

clusterrolebinding 개체는 사용자와 cluster role을 연결한다.
subjects 영역에 사용자 세부 정보를 지정한다. roleRef 영역에는 cluster role에 대해 지정한다.

cluserrole과 clusterrolebinding은 cluster scope의 리소스에 사용된다고 했지만 namespace 리소스에도 적용할 수 있다.
그렇게 하면 사용자는 모든 네임스페이스의 리소스에 접근하게 된다.
쿠버네티스는 클러스터가 처음 설정되면 기본값으로 clusterrole을 여러 개 만든다.


테스트 문제 정리

How many ClusterRoles do you see defined in the cluster?

kubectl get clusterrole --no-headers | wc -l

How many ClusterRoleBindings exist on the cluster?

kubectl get clusterrolebindings.rbac.authorization.k8s.io --no-headers | wc -l

A new user michelle joined the team. She will be focusing on the nodes in the cluster. Create the required ClusterRoles and ClusterRoleBindings so she gets access to the nodes. (ClusterRole 및 ClusterRoleBinding을 생성)

---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: node-admin
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "watch", "list", "create", "delete"]

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: michelle-binding
subjects:
- kind: User
  name: michelle
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: node-admin
  apiGroup: rbac.authorization.k8s.io

michelle's responsibilities are growing and now she will be responsible for storage as well. Create the required ClusterRoles and ClusterRoleBindings to allow her access to Storage. (스토리지에 대한 액세스를 허용하는 데 필요한 ClusterRole 및 ClusterRoleBinding을 생성)

---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: storage-admin
rules:
- apiGroups: [""]
  resources: ["persistentvolumes"]
  verbs: ["get", "watch", "list", "create", "delete"]
- apiGroups: ["storage.k8s.io"]
  resources: ["storageclasses"]
  verbs: ["get", "watch", "list", "create", "delete"]

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: michelle-storage-admin
subjects:
- kind: User
  name: michelle
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: storage-admin
  apiGroup: rbac.authorization.k8s.io

명령적인 방법을 사용해서 clusterrole과 clusterrolebinding 개체를 생성하는 방법도 있다.

테스트 통과 완료


Service Accounts

Service Account의 개념은 쿠버네티스의 다른 보안 관련 개념과 연결되어 있다.

쿠버네티스 계정에는 두 가지 유형이 있다.
사용자 계정은 사람이 사용하고 서비스 계정은 컴퓨터가 사용한다.

사용자 계정의 예시) 관리 작업을 수행하기 위해 클러스터에 접근하는 Admin이 될 수 있고 응용 프로그램 배포 등을 위해 개발자가 클러스터에 접근하는 Developer가 있다.

서비스 계정의 예시) 프로메테우스 같은 모니터링 어플리케이션을 통해 쿠버네티스 API의 성능을 뽑아내는 Prometheus, 젠킨스 같은 자동화된 빌드 툴을 이용해 쿠버네티스 클러스터에 응용 프로그램을 배포하는 Jenkins

응용 프로그램이 쿠버네티스 API를 쿼리하려면 인증이 되어야 한다. 그래서 서비스 계정을 사용한다.
서비스 계정을 생성하고 조회하는 명령어는 다음과 같다.
서비스 계정이 생성되면 토큰도 자동으로 생성된다. 서비스 계정 토큰은 쿠버네티스 API에 인증하는 동안 외부 앱이 반드시 사용해야 하는 것이다.

자동으로 생성된 토큰은 Secret 객체로 저장된다. Service Account가 생성되면 먼저 Service Account개체를 생성하고 그 다음 Service Account를 위한 토큰을 생성한다. 그런 다음 Secret을 만들어 그 안에 토큰을 저장한다.

쿠버네티스 API에 대한 인증이 필요한 타사 응용 프로그램의 경우, 타사 응용 프로그램을 호스팅하는 파드 내부에 Service Account의 Secret 토큰을 볼륨으로 자동 마운트함으로써 해결할 수 있다.

쿠버네티스의 모든 네임스페이스에는 default라고 명명된 Service Account가 자동으로 생성된다.
따라서, 각 네임스페이스에는 자동으로 생성된 default Service Account가 있고 파드가 생성될 때마다 default Service Account과 토큰이 자동으로 해당 파드로 볼륨 마운트된다.

파드 정의 파일을 확인해보면 어떠한 Secret이나 볼륨 마운트를 명시하지 않았다.
하지만 kubectl describe 명령어로 파드의 상세 사항을 살펴보면 default-token이라는 Secret으로부터 볼륨이 자동으로 생성되었음을 확인할 수 있다. 그리고 default-token Secret은 Service Account를 위한 토큰을 포함하는 Secret이다.

default-token Secret의 위치가 '/var/run/secrets/kubernetes.io/serviceaccount'인 것을 확인할 수 있다. 파드 내부에서 ls 명령을 실행해서 해당 디렉토리에 존재하는 3개의 파일로 마운트된 secret을 확인할 수 있다. 실제 토큰 정보를 가지고 있는 것은 token이라는 파일이다. 해당 파일 내용을 보면 kubernetes API 접근에 사용되는 토큰을 확인할 수 있다.

default Service Account는 기본 쿠버네티스 API 쿼리를 실행하는 권한만 갖도록 제한된다.
다른 Service Account를 사용하고 싶다면 파드 정의 파일을 수정해서 serviceAccountName 필드가 새로운 Service Account의 이름을 참조하도록 해야한다.

기존 파드의 Service Account는 수정할 수 없기 때문에 파드를 삭제하고 다시 만들어야 한다.
하지만 deployment의 경우, 파드 정의 파일에 변화가 생기면 자동으로 deployment를 위해 rollout하기 때문에 새로운 Service Account으로 새 파드를 삭제하고 재생성한다.

쿠버네티스에서 아무것도 명시하지 않으면 자동으로 default Service Account를 마운트한다는 것을 명심해라!!

automountServiceAccountToken 필드를 false로 설정하면 Service Account를 자동으로 마운트하지 않는다.

릴리즈버전 1.22, 1.24에서 Service Account와 관련해 변경된 사항들을 확인해보자!

모든 네임스페이스에는 default Service Account이 있고 그 Service Account에는 관련된 token이 있는 Secret이 있다. 파드가 생성되면 자동으로 Service Account와 파드를 연결하고 파드 내 잘 알려진 위치로 토큰을 마운트한다.
이 경우엔 'var/run/secrets/kubernetes.io/serviceaccount'이다.


토큰을 jwt 웹사이트에서 해독해볼 수 있다.

해독해봤듯이 토큰에 만료일자가 없다. 그래서 서비스 계정이 존재하는 한 토큰은 유효하다.
더구나 각 JWT는 서비스 당 개별 Secret 개체를 요구한다. 그 결과 확장성 문제가 발생한다.
버전1.22에서 TokenRequestAPI는 쿠버네티스 개선 제안서1205의 일부로 API를 통해 더 안전하고 확장성 있게 쿠버네티스 서비스 계정 토큰을 프로비저닝하는 메커니즘을 도입했다.

TokenRequestAPI에서 생성된 토큰은 Audience Bound, Time Bound, Object Bound로 인해 더 안전하다.

버전 1.22 이후로 새로운 파드가 생성되면 더 이상 Service Account의 Secret token에 의존하지 않는다.
대신 TokenRequestAPI를 통해 정해진 만료일자를 가진 토큰이 생성되고 파드에 volume으로 탑재된다.

버전 1.24에서는 더 이상 자동으로 Secret이나 Secret Token이 생성되지 않도록 변경되었다.
따라서, kubectl create 명령어로 필요한 토큰을 생성해야 한다. 이때, 서비스 계정 이름을 입력해 필요한 서비스 계정을 위한 토큰을 생성하도록 해야 한다.

생성한 토큰을 해독해보면 시간 'exp' 만료 날짜가 정의되어 있다. 시간 제한을 명시하지 않았다면 보통 1시간으로 제한한다. 명령에 추가 옵션을 전달해 토큰의 만료 기간을 늘릴 수도 있다.

버전 1.24에서 옛날 방식으로 Secret token을 이용한 service account를 만들고 싶다면 Secret 정의 파일을 통해 만들 수 있다. kind 필드를 'kubernetes.io/service-account-token'으로 지정해야 한다. 그리고 metadata 영역에 kubernetes.io/service-account.name 필드에 service account의 이름을 명시해야 한다.
서비스 계정을 먼저 생성하고 그 다음에 Secret을 생성하기 때문에 secret 개체가 특정 service account와 연결되는 것이다.
그래서 service-account-token 타입으로 secret을 만들면 service account와 관련된 secret 개체에 만료되지 않는 토큰을 생성할 것이다.

공식 문서에 명시된 Service account token Secrets에 대한 내용은 다음과 같다.


테스트 문제 기록

What type of account does the Dashboard application use to query the Kubernetes API?

kubectl describe pod web-dashboard-97c9c59f6-zqs49

At what location is the ServiceAccount credentials available within the pod? (포드 내에서 ServiceAccount 자격 증명을 사용할 수 있는 위치)

kubectl describe pod web-dashboard-97c9c59f6-zqs49

The application needs a ServiceAccount with the Right permissions to be created to authenticate to Kubernetes. The default ServiceAccount has limited access. Create a new ServiceAccount named dashboard-sa. (Dashboard-sa라는 새 ServiceAccount를 만들기)

kubectl create serviceaccount dashboard-sa

You shouldn't have to copy and paste the token each time. The Dashboard application is programmed to read token from the secret mount location. However currently, the default service account is mounted. Update the deployment to use the newly created ServiceAccount ( pod의 service account 변경하기)

kubectl set serviceaccount deploy/web-dashboard dashboard-sa


테스트 통과 완료


Image Security

파드 정의 파일에서 컨테이너 이미지 이름은 Docker의 이미지 명명 규칙을 따른 것이다.
nginx는 이미지 혹은 저장소 이름이다.
이미지 이름의 앞 부분은 사용자 또는 계정 이름이다. 그래서 사용자나 계정 이름을 제공하지 않으면 library라고 인식한다. library는 docker의 공식 이미지가 저장된는 기본 계정의 이름이다.

사용자 이름의 앞 부분은 레지스트리 이름이다. 레지스트리 이름이 지정되지 않았다면 Docker의 기본값 레지스트리인 Docker Hub로 추정된다.
Docker Hub의 DNS 이름은 docker.io이다.

레지스트리는 모든 이미지를 저장하는 곳이다.
새 이미지를 생성하거나 이미지를 업데이트할 때마다 레지스트리에 푸시(push)하면 누군가 이 응용 프로그램을 배포할 때마다 레지스트리에서 끌어온다(pull).

Docker hub 이 외에도 구글의 gcr 등 유명한 레지스트리들이 많다.

일반인에게 공개되어서는 안되는 응용 프로그램이 있을 경우 private registry를 사용하면 된다.
private registry에 접근하기 위해서는 자격 증명이 필요하다.

파드 정의 파일에서 개인 레지스트리에 있는 이미지를 사용할 수 있다.
이런 경우, 개인 레지스트리에 접근하기 위한 자격 증명을 포함하는 Secret 개체를 생성하고 파드 정의 파일에서 imagePullSecrets 필드로 Secret 개체를 참조하게 함으로써 인증과정을 해결할 수 있다.


테스트 문제 기록

Create a secret object with the credentials required to access the registry. ( pricate registry 접근을 위한 secret 개체 생성)

kubectl create secret docker-registry private-reg-cred --docker-username=dock_user --docker-password=dock_password --docker-server=myprivateregistry.com:5000 --docker-email=dock_user@myprivateregistry.com

Configure the deployment to use credentials from the new secret to pull images from the private registry ( 방금 만든 secret 객체 참조 사용 )

테스트 통과 완료


profile
Web Developer
post-custom-banner

0개의 댓글