서비스(Service) 가 필요한 이유
- 파드는 일회성이다. 노드에서 파드가 제거되면 새로운 파드가 생성되거나, 클러스터의 노드에 장애가 발생되면 다른 노드로 이동된다.
- 쿠버네티스의 파드는 노드에 스케쥴된 후 시작하기 전에 IP 주소를 할당하기 때문에 미리 파드의 IP 주소를 알기 어렵다.
- Scale-out(HPA) 는 여러 파드가 같은 서비스를 제공하는 것을 의미하는데 각 파드는 개별 IP 주소를 가지게 된다. 클라이언트는 서비스를 제공하는 파드의 수와 IP를 신경 쓸 필요가 없어야 한다.
-> 서비스 (Service)를 사용하면 파드가 클러스터 안 어디에 있던 고정 IP 주소 (Endpoint IP Address)를 통해서 접근할 수 있다.
CluserIP
기본 서비스 타입으로 클러스터 내부에서 사용이 가능.
클러스터 안 노드나 파드에서는 ClusterIP를 이용해서 서비스에 연결된 파드에 접근할 수 있다.
클러스터 외부에서는 사용할 수 없다.
root@master:~/k8s_lab/service# cat clusterip-hostname.yaml
apiVersion: v1
kind: Service
metadata:
name: clusterip-hostname-service
spec:
type: ClusterIP
selector:
app: hostname-server
ports:
- protocol: TCP
port: 8080
targetPort: 80
root@master:~/k8s_lab/service# cat hostname-server.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hostname-server
labels:
app: hostname-server
spec:
replicas: 2
selector:
matchLabels:
app: hostname-server
template:
metadata:
labels:
app: hostname-server
spec:
containers:
- name: hostname-server
image: takytaky/hostname
ports:
- containerPort: 80
-> 2개의 pod를 생성하고 각 pod에는 80 포트로 server가 동작함.
root@master:~/k8s_lab/service# kubectl apply -f hostname-server.yaml
deployment.apps/hostname-server created
root@master:~/k8s_lab/service# kubectl apply -f clusterip-hostname.yaml
service/clusterip-hostname-service created
root@master:~/k8s_lab/service# kubectl get deploy,svc,pods -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/hostname-server 2/2 2 2 38s hostname-server takytaky/hostname app=hostname-server
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/clusterip-hostname-service ClusterIP 10.106.104.217 <none> 8080/TCP 26s app=hostname-server
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16d <none>
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/hostname-server-775f65669c-psgkf 1/1 Running 0 37s 192.168.235.140 worker1 <none> <none>
pod/hostname-server-775f65669c-tvh8w 1/1 Running 0 36s 192.168.189.81 worker2 <none> <none>
ClusterIP 서비스를 띄우고 describe 명령어로 상세 내역을 보면 서비스 ClusterIP 및 각 POD의 IP 할당 내용을 볼수 있다.
root@master:~/k8s_lab/service# kubectl describe svc clusterip-hostname-service
Name: clusterip-hostname-service
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=hostname-server
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.106.104.217
IPs: 10.106.104.217
Port: <unset> 8080/TCP
TargetPort: 80/TCP
Endpoints: 192.168.189.81:80,192.168.235.140:80
Session Affinity: None
Events: <none>
마스터 노드에서 ClusterIP로 http request 테스트를 해보면 아래와 같이 worker1, worker2 노드에 각각 떠있는 pod에서 서버 api 호출 결과가 출력 되는 것을 볼수 있다.
root@master:~/k8s_lab/service# for i in $(seq 10);do curl -s 10.106.104.217:8080 | grep Hello;sleep 1;done
<p>Hello, hostname-server-775f65669c-psgkf</p> </blockquote>
<p>Hello, hostname-server-775f65669c-tvh8w</p> </blockquote>
하지만 앞서 말한 대로 ClusterIP는 클러스터 내부에서만 동작 하므로 Node 외부에서는 접근이 불가능하다.
마스터 노드의 외부 IP는 172.30.1.25 이므로 해당 IP로 동일하게 실행시에는 아무런 응답이 발생하지 않는다.
root@master:~/k8s_lab/service# for i in $(seq 10);do curl -s 172.30.1.25:8080 | grep Hello;sleep 1;done (결과 X)
root@master:~/k8s_lab/service#
NodePort
- NodePort 타입의 서비스에 클러스터의 모든 노드들의 지정된 포트를 할당.
- 노드에 상관없이 지정된 포트 번호만 사용하면 파드에 접근 가능.
-> 노드의 주소를 사용하기 때문에 클러스터 안에서 뿐만 아니라 클러스터 외부에서도 접근 가능
worker1 노드에서만 파드가 실행되어 있더라도 worker2 의 주소로 접근이 가능
root@master:~/k8s_lab/service# cat nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: nodeport-hostname-service
spec:
type: NodePort
selector:
app: hostname-server
ports:
- protocol: TCP
port: 8080
targetPort: 80
nodePort: 30080
root@master:~/k8s_lab/service# kubectl delete svc clusterip-hostname-service
service "clusterip-hostname-service" deleted
=> 앞서 실행했던 cluserip service를 삭제
root@master:~/k8s_lab/service# kubectl apply -f nodeport.yaml
service/nodeport-hostname-service created
=> NodePort 서비스 새로 생성
root@master:~/k8s_lab/service# kubectl get deploy,svc,pods -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/hostname-server 2/2 2 2 14m hostname-server takytaky/hostname app=hostname-server
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16d <none>
service/nodeport-hostname-service NodePort 10.99.158.187 <none> 8080:30080/TCP 5s app=hostname-server
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/hostname-server-775f65669c-psgkf 1/1 Running 0 14m 192.168.235.140 worker1 <none> <none>
pod/hostname-server-775f65669c-tvh8w 1/1 Running 0 14m 192.168.189.81 worker2 <none> <none>
위에서 nodeport로 할당된 10.99.158.187:8080 으로 내부 IP 접근을 해보면 pod server 결과가 출력된다.
root@master:~/k8s_lab/service# curl -s 10.99.158.187:8080
<!DOCTYPE html>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="./css/login.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<div class="form-signin">
<blockquote>
<p>Hello, hostname-server-775f65669c-psgkf</p> </blockquote>
</div>
이번에는 node 밖에서 테스트를 해보자. 작업중인 윈도우 PC에서 커맨드 창을 열고 클러스터의 마스터 노드의 외부 IP (172.30.1.25)에 NodePort에서 맵핑한 외부 포트 30080으로 서버 호출을 해보면 정상적으로 결과가 나온다.
신기하게도 클러스터와 연결된 3개 노드(172.30.1.25 마스터, 172.30.1.10 Worker1, 172.30.1.36 Worker2) 모두 접근해도 결과가 나온다. 해당 노드에서 pod가 실행하고 있지 않아도 어떤 노드로 접근을 해도 서버 실행 결과를 볼 수 있다.
-- The End --
'Devops > Kubernetes' 카테고리의 다른 글
[Kubernetes] ingress 설정 (1) | 2023.12.26 |
---|---|
[Kubernetes] apt-get 시 public key is not available: NO_PUBKEY 에러 수정 (1) | 2023.12.21 |
[Kubernetes] Controller - Replicaset (0) | 2022.01.22 |
[Kubernetes] 네임스페이스(Namespace) 살펴보기 (0) | 2022.01.17 |
[Kubernetes] 쿠버네티스 Architecture와 기본 동작 (0) | 2022.01.16 |