본문 바로가기

Develop/DevOps

[MLOps] Kubernetes CKA자격증 공부 - Security

반응형

kube-apiserver는 모든 명령어가 거쳐가는 구역이라서 제일 보안에 신경 써야 하는 부분(?), 또한 모든 유저들의 명령어들은 kube-apiserver에서 허가된 사용자들의 명령어만 수행하게끔 작업

kube apiserver의 보안필요성

1. static password file

특정 유저군들의 아이디, 패스워드를 Csv파일 형식으로 저장해 놓은 다음, kube-apiserver.yaml파일에 해당 Csv파일을 지정해줌

# user-details.csv파일에 유저마다 패스워드 아이디가 적혀있음
--basic-auth-file=user-details.csv

# 위와같이 적용하고, 이후에 특정 팟에 접근을 하려고하면 -u옵션으로 계정정보를 넣어줘야한다
curl -v -k https://localhost:6443/api/v1/pods -u "user1:password123"

2. static token file

static password file과 유사한 방식으로 설정 가능, 다만 비밀번호가 아닌 token이 저장됨.

 

당연히, 위 두가지 방식은 추천하지 않는 방식이다

 

TLS in Kubernetes

강의 영상에서는 openssl로 쿠버네티스에 적용하는 방법을 소개했다

 

- 먼저 인증된 Certificates생성 방법을 소개

# Key generates rsa2048암호화 방식
openssl genrsa -out ca.key 2048

# Certificate Signing Request
openssl req -new -key ca.key -subj "/CN=KUBERNETES-CA" -out ca.csr

# Sign Certificates
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt

 

- 그다음 Admin User의 Certificates 생성방법 소개

# Key generates rsa2048암호화 방식
openssl genrsa -out admin.key 2048

# Certificate Signing Request
openssl req -new -key admin.key -subj "/CN=KUBE-ADMIN" -out admin.csr

# 만일 특정 그룹에 대해서 보여지려면
# openssl req -new -key admin.key -subj "/CN=KUBE-ADMIN/O=system:masters" -out admin.csr

# Sign Certificates
# 주의해야할점은 유저관련 certificates는 이전에 생성한 ca 키로 sign해줘야한다
openssl x509 -req -in admin.csr -CA ca.crt -CAkey ca.key -out admin.crt

- Admin User와 동일하게 Kube-Scheduler, Kube-Controller-Manager, Kube-Proxy에 대해서 생성해준다.

이후 내용은 너무 갑작스럽게 많이 지나쳐서... 다시 복습할 때 정리해야 할 듯

 

특정 crt파일내용을 볼 수 있는 방법(openssl이용)

openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout

문제 1. kube-apiserver의 crt경로는 어떻게 설정되어있는지?

답: cat /etc/kubernetes/manifests/kube-apiservier.yaml을 통해서 확인

 

문제 2. namespace가 kube-system에서 특정 api가 동작하지 않는다. 로그를 어디서 봐야 할까?

답: 로그가 쌓여있는 곳으로 이동해야 한다.

https://kubernetes.io/docs/tasks/debug-application-cluster/debug-cluster/

cat /var/logs/... 문제 원인 쪽으로 이동해서 로그 출력한 거 확인

 

(확실하진 않음) etcd는 독자적인 ca.crt를 갖고 있다

 

Certificates API

특정 유저가 노드에 접근하기 위해 csr를 등록 요청이 올 때

# Jane's Key generates rsa2048암호화 방식 (jane쪽에서 해야함)
openssl genrsa -out jane.key 2048

# Jane's Certificate Signing Request
openssl req -new -key jane.key -subj "/CN=jane" -out jane.csr (jane쪽에서 해야함)

# 위 두개를 다시 서버관리자한테 넘겨줘야함

# read jane.csr by base64
cat jane.csr | base64

jane-csr.yaml

- 밑에 request아래가 "cat jane.csr | base64"로 읽어진 부분을 복붙 한 것

- 이후 kubectl create -f jane-csr.yaml로 jane's csr을 등록

 

쿠버네티스 csr관련 명령어

# 등록된 csr보기
kubectl get csr

# 특정 csr 허가하기
kubectl certificate approve jane

# 특정 csr 정보 보기
kubectl get csr jane -o yaml

KubeConfig

kubeconfig file안에는 세 가지 요소가 포함되어있다.

