본 가이드는 certs 핵심 가이드 및 실전 아키텍처의 핵심 개념, 실전 구성 명령어 및 아키텍처 베스트 프랙티스를 다룹니다. 클라우드 네이티브 및 인프라 엔지니어링 실무에 즉시 활용 가능하도록 체계적으로 정리했습니다.
자동 스크립트
-
– 만료 이후 갱신시
부트스트래핑 시도
부트스트래핑 설정이 되어 있지 않고, 이미 컨트롤 플레인과 kubelet의 인증서가 모두 만료된 최악의 상황을 가정하여 복구 순서를 정리해 드립니다.
이 경우 API 서버가 죽어있으므로
kubectl이 작동하지 않습니다. 따라서 컨트롤 플레인을 먼저 살린 후, 노드의 kubelet을 순차적으로 살리는 방식으로 진행해야 합니다.—
### 1단계: 컨트롤 플레인(Master) 인증서 갱신
가장 먼저 API 서버, 스케줄러, 컨트롤러 매니저가 사용하는 인증서를 갱신해야 클러스터의 “뇌”가 살아납니다.
1. 현재 만료 상태 확인Bash
kubeadm certs check-expiration2. 모든 컨트롤 플레인 인증서 갱신Bash
kubeadm certs renew all3. 정적 포드(Static Pods) 재시작
인증서 파일은 갱신되었지만, 이미 메모리에 올라가 있는kube-apiserver등은 옛날 인증서를 물고 있습니다. 파일을 다시 읽도록 강제 재시작합니다.Bash# 매니페스트 파일을 잠시 옮겼다 다시 가져오면 컨테이너가 재시작됩니다.
mv /etc/kubernetes/manifests/*.yaml /tmp/
sleep 10
mv /tmp/*.yaml /etc/kubernetes/manifests/4. 관리자 설정 파일(admin.conf) 갱신
kubectl을 사용할 수 있도록 내 로컬의.kube/config를 새 파일로 교체합니다.Bashcp /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config—
### 2단계: Kubelet 인증서 수동 갱신 준비 (부트스트랩 미설정 시)
부트스트래핑(
bootstrap-kubelet.conf)이 없다면, kubelet은 스스로 인증서를 받아올 통로가 없습니다. 이때는kubeadm의 기능을 이용해 임시로 인증 통로를 열어줘야 합니다.1. RBAC 권한 허용 (마스터에서 실행)
kubelet이 CSR(인증서 서명 요청)을 보낼 수 있도록 권한을 일시적으로 허용합니다. (이미 설정되어 있다면 생략 가능)Bashkubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --group=system:bootstrappers2. 새로운 부트스트랩 토큰 생성Bash
kubeadm token create --print-join-command여기서 생성된 토큰을 복사해두세요.
—
### 3단계: 각 노드(Worker/Master)의 Kubelet 복구
이제 각 노드로 이동하여 만료된
kubelet-client-current.pem을 무시하고 새 인증서를 발급받게 합니다.1. Kubelet 중지 및 기존 인증서 제거Bash
systemctl stop kubelet
# 만료된 인증서와 심볼릭 링크 제거
rm /var/lib/kubelet/pki/kubelet-client-*.pem
rm /var/lib/kubelet/pki/kubelet-client-current.pem2. kubelet.conf 재생성 (중요)
부트스트래핑이 안 되어 있다면/etc/kubernetes/kubelet.conf안의 인증서 정보도 만료되었을 것입니다.kubeadm을 이용해 이 파일을 다시 구성합니다.Bash# 노드에서 실행 (마스터에서 받은 토큰과 주소 사용)
kubeadm join:6443 --token --discovery-token-ca-cert-hash sha256: --control-plane (마스터일 경우만 추가) 이미 조인된 노드라면
--force옵션이 필요하거나, 기존/etc/kubernetes/내의.conf파일들을 백업 후 실행해야 할 수 있습니다.3. Kubelet 시작Bash
systemctl start kubelet—
### 4단계: CSR 승인 (마스터에서 실행)
Kubelet이 살아나면서 마스터에 “나 새로 왔는데 인증 좀 해줘”라고 요청을 보냅니다.
1. 요청 목록 확인Bash
kubectl get csr2. 승인Bash
# Pending 상태인 모든 CSR 승인
kubectl get csr | grep Pending | awk '{print $1}' | xargs kubectl certificate approve—
### 요약 순서
1. Master:
kubeadm certs renew all후 Static Pod 재시작.
2. Master:admin.conf업데이트하여kubectl살리기.
3. Master:kubeadm token create로 새 통로 확보.
4. Node: 기존kubelet-client-*.pem삭제.
5. Node:kubeadm join명령(또는 관련 설정 업데이트)으로 재인증 시도.
6. Master:kubectl certificate approve로 최종 승인.이 절차를 마치면
kubectl get nodes에서 모든 노드가Ready상태로 돌아오게 됩니다. 1.23 버전은 특히kubeadm의 인증서 관리 명령어가 안정화된 버전이므로 위 명령어들이 잘 작동할 것입니다.
부트스트래핑 무시
부트스트래핑(Token 기반 자동 조인) 기능을 사용하지 않으면서, 만료된 컨트롤 플레인과 kubelet을 수동으로 복구하는 핵심은 \*\*”직접 인증서 파일을 생성하고 kubeconfig를 수동으로 업데이트”\*\*하는 것입니다.
이 방식은
kubeadm join이나token없이, 오직kubeadm의 인증서 갱신 기능과 파일 복사만으로 진행됩니다.—
### 1단계: 컨트롤 플레인(Master) 인증서 수동 갱신
가장 먼저 ‘인증 기관(CA)’과 API 서버 관련 인증서를 살려야 합니다.
1. 컨트롤 플레인 인증서 일괄 갱신Bash
kubeadm certs renew all2. 정적 포드(Static Pods) 재시작 (인증서 로드)Bash
# 매니페스트를 잠시 옮겼다 복사하여 컨테이너 재시작 유도
mv /etc/kubernetes/manifests/*.yaml /tmp/
sleep 5
mv /tmp/*.yaml /etc/kubernetes/manifests/3. 관리자용 kubeconfig 업데이트Bash
cp /etc/kubernetes/admin.conf $HOME/.kube/config—
### 2단계: Kubelet용 설정 파일(
kubelet.conf) 수동 갱신부트스트래핑을 쓰지 않는다면,
/etc/kubernetes/kubelet.conf파일 내부에 있는 클라이언트 인증서 데이터를 직접 갱신해줘야 합니다.kubeadm은 이 과정을 위한 전용 명령어를 제공합니다.\[모든 노드(Master 포함)에서 수행\]
1. kubelet 설정 파일 내 인증서 갱신Bash
kubeadm init phase kubeconfig kubelet --config /etc/kubernetes/kubeadm-config.yaml (또는 기본값 사용 시 생략 가능)이 명령은
/etc/kubernetes/kubelet.conf파일을 새로 생성하며, 내부에 새로운 임베디드 인증서를 포함시킵니다.2. 기존의 개별 PEM 파일 정리Bash
부트스트래핑을 안 쓴다면
/var/lib/kubelet/pki/에 있는kubelet-client-current.pem이 아니라/etc/kubernetes/kubelet.conf내의 데이터를 우선 참조하게 됩니다. 충돌 방지를 위해 기존 파일은 치워둡니다.rm -f /var/lib/kubelet/pki/kubelet-client-*.pem
rm -f /var/lib/kubelet/pki/kubelet-client-current.pem—
### 3단계: Kubelet 서비스 재시작 및 권한 확인
이제 각 노드의 kubelet이 새로운
kubelet.conf를 읽고 API 서버와 통신하게 합니다.1. Kubelet 재시작Bash
systemctl restart kubelet2. CSR 수동 승인 (필요 시)Bash
일부 환경에서는
kubelet.conf갱신 후에도 kubelet이 추가적인 서빙 인증서를 요청할 수 있습니다. 마스터에서 확인 후 승인합니다.kubectl get csr
kubectl certificate approve—
### 4단계:
kubelet-client-current.pem이 다시 생기게 하려면?사용자께서 질문 초기에 언급하신
/var/lib/kubelet/pki/kubelet-client-current.pem파일은 사실 Kubelet의 Rotation 기능이 켜져 있을 때 생성되는 파일입니다.부트스트래핑 없이 이 파일을 다시 유지하고 싶다면,
kubelet.conf가 갱신된 상태에서 kubelet 설정(config.yaml)에 다음이 포함되어야 합니다:–
rotateCertificates: true
–serverTLSBootstrap: true(선택 사항)### 정리된 명령어 흐름도
단계 실행 위치 명령어 1. CP 갱신 Master kubeadm certs renew all2. 설정 갱신 모든 노드 kubeadm init phase kubeconfig kubelet3. 파일 정리 모든 노드 rm -f /var/lib/kubelet/pki/kubelet-client*4. 재시작 모든 노드 systemctl restart kubelet이렇게 하면 토큰 기반의 부트스트래핑(
bootstrap-kubelet.conf) 과정을 거치지 않고도,kubeadm이 생성해주는 정적 설정 파일을 통해 인증서를 수동으로 교체하고 정상 동작시킬 수 있습니다.혹시
kubeadm init phase실행 시 특정 설정 파일을 찾지 못한다는 에러가 발생하나요? 해당 클러스터의kubeadm-config덤프가 필요하다면 알려주세요.
근거
kubeadm으로 생성된 클라이언트 인증서는 1년 후에 만료된다.
# kubectl 명령어 사용시
Unable to connect to the server: x509: certificate has expired or is not yet valid.
인증서 만료시점 조회
sudo kubeadm certs check-expiration
#>>> 출력
#[check-expiration] Reading configuration from the cluster...
#[check-expiration] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
#W0818 13:43:59.620410 4001964 utils.go:69] The recommended value for "clusterDNS" in "KubeletConfiguration" is: [10.233.0.10]; the provided value is: [10.233.0.3]
#
#CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
#admin.conf Aug 17, 2024 01:21 UTC 364d ca no
#apiserver Aug 17, 2024 01:21 UTC 364d ca no
#apiserver-kubelet-client Aug 17, 2024 01:21 UTC 364d ca no
#controller-manager.conf Aug 17, 2024 01:21 UTC 364d ca no
#front-proxy-client Aug 17, 2024 01:21 UTC 364d front-proxy-ca no
#scheduler.conf Aug 17, 2024 01:21 UTC 364d ca no
#
#CERTIFICATE AUTHORITY EXPIRES RESIDUAL TIME EXTERNALLY MANAGED
#ca Aug 14, 2032 13:09 UTC 8y no
#front-proxy-ca Aug 14, 2032 13:09 UTC 8y no
#<<<
수행
작업
# 모든 master 노드
kubeadm certs renew all #or 다른 방법으로 갱신
# 갱신된 kubeapiserver config CLI 인증에 사용
mv ~/.kube/config ~/.kube/config-backup
cp /etc/kubernetes/admin.conf ~/.kube/config
# !! kubeconfig를 커스텀해서 사용중이라면 전체 복사/붙여넣기가 아니라 아래의 내용만 갱신하면 됩니다.
# client-certificate-data: <crt-sting>
# client-key-data: <key-string>
추가작업
아래의 로직중에 kubeadm init phase kubeconfig까지는 kubeadm certs renew all 에서 반영되었을 가능성도 있으니 확인필요합니다.
- 실제로
admin.conf는 반영된것을 확인함 kubelet.conf는 반영되지 않음을 확인함.scheduler.conf,controller-manager.conf확인필요
static pod 재시작이 되지 않아서 unauthorized 발생가능성이 있음.
- master nodes
Error Logs (kube-scheduler)
W0820 05:54:38.069851 1 reflector.go:324] vendor/k8s.io/client-go/informers/factory.go:134: failed to list *v1.PersistentVolumeClaim: Unauthorized
E0820 05:54:38.069907 1 reflector.go:138] vendor/k8s.io/client-go/informers/factory.go:134: Failed to watch *v1.PersistentVolumeClaim: failed to list *v1.PersistentVolumeClaim: Unauthorized
W0820 05:54:38.943924 1 reflector.go:324] vendor/k8s.io/client-go/informers/factory.go:134: failed to list *v1.StatefulSet: Unauthorized
E0820 05:54:38.943996 1 reflector.go:138] vendor/k8s.io/client-go/informers/factory.go:134: Failed to watch *v1.StatefulSet: failed to list *v1.StatefulSet: Unauthorized
W0820 05:54:39.911036 1 reflector.go:324] vendor/k8s.io/client-go/informers/factory.go:134: failed to list *v1.CSINode: Unauthorized
E0820 05:54:39.911123 1 reflector.go:138] vendor/k8s.io/client-go/informers/factory.go:134: Failed to watch *v1.CSINode: failed to list *v1.CSINode: Unauthorized
W0820 05:54:41.927021 1 reflector.go:324] vendor/k8s.io/client-go/informers/factory.go:134: failed to list *v1.Pod: Unauthorized
E0820 05:54:41.927132 1 reflector.go:138] vendor/k8s.io/client-go/informers/factory.go:134: Failed to watch *v1.Pod: failed to list *v1.Pod: Unauthorized
- 인증서 재발급 하는 법 (필요하지 않을 확률이 높음)
# 인증서 갱신 후 kube-scheduler, kube-controller-manager 인증에러 발생
# 클라이언트인증서 미사용으로 인함
# 백업 후 삭제
mv /etc/kubernetes/scheduler.conf /etc/kubernetes/scheduler.conf.bak
mv /etc/kubernetes/controller-manager.conf /etc/kubernetes/controller-manager.conf.bak
mv /etc/kubernetes/kubelet.conf /etc/kubernetes/kubelet.conf.bak
# 삭제되어있어야 신규발급됨
kubeadm init phase kubeconfig scheduler
kubeadm init phase kubeconfig controller-manager
kubeadm init phase kubeconfig kubelet
- 재발급한 인증서를 적용하는 법
# kubelet 재시작
mkdir ~/kubelet-backup
mv /var/lib/kubelet/pki/* ~/kubelet-backup
systemctl restart kubelet
cd /etc/kubernetes/manifests
# 기존 프로세스 종료
mv kube-controller-manager.yaml ..
mv kube-scheduler.yaml ..
# 중지 확인
kubectl -n kube-system get pods -l 'component in (kube-controller-manager,kube-scheduler)'
# 재시작
mv ../kube-controller-manager.yaml .
mv ../kube-scheduler.yaml .
- worker nodes
# 아래와같이 파일로명시되어있으면 자동갱신 되고 있을 가능성이 높음. 마스터노드도 해당설정되어있으면 조치X
grep client-certificate /etc/kubernetes/kubelet.conf
client-certificate: /var/lib/kubelet/pki/kubelet-client-current.pem
Olds
old
##### 조치방법\*\*\*\*: 각 master node에서 실행\*\*\*\*
1. 백업
# [[ master node ]]
## kube pki backup
sudo mkdir -p $HOME/fcik8s-old-certs/pki
sudo mkdir -p $HOME/fcik8s-old-certs/kubelet
sudo mkdir -p $HOME/fcik8s-old-certs/.kube
sudo cp -p /etc/kubernetes/pki/*.* $HOME/fcik8s-old-certs/pki
sudo cp -p /etc/kubernetes/*.conf $HOME/fcik8s-old-certs
sudo cp -p /var/lib/kubelet/pki/* $HOME/fcik8s-old-certs/kubelet
sudo cp -p ~/.kube/config $HOME/fcik8s-old-certs/.kube/.
2. 갱신
sudo kubeadm certs renew all --config=/etc/kubernetes/kubeadm-config.yaml
>>>
W0818 10:21:42.676045 3888005 utils.go:69] The recommended value for "clusterDNS" in "KubeletConfiguration" is: [10.233.0.10]; the provided value is: [10.233.0.3]
certificate embedded in the kubeconfig file for the admin to use and for kubeadm itself renewed
certificate for serving the Kubernetes API renewed
certificate for the API server to connect to kubelet renewed
certificate embedded in the kubeconfig file for the controller manager to use renewed
certificate for the front proxy client renewed
certificate embedded in the kubeconfig file for the scheduler manager to use renewed
Done renewing certificates. You must restart the kube-apiserver, kube-controller-manager, kube-scheduler and etcd, so that they can use the new certificates.
<<<
# 확인
sudo kubeadm certs check-expiration
# kublet 재시작
#systemctl daemon-reload&&systemctl restart kubelet
# control-plane components 종료
sudo cp -pr /etc/kubernetes/manifest $HOME/fcik8s-old-certs
sudo rm /etc/kubernetes/manifest/*
# componets container 프로세스 확인
sudo nerdctl ps
# control-plane components 재시작
sudo cp -p $HOME/fcik8s-old-certs/manifest/* /etc/kubernetes/manifest
kubectl get pods -n kube-system -l component=kube-apiserver
kubectl get pods -n kube-system -l component=kube-controller-manager
kubectl get pods -n kube-system -l component=kube-scheduler
kubectl get pods -n kube-system -l component=etcd
kubectl get nodes
3. 문제 추적
# log 확인
journalctl -u kubelet -f
journalctl -u etcd -f
journalctl -u containerd -f
kubectl logs -n kube-system -l component=kube-apiserver
kubectl logs -n kube-system -l component=kube-controller-manager
kubectl logs -n kube-system -l component=kube-scheduler
kubectl logs -n kube-system -l component=etcd
#!! kubeadm 1.17 이전의 버전에서 kubeadm init 으로 작성된 Node 에는 kubelet.conf 파일을 수동으로 수정해야 하는 버그가 있다.
## 최대 5분동안 적용여부 모니터링 필요
kubectl get nodes #정상조회 불가하다면 kubelet 구성 혹은 kubeconfig 파일 확인 필요
### error: You must be logged in to the server (Unauthorized) 발생시
### -> [2] 조치사항 확인
### [1] kubelet.conf 미갱신의 경우
sudo diff $HOME/fcik8s-old-certs/kubelet.conf /etc/kubernetes/kubelet.conf #차이가 없으면 미갱신
## 사용 전 분석 필요
#cd /etc/kubernetes
sudo kubeadm kubeconfig user --org system:nodes --client-name system:node:$(hostname) > kubelet.conf
# kubelet.conf에 파일로 명시한다면
### [1-2] v1.23.7에서 확인시 갱신하지 않은것이 정상으로 보임
sudo diff $HOME/fcik8s-old-certs/kubelet.conf /etc/kubernetes/kubelet.conf
sudo diff $HOME/fcik8s-old-certs/kubelet/kubelet-client-current.pem /var/lib/kubelet/pki/kubelet-client-current.pem
sudo diff $HOME/fcik8s-old-certs/kubelet/kubelet.key /var/lib/kubelet/pki/kubelet.key
sudo diff $HOME/fcik8s-old-certs/kubelet/kubelet.crt /var/lib/kubelet/pki/kubelet.crt
### [2] kubeconfig 미갱신의 경우
sudo diff ~/.kube/config $HOME/fcik8s-old-certs/.kube/config #차이가 없으면 미갱신
cat /etc/kubernetes/kubelet.conf # 내용 참조하여 삽입. 파일의 경우 [여기](<https://www.notion.so/cmd-cm-base64-d7e4a9892c6a4eaf8abc0e9ec1a13684?pvs=21>) 참조
client-certificate -> ~/.kube./config:client-certificate-data
client-key -> ~/.kube./config:client-key-data
systemctl daemon-reload&&systemctl restart kubelet
kubectl get nodes
4. 참고자료: 이전버전 갱신
[SKT Enterprise](https://www.sktenterprise.com/bizInsight/blogDetail/dev/2918)
# [[ master node ]]
### **1. 인증서가 존재하는 pki 디렉토리를 백업합니다.**
cp -f /etc/kubernetes/pki /etc/kubernetes/pki-backup
### **2. 인증서를 일괄적으로 업데이트 합니다.**
kubeadm certs renew all
### **3. 갱신 여부를 다시 체크합니다.**
[12:56:54][danawa@kube3 /etc/kubernetes/pki]
$ openssl x509 -in apiserver.crt -noout -text |grep ' Not '
Not Before: Mar 25 08:12:56 2020 GMT
Not After : Mar 28 02:26:40 2023 GMT
#정상적으로 1년 연장 되었습니다.
### **4. 사용자 구성을 업데이트 하기 위해 kubernetes 디렉토리를 백업합니다.**
cp -f /etc/kubernetes /etc/kubernetes-backup
### **5. 사용자 구성을 업데이트합니다.**
kubeadm kubeconfig user --client-name=admin --config=/etc/kubernetes/kubeadm-config.yaml
kubeadm kubeconfig user --org system:masters --client-name=kubernetes-admin --config=/etc/kubernetes/kubeadm-config.yaml > /etc/kubernetes/admin.conf
kubeadm kubeconfig user --client-name system:kube-controller-manager --config=/etc/kubernetes/kubeadm-config.yaml > /etc/kubernetes/controller-manager.conf
kubeadm kubeconfig user --org system:nodes --client-name system:node:$(hostname) --config=/etc/kubernetes/kubeadm-config.yaml > /etc/kubernetes/kubelet.conf
kubeadm kubeconfig user --client-name system:kube-scheduler --config=/etc/kubernetes/kubeadm-config.yaml > /etc/kubernetes/scheduler.conf
### **6. /root/.kube/config를 교체합니다.**
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
### **7. 서비스를 재시작합니다.**
systemctl daemon-reload&&systemctl restart kubelet
### csr approve
kubectl certificate approve $(kubectl get csr | grep Pending | awk '{print $1}' | sed -z 's/[\\n\\r]/ /g')
# [[ worker node ]]
## master에서 복사한 후 붙여넣기
vi /etc/kubernetes/kubelet.conf
>>>
# 아래 ip locahost로 수정
server: <https://localhost:6443>
<<<
systemctl restart kubelet
# systemctl 서비스에서 사용할 경우
systemctl restart kube-apiserver
systemctl restart kube-scheduler
# 도커 컨테이너를 사용할 경우
docker restart [apiserver 컨테이너]
docker restart [scheduler 컨테이너]
docker restart [controller 컨테이너]
##### 그 외의 방법
###### 참고 자료
[Certificate Management with kubeadm](https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-certs/#automatic-certificate-renewal)
Leave a Reply