본문 바로가기
WIKI 기술 지식 베이스

Kubernetes deployment customization

원문 보기 위키 갱신

출처: 문서

본문

Kubernetes 배포 커스터마이징

OpenSearch 자체를 설정하는 것 외에도, 오퍼레이터가 OpenSearch와 OpenSearch Dashboards 파드를 배포하는 방식도 커스터마이징할 수 있어요.

데이터 영속성

기본적으로 오퍼레이터는 기본 Storage Class의 영구 스토리지를 사용해 OpenSearch 노드 풀을 생성해요. 이 동작은 노드 풀별로 변경할 수 있어요. 다른 스토리지 클래스와 접근 모드를 지정하거나, hostPath 또는 emptyDir 스토리지를 설정할 수도 있어요.

사용 가능한 스토리지 옵션은 다음과 같아요:

Persistent Volume Claim (PVC)

기본 옵션은 PVC를 사용하는 영구 스토리지예요. 필요하다면 storageClass, annotations, labels를 명시적으로 정의할 수 있어요:

nodePools:
  - component: masters
    replicas: 3
    diskSize: "30Gi"
    roles:
      - "data"
      - "master"
    persistence:
      pvc:
        storageClass: mystorageclass # Set the name of the storage class to be used
        accessModes: # You can change the accessMode
          - ReadWriteOnce
        annotations: # You can add annotations
          test.io/crypt-key-id: "your-kms-key-id"
        labels: # You can add labels
          team: "backend-data"

{% include copy.html %}

emptyDir

영구 스토리지를 사용하고 싶지 않다면 emptyDir 옵션을 사용할 수 있어요. 다만 이 옵션은 데이터 손실로 이어질 수 있으니, 테스트용이나 다른 방식으로 영속화된 데이터에만 사용하는 게 좋아요.

nodePools:
  - component: masters
    replicas: 3
    diskSize: "30Gi"
    roles:
      - "data"
      - "master"
    persistence:
      emptyDir: {} # This configures emptyDir

{% include copy.html %}

emptyDir를 사용한다면 spec.general.drainDataNodes를 true로 설정하세요. 이렇게 하면 롤링 업그레이드나 재시작 작업을 수행하기 전에 샤드가 파드에서 빠져나가는 게 보장돼요.

hostPath

마지막 옵션으로 hostPath를 사용할 수 있어요. 하지만 hostPath 사용은 강력히 권장되지 않아요. 기본적으로 오퍼레이터는 여러 파드가 같은 노드에 스케줄링되지 않도록 파드 안티 어피니티를 적용하는데, 이게 hostPath를 사용할 때 도움이 돼요. 다만 더 엄격한 제어가 필요하다면, 여러 파드가 같은 Kubernetes 호스트에 스케줄링되지 않도록 노드 풀에 명시적인 어피니티 규칙을 설정하세요.

nodePools:
  - component: masters
    replicas: 3
    diskSize: "30Gi"
    roles:
      - "data"
      - "master"
    persistence:
      hostPath:
        path: "/var/opensearch" # Define the path on the host here

{% include copy.html %}

파드와 컨테이너의 보안 컨텍스트

OpenSearch 파드와 OpenSearch Dashboards 파드에 보안 컨텍스트를 설정해서 권한과 접근 제어 설정을 정의할 수 있어요. 파드에 보안 설정을 지정하려면 podSecurityContext 필드를 포함하고, 컨테이너에는 securityContext 필드를 포함하세요.

구조는 OpenSearch 파드(spec.general)와 OpenSearch Dashboards 파드(spec.dashboards) 모두 동일해요:

spec:
  general:
    podSecurityContext:
      runAsUser: 1000
      runAsGroup: 1000
      runAsNonRoot: true
    securityContext:
      allowPrivilegeEscalation: false
      privileged: false
  dashboards:
    podSecurityContext:
      fsGroup: 1000
      runAsNonRoot: true
    securityContext:
      capabilities:
        drop:
          - ALL
      privileged: false

