이 글은 CloudNet@팀의 AWS EKS Workshop Study(AEWS) 3기 스터디 내용을 바탕으로 작성되었습니다.
AEWS는 CloudNet@의 '가시다'님께서 진행하는 스터디로, EKS를 학습하는 과정입니다.
EKS를 깊이 있게 이해할 기회를 주시고, 소중한 지식을 나눠주시는 가시다님께 다시 한번 감사드립니다.
이 글이 EKS를 학습하는 분들께 도움이 되길 바랍니다.
운영 서버에서 EC2 인스턴스의 공인 IP를 확인한 후 SSH 접속을 수행합니다.
# 노드 IP 확인
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table
ssh -i <your-key.pem> ec2-user@<PublicIP>
Kubernetes 이벤트 모니터링을 위한 inotify 설정을 조정합니다.
이는 Kubernetes가 다수의 파일 변경 이벤트를 감지할 수 있도록 리소스 제한을 늘려주는 역할을 합니다.
sudo sysctl fs.inotify.max_user_watches=524288
sudo sysctl fs.inotify.max_user_instances=512
kind는 Docker 컨테이너 안에서 Kubernetes 클러스터를 실행하는 도구입니다.
이를 통해 로컬 개발 및 테스트 환경을 손쉽게 구축할 수 있습니다.
kind create cluster --name myk8s

Kubernetes는 보안 강화를 위해 클러스터의 주요 구성 요소 간의 통신을 TLS(Transport Layer Security)로 보호합니다.
각 구성 요소의 신뢰성을 검증하기 위해 다양한 인증서가 필요하며, 이를 /etc/kubernetes/pki/ 경로에서 확인할 수 있습니다.
docker exec -it myk8s-control-plane ls -l /etc/kubernetes/pki
-rw-r--r-- 1 root root 1123 Mar 7 13:34 apiserver-etcd-client.crt
-rw------- 1 root root 1675 Mar 7 13:34 apiserver-etcd-client.key
-rw-r--r-- 1 root root 1176 Mar 7 13:34 apiserver-kubelet-client.crt
-rw------- 1 root root 1675 Mar 7 13:34 apiserver-kubelet-client.key
-rw-r--r-- 1 root root 1326 Mar 7 13:34 apiserver.crt # 루트인증서로부터 발급된 하위 인증서
-rw------- 1 root root 1675 Mar 7 13:34 apiserver.key
-rw-r--r-- 1 root root 1107 Mar 7 13:34 ca.crt # 루트인증서
-rw------- 1 root root 1675 Mar 7 13:34 ca.key # 루트인증서에 대응하는 비밀키
drwxr-xr-x 2 root root 4096 Mar 7 13:34 etcd
-rw-r--r-- 1 root root 1123 Mar 7 13:34 front-proxy-ca.crt
-rw------- 1 root root 1679 Mar 7 13:34 front-proxy-ca.key
-rw-r--r-- 1 root root 1119 Mar 7 13:34 front-proxy-client.crt
-rw------- 1 root root 1679 Mar 7 13:34 front-proxy-client.key
-rw------- 1 root root 1679 Mar 7 13:34 sa.key
-rw------- 1 root root 451 Mar 7 13:34 sa.pub
주요 인증서 파일

