Certified Kubernetes Administrator (CKA) with Practice Tests (강의 링크, 레퍼런스 노트)
- 평소 강의 할인도 많이 하고, 연습문제도 풀어볼 수 있으니 실제 강의 수강을 추천
- 아래는 강의 내용 번역 및 정리본 (문제 시 댓글로 알려주세요)
쿠버네티스 보안 기초요소
- kube-apiserver를 통해 거의 모든 동작을 수행할 수 있기 때문에 접근을 제한해야 함
- 누가 접속할 수 있는가
- 인증 (Authentication)
- 사용자명 및 비밀번호 (파일)
- 사용자명 및 토큰 (파일)
- 인증서
- 외부 인증 제공 - LDAP
- 서비스 계정
- 무엇을 할 수 있는가
- RBAC 허가 (Authorization)
- ABAC 허가 (Authorization)
- Node 허가 (Authorization)
- Webhook Mode
- TLS 인증서 (Certificate)
- ETCD 클러스터, Kube Controller Manager, Kube Scheduler, Kube Proxy, Kubelet 등의 통신은 TLS 암호화로 이루어짐
- 네트워크 정책
- 기본적으로 모든 pod는 클러스터 내 모든 pod에 대해 접근 가능 (노드와 상관없이)
- 네트워크 정책을 통해서 통신을 제한할 수 있음
Authentication (인증)
Account (계정)
- 계정 종류
- 사용자 (user): 관리자, 개발자 등
- 서비스 계정 (service account): 봇 등
- 쿠버네티스가 직접 사용자 계정을 관리하지는 않음
- 인증서, 사용자 정보 파일, LDAP 등의 외부 소스 혹은 서비스 활용
- 사용할 수 없는 명령어
kubectl create user [사용자명]
kubectl list users
- 사용할 수 있는 명령어
kubectl create serviceaccount [계정명]
kubectl get serviceaccount
사용자 계정
- 모든 사용자 접근은 apiserver에 의해 관리됨
kubectl 로 접근
curl [경로] 로 접근
인증 메커니즘
- 고정 비밀번호 파일
- 비밀번호, 사용자명, 사용자 ID (+ 그룹 ID)를 담은 csv 파일이 있다고 가정
- 방법 1. kube-apiserver.service 파일에
--basic-auth-file=[csv파일명].csv 추가
- 방법 2. kube-apiserver pod yaml 파일의 command에
--basic-auth-file=[csv파일명].csv 추가
- kubeadm tool로 쿠버네티스 구성한 경우 사용 가능
- kube-apiserver가 자동으로 재시작
- apiserver 접근 시 인증이 필요할 경우,
curl -v -k [경로] -u "사용자:비밀번호" 처럼 사용
- 고정 토큰 파일
--token-auth-file=[토큰파일명].csv 추가
- apiserver 접근 시
curl -v -k [경로] --header "Authorization: Bearer [토큰] 처럼 사용
- curl 명령어 옵션에 관한 설명은 해당 링크 참고
- 고정 파일을 이용한 형식은 추천되는 인증 방식은 아님 (insecure)
- kubeadm 세팅의 경우 volume mount를 고려하는 것이 좋음
- 인증서
- 제 3의 인증 프로토콜 (e.g. LDAP)
TLS 배경지식
- 키를 활용하여 통신을 암호화하여 안전한 송신/수신을 가능케 함
- 관련하여 처음 학습한다면 해당 동영상 링크 유용
대칭 암호 (symmetric encryption)
- 암호화 및 복호화에 동일한 키를 사용하는 방식
- 수신자, 발신자 간 키가 교환되기 때문에 해킹의 위험이 있음
비대칭 암호 (asymmetric encryption)
- 키의 쌍(pair)을 활용 (개인 키(private key), 공개 키(public key))
- 하나의 키로 암호화하면 다른 키로 복호화할 수 있음
- case 1. ssh 목적으로 개인 키, 공개 키 생성
ssh-keygen
cat ~/.ssh/authorized_keys
- authorized keys에 존재하는 공개 키 이외에는 서버로 접근이 불가능하도록 막음
- case 2. 클라이언트와 서버 통신 시 서버에서 개인 키, 공개 키 생성
openssl genrsa -out [개인키명].key 1024
openssl rsa -in [개인키명].key -pubout > [공개키명].[pem]
- 사용자가 https로 서버에 접근할 경우 서버로부터 서버의 공개 키를 얻게 됨
- 해커의 서버가 아니라 제대로 된 서버임을 알기 위해 공개 키는 인증서와 함께 이동
- 인증서는 생성 시 서명이 되는데, 이를 통해 합법적인 인증서인지 확인 가능
- 서명을 생성하고 인증하는 CA (Certificate Authority) 존재
- 서버의 공개 키를 사용해 사용자가 자신의 개인 키(symmetric)를 암호화, 이를 서버로 보냄
- 서버는 자신의 개인 키(asymmetric)를 사용해 사용자의 개인 키(symmetric)를 복호화
- 서버의 개인 키와 사용자의 개인 키가 다름에 주의
PKI (Public Key Infrastructure)
- 인증서를 생성하고, 배포하고, 유지하는 CA를 포함한 이러한 과정을 일컫는 용어
- 공개 키 혹은 인증서는 일반적으로 .crt, .pem으로 이름이 붙음
- 개인 키는 일반적으로 .key, -key.pem으로 이름이 붙음
CA (Certificate Authority)
- 서명을 생성하고 인증하는 기관
- e.g. Symantec, GlobalSign, digicert, ...
- 인증서 서명 절차
- CSR (Certificate Signing Requiest) 생성
openssl req -new -key [개인키명].key -out [이름].csr -subj "/C=US/ST=CA/O=MyOrg,Inc./CN=mydomain.com"
- CA에서 정보 인증
- 서명 및 인증서 송부
- CA의 진위여부 판별
- 모든 CA는 각자의 개인 키와 공개 키를 가지고 있음
- CA들의 공개 키는 모두 브라우저에 빌트인 되어있음
쿠버네티스에서의 인증서
- 인증서 종류
- Root Certificate: CA 소유
- Client Certificate: 사용자 소유
- Server Certificate: 서버 소유
- 쿠버네티스 내 모든 통신은 안전해야 함
- 쿠버네티스는 마스터 노드와 워커 노드로 이루어져 있음
- 서버를 위한 Server Certificate 필요
- 쿠버네티스의 관리자는 kubectl 유틸리티를 활용하거나 직접 apiserver에 접근 가능
- 사용자를 위한 Client Certificate 필요
서버
- kube-apiserver
- apiserver.crt, apiserver.key 필요
- 인증서와 개인 키의 이름은 달라질 수 있음
- ETCD server
- etcdserver.crt, etcdserver.key 필요
- kubelet server
- 워커노드의 kubelet 또한 https API 엔드포인트를 노출, apiserver와 소통할 수 있음
- kubelet.crt, kubelet.key 필요
클라이언트
- 관리자
- kubectl REST API를 통해 kube-apiserver와 소통
- admin.crt, admin.key 필요
- kube-scheduler
- apiserver와 통신하면서 스케줄링이 필요한 pod를 찾고 apiserver로 하여금 pod를 알맞은 노드에 스케줄되게 함
- scheduler.crt, scheduler.key 필요
- kube-controller-manager
- 마찬가지로 apiserver와 통신
- controller-manager.crt, controller-manager.key 필요
- kube-proxy
- kube-apiserver를 인증하기 위해 필요
- kube-proxy.crt, kube-proxy.key
- kube-apiserver
- ETCD 서버와 통신할 때, kube-apiserver는 client의 역할
- kubelet 서버와 통신할 때, kube-apiserver는 client의 역할이 되기도 하고 반대로 server의 역할이 되기도 함 (이럴 경우 kubelet이 client)
- 서버 인증서로 사용했던 인증서와 개인 키를 그대로 사용하거나, 새로운 쌍을 만들어 사용할 수도 있음
CA
- 클러스터 내 최소 1개의 CA 필요 (1개 이상 가능)
- ca.crt, ca.key 필요
쿠버네티스에서 인증서 생성
- EASYRSA, OPENSSL, CFSSL 등을 사용해 생성 가능
CA
openssl genrsa -out ca.key
openssl req -new -key ca.key -subj "/CN=KUBERNETES-CA" -out ca.csr
- 인증서 서명 요청 (Certificate Signing Request) 생성
- 모든 세부 정보를 담은 인증서와 유사하나 서명이 없다는 차이 존재
- CN은 Common Name의 약자로, 인증서를 사용할 요소의 이름을 특정하는 부분
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
- 앞서 생성한 CA의 개인 키를 활용해 인증서 서명
- CA의 root certificate는 모든 클라이언트와 서버에 복사되어 존재
- admin, kube-scheduler, kube-controller-manager, kube-proxy, kube-apiserver, etcd server, kubelet server, ...
- e.g. yaml 파일의 --trusted-ca-file=...
클라이언트
관리자 클라이언트
openssl genrsa -out admin.key
openssl req -new -key admin.key -subj "/CN=kube-admin/O=system:masters" -out admin.csr
- 관리자를 일반 사용자와 구분하기 위해서는 인증서에 그룹 정보를 포함하는 방법이 있음
- e.g. CSR에 그룹 정보 (/O=system:masters) 포함
openssl x509 -req -in admin.csr -CA ca.crt -CAkey ca.key -out admin.crt
- CA와 다른 점은 CA의 인증서와 개인 키를 사용했다는 점
kube-scheduler, kube-controller-manager
- controlplane의 요소인 시스템
- 이름에 SYSTEM:이라는 키워드를 붙여줘야 함 (prefix)
- e.g. SYSTEM:KUBE-SCHEDULER
- 클라이언트 인증서 및 개인 키 사용 방법
- REST API 호출 시 사용자명, 비밀번호 대신 옵션으로 전달
curl https://kube-apiserver:6443/api/v1/pods --key admin.key --cert admin.crt --cacert ca.crt
- 인증서 및 개인 키 정보를 KubeConfig 파일로 관리 및 사용
서버
ETCD 서버
- etcd-server는 여러 개의 서버에 걸친 클러스터의 형태로 배포될 수 있음
- 클러스터 내 다른 멤버들의 안전한 통신을 위해 peer certificate를 추가적으로 생성
- e.g. --peer-cert-file= 등의 정보를 etcd.yaml이 가지고 있어야 함
kube-apiserver
- 거의 모든 요소들과 소통하기 때문에 여러 가지 이름으로 불리곤 함
- e.g. kubernetes, kubernetes.default, kubernetes.default.svc, kubernetes.default.svc.cluster.local, IP 주소 등
- 해당 정보들이 모두 인증서에 작성되어야 함
openssl genrsa -out apiserver.key 2048
openssl req -new -key apiserver.key -subj "/CN=kube-apiserver" -out apiserver.csr -config openssl.cnf
- openssl.cnf 파일에 이름들을 모두 작성해 config로 넘김
- e.g. DNS_1 = kubernetes, DNS_2 = kubernetes.default, ...
openssl x509 -req -in apiserver.csr -CA ca.crt -CAkey ca.key -out apiserver.crt
- --client-ca-file을 통해 CA 인증서 제공
- --tls-cert-file, --tls-private-key-file을 통해 서버 인증서 및 키 정보 제공
- --etcd-cafile, --etcd-certfile, --etcd-keyfile 등을 통해 ETCD와 소통할 때 클라이언트 인증서 및 키 정보를 제공
- --kubelet-certificate-authority, --kubelet-client-certificate, --kubelet-client-key 등을 통해 Kubelet과 소통할 때 클라이언트 인증서 및 키 정보를 제공
kubelet
- 클러스터의 각 노드마다 인증서 및 키 정보 존재
- kubelet 인증서의 이름은 노드의 이름을 따라감
- e.g. 서버일 경우 node01, 클라이언트일 경우 system:node:node01
- 클라이언트일 경우 그룹 정보를 인증서에 포함해야 함 (e.g. SYSTEM:NODES)
- KubeletConfiguration 파일로 인증서, 키 관리
- authentication: x509: clientCAFile: 이용해 CA 인증서 관리
- tlsCertFile, tlsPrivateKeyFile: 이용해 서버 인증서 및 키 관리
인증서 확인
- 인증서 위치 확인
- kubeadm을 활용해 클러스터 구성했을 때
/etc/kubernetes/manifests/kube-apiserver.yaml
- 처음부터 직접 클러스터 구성했을 때
/etc/systemd/system/kube-apiserver.service
- 인증서 보기
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout
- 이름(CN), 별명(Alternative Name), 만료일자(Validity), 발행자(Issuer) 등 확인 가능
- 서비스 로그 확인
- kubeadm을 활용해 클러스터 구성했을 때
kubeadm logs [pod명]
- kubeadm이 제대로 작동하지 않을 때
docker logs [컨테이너ID] 혹은 crictl logs [컨테이너ID]
- 처음부터 직접 클러스터 구성했을 때
journalctl -u etcd.service -l
- journalctl은 systemd의 서비스 로그 확인 명령어 (참고 링크)
인증서 API
- 쿠버네티스에서 CA는 우리가 생성한 키와 인증서의 쌍을 의미
- 해당 파일에 접근할 수 있다면 누구나 인증서에 서명을 받을 수 있음
- 이를 막기 위해, CA 서버라는 안전한 환경에 CA 키와 인증서가 존재해야 함
- 쿠버네티스에서는 마스터 노드에 CA 키와 인증서 저장
- 쿠버네티스는 빌트인 인증서 API를 가짐
- 마스터 노드에 로그인해 수동으로 서명을 받는 게 아니라, API 호출을 통해 인증서 서명이 이루어짐
- 자동으로 인증서 및 인증서 서명 요청 관리 + 유효기간 만료 시 인증서 변경
인증서 서명 관련 명령어
- 사용자가 개인 키와 CSR 생성하여 관리자에게 전송
openssl genrsa -out jane.key 2048
openssl req -new -key jane.key -subj "/CN=jane" -out jane.csr
- 관리자가 CertificateSigningRequest 객체 생성
- apiVersion: certificates.k8s.io/v1
- kind: CertificationSigningRequest
- metadata:
- spec:
- expirationSeconds: 600
- usages:
- -digital signature
- -key encipherment
- -server auth
- request:
cat jane.csr | base64 | tr -d "\n" 혹은 cat jane.csr | base64 -w 0 등을 통해 인코딩된 텍스트
- 요청 리뷰 및 승인 (kubectl 이용)
kubectl get csr
kubectl certificate approve jane : 승인
kubectl certificate deny jane : 거절
- controller-manager에서 인증서 관련 동작을 담당
- csr-approving, csr-signing 등 존재
- yaml 파일에 --cluster-signing-cert-file, --cluster-sigining-key-file
- 사용자에게 인증서 공유
kubectl get csr jane -o yaml
echo [status:certificate 하위 인코딩 텍스트] | base64 --decode
KubeConfig
- 명령어를 사용할 때 인증서 정보를 항상 작성하는 것은 번거로움
- KubeConfig 파일을 활용하는 것이 편리
- 명령어에 --kubeconfig config 추가
kubectl get pods --kubeconfig config
- $HOME/.kube/config 경로에 저장
kubectl get pods 만 작성해도 됨
- 객체를 별도로 만들 필요 없이 파일만 있으면 됨
KubeConfig 파일 구성요소
- 섹션 1. 클러스터
- e.g. 개발환경, 운영환경, 테스트환경, 타조직(Google), ...
- 명령어에서 --server, --certificate-authority (서버 사양) 관련 부분이 여기에 포함
- 섹션 2. 사용자
- e.g. 관리자, 개발환경 사용자, 운영환경 사용자, ...
- 클러스터마다 다른 권리(priviledge)를 가질 수 있음
- 명령어에서 --client, client-certificate (클라이언트 사양) 관련 부분이 여기에 포함
- 섹션 3. 컨텍스트
- 어떤 사용자 계정이 어떤 클러스터를 접속하는데 사용될 지를 결정
- e.g. Admin@Production, Dev@Google, ...
KubeConfig Yaml 예시
- apiVersion: v1
- kind: Config
- current-context: dev-user@google
- clusters: array 형식
- -name: my-kube-playground
- cluster:
- -name: google (하위 변수 생략)
- contexts:
- -name: my-kube-admin@my-kube-playground
- context:
- cluster: my-kube-playground
- user: my-kube-admin
- namespace: finance
- -name: dev-user@google (하위 변수 생략)
- users:
- -name: my-kube-admin
- user:
- client-certificate: admin.crt
- client-key: admin.key
- -name: dev-user (하위 변수 생략)
관련 명령어
kubectl config view
- 사용되고 있는 config 확인 (기본 파일)
kubectl config view --kubeconfig=[config명]
kubectl config use-context [context명]
- 기본 컨텍스트 변경
- 실제로 파일 내 current-context 내용이 변경됨
- 컨텍스트가 변경될 때 namespace가 달라진다면 namespace도 자동으로 변경됨
cat [파일경로] | base64
echo "[인코딩된 내용]" | base64 --decode
cka 자격증 준비중이고, udemy에서 현재 security부분 듣고 있는데요
시험에서 해당 영역도 나올까요?
이 부분 좀 어렵고 길고 해서 시험에 해당 하는 영역이 아니면 가볍게 듣고 넘기고 싶어서요 ㅠㅠ