Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Reference

  • 이 포스팅은 의식의 흐름대로 ChatGPT 에게 쿠버네티스를 물어보는 방식으로 작성되었어요.

Kubernetes 의 전반적인 아키텍처 질문들

Kube-proxy 는 쿠버네티스 클러스터의 모든 노드에서 실행되는 프로세스입니다. 이 프로세스는 클러스터 내부에서 서비스를 외부로 노출하는 역할을 합니다. 이를 통해 클러스터 외부에서 서비스에 접근할 수 있습니다. 하지만 CNI 는 파드 내부의 컨테이너 네트워크 설정과 관련있죠.

맞습니다. 설명하신 내용이 정확합니다.

  • Kube-proxy: Kube-proxy는 Kubernetes 클러스터의 각 노드에서 실행되며, 클러스터 내부에서 서비스를 외부로 노출하고 서비스 디스커버리를 담당합니다. 이를 통해 클러스터 외부에서 서비스에 접근할 수 있도록 해주며, 이를 위해 NodePort, LoadBalancer, Ingress 등과 같은 서비스 유형을 관리하고 로드 밸런싱을 수행합니다.

  • CNI (Container Networking Interface): CNI는 파드 내부의 컨테이너 네트워크 설정과 관련이 있습니다. 각 파드의 컨테이너 네트워크를 설정하고 IP 주소 할당, 네트워크 정책 적용 등을 담당합니다. 이를 통해 파드 간 통신 및 외부와의 통신을 관리하며, 다양한 네트워크 드라이버와 통합할 수 있습니다. CNI는 파드 간의 네트워킹을 관리하는 데 사용됩니다.

두 컴포넌트는 Kubernetes 클러스터의 네트워크 관리를 다른 레벨에서 처리하며, Kube-proxy는 서비스와 파드 간의 네트워크 트래픽을 관리하고 노드 간 서비스 노출을 담당하고, CNI는 파드 내부의 컨테이너 네트워크 설정을 관리합니다.

아하 그렇다면 docker-compose 와 비교한다면, 자동으로 설정해주는 network 와 비슷하다고 볼수 있나요? CNI 가요. 각각 컨테이너 별 다른 IP 를 할당하잖아요

네, CNI는 Docker Compose에서 자동으로 설정되는 네트워크와 유사한 역할을 합니다. Docker Compose는 여러 컨테이너로 구성된 애플리케이션을 정의하고 관리하기 위한 도구로, 컨테이너 간 통신을 관리하는 네트워크를 자동으로 생성하고 구성합니다.

CNI는 Kubernetes에서 파드 내부의 컨테이너 네트워크를 관리하는 역할을 합니다. 각 파드의 컨테이너에 대한 네트워크 설정을 자동으로 처리하고, 각각의 컨테이너에 고유한 IP 주소를 할당합니다. 이렇게하여 파드 내부의 컨테이너 간에 통신할 수 있게 되며, 또한 파드 간 통신 및 외부와의 통신도 관리합니다.

따라서 Docker Compose에서 자동으로 설정되는 네트워크와 CNI는 비슷한 목적을 가지고 있으며, 컨테이너 간의 네트워킹을 관리하고 각각의 컨테이너에 IP 주소를 할당하여 통신을 가능하게 합니다. 그러나 Kubernetes와 CNI는 컨테이너 오케스트레이션 및 관리를 위한 훨씬 더 복잡하고 확장 가능한 시스템을 제공합니다.

그러면 파드 별 네트워크 할당 및 관리가 CNI 인것이고, Kube-proxy 는 외부포트노출 및 로드밸런싱 역할을 수행한다는거네요?

맞습니다. 여러 파드가 클러스터 내에서 실행되는 Kubernetes 환경에서, CNI는 각 파드 별 네트워크 할당 및 관리 역할을 담당합니다. 이것은 파드 내부의 컨테이너 간 통신 및 파드 간 통신을 가능하게 합니다.

한편, Kube-proxy는 서비스 디스커버리 및 로드 밸런싱과 같은 서비스 관련 네트워크 역할을 수행합니다. Kube-proxy는 클러스터 내부에서 서비스를 외부로 노출하고, 외부에서 서비스에 접근할 수 있도록 서비스에 대한 로드 밸런싱을 제공합니다. Kube-proxy는 서비스와 파드 간의 네트워크 트래픽 관리를 담당하며, 노드 포트 노출, 로드 밸런싱 구성, 패킷 라우팅 등을 수행합니다.

