실습
- NGINX Service를 생성해 보세요.
- Service 적용 후 Endpoint가 제대로 생성되었는지 확인해 보세요.
- 기존 POD를 Delete 후 Service 연결을 검증해 보세요.
- 복수의 POD를 실행하여 POD Load Balancing 기능을 검증해 보세요.
Why Service Discovery
Kube는 기본 철학(?)이 POD는 항상 죽을 수 있다 입니다. 기존 POD가 죽고 나서 새로 생성되는 POD는 IP, Hostname 등 환경 정보가 기존 POD와 다릅니다. (재시작이 아니라 새로운 POD가 생성입니다.) 이 때 POD 간 통신이 IP 기반이라면 Client 단에서 일일이 새로운 IP를 추가해야 하므로 관리가 불가능합니다. 그리고 기존 POD를 이중화하여 새로운 POD가 추가되면 해당 IP를 LoadBalancer에 새롭게 추가하는 기능도 필요합니다.
Kube는 이러한 문제를 Service라는 Object에서 DNS 기반으로 처리하여 해결합니다. 그리고 변경된 사항은 자동으로 데이터베이스에 업데이트되어 자동으로 반영합니다.
What is Kubernetes Service
Kubernetes 에서는 Service를 사용하여 POD 간 통신 또는 외부에서 POD 접속을 처리 합니다. (용어가 Service인데, 우리가 아는 Application 서비스와 전혀 상관 없습니다.)
Kube 환경에서 POD는 죽었다 (새로운 POD) 살았다 반복이 가능합니다. 이 때 신규로 생성된 POD는 새로운 POD 이므로 기존과 다른 IP(ex 10.10 -> 10.11)를 가집니다. 따라서 기존 VM간 통신처럼 IP 기반인 경우 클라이언트 단에서 변경된 IP 정보를 계속 업데이트 해야하는 등의 문제가 발생합니다.
이러한 문제를 Kubernetes Service는 IP가 아닌 도메인 이름(서비스 이름)을 사용하여 해결합니다.
그럼, 예제를 통하여 알아 보겠습니다.
1. NGINX POD를 지정(selector)하는 Service를 생성해 보세요
- 먼저 NGINX의 label을 확인합니다.
NGINX Deploy YAML
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-hello
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx # Service 등에서 참조할 Label 이름
spec:
containers:
- name: nginx
image: nginxdemos/hello
[spkr@erdia22 06.Deployment (k3s:nginx)]$ ka nginxhello-deploy.yml
deployment.apps/nginx-hello created
[spkr@erdia22 06.Deployment (k3s:nginx)]$ k get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-hello-c97cdb45c-9sn4w 1/1 Running 0 17s app=nginx,pod-template-hash=c97cdb45c
nginx-hello-c97cdb45c-2f2tq 1/1 Running 0 17s app=nginx,pod-template-hash=c97cdb45c
- 서비스 YAML 생성 시 위 label(app=nginx)을 selector 로 지정합니다. (selector는 말 그대로 지정자, 지정하는 대상을 가르킵니다.)
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
type: ClusterIP
ports:
- name: tcp
port: 80
selector: # 선택해야 할 POD 선택
app: nginx # POD Label 과 동일
port 번호는 컨테이너 이미지 생성 시 사용한 port 번호입니다.
서비스 확인
[spkr@erdia22 11.Service (spkn02:nginx)]$ k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc ClusterIP 10.233.25.109 <none> 80/TCP 2m2s
2. NGINX 서비스의 endpoint를 확인해 보세요
Kube는 service로 연결되는 실제 대상을 endpoint라는 이름으로 관리합니다.
Service 생성 후 endpoint로 조회 가능합니다.
[spkr@erdia22 junghoon2.github.io (spkn02:nginx)]$ k get endpoints
NAME ENDPOINTS AGE
nginx-svc 10.233.90.71:80 4m37s
위와 같이 nginx-svc에 해당하는 endpoint 대상의 ip(10.233.90.71)를 확인 가능합니다. 만약 위 endpoint 가 없다면 service가 바라보는 대상이 없으므로 service 설정이 제대로 안되어 있다는 걸 의미 합니다.
describe로 보시면 좀 더 자세한 정보를 확인하실 수 있습니다.
[spkr@erdia22 junghoon2.github.io (spkn02:nginx)]$ k describe endpoints nginx-svc
Name: nginx-svc
Namespace: nginx
Labels: <none>
Annotations: endpoints.kubernetes.io/last-change-trigger-time: 2021-05-21T00:45:58Z
Subsets:
Addresses: 10.233.90.71
NotReadyAddresses: <none>
Ports:
Name Port Protocol
---- ---- --------
tcp 80 TCP
Events: <none>
Kube 에서는 아래와 같이 API Server로 service, endpoint 변경 내역을 계속 체크 합니다.
3. 신규 Busybox POD를 생성하여 NGINX POD와 서로 연결해 보세요.
- Service 기능 검증을 위하여 새로운 Deploy를 생성하겠습니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: busybox
namespace: nginx
labels:
app: busybox
spec:
replicas: 1
selector:
matchLabels:
app: busybox # POD label과 일치
template:
metadata:
labels:
app: busybox # Selector label과 일치
spec:
containers:
- name: busybox
image: busybox
command:
- "/bin/sh"
- "-c"
- "sleep inf"
간단한 busybox pod 입니다.
[spkr@erdia22 11.Service (spkn02:nginx)]$ kgp
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox-6d8496d56f-z4mf2 1/1 Running 0 84s 10.233.90.72 node1 <none> <none>
nginx-6799fc88d8-rk4lj 1/1 Running 0 20h 10.233.90.71 node1 <none> <none>
이 때 busybox POD와 NGINX POD 연결 시 IP를 사용하지 않고 service 이름을 사용해서 통신이 가능 합니다.
[spkr@erdia22 11.Service (spkn02:nginx)]$ k exec -it busybox-6d8496d56f-z4mf2 -- sh
/ #
[spkr@erdia22 junghoon2.github.io (spkn02:nginx)]$ k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc ClusterIP 10.233.25.109 <none> 80/TCP 13m
/ # ping nginx-svc
PING nginx-svc (10.233.25.109): 56 data bytes
64 bytes from 10.233.25.109: seq=0 ttl=64 time=0.078 ms
64 bytes from 10.233.25.109: seq=1 ttl=64 time=0.089 ms
위와 같이 POD간 연결을 IP가 아닌 서비스 이름을 사용합니다.
/ # telnet nginx-svc 80
Connected to nginx-svc
흔히 port 오픈 확인 용도로 사용하시는 telnet도 사용 가능합니다.
만약, 실행 중인 POD의 namespace가 서로 다르면 연결 시 namespace 이름까지 붙여 줍니다. ‘default’ namespace POD에서 연결해 보겠습니다.
[spkr@erdia22 41.NGINX (k3s:nginx)]$ kns default
Context "k3s" modified.
Active namespace is "default".
[spkr@erdia22 41.NGINX (k3s:default)]$ ka busybox-deploy.yml
deployment.apps/busybox unchanged
[spkr@erdia22 junghoon2.github.io (spkn02:nginx)]$ k exec -it -n default date-pvc-mirror-5cf6bf8f4b-6jljp -- sh
/ # ping nginx-svc.nginx
PING nginx-svc.nginx (10.233.25.109): 56 data bytes
64 bytes from 10.233.25.109: seq=0 ttl=64 time=0.084 ms
64 bytes from 10.233.25.109: seq=1 ttl=64 time=0.923 ms
^C
--- nginx-svc.nginx ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.084/0.503/0.923 ms
/ # ping nginx-svc
ping: bad address 'nginx-svc'
위와 같이 nginx-svc.nginx (namespace 이름)는 가능하지만 nginx-svc로는 안 됩니다. 즉 다른 namespace에서는 namespace 이름까지 같이 지정해 주셔야 합니다.
4. NGINX POD 삭제하여 Service 접속 여부를 확인해 보세요.
기존 POD를 삭제하고 새로운 POD를 생성해 보겠습니다.
[spkr@erdia22 ~ (spkn02:nginx)]$ kgp
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-6799fc88d8-rk4lj 1/1 Running 0 20h 10.233.90.71 node1 <none> <none>
[spkr@erdia22 ~ (spkn02:nginx)]$ k delete pod nginx-6799fc88d8-rk4lj
pod "nginx-6799fc88d8-rk4lj" deleted
[spkr@erdia22 ~ (spkn02:nginx)]$ kgp
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-6799fc88d8-xqrcv 1/1 Running 0 47s 10.233.92.50 node3 <none> <none>
위와 같이 새로운 POD가 생성되어 IP가 변경되었습니다. (90.71 -> 92.50)
그럼 POD 간 연결을 확인해 보겠습니다.
[spkr@erdia22 junghoon2.github.io (spkn02:nginx)]$ k exec -it busybox-6d8496d56f-z4mf2 -- sh
/ # ping nginx-svc
PING nginx-svc (10.233.25.109): 56 data bytes
64 bytes from 10.233.25.109: seq=0 ttl=64 time=0.067 ms
64 bytes from 10.233.25.109: seq=1 ttl=64 time=0.077 ms
기존처럼 동일하게 서비스 이름(nginx-svc)으로 연결 가능합니다.
Service에서 자동으로 신규 생성된 POD IP를 endpoint로 등록하기 때문입니다. 따라서 POD IP가 변경되어도 동일하게 서비스 이름으로 POD간 통신이 가능합니다.
endpoint를 확인해 보면 ip가 변경(90.71 -> 92.50) 된 걸 확인 가능합니다.
[spkr@erdia22 ~ (spkn02:nginx)]$ k get endpoints
NAME ENDPOINTS AGE
nginx-svc 10.233.92.50:80 21m
이상으로 간단히 Service Discovery에 대하여 알아 보았습니다.
Kubernetes 컨설팅, 교육, 기술 지원 문의 : leejunghoon@spkr.co.kr
참조
https://kubernetes.io/ko/docs/tasks/access-application-cluster/connecting-frontend-backend/
'쿠버네티스 교육' 카테고리의 다른 글
09. Kube 교육 - MetalLB (2) | 2021.06.04 |
---|---|
08. Kube 교육 - NodePort, LoadBalancer (5) | 2021.06.04 |
14. Kube 교육 - Readiness/Liveness Probe (0) | 2021.06.04 |
13. Kube 교육 - Label & Affinity (0) | 2021.06.04 |
12. Kube 교육 - ConfigMap (0) | 2021.06.04 |