AWS Kubernetes Cluster에서 Private Docker Registry 구축하기

2 months ago   •   8 min read

By mAsh

메이아이는 영상 기반의 오프라인 방문자 분석 솔루션을 개발하여 제공하고 있습니다. 이에 엔지니어링 팀에서는 영상 분석 프로세스를 자동화하는 데 있어서 Kubernetes를 이용한 cluster를 구성하는 것이 유용할 것이라고 판단했고, 현재 구축하고 있습니다.

다수의 node들로 구성된 Kubernetes cluster에서 docker registry로 이미지를 관리하는 것은 필수라고 할 수 있습니다. 하지만 Docker Hub은 기본적으로 모든 이미지가 공개이기 때문에, 비공개 이미지를 관리하려면 유료 계정으로 private repository를 사용하거나, 직접 private docker registry를 구축해야 합니다. 메이아이에서 사용하는 딥러닝 이미지는 10GB 내외로 상당히 크기 때문에, pull speed를 고려하여 직접 private docker registry를 구축하기로 결정했습니다.

본 글에서는 kops를 이용해 AWS에서 Kubernetes cluster를 이미 구축했다는 것을 가정하고 있습니다.

1. PersistenceVolumeClaim(PVC) 생성하기

우선 이미지를 영구적으로 보관할 Persistence Volume(PV)을 생성해야 합니다. kops를 사용해 클러스터를 구축했다면 아래와 같은 Storage Class들이 이미 존재할 것입니다. 이것을 사용하면 PV 생성 없이 동적으로 EBS Volume을 할당하는 PVC를 만들 수 있습니다.

250GB의 EBS Volume을 지정하는 PVC를 만들었습니다.

2. 계정 생성하기

Private docker registry에서 사용할 docker 계정을 생성해야 합니다. htpasswd를 이용해서 registry 서버에서 사용할 인증정보를 생성합니다. username은 마음대로 변경하시면 됩니다.

3. Deployment 생성하기

이제 Private Docker Registry 서버의 Deployment를 생성합니다. 앞서 생성한 PVC와 인증정보가 사용된 것을 볼 수 있습니다. 인증을 강제하고 싶지 않다면, REGISTRY_AUTH로 시작하는 환경 변수들을 모두 지워주시면 됩니다.

위와 같이 PVC가 Bound되고 Deployment가 READY state라면, 지금까지 문제 없이 진행된 것입니다.

4. Ingress 생성하기

이제 서버가 deploy되었으니, 이것을 외부에 공개하는 Ingress를 생성해 보겠습니다. 먼저 kubectl expose 명령어로 서버를 Kubernetes 내부에 공개합니다.

다음으로 Ingress를 생성해 서버를 Kubernetes 외부에 공개합니다. 본 글에서는 ingress-nginx를 Ingress Controller로 사용하고 있다고 가정합니다. (별도의 설치가 필요합니다)

이 때 registry.domain.com은 Private Docker Registry의 도메인입니다. 커스텀 도메인을 사용하려면 해당 도메인을 입력하시면 되고, AWS의 Elastic Load Balancer(ELB)가 기본으로 제공하는 도메인을 사용하려면 host 필드를 삭제하고 생성하면 됩니다. ELB 도메인은 여러모로 불편한 점이 많기 때문에, 별도의 도메인을 이용하는 것을 추천합니다.

위와 같이 나온다면 성공적으로 Ingress가 생성된 것입니다. AddressPath에 오류가 없는 지 체크해 주시면 됩니다.

5. ELB로 트래픽 라우팅

다음으로는 보유한 도메인의 트래픽을 ELB로 라우팅 해보겠습니다. 본 글에서는 도메인을 AWS Route 53에서 관리하는 도메인을 다루지만, 다른 서비스에서도 동일하게 진행하시면 됩니다.

저희 메이아이의 도메인 may-i.io의 서브도메인인 docker.registry.may-i.io에 Private Docker Registry를 연결한다고 가정하겠습니다. 먼저 호스팅 영역에 들어가서 레코드 생성을 클릭합니다.

단순 라우팅 -> 단순 레코드 정의에서 다음과 같이 선택합니다. ELB는 앞서 4번에서 설정한 Ingress의 Address와 동일한 것으로 선택하시면 됩니다.

이 파트는 아래 글을 참조하여 작성하였습니다.

Routing traffic to an ELB load balancer - Amazon Route 53
Route queries using Route 53 to an ELB Classic, Application, or Network Load Balancer.

6. HTTPS 적용하기

레코드를 생성하고 해당 도메인으로 docker pull을 해 보면 오류가 날 것입니다. 왜냐 하면, docker client는 HTTPS를 지원하는 docker registry만 연결하기 때문입니다. 몇 가지 우회하는 방법들이 있지만, 본 글에서는 cert-manager와 Let’s Encrypt를 이용해서 HTTPS를 적용하도록 하겠습니다.

cert-manager는 Kubernetes에서의 SSL 인증서 관리를 편하게 해 주는 프로젝트입니다. 위 명령어를 실행하면cert-manager 라는 별도의 네임스페이스에 설치됩니다.

위와 같은 ClusterIssuer 리소스를 생성합니다. email 필드만 사용하는 이메일 주소로 변경하시면 됩니다.

이제 기존의 Ingress에 HTTPS를 적용해 보겠습니다.

앞서 생성한 Ingress를 다음과 같이 수정해줍니다. 그리고 인터넷 브라우저로 HTTPS를 적용한 도메인에 접속해서, Kubernetes fake 인증서가 발급된 것을 확인하면 성공입니다. 이것을 확인한 후 위의 letsencrypt-stagingletsencrypt-prod 로 바꿔주게 되면, 잠시 후 성공적으로 Let’s Encrypt 인증서가 발급된 것을 확인할 수 있습니다.

7. 테스트

이제 지금까지 잘 되었는지 docker push 테스트를 해보겠습니다. Docker가 설치된 아무 로컬 머신에서 다음 명령어를 입력해봅니다.

다음과 같이 이미지 push가 완료되면 성공입니다!

8. Service Account에 인증 정보 저장하기

마지막으로 2. 계정 생성하기에서 생성한 것과 동일한 인증정보를 가진 Secret을 생성하고, Service Account의 ImagePullSecrets에 등록합니다. 위에서 htpasswd로 생성한 것과는 포맷이 다르기 때문에, 같은 인증정보로 2개의 secret을 생성하는 것입니다. 이 작업을 마치고 나면 모든 노드가 Private Docker Registry의 계정 인증정보를 가지고 있게 됩니다.

이 인증 정보를 가지고 docker pull 테스트를 하는 방법은 각각의 클러스터 환경에 따라 다르기 때문에, 개인의 몫에 맡기도록 하겠습니다.  :)

Spread the word

Keep reading