TLS in Kubernetes - Certificate Creation

Yu Sang Min·2025년 6월 15일

CKA

목록 보기
48/110
post-thumbnail
  • 인증서를 생성하기 위한 도구로는 Easy-RSA, OpenSSL, CFSSL 등 다양한 도구들이 있다.
  • 예제 에서는 OpenSSL을 사용해서 인증서를 생성.
  • 먼저, 클러스터의 CA(Certificate Authority) 인증서를 생성.

📍 1. CA 인증서 생성

  • OpenSSL로 CA의 개인 키 생성 (Generate Keys):
$ openssl genrsa -out ca.key 2048
  • CSR(Certificate Signing Request) 생성
$ openssl req -new -key ca.key -subj “/CN=KUBERNETES-CA” -out ca.csr
  • CSR을 자체 서명(self-signed)
$ openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
  • 즉, 방금 생성한 개인 키로 자신을 서명.
  • 이제 CA는 자신의 개인 키와 루트 인증서 파일을 갖게 됨. 이후 다른 모든 인증서들은 이 CA 키 쌍으로 서명.

👤 2. 클라이언트 인증서 생성 (예: admin)

  • admin 사용자용 개인 키 → CSR → CA 서명 인증서 순으로 생성
  • CN(Common Name): kube-admin

💡 admin 사용자가 단순한 일반 사용자가 아니라 클러스터의 관리자인 것을 구분하기 위해서는 그룹 정보를 인증서에 추가해야함. Kubernetes에는 system:masters라는 관리자 권한을 가진 그룹이 있으며, 이 그룹에 속해야 관리자 권한을 얻을 수 있다.

  • OU(Organizational Unit): system:masters → 관리자 권한 부여
$ openssl genrsa -out admin.key 2048 
$ openssl req -new -key admin.key -subj "/CN=kube-admin/O=system:masters" -out admin.csr  // 관리자 권한 부여됨
$ openssl x509 -req -in admin.csr -CA ca.crt -CAkey ca.key -out admin.crt

| ⚠️ Kubernetes는 RBAC을 위해 CN과 OU 필드를 인증된 사용자 정보로 사용

  • 클러스터 컴포넌트들도 동일 방식으로 생성:
    • system:kube-scheduler
    • system:kube-controller-manager
    • system:kube-proxy
      | ✅ system: 접두사는 Kubernetes에서 시스템 사용자임을 의미
      예: system:kube-scheduler, system:kube-controller-manager

🛠️ 3. 인증서 활용 방법

  • 클러스터 접근 시, 클라이언트 인증서 + 개인 키 + CA 인증서 사용
  • 예를 들어 admin 인증서를 사용해 클러스터를 관리가능. username/password 대신, API 호출 시 클라이언트 인증서, 개인 키, CA 인증서를 옵션으로 함께 전달.
$ curl https://kube-apiserver:6443/api/v1/pods \
   -- key admin.key --cert admin.crt
   -- cacert ca.crt
  • 보통은 이러한 정보들을 kubeconfig 파일에 구성.
# kube-config.yaml
apiVersion: v1
clusters:
- cluster:
    certificate-authority: ca.crt
    server: https://kube-apiserver:6443
  name: kubernetes
kind: Config
users:
- name: kubernetes-admin
  user:
    client-certificate: admin.crt
    client-key: admin.key
  • 주로 kubeconfig 파일에 구성:
    • API 서버 주소
    • 인증서 경로
    • 사용자 식별 정보 포함
  • 각 구성 요소(컴포넌트)들은 공통적으로 CA 인증서를 보유해야 함
    | 💡 브라우저가 루트 CA로 HTTPS 인증서를 검증하는 원리와 동일

📡 4. 서버 측 인증서 생성 (ETCD)

  • ETCD도 TLS 통신을 위해 서버 인증서 필요
    • etcd-server 이름으로 생성
  • 고가용성 ETCD는 peer 통신용 인증서도 별도로 생성 필요
  • 실행 시 사용 옵션:
- etcd
  --advertise-client-urls=https://127.0.0.1:2379
  --key-file=/path-to-certs/etcdserver.key     // 옵션
  --cert-file=/path-to-certs/etcdserver.crt    // 옵션
  --client-cert-auth=true
  --data-dir=/var/lib/etcd
  --initial-advertise-peer-urls=https://127.0.0.1:2380
  --initial-cluster=master=https://127.0.0.1:2380
  --listen-client-urls=https://127.0.0.1:2379
  --listen-peer-urls=https://127.0.0.1:2380
  --name=master
  --peer-cert-file=/path-to-certs/etcdpeer1.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  // 옵션