요약하면, CNI는 파드 별 네트워크 할당 및 관리에 집중하고, Kube-proxy는 서비스 관련 네트워크 역할을 수행하여 외부 포트 노출 및 로드 밸런싱을 담당합니다. 이 두 컴포넌트는 Kubernetes 클러스터의 네트워크를 구성하고 관리하는 데 필요한 서로 다른 역할을 수행합니다.

그렇다면 `kubectl get pod -o wide` 여기서 말하는 IP 란, 외부에서 접근 불가능한 클러스터 내부에서 CNI 에 의해 할당된 IP라는건가요?

네, 맞습니다. kubectl get pod 명령을 사용하여 출력된 IP 주소는 클러스터 내부에서 사용되는 내부 IP 주소입니다. 이 IP 주소는 파드 내부에서 통신하거나 클러스터 내의 다른 리소스와 상호작용하기 위한 목적으로 할당됩니다. 클러스터 외부에서 이 IP 주소로 직접 접근할 수 없습니다.

CNI (Container Networking Interface)는 파드 간 통신 및 파드 내부에서의 네트워크 설정을 관리하며, 이러한 내부 IP 주소를 할당하고 관리합니다. 클러스터 외부에서 파드에 접근하려면 서비스를 사용하거나 Ingress 리소스를 설정하여 외부 노출을 구성해야 합니다.

그렇다면 Ingress 리소스와 서비스는 무엇이 다른가요?

Ingress 리소스와 서비스는 Kubernetes 클러스터에서 네트워크 관리를 다르게 다루는 두 가지 다른 컨셉입니다. 각각의 역할과 사용 사례를 설명하겠습니다.

  1. 서비스 (Service):
    • 서비스는 Kubernetes 내부에서 파드 간 통신 및 서비스 디스커버리를 관리하는 데 사용됩니다. 서비스는 논리적으로 파드 그룹에 대한 네트워크 엔드포인트를 정의하고, 이를 로드 밸런싱하며 외부 또는 내부에서 서비스에 액세스할 수 있는 방법을 제공합니다.
    • 서비스 유형에는 ClusterIP, NodePort, LoadBalancer 등이 있으며, 각 유형은 다른 방식으로 서비스를 노출하고 관리합니다. 예를 들어 ClusterIP는 클러스터 내부에서만 액세스할 수 있으며, NodePort는 클러스터 외부에서 노드의 포트를 통해 액세스할 수 있으며, LoadBalancer는 외부 로드 밸런서를 사용하여 서비스를 노출합니다.
  2. Ingress 리소스 (Ingress Resource):
    • Ingress 리소스는 HTTP 및 HTTPS와 같은 Layer 7 프로토콜을 기반으로 클러스터 외부에서 내부 서비스에 라우팅하는 데 사용됩니다. Ingress는 특정 도메인 이름, 경로 또는 URL 패턴을 기반으로 요청을 처리하고, 이를 백엔드 서비스로 라우팅합니다.
    • Ingress 컨트롤러 (예: Nginx Ingress Controller 또는 Traefik Ingress Controller)는 Ingress 리소스를 해석하고 구성된 라우팅 규칙에 따라 클러스터 외부에서 내부 서비스로 요청을 라우팅합니다.
    • Ingress를 사용하면 여러 도메인에 대한 가상 호스트 기반 라우팅, 경로 기반 라우팅, SSL/TLS 암호화 등 고급 네트워크 구성을 쉽게 구현할 수 있습니다.

간단히 말해서, 서비스는 클러스터 내에서 파드 간 통신 및 서비스 디스커버리를 관리하는 데 사용되며, Ingress 리소스는 클러스터 외부에서 HTTP 및 HTTPS 요청을 내부 서비스로 라우팅하는 데 사용됩니다. 이 두 가지는 서로 다른 레벨에서 네트워크를 관리하고 클러스터의 내부 및 외부 트래픽을 다르게 처리합니다.


kind: Deployment

Deployment.yaml 의 spec.selector.matchLabels 는 Pod 의 라벨을 매칭하는건가요?
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  labels:
    app: my-app-2
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-container
          image: my-image

