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}