CA 인증서 수동 회전하기
CA 인증서 수동 회전하기 (Manual Rotation of CA Certificates)
이 페이지는 인증 기관(CA) 인증서를 수동으로 회전하는 방법을 보여드려요.
출처: 문서
본문
시작하기 전에 (Before you begin)
쿠버네티스 클러스터가 필요하고, kubectl 명령줄 도구가 클러스터와 통신하도록 구성돼 있어야 해요. 이 튜토리얼은 컨트롤 플레인 호스트가 아닌 노드가 두 개 이상 있는 클러스터에서 실행하는 것을 권장해요. 아직 클러스터가 없다면 minikube로 만들거나 다음 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있어요.
- iximiuz Labs
- Killercoda
- KodeKloud
- 쿠버네티스의 인증에 대한 자세한 정보는 Authenticating를 참고하세요.
- CA 인증서의 모범 사례에 대한 자세한 정보는 Single root CA를 참고하세요.
CA 인증서 수동 회전하기 (Rotate the CA certificates manually)
주의: 인증서 디렉토리를 구성 파일 및 기타 필요한 파일과 함께 반드시 백업하세요.
이 접근 방식은 여러 API 서버가 있는 HA 구성에서 쿠버네티스 컨트롤 플레인이 운영된다고 가정해요. API 서버의 정상 종료(graceful termination)도 가정하므로 클라이언트가 한 API 서버에서 깨끗하게 연결을 끊고 다른 서버에 다시 연결할 수 있어요. 단일 API 서버가 있는 구성은 API 서버가 재시작되는 동안 사용 불가를 겪을 거예요.
- 새 CA 인증서와 개인 키(예:
ca.crt,ca.key,front-proxy-ca.crt,front-proxy-ca.key)를 쿠버네티스 인증서 디렉토리의 모든 컨트롤 플레인 노드에 배포해요. - kube-controller-manager의
--root-ca-file플래그를 업데이트해 이전과 새 CA를 모두 포함시킨 다음 kube-controller-manager를 재시작해요. 이 시점 이후에 생성되는 어떤 ServiceAccount든 이전과 새 CA를 모두 포함하는 Secrets를 얻게 돼요.
참고: kube-controller-manager 플래그
--client-ca-file과--cluster-signing-cert-file이 지정하는 파일은 CA 번들일 수 없어요. 이 플래그와--root-ca-file이 같은ca.crt파일(이제 번들, 이전과 새 CA 모두 포함)을 가리키면 오류가 발생할 거예요. 이 문제를 해결하려면 새 CA를 별도 파일로 복사하고--client-ca-file과--cluster-signing-cert-file플래그가 그 복사본을 가리키게 해요.ca.crt가 더 이상 번들이 아니면 해당 플래그를ca.crt로 복원하고 복사본을 삭제할 수 있어요. kubeadm의 Issue 1350은 kube-controller-manager가 CA 번들을 받아들이지 못하는 버그를 추적해요.
- controller manager가 서비스어카운트 Secrets의
ca.crt를 이전과 새 CA 인증서를 모두 포함하도록 업데이트할 때까지 기다려요. API 서버가 새 CA를 사용하기 전에 시작된 어떤 Pod든 이 업데이트를 받고 이전과 새 CA를 모두 신뢰하게 돼요. - 인클러스터 구성을 사용하는 모든 파드(예: kube-proxy, CoreDNS 등)를 재시작해 ServiceAccount에 연결된 Secrets의 업데이트된 인증 기관 데이터를 사용할 수 있게 해요.
- CoreDNS, kube-proxy 및 인클러스터 구성을 사용하는 다른 Pod가 예상대로 작동하는지 확인해요.
kube-apiserver구성의--client-ca-file과--kubelet-certificate-authority플래그가 가리키는 파일에 이전과 새 CA를 모두 추가해요.kube-scheduler구성의--client-ca-file플래그가 가리키는 파일에 이전과 새 CA를 모두 추가해요.client-certificate-data와client-key-data의 내용을 각각 교체해 사용자 계정의 인증서를 업데이트해요. 개별 사용자 계정용 인증서 생성에 대한 정보는 "Configure certificates for user accounts"를 참고하세요. 또한 kubeconfig 파일의certificate-authority-data섹션을 Base64로 인코딩된 이전 및 새 인증 기관 데이터로 각각 업데이트해요.- Cloud Controller Manager의
--root-ca-file플래그를 업데이트해 이전과 새 CA를 모두 포함시킨 다음 cloud-controller-manager를 재시작해요.
참고: 클러스터에 cloud-controller-manager가 없다면 이 단계를 건너뛸 수 있어요.
아래 단계를 롤링 방식으로 따르세요.
- 새 CA 인증서를 신뢰하도록 다른 모든 애그리게이트 API 서버나 웹훅 핸들러를 재시작해요.
- 모든 노드에서 kubelet 구성의
clientCAFile에 대한 파일과kubelet.conf의certificate-authority-data를 업데이트해 이전과 새 CA를 모두 사용하도록 한 다음 kubelet을 재시작해요. kubelet이 클라이언트 인증서 회전을 사용하지 않는다면 모든 노드의kubelet.conf에서client-certificate-data와client-key-data를, 그리고 일반적으로/var/lib/kubelet/pki에 있는 kubelet 클라이언트 인증서 파일과 함께 업데이트해요. - 새 CA가 서명한 인증서(
apiserver.crt,apiserver-kubelet-client.crt,front-proxy-client.crt)로 API 서버를 재시작해요. 기존 개인 키나 새 개인 키를 사용할 수 있어요. 개인 키를 변경했다면 쿠버네티스 인증서 디렉토리에서도 업데이트해요. 클러스터의 Pod가 이전과 새 CA를 모두 신뢰하므로 잠시 연결이 끊긴 후 파드의 쿠버네티스 클라이언트가 새 API 서버에 다시 연결돼요. 새 API 서버는 새 CA가 서명한 인증서를 사용해요. - 새 CA를 사용하고 신뢰하도록 kube-scheduler를 재시작해요.
- 컨트롤 플레인 컴포넌트 로그에 TLS 오류가 없는지 확인해요.
참고:
openssl명령줄 도구로 클러스터용 인증서와 개인 키를 생성하려면 Certificates (openssl)를 참고하세요.cfssl도 사용할 수 있어요.
- 더 안전한 롤링 방식으로 파드 교체를 촉발하기 위해 DaemonSet과 Deployment에 어노테이션을 달아요.
for namespace in $(kubectl get namespace -o jsonpath='{.items[*].metadata.name}'); do
for name in $(kubectl get deployments -n $namespace -o jsonpath='{.items[*].metadata.name}'); do
kubectl patch deployment -n ${namespace} ${name} -p '{"spec":{"template":{"metadata":{"annotations":{"ca-rotation": "1"}}}}}';
done
for name in $(kubectl get daemonset -n $namespace -o jsonpath='{.items[*].metadata.name}'); do
kubectl patch daemonset -n ${namespace} ${name} -p '{"spec":{"template":{"metadata":{"annotations":{"ca-rotation": "1"}}}}}';
done
done
참고: 애플리케이션이 겪는 동시 중단 수를 제한하려면 configure pod disruption budget을 참고하세요. StatefulSet을 어떻게 사용하는지에 따라 유사한 롤링 교체를 수행해야 할 수도 있어요.
- 클러스터가 부트스트랩 토큰으로 노드를 조인한다면
kube-public네임스페이스의 ConfigMapcluster-info를 새 CA로 업데이트해요.
base64_encoded_ca="$(base64 -w0 /etc/kubernetes/pki/ca.crt)"
kubectl get cm/cluster-info --namespace kube-public -o yaml | \
/bin/sed "s/\(certificate-authority-data:\).*/\1 ${base64_encoded_ca}/" | \
kubectl apply -f -
- 클러스터 기능을 검증해요. 컨트롤 플레인 컴포넌트의 로그와 함께 kubelet과 kube-proxy의 로그를 확인해요. 이 컴포넌트가 TLS 오류를 보고하지 않는지 확인하세요.
- 인클러스터 구성을 사용하는 애그리게이트 api server와 파드의 로그를 검증해요.
- 클러스터 기능이 성공적으로 검증되면:
- 모든 서비스어카운트 토큰에 새 CA 인증서만 포함하도록 업데이트해요.
- 인클러스터 kubeconfig를 사용하는 모든 파드는 새 Secret을 가져오기 위해 결국 재시작해야 하므로, 어떤 파드도 이전 클러스터 CA에 의존하지 않아야 해요.
- kubeconfig 파일과
--client-ca-file,--root-ca-file플래그가 가리키는 파일에서 이전 CA를 제거해 컨트롤 플레인 컴포넌트를 재시작해요. - 각 노드에서
clientCAFile플래그에 대한 파일과 kubelet kubeconfig 파일에서 이전 CA를 제거해 kubelet을 재시작해요. 이를 롤링 업데이트로 수행해야 해요. 클러스터가 이 변경을 허용한다면 노드를 재구성하는 대신 교체하는 방식으로 롤아웃할 수도 있어요.