---
share: true
toc: true
categories: [Development, Kubernetes]
path: "_posts/development/kubernetes"
tags: [kubernetes, sre, devops]
title: "05. Services: Enabling Clients to Discover and Talk to Pods"
date: "2021-04-07"
github_title: "2021-04-07-05-services"
image:
  path: /assets/img/posts/development/kubernetes/k8s-05.jpeg
attachment:
  folder: assets/img/posts/development/kubernetes
---

![k8s-05.jpeg](/assets/img/posts/development/kubernetes/k8s-05.jpeg) _Using `kubectl exec` to test out a connection to the service by running curl in one of the pods. (출처: https://livebook.manning.com/book/kubernetes-in-action/chapter-5)_

많은 앱들이 request (요청) 을 받아 서비스를 제공하는 형태인데, 이런 요청을 보내려면 IP 주소를 알아야 한다. 한편 Kubernetes 를 사용하게 되면 pod 의 IP 주소를 알아야 하는데, Kubernetes 의 pod 들은 굉장히 동적이므로 이들의 IP 주소를 알아낼 방법이 필요하다.

Pod 들은 스케쥴링 되고 스케일링 되기 때문에 IP 주소가 자주 바뀔 수 있으며, pod 가 시작된 후 IP 주소가 할당될 뿐만 아니라, 하나의 서비스를 위해 pod 를 여러 개 사용하는 경우 하나의 IP 를 사용하여 여러 개의 pod 에 접근할 방법이 필요하다. (쿠버네티스를 사용하지 않으면 고정 IP 등을 사용하거나 따로 설정된 주소로 요청이 가도록 했을 것이다)

## 5.1 Services 소개

---

Service 를 이용하면 같은 일을 하는 여러 개의 pod 에 하나의 entrypoint 를 제공할 수 있다.

Service 는 IP 와 포트가 설정되어 있고 (service 가 살아있는 동안) 고정되어 있다. 자신의 주소로 요청이 들어오면 연결된 pod 중 하나로 요청을 보내준다. (로드 밸런싱도 가능)

### 5.1.1 Service 만들기

Service 에 포함되는 pod 를 정의하기 위해서는 **label selector** 를 사용한다.

```yaml
apiVersion: v1
kind: Service
metadata:
  name: sung
spec:
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: kubia
```

Service 가 실행했을 때 할당되는 IP 주소의 80 포트로 들어오는 요청은 `app=kubia` label 을 가진 pod 의 8080 포트로 요청이 전달된다.

`kubectl create` 로 service 를 생성한 후, `kubectl get svc` 를 하면 service 목록을 확인할 수 있다. Column 중에 `CLUSTER-IP` 가 있는데 이는 클러스터 내부에서 사용하는 IP 주소이다. (`EXTERNAL-IP` 는 외부에서 사용하는 주소인데 일단은 `<none>` 이다.)

원래 service 의 주 목적은 클러스터 내의 pod 들을 다른 pod 들에게 보여주는 것이므로 cluster IP 가 존재한다. (프론트, 백 각각 service 로 만들어 두면 프론트에서 백엔드 service 에 접근할 수 있어야 한다) 하지만 주로 클러스터 외부로 expose 하는 경우가 더 많을 것이다.

#### Session affinity

4장에서 사용한 ReplicationController 를 생성하고 service 를 만든 뒤 service 의 주소로 `curl` 을 날려보면 항상 같은 pod 가 요청을 처리하지는 않는다는 것을 확인할 수 있다. 만약에 같은 client 의 요청은 같은 pod 에서 처리하고 싶다면 `.spec.sessionAffinity` 를 설정하면 된다.

Service 의 `sessionAffinity` 는 `None` 과 `ClientIP` 만 지정할 수 있다. `ClientIP` 로 지정하게 되면 같은 client 의 요청은 하나의 pod 에서 무조건 처리하게 된다.

Cookie 를 사용한 affinity 설정은 불가능하다. Service 가 애초에 TCP/UDP 레벨 (transport layer)에 있어서 Cookie 가 있는 HTTP 레벨 (application layer) 과 다르다.

#### 여러 개의 포트 개방

여러 개의 포트를 개방하여 pod 의 포트로 redirect 시킬 수 있다. 다만 각 포트에 해당하는 이름을 설정해줘야 한다.

```yaml
...
spec:
  ports:
  - name: http # 이름을 지정해줘야 한다
    port: 80
    targetPort: 8080
  - name: https 
    port: 443
    targetPort: 8443
  selector:
    app: kubia
```

또한 label selector 는 포트마다 다르게 설정할 수 없다. 포트마다 다른 label selector 를 사용하고 싶다면 service 를 여러 개 만들어야 한다.

#### 포트에 이름 붙이기

애플리케이션이 복잡해지면 포트를 변경할 일이 생길 수도 있다. 포트 번호를 단순히 숫자로 관리하면 나중에 pod 레벨에서 port 가 변경되었을 때 이를 참조하는 모든 쿠버네티스 오브젝트의 spec 에서 포트 번호를 변경해야 할 수도 있다. 그래서 pod 정의시 포트에 이름을 붙일 수 있다.

```yaml
kind: Pod
spec:
  containers:
  - name: kubia
    ports:
    - name: http # 포트에 이름 붙이기
      containerPort: 8080
    - name: https
      containerPort: 8443
```

Service 의 YAML 파일에서는 아래와 같이 사용하면 된다.

```yaml
kind: Service
spec:
  ports:
  - name: http
    port: 80
    targetPort: http
  - name: https
    port: 443
    targetPort: https
```

Service 는 label selector 에 match 된 pod 중 임의의 한 pod 에 요청을 보낼텐데, 그 pod 의 정의에 포트 이름이 정의되어 있으면 그 포트 번호로 요청을 보내는 듯하다.

그러므로 이런 것도 가능하다. 예전에 만든 pod 에는 8080 포트에 이름 `http` 가 있었는데, 새로 만든 pod 에는 80 포트에 `http` 를 붙여놓았다면, (같은 일을 하는 pod 라고 하자) service 에서는 `http` 라는 이름만 이용해서 pod 에게 요청을 전달하므로 실제 포트 번호는 다르게 설정할 수도 있다.

### 5.1.2 Discovering services

Service 또한 pod 처럼 생성이 되어야 IP 주소가 할당되므로, pod 와 같은 문제를 갖고있다. Service 를 생성하고 그 IP 를 pod 에 하드코딩 하는 것도 바람직하지는 않아 보인다.

특정 service 가 필요한 pod 들에게 service 의 IP 주소를 알려줄 방법이 필요하다.

#### 환경 변수 사용

쿠버네티스는 pod 가 생성될 때 현재 존재하고 있는 각 service 를 가리키는 환경 변수를 설정한다.

그래서 service 를 먼저 만들고 이를 필요로 하는 pod 를 생성하면 환경 변수에서 service 의 IP 주소를 알 수 있다.

단, 이렇게 하면 의존성이 생기고, 쿠버네티스 리소스를 띄워야 하는 순서가 생겨버린다.

#### DNS, FQDN

쿠버네티스에도 DNS 서버가 있어서, 각 service 는 내부 DNS 서버에 등록된다. 그래서 pod 가 만약 service 의 이름을 알면 FQDN 을 이용해서 접근할 수 있게 된다.

FQDN 은 대략 이런 모양이다.

```
<service_name>.<namespace>.svc.cluster.local
```

단, 이렇게 하더라도 service 가 listen 하고있는 포트는 알아야 한다. (이건 IP 주소 알아내는 것보다는 쉬울 듯)

만약 namespace 가 같다면, service 의 이름만 가지고서도 접근이 가능하다!

#### Service IP 로 `ping` 이 불가능한 이유

`curl` 은 되지만 `ping` 은 안되는 이유는 cluster IP 가 virtual IP 라서 포트와 결합되었을 때 의미를 갖기 때문이다.

정확히는, `ping` 명령어는 ICMP 위에서 동작한다. 그런데 service 의 클러스터 내부에서 특정 포트만 사용하기 때문에 ICMP request 에 응답하지 않으므로 `ping` 이 불가능하다.

## 5.2 클러스터 외부의 service 에 접속하기

---

### 5.2.1 Service endpoints

Service 와 pod 은 직접 연결되지 않고 사이에 endpoints 라는 리소스가 있다. `kubectl describe svc <SVC_NAME>` 을 실행해보면 `Endpoints: ...` 라면서 IP 주소와 포트가 나열되어있는 것을 확인할 수 있다.

Pod selector 가 YAML 파일에 정의되어 있기는 하지만, 실제로 service 가 요청을 처리할 때는 pod selector 를 사용하지 않고 이 endpoints 에 있는 값들을 사용한다. Selector 는 endpoints 의 값들을 만들 때 사용한다.

그럼 endpoints 의 값들은 언제 갱신하는데? Pod 이 생길 때마다? -> 계속 읽어보니 readiness probe 가 성공했을 때 추가된다고 한다.

### 5.2.2 Service endpoints 직접 설정하기

Pod selector 가 없는 service 를 만들면 endpoints 가 설정되지 않는다.

Endpoints 리소스를 직접 만들어서 service 에 갖다 붙일 수 있다. 다만 만들어진 endpoints 리소스의 이름은 service 의 이름과 동일해야 한다.

이 방법을 이용하면 외부의 서버 등에 연결할 수 있는 service 를 하나 만들어두고 pod 들이 외부 서버에 접속할 때 해당 service 로 요청을 보내도록 할 수 있다. (로드 밸런싱은 덤)

Label selector 를 지정하면 endpoints 가 자동으로 관리되고, label selector 를 제거하면 endpoints 의 갱신은 멈춘다.

### 5.2.3 외부의 서비스 alias 설정

외부 서비스의 FQDN 을 이용해서 접근할 수 있다. Service 오브젝트를 생성할 때 `.spec.type` 를 `ExternalName` 으로 설정하면 된다. 이렇게 하면 외부 서비스의 FQDN 을 직접 이용하지 않고 service 를 경유하여 사용할 수 있게 된다. 나중에 외부 서비스를 교체할 일이 생길 때 훨씬 수월하게 교체할 수 있게 된다.

`ExternalName` service 들은 DNS 레벨에서 구현되어 있어서 `CNAME` record 가 생성된다. 이 service 에 접속을 시도하는 client 들은 외부 서비스에 직접 접속하며, service 에는 IP 가 할당 되지 않는다.

## 5.3 Service 를 외부에 공개하기

---

프론트엔드의 경우 외부로 공개할 필요가 있다. 공개하는 방법에는 세 가지 방법이 있다.

- Service 타입 `NodePort` 로 설정하기: 클러스터의 *각* 노드가 한 포트를 개방한다. 개방된 포트로 들어오는 요청은 해당 service 로 redirect 된다. 특정 노드에 구애받지 않고, 모든 노드의 해당 포트로 들어오는 요청이 redirect 된다.
- Service 타입 `LoadBalancer` 로 설정하기: 해당 service 를 위한 load balancer 의 IP 주소를 통해서 service 에 접근할 수 있도록 한다. (Cloud infrastructure 에서 관리)
- Ingress 리소스 만들기: HTTP level 에서 동작한다. 5.4 에서 설명한다.

### 5.3.1 NodePort service

`NodePort` service 를 생성하면 모든 노드의 한 포트가 reserve 된다. 해당 포트로 들어오는 요청은 모두 service 로 연결된다.

일반적인 service 와 크게 다르지 않지만, cluster IP 뿐만 아니라 임의의 노드 IP 와 포트를 통해서도 접근이 가능하다.

#### NodePort service 생성

```yaml
...
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30123 # 노드의 포트를 개방하도록 설정
```

개방할 포트를 안적으면 random 하게 선택되며, GKE 의 경우 방화벽 설정을 해야한다.

모든 노드의 IP 주소로부터 접근이 가능하지만, 만약 어떤 client 가 무조건 한 노드의 IP 로만 접근하는데 해당 노드가 죽는 경우에는 접근이 불가능해진다. 따라서 load balancer 를 사용하는 방법이 더 바람직하다.

### 5.3.2 Exposing a service through an external load balancer

Service 타입을 `LoadBalancer` 로 설정하면 된다. 다만 cloud infrastructure 단에서 load balancer 를 지원해줘야 한다. 만약 지원해주지 않는다면 `NodePort` service 와 동일하게 동작한다. (extension 이기 때문)

`LoadBalancer` service 를 생성하게 되면 해당 service 에 external IP 가 설정되며, 해당 주소로 접근할 수 있다.

`LoadBalancer` service 를 생성할 때도 `NodePort` service 가 그랬듯이 모든 노드에서 한 포트를 개방하게 되며, 로드 밸런싱을 거쳐 적절한 노드로 요청을 redirect 해준다. 또한 노드에서 한 포트가 개방되는 셈이므로, `kubectl describe` 를 이용하여 개방된 포트를 확인하고 방화벽 설정을 고쳐주면 `NodePort` service 처럼 노드의 IP 주소와 포트를 이용해 접근할 수 있다.

### 5.3.3 Understanding the peculiarities of external connections

#### Avoiding additional network hops

`NodePort` service 를 이용하게 되면 요청을 받은 노드에 요청을 처리해줄 pod 이 존재하지 않을 수도 있다. 혹은 임의로 선택된 pod 가 해당 노드에 존재하지 않을 수도 있다. 이 때 해당 pod 이 존재하는 노드로 가야하기 때문에 추가 delay 가 생긴다.

`.spec.externalTrafficPolicy` 를 `local` 로 설정하면 요청을 받은 노드 안에 있는 pod 로만 redirect 된다. 만약에 그런 pod 가 없으면 대기한다. 그러므로 쓰기 전에 노드에 pod 가 있음을 확신할 수 있어야 한다.

위 옵션을 사용하면 더 이상 요청이 pod 별로 균등하게 분배되지 않는다.

#### Non-preservation of the client's IP

`NodePort` service 를 통해 외부에서 접근하게 되면 SNAT 로 인해 source IP 가 변경된다. (내부에서는 무관) 그런데 만약 애플리케이션이 source IP 를 필요로 한다면 문제가 될 수도 있다.

## 5.4 Ingress resource

---

### Ingress 가 필요한 이유

`LoadBalancer` service 는 각 service 마다 load balancer 를 생성하고, 공개 IP 주소가 필요하지만, Ingress 는 여러 개의 service 를 관리하는데도 하나의 IP 주소만 있어도 된다. HTTP 요청을 받을 때, host 와 path 를 보고 어느 service 로 redirect 해야하는지 알 수 있다.

또한 application layer 에서 동작하기 때문에 service 가 제공하지 않는 기능들을 사용할 수 있다.

(IP 주소 하나 쓰는 것만으로는 조금 부족해 보이는데 어떤 기능들이 있는지 확인해 봐야겠다.)

더불어 Ingress 가 동작하려면 Ingress controller 가 동작하고 있어야 한다.

### 5.4.1 Ingress 리소스 생성

```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: sung
spec:
  rules:
  - host: sung.example.com # 이 주소로 들어오는 요청은 서비스로 redirect
    http:
      paths:
      - path: /
        backend:
          serviceName: sung
          servicePort: 80
```

Note. 위 처럼 생성하면 warning 이 발생한다.

```
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
```

### 5.4.2 Ingress 를 이용하여 service 접속

Domain name resolution 이 잘 되어야 한다! `kubectl get ingresses` 로 IP 를 확인할 수 있다. Ingress 에 입력한 `host` 값이 해당 IP 로 resolve 될 수 있도록 직접 설정해줘야 한다. `/etc/hosts` 를 쓰거나, DNS 서버를 직접 사용하거나...

#### How does it work?

1. Client 가 `sung.example.com` 의 IP 주소를 DNS 에서 찾아본다.
2. 받은 IP 주소에 HTTP 요청을 보낼 때 `Host: sung.example.com` 헤더를 넣어서 보낸다.
3. Ingress controller 는 어느 service 에 대한 요청인지 파악한다.
4. 해당 서비스의 endpoints 중 하나의 주소로 요청을 보낸다.

유의하여 볼 점은 service 에게 요청을 전달하지 않고 직접 pod 를 선택했다는 점이다.

### 5.4.3 하나의 Ingress 에 여러 service 연결하기

#### Mulitple paths

```yaml
...
- host: sung.example.com
  http:
    paths:
    - path: /sung # sung.example.com/sung
      backend:
        serviceName: sung
        servicePort: 80
    - path: /foo # sung.example.com/foo
      backend:
        serviceName: bar
        servicePort: 80
```

각 path 별로 다른 service 를 사용하도록 설정할 수 있다.

#### Multiple hosts

`host` 를 여러 개 등록하면 `Host: ...` 헤더 값에 따라 다른 service 에 접근할 수 있다. DNS 에 `host` 값을 등록하는 것을 잊으면 안 된다.

### 5.4.4 Configuring Ingress to handle TLS traffic

HTTPS 요청을 처리하는 방법에 대해서 알아본다.

#### TLS certificate for the Ingress

Client 와 controller 사이의 통신은 암호화 되어있지만, controller 와 pod 사이의 통신은 암호화 되어있지 않다. 그러므로 pod 에서 돌아가는 앱은 TLS 를 지원할 필요는 없다.

인증서와 private key 를 생성하여 Ingress 에 넣어주어야 한다. 원래는 Secret 이라는 쿠버네티스 리소스에 저장되지만 7장에서 자세히 살펴본다.

```bash
$ openssl genrsa -out tls.key 2048
$ openssl req -new -x509 -key tls.key -out tls.cert -days 360 -subj CN=sung.example.com

# Create Secret
$ kubectl create secret tls tls-secret --cert=tls.cert --key=tls.key
```

이제 YAML 파일을 수정한다.

```yaml
...
spec:
  tls:
  - hosts:
    - sung.example.com
    secretName: tls-secret
  rules:
...
```

## 5.5 연결을 받을 준비가 되었을 때 신호 보내기

---

Service 나 Ingress 를 사용하면 pod 가 생성되자마자 요청이 전달될 수 있다. (label 만 검사하므로) 한편 startup 이 오래걸리는 애플리케이션의 경우 아직 pod 는 준비가 안되었는데 요청을 받게 되어 요청을 정상적으로 처리 못하게 될 수 있다.

Pod 가 요청을 처리할 준비가 되었음을 확인할 방법이 필요하다.

### 5.5.1 Readiness probes

Readiness probe 는 주기적으로 실행되며, pod 가 client request 를 받을 준비가 되었는지 확인한다.

종류는 liveness probe 와 마찬가지로 세 종류가 있다.

- **HTTP GET probe**: 컨테이너 IP 주소에 GET 요청 보내보기
  - 응답 코드가 2xx, 3xx 이면 OK
  - 이외의 에러 코드나 응답이 없으면 실패로 간주
- **TCP socket probe**: 컨테이너의 정해진 포트에 TCP 연결을 시도해서 성공하면 준비된 것으로 판단
- **Exec probe**: 컨테이너 안에서 임의의 명령을 실행하고 exit code 가 0 이면 준비된 것으로 판단

#### Understanding the operation of readiness probes

- 첫 readiness probe 를 실행하기 전 얼만큼 기다릴지 미리 설정할 수 있다. 그 이후에는 주기적으로 실행한다.
- Ready 상태가 아니면 service 의 endpoints 에서 제거되고, 준비가 되면 추가된다.
- Liveness probe 는 실패하면 컨테이너를 재시작하지만, readiness probe 는 그렇지 않다.

Pod 이 죽을 때 어떤 방식으로 endpoints 를 업데이트 하는지? -> 이게 아니고 readiness probe 가 실패해서 endpoints 가 업데이트 되는 듯 하다. + 삭제시 쿠버네티스가 알아서 업데이트 해준다.

아무튼, readiness probe 는 client 들이 healthy pod 에만 요청을 할 수 있도록 관리해준다.

### 5.5.2 Pod 에 readiness probe 추가하기

ReplicationController's pod template 를 수정하여 readiness probe 를 추가한다. 컨테이너별로 readiness probe 의 동작을 다르게 정할 수 있다.

ReplicationController 의 pod template 을 수정하면 현재 존재하는 pod 에는 영향이 없으므로, 존재하는 pod 들은 삭제하고 새롭게 pod 를 띄우거나, ready 상태가 될 수 있도록 적절한 동작을 취해줘야 할 수도 있다.

### 5.5.3 Readiness probe 가 해야할 일

- 항상 readiness probe 를 사용할 것

사용하지 않으면, pod 의 시작과 동시에 service endpoints 에 추가되므로, 요청을 처리하지 못할 것이다.

- Don't include pod shutdown logic

Shutdown 이 시작되었음을 감지하고 readiness probe 가 실패하도록 로직을 짤 필요는 없다. Pod 가 삭제되면 쿠버네티스가 자동으로 service endpoints 에서 제거한다.

## 5.6 Headless service for discovering individual pods

---

Client 가 모든 pod 에 접근해야 한다면? (어떤 경우에 이러한가? - 아래 Discussion 참고)

DNS lookup 을 이용할 수 있다! 보통 service 를 위해 DNS lookup 을 하면 하나의 IP (service IP) 를 돌려주지만, service 에 cluster IP 가 필요없다고 설정하면, endpoints 에 있는 IP 들을 DNS `A` 레코드로 돌려준다.

### 5.6.1 Headless service 생성

`.spec.clusterIP: None` 으로 설정하면 된다.

### 5.6.2 Discovering pods through DNS

`nslookup` 명령어로 확인하면 된다!

#### YAML 없이 pod 띄우기

```bash
$ kubectl run <POD_NAME> --image=<IMAGE_NAME> --generator=run-pod/v1
```

진짜로 pod 만 만들어준다. ReplicationController, service 이런거 없이 만들어 준다.

### 5.6.3 Discovering all pods - even those that aren't ready

Service 에서 `publishNotReadyAddresses=True` 로 설정하면 된다.

## 5.7 Troubleshooting

---

순서대로 해보면 좋을 것이다!

- Service cluster IP 를 사용하는 경우 클러스터 내에서 접속하고 있는지 확인하자.
- Service IP 에는 `ping` 이 동작하지 않는다.
- Readiness probe 를 설정했다면 성공하는지 꼭 확인해야 한다. 그렇지 않으면 pod 가 service 의 endpoints 에 등록되지 않는다.
- Pod 가 service 의 endpoints 에 등록되었는지 확인하려면 `kubectl get endpoints`.
- FQDN 으로 접속이 안되면, cluster IP 를 사용해서 되는지 확인해본다.
- Service 의 타겟 포트가 아니고 expose 한 포트로 접속하고 있는지 확인한다.
- Pod IP, 포트로 직접 접속하여 요청을 받는지 확인한다.
- 마지막으로, 앱이 localhost 에 바인딩 하지 않았는지 확인한다.

11장에서 service 가 어떻게 구현되었는지 공부하면 디버깅이 더 쉬울 것이라고 한다 ...

---

## Discussion & Additional Topics

### When would you want to set sessionAffinity to `ClientIP` ?

- 좋은 방법은 아니겠지만, session 정보를 저장해야 하는 경우가 그럴 것이다. 예를 들면 pod A, B 가 실행 중인데 처음에 A 로 접속해서 로그인했다고 하자. 그러면 다음 요청을 보낼 때 A 로 가게 되면 로그인 된 것으로 처리하지만, pod B 로 요청이 가게 되면 로그인하지 않은 상태일 것이다.
- 위와 같은 경우 로그인 상태를 캐싱하고 있는 서버를 별도로 두는 것이 좋다. Pod B 에서 캐싱 서버로 요청을 보내 사용자의 로그인 여부를 판단할 수 있게 될 것이다.

### Current Ingress resource example

- https://kubernetes.io/docs/concepts/services-networking/ingress/#the-ingress-resource

### Why does Ingress controller select pods directly, and not pass the request to the service?

### Pod 가 이미 에러나서 요청을 처리하지 못하지만 죽지는 않은 상태이다. 한편 readiness probe 가 아직 실행되지 않았으면 그 사이에 도착한 요청들은 다 망한건가? ㅋㅋ

- 예.

### 왜 pod 의 YAML 에서 설정하는 것이 아니고 rc 에서 하는 것일까? 현실에서는 어차피 복제될 pod 라 괜찮겠지만...

- Pod 를 실제로 복제할 때 readiness probe 에 대한 정보도 필요하므로 rc 의 template 에 넣어야 맞을 것이다.

### When would we actually use `publishNotReadyAddresses=True` ?

- https://stackoverflow.com/questions/51098498/keep-a-kubernetes-pod-in-service-when-in-a-state-of-not-ready
- 뭔지 잘 모르겠다.

### FQDN 사용 시 `cluster.local` 이 아닌 곳으로도 접근이 가능한 경우가 있을까?

### FQDN

- https://en.wikipedia.org/wiki/Fully_qualified_domain_name

### DNS Records

- https://en.wikipedia.org/wiki/List_of_DNS_record_types
- `dig` 명령어로 DNS record 조회 가능하다.

#### 대표적인 records

- A record: 도메인에 IP 를 할당한다.
- CNAME record: Canonical NAME record 으로, 특정 도메인을 다른 도메인 이름으로 매핑한다.

### Load Balancer 이야기

- https://d2.naver.com/helloworld/605418

### Client 가 여러 pod 에 동시에 연결하는 상황의 예시

- 동영상 스트리밍 할 때, 자연스럽게 화질을 전환하는 경우!
- 고화질, 중화질, 저화질 서버를 각각 pod 으로 만들어 둔 뒤, client 는 모든 pod 에 연결하고, 네트워크 상황에 따라 pod 을 바꿔가며 동영상을 스트리밍 하면 된다.

### Can a single K8s pod host 2 or more K8s services?

- https://stackoverflow.com/questions/46981184/kubernetes-can-a-single-k8s-pod-host-2-or-more-k8s-services/46984384#46984384

### JSONPath / XPath

- https://kubernetes.io/docs/reference/kubectl/jsonpath/
