Service Discovery
๊ฐ์
Creating a single control-plane cluster with kubeadm | Testing a simple Nginx deployment ์์ ์ค์ตํ๋ ๋ด์ฉ์์ ์กฐ๊ธ ๋ ํ์ฅํ์ฌ ์ดํดํ์ฌ ๋ณธ๋ค.
์ฌ๊ธฐ์์ ์ฌ์ฉ๋๋ config ํ์ผ์ https://github.com/snetsystems/K8s-Objects/tree/master/tests ์ ์ ๋ก๋ ๋์ด ์๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก pod๋ ๋ด๋ถ IP๊ฐ ํ ๋น๋๋ฉฐ ์ธ๋ถ์์ ์ ๊ทผ์ด ๋ถ๊ฐ๋ฅ ํ๋ค.
๋ํ, Pod๋ ์ธ์ ๋ ์ฃฝ์ ์ ์๋ค๋ ๊ฒ์ด k8s์ ์ฒ ํ์ด๋ฉฐ pod๊ฐ ๋ค์ ๋ง๋ค์ด ์ง ๊ฒฝ์ฐ pod์ ํ ๋น๋ IP๊ฐ ๋ณ๊ฒฝ๋๊ฒ ๋๋ค. ํด์, ๋ด๋ถ Pod๊ฐ ํต์ ์ ์ํด์๋ ์ ํต์ ๋ฐฉ์์ธ IP addr์ ํตํ ํต์ ์ผ๋ก๋ ๋ถ๊ฐ๋ฅํ๋ค.
์ฆ, Service discovery ๋ฐฉ์์ผ๋ก ํด๊ฒฐํ๊ฒ ๋๋๋ฐ, ์ฆ ๋๋ฉ์ธ ๋ฐฉ์์ผ๋ก ์ ๊ทผํ๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก K8s๋ฅผ Initializeํ๊ฒ ๋๋ฉด, coredns pod๊ฐ ์์ฑ๋๋ฉฐ, ์์ฑ๋ ๋ชจ๋ pod๋ ์ฌ๊ธฐ ๋ฑ๋ก๋์ด ์๋์ ๊ฐ์ด kube-dns
์๋น์ค๋ก dns ์ฟผ๋ฆฌํ์ฌ pod IP๋ฅผ ์์๋ธ ํ ํต์ ์ ์ฐ๊ฒฐํ๊ฒ ๋๋ค.
$ kubectl get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 13d
์ ๋ฆฌํ์๋ฉด, ๊ฐ๊ฐ์ Pod๋ ์ธ์ ๋ IP๊ฐ ๋ณ๊ฒฝ๋ ์ ์์ผ๋ฉฐ ํ ๋น๋ IP๋ label selector๋ก ์ง์ ๋ ์๋น์ค๋ฅผ ํตํด ๋๋ฉ์ธ์ผ๋ก ํต์ ํ๊ฒ ๋๋ค.
์ด์ ์๋ ์์ ๋ฅผ ํตํด ์ดํด๋ฅผ ๋์ฌ๋ณด์.
์ธ๋ถ์์์ Pod ์ ์ ํ ์คํธ
nginx-deployment.yaml
ํธ์๋ฅผ ์ํด test namespace๋ฅผ ์์ฑํ๋ค.
apiVersion: v1
kind: Namespace
metadata:
name: test
nginx pod๋ฅผ 2๊ฐ(replicas: 2
)๋ก ์์ฑํ๋ค.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: test
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx # ์ด label์ Service object์ ์ง์ ํด์ผ ์๋น์ค ๋๋ฉ์ธ์ ํตํ ํต์ ์ฐ๊ฒฐ์ด ์ํ๋จ.
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:stable-alpine3.17-slim
ports:
- containerPort: 80
๊ฐ๊ฐ์ ํ์
๋ณ ํ
์คํธ๋ฅผ ์ํด,
ClusterIP, LB, NodePort ํ์
์ ์๋น์ค๋ค์ ๊ฐ๊ฐ ์์ฑํ์ฌ ๋ณธ๋ค.
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: test
spec:
selector:
app: nginx # ์ matchLabels์ ์ง์ ๋์๋ label ์ง์ .
type: ClusterIP
ports:
- name: http
port: 80 # targetPort๋ฅผ ์ง์ ํ์ง ์์ ๊ฒฝ์ฐ, targetPort=port ์ค์ ๊ฐ.
externalIPs:
- 10.20.2.235
- 10.20.2.236
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc-lb
namespace: test
spec:
selector:
app: nginx # ์ matchLabels์ ์ง์ ๋์๋ label ์ง์ .
type: LoadBalancer
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 80
#nodePort: 30036 # ์๋ต ์, ์์๊ฐ ์ง์ ๋จ.(30000-32767)
externalIPs:
- 10.20.2.235
- 10.20.2.236
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc-np
namespace: test
spec:
selector:
app: nginx # ์ matchLabels์ ์ง์ ๋์๋ label ์ง์ .
type: NodePort
ports:
- name: http
port: 8081
protocol: TCP
targetPort: 80
#nodePort: 30037 # ์๋ต ์, ์์๊ฐ ์ง์ ๋จ.(30000-32767)
externalIPs:
- 10.20.2.235
- 10.20.2.236
๋ชจ๋ ๋ฌธ์ ์์ด ์์ฑ๋๋ค๋ฉด, ์๋์ ๊ฐ์ ๊ฒ์ด๋ค.
$ kubectl get po -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-6c8cf466cd-mpfz4 1/1 Running 0 129m 10.244.1.15 test-k8s-worker01-centos8.snetsystems.com <none> <none>
nginx-6c8cf466cd-xgbd7 1/1 Running 0 129m 10.244.2.14 test-k8s-worker02-centos8.snetsystems.com <none> <none>
$ kubectl get svc -n test
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc ClusterIP 10.105.132.127 10.20.2.235,10.20.2.236 80/TCP 45h
nginx-svc-lb LoadBalancer 10.110.214.153 10.20.2.235,10.20.2.236 8080:31558/TCP 45h
nginx-svc-np NodePort 10.97.16.76 10.20.2.235,10.20.2.236 8081:31511/TCP 45h
์์์ externalIPs
๋ฅผ ๊ฐ๊ฐ ์ง์ ํ์ฌ ๋์๊ธฐ ๋๋ฌธ์, ๊ฐ๊ฐ์ externalIPs
๋ฅผ ํตํ์ฌ ๊ฐ 80, 8080 ํฌํธ๋ก ์ ์์ด ๊ฐ๋ฅํ๋ค.
๊ฐ๋ฅํ ์กฐํฉ์ curl ํ ์คํธ:
$ curl http://10.20.2.235
$ curl http://10.20.2.236
$ curl http://10.20.2.235:8080
$ curl http://10.20.2.236:8080
$ curl http://10.20.2.236:8081
$ curl http://10.20.2.236:8081
# ๋ฌผ๋ก LoadBalancer์ NodePort Type ์๋น์ค๋ nodeport๋ก๋ ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค.
$ curl http://10.20.2.235:31558
$ curl http://10.20.2.236:31558
$ curl http://10.20.2.235:31511
$ curl http://10.20.2.236:31511
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
</html>
๋ํ, ๊ฐ๊ฐ์ ์๋น์ค๋ label selector app: nginx
๋ก ์ง์ ํ์๊ธฐ ๋๋ฌธ์ deploy๋ก ์์ฑํ 2๊ฐ์ nginx pod์ Load balancing ๋๋ค.
nginx-6c8cf466cd-xgbd7 ๋ก๊ทธ:
10.244.2.1 - - [27/Jun/2023:08:30:40 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
10.244.2.1 - - [27/Jun/2023:08:31:58 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
10.244.2.1 - - [27/Jun/2023:08:34:14 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
10.244.2.1 - - [27/Jun/2023:08:34:18 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
10.244.2.1 - - [27/Jun/2023:08:34:19 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
10.244.2.1 - - [27/Jun/2023:08:34:20 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
10.244.2.1 - - [27/Jun/2023:08:34:20 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
10.244.2.1 - - [27/Jun/2023:08:34:40 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
nginx-6c8cf466cd-mpfz4 ๋ก๊ทธ:
10.244.2.1 - - [27/Jun/2023:08:30:40 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
10.244.2.1 - - [27/Jun/2023:08:31:58 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
10.244.2.1 - - [27/Jun/2023:08:34:14 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
10.244.2.1 - - [27/Jun/2023:08:34:18 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
10.244.2.1 - - [27/Jun/2023:08:34:19 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
10.244.2.1 - - [27/Jun/2023:08:34:20 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
10.244.2.1 - - [27/Jun/2023:08:34:20 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
10.244.2.1 - - [27/Jun/2023:08:34:40 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.61.1" "-"
๋ด๋ถ Pod๊ฐ ํต์
์์ ๊ฐ์์์ ์ธ๊ธํ์๋ฏ์ด, ๋ชจ๋ Pod๋ค์ IP ๋์ ๋๋ฉ์ธ์ผ๋ก ํต์ ํ ์ ์๋ค.
์ฆ, Pod๊ฐ internal ํต์ ์ ์ํด์๋ ์๋น์ค๋ช
์ผ๋ก accessํ๋ค.
๊ด๋ จ ํ ์คํธ๋ฅผ ์ํด test namespace์ ์๋์ ๊ฐ์ pod๋ฅผ ํ๋ ์์ฑํ์.
apiVersion: apps/v1
kind: Deployment
metadata:
name: busybox
namespace: test
labels:
app: busybox
spec:
replicas: 1
selector:
matchLabels:
app: busybox
template:
metadata:
labels:
app: busybox
spec:
containers:
- name: busybox
image: busybox
command:
- "/bin/sh"
- "-c"
- "sleep inf"
์ ์ ์์ฑ๋๋ฉด ์๋์ ๊ฐ์ ๊ฒ์ด๋ค.
$ kubectl get po -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox-9ff887cc8-f5m46 1/1 Running 0 46h 10.244.1.16 test-k8s-worker01-centos8.snetsystems.com <none> <none>
nginx-6c8cf466cd-mpfz4 1/1 Running 0 46h 10.244.1.15 test-k8s-worker01-centos8.snetsystems.com <none> <none>
nginx-6c8cf466cd-xgbd7 1/1 Running 0 46h 10.244.2.14 test-k8s-worker02-centos8.snetsystems.com <none> <none>
busybox ๋ด๋ถ ์๋ก ์ง์ ํ์ฌ ๊ฐ pod ip๋ก ์ ๊ทผํด๋ณด๋ฉด, ๋น์ฐํ๊ฒ๋ overlay networking์ ํตํด ์ ์ ๊ทผ๋๋ค๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
# kubectl exec -n test -it busybox-9ff887cc8-f5m46 -- sh
/ # ping 10.244.2.14
PING 10.244.2.14 (10.244.2.14): 56 data bytes
64 bytes from 10.244.2.14: seq=0 ttl=62 time=1.243 ms
64 bytes from 10.244.2.14: seq=1 ttl=62 time=0.887 ms
^C
--- 10.244.2.14 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.887/1.065/1.243 ms
--- 10.244.2.15 ping statistics ---
7 packets transmitted, 0 packets received, 100% packet loss
/ #
/ # ping 10.244.1.15
PING 10.244.1.15 (10.244.1.15): 56 data bytes
64 bytes from 10.244.1.15: seq=0 ttl=64 time=0.322 ms
^C
--- 10.244.1.15 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.322/0.322/0.322 ms
CRI-O runtime์ ๊ฒฝ์ฐ ๋ณด์ ์ pod ๋ด๋ถ์์ ping์ด ๋๊ฐ๋ ๊ฒ์ด ๋งํ์๋ค.
๊ฐ K8s ํด๋ฌ์คํฐ ๋
ธ๋๋ค์ /etc/crio/crio.conf.d/default_capabilities.conf
๋ฅผ ์์ฑํ์ฌ,
์๋ ์ต์
(โNET_RAW
")์ ๋ฃ์ด์ค๋ค.[crio.runtime]
default_capabilities = [
"CHOWN",
"DAC_OVERRIDE",
"FSETID",
"FOWNER",
"SETGID",
"SETUID",
"SETPCAP",
"NET_BIND_SERVICE",
"KILL",
"NET_RAW",
]
์ดํ, systemctl restart crio๋ฅผ ํตํด crio๋ฅผ ์ฌ์์ํ๊ณ ,
ping์ ์ฌ์ฉํ๋ ค๋ pod(โbusyboxโ)๋ ์ฌ์์ฑํด์ผ ํ๋ค.
์์ธํ ๋ด์ฉ์ https://flavono123.github.io/posts/crio-capabilities-bug/ ์ ์ฐธ๊ณ ํ๊ธฐ ๋ฐ๋๋ค.
๊ทธ๋ฌ๋, IP๋ ์ธ์ ๋ ๋ฐ๋ ์ ์์ผ๋ฏ๋ก, ์ด๋ฒ์๋ ๋ฏธ๋ฆฌ ๋ง๋ค์ด๋ Service๋ฅผ ํตํด ์ ๊ทผํด๋ณด๋๋ก ํ์.
๋น์ฐํ ๋ง์ด์ง๋ง, Service๋ Pod๊ฐ ์๋๋ผ pod์ ํน์ ํฌํธ๋ฅผ cluster ip์ ํฌํธ๋ก ์ฐ๊ฒฐํด์ฃผ๋ ์ผ์ข ์ ์ ์ฑ ์ด๋ฏ๋ก, ์์ ping์ ๋๋ฌํ์ง ์๋๋ค.
์๋์ ๊ฐ์ด telnet์ ํตํด ์๋น์ค ํฌํธ๋ก ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
/ # telnet nginx-svc 80
Connected to nginx-svc
/ # telnet nginx-svc-lb 8080
Connected to nginx-svc-lb
# telnet nginx-svc-np 8081
Connected to nginx-svc-np
๊ทธ๋ผ ์ด๋ป๊ฒ pod์์ ์๋น์ค ํฌํธ๋ก ์ ๊ทผ์ด ๊ฐ๋ฅํ ๊น?
nslookup์ ํตํด ๋๋ฉ์ธ ์ฐพ๊ธฐ๋ฅผ ํด๋ณด์.
/ # nslookup nginx-svc
Server: 10.96.0.10
Address: 10.96.0.10:53
** server can't find nginx-svc.svc.cluster.local: NXDOMAIN
Name: nginx-svc.test.svc.cluster.local
Address: 10.105.132.127
์์ 10.96.0.10:53
์ kube-dns
์๋น์ค์ CLUSTER-IP
์ด๋ค.(kubectl get svc -n kube-system
๋ช
๋ น์ผ๋ก ํ์ธํ ์ ์๋ค.)
10.105.132.127
๋ nginx-svc
์๋น์ค์ CLUSTER-IP
์ด๋ค.
์ฆ, CLUSTER-IP: 10.105.132.127
์ ๋ํ์ฌ nginx-svc.test.svc.cluster.local
์ผ๋ก ๋๋ฉ์ธ์ด ๋ฑ๋ก๋์ด ์์์ ์ ์ ์์ผ๋ฉฐ, nginx-svc
๋ label selector๋ก ๊ฐ pod์ ์ฐ๊ฒฐ๋๋ค๋ ๊ฒ์ ์ถ์ ํ ์ ์์ ๊ฒ์ด๋ค.
์ฐธ๊ณ ๋ก, ๋ค๋ฅธ domain์ pod์ ์ ๊ทผํ๊ธฐ ์ํด์๋ ์๋น์ค๋ช
.๋๋ฉ์ธ๋ช
์ผ๋ก ์ฌ์ฉํ๋ฉด ๋๋ค.
/ # telnet kube-dns.kube-system 53
Connected to kube-dns.kube-system
Connection closed by foreign host
Headless Service
์ Service ์์ ์์๋ ํธ์์ externalIPs
๋ฅผ ๋ชจ๋ ํ ๋นํ์๋ค.
ํ์ง๋ง,
Pod ๊ฐ ํต์ ์ฆ ํด๋ฌ์คํฐ ๋ด ํต์ ๋ง์ ํ๊ธฐ ๋๋ฌธ์ ๊ตณ์ด
externalIPs
๋ฅผ ํ ๋นํ ํ์๊ฐ ์๋ค.ํด๋ฌ์คํฐ๋ Pod๊ฐ 2๊ฐ ์ด์์ด๊ณ , ์ด๋ค pod๋ค์ load balancing ํ์ฌ requestํ ํ์๊ฐ ์๋ค.
๋ฑ์ ๊ฒฝ์ฐ, Headless ์๋น์ค๋ฅผ ์์ฑํ๋ฉด ๋๋๋ฐ, ํด๋ฌ์คํฐ ๋ด์์ DNS ์ฟผ๋ฆฌ๋ฅผ ํ๋ฉด, ์ ์ฅ์์ ์ดํด๋ณธ CLUSTER-IP
๊ฐ ํ ๋น๋์ง ์๊ธฐ ๋๋ฌธ์ ํด๋น Pod์ IP๋ฅผ ์ง์ ์ ๊ณตํด์ค๋ค.
๋ง์ฝ 2๊ฐ ์ด์์ Pod๊ฐ seletor๋ก ์ฐ๊ฒฐ๋์ด ์๋ค๋ฉด, ๋๋คํ ์์๋ก ์ด ์๋น์ค์ ์ฐ๊ฒฐ๋ ๋ชจ๋ IP ๋ฆฌ์คํธ๋ฅผ ๋ฆฌํดํ๊ฒ ๋๋ค. ๋ง๊ทธ๋๋ก, DNS ์๋ฒ ์ญํ ๋ง ์ํํ๋ค.
์์ธํ ๋ด์ฉ์ ๊ตฌ๊ธ ๊ฒ์ ๋ฑ์ ํตํด ์ดํด๋ณด๊ธฐ๋ฅผ ๋ฐ๋ผ๋ฉฐ, ์๋์ ๊ฐ์ด clusterIP: None
์ ๋ช
์์ ์ผ๋ก ๋ถ์ฌ์ฃผ๋ฉด ๋๋ค.
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: test
spec:
selector:
app: nginx # ์ matchLabels์ ์ง์ ๋์๋ label ์ง์ .
type: ClusterIP
clusterIP: None
ports:
- name: http
port: 80 # targetPort๋ฅผ ์ง์ ํ์ง ์์ ๊ฒฝ์ฐ, targetPort=port ์ค์ ๊ฐ.
์์ฑ ํ, ์ ์ฅ์ ๋ด์ฉ๋๋ก nslookup
ํ
์คํธ๋ฅผ ํด๋ณด๋ฉด ์ดํด๊ฐ ๋ ๊ฒ์ด๋ค.
์ ๋ฆฌ
์ด ์ค์ต๋ค์ ํตํด ๋ชจ๋ ์ดํ๋ฆฌ์ผ์ด์ ์์คํ ์ ์ด๋ป๊ฒ K8s ์์ ๊ตฌ์ถํ ๊ฒ ์ธ๊ฐ์ ๋ํ ํต์์ ๊ฐ๋ ์ ์์๋ณด์๋ค.
๋ค์์๋ ์๋์ ๊ฐ์ ์์ฑ๋ ํํ์ ์ดํ๋ฆฌ์ผ์ด์ ์๋น์ค์ Server side๋ฅผ deploy ํด๋ณผ ๊ฒ์ด๋ค.
ย