Kubernetes 클러스터에 사설 레지스트리 인증서 주입 (DaemonSet 활용)
사설 이미지 레지스트리(예: Harbor)를 자체 서명된(self-signed) SSL 인증서와 함께 사용하는 경우, Kubernetes 클러스터의 모든 노드가 해당 레지스트리를 신뢰하도록 인증서를 설치해야 함. 이 과정을 수동으로 진행하는 것은 비효율적이므로, ConfigMap과 DaemonSet을 활용하여 자동화함.
ConfigMap의 개념과 활용
ConfigMap은 Kubernetes에서 민감하지 않은 설정 데이터(configuration data)를 키-값(key-value) 쌍으로 저장하는 API 객체임. 애플리케이션 코드와 설정을 분리하여 컨테이너 이미지의 재사용성을 높이고, 설정을 중앙에서 관리할 수 있게 해줌.
클러스터 내 활용 방안:
- 환경 변수 주입: Pod의 컨테이너에 환경 변수로 값을 전달함.
- 커맨드 라인 인자: 컨테이너 실행 시 필요한 인자로 값을 전달함.
- 볼륨 마운트: 설정 파일 전체를 Pod 내부의 특정 경로에 파일 형태로 마운트함.
본 프로젝트에서는 볼륨 마운트 방식을 사용하여, 레지스트리의 CA 인증서(ca.crt) 파일을 ConfigMap에 저장한 뒤, 이 ConfigMap을 모든 노드에서 실행되는 Pod에 파일 시스템 볼륨으로 연결했음. 이를 통해 각 노드에서 인증서 파일에 안전하고 일관되게 접근할 수 있도록 구성함.
적용 과정
1단계: 인증서를 담은 ConfigMap 생성
먼저, 클러스터의 모든 노드에 배포할 CA 인증서 파일을 ConfigMap으로 생성함.
# 로컬의 ca.crt 파일을 'harbor-ca'라는 이름의 ConfigMap으로 생성함.
# ca.crt라는 키에 파일 내용이 값으로 저장됨.
# kube-system 네임스페이스에 생성하여 클러스터 전역 서비스로 관리함.
kubectl create configmap harbor-ca --from-file=ca.crt=./ca.crt -n kube-system
2단계: 인증서 주입을 위한 DaemonSet 생성
클러스터의 모든 노드에서 인증서 설치 작업을 수행할 Pod를 하나씩 실행하기 위해 DaemonSet을 정의했음. initContainer를 사용하여 Pod의 메인 컨테이너가 시작되기 전에 필요한 모든 설치 작업을 완료하도록 설계함.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: harbor-cert-injector
namespace: kube-system
labels:
app: harbor-cert-injector
spec:
selector:
matchLabels:
name: harbor-cert-injector
template:
metadata:
labels:
name: harbor-cert-injector
spec:
# initContainer: 메인 컨테이너 실행 전에 일회성 작업을 수행함.
initContainers:
- name: cert-injector
image: alpine:latest # 가벼운 이미지 사용
# 호스트 노드의 파일 시스템을 직접 수정해야 하므로, 컨테이너에 높은 권한을 부여함.
securityContext:
privileged: true
command:
- /bin/sh
- -c
- |
set -x
# --- 경로 변수 설정 ---
CONFIGMAP_CERT_FILE="/certs/ca.crt"
HOST_CONTAINERD_CERT_PATH="/host/etc/containerd/certs.d/harbor.192.168.0.110.nip.io"
HOST_SYSTEM_CERT_FILE="/host/usr/local/share/ca-certificates/harbor-ca.crt"
# --- 1. Containerd용 인증서 설치 ---
# containerd가 사설 레지스트리 이미지를 pull 할 수 있도록 인증서를 복사함.
echo "Creating directory for containerd on host: $HOST_CONTAINERD_CERT_PATH"
mkdir -p $HOST_CONTAINERD_CERT_PATH
cp $CONFIGMAP_CERT_FILE "$HOST_CONTAINERD_CERT_PATH/ca.crt"
# --- 2. 호스트 시스템용 인증서 설치 ---
# 노드 자체의 신뢰 저장소에 인증서를 추가함.
echo "Copying certificate for the host OS..."
cp $CONFIGMAP_CERT_FILE $HOST_SYSTEM_CERT_FILE
# --- 3. 호스트 시스템 인증서 업데이트 ---
# chroot: 컨테이너 내부가 아닌, 마운트된 호스트의 루트 파일 시스템(/host)을 기준으로 명령을 실행함.
echo "Updating host OS certificates..."
chroot /host update-ca-certificates
echo "All certificates installed and updated successfully."
volumeMounts:
# 호스트의 루트(/) 파일 시스템을 컨테이너의 /host 디렉터리에 마운트함.
- name: host-root
mountPath: /host
# 1단계에서 생성한 ConfigMap을 컨테이너의 /certs 디렉터리에 마운트함.
- name: cert-configmap
mountPath: /certs
# 실제 작업을 수행하는 메인 컨테이너는 아무 작업 없이 대기만 함.
# initContainer가 모든 작업을 완료한 후 Pod가 Running 상태를 유지하도록 함.
containers:
- name: pauser
image: registry.k8s.io/pause:3.9
volumes:
- name: host-root
hostPath:
path: /
- name: cert-configmap
configMap:
name: harbor-ca # 1단계에서 생성한 ConfigMap 이름
3단계: DaemonSet 적용
작성한 DaemonSet YAML 파일을 클러스터에 적용.
kubectl apply -f cert-injector-daemonset.yaml
이 명령어를 실행하면, Kubernetes 클러스터의 각 노드에 harbor-cert-injector Pod가 하나씩 생성되고, initContainer가 실행되어 인증서 설치 작업을 자동으로 수행함.
4단계: 노드 재시작 (필요시)
containerd와 같은 컨테이너 런타임은 서비스 재시작만으로도 새 인증서를 인식하는 경우가 많지만, 호스트 OS의 시스템 전반에 걸쳐 인증서 변경 사항이 안정적으로 적용되도록 하려면 노드를 재시작하는 것이 가장 확실함.
drain: 재시작 전에kubectl drain <node-name>명령을 사용하여 해당 노드의 모든 워크로드를 다른 노드로 안전하게 이동시킴.- 재시작: 노드를 재부팅하여 모든 시스템 서비스가 업데이트된 인증서 신뢰 저장소를 로드하도록 함.
'인프라' 카테고리의 다른 글
| Tailscale 로 zerotrust 아키텍쳐 적용하기 (1) | 2025.07.16 |
|---|---|
| [K8S] Harbor : LoadBalancer 및 TLS 설정 (0) | 2025.06.17 |
| [K8S] 클러스터의 리소스 분배 전략 (0) | 2025.06.15 |
| [Jenkins] Jenkins 빌드 머신 설정 하기 (0) | 2025.06.14 |
| [Jenkins] Helm으로 Jenkins 설치하기 (0) | 2025.06.13 |