Kubernetes 인증서 갱신
대상 환경
| 항목 | 값 |
|---|---|
| 클러스터 구성 | HA 3-node 컨트롤 플레인 |
| 노드 호스트명 | dev-a1-ms01, dev-a1-ms02, dev-a1-ms03 |
| Kubernetes 버전 | v1.25.15 |
| OS | RHEL 8.9 |
| 컨테이너 런타임 | cri-o |
인증서 갱신
kubeadm으로 관리되는 클러스터이므로, 각 컨트롤 플레인 노드에서 아래 명령으로 인증서를 갱신합니다.
kubeadm certs renew all
실제 작업에서는 3개 노드 모두에서 총 10개 인증서가 갱신되었고, 갱신 후 만료일은 2027년 3월 3일로 확인되었습니다.
갱신 여부는 아래 명령으로 확인합니다.
kubeadm certs check-expiration
⚠️ 컨트롤 플레인 재시작 — 중요한 정정 사항
인증서를 갱신한 뒤에는 kube-apiserver, kube-controller-manager, kube-scheduler, etcd가 새 인증서를 읽도록 재시작해야 합니다. 흔히 알려진 아래 두 방법은 이 환경에서는 동작하지 않는 것으로 확인되었습니다.
동작하지 않는 방법
# 방법 1 — 동작 안 함
touch /etc/kubernetes/manifests/*.yaml
# 방법 2 — 동작 안 함
kill -s SIGHUP <pid>
원인:
touch는 파일의 mtime만 변경할 뿐입니다. kubelet은 static pod manifest를 감지할 때 파일의 mtime이 아니라 Pod spec의 실제 내용 변경 여부를 기준으로 판단하기 때문에, 내용이 그대로면 touch만으로는 재시작이 트리거되지 않습니다.- kube-apiserver는 SIGHUP을 인증서 재로드 시그널로 처리하지 않습니다. 일부 데몬(nginx 등)과 달리 kube-apiserver에는 이런 핫 리로드 메커니즘이 구현되어 있지 않습니다.
실제로 동작하는 방법
# 1. 대상 컴포넌트의 컨테이너 ID 확인
crictl ps | grep kube-apiserver
# 2. 확인된 컨테이너 ID로 정지 — kubelet이 자동으로 재생성
crictl stop -t 20 <container-id>
crictl stop -t는 -t(timeout)로 지정한 시간 동안 SIGTERM으로 정상 종료를 먼저 시도하고, 시간 내에 종료되지 않으면 강제 종료(SIGKILL)합니다. 즉 무조건적인 강제 킬이 아니라 그레이스풀 셧다운입니다.
컴포넌트별 권장 timeout
| 컴포넌트 | 권장 -t 값 | 비고 |
|---|---|---|
| etcd | 30초 | 데이터 정합성 때문에 넉넉하게 |
| kube-apiserver | 10~20초 | — |
| kube-controller-manager | 10~20초 | — |
| kube-scheduler | 10~20초 | — |
정지된 컨테이너는 kubelet이 static pod manifest를 기준으로 자동 재생성하며, 이때 새로 갱신된 인증서를 읽어들입니다.
재시작 후 확인
# 모든 컨트롤 플레인 컴포넌트가 정상 기동했는지 확인
kubectl get pods -n kube-system
# 인증서 만료일 재확인
kubeadm certs check-expiration
참고: 대안 (fallback)
crictl stop 방식이 어떤 이유로든 여의치 않을 경우, manifest 파일을 임시로 다른 경로로 옮겼다가 되돌리는 방법도 사용할 수 있습니다 (kubelet이 manifest 디렉토리에서 파일이 사라졌다가 다시 나타나는 것을 감지하여 재생성).
mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/
sleep 5
mv /tmp/kube-apiserver.yaml /etc/kubernetes/manifests/
다만 이 방법보다는 crictl stop -t가 더 예측 가능하고 로그로 확인하기 쉬워 주 방법으로 권장합니다.