해당 파일의 역할은 유저군과 클러스터의 key나 certificate file정보 값을 따로 저장해두며, 유저와 클러스터사이 관계를 정의해둠.

  • Clusters - 클러스터 정보 값 저장 (ex. Development, Production, Google...)
  • Users - 사용자 정보값 저장 (ex. Admin, Dev User, Prod User)
  • Contexts - 클러스터와 사용자를 이어주는 정보 값을 저장 (ex. Admin은 Production클러스터를 사용함)

KubeConfig YAML File 예시

# config 관련 세팅을 보려면 다음과같은 명령어 실행
kubectl config view

# current-context 바꾸는법
kubectl config use-context [context 대상]

1. kind - clusters 정보값 사이에 사용하는 Context를 정의한다

- current-context: my-kube-admin@my-kube-playground

 

2. 특정 namespace에서 사용하고 싶다면 contexts의 context아래에 namespace를 정의해준다

(그냥 기록용) 특정 문자열을 base64로 디코드 하고 싶다면 echo "LS0...bnJ" | base64 --decode

 

3. 특정 KubeConfig파일을 시스템에 적용하려면

# my-kube-config파일에 current-context값 저장
kubectl config --kubeconfig=/root/my-kube-config current-context

# 현재 설정된 context 확인
kubectl --kubeconfig=/root/my-kube-config current-context

4. default KubeConfig파일 적용방법(두 가지 방법)

# 1. KUBECONFIG 환경변수를 내가 만든 config파일 경로로 설정
export KUBECONFIG=/root/.kube/config

# 2. 또는 .kube폴더 아래에있는 Config파일을 내껄로 변경

Authorization

Authorization(권한)은 쿠버네티스에서 왜 필요할까? 특정 유저군에게는 특정 명령어가 듣지 않게끔 필요할 때가 있다. 예를 들어 새로 입사한 개발자한테 delete권한을 주기에는 좀 부담이 될 수도 있다, 자칫하면 다 날릴 수도 있으니... 이럴 때 Authorization을 설정하여 신규 입사자들은 delete명령어를 못쓰게끔 막을 수가 있다.

 

권한을 주는 방식은 여러 개 있지만, 강의에서는 두가지를 설명

1. ABAC - Attribute Based Access Controls

유저 개개인한테 권한을 부여하는 방식. 하지만, 이방법은 새로운 유저가 들어올때마다 권한정보를 업데이트를 시켜줘야해서 불편한점이 있다. 또한, 특정 권한에 따라서 사용하는 명령어들이 업데이트될때마다, 모든 유저들을 하나하나씩 찾아서 업데이트를 해줘야하는 불편함이있다.

2. RBAC - Role Based Access Controls

유저 개개인이 아닌 룰에 따라서 유저들이 포함되는 방식. ABAC에서 말한 단점들이 보완이된다.

이외에도 AlwaysAllow, NODE, WEBHOOK, AlwaysDeny이 있다.

 

RBAC(ClusterRole도 매우 유사하다)에 대해서는 YAML파일로 설정하여 적용할수있다.

(developer-role.yaml파일)rule구조체 안에 어떤 리소스에 어떤 명령어를 사용할수있는지 설정할수있다. 

만약에 특정 pod에 등록하는거라면 rules 구조체 아래 매 list마다 roleResources에 해당 Pod 이름을 넣어줘야한다

위와같이 Role에 대해서 설정을 했다면, 아래와 같이 시스템에 적용 할 수 있게끔 바인딩작업도 진행해줘야한다.

만약에 특정 Namespace에 등록하는거라면 metadata아래에 지정해줘야한다.

# role정보를 보려면
kubectl get roles

# role binding 정보를 보려면
kubectl get rolebindings

# 특정 Role의 상세 정보를 보고싶다면
kubectl describe role developer

# 특정 명령어를 실행 할 수 있는지 여부 확인 (Return은 yes, no로만 나옴)
kubectl auth can-i create deployments
kubectl auth can-i delete nodes

# 특정 role이 특정 명령어를 실행 할 수 있는지 여부 확인
## as 뒤에 role기입
kubectl auth can-i create deployments --as dev-user

# 특정 Namespace에서 특정 role이 특정 명령어를 실행 할 수 있는지 여부 확인
## as 뒤에 role기입
kubectl auth can-i create deployments --as dev-user --namespace dev

