
$ openssl genrsa -out ca.key 2048
$ openssl req -new -key ca.key -subj “/CN=KUBERNETES-CA” -out ca.csr
$ openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
kube-admin💡 admin 사용자가 단순한 일반 사용자가 아니라 클러스터의 관리자인 것을 구분하기 위해서는 그룹 정보를 인증서에 추가해야함. Kubernetes에는 system:masters라는 관리자 권한을 가진 그룹이 있으며, 이 그룹에 속해야 관리자 권한을 얻을 수 있다.
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-schedulersystem:kube-controller-managersystem:kube-proxysystem: 접두사는 Kubernetes에서 시스템 사용자임을 의미system:kube-scheduler, system:kube-controller-manager$ curl https://kube-apiserver:6443/api/v1/pods \
-- key admin.key --cert admin.crt
-- cacert ca.crt
# 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
- 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 // 옵션
가장 중요한 컴포넌트인 Kube API 서버 인증서 생성도 같은 방식이지만, 주의할 점이 하나 있다.
API 서버는 클러스터 내 모든 컴포넌트가 통신하는 핵심 엔드포인트. 따라서 다양한 이름(DNS명)으로 호출:
$ 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
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
system:node:<node-name>system:nodeskind: 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" // 주목
| ⚠️ 잘못된 CN/OU는 API 서버가 노드를 신뢰하지 않아 등록이 거부됨