인증서 정보를 직접 확인하여 만료 날짜 및 발급 기관을 검토할 수 있습니다.
docker exec -it myk8s-control-plane cat /etc/kubernetes/pki/ca.crt
docker exec -it myk8s-control-plane openssl x509 -in /etc/kubernetes/pki/ca.crt -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 8736798006158023849 (0x793f577f3f63dca9)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = kubernetes
Validity
Not Before: Mar 7 13:29:06 2025 GMT
Not After : Mar 5 13:34:06 2035 GMT
Subject: CN = kubernetes
...
X509v3 extensions:
X509v3 Key Usage: critical # 클라이언트는 이 키 사용 용도를 반드시 준수
Digital Signature, Key Encipherment, Certificate Sign
# Digital Signature: 인증서가 디지털 서명에 사용됨.
# Key Encipherment: 인증서가 키 암호화(예: TLS에서 세션 키 암호화)에 사용됨.
# Certificate Sign: 이 인증서가 다른 인증서를 서명(즉, CA 역할)할 수 있음. 주로 인증 기관(CA) 인증서에서 사용됨.
X509v3 Basic Constraints: critical # 인증서가 인증 기관(CA) 역할을 할 수 있는지를 나타냄.
CA:TRUE
X509v3 Subject Key Identifier:
32:75:7F:9F:C2:C4:C8:25:8C:04:79:6A:B7:18:84:27:37:E2:4A:75
X509v3 Subject Alternative Name: # 인증서가 적용되는 주체(Subject)의 대체 이름
DNS:kubernetes
...
Signature Value:
18:9b:6f:ad:09:d1:ea:78:4a:3d:b7:93:cc:7e:e2:c1:94:30:
...
docker exec -it myk8s-control-plane cat /etc/kubernetes/pki/apiserver-kubelet-client.crt
docker exec -it myk8s-control-plane openssl x509 -in /etc/kubernetes/pki/apiserver-kubelet-client.crt -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 805610438108720721 (0xb2e1a6cd6d12e51)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = kubernetes
Validity
Not Before: Mar 7 13:29:06 2025 GMT
Not After : Mar 7 13:34:06 2026 GMT
Subject: O = kubeadm:cluster-admins, CN = kube-apiserver-kubelet-client
...
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:
32:75:7F:9F:C2:C4:C8:25:8C:04:79:6A:B7:18:84:27:37:E2:4A:75
인증서 정보 예시




Kubernetes의 클라이언트 인증을 위해 생성된 CSR을 조회합니다.
CSR은 인증서 요청의 일환으로, 관리자가 이를 승인하면 새로운 클라이언트 인증서가 발급됩니다.
kubectl get certificatesigningrequests
# 출력 예시
NAME AGE SIGNERNAME REQUESTOR CONDITION
csr-852t8 4m14s kubernetes.io/kube-apiserver-client-kubelet system:node:myk8s-control-plane Approved,Issued
csr-t8hvk 4m4s kubernetes.io/kube-apiserver-client-kubelet system:bootstrap:abcdef Approved,Issued
kubectl describe certificatesigningrequests csr-852t8
# 출력 예시
Name: csr-852t8
...
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>
Name: csr-t8hvk
...
Requesting User: system:bootstrap:abcdef
Signer: kubernetes.io/kube-apiserver-client-kubelet
Status: Approved,Issued
Subject:
Common Name: system:node:myk8s-worker
Serial Number:
Organization: system:nodes
Events: <none>
주요 정보
system:node:myk8s-control-planekubernetes.io/kube-apiserver-client-kubeletsystem:node:myk8s-control-plane, Organization = system:nodes
CSR이 승인되면 해당 사용자는 클러스터에 대한 인증서를 발급받아 API 서버와의 보안 연결을 수립할 수 있습니다.
kind 설치자의 kubeconfig 파일에서 인증서 정보를 확인합니다.
cat $HOME/.kube/config
# 출력 예시
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0...
server: https://127.0.0.1:50032
name: kind-myk8s
contexts:
- context:
cluster: kind-myk8s
user: kind-myk8s
name: kind-myk8s
current-context: kind-myk8s
kind: Config
preferences: {}
users:
- name: kind-myk8s
user:
client-certificate-data: LS0tL...
client-key-data: LS0tLS1CR....
주요 필드

echo "<base64-encoded-cert>" | base64 -d



vi myuser.crt
-----BEGIN CERTIFICATE-----
MIIDKTCCAhGgAwIBAgIIeKzXmvzBrkswDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
...
#
openssl x509 -in myuser.crt -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 8695562041211072075 (0x78acd79afcc1ae4b)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=kubernetes
Validity
Not Before: Mar 8 12:26:08 2025 GMT
Not After : Mar 8 12:31:08 2026 GMT
Subject: O=kubeadm:cluster-admins, CN=kubernetes-admin
...
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:
BC:3D:E4:40:A8:C1:A5:95:14:4F:1C:8D:00:3B:46:68:B0:FD:14:A5
O=kubeadm:cluster-admins, CN=kubernetes-admin은 Kubernetes 클러스터 관리자로 지정된 사용자임

