CKA-12일차

YeJi Kim·2023년 2월 28일
0

CKA

목록 보기
12/15

📍 CKA 12일차
📍 Udemy-Certified Kubernetes Administrator (CKA) with Practice Tests 144-152




144. TLS in Kubernetes

공용키가 있는 인증서는 보통 .crt 확장자나 .pem 확장자를 가진다.
개인키가 있는 인증서는 보통 .key나 -key.pem 확장자를 가진다. 개인키는 파일명이나 파일 확장자에 'key'가 들어간다.


쿠버네티스 클러스터는 마스터와 작업자 노드 집합으로 구성되어 있다.
이 노드들 사이의 모든 통신은 보안이 필요하고 암호화되어야 한다.
kubectl 명령어를 통해 클러스터와 상호작용하거나 kubernetes API에 접근할 때에도 TLS 연결을 설정해야 한다.
쿠버네티스 클러스터 내 모든 구성 요소 간의 통신은 보안이 필요하다.
두 가지 주요 요구 사항은 클러스터 내의 다양한 서비스를 이용하기 위해 서버 인증서를 사용하고, 정체를 확인하기 위해 클라이언트 인증서를 사용하는 것이다.


쿠버네티스 클러스터의 서버 구성요소는 다음과 같다.

kube-api server는 다른 구성 요소와 외부 사용자에게 쿠버네티스 클러스터를 관리하기 위해 HTTPS 서비스를 제공한다. kube-api server는 클라이언트와의 모든 통신을 보호하기 위해 인증서가 필요하다. 그래서 인증서와 개인키 쌍을 생성한다.

클러스터에 있는 또 다른 서버는 etcd server이다. etcd 서버는 클러스터에 관한 모든 정보를 저장한다. 따라서, etcd 서버도 인증서와 개인키 쌍이 필요하다.

클러스터에 있는 다른 서버는 작업자 노드에 있는 kubelet server이다. kubelet server는 kube-api server가 작업자 노드와 통신하기 위해 사용하는 HTTPS를 제공한다. 그래서 kubelet server는 인증서와 개인키 쌍이 필요하다.

이것이 쿠버네티스에 있는 서버 구성요소들이다.


다음으로 쿠버네티스 클러스터의 클라이언트 구성요소는 다음과 같다.

kube-api server에 접근하는 클라이언트는 kubectl REST API를 사용하는 관리자이다.
관리자 사용자는 kube-api server에 인증하기 위해 인증서와 개인키 쌍이 필요하다.

kube-scehduler도 kube-api server에 접근하는 클라이언트이다. 스케줄러는 클라이언트 TLS 인증서를 이용해 ID를 확인하기 때문에 자체 인증서와 개인키가 필요하다.

kube-controller-manager는 kube-api server에 접근하는 또 다른 클라이언트이다. kube-api server에 인증하기 위한 인증서를 요구한다. 그래서 인증서와 개인키를 만든다.

마지막 클라이언트 구성요소는 kube-proxy이다. kube-proxy는 kube-api server에 인증하기 위해 클라이언트 인증서를 필요로 한다. 따라서 인증서와 개인키 쌍이 필요하다.


가령, kube-api server는 etcd 서버와 통신한다.
kube-api server는 etcd 서버와 통신하는 유일한 서버이다.
etcd 서버와의 통신에 있어서 kube-api server는 클라이언트이다. 그래서 인증이 필요하다.

kube-api server는 고유의 API 서비스를 처리하기 위해 사용했던 것과 같은 키(apiserver.crt, apiserver.key)를 사용할 수 있다. 아니면 kube-api server를 위한 새로운 인증서와 개인키 쌍을 생성해 etcd 서버에 인증할 수도 있다.

kube-api server는 작업자 노드를 모니터하기 위해 개별 노드에 있는 kubelet 서버와도 통신한다. 이 경우에도 원본 인증서를 사용할 수도 있고 새로운 인증서를 발급할 수도 있다.


