ETC

[CKA] kubernetes Service

코린이s 2023. 9. 10. 11:41
728x90

동일한 기능을 구현하는 파드들을 하나의 진입점으로 접근 가능하도록 하는것이 서비스이다!

서비스는 4가지 타입이 있다.

타입 내용
ClusterIP(default) 클러스터 내부에서만 사용가능한 IP 할당 받아 파드 통신 하는 서비스 
NodePort ClusterIP 기능 + 각 노드에 특정 포트로 통신 가능한 서비스
만약 노드에 IP가 외부에서 접속 가능하다면 Port 를 통해 외부 통신이 가능하다.
LoadBalancer 클러스터 외부에서 사용 가능한 IP 할당 받아 파드 통신 하는 서비스
외부 사용 가능한 IP는 로드밸런서 IP로 클라우드에 로드 밸런서를 자동으로 만들어져야 하여 클라우드 사용시에만 사용 가능
ExternalName 클러스터 내부에서 외부 호출시 서비스 이름으로 통신 가능하도록 하는 서비스
내부 DNS에 외부 IP를 서비스명으로 설정하여 외부 통신 가능한 형태

각각 실습을 통해 알아보도록 하자!

Cluster IP 먼저 알아보자!

# deploy-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webui
  template:
    metadata:
      name: pod-nginx
      labels:
        app: webui
    spec:
      containers:
      - name: my-nginx
        image: nginx:1.14

해당 파드를 생성한다.

$ kubectl create -f deploy-nginx.yaml

이제 해당 파드를 관리하는 cluster ip 타입의 서비스를 만들어 보자!

# clusterip-nginx.yaml

apiVersion: v1
kind: Service
metadata:
  name: clusterip-service
spec:
  type: ClusterIP
  clusterIP: 10.100.100.100
  selector:
    app: webui
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

해당 yaml을 생성한다.

$ kubectl create -f clusterip-nginx.yaml 
service/clusterip-service created

서비스가 정상적으로 생성 되었는지 확인하면 서비스 IP 가 정의한대로 정상 생성 되었다.

$ kubectl get service
NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
clusterip-service   ClusterIP   10.100.100.100   <none>        80/TCP    91s
kubernetes          ClusterIP   10.96.0.1        <none>        443/TCP   40m

cluster ip 를 통해 서비스를 호출해보면 정상적으로 호출 된다.

$ curl 10.100.100.100
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

여기서 파드 밸런싱 되어 호출 되는지 확인을 위해 nginx ui 를 변경 해보도록 하자! 파드 3개 모두 접속하여 내용을 다르게 표기한다.

$ kubectl exec -it deploy-nginx-XX-XX -- bash
# cd /usr/share/nginx/html/
# ls
50x.html  index.html
# echo "#1" > index.html
# cat index.html 
   #1
# exit

이제 다시 cluster ip를 호출해보면 계속 다른 파드로 접속 되는것을 알 수 있다. 라운드 로빈 방식이 아닌 부하에 따라 균등하게 호출 하는 방식이기에 순서가 정확하지 않다.

[node1 ~]$ curl 10.100.100.100
#3
[node1 ~]$ curl 10.100.100.100
#2
[node1 ~]$ curl 10.100.100.100
#1
[node1 ~]$ curl 10.100.100.100
#1
[node1 ~]$ curl 10.100.100.100
#3
[node1 ~]$ curl 10.100.100.100
#1
[node1 ~]$ curl 10.100.100.100
#1
[node1 ~]$ curl 10.100.100.100
#2

만약 파드수가 늘어나면 어떻게 될까? 3개에서 5개로 늘려보자!

$kubectl scale deployment deploy-nginx --replicas=5
deployment.apps/deploy-nginx scaled

서비스 상세정보를 보면 endpoint 가 5개로 자동 늘어났다. 여기서 알 수 있는점은 파드를 늘려도 service에서는 엔드포인트를 알아서 감지하여 해당하는 서비스를 찾아 호출하여 따로 관리하지 않아도 된다는 것이다.

[node1 ~]$ kubectl describe service clusterip-service
Name:              clusterip-service
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=webui
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.100.100.100
IPs:               10.100.100.100
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.5.1.2:80,10.5.1.3:80,10.5.1.4:80 + 2 more...

다음 실습을 위해 다시 3개로 줄인다.

$ kubectl scale deployment deploy-nginx --replicas=3
deployment.apps/deploy-nginx scaled

이제 NodePort를 알아보자!

clusterip 형태에 각 노드에 Port 열리는기능이 추가 된 것이다.

각 노드는 노드 포트가 default 로 30000-32767 포트로 랜덤 할당 되어 열린다.

실습을 진행해보자!

