가끔 보자, 하늘.

k8s 를 위한 기본 설정 + 사이드카 본문

개발 이야기/인프라 구축 및 운영

k8s 를 위한 기본 설정 + 사이드카

가온아 2025. 8. 19. 09:00

주요 쿠버네티스 리소스 설정 파일

리소스 종류 (Kind) apiVersion 설명 주요 spec 필드
Pod v1 쿠버네티스에서 실행되는 가장 작은 배포 단위. 하나 이상의 컨테이너를 포함합니다. containers: 파드에서 실행될 컨테이너 목록 (이미지, 포트, 환경 변수 등 설정)<br>volumes: 컨테이너가 사용할 수 있는 볼륨
Service v1 여러 파드에 대한 안정적인 네트워크 엔드포인트(고정 IP 주소와 DNS 이름)를 제공하여 파드 간 또는 외부와의 통신을 가능하게 합니다. selector: 서비스를 통해 노출할 파드를 선택하는 레이블<br>ports: 서비스가 노출할 포트와 대상 파드의 포트<br>type: 서비스 종류 (ClusterIP, NodePort, LoadBalancer, ExternalName)
Ingress networking.k8s.io/v1 클러스터 외부에서 내부 서비스로의 HTTP, HTTPS 요청을 관리하고 라우팅 규칙을 제공합니다. rules: 호스트 이름 및 경로 기반 라우팅 규칙<br>tls: TLS/SSL 인증서 설정
Deployment apps/v1 파드와 ReplicaSet에 대한 선언적 업데이트를 제공합니다. 배포, 롤백, 확장 등을 관리하는 데 사용됩니다. replicas: 실행할 파드의 개수<br>selector: 관리할 파드를 선택하는 레이블<br>template: 생성할 파드의 템플릿 (Pod spec과 유사)
ReplicaSet apps/v1 지정된 수의 파드 복제본이 항상 실행되도록 보장합니다. 일반적으로 Deployment에 의해 관리됩니다. replicas: 유지할 파드의 복제본 수<br>selector: 관리할 파드를 선택하는 레이블<br>template: 생성할 파드의 템플릿
ConfigMap v1 설정 데이터를 키-값 쌍으로 저장하여 파드에서 사용할 수 있도록 합니다. 설정과 코드를 분리하는 데 사용됩니다. data: 일반 텍스트 형식의 설정 데이터<br>binaryData: 바이너리 형식의 설정 데이터
Secret v1 비밀번호, API 키, 인증서와 같은 민감한 정보를 저장하고 관리합니다. 데이터는 Base64로 인코딩되어 저장됩니다. data: Base64로 인코딩된 민감한 데이터<br>type: 시크릿의 종류 (Opaque, kubernetes.io/tls 등)
PersistentVolume (PV) v1 관리자가 프로비저닝한 클러스터의 스토리지 조각입니다. 파드가 데이터를 영구적으로 저장할 수 있도록 합니다. capacity: 볼륨의 크기<br>accessModes: 접근 모드 (ReadWriteOnce, ReadOnlyMany 등)<br>persistentVolumeReclaimPolicy: 볼륨 회수 정책
PersistentVolumeClaim (PVC) v1 사용자가 PersistentVolume에 대한 스토리지 요청입니다. 파드는 PVC를 통해 PV를 사용합니다. accessModes: 요청하는 접근 모드<br>resources: 요청하는 스토리지의 크기<br>storageClassName: 특정 스토리지 클래스를 요청
Namespace v1 단일 클러스터 내에서 리소스를 논리적으로 그룹화하고 격리하는 데 사용됩니다. - spec 필드는 일반적으로 비어 있습니다.
Sidecar (패턴) - 사이드카는 별도의 리소스(kind)가 아니라, 하나의 파드 안에 메인 컨테이너와 함께 보조 컨테이너를 추가하는 디자인 패턴입니다. 마치 오토바이 옆에 붙어있는 사이드카처럼, 메인 애플리케이션의 기능을 확장하거나 보조합니다. containers 필드 아래에 메인 컨테이너와 함께 사이드카 컨테이너를 나란히 정의합니다.
 

예시 1) 서비스 설정

서비스는 파드(Pod)들에게 안정적인 네트워크 엔드포인트를 제공합니다. 서비스의 종류(type)에 따라 클러스터 내부에서만 접근 가능하게 하거나 외부로 노출할 수 있습니다.

아래는 my-service라는 이름의 간단한 서비스 매니페스트 예시입니다. 이 서비스는 app: my-app 레이블을 가진 파드들을 찾아내고, 클러스터 내부의 80번 포트로 들어오는 요청을 파드의 9376번 포트로 전달합니다.

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

 

서비스와 파드의 연동 관계

서비스는 selector에 지정된 라벨(app: my-app)을 가진 모든 파드를 찾아내고, 이들을 하나의 그룹으로 묶어 트래픽을 분산합니다. 즉, 서비스는 라벨을 통해 어떤 파드에게 요청을 전달해야 하는지 식별합니다.

  • 서비스 (my-service.yaml): selector: app: my-app를 통해 대상을 찾습니다.
  • 파드 (my-app-pod.yaml): metadata.labels.app: my-app을 가지고 있어 서비스의 대상이 됩니다.

예시 2) pod와 연동하는 서비스 (Service) 설정 예시