정리해보자면, 클라이언트가 kube-api server에 연결할 때 사용하는 클라이언트 인증서 모음이 있고 kube-api server가 클라이언트로서 사용하는 클라이언트 인증서 모음이 있다.

  • 클라이언트 입장
    • kube-api server와 통신하기 위한 admin의 인증서와 개인키
    • kube-api server와 통신하기 위한 kube-scheduler의 인증서와 개인키
    • kube-api server와 통신하기 위한 kube-controller-manager의 인증서와 개인키
    • kube-api server와 통신하기 위한 kube-proxy의 인증서와 개인키
    • etcd server와 통신하기 위한 kube-api server의 인증서와 개인키
    • kubelet server와 통신하기 위한 kube-api server의 인증서와 개인키
    • kubelet server와 통신하기 위한 kubelet server의 인증서와 개인키
  • 서버의 입장
    • etcd server의 인증서와 개인키
    • kube-api server의 인증서와 개인키
    • kubelet server의 인증서와 개인키


모든 인증서에 서명하기 위해서는 CA(Certificate Authority)가 필요하다.
쿠버네티스는 클러스터에 대해 적어도 하나의 인증서 인증을 요구한다. 그래서 다음 사진처럼 하나 이상의 CA를 가질 수 있다.

CA는 자체 인증서와 키를 갖는다.




145. TLS in Kubernetes - Certificate Creation

클러스터를 위한 인증서를 생성하기 위해 EASYRSA, OPENSSL, CFSSL 같은 다양한 도구들을 이용할 수 있다. 이번 강의에서는 OpenSSL 도구를 사용해 인증서를 생성한다.

인증서는 개인키 소유자의 공개키에 인증기관의 개인키로 전자서명한 데이터이다.

1단계. CA 구축
먼저 openssl genrsa 명령을 이용해 개인키(ca.key)를 생성한다.
그런 다음 openssl req 명령을 이용해 인증서서명요청(ca.csr)를 생성한다. 인증서 서명 요청에서 CN(Common Name) 필드에 이름을 지정한다.
마지막으로 openssl x509 명령을 이용해 인증서에 서명한다.

이것은 CA 자체에 대한 거라 첫 단계에서 생성된 개인키를 이용해 CA가 자체 서명했다.
다른 모든 인증서에서는 CA 키 쌍을 사용해서 서명할 것이다.


CA는 이제 개인키와 인증서 파일이 있다.

2단계. 클라이언트 인증서 생성
관리자의 클라이언트 인증서 생성 과정을 살펴보자.
먼저 openssl genrsa 명령을 이용해 개인키(admin.key)를 생성한다.
그런 다음 open req 명령을 이용해 인증서서명요청(admin.csr)을 생성해 관리자의 이름을 지정한다.
마지막으로 openssl x509를 사용해서 서명된 인증서를 생성한다. 이때 CA 인증서와 CA 개인키를 지정해야 한다. CA 개인키로 인증서에 서명한다.
이로써, 클러스터 내에 유효한 인증서(admin.crt)가 생성된다.

인증서와 개인키를 생성하는 이 과정은 새 사용자에 대한 사용자 계정을 만드는 것과 유사하다.
인증서는 유효한 사용자 ID이고 키는 암호와 같다. 인증서와 개인키는 단순한 사용자 이름과 암호보다 보안이 훨씬 더 철저하다.

이 관리자를 위한 인증서를 다른 인증서와 구분하기 위해 그룹 세부 정보를 추가해야한다.
쿠버네티스에서 관리 권한을 가진 system:masters라는 그룹이 있다. 즉, 인증서 서명 요청에서 반드시 'O'필드를 통해 그룹 세부 정보를 명시해야 한다.


클라이언트 인증서를 생성하는 과정은 모두 동일하다.

kube-scheduler는 시스템 구성 요소로 쿠버네티스 제어판의 일부이다.
그래서 이름 앞에 키워드 'SYSTEM'을 붙여야 한다.

kube-controller-manager도 시스템 구성 요소라서 이름 앞에 'SYSTEM'을 붙여야 한다.

위의 과정을 통해 다음과 같은 클라이언트 인증서를 생성할 수 있다.

  • kube-api server와 통신하기 위한 admin의 인증서와 개인키
  • kube-api server와 통신하기 위한 kube-scheduler의 인증서와 개인키
  • kube-api server와 통신하기 위한 kube-controller-manager의 인증서와 개인키
  • kube-api server와 통신하기 위한 kube-proxy의 인증서와 개인키

