K8S 인증서 갱신

작성자 김아름 수정일 2022-10-12 08:48

#k8s인증서, #인증서갱신, #kubernetes, #쿠버네티스, #인증서

들어가며

  • 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 계정이 필요합니다.


  1. 기존 인증서 만료 일자 확인
    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


  2. 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"}


  3. 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 구동 중임을 확인

  4. 기존 인증서 백업
    /etc/kubernetes 디렉터리를 백업합니다.
    cp -r kubernetes/ kubernetes.backup


  5. 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 노드에서 작업합니다.

  1. 기존 인증서 백업
    cp -r /etc/kubernetes/ /etc/kubernetes.back

  2. install_worker_join.sh 백업
    처음 cluster 구축 시, worker join 쉘 스크립트가 있다면, 백업합니다.

    cp install_worker_join.sh install_worker_join.sh.back


kubernetes 인증서 갱신

작업 순서는 아래와 같습니다.

  1. master 인증서 갱신

  2. master kubelet, docker 재시작

  3. master에서 worker join token 발행

  4. worker 노드 설정 파일 삭제

  5. worker join

  6. k8s configmap 갱신

  7. k8s context namespace 변경

  8. kubectl-configmap 참조하는 pod 재시작


  1. 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


  2. 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) 임을 확인합니다.

  3. 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 노드에 적용합니다.

  4. 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와 동일한 값으로 생성됩니다.

  5. 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


  6. 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


  7. k8s context namespace 변경
    master 노드에서 작업합니다.
    해당 작업은 root와 aiadmin 계정 별로 각각 적용해야 합니다.

    kubectl config set-context --current --namespace=devai-cluster
    Context "kubernetes-admin@kubernetes" modified.


  8. 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 인증서를 갱신하는 순서에 대해 알아보았습니다.

아티클이 유용했나요?

훌륭합니다!

피드백을 제공해 주셔서 감사합니다.

도움이 되지 못해 죄송합니다!

피드백을 제공해 주셔서 감사합니다.

아티클을 개선할 수 있는 방법을 알려주세요!

최소 하나의 이유를 선택하세요
CAPTCHA 확인이 필요합니다.

피드백 전송

소중한 의견을 수렴하여 아티클을 개선하도록 노력하겠습니다.

02-558-8300