{% include copy.html %}

OpenSearch 파드는 기본적으로 볼륨을 구성하기 위해 init 컨테이너를 실행해요. 이 컨테이너는 root 권한으로 실행되어야 하고 정의된 securityContext를 사용하지 않아요. Kubernetes 환경에서 root 사용자 컨테이너를 허용하지 않는다면 이 init 헬퍼를 비활성화하세요. 이런 상황에서는 general.setVMMaxMapCount를 false로 설정하세요. 이 기능도 root로 init 컨테이너를 실행하기 때문이에요.

초기 클러스터 셋업 중에 시작되는 부트스트랩 파드는 OpenSearch 파드와 동일한 파드 securityContext를 사용해요 (init 컨테이너에 대해서도 동일한 제한이 적용돼요). {: .note}

부트스트랩 파드는 초기화 중 재시작이 발생해도 클러스터 상태를 유지할 수 있도록 영구 스토리지(PVC)를 사용해요. 이 덕분에 보안 설정 업데이트 작업이 완료된 후 부트스트랩 파드가 재시작하더라도 클러스터 형성 실패를 예방할 수 있어요. 부트스트랩 PVC는 부트스트랩 파드와 함께 자동으로 생성되고 삭제돼요.

OpenSearch 노드의 레이블 또는 어노테이션

노드 풀 설정에 추가 레이블이나 어노테이션을 붙일 수 있어요. 서비스 메시 같은 다른 애플리케이션과의 통합이나 Prometheus 스크레이프 엔드포인트 설정에 유용해요.

또한 spec.general.annotations 필드를 사용해 어노테이션을 전역으로 설정할 수도 있어요. 이 어노테이션은 노드 풀뿐만 아니라 Kubernetes 서비스에도 적용돼요.

spec:
  nodePools:
    - component: masters
      replicas: 3
      diskSize: "5Gi"
      labels: # Add any extra labels as key-value pairs here
        someLabelKey: someLabelValue
      annotations: # Add any extra annotations as key-value pairs here
        someAnnotationKey: someAnnotationValue
      nodeSelector:
      resources:
        requests:
          memory: "2Gi"
          cpu: "500m"
        limits:
          memory: "2Gi"
          cpu: "500m"
      roles:
        - "data"
        - "master"

{% include copy.html %}

정의된 어노테이션과 레이블은 노드 풀 파드에 직접 추가돼요.

OpenSearch Dashboards 배포에 레이블 또는 어노테이션 추가하기

OpenSearch Dashboards 파드 스펙에 레이블이나 어노테이션을 추가할 수 있어요. OpenSearch Dashboards를 서비스 메시의 일부로 만들거나 레이블이나 어노테이션에 의존하는 다른 애플리케이션과 통합하고 싶을 때 유용해요.

spec:
  dashboards:
    enable: true
    version: 3.0.0
    replicas: 1
    labels: # Add any extra labels as key-value pairs here
      someLabelKey: someLabelValue
    annotations: # Add any extra annotations as key-value pairs here
      someAnnotationKey: someAnnotationValue

{% include copy.html %}

정의된 어노테이션과 레이블은 OpenSearch Dashboards 파드에 직접 추가돼요.

OpenSearch 노드의 Priority class

priority class 이름을 지정해서 OpenSearch 노드가 PriorityClass를 사용하도록 설정할 수 있어요. 이렇게 하면 OpenSearch 노드가 원치 않는 축출(eviction)을 당하는 것을 예방하는 데 도움이 돼요.

spec:
  nodePools:
    - component: masters
      replicas: 3
      diskSize: "5Gi"
      priorityClassName: somePriorityClassName
      resources:
        requests:
          memory: "2Gi"
          cpu: "500m"
        limits:
          memory: "2Gi"
          cpu: "500m"
      roles:
        - "master"

{% include copy.html %}

파드 어피니티