생성한 클라이언트 인증서는 kube-api server와의 REST API 통신에서 사용할 수 있다. 옵션을 통해 인증서와 키, ca를 명시한다.
다른 방법은 이 모든 매개변수를 kubeconfig 구성 파일에 명시하는 것이다. 구성 파일에 통신할 서버의 목적지 정보와 사용할 인증서 등을 지정해야 한다.


쿠버네티스에서도 구성 요소끼리 서로 확인하려면 CA의 루트 인증서 복사본이 필요하다. 서버나 클라이언트가 인증서를 갖고 구성할 때마다 CA 루트 인증서도 지정해야 한다.
아래 사진에서 쿠버네티스의 모든 구성 요소가 CA의 루트 인증서 복사본을 갖고 있는 것을 확인할 수 있다.


3단계. 서버 인증서 생성
ETCD 서버의 인증서 생성 과정을 살펴보자.
인증서를 생성하는 과정은 이전과 동일하다.
ETCD 서버는 고가용성 환경에서 다중 서버에 걸쳐 클러스터로 배포될 수 있다. 이 경우, 클러스터 내 다른 멤버들 간의 통신을 안전하게 하려면 추가 피어 인증서를 생성해야 한다.

키와 인증 파일 옵션, 피어 인증서, CA 루트 인증서 등을 지정할 수 있다.


kube-api server도 동일한 인증서 생성과정을 거친다.
클러스터 내의 모든 작업은 kube-api를 거친다. 클러스터 내 움직이는 모든 것을 kube-api server가 안다.
kube-api server가 kubernetes이다. kube-api server는 kubernetes, kubernetes.default, kubernetes.default.svc, kubernetes.default.svc.cluster.local 등으로 언급된다. 일부 장소에선 단순히 IP 주소로 언급되기도 한다.

kube-api server를 실행하는 호스트의 IP 주소나 그걸 실행하는 파드의 모든 이름은 반드시 kube api server를 위해 생성된 인증서에 존재해야 한다.
그래야만 kube-api server를 이런 이름으로 참조하는 이들이 유효한 연결을 설정할 수 있다.

kube-api server의 키를 생성하기 위해 아까와 같은 openssl genrsa 명령어를 사용한다.
인증서서명요청(csr)에서 kube-api server 이름을 지정한다.

하지만 kube-api server의 다른 이름은 어떻게 명시할까?

kube-api server의 다른 이름을 지정하기 위해 openssl.cnf 파일을 생성하고 대체 이름을 지정한다. 이 구성 파일을 인증서서명요청의 옵션으로 지정한다.

마지막으로 CA 인증서와 ca 개인키를 이용해 인증서에 서명한다.

ETCD와 kubelet 서버와 통신할 때 클라이언트로서 kube-api server가 필요하다. 이때 kube-api server의 클라이언트 인증서를 고려해야 한다.

앞에서 생성된 인증서의 위치는 kube-api server의 서비스 구성 파일로 전달된다.
첫째, CA 파일이 전달되어야 한다. 모든 구성 요소가 클라이언트를 확인하기 위해 CA 인증서를 필요로 하기 때문이다.
둘째, kube-api server의 인증서를 TLS 인증 옵션으로 제공해야 한다.
그런 다음 etcd server와 통신하기 위해 kube-api server에서 사용되는 클라이언트 인증서를 지정해 etcd server에 ca 파일로 다시 연결한다.
마지막으로 kubelet server와 통신하기 위해 kube-api server에서 사용되는 클라이언트 인증서를 지정해 kubelet server에 ca 파일로 다시 연결한다.


다음으로 kubelet server이다.
kubelet 서버는 HTTPS API 서버로 각 노드에서 실행되며 노드 관리를 책임진다.
kube-api server가 노드를 모니터하기 위해 kubelet과 통신하는 것이다. 또한 kube-api server는 kubelet 서버와 통신을 통해 그 노드에 어떤 파드가 스케줄될지에 대한 정보도 보낸다.

클러스터의 각 노드에 대해 인증서와 개인키 쌍이 필요하다.
각 노드에 대한 인증서와 개인키의 이름은 노드의 이름을 따서 짓는다.
인증서가 생성되면 kubeletConfiguration 정의 파일을 사용한다.
클러스터의 각 노드에서 kubeletConfigutaion을 생성해야 한다.

