Kubernetes에서 Service(서비스) 객체는 Pod들의 논리적인 집합에 단일 접근 포인트(IP 및 DNS 이름)을 제공하는 역할을 한다.
앞서 Deployment로 Nginx Pod 여러 개를 띄웠다면, 클라이언트가 그중 어떤 Pod에 접속해야 할지 알기 어렵다.
Service를 사용하면 여러 Pod들을 하나의 서비스로 묶고, 부하 분산(Load Balancing) 및 서비스 디스커버리(DNS)를 제공할 수 있다.
Kubernetes에는 몇 가지 서비스 유형(Service Types)이 있다.
- ClusterIP (기본값)
- 클러스터 내부에서만 접근 가능한 가상 IP를 부여한다.
- 내부 서비스 용도로 사용된다.
- NodePort
- 각 Node의 IP에서 정해진 포트를 열어, 외부에서 노드IP:포트로 접근할 수 있게 한다.
- LoadBalancer
- 클라우드 환경의 L4 로드밸런서를 프로비저닝하여 외부 IP를 할당한다.
- on-prem 환경에서는 ServiceLB같은 로드밸런서 컨트롤러가 필요하며, k3s는 기본적으로 ServiceLB를 내장하여 지원한다.
- ExternalName
- 서비스에 ClusterIP를 만들지 않고, DNS 이름 별칭만 제공하여 쿠버네티스 외부 서비스를 지칭할 때 쓴다 (특수한 경우).
추가로, HTTP/HTTPS 등의 L7 경로 기반 라우팅을 위해 Ingress라는 리소스를 사용한다.
Ingress는 여러 서비스들을 한 곳으로 모아 도메인/경로 기반으로 분기시켜주는 진입점이다.
Ingress 리소스는 자체로 동작하지 않고, Ingress Controller(예: Nginx Ingress, Traefik 등)가 클러스터에 설치되어야 동작한다.
k3s는 Traefik Ingress Controller를 기본 내장하고 있어서, 별도 설정 없이 Ingress 리소스를 바로 사용할 수 있다.
이번 섹션에서는 ClusterIP, NodePort, Ingress 각각을 실습해보자.
우선 Deployment로 실행 중인 Nginx Pod들을 대상으로 서비스를 생성해볼 것이다
(Deployment 섹션의 hello-deployment 또는 새로 Deployment를 만들어 사용).
ClusterIP 서비스 만들기
ClusterIP Service 매니페스트 작성
hello-svc.yaml 파일을 생성한다.

- selector는 이 서비스가 트래픽을 보낼 Pod들을 선택하는 라벨이다.
- app: hello 레이블을 가진 Pod들이 대상이 된다 (이전에 Deployment에 지정했던 라벨).
- port: 80은 서비스 자체의 포트 번호이다. (ClusterIP 가상 IP에 연결된 포트)
- targetPort: 80은 대상 Pod에서 열고 있는 포트 번호이다.
- 여기서는 Nginx 컨테이너의 80포트로 트래픽을 전달한다는 의미이다.
- 숫자 외에 컨테이너 포트 명을 쓸 수도 있지만 여기선 숫자로
- type: ClusterIP은 기본값으로, 명시하지 않아도 ClusterIP로 생성된다. 클러스터 내부에서만 접근 가능한 IP를 하나 배정받는다.
적용 및 확인

- CLUSTER-IP로 10.96.203.120 같은 IP가 부여된 것을 볼 수 있다. 이것은 가상 IP로, 클러스터 내부에서 이 IP로 접근하면 자동으로 hello-service로 연결된다.
- EXTERNAL-IP는 ClusterIP 타입이므로 <none> (외부 IP 없음)이다.
이제 hello-service를 통해 Pod들에 접근해보자.
서비스 통신 확인 (클러스터 내부)
ClusterIP 서비스는 클러스터 내 Pod 또는 노드에서 접근 가능하다.
먼저 실습을 위해 클러스터 내부에 테스트용 Pod를 하나 띄워보자.

- 위 명령은 busybox:1.34 이미지를 실행한 임시 Pod에 쉘로 접속한다.
- (종료 시 --rm에 의해 Pod 삭제)
- Busybox 쉘 내에서 하단의 명령어를 입력하면 위의 HTML 출력이 나온다.

