Certified Kubernetes Administrator (CKA) with Practice Tests (강의 링크, 레퍼런스 노트)
- 평소 강의 할인도 많이 하고, 연습문제도 풀어볼 수 있으니 실제 강의 수강을 추천
- 아래는 강의 내용 번역 및 정리본 (문제 시 댓글로 알려주세요)
API 그룹
쿠버네티스 API
- 클러스터에서 어떠한 동작을 수행하기 위해서는 API 서버와 통신해야 함
- kubectl 활용해 접근 가능
- REST를 통해 직접 접근 가능
- e.g.
curl https://kube-master:6443/version
- e.g.
curl https://kube-master:6443/api/v1/pods
- 직접 접근 시 --key, --cert, --cacert를 옵션으로 넘겨줌으로써 인증 필요
- 혹은
kubectl proxy 로 8001 포트에 프록시 서비스를 띄우면 kubeconfig를 사용하기 때문에 curl 명령어에 옵션을 넘겨줄 필요가 없음
kube proxy vs. kubectl proxy
- kube proxy
- 다른 노드에 위치한 pod와 service의 연결을 도움
- kubectl proxy
- kube-apiserver에 접근하기 위해 kubectl이 만드는 http 프록시 서비스
쿠버네티스 API 그룹
- 쿠버네티스 API는 목적에 따라 여러 그룹으로 나뉨
- e.g. /metrics, /healthz, /version, /api, /apis, /logs
- api는 핵심(core) 그룹(/api)과 지정(named) 그룹(/apis)으로 나뉨
- 핵심 그룹(/api)
- 핵심 기능들 존재
- e.g. v1 하위에 namespaces, pods, rc, event, nodes, endpoints, secrets, configmaps, services, ...
- 지정 그룹(/apis)
- 새롭게 만들어진 기능들 존재
- e.g. /apps: v1 하위에 /deployments, /replicasets, /statefulsets
- e.g. /networking.k8s.io: v1 하위에 /networkpolicies
- e.g. /certificates.k8s.io: v1 하위에 /certificatesigningrequest
- /apps, /networking.k8s.io 등이 API 그룹
- 그 하위의 /deployments, /networkpolicies 등이 자원(Resource)
- 해당 자원은 수행할 수 있는 동작들과 연계되어 있음 (동사(Verbs))
- e.g. list, get, create, delete, update, watch..
허가 (Authorization)
- 사용자마다 수행할 수 있는 동작이 달라져야 함
- e.g.
kubectl get 은 사용 가능하나 kubectl delete node 는 사용 불가
- 사용자 혹은 조직마다 접근할 수 있는 네임스페이스를 구분할 필요가 있음
허가 메커니즘
- Node
- 클러스터 내부에서의 접근 허가 (kubelet-kubeapi)
- kubelet은 kubeapi로부터 서비스, 엔드포인트, 노드, 파드에 대한 정보를 읽고(read) kubeapi에게 노드 상태, 파드 상태, 이벤트 등에 대한 정보를 작성함(write)
- 이러한 작업을 가능하도록 허가해주는 것이 node authorizer
- kubelet은 인증서에서 system:node:로 이름이 시작해야 하고, system:nodes 그룹에 속해야 함
- ABAC (Attribute-Based Access Control)
- 클러스터 외부에서의 접근 허가 (user-kubeapi)
- 각 사용자 혹은 그룹의 정책에 대한 내용을 json 형태의 파일로 작성
- e.g. {"kind": "Policy", "spec": {"user": "dev-user", "namespace": "*", "resource": "pods", "apiGroup": "*"}}
- 허가 내용을 변경하고 싶을 경우 json 파일을 수정하고 kubeapi를 재구동해야 함
- RBAC (Role-Based Access Control)
- 클러스터 외부에서의 접근 허가 (user-kubeapi)
- 특정 권한이 허용된 역할(role)을 생성, 사용자와 특정 역할을 연결
- e.g. Developer의 경우 pod의 조회, 생성, 삭제 가능
- Webhook
- 접근권한을 빌트인이 아니라 외부 메커니즘을 활용해 설정
- e.g. Open Policy Agent (제 3의 도구)
Kube API 서버에서 허가 메커니즘 설정
- 확인 가능한 명령어
kubectl describe pod [kube-api pod] -n kube-system
cat /etc/kubernetes/manifests/kube-apiserver.yaml
ps -aux | grep authorization
- 설정하지 않을 경우 --authorization-mode=AlwaysAllow 기본값
- --authorization-mode=Node,RBAC,Webhook 처럼 설정 가능
- 여러 메커니즘을 사용할 경우 작성한 순서대로 접근가능 여부를 확인
Role Based Access Controls (RBAC)
role 객체 생성 (yaml 파일)
- apiVersion: rbac.authorization.k8s.io/v1
- kind: Role
- metadata:
- rules:
- -apiGroups: [""] # core group의 경우 빈칸으로 둬도 무방, 그렇지 않은 경우 그룹명 지정
- resources: ["pods"]
- verbs: ["list", "get", "create", "update", "delete"]
- resourceNames: ["blue", "orange"] # 전체 pod가 아니라 특정 pod에 대해서만 권한 허가 필요 시
- -apiGroups: [""]
- resources: ["ConfigMap"]
- verbs: ["create"]
role binding 객체 생성 (yaml 파일)
- apiVersion: rbac.authorization.k8s.io/v1
- kind: RoleBinding
- metadata:
- name: devuser-developer-binding
- namespace: # 네임스페이스 지정하고 싶은 경우 해당 항목 작성
- subjects: # 사용자 정보
- -kind: User
- name: dev-user
- apiGroup: rbac.authorization.k8s.io
- roleRef: # 역할 정보
- kind: Role
- name: developer
- apiGroup: rbac.authorization.k8s.io
명령어
kubectl get roles
kubectl get rolebindings
kubectl describe role [역할명]
kubectl describe rolebinding [역할바인딩명]
kubectl auth can-i create deployments
- 특정 작업을 수행할 수 있는지 여부를 확인 (yes, no)
--as dev-user
- 특정 사용자가 작업을 수행할 수 있는지 여부를 확인하는 옵션
--namespace test
- 특정 네임스페이스에서 작업을 수행할 수 있는지 여부를 확인하는 옵션
kubectl get roles -A --no-headers | wc -l
- 전체 네임스페이스에 존재하는 role의 개수 파악
kubectl create role [이름] --verb=list,create,delete --resource=pods
- yaml 파일 말고 간단하게 명령어로 role 객체 생성
kubectl edit role [이름] -n [네임스페이스명]
- resource name, rule 등 수정 가능
클러스터 역할, 클러스터 역할바인딩
- 네임스페이스 범위 (namespaced)
- 역할과 역할바인딩은 네임스페이스 안에서 생성됨
- 특정 네임스페이스를 생성해주지 않을 경우 default 네임스페이스에 생성됨
- e.g. pods, replicasets, jobs, deployments, services, secrets, roles, rolebindings, configmaps, PVC, ...
kubectl api-resources --namespaced=true
- 클러스터 범위 (cluster scoped)
- 노드는 특정 네임스페이스 안에서 생성될 수 없음
- e.g. nodes, PV, clusterroles, clusterrolebindings, certificatesigningrequests, namespaces, ...
kubectl api-resources --namespaced=false
clusterrole (클러스터 역할)
- e.g. cluster admin
- node 조회, 생성, 삭제하는 역할 부여 가능
- e.g. storage admin
- persistent volume(PV)과 persistent volume claim(PVC) 조회, 생성, 삭제하는 역할 부여 가능
- yaml 파일 형식
- apiVersion: rbac.authorization.k8s.io/v1
- kind: ClusterRole
- metadata:
- name: cluster-administrator
- rules:
- -apiGroups: [""]
- resources: ["nodes"]
- verbs: ["list", "get", "create", "delete"]
clusterrolebinding (클러스터 역할바인딩)
- yaml 파일 형식
- apiVersion: rbac.authorization.k8s.io/v1
- kind: ClusterRoleBinding
- metadata:
- name: cluster-admin-role-binding
- subjects:
- -kind: User
- name: cluster-admin
- apiGroup: rbac.authorization.k8s.io
- roleRef:
- kind: ClusterRole
- name: cluster-administrator
- apiGroup: rbac.authorization.k8s.io
서비스 계정
- 사용자 계정은 사람에 의해 사용됨
- 서비스 계정은 기계에 의해 사용됨
- e.g. 모니터링 어플리케이션 (Prometheus), 빌드툴 (Jenkins)
- 특정 어플리케이션이 쿠버네티스 API를 쿼링하고자 한다면 인증이 필요
kubectl create serviceaccount(sa) [서비스 계정명]
- 외부 어플리케이션이 인증을 하기 위해 필요한 토큰 또한 생성 (secret 객체)
kubectl get serviceaccount
kubectl describe serviceaccount [서비스 계정명]
kubectl describe secret [토큰명]
토큰
- REST로 호출할 때 사용 가능
- e.g.
curl https://.../api -insecure --header "Authorization: Bearer [토큰]
- 만약 외부 어플리케이션이 pod의 형태로 쿠버네티스 클러스터 내에 존재한다면
- 서비스 토큰 시크릿이 pod에 volume으로 자동으로 마운팅
kubectl exec -it [pod명] --ls [마운트 경로: /var/run/secrets/kubernetes.io/serviceaccount]
- ca.crt, namespace, token 파일 확인 가능
kubectl exec -it [pod명] cat [마운트 경로 내 토큰파일: /var/run/secrets/kubernetes.io/serviceaccount/token]
- 만약 기본이 아니라 특정 서비스 계정을 사용하고 싶다면 pod yaml 파일 > spec > serviceAccountName에 원하는 서비스 계정 사용
- pod의 경우 삭제 후 재생성해야 반영 가능
- deployment의 경우 수정 시 자동 반영
kubectl set serviceaccount deploy/[deploy명] [서비스 계정명]
- 혹은 deployment yaml 파일 > spec > template > spec > serviceAccountName에 작성 후
kubectl apply -f [파일명]
- 만약 서비스 계정을 자동으로 마운트하지 않고 싶다면 pod yaml 파일 > spec > automountServiceAccountToken: false 사용
최신 업데이트 내용
v1.22
- TokenRequestAPI
- 기존의 토큰은 사용제한 기간이 없었음
- 이제 토큰은 Service Account Administration Controller가 TokenRequestAPI를 통해 생성 (pod 생성 시)
- TokenRequestAPI는 Audience, Time, Object Bound
- pod yaml 파일 예시 (volumes > projected: 링크)
- sources:
- -serviceAccountToken:
- expirationSeconds: 3607
- path: [volumeMount명]
v1.24
- 이전에는 서비스 계정을 생성하면 시크릿 객체와 토큰이 생성되었음
- 이제는 서비스 계정을 생성하면 서비스 계정만 생성
- 토큰을 생성하기 위해서는
kubectl create token [서비스 계정명] 으로 별도 생성해야 함
- 해당 토큰은 시크릿 객체가 아님
- 만약 시크릿 객체로 만들고 싶다면 아래와 같은 yaml 파일로 생성 가능 (TokenRequestAPI 사용할 수 없을 때, 보안 문제가 중요하지 않을 때)
- apiVersion: v1
- kind: Secret
- type: kubernetes.io/service-account-token
- metadata:
- annotations:
- kubernetes.io/service-account.name: [서비스 계정명]
이미지 보안
- e.g. image: docker.io/library/nginx
- 맨 마지막 부분(nginx)은 이미지, 레포지토리
- 중간 부분(library)은 사용자, 계정명
- 만약 해당 부분이 제공되지 않는다면 도커의 공식 이미지들이 저장된 기본 계정인 library가 사용됨
- 맨 앞 부분(docker.io)은 레지스트리
- 이미지가 풀(pull)되는 위치
- 제공되지 않는다면 도커의 기본 레지스트리인 도커 허브 (docker.io)
- e.g. gcr.io (구글 레지스트리)
프라이빗 레포지토리 (private repository)
- 특정 자격 증명(credential)이 있어야지만 접근 가능할 수 있도록 지정 가능
docker login private-registry.io
docker run private-registry.io/apps/internal-app
kubectl create secret docker-registry [시크릿 이름] --docker-server=[private-registry.io] --docker-username=[사용자명] --docker-password=[비밀번호] --docker-email=[이메일 주소]
- 도커 크레덴셜을 저장하기 위한 도커 레지스트리를 시크릿 객체 형태로 생성
- pod yaml 파일 수정
- (spec > containers > ) image: private-registry.io/apps/internal-app
- (spec > ) imagePullSecrets:
보안 맥락 (Security Context)
도커에서의 보안 설정 (사용자, 리눅스)
- 도커가 설치된 호스트에서 OS 프로세스, 도커 데몬, SSH 서버 등 여러 프로세스가 돌아가고 있다고 가정
- 호스트에서 새로운 도커 컨테이너 실행
- 가상 머신과 다르게 컨테이너는 호스트와 완전히 분리되지 않음
- 동일한 커널을 공유, 리눅스에서 네임스페이스를 통해 분리됨
- 도커 컨테이너 내에서 프로세스 확인 시 컨테이너 내의 프로세스만 확인 가능하나, 호스트에서는 도커 컨테이너를 포함한 모든 프로세스 확인 가능
- 도커 컨테이너 내 프로세스를 root user가 아닌 다른 사용자가 실행할 수 있도록 하려면
docker run --user=[user ID] ...
- Dockerfile에 이미지 생성 당시 직접 지정
- e.g. FROM [이미지명] USER [user ID]
docker build -t [이미지명] .
docker run [이미지명] ...
- 도커 컨테이너에 리눅스에서 가능한 기능 추가/제거
- /usr/include/linux/capability.h에 리눅스에서 가능한 기능들 제공됨
- e.g.
docker run --cap-add MAC_ADMIN [이미지명]
- e.g.
docker run --cap-drop KILL [이미지명]
- e.g.
docker run --privileged [이미지명]
쿠버네티스에서의 보안 설정 (사용자, 리눅스)
- 도커 컨테이너를 실행할 때 사용자 ID, 리눅스 기능 등 다양한 보안 기준을 적용할 수 있음
- 쿠버네티스에서도 유사한 보안 설정 가능
- 일반적으로 pod 내에 container가 캡슐화되어 존재하는 형태
- pod-level, container-level 등 설정 가능 (둘 다 있을 경우 container-level 우선)
pod yaml 파일
- spec:
- securityContext:
- runAsUser: [사용자 ID] # pod-level
- containers:
- -name: ubuntu
- image: ubuntu
- command: ["sleep", "3600"]
- securityContext: # container-level
- runAsUser: [사용자 ID]
- capabilities: # container-level에서만 적용 가능
네트워크 정책
- 트래픽
- ingress: 들어오는 방향의 트래픽
- egress: 나가는 방향의 트래픽
- 네트워크 보안
- 노드, 파드, 서비스는 모두 각자 별개의 IP 주소를 가짐
- 파드는 추가적인 세팅 없이도 서로 소통이 가능 (전제 조건)
- 네트워크 정책 (객체)
- 네트워크 정책을 한 개 이상의 파드와 연결
- 트래픽 정책을 결정할 수 있음
- e.g. DB 서버의 경우 API 서버(포트)로부터 오는 ingress 트래픽만 허용
- selector를 이용해 네트워크 정책과 파드를 연결
- Kube-router, Calico, Romana, Weave-net의 경우 네트워크 정책 지원
- Flannel의 경우 네트워크 정책 미지원
네트워크 정책 yaml 파일
ingress
- e.g. DB 파드의 경우 API 파드로부터 오는 ingress 트래픽만 허용할 것 (포트: 3306)
- apiVersion: networking.k8s.io/v1
- kind: NetworkPolicy
- metadata:
- spec:
- podSelector:
- matchLabels:
- role: db # DB 역할을 하는 pod와 연결
- policyTypes:
- -Ingress # ingress, egress 중 고립하려는 트래픽을 명시
- ingress:
- -from: # from 하위에 podSelector & namespaceSelector 그리고 ipblock 이라는 2 가지 규칙이 존재하는 상황 (둘 중 하나만 만족하면 됨; -로 규칙 분리)
- -podSelector:
- namespaceSelector: # 특정 네임스페이스의 api-pod로 트래픽을 제한하고 싶을 때
- -ipblock: # 특정 범위의 IP의 경우 DB 파드에 접근 허용 (e.g. 쿠버네티스 클러스터에 배포되지 않은 백업서버 등)
- ports:
- -protocol: TCP
- port: 3306
egress
- apiVersion: networking.k8s.io/v1
- kind: NetworkPolicy
- metadata:
- spec:
- podSelector:
- matchLabels:
- role: db # DB 역할을 하는 pod와 연결
- policyTypes:
- ingress:
- -from:
- ports:
- -protocol: TCP
- port: 3306
- egress: # DB 서버가 외부 백업서버에 트래픽을 보내는 경우
참고
기타 명령어
kubectl api-resources
- 객체 이름, 단축어, api 버전, namespaced 여부, 종류 등을 확인할 수 있음
jq -R 'split(".") | select(length > 0) | .[0],.[1] | @base64d | fromjson' <<< [토큰내용]
kubectl exec [pod명] -- whoami
- 해당 pod 내에서 프로세스를 실행할 수 있는 사용자 확인 가능
kubectl get networkpolicies(netpol)