EKS에서 webhook 사용하기
June 2023 (410 Words, 3 Minutes)
EKS에서 webhook 승인하기
EKS 클러스터를 장기간 사용하다 보니, 오래된 버전의 프로젝트들을 업그레이드 해야 하는 시기가 왔다.
관리 중인 클러스터에서는 pod에서 EBS 를 마운트시키는 시스템이기 때문에, volumesnapshot을 생성하는 기능을 위해 external snapshotter이라는 프로젝트를 사용 중이었다.
이 프로젝트를 업그레이드한 후에, 이 프로젝트에서 snapshot을 생성하는 과정에서 이 요청이 정상적인 요청인지 확인하는 webhook이 있다는 것을 확인했다.
온프레미스 클러스터에서도 같은 프로젝트를 사용하고 있었고, 온프레미스에서는 일련의 업데이트과정에 전혀 문제가 없는것을 확인했다.
근데 EKS 클러스터에서 같은 업그레이드를 하던중 문제를 겪어 무슨일인가 확인을 하던중, cert 부분에서 문제가 발생하는것을 확인했다.
우선 webhook이 정상적으로 승인이 되기 위한 과정은 다음과 같다
서버 인증서/키 CSR 생성 및 k8s API로 전송
CSR이 생성되었는지 확인
서명된 인증서 승인 및 가져오기
인증서가 서명되었는지 확인
등의 과정을 거쳐, 정상적인 인증서/키로 요청하는 것인지 검증하는 과정을 갖는다.
CSR를 생성해서 승인하면
approved 로 변경된 후, issued 라는 문구가 발생해야 하는데
여기서 issue가 안되는 현상이었다.
자세히 찾아보니 자체 인증서인
signerName 이라는 부분에서 발생하는 문제였다.
# create server cert/key CSR and send to k8s API
cat <<EOF | kubectl create -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: ${csrName}
spec:
groups:
- system:authenticated
request: $(cat ${tmpdir}/server.csr | base64 | tr -d '\n')
signerName: kubernetes.io/kubelet-serving
usages:
- digital signature
- key encipherment
- server auth
EOF
쿠버네티스에서 제공하는 SignerName들이다.
kubernetes.io/kube-apiserver-client
kube-apiserver에 대한 인증을 요청하는 클라이언트 인증서를 생성하는 데 사용됩니다. 이 인증서는 일반적으로 API 서버에 대한 인증에 사용되는 클라이언트 인증서입니다.
kubernetes.io/kube-apiserver-client-kubelet
kubelet이 kube-apiserver에 연결하는 데 사용하는 특정 클라이언트 인증서를 생성하는 데 사용됩니다.
kubernetes.io/kubelet-serving
kubelet의 HTTPS 서버 엔드포인트를 위한 서버 인증서를 생성하는 데 사용됩니다. 이 인증서는 kubelet의 HTTPS 엔드포인트가 신뢰할 수 있는지 확인하는 데 사용됩니다.
kubernetes.io/legacy-unknown
Kubernetes 1.18 이전에 사용되었으며, 이 signerName에 대한 요청은 kube-controller-manager에 의해 자동으로 승인됩니다. 이 signerName는 서버나 클라이언트 인증서 모두에 사용할 수 있습니다.
Certificates and Certificate Signing Requests
여기서 signerName: kuberntes.io/kubelet-serving 이라는 자체인증서를 이용하기로 되어있다.
하지만 EKS에서는 1.21버젼 이후부터는 자체 인증서의 사용을 방지하기로 했다.
기존에 발급된 CSR들의 경우 만료될 때까지 사용 가능하지만, 신규 발급이 방지된 것이고 자세한 내용은 링크를 참조하면 자세히 볼 수 있다.
요약하자면 Amazon EKS 1.21 이후 버전에서는 기본 제공 서명자를 사용하는 대신 사용자 지정 서명자를 사용하여 인증서를 생성하고 관리해야 한다.
# create server cert/key CSR and send to k8s API
cat <<EOF | kubectl create -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: ${csrName}
spec:
groups:
- system:authenticated
request: $(cat ${tmpdir}/server.csr | base64 | tr -d '\n')
signerName: kubernetes.io/kubelet-serving
usages:
- digital signature
- key encipherment
- server auth
EOF
따라서 저 Script의 signerName을
beta.eks.amazonaws.com/app-serving로 변경해주었다.
로 변경해주었다.
저 CSR 를 생성하는 코드 외에도 다른 script들은 수정할 필요 없지만, 한 번쯤 살펴보자.
설치하고자 하는 것들이 어떤 구성 요소들로 이루어져 있고, 어떤 방식으로 동작이 이루어지는지 파악해두면 참 좋을 것 같다.
쿠버네티스에서 admission webhook을 이용한 동작들이 빈번하게 이루어져 있는 것으로 보아 자세히 공부해야겠다는 생각이 든다.