kube-api server과 어떤 노드가 인증하는지를 알아야 하고 올바른 사용 권한을 부야해야 한다.
따라서 노드는 형식에 올바른 이름을 갖춰야 한다. 노드는 시스템 구성요소이기 때문에 인증서의 이름은 'system:node:노드명' 형식을 따른다.




146. View Certificate Details

이번 강의에서는 기존 클러스터에서 인증서를 보는 방법에 대해 알아본다.

먼저, 클러스터가 어떻게 배포되었는지 알아야 한다. 쿠버네티스 클러스터가 처음부터 서비스의 형태로 배포되었는지 아니면 kubeadm 같은 자동 프로비저닝 툴에 의해 파드 형태로 구성되었는지 알아야 한다.
이번 강의에서는 kubeadm에 의한 클러스터 프로비저닝을 살펴본다.


'/etc/kubernetes/manifest/kube-api server.yaml'에서 kube-api server와 관련된 모든 인증서에 대한 정보를 얻을 수 있다.

openssl x509 명령을 사용하여 인증서 파일의 내용을 디코딩하고 세부 사항을 확인할 수 있다.

인증서의 세부사항을 확인하고 올바른 이름과 올바른 대체 이름을 갖고 있는지, 인증서가 올바른 조직의 일부인지, 인증서가 올바른 발행인에 의해 발행되었는지, 인증서가 만료되지 않았는지 확인해야 한다.
인증서 헬스체크 시트 예시

로그를 통해서도 문제가 생겼는지 확인할 수 있다. kubadm은 다양한 구성 요소를 파드로 배포하기 때문에 kubectl logs 명령어를 통해 로그를 확인할 수 있다.




149. Solution - View Certification Details

/etc/kubernetes/manifests 폴더 아래에 있는 클러스터 구성 요소 정의 파일에서 certificate file의 위치를 알 수 있다.


cerftificate file의 CN(Common Name)을 알기 위한 명령어 openssl x509 -in file-path.crt -text -noout를 실행하고 Subject 필드를 확인하면 된다.


연결이 끊겨서 kubectl 명령어를 사용할 수 없는 경우, 문제를 해결하는 방법은 다음과 같다.
docker ps -a 명령어를 사용하여 컨테이너ID를 확인하고 docker logs 명령어를 사용해서 로그를 확인한다.

2379번 포트에 연결할 수 없다는 로그를 확인할 수 있다.
이러한 경우, 2379번은 ETCD의 포트이므로 ETCD의 로그를 확인해봐야 한다.

로그에 따르면 server-certificate.crt 파일이 없다는 에러를 확인할 수 있다.
이것이 오류의 원인이다.

etcd의 manifest 파일을 확인하여 server-certificate.crt 파일 경로가 잘못 작성된 것을 확인할 수 있다.
ls /etc/kubernetes/pki/etcd 명령어를 통해 server-certificate.crt라는 파일은 없고 대신 server.crt 파일이 존재하는 것을 확인할 수 있다.
따라서, server-certificate.crt를 server.crt로 변경해야 한다.


이번 문제의 경우, docker ps -a | grep kube-apiserver를 통해 컨테이너 ID를 확인하고 docker logs 명령어로 로그를 확인했을 때 다음과 같은 로그를 확인할 수 있다.

2379번 포트에서 문제가 발생하고 있기 때문에 ETCD 서버 문제라는 것을 알 수 있다.
따라서, ETCD 컨테이너의 로그를 확인해봐야 한다.

kube-api server가 잘못된 인증서를 보내고 있는 것을 확인할 수 있다.

올바르게 인증서 파일명을 변경해주면 오류가 해결된다.




150. Certificates API

나는 클러스텉 관리자로서 전체 클러스터를 설정하는 과정에 CA 서버와 다양한 구성 요소에 대한 인증서 뭉치를 설정했다. 팀에 새로운 관리자가 왔다. 클러스터에 접속할 수 있게 인증서와 개인키 쌍을 줘야 한다.
그녀는 개인키를 만들어 인증서 서명 요청을 작성해서 나한테 보낸다.
나는 클러스터의 유일한 관리자이므로 인증서 서명 요청을 내 CA 서버로 가져가서 CA 서버가 CA 서버의 개인키와 루트 인증서를 이용해서 서명하게 한다.
인증서가 생성되면 인증서를 그녀에게 다시 보낸다. 이제 그녀는 자신만의 유효한 인증서와 키를 갖고 있다.
인증서에는 유효기간이 있기 떄문에 유효기간이 만료될 때마다 새로운 CSR을 생성하고 CA에 서명받는 같은 과정을 따른다.

