[k8s 기초 4편] 내 서비스를 외부로 노출하는 법: Service와 Ingress
jay
2026년 1월 19일 22:43
지난 3편에서 Deployment를 사용해 Nginx 파드(Pod) 3개를 띄우는 데 성공했다. kubectl get pods를 쳐보면 Running 상태로 아주 잘 돌아간다.
하지만 문제가 하나 있다. 접속할 수가 없다. 파드에도 IP(10.42.x.x 등)가 있긴 하지만, 이 IP는 클러스터 내부에서만 통용되는 사설 IP다. 외부의 내 노트북 브라우저에서는 이 IP로 접근할 방법이 없다.
오늘은 굳게 닫힌 쿠버네티스 클러스터에 문을 달고, 도메인 주소로 개발자 스럽게 접속하는 방법인 Service(서비스)와 Ingress(인그레스)에 대해 정리해 본다.
목차
1. 파드의 IP는 믿을 수 없다
서비스라는 개념이 왜 필요할까? 앞서 배웠듯이 파드는 ‘개복치’다. 언제든 죽을 수 있고, 다시 살아나면 IP가 바뀐다.
만약 우리가 파드의 IP를 직접 보고 접속하도록 설정했다면, 파드가 재시작될 때마다 설정을 바꿔줘야 할 것이다. 이는 자동화된 시스템에서 있을 수 없는 일이다.
그래서 고정된 주소(진입점)가 필요하다. 파드가 죽든 말든, IP가 바뀌든 말든 상관없이 트래픽을 받아서 적절한 파드에게 토스해 주는 존재, 그것이 바로 Service다.

2. Service의 3가지 종류 (접속 방식)
서비스를 정의할 때 type을 지정해야 하는데, 크게 3가지 방식이 있다. 홈서버(k3s) 환경과 클라우드 환경의 차이를 이해하는 것이 중요하다.
① ClusterIP (기본값)
- 특징: 클러스터 내부에서만 접속 가능한 IP를 할당한다.
- 용도: 외부 노출이 필요 없는 DB나 백엔드 내부 통신에 사용된다. 외부에서는 접근 불가능하다.
② NodePort
- 특징: 모든 노드(서버)의 특정 포트를 열어서 외부 접속을 허용한다.
- 방식:
30000~32767범위의 포트를 사용한다. 예를 들어30080포트로 설정하면http://내-서버-IP:30080으로 접속할 수 있다. - 용도: 홈서버나 테스트 환경에서 가장 간단하게 외부 접속을 뚫는 방법이다. 하지만 포트 번호를 일일이 관리해야 하므로 실제 운영 환경에서는 잘 쓰지 않는다.
③ LoadBalancer
- 특징: 클라우드 제공자(AWS, GCP 등)의 로드밸런서를 자동으로 생성하고 연결한다. 외부 IP(Public IP)를 할당받는다.
- 용도: 실무에서 가장 많이 쓰는 방식이다.
- 주의: k3s 같은 베어메탈(직접 구축) 환경에서는
EXTERNAL-IP가Pending상태로 멈춰 있을 수 있다. (이를 해결하려면 MetalLB 같은 추가 세팅이 필요하다.)
3. Ingress (인그레스)
NodePort를 쓰면 접속은 되지만 멋이 없다. naver.com 뒤에 :30080 같은 포트를 붙여서 쓰는 서비스는 없다. 우리는 http://myapp.com 처럼 80(HTTP)이나 443(HTTPS) 포트로 깔끔하게 접속하길 원한다.
이때 등장하는 것이 Ingress다.
Ingress란?
서비스가 L4(TCP/UDP) 레벨의 부하 분산이라면, 인그레스는 L7(HTTP/HTTPS) 레벨의 라우터다. 쉽게 말해 “교통 정리 담당자”다.
blog.myserver.com으로 들어오면 -> 블로그 서비스로 가라.shop.myserver.com으로 들어오면 -> 쇼핑몰 서비스로 가라./api로 들어오면 -> 백엔드 서비스로 가라.

💡 k3s Tip: k3s는 기본적으로 Traefik(트래픽)이라는 인그레스 컨트롤러가 내장되어 있다. 별도 설치 없이 인그레스 설정만 하면 바로 작동한다.
4. 실전 YAML: NodePort와 Ingress 설정하기
홈서버 환경이라 가정하고, Nginx를 외부로 노출하는 가장 일반적인 설정을 작성해 본다.
1단계: Service 만들기 (ClusterIP)
인그레스를 쓸 거라면 굳이 NodePort를 열 필요 없이 ClusterIP로 만들어도 된다. 인그레스가 내부적으로 연결해 주기 때문이다.
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx # 3편에서 만든 Pod의 라벨과 일치해야 함
ports:
- protocol: TCP
port: 80 # 서비스의 포트
targetPort: 80 # 타겟 파드의 포트
type: ClusterIP
2단계: Ingress 만들기
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
spec:
rules:
- host: my-nginx.local # 접속할 도메인 주소
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service # 위에서 만든 서비스 이름
port:
number: 80
이렇게 설정하고 kubectl apply를 한 뒤, 내 PC의 hosts 파일에 my-nginx.local을 서버 IP로 등록하면, 브라우저에서 도메인으로 접속되는 것을 확인할 수 있다.
5. 정리: 접속의 흐름
이제 외부 사용자가 내 서비스에 접속하는 전체 흐름이 완성되었다.
- User:
http://my-nginx.local접속 요청. - Ingress: 도메인을 확인하고
nginx-service로 트래픽을 보냄. - Service: 자신에게 연결된 파드 중 하나(
nginx-pod)를 선택해 트래픽을 전달. - Pod: 요청을 처리하고 응답.
여기까지 하면 “Stateless(상태가 없는)” 웹 서버 배포는 마스터한 셈이다. 하지만 아직 중요한 게 남았다. 파드가 죽었다 살아나면 데이터는 어떻게 될까? DB에 저장해 둔 데이터가 파드 재시작과 함께 날아간다면?
다음 5편에서는 쿠버네티스에서 데이터를 영구적으로 저장하는 Volume(볼륨)과 PV/PVC의 개념에 대해 정리하며 시리즈를 마무리한다.
이 글은 개인 학습을 위해 정리한 내용이며, 오류가 있다면 피드백 부탁드립니다.
You might also like
Comments (0)
Leave a Reply
Or login to comment with your account.
No comments yet. Be the first to share your thoughts!