You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Service로 노출할 때 어느 컨테이너로 가는지가 궁금하신 것이라 그 각도로 정리합니다.
답부터
Service는 컨테이너를 모릅니다. 포트만 봅니다.
Service의 targetPort에 적는 것은 컨테이너 이름이 아니라 포트입니다. 그 포트를 어느 컨테이너가 열었는지는 Service가 신경 쓰지 않습니다. 열어 둔 쪽으로 갈 뿐입니다.
그래서 컨테이너를 구별하는 것이 아니라 포트를 구별하는 것입니다.
왜 그런가
같은 Pod 안 컨테이너는 IP를 공유하기 때문입니다. 쿠버네티스 문서의 서술입니다.
Within a Pod, containers share an IP address and port space, and can find each other via localhost.
(Pod 안에서 컨테이너들은 IP 주소와 포트 공간을 공유하며 localhost로 서로를 찾을 수 있습니다.)
IP가 같으니 IP로는 구별할 수가 없습니다. 남는 것이 포트입니다.
flowchart LR
SVC["Service<br/>port 80 → targetPort 80<br/>port 9090 → targetPort 9090"]
subgraph POD["Pod 하나 (IP 10.1.2.3 하나)"]
direction TB
C1["컨테이너 A<br/>80에서 대기"]
C2["컨테이너 B<br/>9090에서 대기"]
end
SVC -->|"10.1.2.3 : 80"| C1
SVC -->|"10.1.2.3 : 9090"| C2
C1 <-->|"서로는 localhost로 부름"| C2
class POD podbox
classDef podbox fill:#1e293b,stroke:#94a3b8,color:#ffffff
Loading
Pod 상자 하나에 IP가 하나입니다. Service가 보내는 주소는 둘 다 10.1.2.3이고 포트만 다릅니다.
같은 Pod 안이라 서로는 localhost로 부릅니다. 컨테이너 A에서 컨테이너 B를 부를 때 Service를 거치지 않고 localhost:9090이면 됩니다.
이러면 하나의 Service로 두 포트가 열립니다. 클러스터 안에서 my-service:80으로 부르면 컨테이너 A로 가고 my-service:9090으로 부르면 컨테이너 B로 갑니다.
포트가 두 개 이상이면 name을 붙여야 합니다. 하나뿐일 때는 생략할 수 있습니다.
포트는 겹치면 안 됩니다
같은 Pod 안에서 두 컨테이너가 같은 포트를 열 수는 없습니다. 포트 공간이 하나이기 때문입니다. 문서에도 그렇게 적혀 있습니다.
When containers in a Pod communicate with entities outside the Pod, they must coordinate how they use the shared network resources (such as ports).
(Pod 안의 컨테이너들이 Pod 바깥과 통신할 때는 공유하는 네트워크 자원(포트 같은)을 어떻게 쓸지 서로 맞춰야 합니다.)
컨테이너 하나만 있을 때는 신경 쓸 일이 없다가, 둘이 되는 순간 생기는 제약입니다. 같은 이미지를 두 개 넣으면 둘 다 같은 포트를 열려고 해서 하나가 뜨지 못합니다.
번호 대신 이름을 붙이면 편합니다
Pod 쪽에서 포트에 이름을 붙이고 Service가 그 이름을 가리킬 수 있습니다. 제 실습 클러스터에 실제로 그렇게 쓰는 것이 있습니다.
targetPort가 숫자가 아니라 이름입니다. 이렇게 두면 나중에 앱이 포트 번호를 바꿔도 Service는 안 고쳐도 됩니다. 이름만 그대로면 됩니다.
이 예는 컨테이너 하나가 포트를 세 개 연 경우인데 동작 원리는 컨테이너가 여러 개일 때와 같습니다. Service는 어차피 컨테이너를 보지 않고 포트만 보기 때문입니다.
Service를 하나로 할지 여러 개로 할지
둘 다 됩니다. 기준은 누가 부르느냐입니다.
상황
이렇게 합니다
부르는 쪽이 같은 무리이고 접근 범위도 같다
Service 하나에 포트를 여러 개
하나는 밖에 열고 하나는 안에서만 쓴다
Service를 둘로 나누고 타입을 다르게
예를 들어 웹은 밖에 열고 메트릭은 클러스터 안에서만 보게 하려면, 웹용 Service는 LoadBalancer로 메트릭용 Service는 ClusterIP로 각각 둡니다. 같은 Pod를 가리키는 Service가 둘이어도 됩니다. Service는 라벨로 Pod를 고를 뿐이라 여러 Service가 같은 Pod를 가리켜도 문제가 없습니다.
이 과정 앱은 어떤가
k8s/frontend-deployment.yaml과 k8s/backend-deployment.yaml을 보시면 각 Pod에 컨테이너가 하나씩입니다. 그래서 이 과정에서는 위 상황을 만나지 않습니다.
frontend Pod 안의 nginx가 /api 요청을 backend로 넘기는데, 그건 같은 Pod 안 컨테이너끼리가 아니라 다른 Pod로 가는 것입니다. 그래서 localhost가 아니라 backend-service라는 Service 이름으로 부릅니다. 4회차에 두 Service를 만든 이유가 이것입니다.
컨테이너를 여러 개 넣는 것은 주로 본체 옆에 도우미를 붙일 때입니다. 로그를 모아 보내는 것, 앞에서 트래픽을 받아 넘기는 것 같은 역할입니다. 본체와 생명주기를 같이해야 하고 같은 파일이나 네트워크를 봐야 할 때 한 Pod에 넣습니다. 그럴 이유가 없으면 Pod를 나누는 편이 낫습니다.
직접 확인해 보시기 바랍니다
# Pod마다 컨테이너가 몇 개인지
kubectl get pods -o custom-columns='NAME:.metadata.name,CONTAINERS:.spec.containers[*].name'# 컨테이너가 여는 포트
kubectl get pods -o jsonpath='{.items[*].spec.containers[*].ports}'# Service가 어느 포트로 보내는지
kubectl get svc -o jsonpath='{.items[*].spec.ports}'
컨테이너가 여러 개인 Pod에서는 명령에 -c로 어느 컨테이너인지 알려 줘야 합니다. 하나뿐일 때는 생략해도 됩니다.
4회차에 이런 질문이 나왔습니다.
Service로 노출할 때 어느 컨테이너로 가는지가 궁금하신 것이라 그 각도로 정리합니다.
답부터
Service는 컨테이너를 모릅니다. 포트만 봅니다.
Service의
targetPort에 적는 것은 컨테이너 이름이 아니라 포트입니다. 그 포트를 어느 컨테이너가 열었는지는 Service가 신경 쓰지 않습니다. 열어 둔 쪽으로 갈 뿐입니다.그래서 컨테이너를 구별하는 것이 아니라 포트를 구별하는 것입니다.
왜 그런가
같은 Pod 안 컨테이너는 IP를 공유하기 때문입니다. 쿠버네티스 문서의 서술입니다.
IP가 같으니 IP로는 구별할 수가 없습니다. 남는 것이 포트입니다.
flowchart LR SVC["Service<br/>port 80 → targetPort 80<br/>port 9090 → targetPort 9090"] subgraph POD["Pod 하나 (IP 10.1.2.3 하나)"] direction TB C1["컨테이너 A<br/>80에서 대기"] C2["컨테이너 B<br/>9090에서 대기"] end SVC -->|"10.1.2.3 : 80"| C1 SVC -->|"10.1.2.3 : 9090"| C2 C1 <-->|"서로는 localhost로 부름"| C2 class POD podbox classDef podbox fill:#1e293b,stroke:#94a3b8,color:#ffffffPod 상자 하나에 IP가 하나입니다. Service가 보내는 주소는 둘 다
10.1.2.3이고 포트만 다릅니다.같은 Pod 안이라 서로는
localhost로 부릅니다. 컨테이너 A에서 컨테이너 B를 부를 때 Service를 거치지 않고localhost:9090이면 됩니다.노출하는 방법
Service의
ports는 배열입니다. 여러 개를 적을 수 있습니다.이러면 하나의 Service로 두 포트가 열립니다. 클러스터 안에서
my-service:80으로 부르면 컨테이너 A로 가고my-service:9090으로 부르면 컨테이너 B로 갑니다.포트가 두 개 이상이면
name을 붙여야 합니다. 하나뿐일 때는 생략할 수 있습니다.포트는 겹치면 안 됩니다
같은 Pod 안에서 두 컨테이너가 같은 포트를 열 수는 없습니다. 포트 공간이 하나이기 때문입니다. 문서에도 그렇게 적혀 있습니다.
컨테이너 하나만 있을 때는 신경 쓸 일이 없다가, 둘이 되는 순간 생기는 제약입니다. 같은 이미지를 두 개 넣으면 둘 다 같은 포트를 열려고 해서 하나가 뜨지 못합니다.
번호 대신 이름을 붙이면 편합니다
Pod 쪽에서 포트에 이름을 붙이고 Service가 그 이름을 가리킬 수 있습니다. 제 실습 클러스터에 실제로 그렇게 쓰는 것이 있습니다.
Pod 쪽입니다.
[ { "containerPort": 9978, "name": "grpc-xds-agw" }, { "containerPort": 9093, "name": "health" }, { "containerPort": 9092, "name": "metrics" } ]그것을 가리키는 Service입니다.
[ { "name": "grpc-xds-agw", "port": 9978, "targetPort": "grpc-xds-agw" }, { "name": "health", "port": 9093, "targetPort": "health" }, { "name": "metrics", "port": 9092, "targetPort": "metrics" } ]targetPort가 숫자가 아니라 이름입니다. 이렇게 두면 나중에 앱이 포트 번호를 바꿔도 Service는 안 고쳐도 됩니다. 이름만 그대로면 됩니다.이 예는 컨테이너 하나가 포트를 세 개 연 경우인데 동작 원리는 컨테이너가 여러 개일 때와 같습니다. Service는 어차피 컨테이너를 보지 않고 포트만 보기 때문입니다.
Service를 하나로 할지 여러 개로 할지
둘 다 됩니다. 기준은 누가 부르느냐입니다.
예를 들어 웹은 밖에 열고 메트릭은 클러스터 안에서만 보게 하려면, 웹용 Service는
LoadBalancer로 메트릭용 Service는ClusterIP로 각각 둡니다. 같은 Pod를 가리키는 Service가 둘이어도 됩니다. Service는 라벨로 Pod를 고를 뿐이라 여러 Service가 같은 Pod를 가리켜도 문제가 없습니다.이 과정 앱은 어떤가
k8s/frontend-deployment.yaml과k8s/backend-deployment.yaml을 보시면 각 Pod에 컨테이너가 하나씩입니다. 그래서 이 과정에서는 위 상황을 만나지 않습니다.frontend Pod 안의 nginx가
/api요청을 backend로 넘기는데, 그건 같은 Pod 안 컨테이너끼리가 아니라 다른 Pod로 가는 것입니다. 그래서localhost가 아니라backend-service라는 Service 이름으로 부릅니다. 4회차에 두 Service를 만든 이유가 이것입니다.컨테이너를 여러 개 넣는 것은 주로 본체 옆에 도우미를 붙일 때입니다. 로그를 모아 보내는 것, 앞에서 트래픽을 받아 넘기는 것 같은 역할입니다. 본체와 생명주기를 같이해야 하고 같은 파일이나 네트워크를 봐야 할 때 한 Pod에 넣습니다. 그럴 이유가 없으면 Pod를 나누는 편이 낫습니다.
직접 확인해 보시기 바랍니다
컨테이너가 여러 개인 Pod에서는 명령에
-c로 어느 컨테이너인지 알려 줘야 합니다. 하나뿐일 때는 생략해도 됩니다.포트 세 개가 각각 어느 문인지는 #28에 있습니다.
이 글은 참고용입니다. 읽지 않아도 수업 진행에는 지장이 없습니다.