기본적으로 오퍼레이터는 같은 OpenSearch 클러스터의 여러 파드가 같은 노드에 스케줄링되지 않도록 파드 안티 어피니티 규칙을 적용해요. 이를 통해 단일 노드 장애로 여러 파드가 함께 영향을 받을 위험을 줄여 고가용성을 높일 수 있어요.

기본 안티 어피니티는 PreferredDuringSchedulingIgnoredDuringExecution을 사용해요. 이건 소프트 선호 설정이라서 다른 노드가 없으면 스케줄링을 막지는 않지만, 가능하면 파드를 여러 노드에 분산하는 쪽을 선호해요.

노드 풀, 부트스트랩, 또는 OpenSearch Dashboards 설정에서 affinity 필드를 명시적으로 설정하면 이 기본 동작을 재정의할 수 있어요:

spec:
  nodePools:
    - component: masters
      replicas: 3
      diskSize: "30Gi"
      roles:
        - "master"
        - "data"
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchLabels:
                  opensearch.org/opensearch-cluster: my-cluster
              topologyKey: kubernetes.io/hostname
  bootstrap:
    affinity:
      podAntiAffinity:
        preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchLabels:
                  opensearch.org/opensearch-cluster: my-cluster
              topologyKey: kubernetes.io/hostname
  dashboards:
    enable: true
    affinity:
      podAffinity:
        preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchLabels:
                  app: opensearch-dashboards
              topologyKey: kubernetes.io/zone

{% include copy.html %}

명시적인 affinity를 설정하면 기본 안티 어피니티 동작이 완전히 대체돼요. 안티 어피니티를 완전히 비활성화하려면 affinity: {}로 설정하세요.

사이드카 컨테이너

같은 파드 안에서 OpenSearch와 함께 추가 사이드카 컨테이너를 배포할 수 있어요. 로그 전송, 모니터링 에이전트, 또는 OpenSearch 노드와 함께 실행되어야 하는 다른 보조 서비스에 유용해요.

spec:
  nodePools:
    - component: masters
      replicas: 3
      diskSize: "30Gi"
      resources:
        requests:
          memory: "2Gi"
          cpu: "500m"
        limits:
          memory: "2Gi"
          cpu: "500m"
      roles:
        - "master"
        - "data"
      sidecarContainers:
        - name: log-shipper
          image: fluent/fluent-bit:latest
          resources:
            requests:
              memory: "64Mi"
              cpu: "100m"
            limits:
              memory: "128Mi"
              cpu: "200m"
          volumeMounts:
            - name: varlog
              mountPath: /var/log
        - name: monitoring-agent
          image: prometheus/node-exporter:latest
          ports:
            - containerPort: 9100
              name: metrics

{% include copy.html %}

사이드카 컨테이너는 같은 파드에서 실행되기 때문에 OpenSearch 컨테이너와 동일한 네트워크 네임스페이스와 스토리지 볼륨을 공유해요.

추가 볼륨

OpenSearch 파드에 추가 볼륨을 마운트해서 추가 설정(예: 플러그인 설정 파일)을 제공할 수 있어요. 지원되는 볼륨 타입에는 ConfigMap, Secret, emptyDir, projected 볼륨, CSI 볼륨이 있어요.

spec.general.additionalVolumes 또는 spec.dashboards.additionalVolumes에 추가 볼륨 배열을 제공하세요:

