Architecture/k8s

Kubernetes 아주 조금만 알아보자 - Service

KOOCCI 2019. 6. 6. 23:54

※ 개인적으로 받았던 Kubernetes 교육을 정리한 내용입니다.

1편 > Kubernetes 아주 조금만 알아보자 - Kubernetes란? : https://koocci-dev.tistory.com/3

2편 > Kubernetes 아주 조금만 알아보자 - Kubernetes의 흐름 : https://koocci-dev.tistory.com/5

3편 > Kubernetes 아주 조금만 알아보자 - 마스터, 노드 : https://koocci-dev.tistory.com/6

4편 > Kubernetes 아주 조금만 알아보자 - Model, Declared State, Pod : https://koocci-dev.tistory.com/10

5편 > Kubernetes 아주 조금만 알아보자 - ReplicaSets,Deployments : https://koocci-dev.tistory.com/11

6편 > Kubernetes 아주 조금만 알아보자 - Service : 현재 Post


Service 란?

[참고: https://bcho.tistory.com/1262?category=731548#recentComments ]

드디어 Service의 차례다.

이후에 할 내용이 많지만, 우선 여기 이후에는 실습을 먼저 진행해보고 이론을 좀 더 다가가 볼려고 한다.

 

앞서, Service에 대한 언급은 자주했었다.

이를 알아보기 전에 전체 내용을 한번 정리해보자.

 

우리는 앞서, Kubernetes의 상태를 나타내는 엔티티Object라는 것을 배웠다.

앞서 언급했던 Pod, 이번에 언급할 Service, 추후 알아갈 디스크 영역의 Volume, 패키지명인 Namespace 4가지는 이 Object의 Base Object 들이다.

 

따라서, Service는 이전에 언급했던 Pod와 같이 Object의 Type으로 생각할 수 있다.

 

Service가 필요한 이유를 알아보자.

 

Docker에서 각 Container끼리의 Network 연결을 Container Network라고 하지만, Kubernetes에서는 Pod가 가장 기본 단위이므로, Pod Network라고 한다.

 

Pod Network에서 권장하는 것은 당연히 loosely Coupled 된 방식이다.

TCP/IP로 서로 통신한다는 것이고, IP AddressHost Name이 필요하다.

 

그러나, Pod가 생성될 때 Kubernetes가 할당하며, 고정되지 않는다.

지금 올라간 Pod가 어떤 IP를 들고 있는지, Host Name이 무엇인지는 API 서버에 물어봐야 비로소 알 수 있다.

 

이를 해결하기 위해 Service가 등장했다.

 

  • Stable DNS, IP Address를 Pod그룹에 제공한다.
  • TCP와 UDP를 지원한다(TCP가 Default)
  • Pod드 간의 Randomized load-balancing을 수행한다. (돌아가면서, IP 할당)
  • Pod의 생성과 종료를 추적하고, 자동으로 업데이트되며 안정적으로 Network의 EndPoint를 제공한다.

위 내용에서 마지막 내용은 Service가 IP 정보를 알고 있다는 것이다. 

마치, Floating IP와 비슷한 개념으로, Pod와 Static하게 연결되어 있는 것은 아니다.

연결되는 것은 앞서 자주 말했던 label selector를 통해 연결된다.

 

개념적인 그림을 한 번 보자 (트래픽에 대한 설명은 아니다)

위 4개의 Node가 Replica로 올라와 있다고 하자.

Service 설명

Nginx로 올라온 위 Web Server가 DB에 붙으려고 할 때, Service IP로 보내면 Pod 각각에 Load Balancing후 처리한다.

DNS로 보내면 Pod에 직접 연결 후 자동 Load Balancing 처리하게 된다.

 

서비스에는 여러가지 Type이 있다.

Service Type이라고 하는데, 어떻게 IP를 연결하냐 혹은, 연동 서비스마다 4가지로 나뉘어 진다.

  • Cluster IP
  • Load Balancer
  • Node IP
  • External Name

Cluster IP는 Default 값으로 서비스에 Kubernetes 내부에 연결될 내부IP를 할당한다.

즉, Kubernetes 내부 클러스터에서는 접근이 되지만, 외부에서는 불가능하다.

 

Load Balancer는 외부IP를 가진 로드밸런서를 할당한다. 따라서, Cluster 외부에서 접근이 가능하다.

 

NodePort는 Cluster IP로만 접근이 가능한것이 아니라, 모든 Node의 IP와 포트를 통해서도 접근이 가능하게 된다.

 

예시를 보자.

apiVersion: v1
kind: Service
metadata:
  name: hello-node-svc
spec:
  selector:
    app: hello-node
  type: NodePort
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: 8080
      nodePort: 30036

typeNodePort이고, ports를 보면, port: 80, targetPort: 8080, nodePort: 30036 임을 볼 수 있다.

 

NodePort

위 이미지를 보면, Service에 열려있는 포트 80으로 들어가면, TargetPort인 8080을 통해 Load Balancing이 되는 것을 볼 수 있지만, nodePort인 30036을 통해 바로 연결도 가능한 것을 알 수 있다.

 

ExternalName 외부 서비스를 쿠버네티스 내부에서 호출하고자 할때 사용한다.

각 Pod들은 Cluster IP를 가지고 있기 때문에, 연결하려면 NAT(Network Access Transfer) 설정 등이 필요하게 된다.

따라서, 외부 DataBase 등을 연결하고자 할때, 해당 설정을 이용한다.

kind: Service
apiVersion: v1
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

위처럼, externalName을 DNS로 설정해두면, 위 서비스로 들어오는 모든 요청을 externalName으로 포워딩해준다.

IP로 설정하기 위해서는 Cluster IP 설정과, EndPoint를 추가로 설정해준다.

apiVersion: v1
kind: Service
metadata:
  name: external-svc-nginx
spec:
  ports:
  - port: 80
  
  
  
apiVersion: v1
kind: Endpoints
metadata:
  name: external-svc-nginx
subsets:
  - addresses:
    - ip: 35.225.75.124
    ports:
    - port: 80

단, 이때 서비스명과 서비스 EndPoints의 이름이 동일해야 한다.

 

 

아직 이야기 할 것이 많이 있지만,

다음 포스팅에서는 Docker를 띄우고, 실습을 진행해 보도록 하자.