1. Security 기본
kubernetes 는 다양한 요소가 모여있는 만큼 인증이 여러가지가 있다.
kubernetes의 모든 중심에는 kube-apiserver가 있다.
따라서 1차적으로 API 서버 자체에 대한 엑세스를 제어하는 방법이 있다.
클러스터와의 모든 통신 구성요소들은 TLS 암호화로 구성되어 있다.
애플리케이션은 네트워크 정책에 따라 제어할 수 있다.
클러스터 액세스 권한
kubernetes 는 사용자 계정을 직접 관리하지 않는다. 외부 source에 의존한다.
api 서버에 사용자를 간단히 등록하는 방법이 있지만 권장하지 않는다.
2. TLS 인증이란
인증서는 상호 신뢰를 보장하기 위해서 사용된다.
공부하다 보니 헷갈리는 부분이 있었는데, 바로 잡고 가보자.
일단 서버와 클라이언트간의 통신 ( 예 : 웹 통신) 과 SSH 접속하여 통신하는 건 다른 것이다.
하나로 묶어서 설명하겠다.
그림과 같이 클라이언트와 관리자, 웹서버가 있다.
- 관리자는 한 쌍의 키로 서버 SSH 연결을 한다.
SSH 접속 시 인증 방법은 아래와 같다.
관리자는 ssh-keygen을 통해 개인키와 공개키 쌍을 생성한다.
ssh-keygen
사용자는 생성된 공개 키를 서버에 등록하게 된다.
이를 위해 보통은 ssh-copy-id 명령어를 사용하거나, 직접 공개 키 내용을 서버의 ~/.ssh/authorized_keys 파일에 복사한다.
ssh-copy-id 사용자명@서버주소 cat ~/.ssh/id_rsa.pub | ssh 사용자명@서버주소mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys
이 과정에서 서버는 사용자의 공개 키로 암호화된 데이터를 개인 키를 가진 사용자만이 복호화할 수 있도록 한다.
공개 키가 서버에 등록되면, 사용자는 서버에 비밀번호 없이 접속할 수 있게 됩니다. 이 때, 클라이언트는 개인 키를 사용하여 서버와 안전하게 통신한다.
ssh 사용자명@서버주소
- 서버는 한 쌍의 키로 https 트래픽을 확보한다.
이 경우 서버는 먼저 CSR을 생성한다.
CSR은 서버의 공개 키 등을 포함하고 있다. (이 과정에서 서버 개인키도 생성된다.)
서버 개인키로 CSR 에 서명한다.
CA(Certificate Authority) 에 CSR을 제출하여 인증서 발급을 요청 한다.
그리고 인증서는 CA 개인키로 묶어서 다시 서버로 보내진다.
(모든 사용자는 CA 퍼블릭 키의 복사본을 가지고 있다.)
사용자가 웹서버에 액세스 할 때마다 서버는 먼저 공개키로 인증서를 사용자에게 보낸다.
사용자는 CA 공용키를 가지고 해당 인증서를 확인한다.
그러면 그 안에 서버의 공개키(아까 서명할 때 쓴)가 포함되어 있다.
그 다음 사용자가 작성한 내용이 서버의 공개키로 암호화 되어 서버로 전송된다.
서버는 개인키로 메시지를 해독한다.
3. TLS 인증서를 이용한 Kubernetes 클러스터 보안
알면 좋은 상식 :
Public Key : 보통 .crt, .pem 확장자
Private Key : 보통 .key, key.pem 확장자
kubernetes 클러스터는 master와 worker node 집합으로 이루어져 있다.
이 노드 사이의 통신은 보안이 필요하고 또한 모든 서비스와 고객간, kubernetes와 관리자 간의 보안들도 필요하다.
kube-API SERVER 는 HTTPS 서비스를 사용한다. 그래서 인증서와 키페어를 생성한다.
ETCD SERVER와 KUBELET SERVER 도 마찬가지다.
엄~~청 많다.
이런 인증서들을 CA가 관리해줘야하는데, 클러스터 내의 보안 통신을 위해 자체 CA를 사용하여 인증서를 관리하고 발급한다
4. 클러스터 보안을 위한 인증서 생성
여러가지 방법이 있지만 가장 보편적인 OpenSSL 도구를 사용해 인증서를 생성하는 방식을 설명하겠다.
먼저 OpenSSL 명령을 이용해 Private key를 생성한다.
openssl genrsa -ou ca.key 2048
OpenSSL을 사용하여 CSR 생성
openssl req -new -key ca.key -subj "/CN-KUBERNETES-CA" -out ca.csr
OpenSSL x509를 사용하여 인증서에 서명
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
이제 클라이언트(관리자가 될 수도 있다)가 인증서 생성하는 방식이다.
개인키를 생성한다.
openssl genrsa -out admin.key 2048
CSR을 생성 ( “system:masters” 그룹 )
openssl req -new -key admin.key -subj "/CN=kube-admin/O=system:masters" -out admin.csr
서명된 인증서 생성, 이때 CA인증서와 CA키를 지정해서 생성한다.
openssl x509 -req -in admin.csr -CA ca.crt -CAkey ca.key -out admin.crt
이렇게 생성한 인증서들을 복사해서 여러 옵션에 넣고 사용할 수 있다.
5. csr을 통한 인증과정
CSR을 통한 인증 과정은 다음과 같다
- 클라이언트가 자신의 인증서를 생성한다.
- 클라이언트는 생성한 CSR을 Kubernetes API 서버에 제출한다. 이때, 위에서 제시한 방법처럼 CertificateSigningRequest 객체를 생성하여 제출한다.
- Kubernetes API 서버는 CSR을 받고 확인한다.
- 클러스터 관리자는 CSR을 승인하거나 거부한다.
- CSR이 승인되면 Kubernetes API 서버는 클라이언트에 대한 인증서를 발급한.
- 클라이언트는 발급받은 인증서를 사용하여 Kubernetes 클러스터에 접근하고 리소스를 사용할 수 있다.
문제
“akshay.csr” 파일의 내용을 사용해서
이름이 “akshay”인 CertificateSigningRequest 객체를 생성해라.
CSR을 생성할 때 추가 필드인 signerName을 지정해라.
API 서버에 대한 클라이언트 인증에는 내장된 서명자 kubernetes.io/kube-apiserver-client를 사용해라.
풀이
akshay-csr.yaml 파일안에
apiVersion: certificates.k8s.io/v1kind: CertificateSigningRequestmetadata: name: akshayspec: request: <base64-encoded-contents-of-akshay.csr> signerName: kubernetes.io/kube-apiserver-client
<base64-encoded-contents-of-akshay.csr> 부분에는 “akshay.csr” 파일의 내용을 Base64로 인코딩한 값이 들어가야 한다.
docs에서 csr 부분에서 찾아서 yaml 파일을 생성
controlplane ~ ➜ cat > akshay.yamlapiVersion: certificates.k8s.io/v1kind: CertificateSigningRequestmetadata: name: myuserspec: request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZqQ0NBVDRDQVFBd0VURVBNQTBHQTFVRUF3d0dZVzVuWld4aE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRgpBQU9DQVE4QU1JSUJDZ0tDQVFFQTByczhJTHRHdTYxakx2dHhWTTJSVlRWMDNHWlJTWWw0dWluVWo4RElaWjBOCnR2MUZtRVFSd3VoaUZsOFEzcWl0Qm0wMUFSMkNJVXBGd2ZzSjZ4MXF3ckJzVkhZbGlBNVhwRVpZM3ExcGswSDQKM3Z3aGJlK1o2MVNrVHF5SVBYUUwrTWM5T1Nsbm0xb0R2N0NtSkZNMUlMRVI3QTVGZnZKOEdFRjJ6dHBoaUlFMwpub1dtdHNZb3JuT2wzc2lHQ2ZGZzR4Zmd4eW8ybmlneFNVekl1bXNnVm9PM2ttT0x1RVF6cXpkakJ3TFJXbWlECklmMXBMWnoyalVnald4UkhCM1gyWnVVV1d1T09PZnpXM01LaE8ybHEvZi9DdS8wYk83c0x0MCt3U2ZMSU91TFcKcW90blZtRmxMMytqTy82WDNDKzBERHk5aUtwbXJjVDBnWGZLemE1dHJRSURBUUFCb0FBd0RRWUpLb1pJaHZjTgpBUUVMQlFBRGdnRUJBR05WdmVIOGR4ZzNvK21VeVRkbmFjVmQ1N24zSkExdnZEU1JWREkyQTZ1eXN3ZFp1L1BVCkkwZXpZWFV0RVNnSk1IRmQycVVNMjNuNVJsSXJ3R0xuUXFISUh5VStWWHhsdnZsRnpNOVpEWllSTmU3QlJvYXgKQVlEdUI5STZXT3FYbkFvczFqRmxNUG5NbFpqdU5kSGxpT1BjTU1oNndLaTZzZFhpVStHYTJ2RUVLY01jSVUyRgpvU2djUWdMYTk0aEpacGk3ZnNMdm1OQUxoT045UHdNMGM1dVJVejV4T0dGMUtCbWRSeEgvbUNOS2JKYjFRQm1HCkkwYitEUEdaTktXTU0xMzhIQXdoV0tkNjVoVHdYOWl4V3ZHMkh4TG1WQzg0L1BHT0tWQW9FNkpsYWFHdTlQVmkKdjlOSjVaZlZrcXdCd0hKbzZXdk9xVlA3SVFjZmg3d0drWm89Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo= signerName: kubernetes.io/kube-apiserver-client expirationSeconds: 86400 # one day usages: - client auth^C controlplane ~ ✖ lsakshay.csr akshay.key akshay.yaml
이제 akshay.csr 을 base64 로 인코딩 한 값을 넣어준다.
controlplane ~ ➜ cat akshay.csr | base64 -w 0LS0tLS1CRUdJ.......................S0tLQo=
yaml 파일 수정
controlplane ~ ➜ vi akshay.yaml apiVersion: certificates.k8s.io/v1kind: CertificateSigningRequestmetadata: name: akshay (이렇게 수정)spec: request: 여기 수정 signerName: kubernetes.io/kube-apiserver-client expirationSeconds: 86400 # one day usages: - client auth
적용
controlplane ~ ➜ kubectl apply -f akshay.yaml certificatesigningrequest.certificates.k8s.io/myuser created
6. Security Kubeconfig
매번 입력하면서 같은 정보를 명시할 필요 없이 kubeconfig 구성파일을 사용하자.
apiVersion: v1kind: Config clusters:- cluster: proxy-url: http://proxy.example.org:3128 server: https://k8s.example.org/k8s/clusters/c-xxyyzz name: development users:- name: developer contexts:- context: name: development