네, Kubernetes에서 Deployment의 spec.selector.matchLabels 필드는 해당 Deployment와 관련된 Pod를 선택하는 데 사용되는 라벨 셀렉터(selector)입니다. 이 필드를 통해 Deployment는 어떤 라벨을 가진 Pod를 관리할 것인지 지정할 수 있습니다.

matchLabels 필드는 Pod 템플릿의 라벨과 일치하는 Pod만을 선택합니다. 예를 들어, 다음과 같은 Deployment YAML 구성을 고려해 보겠습니다:

위의 예제에서 spec.selector.matchLabelsapp: my-app 라벨과 일치하는 Pod만 선택하도록 구성되어 있습니다. 따라서 이 Deployment는 app: my-app 라벨을 가진 Pod를 관리하고 배포합니다.

이를 통해 Deployment는 해당 라벨을 가진 Pod의 상태를 관리하고 업데이트를 수행하며, 필요에 따라 롤링 업데이트나 스케일링과 같은 작업을 수행할 수 있습니다.

그렇다면 서비스가 spec.selector.matchLabels 로 "my-app-2" 나 "my-app" 를 매칭해도 상관없겠네요? 만약 "my-app-2" 를 선택하면 Deployment 가 선택될테고, 이 Deployment 는 결국 spec 에서 "my-app" 파드와 매칭되니깐 말이에요. 만약 서비스가 "my-app" 를 매칭해도 Pod 와 직접 매칭되니 이또한 상관없겠네요. 결론은 둘 다 "my-app" Pod 와 매칭되겠네요?

네, 맞습니다. 서비스 (Service)의 spec.selector.matchLabels에서 “my-app-2” 또는 “my-app” 라벨을 매칭해도 상관없습니다. 그 이유는 다음과 같습니다:

  1. 서비스의 역할은 파드 집합에 대한 네트워크 라우팅 및 로드 밸런싱을 제공하는 것입니다.
  2. 서비스는 spec.selector.matchLabels를 사용하여 어떤 파드를 선택할지 지정합니다.
  3. 만약 “my-app-2”를 선택하면 해당 서비스는 “my-app-2” 라벨을 가진 파드를 선택하게 되고, 이 파드가 속한 Deployment를 통해 “my-app” 라벨을 가진 파드도 선택됩니다.
  4. 마찬가지로 “my-app”을 선택하면 “my-app” 라벨을 가진 파드를 선택하고, 이 파드가 속한 Deployment를 통해 “my-app-2” 라벨을 가진 파드도 선택됩니다.

결국 서비스의 spec.selector.matchLabels 설정에 관계없이 두 가지 라벨 중 하나를 선택하면 해당 서비스는 두 라벨 모두를 가진 파드를 선택하게 되며, 이로 인해 “my-app”과 “my-app-2” 파드가 선택될 것입니다. 이것은 두 가지 라벨을 사용하여 다양한 상황에서 라우팅 및 로드 밸런싱을 설정하는 데 유용할 수 있습니다.

3. 만약 "my-app-2"를 선택하면 해당 서비스는 "my-app-2" 라벨을 가진 파드를 선택하게 되고, 이 파드가 속한 Deployment를 통해 "my-app" 라벨을 가진 파드도 선택됩니다. 이 설명이 맞는걸까요? 서비스는 "my-app-2" 라벨을 가진 Deployment 를 선택하는 게 아닌가요?

죄송합니다, 이전 답변에서의 설명이 부정확했습니다. 서비스의 spec.selector.matchLabels는 해당 서비스가 선택할 파드를 결정하는 중요한 부분입니다. 서비스는 파드의 라벨을 기준으로 트래픽을 라우팅하고, 서비스의 선택된 파드를 대상으로 트래픽을 전달합니다.

따라서 서비스의 spec.selector.matchLabels가 “my-app-2” 라벨을 가진 경우, 해당 서비스는 “my-app-2” 라벨을 가진 파드만 선택하며, 해당 Deployment를 선택하지 않습니다. 서비스의 spec.selector.matchLabels 설정에 따라 파드가 직접 선택되며, 선택된 파드의 라벨과 Deployment와는 직접적인 연관성이 없습니다.

