쿠버네티스 교육/강의 내용 정리
220624_1_k8s_클러스터 내부 서비스-Cluster IP
kimhope
2022. 6. 24. 18:31
728x90
서비스
Service
서비스의 이해
- 파드는 클러스터 외부의 요청이나 클러스터 내부의 다른 파드의 요청에 응답해야 하고 파드가 다른 파드에서 제공하는 애플리케이션에 접근하기 위해서는 파드를 찾을 수 있어야 함
- 쿠버네티스가 아닌 기존의 시스템은 애플리케이션이 동작하는 시스템의 호스트 이름이나 정적 IP를 할당하여 해당 애플리케이션을 찾을 수 있지만, 쿠버네티스 환경에서는 그렇게 할 수 없음
쿠버네티스 환경에서 정적 IP 또는 시스템 호스트의 이름을 사용할 수 없는 이유
- 파드는 일회성으로 동작하기 위해 설계되었으며, 언제든 제거될 수 있음
- 특정 노드에 파드가 스케줄링되고 IP 주소가 동적으로 할당되며 클라이언트는 파드의 IP 주소를 미리 예측할 수 없음
- 분산 아키텍처 및 스케일 아웃의 경우 여러 파드가 같은 애플리케이션을 제공하기 때문에 각 파드마다 IP가 존재하고, 스케일링이 될 때마다 클라이언트가 해당 IP를 알 수 없음
서비스란
- 쿠버네티스 시스템에서 같은 애플리케이션을 실행하고 있는 컨트롤러의 파드 그룹에 단일 네트워크 진입 점을 제공하는 리소스
- 서비스에 부여된 IP는 해당 서비스가 종료될 때까지 변경되지 않음
- 클라이언트는 서비스가 제공하는 IP 및 Port를 통해 파드에 접근하게 되고 kube-dns( coredns )가 적용되어 있다면 서비스의 이름에 기반한 고유한 FQDN이 부여됨
- 서비스는 레이블 셀렉터를 이용하여 서비스의 대상( 백엔드 ) 파드를 설정하는 데, 서비스에 선택된 파드의 목록은 엔드포인트( Endpoint ) 리소스로 관리
- 서비스 리소스는 여러 파드가 연결되어 있을 때 라운드 로빈( Round Robin ) 방식의 부하 분산 제공
서비스의 종류
ClusterIP | 클러스터 내부용 서비스 |
NodePort | - NodePort + ClusterIP - 모든 노드에 외부 접근용 포트 할당 - 노드의 포트를 사용하여 외부에서 접근 가능 - 노드의 포트로 접근하면 서비스에 의해 파드로 리다이렉션 함 - 파드를 실행하고 있지 않은 노드에도 포트가 할당되어 접근 가능 |
LoadBalancer | - LoadBalancer + NodePort + ClusterIP - NodePort의 확장 - 클러스터 외부의 로드밸런서를 사용하여 외부에서 접근 가능 - 외부 로드밸런서로 접근하면 서비스를 통해 파드로 리다이렉션 함 - 클라우드 공급업체(AWS, GCP 등)나 MetalLB에서 지원 |
ExternalName | - 외부에서 접근하기 위한 종류가 아님 - 외부의 특정 FQDN에 대한 CNAME 매핑을 제공함 - 파드가 CNAME을 이용해 특정 FQDN과 통신하기 위함 |
Cluster IP
- 서비스 및 엔드포인트는 쿠버네티스 아키텍처에서 살펴본 컨트롤 플레인의 API 서버( kube-apiserver )로 접근할 수 있는 서비스로 클러스터 내부의 파드가 API 서버에 접근하기 위해 해당 서비스를 통해 접근
- 서비스 목록 확인
- TYPE-Cluster IP( 서비스 타입 ): 쿠버네티스 클러스터 내에서만 접근할 수 있음
- CLUSTER-IP 10.233.6.53: 서비스에 할당된 클러스터 IP
- EXTERNAL-IP: 클러스터 외부에서 접근할 때 사용하며 로드밸런서 타입의 서비스를 선언할 경우 할당됨
vagrant@kube-master1:~/test$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.233.0.1 <none> 443/TCP 2d22h
- 서비스 리소스와 동일한 이름의 엔드포인트 리소스도 확인
vagrant@kube-master1:~/test$ kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 192.168.56.11:6443 2d22h
Cluster IP
서비스 생성
testapp-svc.yml
.spec.ports.port | 서비스 리소스의 포트 - 클라이언트가 접근할 서비스의 포트 |
.spec.ports.targetPort | 파드(대상) 리소스의 포트 - 클라이언트가 포트로 접근하면 파드의 서비스 포트로 포워딩 |
.spec.selector | 파드 레이블 셀렉터, 엔드포인트 리소스 생성 - 서비스에 연결할 파드를 레이블 셀렉터를 이용하여 매칭하게 되며 레이블 셀렉터가 있는 경우 서비스 리소스 이름과 똑같은 엔드포인트 리소스가 자동으로 생성됨 |
- yml 파일 생성
vagrant@kube-master1:~/test$ cat testapp-svc.yml
apiVersion: v1
kind: Service
metadata:
name: testapp-svc
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: testapp-rs
- 서비스 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-svc.yml
service/testapp-svc created
- 파드 생성 및 엔드포인트 연결
vagrant@kube-master1:~/test$ kubectl create -f testapp-rs.yml
replicaset.apps/testapp-rs created
vagrant@kube-master1:~/test$ cat testapp-rs.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: testapp-rs
spec:
replicas: 3
selector:
matchLabels:
app: testapp-rs
template:
metadata:
labels:
app: testapp-rs
spec:
containers:
- name: testapp
image: c1t1d0s7/myweb
ports:
- containerPort: 8080
imagePullPolicy: Never
- 엔드포인트 목록과 파드의 IP 동일
- 접속 확인
- 접속 확인을 위해 nettool이라는 파드를 생성함
vagrant@kube-master1:~/test$ kubectl run nettool -it --image=ghcr.io/c1t1d0s7/network-multitool --rm bash
If you don't see a command prompt, try pressing enter.
bash-5.1#
- 부하 분산을 통해 접속할 때마다 다른 파드로 연결되는 것을 확인할 수 있음
- curl http://testapp-svc 서비스의 CLUSTER-IP
세션 어피니티 구성
testapp-svc-aff.yml
- Session Affinity
- 클라이언트 요청을 매번 같은 파드로 연결하고 싶은 경우 사용
- 세션 유지가 필요한 경우 사용
필드 | 속성 값 |
.spec.sessionAffinity | - None( 기본 값 ): 세션 어피니티가 없음 - ClientIP: 클라이언트의 IP를 확인하고 접속 시 마다 동일한 파드로 연결함 |
- yml 파일 생성
vagrant@kube-master1:~/test$ cat testapp-svc-aff.yml
apiVersion: v1
kind: Service
metadata:
name: testapp-svc-aff
spec:
sessionAffinity: ClientIP
ports:
- port: 80
targetPort: 8080
selector:
app: testapp-rs
- 서비스 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-svc-aff.yml
service/testapp-svc-aff created
- 접속 확인
- 여러 번 접속해도 동일한 파드로 연결되는 것을 확인할 수 있음
vagrant@kube-master1:~/test$ kubectl run nettool -it --image=ghcr.io/c1t1d0s7/network-multitool --rm bash
If you don't see a command prompt, try pressing enter.
bash-5.1#
포트 이름 참조
testapp-rs-named-port.yml / testapp-svc-named-port.yml
- 다중 포트 설정 시 반드시 포트 이름을 부여해야 함
- 파드나 파드를 생성하는 컨트롤러의 파드 템플릿의 컨테이너 포트에도 이름을 부여할 수 있음
- 파드( 컨테이너 )의 포트 이름을 이용하여 서비스 생성 시 파드의 대상 포트( targetPort )에 이름을 이용하여 연결 가능
- 이름으로 참조하기 때문에 파드의 포트 이름만 변경되지 않는다면, 실제 파드의 포트 번호가 변경되더라도, 스펙의 변경 없이 연결을 유지할 수 있음
- 레플리카셋 생성 파일
- .spec.ports.name: 포트 이름
- 컨테이너 8080 포트에 testapp-http라는 이름 부여
- 서비스 생성 시 이름 참조
vagrant@kube-master1:~/test$ cat testapp-rs-named-port.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: testapp-rs-named-port
spec:
replicas: 3
selector:
matchLabels:
app: testapp-rs
template:
metadata:
labels:
app: testapp-rs
spec:
containers:
- name: testapp
image: c1t1d0s7/myweb
ports:
- name: testapp-http
containerPort: 8080
imagePullPolicy: Never
- 서비스 생성 파일
- .spec.ports.targetPort: 대상 파드의 포트 이름 지정
- testapp-http 포트 이름을 참조하는 서비스 구성
vagrant@kube-master1:~/test$ cat testapp-svc-named-port.yml
apiVersion: v1
kind: Service
metadata:
name: testapp-svc-named-port
spec:
ports:
- name: testapp-http
port: 80
targetPort: testapp-http
selector:
app: testapp-rs
- 레플리카셋 컨트롤러와 서비스 생성
vagrant@kube-master1:~/test$ kubectl create -f testapp-rs-named-port.yml
replicaset.apps/testapp-rs-named-port created
vagrant@kube-master1:~/test$ kubectl create -f testapp-svc-named-port.yml
service/testapp-svc-named-port created
- 파드의 포트 변호 변경: 8080 > 8081
vagrant@kube-master1:~/test$ kubectl edit replicasets.apps testapp-rs-named-port
- 파드 삭제 ( 레플리카셋 삭제 X )
- 파드의 포트 번호가 8081로 변경되어 파드가 생성됨
- endpoint 목록에 세 개의 파드 IP가 있으므로 연결이 유지되어 있는 것을 확인할 수 있음
vagrant@kube-master1:~/test$ kubectl delete pods --all
728x90