베어메탈에서도 네트워크가 가장 어려웠는데 .. k8s 도 참으로 번잡하다

우선 관련 유튭을 보면서 이해한 내용을 적는다 

 


service는 무엇인가?

pod ip는 고정이 아니다 

- pod은 고유의 ip를 갖는다 / 단,임시적이다 (고정ip아님) / pod 재기동하면 새로운 ip 를 갖는다 

- 즉 pod ip로 서비스 생성하는건 무리다

service로 해결이 가능하다 

- stable ip 를 설정하여 , pod가 재기동 되어도 같은 ip로 pod 에 접속할 수 있게 한다 

service는 load balancing이 된다 

 - client는 service ip로 붙고 service에서 load balancing 하여 개별 pod에 업무를 준다 

 

k8s cluster 내부에서도 service는 사용가능하다

- loose coupling 이라고 k8s 내에서 pod들이 service를 사용하여 연결되고 통신한다  

 

 

 


Cluster IP (svc) 란?

- service를 생성하면 default로 만들어지는 유형이다 

- pod 하나에 port 등록이 아니라 하나의 pod내의 container 단위로 port를 열 수 있다  

spec :
  containers:
   - name : server 
     image : repo/server
     ports:
     - containerPort : 3000
   - name : logger 
     image : repo/logger
     ports:
     - containerPort : 5000

  

- cluster IP를 할당할 수도 있다 

 - 실제 물리 node에 IP를 할당하여 사용한다. 10.2.2.5로 할당한다면 10.2.2.x대역을 갖는 Node2번에 할당하게 되는것이다 

 

[root@tech7 statefulset]# k get pod -o wide
NAME                                READY   STATUS    RESTARTS   AGE    IP              NODE       NOMINATED NODE   READINESS GATES
nginx-deployment-86dcfdf4c6-b2q4v   1/1     Running   0          179m   172.16.30.127   worker02   <none>           <none>
nginx-deployment-86dcfdf4c6-gpvlh   1/1     Running   0          179m   172.16.5.11     worker01   <none>           <none>



[root@tech7 statefulset]# k get pod -o wide -n goldilocks
NAME           READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
goldilocks-0   1/1     Running   0          24h   172.16.5.4   worker01   <none>           <none>
goldilocks-1   1/1     Running   0          24h   172.16.5.7   worker01   <none>           <none>

 

worker01 은 172.16.5.x 대역대를 갖는 걸 확인할 수 있다 

 

- replica 수를 늘려서 같은 pod를 하나 더 만든다면, 새로 만들어진 pod도 같은 port 가 열리고 , 다른 ip 를 갖게된다 

 

AP는 어떻게 cluster ip로 접근을 하는 걸까?

AP가 ingress를 사용하여 각 pod에 접근한다는 가정

- ingress는 Service(Cluster IP) 를 통해서 pod에 접근을 한다

- ingress yaml에서 service name 과 service port(3200)를 설정한다 

-  service yaml에선 service에서 열릴포트와(3200)  mapping할 target port (3000) 을 설정한다 

 

service는 프로세스인가?

 프로세스가 아니다 . ip 주소를 갖고 있는 하나의 계층인거다 

 

service는 어떻게 어떤 pod 에 접근할 건지 결정하는 건가? (selector)

deployment (pod)에는 label을 설정해준다  

service에는 selector가 쓸 pod또는 deployment의 label을 쓴다 

그럼 selector는 random 하게 pod 에 접근한다 

kind : Deployment
metadata : 
 name : test-pod
spec :
 replicas : 2
 ...
 template: 
   metadata : 
    labels:
      app : test-pod

 

kind :  Service 
metadata :
 name : test-service
 spec :
  selector : 
    app : test-pod

 

 

service가 등록된 pod정보를 ( endpoint ) 를 확인하는 법

kubectl get endpoints 명령으로 service에 등록된 pod의 정보를 알 수 있다 

아래 는 replica:2로  pod이 2개가 생성되었고 service에 다른 ip 같은 port 로 pod이 매핑 된 걸 확인할 수 있다  

[root@tech7 statefulset]# k get pod
NAME      READY   STATUS    RESTARTS   AGE
memdb-0   1/1     Running   0          24h
memdb-1   1/1     Running   0          24h


[root@tech7 statefulset]# k get endpoints 
NAME        ENDPOINTS                           AGE
svc-memdb   172.16.5.4:22581,172.16.5.7:22581   15d

 

 

구성 예시 

 

 

AP는 브라우저를 통해 요청을 하고 -> ingress 로 들어온 요청은 Service 를 통해 Server pod에게 랜덤하게 일을 준다 

일을 받은 Server pod은 DB처리를 위해 DB 서버에 접근을 해야하는데 , 이를 위해 DB pod을 위한 DB service를 생성한다    

 