컨트롤러(Deployment)와 서비스(Service) 간의 연결은 일반적으로 라벨 셀렉터를 사용하여 이루어지며, 서비스가 특정 라벨을 가진 파드를 선택하고 해당 파드로 트래픽을 전달합니다. 따라서 서비스의 spec.selector.matchLabels 설정에 주목하여 어떤 파드가 해당 서비스를 통해 라우팅될지를 결정하게 됩니다.

그렇다면 서비스가 spec.selector 로 "my-app-2" 를 매칭한다면, 위의 예제에서는 어떤 파드도 선택되지 않겠네요?

네, 맞습니다. 서비스의 spec.selector가 “my-app-2” 라벨을 가리키고 있는 경우, 위의 예제에서는 어떤 파드도 선택되지 않을 것입니다. 이는 서비스가 해당 라벨을 가진 파드를 찾을 수 없기 때문입니다. Deployment의 파드 템플릿과 라벨이 “my-app”로 설정되어 있으므로, “my-app-2” 라벨을 가진 파드는 존재하지 않습니다.

따라서 서비스의 spec.selector 설정은 파드의 라벨과 일치하는 경우에만 해당 파드를 선택할 수 있으며, “my-app-2” 라벨을 가진 파드는 선택되지 않습니다. Deployment에 속한 파드는 “my-app” 라벨을 가지고 있으므로 서비스가 “my-app-2” 라벨을 가진 파드를 선택하는 경우, 해당 라벨을 가진 파드가 없어 선택되지 않을 것입니다.

설령 Deployment 의 metadata 가 "my-app-2" 이라도 말이죠?

네, 맞습니다. Deployment의 metadata의 라벨이 “my-app-2”로 설정되어 있다면, 서비스의 spec.selector가 “my-app-2” 라벨을 가리키는 경우 해당 Deployment가 선택될 것입니다. 그리고 해당 Deployment에 속한 파드 중에서 “my-app” 라벨을 가진 파드가 선택될 것입니다.

예를 들어, 다음과 같은 Deployment와 서비스가 있다고 가정해 봅시다:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  labels:
    app: my-app-2
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-container
          image: my-image

위의 Deployment의 metadata의 라벨이 “my-app-2”로 설정되어 있지만, selector 내의 matchLabels가 “my-app” 라벨을 가리키고 있습니다. 이 경우, 서비스의 spec.selector가 “my-app” 라벨을 가리키는 경우 해당 서비스는 “my-app” 라벨을 가진 파드를 선택하게 되고, 이 파드는 해당 Deployment의 파드 중 하나일 것입니다. 따라서 “my-app” 라벨을 가진 파드가 서비스를 통해 선택됩니다.

spec.selector 는 파드의 라벨만 선택할 수 있는게 아니였나요?

죄송합니다, 이전 답변에서 혼동이 있었습니다. spec.selector는 파드의 라벨을 선택할 때 사용되며 다른 리소스(예: ReplicaSet 또는 Deployment)의 라벨과 매칭하여 파드를 선택하는 데 중요한 역할을 합니다.

따라서 spec.selector는 파드의 라벨과 관련이 있으며, 다른 리소스의 라벨과 일치하는 파드를 선택하는 기준을 설정합니다. 서비스는 이 기준을 사용하여 특정 파드를 선택하고 그 파드로 트래픽을 라우팅합니다.

이전 답변에서의 혼동을 바로잡아드려 죄송합니다. 서비스의 spec.selector 설정은 파드의 라벨과 일치하는 경우에만 해당 파드를 선택할 수 있습니다. 다른 라벨과 일치하지 않는 경우 해당 파드는 서비스에 의해 선택되지 않습니다.

그렇다면 Deployment 의 "my-app-2" 라벨은 선택되지 않겠네요?

맞습니다. 서비스의 spec.selector가 “my-app” 라벨을 가리키고 있는 경우, 해당 서비스는 “my-app” 라벨을 가진 파드만 선택합니다. Deployment의 metadata 내에 “my-app-2” 라벨이 있더라도, 서비스가 “my-app” 라벨을 사용하므로 “my-app-2” 라벨을 가진 파드는 서비스에 의해 선택되지 않습니다.

