개요
k8s에서 어떻게 상호 인증을 하는지 알아보겠습니다.
사전 필수 지식
[CKA] 35. Security - TLS통신 이해를 위한 PKI 기본 지식
상호 인증 원리
k8s에 있는 여러 service(apiserver, etcd, kubelet ...) 들은 상호 인증을 위해서 인증서와 개인키를 사용합니다.
service 별 인증서
아래 그림은 service별 인증서(*.crt) 및 개인키(*. key)를 분리해 놓은 자료입니다.
위 그림에서 모든 인증서 admin.crt, scheduler.crt, controller-manager.crt, kube-proxy.crt 등등은 모두ca.crt 와 ca.key를 사용하여 전자 서명이 되어있습니다.
admin.crt 생성 과정
모든 인증서 생성과정은 이름만 변경될뿐 모두 동일한 방식으로 생성이 됩니다.
그리고 인증서의 실제 위치는 위치는 다음과 같습니다.
실제 위치
controlpane에서 인증서 위치
/etc/kubernets/pki에 존재합니다.
kubelet 인증서 위치
/var/lib/kubelet/pki 에 존재합니다.
여기서 보면 kubelet-client는 crt, 과 key가 존재하는 것이 아니라 pem으로 존재하는데요. 이 파일은 crt와 key을 합쳐 놓은 파일입니다.
인증서 및 개인 키의 필요성
클라이언트와 서버 간의 상호 인증을 하는데 사용이 됩니다. 이렇게 되면 따로 인증 체계를 만들 이 않아도 되는 장점이 존재합니다.
그러나 인증서가 털리면 다 뚫리는 상황도 발생합니다. k8s에서의 인증서 및 개인키의 역할은 아래의 개념처럼 이해하면 좋습니다
certificate == User ID
private key == password
그러면 이번에는 인증서와 개인키로 가지고 실제로 정상적올 apiserver와 통신이 되는지 확인을 해보겠습니다.
통신 테스트
명령어는 아래와 같고, 통신 테스트는 woker node에서 진행하겠습니다.
curl https://192.168.0.26:6443/api/v1/namespaces/default/pods --cert /var/lib/kubelet/pki/kubelet-client-current.pem --cacert /etc/kubernetes/pki/ca.crt
위 명령을 실행하기 위해서 우리는 3가지 정보를 알아야 합니다.
1. controlplane의 apiserver 정보
2. kubelet-client 인증서 위치
3. ca 인증서 위치
controlplane의 apiserver 정보
controlplane의 IP와 port 그리고 지원하는 api, 지원하는 API는 https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#api-overview 에서 확인이 가능합니다. 저는 여기서 pods 정보만 가져오는 api를 사용하겠습니다.
https://192.168.0.26:6443/api/v1/pods
kubelet-client 인증서 위치
/etc/kubernetes/kubelet.conf 이 파일의 마지막줄에 나와있습니다.
인증서의 파일명이 crt가 아니고 kubelet-client-current.pem인 이유는 이 파일 안에는 인증서와 개인키가 들어가 있기 때문입니다.
그래서 인증서와 개인키의 파일명이 동일합니다.
인증서 확인
root@master:/var/lib/kubelet/pki# cat kubelet-client-2023-01-16-22-52-13.pem
-----BEGIN CERTIFICATE-----
MIIDITCCAgmgAwIBAgIIHegmr52Po6cwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
.... 생략 ....
m+V0S9tY2d3FDif47c235WIbtZiT9PfBm1JnZx/UNj+owbMKAg==
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA0IXuM57aRZMyfmYwoKghvEQ0VAUf8zcn7BW9EtfT+PensonX
.... 생략 ....
iAEU3poL4RAi34UknKrytpY3MJLgYs0cVpdhWZNift3syyH3/Xf9
-----END RSA PRIVATE KEY-----
ca 인증서 위치
/etc/kubernetes/pki 에 존재합니다.
통신 검증
그럼 이제 통신에 필요한 모든 정보를 알아냈으니 아래 명령을 실행해 보겠습니다.
curl https://192.168.0.26:6443/api/v1/namespaces/default/pods --cert /var/lib/kubelet/pki/kubelet-client-current.pem --cacert /etc/kubernetes/pki/ca.crt
통신이 잘되고 Pod list의 정보가 잘 나옵니다.
이를 통해서 알 수 있는 것은 apiserver와 통신을 위해서는 k8s에서 제공하는 ca.crt로 인증된 인증서가 필요하다입니다.
그럼 지금 까지는 잘되는 환경을 테스트하였으니 잠시 인증서에 문제가 있을 때 어떻게 처리해야 하는지 알아보겠습니다.
인증서 정보확인 방법
openssl x509 -in {인증서} -text -noout
주요 정보
Issuer
인증서 발행자의 정보
Validity
Not Before: [시작 날짜]
Not After : [만료 날짜]
유효기간
Subject
인증서 주체의 정보
X509v3 Subject Alternative Name
(주로 SAN, SubjectAltName로 알려짐)은 X.509 인증서에 포함된 확장 필드 중 하나입니다. SAN은 주체의 추가 식별 정보를 제공하는 데 사용되며, 주로 여러 도메인 이름이나 IP 주소를 하나의 인증서에 연결할 때 사용됩니다.
예제
openssl x509 -in apiserver.crt -text -noout
root@master:/etc/kubernetes/pki# openssl x509 -in apiserver.crt -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 6064824178665716266 (0x542a95752a91fa2a)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = kubernetes
Validity
Not Before: Jan 16 13:52:10 2023 GMT
Not After : May 4 13:48:03 2024 GMT
Subject: CN = kube-apiserver
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:a5:10:67:70:af:76:8c:13:00:80:e1:c6:51:0f:
... 생략 ...
d9:36:c6:2e:4f:34:6c:70:63:c0:07:49:03:3f:fb:
0d:ad
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Authority Key Identifier:
keyid:39:00:D7:1A:58:4A:C0:55:72:D6:BC:C5:36:0A:82:8F:85:7D:F7:C3
X509v3 Subject Alternative Name:
DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:master, IP Address:10.96.0.1, IP Address:192.168.0.26
Signature Algorithm: sha256WithRSAEncryption
03:3c:dd:20:3d:94:28:17:89:2e:2d:f4:64:98:d6:8f:c2:76:
... 생략 ...
4f:08:60:b4
service 별 인증서 관련 설정
k8s에서 존재하는 service 별 yaml 파일에서의 인증서 관련 설정 정보
apiserver
파일 명
/etc/kubernetes/manifests/kube-apiserver.yaml
인증 설정
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.0.26
- --allow-privileged=true
- --authorization-mode=Node,RBAC
- --client-ca-file=/etc/kubernetes/pki/ca.crt
- --enable-admission-plugins=NodeRestriction
- --enable-bootstrap-token-auth=true
- --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
# etcd에서 사용하는 ca 인증서
- --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
# apiserver가 etcd server에 접근할때 사용하는 인증서
- --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
# apiserver가 etcd server에 접근할때 사용하는 개인키
- --etcd-servers=https://127.0.0.1:2379
- --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
# apiserver가 kubelet server에 접근할때 사용하는 인증서
- --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
# apiserver가 kubelet server에 접근할때 사용하는 개인키
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
# apiserver가 api aggregation layer에 연결할 때 사용하는 사용하는 인증서
- --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
# apiserver가 api aggregation layer에 연결할 때 사용하는 사용하는 개인키
- --requestheader-allowed-names=front-proxy-client
- --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
- --requestheader-extra-headers-prefix=X-Remote-Extra-
- --requestheader-group-headers=X-Remote-Group
- --requestheader-username-headers=X-Remote-User
- --secure-port=6443
- --service-account-issuer=https://kubernetes.default.svc.cluster.local
- --service-account-key-file=/etc/kubernetes/pki/sa.pub
- --service-account-signing-key-file=/etc/kubernetes/pki/sa.key
- --service-cluster-ip-range=10.96.0.0/12
- --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
#apiserver가 service를 위해서 사용하는 인증서
- --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
#apiserver가 service를 위해서 사용하는 개인키
etcd
파일 명
/etc/kubernetes/manifests/etcd.yaml
인증 설정
spec:
containers:
- command:
- etcd
- --advertise-client-urls=https://192.168.0.26:2379
- --cert-file=/etc/kubernetes/pki/etcd/server.crt
#etcd가 사용하는 인증서
- --client-cert-auth=true
- --data-dir=/var/lib/etcd
- --experimental-initial-corrupt-check=true
- --experimental-watch-progress-notify-interval=5s
- --initial-advertise-peer-urls=https://192.168.0.26:2380
- --initial-cluster=master=https://192.168.0.26:2380
- --key-file=/etc/kubernetes/pki/etcd/server.key
#etcd가 사용하는 개인키
- --listen-client-urls=https://127.0.0.1:2379,https://192.168.0.26:2379
- --listen-metrics-urls=http://127.0.0.1:2381
- --listen-peer-urls=https://192.168.0.26:2380
- --name=master
- --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt
- --peer-client-cert-auth=true
- --peer-key-file=/etc/kubernetes/pki/etcd/peer.key
- --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
- --snapshot-count=10000
- --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
#etcd가 사용하는 root ca 인증서
정리
k8s에서는 상호인증을 하기 위해서 인증서와 개인키를 사용합니다. 여기서 인증서는 ID의 역할, 개인키는 password의 역할을 합니다.
그리고 모든 service는 자신들만의 인증서 및 개인키를 가지고 있으며 모든 인증서는 ca 인증서와, ca 개인키로 전자 서명되어 있습니다.
Next Post
[CKA] 38. k8s에서 사용자 추가 및 권한 제어
'Cloud > k8s-CKA' 카테고리의 다른 글
[CKA] 39. kubeconfig 구조 분석 및 관리 (0) | 2023.10.26 |
---|---|
[CKA] 38. k8s에서 사용자 추가 및 권한 제어 (0) | 2023.10.15 |
[CKA] 36. Security - TLS 통신과정 (0) | 2023.09.21 |
[CKA] 35. Security - TLS통신 이해를 위한 PKI 기본 지식 (0) | 2023.09.17 |
[CKA] 34. volume 과 PV 그리고 PVC (0) | 2023.09.03 |