본문 바로가기

Kubernetes

[Kubernetes] Service 4가지 종류 실습

반응형

ClusterIP - "단일 진입점 생성(내부)"

 - selector의 label가 동일한 파드들의 그룹으로 묶어 단일 진입점(Virtual IP)을 생성

 - 클러스터 내부에서만 사용 가능

 - type 생략 시 default 값으로 10.96.0.0/12 범위에 할당됨

 - ClusterIP는 고정 시켜도 되고, 고정 시키지 않아도 되지만 고정시키지 않는 이유는 충돌을 예방하기 위함

 

deploy-nginx.yaml

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

 

ClusterIP 테스트 전 먼저 pod를 생성한다.

# kubectl create -f deploy-nginx.yaml 
deployment.apps/webui created

# kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP          NODE                NOMINATED NODE   READINESS GATES
webui-5cfbcf5f65-plpx6   1/1     Running   0          7s    10.36.0.2   node1.example.com   <none>           <none>
webui-5cfbcf5f65-q9tc8   1/1     Running   0          7s    10.44.0.1   node2.example.com   <none>           <none>
webui-5cfbcf5f65-w94c5   1/1     Running   0          7s    10.36.0.1   node1.example.com   <none>           <none>

 

clusterip-nginx.yaml

 - 10.100.100.100 ClusterIP를 생성하여 webui의 단일진입점으로 사용

 - clusterip:protocal → pod:port 로 통신

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

 

ClusterIP 생성

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

# kubectl get service
NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
clusterip-service   ClusterIP   10.100.100.100   <none>        80/TCP    6s
kubernetes          ClusterIP   10.96.0.1        <none>        443/TCP   20d
mydb                ClusterIP   10.104.64.225    <none>        80/TCP    14d
myservice           ClusterIP   10.97.82.81      <none>        80/TCP    14d

 

ClusterIP를 describe로 확인하면 Endpoints 에 ClusterIP에 연결되는 pod 확인 가능

# 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.36.0.1:80,10.36.0.2:80,10.44.0.1:80
Session Affinity:  None
Events:            <none>

 

curl 명령어로 pod 연결 확인

# 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>

 

ClusterIP를 통해 pod 접근시 라운드 로빈으로 접근하는지 체크하기 위해서 pod에 직접 접근해서 index.html 수정  

# kubectl exec webui-5cfbcf5f65-plpx6 -it -- /bin/bash
# cd /usr/share/nginx/html/
# echo "webui #1" > index.html

# kubectl exec webui-5cfbcf5f65-q9tc8 -it -- /bin/bash
# cd /usr/share/nginx/html/
# echo "webui #2" > index.html

# kubectl exec webui-5cfbcf5f65-w94c5 -it -- /bin/bash
# cd /usr/share/nginx/html/
# echo "webui #3" > index.html

 

curl 명령어를 이용하여 ClusterIP 호출 테스트하면 라운드로빈으로 1개씩 순차적으로 호출하지는 않고 균등하게 랜덤으로 호출

# curl 10.100.100.100
webui #2
# curl 10.100.100.100
webui #1
# curl 10.100.100.100
webui #2
# curl 10.100.100.100
webui #1
# curl 10.100.100.100
webui #3
# curl 10.100.100.100
webui #2

 

pod를 3개에서 5개 늘릴 경우 ClusterIP의 Endpoints에 알아서 조절이됨

# kubectl scale deployment webui --replicas=5
deployment.apps/webui scaled

# kubectl describe svc 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.36.0.1:80,10.36.0.2:80,10.36.0.3:80 + 2 more...
Session Affinity:  None
Events:            <none>

Nodeport - "CluserIP + 외부접속"

 - 모든 노드를 대상으로 외부 접속 가능한 포트를 예약

 - Default NodePort 범위 : 30000-32767

 - ClusterIP를 생성 후 NodePort를 예약

 

nodeport-nginx.yaml

 - ClusterIP, nodeport는 입력하지 않으면 랜덤으로 들어감

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-nginx.yaml 실행 후 PORT 부분 확인 80:32000

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