서비스는 파드의 라벨과만 일치하는 파드를 선택하며, 다른 라벨과는 관계없이 동작합니다. 따라서 Deployment의 “my-app-2” 라벨은 서비스에 의해 선택되지 않으며, 서비스가 “my-app” 라벨을 가진 파드만 선택할 것입니다.


kind: Service

쿠버네티스 Service 의 여러 예시를 보여주세요

Kubernetes의 Service 리소스를 정의하는 YAML 파일에 대한 다양한 예시를 제공합니다. 이 예시들은 서비스 유형과 포트 설정을 다르게 하여 다양한 상황에 맞게 사용할 수 있습니다.

  1. ClusterIP 서비스 (기본 유형):
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  1. NodePort 서비스 (노드 외부에서 접근 가능):
apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: NodePort
  1. LoadBalancer 서비스 (클라우드 환경에서 사용):
apiVersion: v1
kind: Service
metadata:
  name: my-loadbalancer-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: LoadBalancer
  1. ExternalName 서비스 (외부 서비스에 대한 CNAME 설정):
apiVersion: v1
kind: Service
metadata:
  name: my-externalname-service
spec:
  type: ExternalName
  externalName: example.com
  1. Headless 서비스 (ClusterIP 없이 라벨 선택):
apiVersion: v1
kind: Service
metadata:
  name: my-headless-service
spec:
  selector:
    app: my-app
  clusterIP: None
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  1. 서비스에 대한 TCP와 UDP 포트 설정:
apiVersion: v1
kind: Service
metadata:
  name: my-tcp-udp-service
spec:
  selector:
    app: my-app
  ports:
    - name: tcp-port
      protocol: TCP
      port: 80
      targetPort: 8080
    - name: udp-port
      protocol: UDP
      port: 53
      targetPort: 53
2. 노드포트같은 경우에는 ports 내부에 nodePort 를 명시해줘야되는거 아닌가요?

네, 맞습니다. NodePort 서비스를 사용할 때는 ports 섹션 내에서 nodePort를 명시해야 합니다. nodePort는 클러스터 외부에서 노드의 IP 주소와 특정 포트 번호를 사용하여 서비스에 접근할 때 사용됩니다.

올바른 구성은 다음과 같습니다:

apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80         # 클러스터 내부에서 사용할 포트
      targetPort: 8080 # 백엔드 파드의 포트
      nodePort: 30000  # 노드 외부에서 접근할 포트
  type: NodePort

위 예시에서는 nodePort30000으로 설정하여 노드 외부에서 30000 포트를 사용하여 서비스에 접근할 수 있도록 정의하였습니다. 이렇게 설정하면 클러스터 외부에서 노드의 IP 주소와 30000 포트를 사용하여 서비스에 접근할 수 있습니다.

반드시 nodePort를 지정해야 하는 것은 아니지만 명시적으로 지정하는 것이 좋습니다. 이렇게 하면 노드 포트 번호를 컨트롤할 수 있고, 충돌을 피할 수 있습니다. 단, 사용 가능한 노드 포트 번호 범위 내에서 선택해야 합니다.

Service.yaml 내의 태그들을 설명해주세요
apiVersion: v1
kind: Service
metadata:
   name: my-nodeport-service
spec:
   selector:
      app: my-app
   ports:
      - protocol: TCP
        port: 80         
        targetPort: 4000 
        nodePort: 30000  
   type: NodePort

