예시: StatefulSet으로 Cassandra 배포하기
예시: StatefulSet으로 Cassandra 배포하기
이 튜토리얼은 Kubernetes에서 Apache Cassandra를 실행하는 방법을 보여줘요. Cassandra는 데이터베이스로, 데이터 내구성(애플리케이션 상태)을 제공하기 위해 영구 스토리지가 필요해요. 이 예시에서 커스텀 Cassandra seed provider가 데이터베이스가 Cassandra 클러스터에 새 인스턴스가 합류할 때 그것을 발견하게 해줘요.
StatefulSet은 유상태(stateful) 애플리케이션을 Kubernetes 클러스터에 배포하는 것을 더 쉽게 만들어요. 이 튜토리얼에서 사용된 기능에 대한 더 많은 정보는 StatefulSet을 참고해요.
Cassandra와 Kubernetes는 둘 다 클러스터의 구성원을 가리킬 때 node라는 용어를 사용해요. 이 튜토리얼에서 StatefulSet에 속한 파드는 Cassandra 노드이며, Cassandra 클러스터(ring이라고 함)의 구성원이에요. 그 파드들이 Kubernetes 클러스터에서 실행될 때, Kubernetes 컨트롤 플레인은 그 파드들을 Kubernetes 노드에 스케줄링해요.
Cassandra 노드가 시작되면 seed 목록을 사용해 ring의 다른 노드 발견을 부트스트랩해요. 이 튜토리얼은 새 Cassandra 파드가 Kubernetes 클러스터 안에 나타날 때 데이터베이스가 그것을 발견하게 하는 커스텀 Cassandra seed provider를 배포해요.
출처: 문서
본문
목표 (Objectives)
- Cassandra 헤드리스 서비스 생성·검증
- StatefulSet으로 Cassandra ring 만들기
- StatefulSet 검증하기
- StatefulSet 수정하기
- StatefulSet과 그 파드 삭제하기
시작하기 전에
Kubernetes 클러스터가 있어야 하고 kubectl 명령줄 도구가 클러스터와 통신하도록 구성되어 있어야 해요. 이 튜토리얼은 컨트롤 플레인 호스트가 아닌 노드가 최소 두 개 있는 클러스터에서 실행하는 것을 권장해요. 아직 클러스터가 없다면 minikube를 이용해 만들거나, 아래 Kubernetes 플레이그라운드 중 하나를 사용할 수 있어요.
이 튜토리얼을 완료하려면 파드, 서비스, StatefulSet에 대한 기본적인 친숙함이 있어야 해요.
추가 Minikube 설정 지침
Minikube는 기본적으로 2048MB 메모리와 2 CPU로 동작해요. 기본 리소스 구성으로 Minikube를 실행하면 이 튜토리얼 중 리소스 부족 오류가 발생해요. 이런 오류를 피하려면 다음 설정으로 Minikube를 시작해요.
minikube start --memory 5120 --cpus=4
Cassandra용 헤드리스 서비스 생성
Kubernetes에서 서비스는 같은 작업을 수행하는 파드 집합을 설명해요.
다음 서비스는 Cassandra 파드와 클러스터 안의 클라이언트 사이의 DNS 조회에 사용돼요.
apiVersion: v1
kind: Service
metadata:
labels:
app: cassandra
name: cassandra
spec:
clusterIP: None
ports:
- port: 9042
selector:
app: cassandra
cassandra-service.yaml 파일에서 모든 Cassandra StatefulSet 구성원을 추적하는 서비스를 만들어요.
kubectl apply -f https://k8s.io/examples/application/cassandra/cassandra-service.yaml
검증 (선택 사항)
Cassandra 서비스를 가져와요.
kubectl get svc cassandra
응답은 다음과 같아요.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cassandra ClusterIP None <none> 9042/TCP 45s
cassandra라는 이름의 서비스가 보이지 않는다면 생성이 실패한 것이에요. 흔한 문제 해결법은 서비스 디버깅을 읽어보세요.
StatefulSet으로 Cassandra ring 만들기
아래 포함된 StatefulSet 매니페스트는 세 개의 파드로 구성된 Cassandra ring을 만들어요.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: cassandra
labels:
app: cassandra
spec:
serviceName: cassandra
replicas: 3
selector:
matchLabels:
app: cassandra
template:
metadata:
labels:
app: cassandra
spec:
terminationGracePeriodSeconds: 500
containers:
- name: cassandra
image: gcr.io/google-samples/cassandra:v13
imagePullPolicy: Always
ports:
- containerPort: 7000
name: intra-node
- containerPort: 7001
name: tls-intra-node
- containerPort: 7199
name: jmx
- containerPort: 9042
name: cql
resources:
limits:
cpu: "500m"
memory: 1Gi
requests:
cpu: "500m"
memory: 1Gi
securityContext:
capabilities:
add:
- IPC_LOCK
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- nodetool drain
env:
- name: MAX_HEAP_SIZE
value: 512M
- name: HEAP_NEWSIZE
value: 100M
- name: CASSANDRA_SEEDS
value: "cassandra-0.cassandra.default.svc.cluster.local"
- name: CASSANDRA_CLUSTER_NAME
value: "K8Demo"
- name: CASSANDRA_DC
value: "DC1-K8Demo"
- name: CASSANDRA_RACK
value: "Rack1-K8Demo"
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
readinessProbe:
exec:
command:
- /bin/bash
- -c
- /ready-probe.sh
initialDelaySeconds: 15
timeoutSeconds: 5
# These volume mounts are persistent. They are like inline claims,
# but not exactly because the names need to match exactly one of
# the stateful pod volumes.
volumeMounts:
- name: cassandra-data
mountPath: /cassandra_data
# These are converted to volume claims by the controller
# and mounted at the paths mentioned above.
# do not use these in production until ssd GCEPersistentDisk or other ssd pd
volumeClaimTemplates:
- metadata:
name: cassandra-data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: fast
resources:
requests:
storage: 1Gi
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: fast
provisioner: k8s.io/minikube-hostpath
parameters:
type: pd-ssd
cassandra-statefulset.yaml 파일에서 Cassandra StatefulSet을 만들어요.
# Use this if you are able to apply cassandra-statefulset.yaml unmodified
kubectl apply -f https://k8s.io/examples/application/cassandra/cassandra-statefulset.yaml
클러스터에 맞게 cassandra-statefulset.yaml을 수정해야 한다면, https://k8s.io/examples/application/cassandra/cassandra-statefulset.yaml을 다운로드한 다음, 수정한 버전을 저장한 폴더에서 그 매니페스트를 적용해요.
# Use this if you needed to modify cassandra-statefulset.yaml locally
kubectl apply -f cassandra-statefulset.yaml
Cassandra StatefulSet 검증
- Cassandra StatefulSet을 가져와요. 응답은 비슷해야 해요. StatefulSet 리소스는 파드를 순차적으로 배포해요.
- 파드를 가져와 순서대로 생성됨 상태를 봐요. 응답은 비슷해야 해요. 세 파드가 모두 배포되려면 몇 분이 걸릴 수 있어요. 배포되면 같은 명령이 다음과 비슷한 출력을 반환해요.
- 첫 파드 안에서 Cassandra nodetool을 실행해 ring의 상태를 표시해요. 응답은 대략 이렇게 보여야 해요.
Cassandra StatefulSet 수정
kubectl edit을 사용해 Cassandra StatefulSet의 크기를 수정해요.
- 다음 명령을 실행해요. 이 명령은 터미널에서 편집기를 열어요. 변경해야 할 줄은
replicas필드예요. 다음 샘플은 StatefulSet 파일의 발췌문이에요. - replicas 수를 4로 변경한 다음 매니페스트를 저장해요. 이제 StatefulSet은 4개 파드로 실행되도록 확장돼요.
- Cassandra StatefulSet을 가져와 변경을 확인해요. 응답은 비슷해야 해요.
정리
StatefulSet을 삭제하거나 축소해도 StatefulSet과 연결된 볼륨은 삭제되지 않아요. 이 설정은 데이터가 관련된 모든 StatefulSet 리소스를 자동으로 지우는 것보다 더 가치 있기 때문에, 안전을 위한 것이에요.
- 다음 명령(단일 명령으로 연결)을 실행해 Cassandra StatefulSet의 모든 것을 삭제해요.
- 다음 명령으로 Cassandra용으로 설정한 서비스를 삭제해요.
Cassandra 컨테이너 환경 변수
이 튜토리얼의 파드들은 Google 컨테이너 레지스트리의 gcr.io/google-samples/cassandra:v13 이미지를 사용해요. 위 Docker 이미지는 debian-base를 기반으로 하며 OpenJDK 8을 포함해요.
이 이미지는 Apache Debian 저장소의 표준 Cassandra 설치를 포함해요. 환경 변수를 사용해 cassandra.yaml에 삽입되는 값을 변경할 수 있어요.
| 환경 변수 | 기본값 |
|---|---|
CASSANDRA_CLUSTER_NAME |
'Test Cluster' |
CASSANDRA_NUM_TOKENS |
32 |
CASSANDRA_RPC_ADDRESS |
0.0.0.0 |
다음 단계
- StatefulSet 확장 배우기
- KubernetesSeedProvider 더 알아보기
- 커스텀 Seed Provider 구성 더 보기