이 서비스는 app: my-app 라벨을 가진 파드를 찾아, 서비스의 80번 포트로 들어온 요청을 파드의 9376번 포트로 전달합니다.

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

예시 3) 파드(Pod) 설정

아래 파드는 metadata 섹션에 app: my-app 이라는 라벨을 가지고 있으므로 위의 my-service에 자동으로 연결됩니다. 또한, 컨테이너의 포트를 9376으로 설정하여 서비스의 targetPort와 일치시켰습니다.

apiVersion: v1
kind: Pod
metadata:
  name: my-app-pod
  # 서비스의 selector와 일치하는 라벨
  labels:
    app: my-app
spec:
  containers:
  - name: my-app-container
    # 간단한 웹페이지를 서빙하는 예시 이미지
    image: nginxdemos/hello
    ports:
      # 서비스의 targetPort와 일치하는 컨테이너 포트
      - containerPort: 9376

 

예시 4) 인그레스(Ingress) 설정

인그레스는 클러스터 외부에서 내부 서비스로 들어오는 HTTP, HTTPS 요청을 관리하는 API 객체입니다. 주로 도메인 주소나 경로에 따라 요청을 다른 서비스로 라우팅하는 역할을 합니다. 인그레스를 사용하기 위해서는 인그레스 컨트롤러(Ingress Controller, 예: NGINX Ingress Controller)가 클러스터에 먼저 설치되어 있어야 합니다.

아래는 example.com이라는 호스트로 들어오는 요청을 경로에 따라 다른 서비스로 전달하는 인그레스 매니페스트 예시입니다.

  • example.com/ 요청은 service-a로 전달됩니다.
  • example.com/api 요청은 service-b로 전달됩니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: "example.com"
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service-a
            port:
              number: 80
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: service-b
            port:
              number: 8080

사이드카(Sidecar) 상세 설명 및 설정 예시

설명

사이드카 패턴은 메인 애플리케이션 컨테이너의 핵심 기능에 영향을 주지 않으면서, 부가적인 기능을 분리하여 별도의 컨테이너로 추가하는 방식입니다. 이 두 컨테이너는 하나의 파드(Pod) 안에서 함께 실행되며, 네트워크와 스토리지(볼륨)를 공유합니다. 이로 인해 localhost를 통해 통신할 수 있고 같은 파일에 접근할 수 있습니다.

주요 장점:

  • 관심사 분리: 로깅, 모니터링, 보안, 프록시 등의 부가 기능을 메인 애플리케이션 코드에서 분리하여 개발 및 관리를 용이하게 합니다.
  • 재사용성: 하나의 사이드카 컨테이너를 여러 다른 종류의 메인 애플리케이션에 동일하게 적용할 수 있습니다.
  • 독립적인 업데이트: 메인 애플리케이션의 중단 없이 사이드카 컨테이너만 독립적으로 업데이트하고 관리할 수 있습니다.

주요 사용 사례

  • 로깅 에이전트: 메인 컨테이너가 파일에 로그를 남기면, 사이드카 컨테이너(예: Fluentd, Logstash)가 이 로그를 수집하여 중앙 로그 서버로 전송합니다.
  • 서비스 메시 프록시: 서비스 메시(예: Istio, Linkerd)의 프록시를 사이드카로 실행하여 서비스 간 통신, 트래픽 관리, 보안 정책 적용 등을 처리합니다.
  • 모니터링: 메인 애플리케이션의 메트릭(metric)을 수집하여 모니터링 시스템(예: Prometheus)으로 내보내는 역할을 합니다.
  • 보안: 외부와의 통신을 위한 TLS 종료(TLS termination)나 인증/인가 처리를 사이드카에서 담당합니다.

설정 예시

아래 예시는 웹 서버(메인 컨테이너)와 로그 수집기(사이드카 컨테이너)가 하나의 파드로 구성된 경우입니다.

  • nginx 컨테이너: 메인 애플리케이션으로, 웹 서버 역할을 하며 /var/log/nginx 디렉토리에 로그 파일을 생성합니다.
  • sidecar-container: 사이드카로, busybox 이미지를 사용하여 10초마다 nginx가 생성한 로그 파일을 읽어 콘솔에 출력합니다.

두 컨테이너는 log-volume이라는 볼륨을 공유하기 때문에, sidecar-container가 nginx 컨테이너의 파일 시스템에 접근할 수 있습니다.

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-sidecar
spec:
  # 파드 내 컨테이너 목록
  containers:
    # 1. 메인 애플리케이션 컨테이너
    - name: main-app-container
      image: nginx
      ports:
        - containerPort: 80
      # 공유할 볼륨을 컨테이너에 마운트
      volumeMounts:
        - name: log-volume
          mountPath: /var/log/nginx

    # 2. 사이드카 컨테이너
    - name: sidecar-container
      image: busybox
      # 10초마다 로그 파일을 읽어서 출력하는 명령어
      command: ["/bin/sh", "-c", "while true; do cat /var/log/access.log; sleep 10; done"]
      # 공유할 볼륨을 컨테이너에 마운트
      volumeMounts:
        - name: log-volume
          mountPath: /var/log

  # 파드 내에서 공유될 볼륨 정의
  volumes:
    - name: log-volume
      # 빈 디렉토리 형태의 볼륨을 생성
      emptyDir: {}

 

반응형