이 Kubernetes Service 리소스의 YAML 정의를 통해 my-nodeport-service라는 NodePort 서비스를 만들고 있습니다. 아래는 정의 내용의 각 부분에 대한 설명입니다:

  • apiVersion: v1: 이 서비스 정의의 Kubernetes API 버전을 지정합니다.

  • kind: Service: 이 YAML 파일이 서비스를 정의하는 Kubernetes 리소스임을 나타냅니다.

  • metadata: 서비스의 메타데이터를 설정하는 섹션입니다. 여기서는 서비스의 이름을 my-nodeport-service로 지정하고 있습니다.

  • spec: 서비스의 스펙을 정의하는 섹션으로, 다음과 같이 설정되어 있습니다:
    • selector: 서비스가 연결할 백엔드 파드를 선택하기 위한 라벨 셀렉터를 지정합니다. 이 경우, app: my-app 라벨이 있는 파드들을 선택하여 서비스에 연결합니다.

    • ports: 서비스가 수신할 포트와 백엔드 파드로 전달할 포트를 지정하는 리스트입니다. 다음과 같이 설정되어 있습니다:

      • protocol: TCP: 포트의 통신 프로토콜을 TCP로 설정합니다.

      • port: 80: 클러스터 내부에서 서비스가 사용할 포트 번호를 지정합니다. 클러스터 내의 다른 파드들은 이 포트를 통해 서비스에 접근할 수 있습니다.

      • targetPort: 4000: 백엔드 파드의 포트 번호를 지정합니다. 이 포트 번호는 서비스가 연결할 백엔드 파드의 포트 번호입니다. 백엔드 파드의 4000 포트와 연결됩니다.

      • nodePort: 30000: 노드 외부에서 서비스에 접근할 때 사용할 포트 번호를 지정합니다. 이 포트 번호를 사용하여 노드의 IP 주소와 함께 서비스에 접근할 수 있습니다. 이 예시에서는 노드 외부에서 30000 포트를 사용하여 서비스에 접근할 수 있도록 설정되어 있습니다.

  • type: NodePort: 이 서비스의 유형을 NodePort로 지정합니다. 이것은 클러스터 외부에서 노드의 IP 주소와 nodePort로 서비스에 접근할 수 있도록 하는 유형입니다.

이 서비스 정의는 클러스터 내의 파드 중 app: my-app 라벨이 있는 파드에 대한 서비스를 생성하며, 클러스터 외부에서 노드의 IP 주소와 30000 포트를 사용하여 해당 서비스에 접근할 수 있도록 합니다. 클러스터 내부에서는 이 서비스를 80 포트를 통해 사용할 수 있습니다.

여기서 말하는 targetPort 는 deployment.yaml 의 containers.ports.containerPort 를 뜻하는건가요?

네, 맞습니다. targetPortService 정의에서 사용되는 포트 중 하나로, 백엔드 파드의 컨테이너 포트인 containers.ports.containerPort와 관련이 있습니다.

  • targetPort: 서비스에서 정의한 포트로 들어오는 요청이 백엔드 파드의 컨테이너 포트인 containers.ports.containerPort로 전달되는 대상 포트를 나타냅니다. 서비스는 클러스터 내의 백엔드 파드에 대한 포트 매핑을 설정하며, 이 targetPort가 백엔드 파드의 컨테이너 포트와 연결됩니다.

예를 들어, 서비스 정의에서 targetPort8080으로 설정하고, 백엔드 파드의 컨테이너 포트 containers.ports.containerPort8080으로 설정한다면, 서비스가 들어오는 요청을 백엔드 파드의 8080 포트로 전달할 것입니다.

간단히 말해, targetPort는 서비스가 백엔드 파드의 어떤 포트로 요청을 전달할지를 지정하는 것이며, 이 값은 백엔드 파드의 컨테이너 포트인 containers.ports.containerPort와 일치해야 합니다.

그리고 port: 80 의 클러스터 내부에서 서비스가 사용할 포트 번호란, 서로 다른 워커 노드이더라도 같은 클러스터라면 접근가능한 포트라는건가요?

맞습니다. port: 80는 클러스터 내부에서 서비스가 사용할 포트 번호를 나타냅니다. 이 포트 번호는 같은 Kubernetes 클러스터 내의 모든 노드에서 서비스에 접근할 수 있는 포트입니다. 즉, 모든 워커 노드와 마스터 노드에서 서비스를 사용하려면 해당 포트 번호를 사용하여 서비스에 접근할 수 있습니다.

서비스의 port는 클러스터 내의 다른 파드들이 서비스에 접근할 때 사용하는 포트입니다. 예를 들어, 다른 파드에서 이 서비스를 호출하거나 통신할 때, 해당 파드는 서비스의 port 번호를 사용하여 통신을 수행할 수 있습니다. 이렇게 함으로써 파드 간의 통신을 쉽게 설정하고 관리할 수 있습니다.

단, 외부에서 클러스터 내의 서비스에 접근하려면 클러스터 외부에서의 네트워크 설정 및 방화벽 규칙을 고려해야 합니다. 이러한 경우 NodePort나 LoadBalancer 서비스를 사용하여 외부로 노출하는 방법을 고려할 수 있습니다.