# kubectl get svc
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes         ClusterIP   10.96.0.1        <none>        443/TCP        39s
nodeport-service   NodePort    10.100.100.200   <none>        80:30200/TCP   4s

 

노드 서버에 접속해서 30200 port가 오픈되어 있는지 확인

netstat 명렁어를 통해 확인시 아무것도 나오지 않는다. 1.25 버전에서는 이전 버전과 다르게 매커니즘이 달라졌다고 한다.

(kube-proxy → dnat 포워딩)

# netstat -napt | grep 30200

 

아래 명령어로 다시 확인시 port가 오픈되어 있는것을 확인 가능

node1:~# iptables -t nat -L KUBE-NODEPORTS | column -t
Chain                      KUBE-NODEPORTS  (1   references)
target                     prot            opt  source       destination
KUBE-EXT-QATUYZLPU4I4HE4S  tcp             --   anywhere     anywhere     /*  default/nodeport-service  */  tcp  dpt:30200

node2:~# iptables -t nat -L KUBE-NODEPORTS | column -t
Chain                      KUBE-NODEPORTS  (1   references)
target                     prot            opt  source       destination
KUBE-EXT-QATUYZLPU4I4HE4S  tcp             --   anywhere     anywhere     /*  default/nodeport-service  */  tcp  dpt:30200

 

노드 ip:port를 이용하여 접근

# kubectl get nodes -o wide
NAME                 STATUS   ROLES           AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
master.example.com   Ready    control-plane   20d   v1.25.4   10.100.0.104   <none>        Ubuntu 20.04.3 LTS   5.15.0-56-generic   containerd://1.4.9
node1.example.com    Ready    <none>          20d   v1.25.4   10.100.0.101   <none>        Ubuntu 20.04.3 LTS   5.15.0-56-generic   containerd://1.4.9
node2.example.com    Ready    <none>          20d   v1.25.4   10.100.0.102   <none>        Ubuntu 20.04.3 LTS   5.15.0-56-generic   containerd://1.4.9

# curl 10.100.0.101:30200
webui #2
# curl 10.100.0.101:30200
webui #2
# curl 10.100.0.101:30200
webui #3

LoadBalancer - "NodePort + LoadBalancer 지원"

 - Public 클라우드(AWS, Azure, GCP 등)에서 운영 가능

 - LoadBalancer를 자동으로 구성 요청

 - NodePort를 예약 후 해당 nodeport로 외부 접근을 허용

 

loadbalancer-nginx.yaml

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

 

Public 클라우드였다면 외부에서 접근할 수 있는 IP가 EXTERNAL-IP에 구성

# kubectl get svc
NAME                   TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes             ClusterIP      10.96.0.1        <none>        443/TCP        27s
loadbalancer-service   LoadBalancer   10.111.228.226   <pending>     80:30728/TCP   7s

ExternalName

 - 클러스터 내부에서 External(외부)의 도메인을 설정

 - DNS를 지원

 - /etc/hosts와 같은 역할

 

external-exam.yaml

apiVersion: v1
kind: Service
metadata:
  name: externalname-svc
spec:
  type: ExternalName
  externalName: google.com
root@master:~/7# cat external-name.yaml 
apiVersion: v1
kind: Service
metadata:
  name: externalname-svc

 

external-name.yaml 실행

- externalname-svc 으로 호출하면  google.com을 호출

# kubectl create -f external-name.yaml 
service/externalname-svc created

# kubectl get svc
NAME               TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
externalname-svc   ExternalName   <none>       google.com    <none>    47s

 

pod 생성한 후에 생성한 pod에 접근한 다음에 curl externalname-svc.default.svc.cluster.local 호출시 구글 페이지 호출

- default.svc.cluster.local : 쿠버네티스가 내부적으로 사용하는 도메인 이름

# kubectl run testpod -it --image=centos:7 
If you don't see a command prompt, try pressing enter.

[root@testpod /]# curl externalname-svc.default.svc.cluster.local
<!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>

 

 

 

[참고]

- https://www.youtube.com/watch?v=WaJyY5KvZj8&list=PLApuRlvrZKohaBHvXAOhUD-RxD0uQ3z0c&index=26 

반응형