[인그레스](/ko/docs/concepts/services-networking/ingress/)를 사용하여 서비스를 노출시킬 수도 있다. 인그레스는 서비스 유형이 아니지만, 클러스터의 진입점 역할을 한다. 동일한 IP 주소로 여러 서비스를 노출시킬 수 있기 때문에 라우팅 규칙을 단일 리소스로 통합할 수 있다.
### NodePort 유형 {#nodeport}
`type` 필드를 `NodePort`로 설정하면, 쿠버네티스 컨트롤 플레인은
`--service-node-port-range` 플래그로 지정된 범위에서 포트를 할당한다 (기본값 : 30000-32767).
각 노드는 해당 포트 (모든 노드에서 동일한 포트 번호)를 서비스로 프록시한다.
서비스는 할당된 포트를 `.spec.ports[*].nodePort` 필드에 나타낸다.
포트를 프록시하기 위해 특정 IP를 지정하려면 kube-proxy의 `--nodeport-addresses` 플래그를 특정 IP 블록으로 설정할 수 있다. 이것은 쿠버네티스 v1.10부터 지원된다.
이 플래그는 쉼표로 구분된 IP 블록 목록 (예: 10.0.0.0/8, 192.0.2.0/25)을 사용하여 kube-proxy가 로컬 노드로 고려해야 하는 IP 주소 범위를 지정한다.
예를 들어, `--nodeport-addresses=127.0.0.0/8` 플래그로 kube-proxy를 시작하면, kube-proxy는 NodePort 서비스에 대하여 루프백(loopback) 인터페이스만 선택한다. `--nodeport-addresses`의 기본 값은 비어있는 목록이다. 이것은 kube-proxy가 NodePort에 대해 사용 가능한 모든 네트워크 인터페이스를 고려해야 한다는 것을 의미한다. (이는 이전 쿠버네티스 릴리스와도 호환된다).
일부 클라우드 공급자는 `loadBalancerIP`를 지정할 수 있도록 허용한다. 이 경우, 로드 밸런서는
사용자 지정 `loadBalancerIP`로 생성된다. `loadBalancerIP` 필드가 지정되지 않으면,
임시 IP 주소로 loadBalancer가 설정된다. `loadBalancerIP`를 지정했지만
클라우드 공급자가 이 기능을 지원하지 않는 경우, 설정한 `loadbalancerIP` 필드는
무시된다.
{{<note>}}
SCTP를 사용하는 경우, `LoadBalancer` 서비스 유형에 대한 아래의 [경고](#caveat-sctp-loadbalancer-service-type)를
참고한다.
{{</note>}}
{{<note>}}
**Azure** 에서 사용자 지정 공개(public) 유형 `loadBalancerIP`를 사용하려면, 먼저
정적 유형 공개 IP 주소 리소스를 생성해야 한다. 이 공개 IP 주소 리소스는
클러스터에서 자동으로 생성된 다른 리소스와 동일한 리소스 그룹에 있어야 한다.
예를 들면, `MC_myResourceGroup_myAKSCluster_eastus`이다.
할당된 IP 주소를 loadBalancerIP로 지정한다. 클라우드 공급자 구성 파일에서 securityGroupName을 업데이트했는지 확인한다. `CreatingLoadBalancerFailed` 권한 문제 해결에 대한 자세한 내용은 [Azure Kubernetes Service (AKS) 로드 밸런서에서 고정 IP 주소 사용](https://docs.microsoft.com/en-us/azure/aks/static-ip) 또는 [고급 네트워킹 AKS 클러스터에서 CreateLoadBalancerFailed](https://github.com/Azure/AKS/issues/357)를 참고한다.
{{</note>}}
#### 내부 로드 밸런서 {#internal-load-balancer}
혼재된 환경에서는 서비스의 트래픽을 동일한 (가상) 네트워크 주소 블록 내로
라우팅해야하는 경우가 있다.
수평 분할 DNS 환경에서는 외부와 내부 트래픽을 엔드포인트로 라우팅 할 수 있는 두 개의 서비스가 필요하다.
쿠버네티스 v1.9부터는 서비스에 대한 HTTPS 또는 SSL 리스너와 함께 [사전에 정의된 AWS SSL 정책](http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html)을 사용할 수 있다.
NLB는 특정 인스턴스 클래스에서만 작동한다. 지원되는 인스턴스 유형 목록은 엘라스틱 로드 밸런싱에 대한 [AWS 문서](http://docs.aws.amazon.com/elasticloadbalancing/latest/network/target-group-register-targets.html#register-deregister-targets)
를 참고한다.
{{</note>}}
클래식 엘라스틱 로드 밸런서와 달리, 네트워크 로드 밸런서 (NLB)는
클라이언트의 IP 주소를 노드로 전달한다. 서비스의 `.spec.externalTrafficPolicy`가
`Cluster`로 설정되어 있으면, 클라이언트의 IP 주소가 종단 파드로
전파되지 않는다.
`.spec.externalTrafficPolicy`를 `Local`로 설정하면, 클라이언트 IP 주소가
`my-service.prod.svc.cluster.local` 호스트를 검색하면, 클러스터 DNS 서비스는
`my.database.example.com` 값의 `CNAME` 레코드를 반환한다. `my-service`에 접근하는 것은
다른 서비스와 같은 방식으로 작동하지만, 리다이렉션은 프록시 또는
포워딩을 통하지 않고 DNS 수준에서 발생한다는 중요한
차이점이 있다. 나중에 데이터베이스를 클러스터로 이동하기로 결정한 경우, 해당
파드를 시작하고 적절한 셀렉터 또는 엔드포인트를 추가하고,
서비스의 `유형(type)`을 변경할 수 있다.
{{<warning>}}
HTTP 및 HTTPS를 포함한, 몇몇 일반적인 프로토콜에 ExternalName을 사용하는 것은 문제가 있을 수 있다. ExternalName을 사용하는 경우, 클러스터 내부의 클라이언트가 사용하는 호스트 이름(hostname)이 ExternalName이 참조하는 이름과 다르다.
호스트 이름을 사용하는 프로토콜의 경우, 이러한 차이로 인해 오류가 발생하거나 예기치 않은 응답이 발생할 수 있다. HTTP 요청에는 오리진(origin) 서버가 인식하지 못하는 `Host :` 헤더가 있다. TLS 서버는 클라이언트가 연결된 호스트 이름과 일치하는 인증서를 제공할 수 없다.
{{</warning>}}
{{<note>}}
이 섹션은 [Alen Komljen](https://akomljen.com/)의 [쿠버네티스 팁 - Part
1](https://akomljen.com/kubernetes-tips-part-1/) 블로그 게시물에 대한 내용이다.
{{</note>}}
### 외부 IP
하나 이상의 클러스터 노드로 라우팅되는 외부 IP가 있는 경우, 쿠버네티스 서비스는 이러한
`externalIPs`에 노출될 수 있다. 서비스 포트에서 외부 IP (목적지 IP)를 사용하여 클러스터로 들어오는 트래픽은
서비스 엔드포인트 중 하나로 라우팅된다. `externalIPs`는 쿠버네티스에 의해 관리되지 않으며
클러스터 관리자에게 책임이 있다.
서비스 명세에서, `externalIPs`는 모든 `ServiceTypes`와 함께 지정할 수 있다.
아래 예에서, 클라이언트는 "`80.11.12.10:80`"(`외부 IP:포트`)로 "`my-service`"에 접근할 수 있다.
```yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
externalIPs:
- 80.11.12.10
```
## 단점
VIP용으로 유저스페이스 프록시를 사용하면, 중소 급 스케일에서는 동작하지만, 수천 개의
서비스가 포함된 대규모 클러스터로는 확장되지 않는다. [포털에 대한
독창적인 설계 제안](http://issue.k8s.io/1107)에 이에 대한 자세한 내용이
있다.
유저스페이스 프록시를 사용하면 서비스에 접근하는 패킷의 소스 IP 주소가
가려진다.
이것은 일종의 네트워크 필터링 (방화벽)을 불가능하게 만든다. iptables
프록시 모드는 클러스터 내
소스 IP를 가리지 않지만, 여전히 로드 밸런서 또는 노드-포트를 통해 오는
클라이언트에 영향을 미친다.
`Type` 필드는 중첩된 기능으로 설계되었다. - 각 레벨은 이전 레벨에
추가된다. 이는 모든 클라우드 공급자에 반드시 필요한 것은 아니지만, (예: Google Compute Engine는
`LoadBalancer`를 작동시키기 위해 `NodePort`를 할당할 필요는 없지만, AWS는 필요하다)
현재 API에는 필요하다.
## 가상 IP 구현 {#the-gory-details-of-virtual-ips}
서비스를 사용하려는 많은 사람들에게 이전 정보가
충분해야 한다. 그러나, 이해가 필요한 부분 뒤에는
많은 일이 있다.
### 충돌 방지
쿠버네티스의 주요 철학 중 하나는 잘못한 것이
없는 경우 실패할 수 있는 상황에 노출되어서는
안된다는 것이다. 서비스 리소스 설계 시, 다른 사람의 포트 선택과
충돌할 경우에 대비해 자신의 포트 번호를 선택하지
않아도 된다. 그것은 격리 실패이다.
서비스에 대한 포트 번호를 선택할 수 있도록 하기 위해, 두 개의
서비스가 충돌하지 않도록 해야한다. 쿠버네티스는 각 서비스에 고유한 IP 주소를
할당하여 이를 수행한다.
각 서비스가 고유한 IP를 받도록 하기 위해, 내부 할당기는
각 서비스를 만들기 전에 {{<glossary_tooltipterm_id="etcd">}}에서
글로벌 할당 맵을 원자적으로(atomically) 업데이트한다. 서비스가 IP 주소 할당을 가져오려면
레지스트리에 맵 오브젝트가 있어야 하는데, 그렇지 않으면
IP 주소를 할당할 수 없다는 메시지와 함께 생성에 실패한다.
컨트롤 플레인에서, 백그라운드 컨트롤러는 해당 맵을
생성해야 한다. (인-메모리 잠금을 사용하는 이전 버전의 쿠버네티스에서 마이그레이션
지원 필요함) 쿠버네티스는 또한 컨트롤러를 사용하여 유효하지 않은
할당 (예: 관리자 개입으로)을 체크하고 더 이상 서비스에서 사용하지 않는 할당된
IP 주소를 정리한다.
### 서비스 IP 주소 {#ips-and-vips}
실제로 고정된 목적지로 라우팅되는 파드 IP 주소와 달리,
서비스 IP는 실제로 단일 호스트에서 응답하지 않는다. 대신에, kube-proxy는
iptables (Linux의 패킷 처리 로직)를 필요에 따라
명백하게 리다이렉션되는 _가상_ IP 주소를 정의하기 위해 사용한다. 클라이언트가 VIP에
연결하면, 트래픽이 자동으로 적절한 엔드포인트로 전송된다.
환경 변수와 서비스 용 DNS는 실제로 서비스의
가상 IP 주소 (및 포트)로 채워진다.
kube-proxy는 조금씩 다르게 작동하는 세 가지 프록시 모드—유저스페이스, iptables and IPVS—를
지원한다.
#### 유저스페이스 (Userspace)
예를 들어, 위에서 설명한 이미지 처리 애플리케이션을 고려한다.
백엔드 서비스가 생성되면, 쿠버네티스 마스터는 가상
IP 주소(예 : 10.0.0.1)를 할당한다. 서비스 포트를 1234라고 가정하면, 서비스는
클러스터의 모든 kube-proxy 인스턴스에서 관찰된다.
프록시가 새 서비스를 발견하면, 새로운 임의의 포트를 열고, 가상 IP 주소에서
이 새로운 포트로 iptables 리다이렉션을 설정한 후,
연결을 수락하기 시작한다.
클라이언트가 서비스의 가상 IP 주소에 연결하면, iptables
규칙이 시작되고, 패킷을 프록시의 자체 포트로 리다이렉션한다.
"서비스 프록시"는 백엔드를 선택하고, 클라이언트에서 백엔드로의 트래픽을 프록시하기 시작한다.
이는 서비스 소유자가 충돌 위험 없이 원하는 어떤 포트든 선택할 수 있음을
의미한다. 클라이언트는 실제로 접근하는 파드를 몰라도, IP와 포트에
간단히 연결할 수 있다.
#### iptables
다시 한번, 위에서 설명한 이미지 처리 애플리케이션을 고려한다.
백엔드 서비스가 생성되면, 쿠버네티스 컨트롤 플레인은 가상
IP 주소(예 : 10.0.0.1)를 할당한다. 서비스 포트를 1234라고 가정하면, 서비스는
클러스터의 모든 kube-proxy 인스턴스에서 관찰된다.
프록시가 새로운 서비스를 발견하면, 가상 IP 주소에서 서비스-별 규칙으로
리다이렉션되는 일련의 iptables 규칙을 설치한다. 서비스-별
규칙은 트래픽을 (목적지 NAT를 사용하여) 백엔드로 리다이렉션하는 엔드포인트-별 규칙에
연결한다.
클라이언트가 서비스의 가상 IP 주소에 연결하면 iptables 규칙이 시작한다.
(세션 어피니티(Affinity)에 따라 또는 무작위로) 백엔드가 선택되고 패킷이
백엔드로 리다이렉션된다. 유저스페이스 프록시와 달리, 패킷은 유저스페이스로
복사되지 않으며, 가상 IP 주소가 작동하기 위해 kube-proxy가
실행 중일 필요는 없으며, 노드는 변경되지 않은 클라이언트 IP 주소에서 오는
트래픽을 본다.
트래픽이 노드-포트 또는 로드 밸런서를 통해 들어오는 경우에도,
이와 동일한 기본 흐름이 실행되지만, 클라이언트 IP는 변경된다.
#### IPVS
iptables 작업은 대규모 클러스터 (예: 10,000 서비스)에서 크게 느려진다.
IPVS는 로드 밸런싱을 위해 설계되었고 커널-내부 해시 테이블을 기반으로 한다. 따라서 IPVS 기반 kube-proxy로부터 많은 개수의 서비스에서 일관성 있는 성능을 가질 수 있다. 한편, IPVS 기반 kube-proxy는 보다 정교한 로드 밸런싱 알고리즘 (least conns, locality, weighted, persistence)을 가진다.
## API 오브젝트
서비스는 쿠버네티스 REST API의 최상위 리소스이다. API 오브젝트에 대한
자세한 내용은 다음을 참고한다. [서비스 API 오브젝트](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#service-v1-core)
## 지원되는 프로토콜 {#protocol-support}
### TCP
모든 종류의 서비스에 TCP를 사용할 수 있으며, 이는 기본 네트워크 프로토콜이다.
### UDP
대부분의 서비스에 UDP를 사용할 수 있다. type=LoadBalancer 서비스의 경우, UDP 지원은
이 기능을 제공하는 클라우드 공급자에 따라 다르다.
### HTTP
클라우드 공급자가 이를 지원하는 경우, LoadBalancer 모드의
서비스를 사용하여 서비스의 엔드포인트로 전달하는 외부 HTTP / HTTPS 리버스 프록시를
설정할 수 있다.
{{<note>}}
서비스 대신 {{<glossary_tooltipterm_id="ingress"text="인그레스">}} 를 사용하여
HTTP / HTTPS 서비스를 노출할 수도 있다.
{{</note>}}
### PROXY 프로토콜
클라우드 공급자가 지원하는 경우에 (예: [AWS](/docs/concepts/cluster-administration/cloud-providers/#aws)),
LoadBalancer 모드의 서비스를 사용하여 쿠버네티스 자체 외부에
로드 밸런서를 구성할 수 있으며, 이때 접두사가
[PROXY 프로토콜](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) 인 연결을 전달하게 된다.
쿠버네티스는 서비스, 엔드포인트, 네트워크 정책 및 파드 정의에서 알파 기능으로 SCTP를 `프로토콜` 값으로 지원한다. 이 기능을 활성화하기 위해서는, 클러스터 관리자가 API 서버에서 `--feature-gates=SCTPSupport=true,…`처럼 `SCTPSupport` 기능 게이트를 활성화해야 한다.
기능 게이트가 활성화되면, 서비스, 엔드포인트, 네트워크 정책 또는 파드의 `프로토콜` 필드를 `SCTP`로 설정할 수 있다. 쿠버네티스는 TCP 연결과 마찬가지로, SCTP 연결에 맞게 네트워크를 설정한다.
#### 경고 {#caveat-sctp-overview}
##### 멀티홈드(multihomed) SCTP 연결을 위한 지원 {#caveat-sctp-multihomed}
{{<warning>}}
멀티홈 SCTP 연결을 위해서는 먼저 CNI 플러그인이 파드에 대해 멀티 인터페이스 및 IP 주소 할당이 지원되어야 한다.
멀티홈 SCTP 연결을 위한 NAT는 해당 커널 모듈 내에 특수한 로직을 필요로 한다.
{{</warning>}}
##### type=LoadBalancer 서비스 {#caveat-sctp-loadbalancer-service-type}
{{<warning>}}
클라우드 공급자의 로드 밸런서 구현이 프로토콜로서 SCTP를 지원하는 경우에만 LoadBalancer `유형`과 SCTP `프로토콜`을 사용하여 서비스를 생성할 수 있다. 그렇지 않으면, 서비스 생성 요청이 거부된다. 현재 클라우드 로드 밸런서 공급자 세트 (Azure, AWS, CloudStack, GCE, OpenStack)는 모두 SCTP에 대한 지원이 없다.