Kubernetes에서 클라이언트 인증을 위해서는 클라이언트가 신뢰할 수 있는 인증서를 사용해야 합니다. 이를 위해 먼저 비밀 키를 생성한 후, 해당 키를 기반으로 CSR(Certificate Signing Request, 인증서 서명 요청)을 생성합니다. 이 과정은 클러스터 관리자가 특정 사용자를 인증할 수 있도록 하는 중요한 단계입니다.
# 하위 인증서를 위한 비밀키 생성 : gasida 대신 자신의 닉네임으로 변경해서 실습해보세요!
openssl genrsa -out gasida.key 2048
# 확인
cat gasida.key
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCpb0u8E7Km0CkX
...
# 인증서 사인 요청 파일(.csr) 파일 생성
openssl req -new -key gasida.key -out gasida.csr -subj "/O=kubeadm:cluster-admins/CN=gasida-cert"
# 확인
cat gasida.csr
-----BEGIN CERTIFICATE REQUEST-----
MIICczCCAVsCAQAwLjEWMBQGA1UECgwNY2xvdWRuZXRhLW9yZzEUMBIGA1UEAwwL
...
# 출력 값을 아래 request 에 붙여넣기 : 끝에 == 빼먹지 말것!
cat gasida.csr | base64 | tr -d '\n'
CSR 파일은 Kubernetes 클러스터 내부에서 특정 사용자에 대한 인증서를 발급하기 위한 요청입니다. 생성된 CSR을 클러스터 관리자가 승인하면, Kubernetes는 이를 기반으로 클라이언트 인증서를 발급합니다.

Kubernetes 클러스터 내부에서는 CSR 요청을 통해 클라이언트 인증을 위한 서명을 받을 수 있습니다. CSR 요청을 적용하면, 클러스터 내의 CA(Certificate Authority)가 이를 검토하고 서명하여 인증서를 발급할 수 있습니다.
# CSR 요청 : k8s 내부적으로 루트인증서의 비밀키로 서명해 반환. 즉 간접적으로 루트 인증서의 비밀키를 사용할 수 있음 셈.
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: gasida-csr
spec:
signerName: kubernetes.io/kube-apiserver-client
groups:
- system:masters
- system:authenticated
request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ2ZEQ0NBV1FDQVFBd056RWZNQjBHQTFVRUNnd1dhM1ZpWldGa2JUcGpiSFZ6ZEdWeUxXRmtiV2x1Y3pFVQpNQklHQTFVRUF3d0xaMkZ6YVdSaExXTmxjblF3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUURTOU9xRktsTCt6Z0RoQ2Qxb3QvS1h0Q1JTMWI5Y3p1YzVDdW5WcTUrdEtFRkIydzFpby9zQUtwOUMKSlo2UklLcXFydm85YXRzTkF1cGFybUNORnV5SHN1d1d3RjdNbTdCYzZpZk1uRElDSU1ybG5BUDhyYkllcHFuRwo4YkJxTXM1c3VoYXl6UlVMT3hkeEg5K1ZqOERoSjZsQ0FaL3ZTcEVtVXJlbjMyMGJIZzRUay9JTnE5a0REN2xJCjR2a0ZTQzlqeDVtRG9mT2FvNzhHZEl1c0lZK01wT3Vvb1I2ZWVmSlJOa3NPanBGQ1F5bGExTURWeHd1OVpDbG4KU3FXZWFmWHZiODNnSGdJYmRsSDRER2Z3bzQrRERQckpZak5oLzA1UVd2Zjh0UW5XTkpJdXRRblpOOGlxRVhrQQpBdG5UY0tWcDFTS2x3LzJ3azJuQkU5anE4VFN2QWdNQkFBR2dBREFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBCm00UGpaZGM1ZERlS3d2dk1qUlRMWmJNRVBTQkQ4QXlLMWEyU1k4QjU1MmFNWlhFekFGQ1Zob2xxWGFsWmhudWkKbDZzeHVTVWVkMWxKQyt4OURZcHlrTmNYTXI3NDgrNkR0dTQybklUVGRZcmg4bHh0cjNSWEFkVXNYSzZoNDBxcApJVEVVNXpkeXBxZmMyMmJpN0hhZWhxZEo0c1lsaGNYK2pJemYxVml6SHUyd25ET1BWdlQxQTFnS3NwRE9kK2NCCm9DeTF2cUNxVDkydjhjektmTHVYdFMvL2QwRkJaRjlqaU9vWnpnV0pUYTV5K1Nsak1oV0hTNU1MMEkrUk9KdW0KYi91NVRDYytKRnhpRFlIOVg3MlNWL3VJaXJVNVgwRmFnaUJ0bjRjVEF1cFVrNFRrYlN4QUxXcmNOeGFXdjZ4MgpqaEV4WThFOGFNeGRuaXRDeU56WjNBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUgUkVRVUVTVC0tLS0tCg==
usages:
- digital signature
- key encipherment
- client auth
EOF
# csr 확인 : 아직은 펜딩 상테
kubectl get csr
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
gasida-csr 1s kubernetes.io/kube-apiserver-client kubernetes-admin <none> Pending
...
이 과정이 완료되면 kubectl get csr 명령어를 사용하여 요청된 CSR이 보류(Pending) 상태인지 확인할 수 있습니다. 관리자가 해당 요청을 승인하면 인증서가 발급됩니다.

