Kubernetes는 강력한 컨테이너 오케스트레이션 플랫폼이지만, 그 잠재력을 최대한 활용하기 위해서는 핵심 구성 요소를 이해하는 것이 중요하며, 그 중에서도 팟(pod)과 서비스(service)가 기본적인 역할을 합니다. 이 기사에서는 이들이 무엇인지, 그리고 Kubernetes 클러스터 내에서 실행되는 애플리케이션에 대한 접근을 노출하고 관리하기 위해 어떻게 함께 작동하는지에 대해 알아보겠습니다.
팟이란 무엇인가?
팟은 Kubernetes에서 생성하고 관리할 수 있는 가장 작은 배포 가능한 컴퓨팅 단위입니다.
팟을 생성하기 전에 Kubernetes 클러스터에서 사용 가능한 API 리소스를 확인해 봅시다. kubectl api-resources
명령어를 사용할 수 있습니다. 이 명령어는 Kubernetes API 서버에서 지원하는 API 리소스를 나열하며, 여기에는 짧은 이름, API 그룹, 네임스페이스 여부가 포함됩니다. 이는 특히 사용자 정의 리소스를 다루거나 새로운 Kubernetes 기능을 탐색할 때 클러스터의 기능을 이해하는 데 유용합니다. kubectl explain
명령어는 개별 리소스에 대한 자세한 정보를 제공하여 이를 보완합니다.
간단한 Nginx 컨테이너를 실행하는 팟을 위한 기본 팟 구성 파일을 생성해 봅시다.
파일 이름을 nginx-pod.yaml
로 생성합니다:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
사용된 용어에 대한 간단한 설명은 다음과 같습니다:
- apiVersion: v1: API 버전을 지정합니다.
- kind: Pod: 이 구성이 팟에 대한 것임을 나타냅니다.
- metadata:name: 팟의 이름입니다.
- 메타데이터: 레이블: Pod를 구성하고 선택하는 데 사용할 수 있는 키-값 쌍입니다.
- 스펙:컨테이너: Pod에서 실행될 컨테이너의 목록입니다.
- 스펙:컨테이너:이름: 컨테이너의 이름입니다.
- 스펙:컨테이너:이미지: 사용할 컨테이너 이미지입니다 (이 경우 최신 Nginx 이미지).
- 스펙:컨테이너:포트: 컨테이너에서 노출할 포트입니다.
구성 파일을 적용하고 Pod를 생성하려면 kubectl
을 사용하십시오:
kubectl apply -f nginx-pod.yaml
생성되었는지 확인하고 실행 중인 Pod의 상태를 확인하려면 다음을 실행하십시오:
kubectl get pods
다음과 유사한 출력이 표시되어야 합니다:
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 10s
다음으로 Pod를 삭제하십시오:
kubectl delete pod nginx-pod
다음과 유사한 출력이 표시되어야 합니다:
kubectl get pod
No resources found in default namespace.
서비스란 무엇인가요?
Kubernetes의 Nginx Pod에 서비스를 만들면 Nginx 애플리케이션을 노출하고 클러스터 내외에서 접근할 수 있게 됩니다. Nginx Pod에 서비스를 만드는 단계별 가이드는 다음과 같습니다.
이미 실행 중인 Nginx Pod가 있는지 확인하려면, 없는 경우 nginx-pod.yaml
이라는 YAML 파일을 만들어 주십시오:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Pod 구성을 적용하십시오:
nginx-service.yaml
파일을 생성하여 Service를 정의합니다.
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
다음 사항을 주의해야 합니다:
- selector: Nginx 팟과 일치하는 레이블 셀렉터입니다.
- app: nginx: Nginx 팟의 레이블과 일치해야 합니다.
- type: ClusterIP: Service의 유형입니다. ClusterIP는 클러스터 내에서만 Service에 접근할 수 있습니다. NodePort나 LoadBalancer를 사용하여 Service를 외부로 노출시킬 수도 있습니다.
kubectl
을 사용하여 Service 구성을 적용합니다:
kubectl apply -f nginx-service.yaml
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service ClusterIP 10.96.0.1 <none> 80/TCP 10s
Service가 ClusterIP 유형이므로 클러스터 내에서만 접근할 수 있습니다. 클러스터 외부에서 접근하려면 Service 유형을 NodePort나 LoadBalancer로 변경할 수 있습니다.
NodePort
를 사용하여 Service를 외부로 노출하려면 nginx-service.yaml
파일을 수정합니다:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30007 # Specify a node port in the range 30000-32767 (optional)
type: NodePort
업데이트된 Service 구성을 적용합니다:
kubectl apply -f nginx-service.yaml
이제 노드의 IP 주소와 노드 포트(예: http://<node-ip>:30007)를 사용하여 Nginx 애플리케이션에 액세스할 수 있습니다.
멀티 컨테이너 팟
단일 컨테이너를 포드당 사용하는 것은 최대의 세분화와 분리를 제공합니다. 그러나 때때로 여러 컨테이너를 단일 포드 내에 배포하는 것이 유익한 시나리오가 있습니다. 이러한 보조 컨테이너는 다양한 역할을 수행할 수 있습니다: 로깅을 처리하거나 기본 컨테이너를 보완하는 역할(사이드카 개념), 외부 시스템에 대한 프록시 역할(앰배서더 개념), 또는 데이터를 외부 형식에 맞게 수정하는 역할(어댑터 개념). 이러한 보조 컨테이너는 기본 컨테이너가 처리하지 않는 작업을 수행하여 기본 컨테이너를 보완합니다.
다음은 Nginx 서버를 실행하는 기본 컨테이너와 로깅을 처리하는 사이드카 역할을 하는 보조 컨테이너를 포함하는 Kubernetes 포드 구성의 예입니다. 사이드카 컨테이너는 Nginx 접근 로그를 tail하는 방법을 보여주기 위해 BusyBox와 같은 간단한 로깅 컨테이너를 사용합니다.
apiVersion: v1
kind: Pod
metadata:
name: nginx-with-logging-sidecar
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
- name: log-sidecar
image: busybox:latest
command: ["sh", "-c", "tail -f /var/log/nginx/access.log"]
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
volumes:
- name: shared-logs
emptyDir: {}
그 다음에는 다음을 수행합니다:
- YAML 구성을 파일에 저장합니다, 예:
nginx-with-logging-sidecar.yaml
. - 구성을 적용합니다:
kubectl:kubectl apply -f nginx-with-logging-sidecar.yaml
. - 포드가 실행 중인지 확인합니다:
kubectl get pods
. - 사이드카 컨테이너의 로그를 확인하여 Nginx 접근 로그를 확인합니다:
kubectl logs -f <pod-name> -c log-sidecar
.
이 단계를 따르면 기존 Pod를 삭제하고 새 구성을 적용하여 Nginx 컨테이너와 로깅을 위한 사이드카 컨테이너가 있는 Pod를 설정할 수 있습니다. 이를 통해 쿠버네티스 클러스터에서 새 구성이 활성화되고 실행되도록 할 수 있습니다.
쿠버네티스의 다중 컨테이너 Pod는 더 유연하고 효율적인 응용 프로그램 배포와 관리를 가능하게 합니다.
다중 컨테이너 Pod 패턴
사이드카 패턴
사이드카 컨테이너는 로깅, 구성 관리 또는 프록시와 같은 보조 기능을 제공하여 기본 응용 프로그램을 향상시킬 수 있습니다. 이 패턴은 주 컨테이너를 수정하지 않고도 기능을 확장하는 데 도움이 됩니다. 사이드카 컨테이너는 주 응용 프로그램 컨테이너로부터 로그를 수집하고 전달하여 로깅을 처리할 수 있습니다.
앰배서더 패턴
앰배서더 컨테이너는 프록시 역할을 하여 주 응용 프로그램과 외부 서비스 간의 통신을 관리합니다. 이를 통해 통합과 구성을 간단하게 할 수 있습니다. 앰배서더 컨테이너는 SSL 종료 또는 API 게이트웨이 기능을 처리할 수 있습니다.
앰배서더 패턴은 주 응용 프로그램과 외부 서비스 간의 통신을 관리하기 위해 사이드카 컨테이너를 사용하는 것을 포함합니다. 이 패턴은 프록시, 로드 밸런싱 또는 안전한 연결 관리와 같은 작업을 처리할 수 있어서 주 응용 프로그램 컨테이너로부터 복잡성을 추상화할 수 있습니다.
- 주 응용 프로그램 컨테이너: HTTP 요청을 수행하는 간단한 웹 서버
- 앰배서더 컨테이너: 외부 API로의 요청을 관리하기 위해 구성된 Envoy 프록시
apiVersion: v1
kind: Pod
metadata:
name: app-with-ambassador
spec:
containers:
- name: web-app
image: python:3.8-slim
command: ["python", "-m", "http.server", "8000"]
volumeMounts:
- name: config-volume
mountPath: /etc/envoy
- name: envoy-proxy
image: envoyproxy/envoy:v1.18.3
args: ["-c", "/etc/envoy/envoy.yaml"]
ports:
- containerPort: 8080
volumeMounts:
- name: config-volume
mountPath: /etc/envoy
volumes:
- name: config-volume
configMap:
name: envoy-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: envoy-config
data:
envoy.yaml: |
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: external_service
http_filters:
- name: envoy.filters.http.router
clusters:
- name: external_service
connect_timeout: 0.25s
type: LOGICAL_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: external_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: api.example.com
port_value: 80
이 예제는 쿠버네티스에서 앰배서더 패턴을 보여주며, Envoy 프록시가 기본 애플리케이션 컨테이너를 위한 외부 통신을 관리하는 중개자로 작용합니다. 이 패턴은 통신의 복잡성을 추상화하고 모듈성과 유지 관리성을 향상시키는 데 도움이 됩니다.
어댑터 패턴
어댑터 컨테이너는 기본 애플리케이션과 외부 시스템 간의 데이터를 수정하거나 변환하여 호환성과 통합을 보장합니다. 예를 들어, 어댑터 컨테이너는 로그 데이터를 외부 로깅 서비스의 요구 사항에 맞게 재포맷할 수 있습니다.
쿠버네티스의 어댑터 패턴은 사이드카 컨테이너를 사용하여 기본 애플리케이션 컨테이너와 외부 시스템 간의 데이터를 변환하는 것을 포함합니다. 이는 기본 애플리케이션이 외부 시스템이 제공하거나 요구하는 형식과 다른 특정 형식의 데이터를 요구할 때 유용할 수 있습니다.
예를 들어, 사용자 정의 형식으로 로그를 생성하는 기본 애플리케이션 컨테이너가 있다고 가정해 보겠습니다. 이러한 로그를 특정 표준 형식으로 요구하는 외부 로깅 서비스에 전송해야 합니다. 어댑터 컨테이너를 사용하여 로그 데이터를 외부 서비스에 전송하기 전에 필요한 형식으로 변환할 수 있습니다.
- 기본 애플리케이션 컨테이너: 사용자 정의 형식으로 로그를 작성하는 간단한 애플리케이션입니다.
- 어댑터 컨테이너: 사용자 정의 로그를 읽고, 이를 JSON 형식으로 변환하여 외부 로깅 서비스에 전송하는 컨테이너입니다.
apiVersion: v1
kind: Pod
metadata:
name: app-with-adapter
spec:
containers:
- name: log-writer
image: busybox
command: ["sh", "-c", "while true; do echo \"$(date) - Custom log entry\" >> /var/log/custom/app.log; sleep 5; done"]
volumeMounts:
- name: shared-logs
mountPath: /var/log/custom
- name: log-adapter
image: busybox
command: ["sh", "-c", "tail -f /var/log/custom/app.log | while read line; do echo \"$(echo $line | sed 's/ - / - {\"timestamp\": \"/;s/$/\"}/')\" >> /var/log/json/app.json; done"]
volumeMounts:
- name: shared-logs
mountPath: /var/log/custom
- name: json-logs
mountPath: /var/log/json
- name: log-sender
image: busybox
command: ["sh", "-c", "while true; do cat /var/log/json/app.json | grep -v '^$' | while read line; do echo \"Sending log to external service: $line\"; done; sleep 10; done"]
volumeMounts:
- name: json-logs
mountPath: /var/log/json
volumes:
- name: shared-logs
emptyDir: {}
- name: json-logs
emptyDir: {}
이 예시는 Kubernetes에서 어댑터 패턴을 보여주며, 어댑터 컨테이너가 기본 애플리케이션 컨테이너의 데이터를 외부 시스템에 전송하기 전에 필요한 형식으로 변환합니다. 이 패턴은 사이드카 컨테이너 내에서 데이터 형식 변환을 처리하여 애플리케이션과 외부 서비스의 통합을 돕습니다.
요약
요약하자면, 파드:
- Kubernetes에서 가장 작은 배포 단위입니다.
- 실행 중인 프로세스의 단일 인스턴스를 나타냅니다.
- 하나 이상의 컨테이너를 포함할 수 있습니다.
서비스:
- 파드에 접근하기 위한 안정적인 IP 주소와 DNS 이름을 제공합니다.
- 일련의 파드에 걸쳐 로드 밸런싱을 가능하게 합니다.
- 클러스터 내에서 서비스 검색을 용이하게 합니다.
Source:
https://dzone.com/articles/the-ultimate-guide-to-kubernetes-pods-and-services