- hello-service라는 DNS 이름으로 서비스에 접근하고 있다.
- Kubernetes는 서비스 생성 시 <서비스명>.<네임스페이스>.svc.cluster.local이라는 DNS 이름을 할당하며, 같은 네임스페이스에서는 간략히 http://hello-service로 접근 가능하다.
결과로 Nginx의 기본 페이지 HTML이 출력되면 서비스 통해 Nginx Pod들과 통신이 잘 된다.
여러 번 실행해보면 wget 결과가 3개의 Pod 중 어느 것으로 가는지 알 수는 없지만, Service가 알아서 라운드로빈으로 트래픽 분배를 수행한다.
참고: Kubernetes DNS는 CoreDNS가 제공하며, 서비스 이름을 resolution해준다.
DNS 설정은 각 Pod의 /etc/resolv.conf에 자동 구성되어, <서비스명>이나 <서비스명>.<네임스페이스> 등을 찾을 수 있게 해준다(예: hello-service.default.svc.cluster.local).
ClusterIP 타입은 클러스터 외부에서는 접근할 수 없기 때문에, 일반 사용자가 이용하는 웹서비스 등을 만들려면 NodePort나 Ingress를 추가로 설정해야 한다.
다음으로 NodePort를 설정해보자.
NodePort 서비스로 외부에 노출하기
NodePort 타입은 Service에 노출용 포트를 할당하여 각 Kubernetes 노드의 IP:포트로 서비스를 이용할 수 있게 해준다.
로컬 환경(k3s 단일 노드 등)에서는 NodePort를 이용하면 곧바로 그 노드(혹은 PC)의 IP에서 포트로 접근이 가능하므로 편리하다.
NodePort로 수정
앞서 만든 hello-service를 NodePort로 변경해보자.
kubectl patch도 사용 가능하지만, 여기에서는 YAML을 새로 작성해 apply 할 것이다.

- type: NodePort로 지정했다.
- nodePort: 30080을 지정하여 고정 포트를 요청했다.
- (30000~32767 범위 내에서 지정 가능하며, 미지정 시 자동 할당)
- port: 80, targetPort: 80은 이전과 동일하다.
적용

PORT(S) 항목이 80:30080/TCP로 표시되는데, 이는 서비스포트 80이 NodePort 30080으로 매핑되었음을 뜻한다.
접근 테스트
NodePort는 클러스터의 각 노드에서 해당 포트를 listening한다. 단일 노드 k3s라면 그 노드 = 호스트 머신이 된다.

- 웹 브라우저로 http://localhost:30080에 접속해도 nginx 환영 페이지가 떠야 한다.
- NodePort를 통해 외부에서도 Pod에 연결된 것을 확인했다.
NodePort 방식은 간단하지만, 포트 번호가 30000번대로 노출되고, 여러 서비스가 있을 경우 포트 관리가 번거로울 수 있다.
또한 HTTP/HTTPS 서비스를 여러 개 운영 시 각기 다른 포트를 사용해야 하므로 사용자 접근성이 떨어진다.
이 문제를 해결하기 위해 Ingress를 사용한다.
Ingress로 HTTP 경로 기반 라우팅하기
Ingress는 하나의 진입점(URL)으로 다수의 서비스들을 라우팅하거나, 도메인명을 기반으로 가상 호스트를 구현할 때 사용된다.
예를 들어 example.com/app1 -> 서비스 A, example.com/app2 -> 서비스 B 식으로 구성 가능하다.
Ingress를 사용하려면 Ingress Controller가 필수인데, k3s는 Traefik을 기본 Ingress Controller로 포함하고 있어 바로 사용할 수 있다.
Traefik이 k3s에서 자동 설치되어 traefik이라는 Pod가 kube-system 네임스페이스에서 동작 중일 것이다.

Traefik Ingress (k3s 기본값): Traefik은 포트 80과 443으로 ingress 진입점을 개방하며, Ingress 리소스를 감시하여 규칙을 만든다.
k3s의 Traefik은 Service 타입이 LoadBalancer로 설정되어 각 노드 80/443 포트를 활용한다.
(실제로 NodePort로 동작하고 Traefik이 그 NodePort를 바인딩하여 사용하는 구조)
따라서 k3s에서 Ingress 리소스를 만들면, 기본적으로 노드의 80/443 포트로 접속하는 HTTP/HTTPS 트래픽을 Traefik이 받아서 처리한다.
주의: Traefik 사용 중에는 80/443 포트를 다른 용도로 NodePort/HostPort에 쓰지 못한다.
Ingress 리소스 생성
hello-ingress.yaml 파일을 만들자.