- Server pod에서 DB pod으로 연결하기 위해 DB service에서 port를 열어줘야한다 

kind : Service
metadata : 
 name : svc-test-db
..
spec : 
  selector : 
    app : test-db   <-- DB pod의 label 명을 적음
   ports : 
    - name : test-db
      protocol : TCP
      port : 27017       <-- Server pod에서 연결할 떄 쓸 DB service 포트 번호
      targetpot : 27017  <-- DB pod에서 연 포트번호
    - name : db-monitor  <-- 만약 DB 모니터링 용 포트를 하나 더 열어야 한다면 
      protocol : TCP
      port : 9216
      targetport : 9216

 

 

DB서버에서 모니터링 용으로 프로메테우스가 접근해야한다는 가정

 

 

 

 


Headless Service는 무엇인가?

언제 사용하는가 

- service 를 통해서 pod과 랜덤하게 연결되는것이 아닌

- 특정 pod에만 접근하고 싶을 경우 

 

사례

- mysql cluster 로 2대를 쓴다고 한다

- mysql-0 (pod) 는 Master여서 DML과 SELECT 가 모두 되는데 

- mysql-1 (pod) 는 worker로 SELECT만 될 경우 

- Service 를 사용해서 랜덤으로 pod 에 접근하면 안되다 

 

 

 연결하고자 하는 Pod 의 IP를 아는 법 

1. k8s API를 통해서 각 pod들의 ip 조회

  1) . k8s API에 의존?하는  코드를 짜야하며,   2) . 연결할때마다 pod 정보와 각 pod의 ip를 가져와야한다 

 

2. DNS Lookup 으로 cluster ip를 받아온다 

kind : Service
metadata : 
 name : db-svc-headless
spec : 
 clusterIP : None <--------------여기서 None 으로 등록
 selector : 
   app : test-db
 ports : 
   - protocol : TCP 
     port : 27017
     targetPort : 27017

 

service 등록 시 Cluster IP 부분에 None 이라고 설정한다 

그럼 DNS 서버가 Service IP가 아닌  Pod IP를 반환한다 

 

 

[root@tech7 svc]# k get service --all-namespaces
NAMESPACE              NAME                        TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                  AGE
default                kubernetes                  ClusterIP   10.96.0.1      <none>        443/TCP                  20d
test-db                svc-memdb                   ClusterIP   None           <none>        22581/TCP                15d

 

headless 로 등록하게 되면 위처럼 Cluster IP에 None 이라고 뜬다 

 

 

 

 

 


NodePort는 무엇인가?

Service를 default 인 cluster ip 로 설정하면 k8s cluster 내에서만 통신이 가능하다   

k8s cluster 가 아닌 외부에서 통신을 하려고 하면 , Node의 특정 port 를 열어두면 된다 

이런식으로 Node에 특정 port를열어두는 거다 

Node Port 로 열 수 있는 포트 번호 범위는 : 30000 부터 32767 까지이다 

 

접근할때 Node 의 ip주소와 node port 번호를 알면 service에 접근할 수 있게 된다 

[root@tech7 nodeport]# k get service --all-namespaces
NAMESPACE              NAME                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE
default                kubernetes                  ClusterIP   10.96.0.1       <none>        443/TCP                  20d
test-db                test-db-nodeport            NodePort    10.103.95.124   <none>        32000:30000/TCP          4s

Node는 30000 로 열려있고  그건 Service port가 3200과 연결된다 

 

 

nodeport는 특정 노드의 포트를 여는 게 아닌, 모든 노드의 포트를 여는것이다 

 

 

문제가 있다 

client가 direct로 Node 에 붙기 때문에 '보안' 관점에서 보면 위험하다 

 

 

 


LoadBalancer 란?

nodeport 의 확장버전으로 nodeport의 보안 문제를 해결한다 

cloud  Load Balancer 기능을 사용한다 (Google cloud , AWS ,  AZURE , Linode , Openstack 등에서 제공하는 loadbalancer )

 

kind : Service
metadata : 
 name : test-loadbalancer
spec : 
 type : LoadBalancer
 selector : 
  app : test-db
 ports : 
  - protocol : TCP
    port : 3200
    targetPort : 3000
    nodePort : 30000

 

이러면 외부에서 30000 번 (nodeport) 로 연결은 불가하다 

오직 LoadBalancer 를 사용해야 nodeport로 접근이 가능하다 

 

 

요약

LoadBalancer Service is an extension of NodePort Service

NodePort Service is an extension of CluterIP Service

 

 


참고한 블로그 유튭

Kubernetes Services explained | ClusterIP vs NodePort vs LoadBalancer vs Headless Service (youtube.com)