
서비스 연결 실패로 당황했던 밤, 해결의 열쇠는 서비스 설정에 있어요
새벽 2시, 방금 배포한 애플리케이션이 동작하지 않는다는 긴급 알림을 받았을 때의 그 막막함을 잘 알고 있어요. 로그를 확인해 보니 파드(Pod)는 분명히 Running 상태인데, 외부에서 접속을 시도하면 계속해서 Connection Refused 에러만 뜨고 있죠. 클러스터 내부에서는 잘 돌아가는 것 같은데, 왜 정작 사용자는 우리 서비스에 접속할 수 없는 걸까요?
이런 문제는 대부분 쿠버네티스의 파드(Pod)가 가진 휘발성 IP 주소 때문이에요. 파드는 언제든 죽고 다시 살아날 수 있고, 그때마다 IP가 바뀌죠. 이 불안정한 연결 고리를 단단하게 묶어주는 것이 바로 쿠버네티스 서비스(Service)예요. 서비스 설정을 제대로 하지 못하면 아무리 완벽한 코드를 배포해도 세상 밖으로 서비스를 내보낼 수 없어요.
특히 1인 서버 담당자라면 네트워크 레이어의 복잡한 문제에 매몰되기 쉬워요. 클러스터 내부 통신부터 외부 노출까지, 혼자서 모든 것을 결정해야 하는 압박감이 상당하죠. 하지만 서비스 설정의 기본 원리만 정확히 이해하면, 어떤 환경에서도 당황하지 않고 안정적인 통신 경로를 설계할 수 있어요.
이 글에서는 단순히 명령어를 나열하는 데 그치지 않고, 실무에서 바로 적용할 수 있는 서비스 설정 방법의 핵심을 다룰 거예요. 다음 내용들을 순서대로 익히고 나면, 여러분의 서비스는 안정적인 주소를 갖게 될 거예요.
- 쿠버네티스 서비스의 핵심 동작 원리와 종류 이해하기
- 실무에서 가장 많이 쓰이는 타입별 설정 YAML 작성법
- 서비스 설정 후 통신이 잘 되는지 검증하는 필수 절차
- 자주 발생하는 네트워크 오류와 즉각적인 해결 방법
본격적인 설정 전, 반드시 챙겨야 할 기초 지식과 준비물
서비스를 구축하기 전에 먼저 우리가 어떤 도구를 가지고 있는지, 그리고 어떤 선택을 해야 하는지 명확히 해야 해요. 무턱대고 설정 파일부터 작성하다가는 나중에 클라우드 비용이 폭탄처럼 불어나거나, 보안 구멍이 생겨 곤란해질 수 있거든요.
가장 먼저 이해해야 할 점은 추상화(Abstraction) 개념이에요. 서비스는 파드의 복잡한 IP 주소를 대신하여, 변하지 않는 하나의 고정된 진입점을 제공하는 역할을 해요. 마치 회사의 전화번호가 직원의 개인 휴대폰 번호가 아니라, 대표 번호로 연결되는 것과 같은 이치예요.
쿠버네티스 서비스는 파드에 직접 접근하는 것이 아니라, 서비스가 관리하는 엔드포인트(Endpoints) 목록을 통해 통신을 중계해요. 이 엔드포인트 목록이 최신 상태로 유지되는지 확인하는 것이 디버깅의 시작이에요.
설정하기 전에 여러분의 환경이 어떤 타입의 서비스를 지원하는지 파악하는 것이 우선이에요. 아래 표를 통해 상황에 맞는 최적의 선택지를 비교해 보세요.
| 서비스 타입 | 접근 범위 | 주요 용도 | 비용/난이도 |
|---|---|---|---|
| ClusterIP | 클러스터 내부 | DB, 내부 API 서버 | 매우 낮음 |
| NodePort | 외부(노드 IP) | 테스트용, 소규모 서비스 | 낮음 |
| LoadBalancer | 전 세계 외부 | 실제 운영 서비스 | 높음 (클라우드 비용) |
| ExternalName | 클러스터 내부 | 외부 도메인 연결 | 매우 낮음 |
만약 여러분이 스타트업에서 운영 중인 AWS나 Google Cloud 환경이라면, 대부분의 운영 서비스는 LoadBalancer 타입을 사용하게 될 거예요. 하지만 개발 단계에서 매번 비용을 지불할 수는 없으니, 로컬 테스트는 ClusterIP나 NodePort로 진행하는 것이 현명해요.
준비물은 간단해요. kubectl 명령어를 사용할 수 있는 환경과, 대상 파드에 부여된 Label(라벨) 정보만 있으면 돼요. 이 라벨이 서비스와 파드를 연결하는 유일한 끈이라는 사실을 절대 잊지 마세요.
실전! 단계별 서비스 설치 및 환경 설정 가이드
이제 본격적으로 서비스 설치를 시작해 볼게요. 이론보다는 직접 명령어를 치고 결과물을 확인하는 것이 훨씬 빠르게 익히는 길이에요. 우리는 가장 기초적인 내부 통신부터 실제 운영 환경의 외부 노출까지 단계별로 진행할 거예요.
STEP 1. 대상 파드와 라벨링 전략 세우기
서비스 설정의 첫 단추는 잘못된 곳을 가리키지 않도록 정확한 타겟을 정하는 것이에요. 쿠버네티스 서비스는 어떤 파드를 관리할지 결정할 때 Selector(셀렉터)라는 기능을 사용해요. 만약 파드에 `app: my-web-app`이라는 라벨이 붙어 있다면, 서비스의 셀렉터도 정확히 일치해야 해요.
먼저 현재 실행 중인 파드들의 라벨을 확인하는 습관을 들이세요. kubectl get pods --show-labels 명령어를 사용하면 됩니다. 라벨이 엉망이면 서비스는 아무리 잘 만들어도 연결될 파드를 찾지 못해 Endpoints가 비어 있는 상태가 돼요.
STEP 2. ClusterIP를 활용한 내부 서비스 구성
대부분의 마이크로서비스 환경에서는 DB나 내부 로직을 처리하는 API 서버를 외부로 노출할 필요가 없어요. 이럴 때 사용하는 것이 바로 ClusterIP예요. 이는 클러스터 내부에서만 접근 가능한 가상 IP를 생성해요.
아래와 같은 YAML 파일을 작성하여 서비스를 생성해 보세요.
apiVersion: v1
kind: Service
metadata:
name: internal-api-service
spec:
selector:
app: backend-api
ports:
- protocol: TCP
port: 80
targetPort: 8080
여기서 주의할 점은 port와 targetPort의 차이에요. port는 서비스가 내부적으로 사용하는 포트이고, targetPort는 실제 파드 내부 애플리케이션이 리스닝하고 있는 포트예요. 이 둘을 헷갈리면 통신이 절대 되지 않아요.
STEP 3. NodePort로 외부 테스트 환경 구축하기
클라우드 비용을 쓰지 않고 내 로컬 컴퓨터나 온프레미스 서버에서 외부 접속을 테스트하고 싶다면 NodePort가 정답이에요. 이 방식은 클러스터 노드의 특정 포트(기본 30000-32767 범위)를 열어 서비스를 노출해요.
설정 예시는 다음과 같아요.
apiVersion: v1
kind: Service
metadata:
name: web-nodeport-service
spec:
type: NodePort
selector:
app: frontend
ports:
- port: 80
targetPort: 80
nodePort: 30080
이렇게 설정하면 `http://<노드IP>:30080`을 통해 접속이 가능해져요. 다만, 보안상 위험할 수 있고 노드 IP가 바뀌면 접속이 끊긴다는 단점이 있어요. 따라서 실제 서비스용으로는 권장하지 않아요.
STEP 4. LoadBalancer로 운영 환경 완성하기
실제 고객에게 서비스를 제공해야 하는 상황이라면 LoadBalancer 타입을 사용해야 해요. AWS의 경우 ELB(Elastic Load Balancer)를 자동으로 생성하여 외부 고정 IP나 도메인을 할당해 주죠. 설정은 매우 간단해요. type: LoadBalancer 한 줄만 추가하면 됩니다.
설정 후 kubectl get svc를 입력했을 때 EXTERNAL-IP 항목에 IP 주소나 주소가 나타날 때까지 잠시 기다려야 해요. 처음에는 pending 상태로 보일 수 있는데, 이는 클라우드 업체가 인프라를 프로비저닝하는 중이라는 뜻이니 조급해하지 마세요.
STEP 5. 동작 검증 및 디버깅 시나리오
설정이 끝났다면 반드시 검증을 거쳐야 해요. 단순히 ‘접속이 된다’에서 끝나지 말고, 다음의 단계를 따라 꼼꼼히 확인하세요.
- 엔드포인트 확인:
kubectl get endpoints <서비스이름>명령어로 연결된 파드 IP가 제대로 표시되는지 확인하세요. 목록이 비어 있다면 셀렉터(Selector) 문제입니다. - 내부 통신 테스트: 클러스터 내부의 다른 파드에 접속해서
curl <서비스IP>:<포트>로 요청을 보내보세요. - 외부 접속 테스트: 브라우저나 Postman을 이용해 외부 IP로 직접 접속을 시도하세요.
만약 클라우드 LoadBalancer가 작동하지 않는다면, 클라우드 제공업체의 보안 그룹(Security Group)에서 해당 포트가 열려 있는지 반드시 확인해야 해요. 쿠버네티스 설정은 완벽해도 인프라 방화벽이 막고 있는 경우가 허다해요.
자주 하는 실수와 해결법 및 궁금한 점 해결하기
서비스 설정을 마치고 나서도 예상치 못한 문제로 발목을 잡힐 때가 많아요. 현장에서 가장 빈번하게 발생하는 문제들을 정리했으니, 문제가 생기면 이 리스트를 먼저 확인해 보세요.
자주 하는 실수와 해결법
❌ 실수: 파드는 잘 도는데 서비스 접속이 안 돼요.
왜 발생하는가: 서비스의 selector와 파드의 label이 일치하지 않아서 서비스가 연결할 파드를 찾지 못하는 경우예요.
✅ 해결법: kubectl get pods --show-labels로 라벨을 확인하고, 서비스 YAML의 selector와 글자 하나 틀리지 않고 똑같은지 확인하세요.
❌ 실수: 포트 설정은 다 했는데 통신이 안 돼요.
왜 발생하는가: 서비스의 targetPort와 파드 내 컨테이너가 실제로 열어둔 포트가 다르기 때문이에요.
✅ 해결법: 애플리케이션 코드에서 사용하는 포트 번호와 서비스 YAML의 targetPort를 일치시키세요.
❌ 실수: LoadBalancer의 EXTERNAL-IP가 계속 pending 상태예요.
왜 발생하는가: 클라우드 환경에서 인프라 생성 시간이 필요하거나, 클라우드 계정의 권한(IAM) 문제로 로드밸런서를 만들지 못하는 상황이에요.
✅ 해결법: 클라우드 콘솔에 들어가서 로드밸런서 생성 로그를 확인하거나, 권한 설정을 점검하세요.
❌ 실수: 서비스는 정상인데 외부에서 접속하면 타임아웃이 떠요.
왜 발생하는가: 쿠버네티스 문제가 아니라, 클라우드 보안 그룹(Security Group)이나 네트워크 ACL에서 해당 포트 접근을 차단하고 있을 확률이 높아요.
✅ 해결법: 클라우드 인프라 설정에서 해당 포러스(Port)에 대한 인바운드 규칙을 허용해 주세요.
❌ 실수: 서비스 IP로 접속하면 엉뚱한 파드로 연결돼요.
왜 발생하는가: 라벨 셀렉터가 너무 광범위해서 의도하지 않은 다른 파드들까지 서비스에 포함된 경우예요.
✅ 해결법: 라벨을 더 구체적으로 정의하여(예: app=web, env=prod) 범위를 좁히세요.
자주 묻는 질문
Q. ClusterIP와 NodePort의 차이점이 정확히 무엇인가요?
ClusterIP는 클러스터 내부의 마이크로서비스끼리 통신할 때 사용하는 ‘내부 전화번호’이고, NodePort는 노드의 IP와 포트를 통해 외부에서도 접근할 수 있게 문을 열어주는 ‘외부 연결 통로’라고 이해하시면 돼요.
Q. 서비스 IP는 왜 자꾸 바뀌나요?
쿠버네티스 서비스 IP(ClusterIP)는 서비스 객체가 삭제되기 전까지는 고정되지만, 서비스를 삭제하고 다시 만들면 새로운 IP가 할당돼요. 따라서 코드에 IP를 직접 적기보다는 서비스 이름을 이용한 DNS 이름을 사용해야 해요.
Q. 하나의 서비스에 여러 개의 포트를 설정할 수 있나요?
네, 가능해요. YAML 파일의 ports 항목 아래에 리스트 형태로 여러 개를 작성하면 HTTP(80)와 HTTPS(443)를 동시에 서비스하는 식의 구성이 가능해요.
Q. 서비스 설정이 완료되었는데 엔드포인트가 비어있으면 어떻게 하나요?
가장 먼저 파드의 라벨을 확인하세요. 그 다음, 파드가 실제로 Ready 상태인지 확인하세요. 파드가 준비되지 않았다면(Readiness Probe 실패 등) 서비스는 해당 파드를 엔드포인트 목록에서 제외해 버려요.
Q. LoadBalancer 타입은 돈이 많이 드나요?
네, 클라우드 환경에서는 로드밸런서 인스턴스 자체에 대한 비용과 데이터 처리 비용이 발생해요. 따라서 운영용이 아니라면 개발 환경에서는 NodePort나 Ingress를 사용하는 것이 비용 절감에 도움이 돼요.
이제 안정적인 서비스 운영을 위한 준비가 끝났어요
지금까지 쿠버네티스 서비스의 개념부터 설치, 그리고 실제 운영 환경에서의 설정법까지 상세히 살펴보았어요. 처음에는 낯선 용어와 복잡한 YAML 설정 때문에 막막할 수 있지만, 라벨과 셀렉터라는 두 가지만 확실히 잡아도 절반은 성공한 거예요.
- 서비스는 파드의 휘발성 IP를 대신하는 고정된 진입점이에요.
- 라벨(Label)과 셀렉터(Selector)의 일치는 서비스 작동의 필수 조건이에요.
- 내부 통신은 ClusterIP, 외부 테스트는 NodePort, 운영은 LoadBalancer를 사용하세요.
- 설정 후에는 반드시
kubectl get endpoints로 연결 상태를 확인하세요. - 포트 설정 시 서비스의 port와 파드의 targetPort를 구분해야 해요.
오늘 배운 내용을 바탕으로 여러분의 클러스터에 작은 서비스 하나를 직접 띄워보는 건 어떨까요? 이론으로 백 번 보는 것보다, 직접 에러를 마주하고 해결했을 때의 성취감이 여러분을 진짜 전문가로 만들어줄 거예요.
🚀 다음 단계로 나아가기
- 오늘 할 일: 현재 운영 중인 파드의 라벨을 확인하고 서비스 YAML 작성해 보기
- 이번 주 할 일: ClusterIP로 만든 서비스를 NodePort로 확장하여 외부 접속 테스트하기
- 실행 직전 할 일: 클라우드 환경이라면 로드밸런서 생성 권한(IAM)이 있는지 미리 체크하기
실습 과정에서 예상치 못한 에러 메시지를 만났거나, 설정이 잘 안 되는 부분이 있다면 주저하지 말고 댓글로 질문을 남겨 주세요. 함께 고민하면 해결책을 찾을 수 있어요!
함께 읽으면 좋은 글: 쿠버네티스 서비스 기본 개념 정리, 클러스터 구축 입문 가이드