블로그로 돌아가기

쿠버네티스 클러스터에서 프록시 설정하기: DevOps 엔지니어를 위한 완벽 가이드

Kubernetes에서 프록시 설정에 대한 완벽한 가이드: 환경 변수 구성, Docker, containerd, kubectl 설정 및 네트워크 접근과 관련된 일반적인 문제 해결.

📅2026년 2월 17일
```html

기업 환경이나 방화벽 뒤에서 Kubernetes를 배포할 때 외부 리소스에 접근하기 위해 프록시 서버를 설정해야 할 필요가 자주 발생합니다. 이는 컨테이너 이미지 다운로드, 패키지 업데이트 및 외부 API와의 상호작용에 매우 중요합니다. 이 가이드에서는 Kubernetes에서 프록시 설정의 모든 수준을 다루겠습니다. 노드 구성부터 개별 포드까지 설명합니다.

Kubernetes 클러스터에서 프록시가 필요한 이유

기업 환경의 Kubernetes 클러스터는 종종 인터넷 접근이 제한된 격리된 네트워크에서 운영됩니다. 프록시 서버는 여러 가지 중요한 작업을 수행합니다:

  • 컨테이너 이미지 다운로드 — Docker Hub, Google Container Registry, 개인 레지스트리 등은 외부 접근이 필요합니다.
  • 패키지 업데이트 — 컨테이너 내에서 apt, yum, pip를 통해 의존성 설치.
  • 외부 API 접근 — 클라우드 서비스, 모니터링, 로깅과의 통합.
  • 보안 — 트래픽 제어, 도메인 필터링, 요청 로깅.
  • 캐싱 — 동일한 리소스에 대한 반복 요청의 속도 향상.

올바른 프록시 설정이 없으면 "image pull failed", "connection timeout" 또는 "network unreachable"와 같은 오류가 발생할 수 있습니다. 이는 특히 자동화된 CI/CD 파이프라인에서 매우 중요하며, 매초의 다운타임이 비용으로 이어질 수 있습니다.

중요: 기업 클러스터의 경우 데이터 센터 프록시를 사용하는 것이 좋습니다. 높은 대역폭과 안정적인 연결이 필요하며, 이는 전체 인프라의 가용성에 영향을 미칩니다.

Kubernetes에서 프록시 설정 수준

Kubernetes는 다층 아키텍처를 가지고 있으며, 각 수준에서 작업에 따라 프록시를 설정해야 합니다:

수준 설정할 항목 필요한 이유
운영 체제 시스템 환경 변수 유틸리티 접근 (curl, wget, apt)
Container Runtime (Docker/containerd) 데몬 구성 컨테이너 이미지 다운로드
kubelet kubelet 시작 매개변수 API 서버와의 상호작용
포드 (Pods) 매니페스트의 환경 변수 애플리케이션의 외부 API 접근
kubectl 클라이언트 환경 변수 프록시를 통한 클러스터 관리

각 수준은 별도의 설정이 필요하며, 이를 пропуск하면 문제가 발생할 수 있습니다. 예를 들어, Docker에 대해서만 프록시를 설정하고 포드에 대해서는 설정하지 않으면 이미지는 다운로드되지만 컨테이너 내의 애플리케이션은 외부 API에 접근할 수 없습니다.

Docker 및 containerd를 위한 프록시 설정

Container runtime은 외부 레지스트리에서 컨테이너 이미지를 다운로드하는 책임이 있는 첫 번째 구성 요소입니다. 두 가지 인기 있는 runtime에 대한 설정을 살펴보겠습니다.

Docker를 위한 프록시 설정

Docker를 위해서는 systemd drop-in 파일을 생성하여 Docker 서비스에 환경 변수를 추가해야 합니다:

# 구성 디렉토리 생성
sudo mkdir -p /etc/systemd/system/docker.service.d

# 프록시 설정 파일 생성
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://proxy.company.com:8080"
Environment="HTTPS_PROXY=http://proxy.company.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.cluster.local,.svc"
EOF

# systemd 구성 재로드
sudo systemctl daemon-reload

# Docker 재시작
sudo systemctl restart docker

# 설정이 적용되었는지 확인
sudo systemctl show --property=Environment docker

이후 Docker는 프록시 서버를 통해 이미지를 다운로드할 수 있습니다. 다음 명령어로 작동을 확인할 수 있습니다:

docker pull nginx:latest

containerd를 위한 프록시 설정

Containerd는 현대 Kubernetes 클러스터에서 기본 container runtime으로 사용됩니다. 프록시 설정은 약간 다릅니다:

# 구성 디렉토리 생성
sudo mkdir -p /etc/systemd/system/containerd.service.d

# 프록시 설정 파일 생성
sudo tee /etc/systemd/system/containerd.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://proxy.company.com:8080"
Environment="HTTPS_PROXY=http://proxy.company.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.cluster.local,.svc"
EOF

# 구성 재로드
sudo systemctl daemon-reload
sudo systemctl restart containerd

# 상태 확인
sudo systemctl status containerd

팁: 개인 컨테이너 레지스트리를 사용하는 경우 NO_PROXY에 해당 도메인을 추가하여 불필요한 지연과 SSL 인증서 문제를 피하십시오.

kubelet을 위한 프록시 구성

Kubelet은 클러스터의 각 노드에서 작동하는 Kubernetes 에이전트입니다. API 서버와 외부 리소스에 접근할 수 있어야 합니다. 설정은 Kubernetes 설치 방법에 따라 다릅니다.

kubeadm 클러스터의 경우

kubeadm을 사용하는 경우 systemd를 통해 프록시를 설정합니다:

# kubelet 구성 디렉토리 생성
sudo mkdir -p /etc/systemd/system/kubelet.service.d

# 프록시 설정 파일 생성
sudo tee /etc/systemd/system/kubelet.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://proxy.company.com:8080"
Environment="HTTPS_PROXY=http://proxy.company.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,10.96.0.0/12,10.244.0.0/16,.cluster.local,.svc"
EOF

# kubelet 재시작
sudo systemctl daemon-reload
sudo systemctl restart kubelet

관리형 Kubernetes (EKS, GKE, AKS)의 경우

관리형 Kubernetes 서비스에서는 kubelet 설정이 일반적으로 노드의 시작 매개변수 또는 사용자 데이터 스크립트를 통해 수행됩니다. 예를 들어 AWS EKS의 경우:

#!/bin/bash
# EKS 워커 노드를 위한 사용자 데이터 스크립트

# 시스템을 위한 프록시 설정
cat <<EOF >> /etc/environment
HTTP_PROXY=http://proxy.company.com:8080
HTTPS_PROXY=http://proxy.company.com:8080
NO_PROXY=localhost,127.0.0.1,169.254.169.254,.ec2.internal,.cluster.local
EOF

# kubelet을 위한 설정
mkdir -p /etc/systemd/system/kubelet.service.d
cat <<EOF > /etc/systemd/system/kubelet.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://proxy.company.com:8080"
Environment="HTTPS_PROXY=http://proxy.company.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,169.254.169.254,.ec2.internal,.cluster.local"
EOF

systemctl daemon-reload
systemctl restart kubelet

169.254.169.254를 NO_PROXY에 추가하는 것을 잊지 마십시오. 이는 AWS의 메타데이터 서비스 주소로, 프록시 없이 접근 가능해야 합니다.

포드 수준에서의 프록시 설정

Docker와 kubelet에 대해 프록시를 설정하더라도 포드 내의 애플리케이션은 자동으로 프록시를 사용하지 않습니다. Kubernetes 매니페스트에서 환경 변수를 명시적으로 지정해야 합니다.

Deployment 매니페스트를 통한 설정

가장 간단한 방법은 컨테이너 사양에 환경 변수를 추가하는 것입니다:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: app
        image: my-company/my-app:latest
        env:
        - name: HTTP_PROXY
          value: "http://proxy.company.com:8080"
        - name: HTTPS_PROXY
          value: "http://proxy.company.com:8080"
        - name: NO_PROXY
          value: "localhost,127.0.0.1,.cluster.local,.svc,10.0.0.0/8"
        ports:
        - containerPort: 8080

중앙 집중식 설정을 위한 ConfigMap 사용

각 Deployment에서 프록시 설정을 중복하지 않으려면 ConfigMap을 생성하십시오:

apiVersion: v1
kind: ConfigMap
metadata:
  name: proxy-config
  namespace: default
data:
  HTTP_PROXY: "http://proxy.company.com:8080"
  HTTPS_PROXY: "http://proxy.company.com:8080"
  NO_PROXY: "localhost,127.0.0.1,.cluster.local,.svc,10.0.0.0/8"

그런 다음 이 ConfigMap을 Deployment에서 사용하십시오:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    spec:
      containers:
      - name: app
        image: my-company/my-app:latest
        envFrom:
        - configMapRef:
            name: proxy-config

이러한 접근 방식은 관리 작업을 간소화합니다. 프록시 주소를 변경할 경우 ConfigMap을 업데이트하면 되고, 포드를 재시작하면 새로운 설정이 자동으로 적용됩니다.

MutatingWebhook을 통한 자동 주입

모든 포드에 프록시 변수를 자동으로 추가하려면 MutatingAdmissionWebhook을 사용할 수 있습니다. 이는 고급 접근 방식으로, 자체 webhook 서비스를 개발해야 하지만, 애플리케이션 매니페스트를 변경하지 않고도 설정을 중앙 집중식으로 관리할 수 있습니다.

올바른 NO_PROXY 구성

NO_PROXY 변수는 어떤 주소와 도메인이 프록시 서버를 우회해야 하는지를 정의합니다. NO_PROXY의 잘못된 설정은 Kubernetes 클러스터에서 가장 흔한 문제의 원인입니다.

Kubernetes를 위한 필수 제외 항목

다음 주소와 범위는 항상 NO_PROXY에 포함되어야 합니다:

주소/범위 목적
localhost, 127.0.0.1 로컬 연결
.cluster.local 클러스터 내부 DNS
.svc Kubernetes 서비스
10.0.0.0/8 Pod 네트워크 (CNI에 따라 다름)
10.96.0.0/12 서비스 네트워크 (기본값)
172.16.0.0/12 Docker의 개인 네트워크
192.168.0.0/16 개인 로컬 네트워크

NO_PROXY의 전체 구성 예제

NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,10.96.0.0/12,.cluster.local,.svc,.default.svc,.default.svc.cluster.local,kubernetes.default.svc,kubernetes.default.svc.cluster.local

주의: 일부 애플리케이션은 NO_PROXY에서 CIDR 표기를 지원하지 않습니다. 이 경우 와일드카드를 사용하십시오: 10.* 대신 10.0.0.0/8를 사용하십시오.

프록시를 통한 kubectl 설정

프록시 뒤에 있는 워크스테이션에서 클러스터를 관리하는 경우 kubectl을 위한 환경 변수를 설정하십시오:

# Linux/macOS의 경우 - ~/.bashrc 또는 ~/.zshrc에 추가
export HTTP_PROXY=http://proxy.company.com:8080
export HTTPS_PROXY=http://proxy.company.com:8080
export NO_PROXY=localhost,127.0.0.1,kubernetes.default.svc,.cluster.local

# Windows PowerShell의 경우
$env:HTTP_PROXY="http://proxy.company.com:8080"
$env:HTTPS_PROXY="http://proxy.company.com:8080"
$env:NO_PROXY="localhost,127.0.0.1,kubernetes.default.svc,.cluster.local"

이후 kubectl은 프록시를 통해 클러스터의 API 서버에 연결할 수 있습니다. 작동을 확인하십시오:

kubectl cluster-info
kubectl get nodes

인증이 필요한 프록시 설정

프록시 서버가 인증을 요구하는 경우 URL에 자격 증명을 추가하십시오:

export HTTP_PROXY=http://username:password@proxy.company.com:8080
export HTTPS_PROXY=http://username:password@proxy.company.com:8080

보안: 구성 파일에 비밀번호를 평문으로 저장하지 마십시오. 환경 변수나 Kubernetes 비밀을 사용하여 프록시 자격 증명을 저장하십시오.

일반적인 문제 진단 및 해결

올바른 설정에도 불구하고 문제가 발생할 수 있습니다. 가장 일반적인 오류와 해결 방법을 살펴보겠습니다.

이미지 다운로드 시 "ImagePullBackOff" 오류

증상: 포드가 시작되지 않으며, 이벤트에서 "Failed to pull image" 또는 "connection timeout" 오류가 표시됩니다.

진단:

# 포드 이벤트 확인
kubectl describe pod <pod-name>

# Docker/containerd의 프록시 설정 확인
sudo systemctl show --property=Environment docker
sudo systemctl show --property=Environment containerd

# 노드에서 이미지를 수동으로 다운로드 시도
sudo docker pull nginx:latest
sudo crictl pull nginx:latest

해결: container runtime에 대한 프록시가 설정되어 있고 이미지 레지스트리 도메인이 NO_PROXY에 포함되어 있지 않은지 확인하십시오.

클러스터 내 DNS 해상도 문제

증상: 포드가 DNS 이름으로 서로 접근할 수 없습니다 (예: service-name.namespace.svc.cluster.local).

진단:

# 포드에서 DNS 확인
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup kubernetes.default

# 포드에서 프록시 변수 확인
kubectl exec -it <pod-name> -- env | grep PROXY

해결: NO_PROXY에 .cluster.local.svc를 추가하십시오.

외부 API 접근 시 느린 작업 또는 타임아웃

증상: 애플리케이션이 느리게 작동하거나 외부 서비스에 요청 시 타임아웃이 발생합니다.

진단:

# 포드에서 프록시 접근성 확인
kubectl exec -it <pod-name> -- curl -v -x http://proxy.company.com:8080 https://www.google.com

# 응답 시간 측정
kubectl exec -it <pod-name> -- time curl -x http://proxy.company.com:8080 https://api.example.com

해결: 문제는 프록시 서버의 성능에 있을 수 있습니다. 지연을 줄이기 위해 지리적으로 가까운 주거용 프록시를 사용하는 것을 고려하십시오.

프록시를 통한 SSL/TLS 오류

증상: "certificate verify failed" 또는 "SSL handshake failed"와 같은 오류가 발생합니다.

원인: 일부 프록시 서버는 SSL 검사를 수행하여 HTTPS 트래픽을 복호화하며, 이로 인해 프록시의 루트 인증서를 설치해야 합니다.

해결:

# 프록시 인증서로 ConfigMap 생성
kubectl create configmap proxy-ca-cert --from-file=ca.crt=/path/to/proxy-ca.crt

# 인증서를 포드에 마운트하고 시스템 저장소에 추가
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
      - name: app
        volumeMounts:
        - name: proxy-ca
          mountPath: /usr/local/share/ca-certificates/proxy-ca.crt
          subPath: ca.crt
      volumes:
      - name: proxy-ca
        configMap:
          name: proxy-ca-cert

운영 환경에서의 프록시 모범 사례

기업 환경에서 Kubernetes 클러스터를 운영한 경험을 바탕으로, 프록시와의 안정적인 작업을 위한 권장 사항은 다음과 같습니다:

1. 고가용성 프록시 서버 사용

프록시는 클러스터의 단일 실패 지점이 됩니다. 로드 밸런서 뒤에 여러 프록시 서버를 설정하십시오:

HTTP_PROXY=http://proxy-lb.company.com:8080

여기서 proxy-lb.company.com은 여러 프록시 서버 앞의 로드 밸런서입니다.

2. 중앙 집중식 구성 관리

각 매니페스트에 하드코딩하는 대신 ConfigMap이나 Secret을 사용하여 프록시 설정을 저장하십시오:

apiVersion: v1
kind: ConfigMap
metadata:
  name: cluster-proxy-config
  namespace: kube-system
data:
  HTTP_PROXY: "http://proxy-lb.company.com:8080"
  HTTPS_PROXY: "http://proxy-lb.company.com:8080"
  NO_PROXY: "localhost,127.0.0.1,.cluster.local,.svc,10.0.0.0/8"

3. 모니터링 및 알림

프록시 서버의 가용성을 모니터링하고 문제가 발생할 경우 알림을 설정하십시오:

  • 프록시의 응답 시간 (로컬 프록시의 경우 < 100ms여야 함)
  • 프록시 연결 오류 수
  • 클러스터 내 ImagePullBackOff 이벤트 수
  • 프록시 서버의 CPU 및 네트워크 로드

4. NO_PROXY 제외 사항 문서화

NO_PROXY에 추가된 도메인과 IP 주소 및 그 이유를 문서화하십시오. 이는 문제 해결 및 보안 감사에 도움이 됩니다.

5. dev 환경에서 변경 사항 테스트

운영 환경에서 프록시 설정을 변경하기 전에 항상 dev/staging 클러스터에서 테스트하십시오:

# 프록시 확인을 위한 테스트 포드
apiVersion: v1
kind: Pod
metadata:
  name: proxy-test
spec:
  containers:
  - name: test
    image: curlimages/curl:latest
    command: ["sleep", "3600"]
    env:
    - name: HTTP_PROXY
      value: "http://new-proxy.company.com:8080"
    - name: HTTPS_PROXY
      value: "http://new-proxy.company.com:8080"

# 외부 리소스 접근성 확인
kubectl exec -it proxy-test -- curl -v https://registry.k8s.io
kubectl exec -it proxy-test -- curl -v https://docker.io

6. 다양한 작업에 대해 서로 다른 유형의 프록시 사용

중요한 구성 요소 (이미지 다운로드, 클러스터 API)에 대해서는 빠른 데이터 센터 프록시를 사용하고, 지리적 다양성이 필요한 애플리케이션에 대해서는 주거용 또는 모바일 프록시를 사용하십시오.

7. NO_PROXY 목록 정기적으로 업데이트

새로운 서비스 추가 또는 네트워크 토폴로지 변경 시 NO_PROXY를 업데이트하십시오. Helm 차트나 Kustomize를 통해 이를 자동화하십시오:

# Helm 차트를 위한 values.yaml
proxy:
  enabled: true
  http: "http://proxy.company.com:8080"
  https: "http://proxy.company.com:8080"
  noProxy:
    - localhost
    - 127.0.0.1
    - .cluster.local
    - .svc
    - 10.0.0.0/8
    - internal-service.company.com

결론

Kubernetes 클러스터에서 프록시 설정은 다층적인 작업으로, 운영 체제와 container runtime에서 개별 포드에 이르기까지 각 수준에서 세부 사항에 주의를 기울여야 합니다. 올바른 구성은 클러스터의 원활한 작동, 외부 리소스에 대한 안전한 접근 및 기업 보안 정책 준수를 보장합니다.

기억해야 할 핵심 사항은 다음과 같습니다:

  • 모든 수준에서 프록시를 설정하십시오: OS, container runtime, kubelet, 포드
  • NO_PROXY를 올바르게 구성하여 클러스터의 모든 내부 네트워크를 포함하십시오
  • ConfigMap을 통해 중앙 집중식 관리를 사용하십시오
  • 프록시 서버의 가용성과 성능을 모니터링하십시오
  • 운영 환경에 적용하기 전에 변경 사항을 테스트하십시오

중요한 Kubernetes 클러스터의 경우 신뢰할 수 있는 데이터 센터 프록시를 사용하여 높은 가용성과 낮은 지연 시간을 보장하는 것이 좋습니다. 이는 인프라의 안정적인 작동을 보장하고 네트워크 접근 문제로 인한 다운타임 위험을 최소화합니다.

문제가 발생하면 체계적인 접근 방식을 사용하여 진단하십시오: 각 수준에서 설정을 확인하고, 로그 및 이벤트를 분석하며, 수동으로 연결을 테스트하십시오. Kubernetes의 프록시와 관련된 대부분의 문제는 환경 변수와 NO_PROXY의 올바른 설정으로 해결됩니다.

```