# node-port.yaml

apiVersion: v1
kind: Service
metadata:
  name: nodeport-service
spec:
  type: NodePort
  clusterIP: 10.100.100.200
  selector:
    app: webui
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30200

이제 nodeport service 를 생성하자

$ kubectl create -f nodeport-nginx.yaml
service/nodeport-service created

서비스를 확인하면 정의한 IP, PORT 로 생성 되었다.

[node1 ~]$kubectl get svc
NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
clusterip-service   ClusterIP   10.100.100.100   <none>        80/TCP         20m
kubernetes          ClusterIP   10.96.0.1        <none>        443/TCP        59m
nodeport-service    NodePort    10.100.100.200   <none>        80:30200/TCP   51s

이제 노드 IP로 직접 호출 되는지 노드 포트로 호출하여 통신 되는지 확인한다.

[node1 ~]$ curl 192.168.0.22:30200
#1
[node1 ~]$ curl 192.168.0.22:30200
#2
[node1 ~]$ curl 192.168.0.22:30200
#1
[node1 ~]$ curl 192.168.0.22:30200
#2

그 다음 클러스터 IP 기능도 확인을 위해 clusterip 로 호출도 해본다.

[node1 ~]$ curl 10.100.100.200
#2
[node1 ~]$ curl 10.100.100.200
#3
[node1 ~]$ curl 10.100.100.200
#3
[node1 ~]$ curl 10.100.100.200
#3
[node1 ~]$ curl 10.100.100.200
#2
[node1 ~]$ curl 10.100.100.200
#2

다음 실습을 위해 모든 서비스를 삭제 한다.

$ kubectl delete svc --all

이제 LoadBalancer 타입에 대해 알아보자!

LoadBalancer 타입은 클라우드에서 운영 가능하며

External IP(외부에서 접속 가능한 IP, LB IP)를 할당하고 각 노드의 nodeport 외부 접근을 허용해주는것이다.

External IP를 할당 할때 LoadBalancer 를 클라우드에 구성 요청을 하나 현재 클라우드에 구성하지 않았으니 External IP 를 할당 받지는 못할것이다.

그러나 어떻게 동작하는지 보기 위해 만들어 보는 실습을 하도록 하자!

# loadbalancer-nginx.yaml

apiVersion: v1
kind: Service
metadata:
  name: loadbalancer-nginx
spec:
  type: LoadBalancer
  selector:
    app: webui
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

이제 서비스를 생성해본다!

$ kubectl create -f loadbalancer-nginx.yaml 
service/loadbalancer-nginx created

서비스를 확인하면 External ip 가 pending 상태이다. 이는 로드 밸런서가 생성 되지 않았기 때문이다.

만약 클라우드에서 생성 한다면 외부에서 접속가능한 IP 가 할당 되어 외부에서 클러스터에 IP 로 호출시 파드와 통신 가능하게 된다.

[node1 ~]$ kubectl get svc
NAME                 TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes           ClusterIP      10.96.0.1     <none>        443/TCP        8m21s
loadbalancer-nginx   LoadBalancer   10.109.9.24   <pending>     80:30280/TCP   14s

노드포트와 동일하게 각 노드의 IP에 포트로 호출이 가능하다.

[node1 ~]$ curl 192.168.0.22:30280
#1
[node1 ~]$ curl 192.168.0.22:30280
#2
[node1 ~]$ curl 192.168.0.22:30280
#3
[node1 ~]$ curl 192.168.0.22:30280
#2
[node1 ~]$

이제 ExternalName에 대해 알아보자!

클러스터 내부에서 외부로 나갈수있는 도메인을 설정하는 서비스로 전체 파드에 dns 설정하는것이라고 생각하면 된다.

실습을 하면서 알아보자!

# external-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: external-svc
spec:
  type: ExternalName
  externalName: google.com

해당 서비스를 생성한다.

$ kubectl create -f external-service.yaml 
service/external-svc created

서비스를 확인하면 external ip 가 생성 되었으며 서비스를 호출하면 external ip로 호출하게 된다.

$ kubectl get svc
NAME                 TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
external-svc         ExternalName   <none>        google.com    <none>         33s

이제 centos 파드를 생성하여 내부에서 서비스를 호출하면 google 로 호출한것을 알 수 있다.

$kubectl run my-centos -it --image=centos:7
If you don't see a command prompt, try pressing enter.
[root@my-centos /]# curl external-svc                          
<!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>Error 404 (Not Found)!!1</title>
  <style>
    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
  </style>
  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
  <p><b>404.</b> <ins>That’s an error.</ins>
  <p>The requested URL <code>/</code> was not found on this server.  <ins>That’s all we know.</ins>

끝!

728x90