NodePort 같은 경우에는 그러면 여러개의 pods 를 묶을 수 있나요? 만약 묶을 수 있다면 자체적으로 로드밸런싱을 수행하나요?

NodePort 서비스는 백엔드 파드의 선택을 기반으로 요청을 여러 파드로 라우팅할 수 있습니다. 이때 로드 밸런싱은 서비스의 핵심 기능 중 하나입니다.

NodePort 서비스는 백엔드 파드의 라벨 셀렉터를 사용하여 트래픽을 라우팅합니다. 즉, 같은 라벨 셀렉터를 가진 모든 파드는 서비스에 등록되며, 들어오는 요청은 이 파드 중 하나로 라우팅됩니다. 이를 통해 여러 개의 파드를 그룹화하고 트래픽을 분산시키는 로드 밸런싱 효과를 얻을 수 있습니다.

로드 밸런싱은 클러스터 내에서 서비스에 연결된 모든 파드에 대한 균등한 분산을 수행합니다. 이것은 서비스의 핵심 기능 중 하나이며, 클라이언트가 서비스의 NodePort에 요청을 보낼 때, 서비스는 라벨 셀렉터와 일치하는 백엔드 파드 중 하나를 선택하여 요청을 전달합니다. 이러한 프로세스를 통해 트래픽 로드 밸런싱이 이루어집니다.

따라서 NodePort 서비스를 사용하면 여러 개의 파드를 그룹화하고 트래픽을 분산시킬 수 있으며, 서비스가 자체적으로 로드 밸런싱을 수행합니다. 이는 파드의 수평 확장과 고가용성을 제공하는 데 도움이 됩니다.

그렇다면 NodePort 와 Ingress 와 다른점이 무엇인가요?

NodePortIngress는 Kubernetes에서 서비스를 외부로 노출하는 두 가지 서로 다른 방법입니다. 각각의 주요 차이점을 요약하겠습니다.

  1. NodePort:
    • NodePort는 Kubernetes 클러스터의 각 노드에 특정 포트를 열어 서비스에 대한 외부 액세스를 허용하는 방법입니다.
    • 각 노드에 열린 포트는 클러스터 외부에서 해당 노드로 접근하고 서비스로 라우팅됩니다.
    • 일반적으로 NodePort 서비스를 사용하면 외부에서 클러스터 내부 서비스에 직접 접근할 수 있지만, SSL/TLS 종단 지원이나 더 복잡한 경로 기반 라우팅을 구현하기 어려울 수 있습니다.
  2. Ingress:
    • Ingress는 클러스터 내부의 여러 서비스에 대한 HTTP 및 HTTPS 경로 기반 라우팅을 제공하는 Kubernetes 리소스입니다.
    • Ingress 컨트롤러(예: Nginx Ingress Controller)를 사용하여 구현됩니다.
    • 하나의 진입 지점(예: 로드 밸런서 또는 인그레스 컨트롤러)에서 여러 서비스에 대한 경로 기반 라우팅을 구성할 수 있습니다.
    • SSL/TLS 종단 지원, 가상 호스트 기반 라우팅, 경로 기반 라우팅 및 기타 고급 기능을 구현하는 데 유용합니다.

간단히 말해, NodePort는 포트 기반 노출을 제공하며 간단한 경우에 사용됩니다. 반면에 Ingress는 더 복잡한 라우팅 및 SSL 종단 지원과 같은 고급 기능을 제공하는 데 사용됩니다. 일반적으로 웹 애플리케이션을 호스팅하거나 HTTP(S) 요청을 처리해야 하는 경우 Ingress를 사용하는 것이 일반적입니다.

아하 그렇다면 Ingress 는 라우팅 패스를 설정할 수 있다는 점, TLS 종단 지원을 한다는 점이 Service 와 다르네요?

