Today I Learned

[쿠버네티스 인 액션] 5. 서비스: 클라이언트가 파드를 검색하고 통신을 가능하게 함 (2) 본문

쿠버네티스

[쿠버네티스 인 액션] 5. 서비스: 클라이언트가 파드를 검색하고 통신을 가능하게 함 (2)

하이라이터 2022. 9. 26. 16:38
728x90

5.2 클러스터 외부에 있는 서비스 연결

  • 서비스가 외부 IP와 포트로 연결을 전달하는 경우, 서비스 로드밸런싱과 서비스 검색 모두 활용할 수 있다.

5.2.1 서비스 엔드 포인트 소개

  • 서비스는 엔드포인트 리소스를 통해 파드에 연결된다.
  • 다음 명령어를 통해 엔드포인트를 확인할 수 있다.
$kubectl describe svc kubia

  • 엔드포인트 리소스는 서비스로 노출되는 파드의 IP 주소와 포트 목록이며, 다른 쿠버네티스 리소스처럼 kubectl get을 사용해 정보를 표시할 수 있다.

  • 파드 셀렉터는 IP와 포트 목록을 작성하는데 사용되며 엔드포인트 리소스에 저장된다.
  • 클라이언트가 서비스에 연결하면 서비스 프록시는 이들 중 하나의 IP와 포트 쌍을 선택하고 들어온 연결을 대상 파드의 수신 대기 서버로 전달한다.

5.2.2 서비스 엔드 포인트 수동 구성

  • 서비스와 엔드포인트를 분리하면 엔드포인트를 수동으루 구성하고 업데이트할 수 있다.
  • 파드 셀렉터가 없으면 서비스가 포함된 파드가 무엇인지 알 수 없기 때문에 엔드포인트 리소스를 만들 수 없다.

셀렉터 없이 서비스 생성

apiVersion: v1
kind: Service
metadata:
  name: external-service
spec:
  ports:
  - port: 80

 

셀렉터가 없는 서비스에 관한 엔드포인트 리소스 생성

  • 셀렉터가 없는 서비스를 생성했기 때문에 엔드포인트 리소스가 자동으로 생성되지 않았으므로 엔드포인트 서비스를 생성해야 한다.
apiVersion: v1
kind: Endpoints
metadata:
  name: external-service
subsets:
  - addresses:
    - ip: 11.11.11.11
    - ip: 22.22.22.22
    ports:
    - port: 80
  • 엔드포인트 오브젝트는 서비스와 이름이 같아야 하고 서비스를 제공하는 대상 IP 주소와 포트 목록을 가져야 한다.
  • 서비스와 엔드포인트 리소스가 모두 서버에 게시되면 파드 셀렉터가 있는 일반 서비스처럼 사용할 수 있으며, 서비스가 만들어진 후 만들어진 컨테이너에는 서비스의 환경변수가 포함된다.


5.2.3 외부 서비스를 위한 별칭 생성

  • FQDN(정규화된 도메인 이름)을 사용하면 수동 엔드포인트를 구성할 때 보다 간단하게  외부 서비스를 참조할 수 있다.

ExternalName 서비스 생성

  • 외부 서비스의 별칭으로 사용되는 서비스를 만들려면 type 필드를 ExternalName으로 설정해 서비스 리소스를 만든다.
apiVersion: v1
kind: Service
metadata:
  name: external-service
spec:
  type: ExternalName
  externalName: api.somecompany.com
  ports:
  - port: 80
  • 서비스의 FQDN 대신 external-service.default.svc.cluster.local 도메인 이름으로 외부 서비스에 연결할 수 있다.
  • 이렇게 하면 서비스를 사용하는 파드에서 실제 서비스 이름과 위치가 숨겨져 externalName 속성을 변경하거나 서비스 스펙을 수정해서 다른 서비스를 가리킬 수 있다.
  • ExternalName 서비스는 DNS 레벨에서만 구현되므로 서비스에 연결하는 클라이언트는 서비스 프록시를 완전히 무시하고 외부 서비스에 직접 연결된다. 그래서 ExternalName 유형의 서비스는 ClusterIP를 얻지 못한다.


5.3 외부 클라이언트에 서비스 노출

  • 프론트 웹 서버와 같은 특정 서비스를 외부에 노출해 외부 클라이언트가 엑세스하도록 하고싶을 수 있다.

  • 외부에서 서비스를 엑세스 할 수 있는 몇 가지 방법이 있다.
    • 노드포트로 서비스 유형 설정 :
      노드포트(NodePort) 서비스의 경우 각 클러스터 노드는 노드 자체에서 포트를 열고 해당 포트로 수신된 트래픽을 서비스로 전달한다.이 서비스는 내부 클러스터 IP와 포트로 엑세스할 수 있을 뿐만 아니라 모든 노드의 전용 포트로도 엑세스할 수 있다.
    • 서비스 유형을 노드포트 유형의 확장인 로드밸런서로 설정 :
      쿠버네티스가 실행중인 클라우드 인프라에서 프로비저닝된 전용 로드밸런서로 서비스에 엑세스할 수 있다. 로드밸런서는 트래픽을 모든 노드의 노드포트로 전달한다. 클라이언트는 로드밸런서의 IP로 서비스에 엑세스한다.
    • 단일 IP 주소로 여러 서비스를 노출하는 인그레스 리소스 만들기 :
      HTTP 레벨에서 작동하므로 4계층 서비스(TCP/UDP 등)보다 더 많은 기능을 제공할 수 있다.

 5.3.1 노드포트 서비스 사용

  • 노드포트 서비스를 만들면 쿠버네티스는 모든 노드에 특정 포트를 할당하고(모든 노드에 동일한 포트번호 사용) 서비스를 구성하는 파드로 들어오는 연결을 전달한다.
  • 이것은 일반 서비스와 유사하지만 서비스의 내부 클러스터IP 뿐만 아니라 모든 노드의 IP와 할당된 노드포트로 서비스에 엑세스할 수 있다.

