23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
K8S 장점이나, 기본적인 구조에 대해서 논의하는 것은 마치 이효리님의 스타성을 논하는 것 만큼 아무 의미 없는 것이 되었다.
따라서, 2024년에는 좀더 Deep 한 주제에 대해서 논의하고 한다. 필자는 그 첫번째 이슈로 보안을 다루어 보기로 했다.
K8S는 백화점, 고속버스 터미널 같은 Platform으로, 공통 편의 시설을 제공하여 효율을 높이는 것이 본질이다.
따라서 필연적으로 공유하는 그 무엇인가가 발생하기 때문에, 보안은 매우 중요한 화두라 생각한다.
보안에 대한 첫번째 기고는 K8S 시스템 보안에 대해서 논하고자 한다.
결론 부터 말하자면, Kubeadm을 사용하면 큰 문제 없이 모든것이 해결된다. (얼마나 기쁜일 인가?)
하지만, 기술을 하는 입장에서 알고는 가야하기에, 필자의 의식의 흐름에 맞춰서 K8S 시스템 보안에 대해서 서술해 보겠다.
K8S는 Micro Service Architecture를 가지고 있다. 아래 그림은, 글을 읽는 독자에게는 익숙한 그리고 별다른 감흥없는 그림일 것 이다.
그림 그대로를 보면, App이 구동되는 Node(Worker Node)에는 Container를 관리하는 Kubelet이라는 Agent가 설치되어 있고, 이는 Control Plane에 연결되어 있다.
Control Plane의 Kube API Server를 통해 모든 기능을 API로 제공하고, 이 API는 사용자와 사용하고 다른 Control Plan의 구성요소들이 같이 사용한다.
Kubernetes 공식 문서에서는 이러한 Control Plane의 구조를 Hubs and Spoke model 이라고 이야기 한다.
Hub and Spoke model을 언급한 이유는, 결국 K8S System의 보안은 Micro Service간 Message/Interface에 대한 연결 보안이기 때문이다.
결과적으로 mTLS와 RBAC과 같은 권한에 대한 이야기로 귀결된다.
현명하게 Kubernetes가 Hub and Spoke Model 을 적용한 덕에 보안설정에 대한 복잡성이 확 준다.
본격적인 구조를 이야기하기전에, 필자가 인식하는 K8S System에 대해서 간략히 서술하겠다.
필자는 무엇인가 오래 기억하기 위해서, 대상을 내가 이미 익히 익숙한 그 무언가에 빗대서 기억한다.
필자의 시각에서 보면 K8S 시스템은 무인 매장과 같은 시스템이다.
무인매장인 “Kub라면”이 있다고 가정한다. 사용자가 KIOSK(API Server)를 통해 원하는 매뉴를 선택하면, 요리 로봇에게 해당 매뉴가 전달된다.
그 후, 각 로봇은 옆의 다른 로봇이 무엇을 하든 상관없이, 그저 자기 차례에 입력된 매뉴에 따라 자기가 할 일만 한다.
그 후 고객은 지속적으로 상황판을 보고 있다가, 본인의 매뉴가 완성되면 맛나게 먹은 시스템이다.
K8S의 경우, 사용자는 원하는 선언을 API로 전달하고 그저 기다린다.
그 후, K8S의 구성하는 여러 로봇팔 (Kube Scheduler, Kubelet, Kube Controller Mananger, Kube DNS, CNI/CSI 그리고 각종 Operator들)들은
주기적으로 Kube API Server를 통해, 자신과 연관있는 선언에 대해서 Polling하고, 만약 관련된 선언이 있다면 각자 할일을 하고 상태를 변경한다.
즉, 실제 무엇인가 일을 하는 구성요소들간 직접적인 연결이 없는 구조이기 때문에, 보안도 일반적인 Client-Server간 보안 설정으로 충분하다
앞으로의 논의를 위해, 간단히 이야기 하겠다.
이름부터가 요상하지 않은가? 키라하면 소중하고 음흉하게 숨겨놨야 하는데, 공개한다고 한다.
수학적인 알고리즘은 바쁘니 넘어가고 그 특징에 대해서 이야기 해 보자. (Keyword: diffie-hellman)
Public Key란 Key Pair로 구성된다. 그 특징은 아래 그림과 같다.
Key 쌍중 하나로 암호화한 암호문은 키쌍중 다른 키로만 복호화 가능하다. Key 자체가 암호용/복호화 용이 나뉜 것은 아니다.
여기에 가장 중요한 특징은 키쌍 중, 하나로 나머지 하나를 절대로 유추할 수 없는 특징을 가지고 있다.
이 특성을 활용하여, 하나의 Key를 공개한다. 이것이 공개키 방식이라고 하자.
즉 수신자에게 암호화된 통신을 제공하기 위해, 수신자는 공개키를 공개하고, 발신자는 공개키로 암호화 하면, 공개키의 주인만이 암호를 풀 수 있게 된다.
빠른 이해를 위해, 통신암호와 전자서명에 Public key가 어떻게 사용되는지 조금더 자세히 알아보자.
Client가 Server A에 접속 시, Server A는 Client에 자기이름과 공개키 그리고 자기 이름을 개인키로 암호화한(전자서명) 자기증명서(인증서)를 제공한다.
Client는 인증서로 부터 제공 받은 공개키로 암호화된 전자서명을 복화화 하여, 평문의 이름과 복호화한 이름이 같음을 확인한다.
만약 같다면, 개인키를 갖고 있는 주체임으로 Server A의 신원을 믿는다. 이를 통해, Server A의 신분확인과 공개키를 Client가 확보하게 되었다.
그 후, Client는 Server A로 보내는 모든 데이터를 Server A의 공개키로 암호화 해서 전달한다.
암호화된 데이터는 개인키가 있는 Server A만 복호화 할 수 있음으로, 안전한 통신이 확보된다.
X.509는 가장 널리 사용되는 인증서 규격이다. 가장 중요한 개념은 Chain of Trust 다.
앞선 예제를 보면, Server A가 본인의 개인키로 전자서명을 했다. 이를 Self-Signed Certificate라 한다.
이방식은 어떤 Server라도 Public Key Pair만 있으면, Server A라고 주장 할 수 있음을 의미한다.
즉 주민등록증을 국가가 발행하는게 아니라, 본인 임의로 만들어서 본인임을 증명하는 꼴이다.
따라서 인증서가 공신력 있으려면, 국가와 같이 누구나 믿을 수 있는 그 누군가가 인증해줘야 한다.
이를 CA(Certificate Authority)라고 한다. 그림으로 보면 다음과 같다.
전자서명을 하는(개인키로 암호화하는) 인증기관(Issuer)과 인증대상(Subject)를 분리 한 인증서 체계가 X.509의 가장큰 특징이다.
따라서 인증서는 인증대상이 스스로 인증(즉 전자서명)하는 것이 아니라 믿을만한 안증기관(CA)를 통해 인증된다.
따라서 Client는 전자서명을 확인하기 위해, 인증서에 포함된 Public Key가 아닌 인증서의 인증기관(Issuer)의 공개키를 확보해야 된다.
결국 신뢰의 Chain이 생기는데 신뢰 Chain의 시작점을 Root CA라 한다. Root CA는 인증기관과 인증대상이 같은 Self-Signed Certificate 다.
앞서 언급 했듯이 Self-Signed Certificate는 누구나 흉내 낼 수 있음으로, 보통은 OS 제공 업체나 브라우저 제공업체가 미리 공인 Root CA들을 은밀하게 제공한다.
보통의 경우 CA들은 OS의 특정 Path에 저장되며, 읽기 권한등이 제한된다.
CA의 유효기간은 보통 10년 정도로 길기 때문에 CA의 업데이트는 빈번하게 발생하지는 않느다.
보통의 경우 OS update 시점에 갱신되지만 정해진 건 아니다.X.509 인증서를 통해, 안전하게 신원확인이 가능하고, 암호화 및 전자서명 검증을 위해 사용되는 Public Key또한 안전하게 배포 할 수 있다.
따라서, X.509 인증서를 활용하면, Server뿐 아니라 Client가 믿을 만한 대상인지 확인 할 수 있다.
이를 mTLS라 일컫는다. 이는 보통 시스템간 Transport 보안 제공을 위해 사용된다.
mTLS는 TLS/SSL 절차 후에, 서버에 Client 인증서를 전달하여, Server로 부터 Authentication/Authorization 을 실행 하게 한다.
앞서 언급했듯이 Kuberentes는 크개 3개의 서버와 기타 다수의 Client로 구성된다.
mTLS를 구성하기 위해서는 각 서버가 사용할 인증서 체계를 수립해야 한다.
인증서는 당연히 Server별로 필요하면, 인증서를 발행하는 CA도 Server별로 다르게 설정 할 수 있다.
따라서 매우 다양한 방식으로 인증체계를 수립하고 인증서를 관리 할 수 있다.
하지만 이런식으로 생각하면 너무 많은 Variant가 발생하게 되어, 논의가 문의미해 진다.
다행이 Kubernetes Community에서 공식으로 제공하는 kubeadm 이란 설치 툴이, 기본적으로 제공하는 구성이 있다.
이 구성은 필자가 보기엔 Best Practice다. 따라서, 해당 구성에 대해서 간략히 설명하고 이 구성 기준으로 인증서 체계에 대해서 설명한다.
아래 그림이 Stacked etcd라는 HA 구성이다.
이 구성은 control plane 기능을 하나의 서버에 모두 설치하여 설정을 간단히 하고, Scalability/Reliabiility를 극대화 한 구성이다.
Stacked etcd 구조는,
apiserver와 통신이 필요한 control plane service들을 동일Server에 설치한 구조다.
이를 통해, 같은 설정을 같는 노드를 찍어내듯 확정할 수 있고, 보안 측면에서도 우수하다.
또란 etcd도 같이 분산 배치한 후, 모든 Data는 N duplicate 됨으로 Reliabiility가 높다.
Single Point Failure는 Load Balancer 지만, Load Balancer 자체도 HA를 지원하는 점.
Control Plane Node의 State가 모두 같음으로 Session Stickyness와 같은 복적성이 없다는 점.
이 장점이다.
다만, etcd에 Duplication들이 있어서, 용량의 낭비가 있어 보이나, HA = Duplication 인점 잊지말자.Kube API Server는 HA를 위한 별도 구성을 제공하지 않는다.
또한 State 정보를 갖지 않고 Backend로 etcd에 모든 State정보를 저장하는 Stateless Server다.
따라서 Kubernetes의 HA는 States(Data) Consistency는 etcd의 Clustering에 의해 제공되고 Singe Access Point는 External Loadbalancer를 통해 제공된다.
그외 API Server의 API를 Consume하는 Client들은 모두 독립적으로 Polling을 통해 동작하기 때문에, Client들은 독립적이다.
위 그림을 보면 apiserver, controller-manager, scheduler, etcd는 동일 서버내에서 동작하고, K8S System내에서의 통신이다.
따라서 하나의 Private CA로 구성시 문제가 없고, 오히려 운영 대상이 일원화 되어 유지보수가 더 간단해 진다.
또한 앞서 이야기 했듯이 동일 서버에서 동작하기 때문에 인증정보를 File로 공유하기 용의하다.
kubeadm은 인증 정보를 File로 사전에 합의된 Path를 통해 관리하고, 스스로 Single Private CA (cn = kuberentes)를 생성하여 인증서를 스스로 발급한다.
아래는 control plane node에 저장되는 인증서 Directory 구조다. (/etc/kubernetes/pki)
해당 Directory에는 apiserver와 etcd가 사용하는 Server/Cleint/Peer(etcd clustering에 필요) 인증서가 저장되어 있고,
K8S Control Plane이 제공하는 Service Account에 포함하는 Token Verification에 사용되는 공개키쌍이 포함되어 있다.(sa.key 와 sa.pub)
ca.crt가 private CA로, control plane Server/Client들이 사용하는 Single private CA다.
참고로, api server는 kubectl를 통해 외부에서도 접근할 수 있어야 한다.
이때 private CA를 사용하기 때문에, OS level에서는 private CA를 검즐 할 수 없으나, 통상 kubectl이라는 특별한 Client를 통해서만 접근하고,
kube config에 K8S가 사용하는 private CA를 명시적으로 포함하기 때문에, 사용상 어려움은 없다.
apiserver의 client들 (controller manager. kubelet등)이 사용하는 Client 인증서는 /etc/kubernetes/ 에 Kubeconfig 형태로 저장된다.
Kubeconfig에는 api server의 주소, CA정보 및 Client Certificate와 Key와 같은 필요한 모든 정보가 포함된다.
아래는 control node에 설치된 client들이 사용하는 kubeconfig 파일이다.
kubeadm 을 사용하여 K8S를 설치하는 경우, master node중 하나에서 먼저 kubeadm init 명령어을 실행하고 되고 Kubeadm은 필요한 인증서를 생성 한다.
그 후 다른 node들에서 kuebadm join명령어를 실핼하게 되는 데,
이때 kubeadm인 최초 init 명령이 실행된 node에서 CA(ca.crt, ca,key)와 Service Account Token Key(sa.pub, sa.key)를 복사후에 필요한 인증정보를 각각 생성한다.
위 언급된 Directory에는 Kubelet에 대한 인증서 구조가 나와 있지 않다.
kubeadm은 kubelet을 통해 container runtime을 제어하여 필요한 control plane을 K8S 설치전 container로 설치한다.
이를 static pod라 한다. kubelet이 다른 K8S의 구성요소들의 관리하는 셈이다.
그럼 Kubelet은 누가 관리하는가? Kubelet은 systemd와 같은 OS level의 Deamon관리 도구를 통해 실행된다.
Kubelet의 인증서는 Kubelet에 설치되는 Node별로 Kubelet 재 부팅시 Kubelet Server인증을 위한 CA부터 인증서까지 별도로 만들어진다.
인증정보는 /var/lib/kubelet/pki에 존재한다.
실제로 Kubelet의 Client는 kube api server가 유일한다. 현재 kube api server의 설정은 Default로 kubelet의 Server인증서를 검증하지 않는다.
이는 보안 구멍 이긴 한지만, kubeadm으로 기본설치시에도 이 상태로 적용된다.
만약 Kubelet의 서버인증서를 검증하게 하기 위해서는 별도로 Kube api server의 설정을 바꾸고, 인증서 관리를 별도로 구축 해줘야 한다.
https://kubernetes.io/docs/concepts/architecture/control-plane-node-communication/
위 경로에 보면 Kubelet에 kube api server에 연결할때 사용되는 client인증서가 있다.
이는TLS bootstrapping 기능을 통해 동적으로 kube api server로 부터 받아온다. (위 구조를 보면 자동으로 갱신 된것을 볼 수 있다.).
이때 Client인증서는 kube api server의 서버인증에 사용된 CA를 통해 발행되는데, kubeadm join 과정에서 CA를 control plane node로 부터 확보한다.
아래 Kubelet 설정에서 Client 인증용 CA파일의 위치가 kubeadm이 관리하는 인증서 directory(/etc/kuberentes/pki)와 같음을 알 수 있다.
kubeadm으로 설치한 경우 CA는 10년, 각 Server/Client인증서는 1년의 유효기간을 가지고 있다. 따라서 보통의 경우 CA가 아닌 인증서에 대한 갱신이 필요하다.
앞서 언급했 듯 이, Kuberentes를 구성하는 3개의 서버 중, Kubelet의 서버인증서의 경우는 결국은 사용되지 않는다.
따라서 etcd와 kube api server의 인증서만 update해면 된다.이는 kubeadm cert renew명령을 모든 node에서 실행 함으로 자동 갱신가능하다.
갱신된 인증서는 각 Server/Client 부팅 시 읽어서 사용됨으로, control plane node의 경우, 순차적으로 static pod를 재기동 시켜야 한다.
다소 장황한 글이었다. 결론은 서두에 언급했듯이, 현재 대부분의 Kubernetes는 kubeadm으로 배포되고, kubeadm은 인증서 갱신기능도 제공하니, 잘 만들어진 툴을 사용하면 된다.
하지만, 보안이라는 것이 보안 기능 자체를 아는것에서 끝이 아니라 보안이 적용되는 시스템에 대한 이해도 해야 두려움이 없어지는 법이고 기억에 오래 남는다.
이글을 통해 인증서 만료시 너무 당황하거나, 문제 발생 시 허둥지둥 되지 않고 여러 가지 억측과 참견(?)에 의해 돌고도는 물래방아같은 인생이 되지 않길 기대한다.
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.