맞습니다! IngressService와 비교하여 다음과 같은 주요 차이점을 가지고 있습니다:

  1. 라우팅 패스 설정:
    • Ingress를 사용하면 HTTP 및 HTTPS 요청에 대한 경로 기반 라우팅을 설정할 수 있습니다. 예를 들어, 서로 다른 경로에 따라 다른 백엔드 서비스로 요청을 라우팅할 수 있습니다.
  2. TLS 종단 지원:
    • Ingress를 통해 SSL/TLS 종단 지원을 구성할 수 있습니다. 이를 통해 클라이언트와의 안전한 통신을 위해 SSL/TLS 암호화를 적용할 수 있습니다.
  3. 가상 호스트 지원:
    • Ingress를 사용하여 하나의 진입 지점에서 여러 가상 호스트(도메인)에 대한 라우팅을 설정할 수 있습니다. 각 가상 호스트는 다른 백엔드 서비스로 라우팅될 수 있습니다.
  4. 더 복잡한 라우팅 제어:
    • Ingress 컨트롤러를 사용하면 보다 복잡한 라우팅 규칙을 구성할 수 있습니다. 경로, HTTP 헤더, 쿠키 및 기타 요청 속성을 기반으로 라우팅 규칙을 정의할 수 있습니다.
  5. 기능 확장성:
    • Ingress는 컨트롤러를 통해 다양한 기능을 확장할 수 있습니다. 예를 들어, Nginx Ingress Controller나 Traefik과 같은 컨트롤러를 사용하여 기능을 확장하고 사용자 정의 설정을 적용할 수 있습니다.

따라서 Ingress는 단순한 포트 기반 노출을 넘어서 웹 애플리케이션을 호스팅하거나 고급 라우팅 및 보안 요구사항을 처리해야 할 때 유용한 Kubernetes 리소스입니다. 반면에 Service는 포트 기반 노출을 위한 간단한 리소스로 사용됩니다.

그렇다면 Ingress 라우팅 패스 설정에서 정규식 표현도 사용가능하나요?

네, Ingress의 경로 설정에서 정규식 표현식을 사용할 수 있습니다. Kubernetes의 일부 Ingress 컨트롤러(예: Nginx Ingress Controller, Traefik 등)는 정규식을 지원하며, 이를 사용하여 복잡한 경로 기반 라우팅 규칙을 정의할 수 있습니다.

예를 들어, 다음과 같은 Ingress 리소스의 일부를 살펴보겠습니다. 이 예에서는 정규식을 사용하여 /api/로 시작하는 모든 경로를 백엔드 서비스로 라우팅합니다:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
    - host: example.com
      http:
        paths:
          - path: ^/api/.*   # 정규식을 사용한 경로 패턴
            pathType: Prefix  # Prefix 또는 Exact 중 선택 가능
            backend:
              service:
                name: my-backend-service
                port:
                  number: 80

위의 예에서 ^/api/.*/api/로 시작하는 모든 경로를 캡처하는 정규식입니다. 이 경로 패턴에 해당하는 요청은 my-backend-service로 라우팅됩니다.

경로 패턴 외에도 정규식을 사용하여 다양한 조건을 만족하는 요청을 처리할 수 있습니다. 다만 사용 중인 Ingress 컨트롤러가 정규식을 지원하는지 확인하고 해당 컨트롤러의 문서를 참조하는 것이 중요합니다.

그렇다면 Prefix 를 제거한 url 을 pod 로 전송할 수도 있나요?

네, Ingress를 사용하면 원하는 경로에서 일부 경로 부분을 제거하거나 수정하여 백엔드 파드로 전달할 수 있습니다. 이를 통해 요청된 URL을 변환하고 필요한 경로를 백엔드 서비스로 라우팅할 수 있습니다.

예를 들어, /api/를 제거하고 나머지 경로를 백엔드 파드로 전달하려면 다음과 같이 Ingress 리소스를 구성할 수 있습니다:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
    - host: example.com
      http:
        paths:
          - path: ^/api(/.*)?$  # 정규식을 사용하여 /api/ 를 선택
            pathType: Prefix    # Prefix 또는 Exact 중 선택 가능
            backend:
              service:
                name: my-backend-service
                port:
                  number: 80

위의 예에서 ^/api(/.*)?$ 정규식은 /api/로 시작하는 경로를 선택하고 /api/ 이후의 부분은 캡처합니다. 그리고 my-backend-service로 이 경로를 라우팅합니다. 따라서 클라이언트가 /api/some/resource를 요청하면 백엔드로는 /some/resource 경로로 전달됩니다.

이렇게 경로를 수정하거나 잘라내는 방식을 사용하면 클라이언트 요청을 더 유연하게 처리할 수 있습니다.