쿠버네티스 기본 오브젝트 Service (이전 완료)
쿠버네티스의 Pod들은 언제든지 삭제되고 생성될 수 있는 자원이다. 그렇기 때문에 클러스터 내에서 이러한 서비스에 접근할때 각 Pod들의 ip를 사용한다는건 여간 불편한 일이 아닐 수 없다.
예를들어 클러스터 내에서 로그인 서비스를 제공해주는 Pod와, 계정 정보가 담긴 데이터 베이스 Pod들
이런 문제를 해결하기 위해 Service라는 오브젝트가 있다.

Service의 목적은 서비스를 제공하는 여러개의 Pod들의 단일 진입점을 제공해주고 DNS를 통한 접근을 가능하게 해주며 요청을 여러개의 Pod로 분산시켜주는 로드밸런싱의 기능을 하게 된다.
서비스
파드 집합에서 실행중인 애플리케이션을 네트워크 서비스로 노출하는 추상화 방법 쿠버네티스를 사용하면 익숙하지 않은 서비스 디스커버리 메커니즘을 사용하기 위해 애플리케이션을 수정할
kubernetes.io
이번 포스팅에서는 두개의 쿠버네티스 서비스 오브젝트에 대해 다룬다.
- ClusterIP
- NodePort
ClusterIP
ClusterIP는 클러스터 내부에서만 접근 가능한 서비스다. ClusterIP는 서비스 이름을 통한 DNS 접속, IP를 통한 접속이 가능하다.

다음은 ClusterIP를 위한 yml 파일 작성 예시다.
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
위 예시는 app: nginx 라는 라벨을 가지고 있는 Pod들을 묶어 nginx-service라는 이름의 ClusterIP 서비스를 제공하기 위한 yml파일이다.
ports 선언을 보면 프로토콜은 TCP를 사용하며, 노출포트는 80번포트, 그리고 타겟포트(Pod의 포트)도 80번으로 설정하였다.
이렇게 선언하게 되면 다른 Pod들에서는 nginx-service:80를 통해 해당 서비스에 접근할 수 있게 된다.
아래는 실제 ClusterIP를 통해 Pod에 어떻게 접근이되는지를 알아보기 위한 실험이다. 이를 위해 3개의 pod와 하나의 service를 준비했다.


즉 다음 그림과 같은 형태이다.

하나의 테스트 pod를 만들어 실험을 진행했다.



위 사진들은 각 Pod의 IP로 통신을 한 케이스다. 각 IP대로 Pod로 통신이 들어간것을 알 수 있다.
그러면 ClusterIP로 통신을 하면 어떻게 될까?



같은 ClusterIP (10.101.212.178)로 통신을 할때마다 3개의 노드로 부하가 분산되어 로드밸런싱이 되는것을 확인할 수 있다.
추가적으로 서비스 이름을 통한 DNS도 제공된다는것을 알 수 있다.

이는 pod내 컨테이너들의 /etc/resolv.conf 를 확인해보면 다음과 같은 네임서버를 확인해볼 수 있다.

또한 아래 명령을 통해 kube-system 네임 스페이스에서 동작중인 kube-dns서비스를 확인할 수 있다.
kubectl get svc -A

NodePort
NodePort는 클러스터 외부에서 Pod들의 단일 진입점을 얻고자 할때 사용하는 서비스다. 클러스터 내에 존재하는 Pod들은 기본적으로 클러스터 내에서만 사용할 수 있는 IP만 부여받았기 때문에 외부에서는 접근이 불가능하다.
이를 해결하기 위해 NodePort로 Pod들을 묶어 단일 진입점을 만들어 외부에서 클러스터 내부의 Pod에 접근한다.
사용하기 위한 yml파일은 다음과 같다.
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30007 #선택
NodePort를 사용하기 위해선 type: NodePort로 명시를 해주어야 한다 (default ClusterIP).
또한 spec의 ports 부분이 약간 다르다.
ports.port : 서비스가 노출할 포트
ports.targetPort : Pod로 접속할 포트
ports.nodePort : 서비스가 외부로 노출할 포트
외부의 서비스가 해당 서비스로 접근하기 위해 someIP:30007로 접근을 하게되면,
해당 서비스의 80 포트로 연결이 전달되고
전달된 연결은 내부 Pod의 80 포트로 전달되게 된다.

NodePort는 내부에서도 접근이 가능하다.
내부에서는 NodePort서비스의 포트를 통해 접근이 가능하며 이 포트는 spec.ports.port로 정의하게 된다.
즉 위의 예시에서는 80번 포트를 통해 클러스터 내부 자원들도 해당 서비스에 접근할 수 있게 된다.

이러한 서비스는 iptables의 NAT테이블에서 자세히 알 수 있다.
다음은 nginx-nodeport 서비스와, nginx-service의 endpoint로써 각 Pod들이 설정되어 있는 테이블이다.

각 서비스는 80 포트로 들어오게 되어있다.

각 서비스의 endpoint로 가기 위한 확률로써, 3개의 endpoint중 첫번째 pod로 갈 확률은 0.33, 첫번째로 가지 않는다면 두번째 Pod로 갈 확률은 0.5, 두번째도 가지 않는다면 마지막 세번째로 가게 된다.
즉 각 노드로 가게될 확률은 0.333333씩 인것이다. (두번째 노드, 세번째 노드는 0.66 * 0.5)