spec:
  general:
    additionalVolumes:
      - name: example-configmap
        path: /path/to/mount/volume
        #subPath: mykey # Add this to mount only a specific key of the configmap/secret
        configMap:
          name: config-map-name
        restartPods: true # Set this to true to restart the pods when the content of the configMap changes
      - name: temp
        path: /tmp
        emptyDir: {}
      - name: example-csi-volume
        path: /path/to/mount/volume
        #subPath: "subpath" # Add this to mount the CSI volume at a specific subpath
        csi:
          driver: csi-driver-name
          readOnly: true
          volumeAttributes:
            secretProviderClass: example-secret-provider-class
      - name: example-projected-volume
        path: /path/to/mount/volume
        projected:
          sources:
            - serviceAccountToken:
                path: "token"
      - name: example-persistentvolumeclaim-volume
        path: /path/to/mount/volume
        persistentVolumeClaim:
          claimName: claim-name
      - name: nfs-volume
        path: /mnt/backups/opensearch
        nfs:
          server: 192.168.1.233
          path: /export/backups/opensearch
          readOnly: false # Optional, defaults to false
  dashboards:
    additionalVolumes:
      - name: example-secret
        path: /path/to/mount/volume
        secret:
          secretName: secret-name

{% include copy.html %}

NFS 볼륨 지원

NFS 볼륨은 외부 프로비저너나 CSI 드라이버 없이도 OpenSearch 파드에 직접 마운트할 수 있어요. NFS 공유에 저장된 스냅샷 리포지토리에 특히 유용해요. NFS 볼륨을 설정하려면 필수 파라미터인 server와 path를 nfs 필드에 지정하세요:

spec:
  general:
    additionalVolumes:
      - name: nfs-backups
        path: /mnt/backups/opensearch
        nfs:
          server: 192.168.1.233
          path: /export/backups/opensearch
          readOnly: false # Optional, defaults to false

{% include copy.html %}

이건 스냅샷 리포지토리 설정과 조합할 수 있어요:

spec:
  general:
    additionalVolumes:
      - name: nfs-backups
        path: /mnt/backups/opensearch
        nfs:
          server: 192.168.1.233
          path: /export/backups/opensearch
    snapshotRepositories:
      - name: nfs-repository
        type: fs
        settings:
          location: /mnt/backups/opensearch

{% include copy.html %}

오퍼레이터는 정의된 볼륨을 OpenSearch 클러스터의 모든 파드에 추가해요. 현재는 노드 풀(nodePools)별로 이를 정의할 수는 없어요.

파드에 환경 변수 추가하기

OpenSearch 파드와 OpenSearch Dashboards 파드에 자체 환경 변수를 추가할 수 있어요. 값은 문자열 리터럴로 제공하거나 secret 또는 ConfigMap에서 마운트해서 제공할 수 있어요.

구조는 OpenSearch와 OpenSearch Dashboards 모두 동일해요:

spec:
  dashboards:
    env:
      - name: MY_ENV_VAR
        value: "myvalue"
      - name: MY_SECRET_VAR
        valueFrom:
          secretKeyRef:
            name: my-secret
            key: some_key
      - name: MY_CONFIGMAP_VAR
        valueFrom:
          configMapKeyRef:
            name: my-configmap
            key: some_key
  nodePools:
    - component: nodes
      env:
        - name: MY_ENV_VAR
          value: "myvalue"
        # The other options are supported here as well.

{% include copy.html %}

커스텀 클러스터 도메인 이름

Kubernetes 클러스터가 커스텀 도메인 이름으로 설정되어 있다면(기본값은 cluster.local), 내부 라우팅이 제대로 동작하도록 오퍼레이터를 그에 맞게 설정해야 해요. Helm chart values에서 manager.dnsBase를 설정하세요.

manager:
  # ...
  dnsBase: custom.domain

{% include copy.html %}

커스텀 init 헬퍼

클러스터 초기화 중에 오퍼레이터는 init 컨테이너를 헬퍼로 사용해요. 이 컨테이너에는 busybox 이미지가 사용돼요 (정확히는 docker.io/busybox:latest). 오프라인 환경에서 작업 중이라 클러스터가 레지스트리에 접근할 수 없거나 이미지를 커스터마이징하고 싶다면, 클러스터 spec에 initHelper 이미지를 지정해서 사용되는 이미지를 재정의할 수 있어요:

