쿠버네티스 x.509 인증서 실습
docker exec -it myk8s-control-plane ls -l /etc/kubernetes/pki
total 56
-rw-r--r-- 1 root root 1123 Mar 15 17:33 apiserver-etcd-client.crt
-rw------- 1 root root 1679 Mar 15 17:33 apiserver-etcd-client.key
-rw-r--r-- 1 root root 1176 Mar 15 17:33 apiserver-kubelet-client.crt
-rw------- 1 root root 1679 Mar 15 17:33 apiserver-kubelet-client.key
-rw-r--r-- 1 root root 1326 Mar 15 17:33 apiserver.crt
-rw------- 1 root root 1675 Mar 15 17:33 apiserver.key
-rw-r--r-- 1 root root 1107 Mar 15 17:33 ca.crt
-rw------- 1 root root 1679 Mar 15 17:33 ca.key
drwxr-xr-x 2 root root 162 Mar 15 17:33 etcd
-rw-r--r-- 1 root root 1123 Mar 15 17:33 front-proxy-ca.crt
-rw------- 1 root root 1675 Mar 15 17:33 front-proxy-ca.key
-rw-r--r-- 1 root root 1119 Mar 15 17:33 front-proxy-client.crt
-rw------- 1 root root 1675 Mar 15 17:33 front-proxy-client.key
-rw------- 1 root root 1675 Mar 15 17:33 sa.key
-rw------- 1 root root 451 Mar 15 17:33 sa.pub
CA 인증서 내용 확인
docker exec -it myk8s-control-plane openssl x509 -in /etc/kubernetes/pki/ca.crt -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 5754887193385032258 (0x4fdd77696428da42)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = kubernetes
Validity
Not Before: Mar 15 17:28:12 2025 GMT
Not After : Mar 13 17:33:12 2035 GMT
Subject: CN = kubernetes
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
- X.509 v3는 확장 필드를 추가할 수 있어 CA 인증서로 사용 가능하며, CA에서 발급하는 각 인증서는 고유한 시리얼 넘버를 가져야 한다.
- 이 인증서는 SHA-256 + RSA를 사용하여 서명되었음으며, 자기 자신을 발급자(Issuer)로 설정(CN = kubernetes)하는 Self-Signed 인증서임을 확인할 수 있다.
이 인증서는 2025년 3월 15일부터 2035년 3월 13일까지 유효하며, CA 인증서는 장기간 유효하도록 설정되지만 일반적으로 노드 인증서는 더 짧은 유효 기간을 가진다.
인증서의 대상(Subject)으로 쿠버네티스가 설정되고 이 인증서가 클러스터 인증을 위해 사용된다. RSA 2048-bit 공개 키를 사용하여 클라이언트가 신뢰할 수 있는 인증서를 확인할 수 있도록 한다.
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment, Certificate Sign
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
5B:71:6E:8E:5E:0B:63:0D:42:F8:A1:37:B8:2B:A1:54:60:74:60:8A
X509v3 Subject Alternative Name:
DNS:kubernetes
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
xx:yy:zz..~~
인증서는 critical로 선언된 용도로만 사용이 가능하다.
- Digital Signature: 디지털 서명 생성 가능
- Key Encipherment: 키 암호화 가능
- Certificate Sign: 이 인증서는 다른 인증서를 서명할 수 있는 CA 역할
쿠버네티스에서 클러스터의 모든 구성 요소가 이 CA를 신뢰하도록 설정되고, 인증서의 고유한 해시값을 통해 다른 인증서들이 이 값을 사용하여 신뢰할 CA인지 확인할 수 있다.
클러스터 내부에서 API 서버를 호출할 때, “kubernetes”라는 이름을 사용하면 이 인증서를 검증할 수 있다. 클라이언트가 이 CA를 검증할 때 발급자의 공개 키를 사용하여 서명을 확인하여 인증을 수행한다.
CSR 내용 확인
kubectl get certificatesigningrequests
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
csr-txkc6 11m kubernetes.io/kube-apiserver-client-kubelet system:node:myk8s-control-plane <none> Approved,Issued
kubectl describe certificatesigningrequests
Name: csr-txkc6
Labels: <none>
Annotations: <none>
CreationTimestamp: Sun, 16 Mar 2025 02:33:26 +0900
Requesting User: system:node:myk8s-control-plane
Signer: kubernetes.io/kube-apiserver-client-kubelet
Status: Approved,Issued
Subject:
Common Name: system:node:myk8s-control-plane
Serial Number:
Organization: system:nodes
Events: <none>
myk8s-control-plane 노드가 Kubelet 인증서를 요청했고 관리자가 이를 승인하여 발급된 상태이다.
이 csr을 좀 더 상세히 살펴보면, “myk8s-control-plane” 노드의 Kubelet 인증서를 위한 것이며 노드가 클러스터에 참여하기 위해 Kube API Server와 인증을 수행하려는 목적을 가지고 있다.
kubernetes.io/kube-apiserver-client-kubelet은 API 서버가 Kubelet의 클라이언트 인증서를 승인하는 기본 Signer이다. Kube API Server가 이 csr을 승인하면, Kubelet이 API Server와 안전하게 통신할 수 있도록 인증서를 발급받는다.
이 인증서를 통해 kubelet이 api 서버와 정상적으로 통신을 진행할 수 있다.
kubeconifg 인증서
echo "LS0tLS1CR..." | base64 -d > myuser.key
cat myuser.key
이 키는 client-certificate-data에 대응하는 개인 키로, kubernetes-admin 사용자가 API 서버에 인증할 때 사용한다.
openssl x509 -in myuser.crt -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1412884469959843802 (0x139b92f08c9f5fda)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=kubernetes
Validity
Not Before: Mar 15 17:28:12 2025 GMT
Not After : Mar 15 17:33:12 2026 GMT
Subject: O=kubeadm:cluster-admins, CN=kubernetes-admin
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Authority Key Identifier:
keyid:5B:71:6E:8E:5E:0B:63:0D:42:F8:A1:37:B8:2B:A1:54:60:74:60:8A
Signature Algorithm: sha256WithRSAEncryption
client-certificate-data 값은 클라이언트 인증서로, 특정 사용자가 Kubernetes API 서버에 인증하는 데 사용된다.
- name: kind-myk8s
user:
client-certificate-data: LS~
client-key-data: LS~
kube config를 보면 client-certificate-data와 client-key-data가 있는데,
client-certificate-data 는 클라이언트 인증서로, 특정 사용자가 Kubernetes API 서버에 인증하는 데 사용되며
client-key-data 는 클라이언트 개인 키(Private Key)로 client-certificate-data에 대응하는 개인 키이다.
cat $HOME/.kube/config
certificate-authority-data: LS
이 인증서는 Kubernetes 클러스터에서 API 서버가 신뢰하는 Root CA 인증서로 사용된다.
kubernetes-admin 사용자는 client-certificate-data와 client-key-data를 이용하여 API 서버와 TLS 인증을 수행하고,
certificate-authority-data를 통해 API 서버를 신뢰할 수 있게 된다.
CSR을 활용한 신규 사용자 인증
openssl genrsa -out $USER.key 2048
openssl req -new -key $USER.key -out $USER.csr -subj "/O=kubeadm:cluster-admins/CN=$USER-cert"
Kubernetes API 서버에 제출할 인증서 서명 요청(CSR) 생성한다.
cat $USER.csr | base64 | tr -d '\n'
로 나오는 값 복사!
kubectl apply -f - <<EOF
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: $USER-csr
spec:
signerName: kubernetes.io/kube-apiserver-client
groups:
- system:masters
- system:authenticated
request: LS...
usages:
- digital signature
- key encipherment
- client auth
EOF
Kubernetes에 CSR을 제출하여 인증서를 요청한다
k get csr
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
csr-txkc6 52m kubernetes.io/kube-apiserver-client-kubelet system:node:myk8s-control-plane <none> Approved,Issued
nana-csr 4s kubernetes.io/kube-apiserver-client kubernetes-admin <none> Pending
kubectl certificate approve nana-csr
certificatesigningrequest.certificates.k8s.io/nana-csr approved
kubectl get csr
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
csr-txkc6 56m kubernetes.io/kube-apiserver-client-kubelet system:node:myk8s-control-plane <none> Approved,Issued
nana-csr 4m30s kubernetes.io/kube-apiserver-client kubernetes-admin <none> Approved,Issue
관리자가 CSR을 승인하여 인증서 발급을 요청한다.
kubectl get csr nana-csr -o jsonpath='{.status.certificate}' | base64 -d > nana.crt
kubectl get csr nana-csr -o jsonpath='{.status.certificate}' | base64 -d > nana.crt
openssl x509 -in nana.crt -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
...
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=kubernetes
Validity
Not Before: Mar 15 18:24:42 2025 GMT
Not After : Mar 15 18:24:42 2026 GMT
Subject: O=kubeadm:cluster-admins, CN=nana-cert
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
...
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Authority Key Identifier:
keyid:...
cat ~/.kube/config
...
- name: nana
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- --region
- ap-northeast-2
- eks
- get-token
- --cluster-name
- myeks
- --output
- json
command: aws
env: null
interactiveMode: IfAvailable
provideClusterInfo: false
- name: nana-user
user:
client-certificate: /root/nana.crt
client-key: /root/nana.key
kubectl config set-credentials nana-user --client-certificate=nana.crt --client-key=nana.key
kubectl config set-context kind-nana --cluster=kind-myk8s --user=nana-user
cat ~/.kube/config
kubectl config use-context kind-
kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* kind-nana kind-myk8s nana-user
k get node
NAME STATUS ROLES AGE VERSION
myk8s-control-plane Ready control-plane 63m v1.32.2
이제 새로운 사용자를 클러스터에 등록하고 해당 사용자가 Kubernetes API 서버에 접근할 수 있도록 설정한 후,
올바르게 설정되었는지 확인할 수 있다.