🔌 5. Kube API Server 인증서

가장 중요한 컴포넌트인 Kube API 서버 인증서 생성도 같은 방식이지만, 주의할 점이 하나 있다.

API 서버는 클러스터 내 모든 컴포넌트가 통신하는 핵심 엔드포인트. 따라서 다양한 이름(DNS명)으로 호출:

  • SAN(Subject Alternative Name) 필수 포함:
$ openssl genrsa -out apiserver.key 2048

$ openssl req -new -key apiserver.key -subj \
     "/CN=kube-apiserver" -out apiserver.csr

# openssl.cnf
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[ v3_req ]
basicConstraints = CA:FALSE
keyUsages = nonRepudiation,
subjectAltName = @alt_names
[alt_names]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster.local
IP.1 = 10.96.0.1 // Cluster IP
IP.2 = 172.17.0.87

$ openssl x509 -req -in apiserver.csr \
    -CA ca.crt -CAkey ca.key -out apiserver.crt
  • OpenSSL config 파일로 SAN 지정 → CSR 생성 → CA로 서명
  • API Server 실행 시 주요 인증서 옵션:
ExecStart=/usr/local/bin/kube-apiserver \
  --advertise-address=${INTERNAL_IP} \
  --allow-privileged=true \
  --apiserver-count=3 \
  --authorization-mode=Node,RBAC \
  --bind-address=0.0.0.0 \
  --enable-swagger-ui=true \
  --etcd-cafile=/var/lib/kubernetes/ca.pem \  // etcd와의 통신을 위한 인증서
  --etcd-certfile=/var/lib/kubernetes/apiserver-etcd-client.crt \  // etcd와의 통신을 위한 인증서
  --etcd-keyfile=/var/lib/kubernetes/apiserver-etcd-client.key \  // etcd와의 통신을 위한 인증서
  --etcd-servers=https://127.0.0.1:2379 \
  --event-ttl=1h \
  --kubelet-certificate-authority=/var/lib/kubernetes/ca.pem \  // kubelet과 통신을 위한 클라이언트 인증서
  --kubelet-client-certificate=/var/lib/kubernetes/apiserver-kubelet-client.crt \  // kubelet과 통신을 위한 클라이언트 인증서
  --kubelet-client-key=/var/lib/kubernetes/apiserver-kubelet-client.key \  // kubelet과 통신을 위한 클라이언트 인증서
  --kubelet-https=true \
  --runtime-config=api/all \
  --service-account-key-file=/var/lib/kubernetes/service-account.pem \
  --service-cluster-ip-range=10.32.0.0/24 \
  --service-node-port-range=30000-32767 \
  --client-ca-file=/var/lib/kubernetes/ca.pem \  // 클라이언트를 검증하기 위한 CA 인증서
  --tls-cert-file=/var/lib/kubernetes/apiserver.crt \  // API 서버의 TLS 인증서
  --tls-private-key-file=/var/lib/kubernetes/apiserver.key \  // API 서버의 TLS 인증서
  --v=2

🧩 6. Kubelet 인증서 (Node 별)

  • 모든 노드는 개별 인증서 필요
    • CN: system:node:<node-name>
    • OU: system:nodes
  • Kubelet 서버 인증서:
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
  x509:
    clientCAFile: "/var/lib/kubernetes/ca.pem"  // 주목
authorization:
  mode: Webhook
clusterDomain: "cluster.local"
clusterDNS:
  - "10.32.0.10"
podCIDR: "${POD_CIDR}"
resolvConf: "/run/systemd/resolve/resolv.conf"
runtimeRequestTimeout: "15m"
tlsCertFile: "/var/lib/kubelet/kubelet-node01.crt"  // 주목
tlsPrivateKeyFile: "/var/lib/kubelet/kubelet-node01.key"  // 주목
  • Kubelet → API Server 통신 시 사용하는 클라이언트 인증서는 별도로 생성하여 kubeconfig에 등록

| ⚠️ 잘못된 CN/OU는 API 서버가 노드를 신뢰하지 않아 등록이 거부됨


🧠 요약

  • 모든 인증서는 CA로 서명됨
  • 각 컴포넌트마다 적절한 CN/OU 설정이 중요
  • API 서버는 SAN 필드에 다양한 접근 이름/IP 포함 필수
  • 각 노드는 고유한 인증서를 가지고 있어야 하며, 클라이언트/서버 역할을 모두 수행
profile
React, Node.js, AWS, Git, Github, Github Action, Docker, K8S

0개의 댓글