spec:
  initHelper:
    # You can either only specify the version
    version: "1.27.2-buildcustom"
    # Or specify a totally different image
    image: "mycustomrepo.cr/mycustombusybox:myversion"
    # Additionally you can define the imagePullPolicy
    imagePullPolicy: IfNotPresent
    # and imagePullSecrets if needed
    imagePullSecrets:
      - name: docker-pull-secret

{% include copy.html %}

init 컨테이너 리소스 편집하기

init 컨테이너는 리소스 제한 없이 실행되지만, YAML 정의에 resources 섹션을 추가하면 리소스 requests와 limits를 지정할 수 있어요. 적절한 리소스 제한을 설정하면 init 컨테이너에 할당되는 CPU와 메모리 양을 조절할 수 있고, 이는 init 컨테이너가 다른 컨테이너의 리소스를 잠식하지 않도록 하는 데 도움이 돼요.

spec:
  initHelper:
    resources:
      requests:
        memory: "128Mi"
        cpu: "250m"
      limits:
        memory: "512Mi"
        cpu: "500m"

{% include copy.html %}

init 헬퍼 비활성화하기

어떤 경우에는 chmod init 컨테이너를 피하고 싶을 수 있어요 (예: OpenShift에서, 또는 클러스터가 root로 실행되는 컨테이너를 차단하는 경우). values.yaml에 다음을 추가하면 비활성화할 수 있어요:

manager:
  extraEnv:
    - name: SKIP_INIT_CONTAINER
      value: "true"

{% include copy.html %}

PodDisruptionBudget

PDB(Pod Disruption Budget)는 유지보수나 예기치 않은 이벤트 중 허용 가능한 중단 수준을 정의해서 애플리케이션의 고가용성을 보장하는 데 도움을 주는 Kubernetes 리소스예요. 원하는 서비스 수준을 유지하기 위해 최소한으로 가용 상태를 유지해야 하는 파드 수를 지정해요. PDB 정의는 노드 풀(nodePools)마다 개별적으로 작성해요. PDB를 설정하려면 minAvailable 또는 maxUnavailable 중 하나를 제공하세요. 둘 다 함께 제공할 수는 없어요.

apiVersion: opensearch.org/v1
kind: OpenSearchCluster
---
spec:
  nodePools:
    - component: masters
      replicas: 3
      diskSize: "30Gi"
      pdb:
        enable: true
        minAvailable: 3
    - component: datas
      replicas: 7
      diskSize: "100Gi"
      pdb:
        enable: true
        maxUnavailable: 2

{% include copy.html %}

OpenSearch Dashboards 노출하기

Kubernetes 클러스터 외부의 사용자나 서비스가 클러스터의 OpenSearch Dashboards 인스턴스를 사용할 수 있게 하려면, ingress를 사용하는 게 권장돼요.

간단한 예시예요:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: opensearch-dashboards
  namespace: default
spec:
  tls:
    - hosts:
        - dashboards.my.company
  rules:
    - host: dashboards.my.company
      http:
        paths:
          - backend:
              service:
                name: my-cluster-dashboards
                port:
                  number: 5601
            path: "/(.*)"
            pathType: ImplementationSpecific

{% include copy.html %}

OpenSearch Dashboards에서 HTTPS를 활성화했다면, ingress 컨트롤러가 내부적으로 HTTPS 연결을 사용하도록 지시하세요. 이 설정 방법은 사용하는 컨트롤러마다 달라요 (예: nginx-ingress 또는 traefik). {: .note}

OpenSearch Dashboards Kubernetes 서비스 설정하기

오퍼레이터가 OpenSearch Dashboards 배포를 위해 생성하는 Kubernetes Service 오브젝트를 커스터마이징할 수 있어요.

지원되는 Service 타입:

  • ClusterIP (기본값)
  • NodePort
  • LoadBalancer

LoadBalancer 타입을 사용할 때는 선택적으로 로드 밸런서 소스 범위를 설정할 수 있어요.