- rules 아래에 호스트와 경로 규칙을 정의한다.
- 여기서는 hello.local 도메인으로 들어오는 / 경로 요청을 hello-service:80으로 보낸다는 의미다.
- pathType: Prefix는 경로 접두사 일치 방식을 나타낸다. (기본값)
- 즉, http://hello.local/ 로 오는 요청을 모두 hello-service 서비스로 라우팅한다.
- 필요에 따라 여러 paths 항목을 넣어 서로 다른 path를 다른 서비스로 보낼 수 있다.
- 또한 rules를 여러개 두어 host 별로 다르게 구성할 수도 있다.
- 여기서는 간단히 하나의 host에 매핑했다.
Ingress 리소스 추가 고려사항 - 멀티 노드 구성
- Ingress는 L7 라우팅 규칙을 정의하는 Kubernetes 리소스이며, 실제 트래픽 처리는 Ingress Controller가 수행한다.
- Ingress Controller는 보통 클러스터 내부에서 Pod(Deployment/DaemonSet) 로 실행되며, 외부 트래픽은 Service(LoadBalancer/NodePort 등) 를 통해 유입된다.
- Ingress를 사용하려면 DNS가 해당 host를 가리키도록 하거나, 개발 환경에서는 호스트 파일에 host명을 추가해야 한다.
- 요청 -> etc/hosts 파일로 DNS 탐색 -> ingress controller에 도착 -> ingress controller가 적절한 파드 선택 -> 연결된 파드 -> 파드 내 컨테이너
- hello.local은 예시 host로, 실제 DNS에 등록되지 않은 도메인이다.
- 로컬 PC에서 테스트하려면 /etc/hosts에 127.0.0.1 hello.local (또는 노드 IP) 항목을 추가하자.

적용 및 확인

- ADDRESS에 192.168.64.10 등이 표시되었다면 Ingress Controller(Traefik)가 할당한 IP이다.
- k3s 기본 Traefik+ServiceLB는 모든 노드 IP를 external IP로 표시하기도 한다.
- 즉 Ingress 진입점이 NodePort/LoadBalancer 통해 열려있는 주소다.
상세 확인

- Traefik이 Ingress를 인식하여 hello.local -> hello-service 규칙이 설정된 것을 볼 수 있다.
접속 테스트
curl http://hello.local 을 수행해보자.

- Traefik(Ingress Controller)이 80 포트에서 요청을 받아 hello-service로 전달하고, hello-service는 다시 Nginx Pod들 중 하나로 포워드하여 응답을 준 것이다.
Ingress를 통해 도메인 기반으로 서비스에 접근할 수 있게 되었다.
필요하면 TLS 인증서 등을 설정하여 HTTPS (hosts: hello.local, tls 필드 등) 구성을 추가할 수도 있지만 여기서는 기본 동작만 확인한다.
Traefik 대시보드
Traefik v2 이상에서는 기본적으로 대시보드가 비활성이다.
k3s 설정을 커스터마이즈하면 Traefik Dashboard도 띄울 수 있지만 본 튜토리얼 범위에서는 다루지 않는다.
Ingress 정리
필요 시 Ingress 리소스를 삭제한다.

요약
- 이번 섹션에서는 Service와 Ingress를 사용한 네트워크 노출 방법을 실습했다.
- ClusterIP 서비스: 내부에서 Pod들에게 접근 가능한 가상 IP와 DNS 이름을 제공.
- 서비스 디스커버리, 로드밸런싱 기능 포함
- NodePort 서비스: 클러스터 노드의 포트를 통해 외부 접근을 허용.
- 간편하지만 포트 관리 이슈 있음.
- Ingress: HTTP(S) 계층에서 호스트/경로 기반으로 다수 서비스 통합 노출.
- Ingress Controller가 필요하며, k3s의 Traefik처럼 L7 프록시/로드밸런서 역할 수행.
- k3s의 Traefik 기본 설정으로 쉽게 Ingress를 활용할 수 있음을 보았다.
배운 개념
- 서비스의 역할(엔드포인트 추상화 및 로드밸런싱)
- 서비스의 DNS 및 가상 IP
- NodePort/LoadBalancer를 통한 외부 노출 원리
- Ingress를 이용한 경로 기반 라우팅
- Ingress Controller의 필요성
'WEB BE Repository > kubernetes, k8s' 카테고리의 다른 글
| [쿠버네티스 튜토리얼] 2. Deployment 생성과 ReplicaSet 이해 (0) | 2025.12.18 |
|---|---|
| [쿠버네티스 튜토리얼] 1. k3s로 배워보자. (0) | 2025.12.17 |