노드포트 서비스 생성

apiVersion: v1
kind: Service
metadata:
  name: kubia-nodeport
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30123
  selector:
    app: kubia
  • type을 노드포트로 설정하고 이 서비스가 모든 클러스터 노드에 바인딩돼야하는 노드포트를 지정한다.
  • 노드포트를 생략하면 쿠버네티스가 임의의 포트를 선택한다.

 

노드포트 서비스 확인

  • EXTERNAL-IP 열을 보면 <none>으로 표시돼 있고 클러스터 노드의 IP 주소로 서비스에 엑세스할 수 있음을 나타낸다.
  • PORT(S) 열에는 클러스터 IP의 내부 포트(80)과 노드포트(30123)이 모두 표시된다.
  • 이 서비스는 다음 주소에서 엑세스할 수 있다.
    • 10.96.5.125:80
    • <첫 번째 노드의 IP>:30123
    • <두 번째 노드의 IP>:30123 등
  • 다음 그림은 두 클러스터 노드의 포트 30123에 노출된 서비스를 보여준다. 이런 포트에 대한 수신 연결은 임의로 선택된 파드로 전달되며, 연결 중인 노드에서 실행 중인 포트일 수도 있고 아닐 수도 있다.

 

외부 클라이언트가 노드포트 서비스에 엑세스할 수 있도록 방화벽 규칙 변경

  • 노드포트로 서비스에 엑세스하려면 해당 노드포트에 대한 외부 연결을 허용하도록 구글 클라우드 플랫폼의 방화벽을 구성해야 한다.

  • 노드 IP와 포트 30123으로 서비스에 엑세스할 수 있으며, 노드의 IP를 확인하는 방법은 다음을 참조한다.

  • 노드의 IP를 알고나면 서비스에 엑세스할 수 있다.


5.3.2 외부 로드밸런서로 서비스 노출

  • 클라우드 공급자에서 실행되는 쿠버네티스 클러스터는 일반적으로 클라우드 인프라에서 로드밸런서를 자동으로 프로비저닝하는 기능을 제공한다. 노드포트 대신 서비스 유형을 로드밸런서로 설정하면 된다.
  • 로드밸런서는 공개적으로 엑세스 가능한 고유한 IP 주소를 가지며 모든 연결을 서비스로 전달한다.

로드밸런서 서비스 생성

apiVersion: v1
kind: Service
metadata:
  name: kubia-loadbalancer
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: kubia
  • 서비스 유형이 노드포트 대신 로드밸런서로 설정한다.

 

로드밸런서를 통한 서비스 연결

  • 서비스를 생성한 후 클라우드 인프라가 로드밸런서를 생성하고 IP 주소를 서비스 오브젝트에 쓰는 데 시간이 걸린다.
  • 완료되면 로드밸런서 IP 주소가 서비스의 external IP 주소로 표시된다.
  • 노드포트 서비스와 달리 이번에는 방화벽을 설정할 필요가 없다.

  • 로드밸런서 유형 서비스는 추가 인프라 제공 로드밸런서가 있는 노드포트 서비스다.
  • kubectl describe를 사용해 서비스에 대한 추가 정보를 보면 서비스에 노드포트가 선택됐음을 알 수 있다.
  • 노드포트 서비스에 대한 포트의 방화벽을 열었다면 노드 IP로도 서비스에 엑세스할 수 있다.


5.3.3 외부 연결의 특성 이해

  • 외부에서 서비스로 들어오는 연결과 관련해 알아둬야 할 몇 가지가 있다.

 

불필요한 네트워크 홉의 이해와 예방

  • 외부 클라이언트가 노드포트로 서비스에 접속할 경우 임의로 선택된 파드가 연결을 수신한 동일한 노드에서 실행중일 수도 있고, 아닐 수도 있다. 파드에 도달하려면 추가적인 네트워크 홉이 필요할 수 있다.
  • 서비스 스펙 섹션의 externalTrafficPolicy 필드를 설정해서 외부의 연결을 수신한 노드에서 실행 중인 파드로만 외부 트래픽을 전달하도록 서비스를 구성해 추가 홉을 방지할 수 있다.
spec:
  externalTrafficPolicy: Local
  ...
  • 이 설정이 포함돼 있고 노드포트로 외부 연결이 열린 경우 서비스 프록시는 로컬에 실행중인 파드를 선택한다.
  • 로컬 파드가 존재하지 않으면 연결이 중단되므로 로드 밸런서는 파드가 하나 이상 있는 노드에만 연결을 전달하도록 해야한다.
  • 또한 이 어노테이션을 사용하면 모든 파드에 균등하게 연결이 분산되지 않을 수 있다.

 

클라이언트 IP가 보존되지 않음 인식

  • 클러스터 내의 클라이언트가 서비스로 연결할 때 서비스의 파드는 클라이언트 IP 주소를 얻을 수 있지만, 노드포트로 연결을 수신하면 패킷에서 소스 네트워크 주소 변환(SNAT)이 수행되므로 패킷의 소스 IP가 변경된다.
  • 파드는 실제 클라이언트의 IP를 볼 수 있으므로, 일부 애플리케이션에서는 문제가 될 수 있다.
  • 로컬 외부 트래픽 정책(Local External Traffic Policy)은 연결을 수신하든 노드와 대상 파드를 호스팅하는 노드 사이에 추가 홉이 없기 때문에 SNAT가 수행되지 않는다.
728x90
Comments