apiVersion: opensearch.org/v1
kind: OpenSearchCluster
---
spec:
  dashboards:
    service:
      type: LoadBalancer # Set one of the supported types
      loadBalancerSourceRanges: "10.0.0.0/24, 192.168.0.0/24" # Optional, add source ranges for a load balancer

{% include copy.html %}

OpenSearch 클러스터 REST API 노출하기

OpenSearch의 REST API를 Kubernetes 클러스터 외부로 노출하려면, ingress를 사용하는 게 권장돼요. 내부적으로는 자체 서명 인증서를 사용하고(오퍼레이터가 생성하게 할 수 있어요), ingress에서는 신뢰할 수 있는 CA가 발급한 인증서(예: Let's Encrypt 또는 사내 CA)를 사용하게 하세요. 이렇게 하면 OpenSearch 클러스터에 커스텀 인증서를 제공하는 번거로움은 없으면서도 사용자에게는 유효한 인증서가 보여요.

프로브 타임아웃과 임계값 커스터마이징하기

임계값에 도달하기 전에 클러스터 노드가 시작되지 않아 파드가 재시작된다면, 필요에 맞게 노드별로 타임아웃과 임계값을 설정할 수 있어요.

apiVersion: opensearch.org/v1
kind: OpenSearchCluster
---
spec:
  nodePools:
    - component: masters
      replicas: 3
      diskSize: "30Gi"
      probes:
        liveness:
          initialDelaySeconds: 10
          periodSeconds: 20
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 10
        startup:
          initialDelaySeconds: 10
          periodSeconds: 20
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 10
        readiness:
          initialDelaySeconds: 60
          periodSeconds: 30
          timeoutSeconds: 30
          successThreshold: 1
          failureThreshold: 5

{% include copy.html %}

startup 및 readiness 프로브 커맨드 커스터마이징하기

liveness 프로브는 TCP 체크인 반면, startup과 readiness 프로브는 cURL을 사용해 OpenSearch API를 호출해요.

startup 또는 readiness 프로브 커맨드를 커스터마이징해야 한다면, 다음 예시처럼 재정의할 수 있어요:

apiVersion: opensearch.org/v1
kind: OpenSearchCluster
...
spec:
  nodePools:
    - component: masters
      ...
      probes:
        startup:
          command:
            - echo
            - "Hello, World!"
        readiness:
          command:
            - echo
            - "Hello, World!"

{% include copy.html %}

리소스 limits와 requests 설정하기

앞선 섹션에서 노드 풀의 리소스 요구 사항을 지정하는 방법을 설명했는데, 그 외에도 더 고급 사용 사례를 위해 오퍼레이터가 생성하는 모든 엔티티에 리소스를 지정할 수 있어요.

오퍼레이터는 init 컨테이너를 사용하는 jobs, stateful sets, replica sets 같은 리소스를 통해 많은 파드를 생성해요. 다음 설정을 사용하면 모든 init 컨테이너에 대한 기본 resources 설정을 지정할 수 있어요.

apiVersion: opensearch.org/v1
kind: OpenSearchCluster
---
spec:
  initHelper:
    resources:
      requests:
        memory: "50Mi"
        cpu: "50m"
      limits:
        memory: "200Mi"
        cpu: "200m"

{% include copy.html %}

다음 예시처럼 보안 업데이트 작업의 리소스도 설정할 수 있어요.

apiVersion: opensearch.org/v1
kind: OpenSearchCluster
---
spec:
  security:
    config:
      updateJob:
        resources:
          limits:
            cpu: "100m"
            memory: "100Mi"
          requests:
            cpu: "100m"
            memory: "100Mi"

{% include copy.html %}

여기 제공된 예시는 실제 리소스 요구 사항을 반영한 게 아니에요. 실제 필요에 맞게 리소스를 적절히 조정하려면 추가 테스트를 진행해야 할 수 있어요. {: .note}

더 알아보기 (Learn more)