[K8s] 쿠버네티스 사설 레지스트리 구축 및 x509: certificate signed by unknown authority 에러 해결 가이드
쿠버네티스(Kubernetes) 환경에서 보안상의 이유로 사설 레지스트리(Private Registry)를 운영하다 보면 반드시 마주치는 문제가 있습니다. 바로 HTTPS/TLS 인증서 관련 에러입니다.
특히 ctr 명령어로는 이미지가 잘 당겨지는데, 정작 kubectl로 배포하면 ImagePullBackOff와 함께 "x509: certificate signed by unknown authority" 에러가 발생하는 상황에서의 완벽한 해결법을 정리합니다.
🟢 사설 TLS 인증서 생성 (OpenSSL)
사설 레지스트리를 HTTPS로 운영하기 위해서는 자체 서명 인증서(Self-Signed Certificate)가 필요합니다. 이때 주의할 점은 IP 주소를 인증서에 명시(SAN 설정)해야 한다는 것입니다.
인증서 생성 명령어
마스터 노드에서 아래 명령어를 실행하여 10년(3650일) 유효한 인증서를 생성합니다.
Bash
openssl req -newkey rsa:4096 -nodes -sha256 -keyout domain.key \
-x509 -days 3650 -out domain.crt \
-subj "/CN=10.202.2.129" \
-addext "subjectAltName = IP:10.202.2.129"
💡 왜 subjectAltName이 중요한가요?
최근의 컨테이너 런타임(containerd, Docker 등)은 보안상의 이유로 일반적인 Common Name(CN)만으로는 인증을 통과시키지 않습니다. subjectAltName (SAN) 필드에 레지스트리의 IP 주소가 정확히 명시되어야만 x509: certificate signed by unknown authority 에러를 방지할 수 있습니다.
🟢 쿠버네티스 Secret 등록
생성된 domain.crt와 domain.key를 쿠버네티스 클러스터에서 사용할 수 있도록 Secret 객체로 등록합니다.
Bash
# 기존 시크릿이 있다면 삭제 후 재생성
kubectl delete secret registry-tls --ignore-not-found
# TLS 타입의 시크릿 생성
kubectl create secret tls registry-tls \
--cert=domain.crt \
--key=domain.key
1. 사설 레지스트리(Private Registry) 배포 설정
사설 레지스트리는 내부망에서 이미지를 안전하게 관리하기 위해 필수적입니다. 아래는 TLS 인증서를 적용한 registry.yaml 예시입니다.
Registry Deployment & Service YAML
YAML
apiVersion: apps/v1
kind: Deployment
metadata:
name: private-registry
spec:
replicas: 1
selector:
matchLabels:
app: registry
template:
metadata:
labels:
app: registry
spec:
dnsPolicy: ClusterFirstWithHostNet
containers:
- name: registry
image: registry:2
env:
- name: REGISTRY_HTTP_ADDR
value: "0.0.0.0:30500"
- name: REGISTRY_HTTP_TLS_CERTIFICATE
value: /certs/tls.crt
- name: REGISTRY_HTTP_TLS_KEY
value: /certs/tls.key
ports:
- containerPort: 5000
volumeMounts:
- name: storage
mountPath: /var/lib/registry
- name: cert-vol
mountPath: /certs
readOnly: true
volumes:
- name: storage
persistentVolumeClaim:
claimName: watercluster-pvc
- name: cert-vol
secret:
secretName: registry-tls
---
apiVersion: v1
kind: Service
metadata:
name: registry-service
spec:
type: NodePort
selector:
app: registry
ports:
- port: 30500
targetPort: 30500
nodePort: 30500
2. 트러블슈팅: x509 인증서 에러 해결 (CentOS/RHEL)
사설 인증서(Self-Signed Certificate)를 사용하면 쿠버네티스 노드들은 해당 레지스트리를 신뢰하지 않습니다. 이를 해결하기 위해 모든 마스터 및 워커 노드에서 다음 작업을 수행해야 합니다.
단계 1: 시스템 인증서 저장소에 등록
레지스트리 서버에서 인증서를 추출하여 OS 신뢰 목록에 추가합니다.
Bash
# 1. 인증서 추출 (129번은 레지스트리 IP)
openssl s_client -showcerts -connect 10.202.2.129:30500 </dev/null 2>/dev/null | openssl x509 -outform PEM > /tmp/registry.crt
# 2. 신뢰 저장소 경로로 복사
sudo cp /tmp/registry.crt /etc/pki/ca-trust/source/anchors/watercluster-registry.crt
# 3. 인증서 갱신
sudo update-ca-trust extract
단계 2: containerd 설정 최적화 (핵심 포인트)
많은 분이 /etc/containerd/config.toml에 config_path를 설정하지만, 사설 인증서를 OS에 등록했다면 이 설정이 오히려 충돌을 일으킬 수 있습니다.
Bash
sudo vi /etc/containerd/config.toml
수정 내용: 아래 설정을 찾아 주석 처리합니다.
Ini, TOML
[plugins."io.containerd.grpc.v1.cri".registry]
# config_path = "/etc/containerd/certs.d" <-- 주석 처리
이렇게 하면 containerd가 개별 설정 대신 시스템 기본 인증서 저장소를 참조하게 되어 훨씬 안정적입니다.
단계 3: 서비스 완전 재시작
설정 적용을 위해 엔진을 새로고침합니다.
Bash
sudo systemctl daemon-reload
sudo systemctl restart containerd
sudo systemctl restart kubelet
3. 대규모 환경에서의 자동화 (Ansible)
관리해야 할 서버가 100대 이상이라면 수동 작업은 불가능합니다. Ansible을 활용하면 폐쇄망 환경에서도 안전하고 빠르게 인증서를 배포할 수 있습니다.
- 에이전트 미설치(Agentless): SSH만 연결되면 즉시 실행 가능.
- 멱등성 보장: 여러 번 실행해도 동일한 설정 상태 유지.
- 폐쇄망 최적화: 외부 인터넷 없이도 내부망 내에서 모든 노드 제어 가능.
4. 서비스 노출 시 포트 매핑 이해
외부 접속을 위해 Service의 ports 설정을 할 때 다음의 구분을 명확히 해야 접속 오류를 방지할 수 있습니다.
| 포트 항목 | 설명 | 예시 |
|---|---|---|
| port | 클러스터 내부 서비스 IP에서 사용하는 포트 | 8080 |
| targetPort | 컨테이너 내부 앱(Tomcat 등)이 실제 리스닝하는 포트 | 8080 |
| nodePort | 외부에서 노드 IP를 통해 접속할 때 사용하는 포트 | 30080 |
요약 및 결론
- 사설 레지스트리 사용 시 인증서 에러는 필수 관문입니다.
- OS 레벨(
update-ca-trust)에 인증서를 등록하는 것이 가장 확실한 방법입니다. containerd의config_path설정 충돌을 주의해야 합니다.- 서버 대수가 많다면 Ansible과 같은 자동화 도구 도입을 적극 고려하세요.
도움이 되셨다면 공감과 댓글 부탁드립니다! 추가적인 질문은 언제든 환영합니다.
'나의 주니어 개발 일기 > 쿠버네티스' 카테고리의 다른 글
| 쿠버네티스 환경세팅시 Could not find a version that satisfies the requirement ansible==8.5.0 오류 발생 (0) | 2024.03.08 |
|---|
