쿠버네티스 교육/강의 내용 정리

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

실행 중인 파드의 포트 번호: 8080
모든 파드 삭제 후 재실행 중인 파드의 포트 번호: 8081

 

728x90