Skip to main content Link Menu Expand (external link) Document Search Copy Copied

쿠버네티스 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 서버에 접근할 수 있도록 설정한 후,

올바르게 설정되었는지 확인할 수 있다.