(기록용) terminal에서 출력되는 row수를 세고싶을때

# pod의 개수를 알고싶을때 결과물에서 -1해줘야함. 제일 첫번째는 설명문이기 때문
kubectl get pods | wc -l

ClusterRole

위에서 얘기한 Role같은 경우에는 Nodes, PV, Namespaces등등 클러스터에 관련된 리소스에 권한을 부여하지는 못한다. 따라서 클러스터에 대한 Role생성을 하고싶을땐, Role과 유사하지만 Type을 ClusterRole로 지정하여 생성한다. 또한, 이전에 보여준 Role형태처럼 똑같이 바인딩도 시켜줘야한다. 바인딩의 Type은 ClusterRoleBinding으로 설정하여 생성하면된다.

Service Account

앞서 설정한 보안은 "유저"들한테 초점이 맞춰졌다면, 이번에는 "서비스"에 초점을 맞춰서 권한을 지정한다.

- 서비스: 외부 솔루션(ex. Prometheus, Jenkins ...)

# service account 생성
kubectl create serviceaccount dashboard-sa

# service account 리스트 확인
kubectl get serviceaccount

# service account 정보 수집
kubectl describe serviceaccount dashboard-sa

 

특정 Pod(service account가 생성되기전 pod)에 Service Account정보를 넣고싶다면 다음과 같이 작업.

- 주의해야할건 pod에 바로 수정을 하는것으로는 안되고 꼭 pod을 삭제하고 다시 띄워줘야 적용된다고한다.

이해를 제대로 했는지 모르겠지만, service account가 생성되면 이후에 생성되는 pod에 자동으로 service account정보가 적용된다고한다. 만일 자동으로 적용되는걸 원치않는다면 spec밑에 "automountServiceAccountToken: false"로 설정하면 된다

 

Image Secret

특정 pod을 만들때 공개된 Image가 아닌 개인공간에서 만든 Image에 대해서 가져오고싶을때는 어떻게 해야할까?

pod을 만들때 image 정보에 개인공간에 따른 Image경로를 넣어주고. docker에 관련된 계정 정보를 Secret를 생성하여 담아준다.

그런다음 Pod YAML파일안에 spec구조체 밑에 "imagePullSecrets"에 secret name을 지정해서 넣어준다



문제 틀린거

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

Context Security

특정 image가 실행되고나서 설정되는 유저를 정의하는 방법

예시. 특정 image가 실행되고 root유저로 실행될것인지, 아니면 지정한 특정 유저로 실행될것인지

 

context security는 spec구조체 아래에 설정되거나, Containers구조체 아래에도 설정이 될수있음.

다만, 우선순위는 containers구조체 아래에있는 지정유저가 높게 설정됨. 즉, spec밑에도 설정하고, containers밑에도 설정했을때, containers밑에있는 유저로 image가 실행됨.

# 특정 팟에서 명령을 수행하는 유저 조회
kubectl exec [pod 이름] -- whoami

Network Policy (중요, 시험에 자주나온다고함)

Ingress와 egress에 대해서 설명

Ingress는 외부로부터 서버 내부로 유입되는 네트워크 트래픽을

egress는 서버 내부에서 외부로 나가는 트래픽을 의미함

 

특정 Pod에서 허용하는 포트로 들어오는 트래픽만 받겠다라는걸 정의하고싶다면 다음과같이 YAML파일을 작성할수있음

  • apiVersion은 networking.k8s.io/v1이며, kind는 NetworkPolicy로 설정한다.
  • podSelector는 위에서 말한것처럼 "특정 Pod"을 지정하기 위함이고,
  • policyTypes은 여러가지가 있지만, 지금 구현해야하는건 내부에서 들어오는 트래픽이니 Ingress로 설정 (여러가지를 동시에 설정 할 수 있음)
  • ingress구조체에서는
    • from으로 "어느 Pod에서 어느 포트로 들어오는지"에 대해서 정의해준다. 추가로 다른 Namespace에서 들어오는건 namespaceSelector로 지정해줄수있다.
    • 만약에 from에서 podSelector가 없을경우에는 모든 pod에 대해서 3306으로 들어오는 트래픽은 다 허용해주겠다라는 의미가 된다

  • egress구조체에서는
    • Ingress와는 반대로 from이 아닌 to 구조체를 사용한다

반응형