들어가며
- kubernetes는 master 및 worker 노드로 구성되어 있습니다.
- node 간의 통신은 보안을 필요로 합니다.
- 따라서, kubeadm 은 클러스터를 실행하는 데 필요한 모든 인증서를 생성합니다.
- 인증서의 기간은 1년이며, 만료 전 갱신이 필요합니다.
kubernetes 인증서
k8s 에서 인증서가 필요한 경우는 아래와 같습니다.
- kubelet에서 API server 인증서를 인증 시 사용하는 client 인증서
- API server endpoint를 위한 server 인증서
- API server에 클러스터 관리자 인증을 위한 clinet 인증서
- API server에서 kubelet과 통신하기 위한 client 인증서
- API server에서 etcd 간의 통신을 위한 client 인증서
- controller manager와 API server 간의 통신을 위한 client 인증서
- scheduler와 API server 간의 통신을 위한 client 인증서
- front-proxy를 위한 client와 server 간의 인증서
k8s 에서 인증서의 저장 위치는 아래와 같습니다.
/etc/kubernetes/pki
갱신 대상이 되는 인증서는 아래와 같습니다.
apiserver.crt apiserver-etcd-client.crt apiserver-kubelet-client.crt front-proxy-client.crt etcd/healthcheck-client.crt etcd/peer.crt etcd/server.crt
root CA 인증서인, ca.crt , front-proxy-ca.crt , etcd/ca.crt는 인증 기간이 10년이기 때문에 갱신 대상이 아닙니다.
kubernetes 인증서 갱신 준비
(본 가이드는 master1, worker1 로 구성된 클러스터입니다.)
master 노드에서 작업합니다.
또한, kubelet과 docker 데몬 등을 내리기 위해 root 계정이 필요합니다.
- 기존 인증서 만료 일자 확인
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text | grep 'Not' Not Before: Jun 21 06:18:46 2021 GMT Not After : Nov 8 06:03:58 2022 GMT
- k8s 버전 확인
k8s 인증서 갱신 시, 사용하는 명령어는 k8s 버전에 따라 다를 수 있습니다.
본 가이드에서는 v1.13 기준으로 작성하였습니다.kubectl version Client Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.10", GitCommit:"37d169313237cb4ceb2cc4bef300f2ae3053c1a2", GitTreeState:"clean", BuildDate:"2019-08-19T10:52:43Z", GoVersion:"go1.11.13", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.10", GitCommit:"37d169313237cb4ceb2cc4bef300f2ae3053c1a2", GitTreeState:"clean", BuildDate:"2019-08-19T10:44:49Z", GoVersion:"go1.11.13", Compiler:"gc", Platform:"linux/amd64"}
- k8s 클러스터 구성 확인
kubectl get po -n kube-system -o wide NAME READY STATUS RESTARTS AGE IP NODE etcd-master 1/1 Running 23 458d 192.168.50.177 master
etcd가 master 노드에서 구동 중임을 확인kubectl get po -o wide NAME READY STATUS RESTARTS AGE IP NODE nginx-ingress-controller-7b4d84d69d-phdk7 1/1 Running 7 458d 6.2.0.99 master nginx-ingress-default-backend-799d4df74f-ghhnz 1/1 Running 7 458d 6.2.0.103 master
master 노드에서 nginx 구동 중임을 확인 - 기존 인증서 백업
/etc/kubernetes 디렉터리를 백업합니다.cp -r kubernetes/ kubernetes.backup
- k8s 인증서 설정 파일 생성
kubeadm.yaml 을 생성합니다.kubeadm config view > kubeadm.yaml
apiServer: certSANs: - master - 192.168.50.177 extraArgs: authorization-mode: Node,RBAC timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta1 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controlPlaneEndpoint: "" controllerManager: {} dns: type: CoreDNS etcd: local: dataDir: /var/lib/etcd imageRepository: repo.sparklingsoda.io:12000/k8s kind: ClusterConfiguration kubernetesVersion: v1.13.10 networking: dnsDomain: cluster.local podSubnet: 6.1.0.0/16 serviceSubnet: 6.5.0.0/16 scheduler: {}
worker 노드에서 작업합니다.
- 기존 인증서 백업
cp -r /etc/kubernetes/ /etc/kubernetes.back
install_worker_join.sh 백업
처음 cluster 구축 시, worker join 쉘 스크립트가 있다면, 백업합니다.cp install_worker_join.sh install_worker_join.sh.back
kubernetes 인증서 갱신
작업 순서는 아래와 같습니다.
- master 인증서 갱신
- master kubelet, docker 재시작
- master에서 worker join token 발행
- worker 노드 설정 파일 삭제
- worker join
- k8s configmap 갱신
- k8s context namespace 변경
- kubectl-configmap 참조하는 pod 재시작
- master 인증서 갱신
master 노드에서 작업합니다.
kubeadm.yaml 이 위치한 디렉터리에서 실행합니다.kubeadm alpha certs renew apiserver --config kubeadm.yaml kubeadm alpha certs renew apiserver-kubelet-client --config kubeadm.yaml kubeadm alpha certs renew apiserver-etcd-client --config kubeadm.yaml kubeadm alpha certs renew front-proxy-client --config kubeadm.yaml kubeadm alpha certs renew etcd-healthcheck-client --config kubeadm.yaml kubeadm alpha certs renew etcd-peer --config kubeadm.yaml kubeadm alpha certs renew etcd-server --config kubeadm.yaml
위 명령어를 실행하면, /etc/kubernetes/pki 디렉터리 하위의 *.crt 파일들이 갱신 됩니다.ll | grep Sep -rw-r--r--. 1 root root 1249 Sep 23 02:43 apiserver.crt -rw-r--r--. 1 root root 1090 Sep 23 02:44 apiserver-etcd-client.crt -rw-------. 1 root root 1675 Sep 23 02:44 apiserver-etcd-client.key -rw-------. 1 root root 1679 Sep 23 02:43 apiserver.key -rw-r--r--. 1 root root 1099 Sep 23 02:44 apiserver-kubelet-client.crt -rw-------. 1 root root 1675 Sep 23 02:44 apiserver-kubelet-client.key -rw-r--r--. 1 root root 1058 Sep 23 02:44 front-proxy-client.crt -rw-------. 1 root root 1679 Sep 23 02:44 front-proxy-client.key ll etcd/ | grep Sep -rw-r--r--. 1 root root 1094 Sep 23 02:44 healthcheck-client.crt -rw-------. 1 root root 1675 Sep 23 02:44 healthcheck-client.key -rw-r--r--. 1 root root 1135 Sep 23 02:44 peer.crt -rw-------. 1 root root 1679 Sep 23 02:44 peer.key -rw-r--r--. 1 root root 1135 Sep 23 02:44 server.crt -rw-------. 1 root root 1679 Sep 23 02:44 server.key
k8s 설정 파일 삭제합니다.rm -f /etc/kubernetes/admin.conf rm -f /etc/kubernetes/controller-manager.conf rm -f /etc/kubernetes/kubelet.conf rm -f /etc/kubernetes/scheduler.conf
ll /etc/kubernetes total 4 drwxr-xr-x. 2 root root 113 Jun 21 2021 manifests drwxr-xr-x. 3 root root 4096 Sep 23 00:40 pki
k8s 설정 파일 생성합니다.kubeadm init phase kubeconfig all --config kubeadm.yaml [kubeconfig] Using kubeconfig folder "/etc/kubernetes" [kubeconfig] Writing "admin.conf" kubeconfig file [kubeconfig] Writing "kubelet.conf" kubeconfig file [kubeconfig] Writing "controller-manager.conf" kubeconfig file [kubeconfig] Writing "scheduler.conf" kubeconfig file kubeadm init phase etcd local --config kubeadm.yaml [etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
위 명령어를 실행하면, /etc/kubernetes 디렉터리 하위에 *.conf 파일이 생성됩니다.ll /etc/kubernetes total 36 -rw-------. 1 root root 5454 Sep 23 02:49 admin.conf -rw-------. 1 root root 5490 Sep 23 02:49 controller-manager.conf -rw-------. 1 root root 5478 Sep 23 02:49 kubelet.conf drwxr-xr-x. 2 root root 113 Jun 21 2021 manifests drwxr-xr-x. 3 root root 4096 Sep 23 00:40 pki -rw-------. 1 root root 5434 Sep 23 02:49 scheduler.conf
k8s 설정 파일 복사합니다.cp /etc/kubernetes/admin.conf /root/.kube/config cp: overwrite ‘/root/.kube/config’? y cp /etc/kubernetes/admin.conf /home/aiadmin/.kube/config cp: overwrite ‘/home/aiadmin/.kube/config’? y
k8s 설정 파일에 권한을 부여합니다.chown -R aiadmin:aiadmin /home/aiadmin/.kube/config chmod -R 777 /home/aiadmin/.kube/config chmod -R 777 /root/.kube/config
kubelet, docker 재시작
master 노드에서 작업합니다.systemctl stop kubelet systemctl stop docker systemctl daemon-reload systemctl start docker systemctl start kubelet
daemon-reload 작업은, 파일 시스템에서 변경된 구성을 가져오고 종속성 트리를 재 생성하기 위함입니다.
kubelet 동작을 확인합니다.systemctl status kubelet -l
Active: active (running) 임을 확인합니다.
worker join token 발행
master 노드에서 작업합니다.kubeadm token create --print-join-command > install_worker_join.sh cat install_worker_join.sh kubeadm join 192.168.50.177:6443 --token 1jd7ea.69e1f77w6dr8ynos --discovery-token-ca-cert-hash sha256:3e710df35d248466c0a41fea68c95382ded76bb1d161a85f75e8e6df21632cd6
IP와 Port를 확인합니다.
해당 파일은 모든 worker 노드에 적용합니다.worker 노드 설정 파일 삭제
worker 노드에서 작업합니다.systemctl stop kubelet systemctl daemon-reload rm -f /etc/kubernetes/kubelet.conf rm -f /etc/kubernetes/bootstrap-kubelet.conf rm -f /etc/kubernetes/pki/ca.crt
pki/ca.crt 는 join 실행 시 master의 ca.crt와 동일한 값으로 생성됩니다.
worker join
worker 노드에서 작업합니다.
master에서 생성한 install_worker_join.sh 를 복사합니다.bash install_worker_join.sh [preflight] Running pre-flight checks [WARNING SystemVerification]: this Docker version is not on the list of validated versions: 19.03.4. Latest validated version: 18.06 [discovery] Trying to connect to API Server "192.168.50.177:6443" [discovery] Created cluster-info discovery client, requesting info from "https://192.168.50.177:6443" [discovery] Requesting info from "https://192.168.50.177:6443" again to validate TLS against the pinned public key [discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server "192.168.50.177:6443" [discovery] Successfully established connection with API Server "192.168.50.177:6443" [join] Reading configuration from the cluster... [join] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml' [kubelet] Downloading configuration for the kubelet from the "kubelet-config-1.13" ConfigMap in the kube-system namespace [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml" [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env" [kubelet-start] Activating the kubelet service [tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap... [patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "nh-worker" as an annotation This node has joined the cluster: * Certificate signing request was sent to apiserver and a response was received. * The Kubelet was informed of the new secure connection details. Run 'kubectl get nodes' on the master to see this node join the cluster.
삭제했던 설정 파일이 생성되었는지 확인합니다.ll /etc/kubernetes total 8 -rw-------. 1 root root 1785 Sep 23 03:06 bootstrap-kubelet.conf -rw-------. 1 root root 1855 Sep 23 03:06 kubelet.conf ll /etc/kubernetes/pki/ total 4 -rw-r--r--. 1 root root 1025 Sep 23 03:06 ca.crt
k8s configmap 갱신
master 노드에서 작업합니다.
k8s 컨테이너 내부에서 참조하는 인증키 정보를 갱신하기 위해 configmap 삭제 후 새로 생성합니다.kubectl delete configmap kubectl-config -n kube-system configmap "kubectl-config" deleted kubectl delete configmap kubectl-config -n devai-cluster configmap "kubectl-config" deleted kubectl create configmap kubectl-config --from-file=/root/.kube/config -n kube-system configmap/kubectl-config created kubectl create configmap kubectl-config --from-file=/root/.kube/config -n devai-cluster configmap/kubectl-config created
k8s context namespace 변경
master 노드에서 작업합니다.
해당 작업은 root와 aiadmin 계정 별로 각각 적용해야 합니다.kubectl config set-context --current --namespace=devai-cluster Context "kubernetes-admin@kubernetes" modified.
kubectl-config 참조하는 pod 재시작
master 노드에서 작업합니다.
k8s configmap 중, kubectl-config가 있으며 해당 configmap 안에 k8s 인증키 정보가 들어있습니다.
인증키 정보가 갱신 되었기 때문에, kubectl-config도 재시작 하였으며
이 configmap을 참조하는 pod들도 재시작 해야 합니다.kubectl get cm --all-namespaces | grep kubectl devai-cluster kubectl-config 1 7m44s kube-system kubectl-config 1 7m47s
마무리
- k8s 인증서가 무엇 인지, 어떠한 파일이 있는지 알아보았습니다.
- 또한, k8s 인증서를 갱신하는 순서에 대해 알아보았습니다.
아티클이 유용했나요?
훌륭합니다!
피드백을 제공해 주셔서 감사합니다.
도움이 되지 못해 죄송합니다!
피드백을 제공해 주셔서 감사합니다.
피드백 전송
소중한 의견을 수렴하여 아티클을 개선하도록 노력하겠습니다.