Kubernetes API 서버 인증서에 도메인 추가하기

Kubernetes API 서버는 http 를 통해서 쿠버네티스에 대한 연산을 제공해 준다. kubectl 명령어로 실행되는 것들은 모두 API 서버를 거쳐서 이루어진다. 하지만 API 서버는 인증서를 기반으로 통신이 이루어지는데, 이 인증서에 기재된 도메인이나 IP가 아니면 통신이 이루어지지 않는다.

kubectl unable to connect to server: x509: certificate signed by unknown authority

API 서버의 인증서는 SAN 인증서여야 한다. 도메인 리스트를 가지고 있는 SAN 인증서. 현재 API 서버의 인증서 상태는 다음과 같다.

$ openssl x509 -text -in /etc/kubernetes/pki/apiserver.crt -noout
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Authority Key Identifier: 
                keyid:98:B6:19:7B:C4:FF:03:49:74:7D:F3:F1:7E:31:67:91:D9:2E:B5:EA

            X509v3 Subject Alternative Name: 
                DNS:haproxy2.systemv.local, DNS:kmaster, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:ol85.systemv.local, DNS:rhel8.systemv.local, IP Address:10.96.0.1, IP Address:192.168.96.23, IP Address:192.168.96.30, IP Address:192.168.96.7
    Signature Algorithm: sha256WithRSAEncryption

위 apiserver.crt 파일 상태를 보면 SAN 에 이미 도메인과 IP 들이 들어가 있다. 내용을 보면 haproxy2.systemv.local 도메인, 192.168.96.7 IP 가 들어가 있는데 이 서버에서 API 서버와 통신이 가능하다.

만일 추가적으로 도메인, IP 를 추가하고 싶다면 어떻게 해야할까? 이에 대해서 알아본다.

kubeadm-config 업데이트

kubeadm-config 라고 불리는 ConfigMap 을 업데이트 해줘야 한다. 이를 위해서 먼저 기존이 설정을 뽑아내야 하는데 다음과 같이 하면 된다.

$ kubectl -n kube-system get configmap kubeadm-config -o jsonpath='{.data.ClusterConfiguration}' > kubeadm.yaml
$ cat kubeadm.yaml
apiServer:
  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: k8s.gcr.io
kind: ClusterConfiguration
kubernetesVersion: v1.14.4
networking:
  dnsDomain: cluster.local
  podSubnet: ""
  serviceSubnet: 10.96.0.0/12
scheduler: {}

파일 내용을 보면 SAN 리스트가 없다. 도메인이나 IP 를 SAN 으로 추가하기 위해서 apiServer 아래에 certSANs 를 추가해 준다. 이미 다른 도메인이 있다면 제거하나 추가할 수도 있다.

apiServer:
  certSANs:
  - 192.168.96.23
  - rhel8.systemv.local
  - 192.168.96.30
  - ol85.systemv.local
  - 192.168.96.7
  - haproxy2.systemv.local
  extraArgs:
    authorization-mode: Node,RBAC
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki

위와같이 SAN 에 추가할 도메인, IP를 적어준다.

apiserver.crt 파일 업데이트

기존의 존재하는 apiserver.crt 파일을 백업한다.

$ sudo mv /etc/kubernetes/pki/apiserver.{crt,key} ~

kubeadm 을 이용해 새로운 인증서를 생성해 준다.

$ sudo kubeadm init phase certs apiserver --config kubeadm.yaml

새로운 인증서가 생성되면서 certSANs 에 설정된 도메인, IP 주소들이 모두 인증서에 업데이트 된다. 이제 새로운 인증서를 가지고 구동되도록 api 서버를 재시작 시켜줘야 한다.

Docker 기반의 경우에는 다음과 같이 하면 된다.

  • docker ps | grep kube-apiserver 명령어로 kube-apiserver 의 컨테이너 ID 를 파악한다.
  • docker kill <containerID> 로 컨테이너를 킬(kill) 한다. 이렇게 하면 api 서버가 재시작 된다.

만약 containerd 를 이용하는 경우에는 다음과 같이 하면 된다.

  • crictl pods | grep kube-apiserver 로 kube-apiserver 의 Pod ID 를 파악한다.
  • crictl stopp <pod-id> 로 pod 를 정지
  • crictl rmp <pod-id> 로 pod 를 제거 합니다. 이렇게하면 다시 Pod 가 재시작 된다.

위와같이 Api 서버가 재시작되면서 새롭게 만들어진 API 서버 인증서를 인식하게 된다.

클러스터 설정 업데이트

마지막으로 클러스터 설정을 업데이트 해줘야 한다.

$ sudo kubeadm init phase upload-config kubeadm --config kubeadm.yaml

이렇게 하면 최종적으로 Api 서버에 인증서가 업데이트 된다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다