CA 서버란 무엇일까?

CA는 우리가 생성한 키와 인증서 파일의 쌍이다. 이 한 쌍의 파일에 접근 권한을 가진 사람은 쿠버네티스 인증서에 서명할 수 있다.
CA에 접근 가능하면 원하는 만큼 많은 사용자를 생성하고 원하는 특권을 넣을 수 있다.
그래서 이런 파일은 안전한 서버에서 보호 및 저장되어야 한다. 즉, CA 파일이 안전하게 저장되는 서버가 CA 서버이다.
인증서에 서명하고 싶을 때마다 CA 서버에 로그인해야만 할 수 있다.
쿠버네티스 클러스터에서 마스터 노드에 CA 파일들이 위치하기 때문에 마스터 노드는 CA 서버이다.


쿠버네티스엔 자동화된 방법으로 인증서를 관리하고 요청에 서명하는 Certificates API가 존재한다.
1. Certificates API를 통해 쿠버네티스로 인증서 서명 요청이 보내진다.
2. 관리자가 인증서 서명 요청을 받으면 인증서서명요청(CSR)을 생성한다.
3. CSR 개체가 생성되고 나면 모든 인증서서명요청은 클러스터 관리자들이 볼 수 있다. kubectl 명령으로 요청을 쉽게 검토하고 승인할 수 있다.
4. 이 인증서는 추출되어 사용자와 공유될 수 있다.


위의 자세한 과정을 살펴보자.
먼저 사용자는 키를 만들고 만들어진 키를 사용해서 인증서서명요청(CSR)을 생성한다.

그런 다음 관리자에게 CSR을 보낸다. 관리자는 키를 받아 인증서서명요청 개체를 만든다.
인증서서명요청 개체는 다른 쿠버네티스 개체처럼 매니페스트 파일을 통해 생성된다. spec 영역에 사용자가 속해야 할 그룹, 계정의 사용 용도를 명시하고 request 필드에 CSR을 지정한다.
이때, base64로 인코딩된 CSR의 텍스트를 사용해야 한다.

일단 개체가 생성되면 kubectl get csr 명령어를 통해 관리자들은 모든 CSR을 볼 수 있다. 새 요청을 식별하고 kubectl certificate approve 명령어를 통해 요청을 승인할 수 있다.
쿠버네티스는 CA 키 쌍을 이용해 인증서에 서명하고 사용자를 위한 인증서를 생성한다.

이 인증서는 추출되어 사용자와 공유될 수 있다.
CSR의 내용을 decode해서 확인할 수 있다.


이제 어떻게 작동하는지 확인했으니 누가 이걸 수행하는지 알아봐야 한다.
쿠버네티스의 컨트롤 플레인을 보면 kube-api server, scheduler, controller manager 등을 볼 수 있다.
인증서와 관련된 모든 작업은 controller manager에 의해 실행된다.

controller manager를 자세히 보면 CSR-APPROVING, CSR-SIGNING을 확인할 수 있다.
CSR-APPROVING은 승인, CSR-SIGNING은 서명 작업을 책임진다.

controller manager 서비스 구성에는 인증서와 개인키를 지정하는 두 옵션이 있다. controller manager가 인증서에 서명하기 위해서 CA 서버의 인증서 경로와 개인키가 필요하기 때문이다.




152. Solution - Certificates API

CertificateSigningRequest(CSR) 개체 생성하기

  1. csr 파일을 base64로 인코딩하기
  2. CertificateSigningRequest 매니페스트 파일 작성하기

    CSR이 pending 상태인 것을 확인할 수 있다.
  3. CSR 요청을 승인한다.
    CSR 요청을 승인했기 때문에 CSR이 Approved,Issued 상태인 것을 확인할 수 있다.

kubectl certificate deny 명령어를 사용해서 CSR 요청을 거부할 수 있다.

profile
이전의 기록들 👉 https://blog.naver.com/reviewerkyj

0개의 댓글