# 'k8s 관리자' 입장에서 해당 서명 요청을 승인하자
kubectl certificate approve gasida-csr
certificatesigningrequest.certificates.k8s.io/gasida-csr approved
CSR을 승인하면 Kubernetes CA가 해당 요청을 검토하고 서명하여 유효한 클라이언트 인증서를 발급하게 됩니다. 이후, 사용자는 발급된 인증서를 이용하여 클러스터 내에서 인증된 사용자로 동작할 수 있습니다.

CSR이 승인된 후, 아래 명령을 사용하여 발급된 인증서를 확인할 수 있습니다. 이 인증서를 kubeconfig 파일에 추가하여 사용자가 인증된 접근을 할 수 있도록 설정해야 합니다.
# 확인 : 정상적으로 하위 인증서가 발급됨
kubectl get csr
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
gasida-csr 2m4s kubernetes.io/kube-apiserver-client kubernetes-admin <none> Approved,Issued
...
# csr 에서 하위 인증서 추출
kubectl get csr gasida-csr -o jsonpath='{.status.certificate}' | base64 -d
kubectl get csr gasida-csr -o jsonpath='{.status.certificate}' | base64 -d > gasida.crt
#
openssl x509 -in gasida.crt -noout -text
...
Issuer: CN=kubernetes
Validity
Not Before: Mar 7 14:03:06 2025 GMT
Not After : Mar 7 14:03:06 2026 GMT
Subject: O=kubeadm:cluster-admins, CN=gasida-cert
...
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Client Authentication


새로운 관리자를 위한 인증서가 발급되었으면, 이를 kubeconfig에 등록하여 해당 사용자가 Kubernetes 클러스터에 접근할 수 있도록 설정해야 합니다. 아래 명령어를 통해 신규 사용자의 인증서를 적용하고, 새로운 Kubernetes 컨텍스트(context)를 생성합니다.
# kubeconfig 에 새로운 사용자 등록
kubectl config set-credentials gasida-user --client-certificate=gasida.crt --client-key=gasida.key
kubectl config set-context kind-gasida --cluster=kind-myk8s --user=gasida-user
cat ~/.kube/config
kubectl config use-context kind-gasida # 혹은 kubectl ctx kind-gasida

위의 설정을 완료하면 생성한 계정이 Kubernetes 클러스터에 정상적으로 접근할 수 있는지 확인해야 합니다. 아래 명령어를 실행하여 kubectl 명령이 제대로 작동하는지 검증할 수 있습니다.
# ctx kind-gasida 로 k8s 정보 확인 시도
kubectl get node
