Kubernetes API 서버 인증서에 도메인 추가하기
Kubernetes API 서버는 http 를 통해서 쿠버네티스에 대한 연산을 제공해 준다. kubectl 명령어로 실행되는 것들은 모두 API 서버를 거쳐서 이루어진다. 하지만 API 서버는 인증서를 기반으로 통신이 이루어지는데, 이 인증서에 기재된 도메인이나 IP가 아니면 통신이 이루어지지 않는다.
1 |
kubectl unable to connect to server: x509: certificate signed by unknown authority |
API 서버의 인증서는 SAN 인증서여야 한다. 도메인 리스트를 가지고 있는 SAN 인증서. 현재 API 서버의 인증서 상태는 다음과 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ 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 을 업데이트 해줘야 한다. 이를 위해서 먼저 기존이 설정을 뽑아내야 하는데 다음과 같이 하면 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
$ 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 를 추가해 준다. 이미 다른 도메인이 있다면 제거하나 추가할 수도 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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 파일을 백업한다.
1 |
$ sudo mv /etc/kubernetes/pki/apiserver.{crt,key} ~ |
kubeadm 을 이용해 새로운 인증서를 생성해 준다.
1 |
$ 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 서버 인증서를 인식하게 된다.
클러스터 설정 업데이트
마지막으로 클러스터 설정을 업데이트 해줘야 한다.
1 |
$ sudo kubeadm init phase upload-config kubeadm --config kubeadm.yaml |
이렇게 하면 최종적으로 Api 서버에 인증서가 업데이트 된다.