What's next
- Learn how to Scale a StatefulSet.
- Learn more about the KubernetesSeedProvider
- See more custom Seed Provider Configurations
<츨처>
https://kubernetes.io/docs/tutorials/stateful-application/cassandra/
이번 튜토리얼에서는 K8S 상에서 여러분이 어떻게 네이티브 클라우드 Cassandra 배포를 개발할 수 있는지 보여준다. 이 예시에서, 주문제작한(custom) Cassandra SeedProvider 는 새로운 Cassandra 노드들이 클러스터에 가입할 때, Cassandra가 그것들을 발견할 수 있도록 해준다.
StatefulSets은 클러스터가 구성된 환경 속에서 stateful 한 애플리케이션을 배포하기 쉽도록 해준다. 이 튜토리얼에서 이용된, 그 특성에 관한 추가 정보는, StatefulSet 문서를 참조한다.
Docker 기반 Cassandra
이 튜토리얼 내 Pods는 구글 container registry에 있는 gcr.io/google-samples/cassandra:v13 이미지를 이용한다 . 위 도커 이미지는 debian-base를 토대로 하며 OpenJDK 8을 포함하고 있다.
이 이미지는 Apache Debian repo의 표준 Cassandra 설치를 포함한다. 여러분은 환경변수를 이용하여 "cassandra.yaml" 내 삽입되어져 있는 value들을 변경할 수 있다.
ENV VAR | DEFAULT VALUE |
---|---|
CASSANDRA_CLUSTER_NAME | 'Test Cluster' |
CASSANDRA_NUM_TOKENS | 32 |
CASSANDRA_RPC_ADDRESS | 0.0.0.0 |
이번 튜토리얼을 완료하기 위해서, 여러분은 Pods, Services, 그리고 StatefulSets에 대해 기본적인 익숙함이 있어야만 한다. 더불어,
kubectl 커맨드-라인 도구를 설치와 구성해야만 한다.
cassandra-service.yaml
과 cassandra-statefulset.yaml 파일을 다운 받아야 한다.
동작 중인 지원가능한 K8S 클러스터를 가지고 있어야 한다.
주의: 만약 클러스터가 아직 없다면, 시작을 위한 가이드를 읽어보기 바란다.
경고: Minikube는 기본적으로 1024MB 메모리에 1 CPU로 구동된다. 기본 자원 구성으로 Minikube를 동작하게 되면, 이 튜토리얼 내내 불충분 자원 에러를 초래하게 된다. 이러한 에러들을 피하기 위해서는, 다음 설정들로 Minikube를 구동시킨다.
minikube start --memory 5120 --cpus=4
실제 위에서 권장한 리소스 뿐만 아니라 추가의 리소스(8G RAM/4 CPU)를 할당해봐도 메모리 에러는 피할 수 없었다. 여러분이 Minikube를 이용해 실습하고자 할 경우, 재확인 해보길 바란다. 아마도 동일한 결과가 나타날 것이다. 시험삼아 한번정도 시도해 보고, 가급적 구글 클라우드 환경에서 진행할 것을 권장한다.
그러나 구글 클라우드의 경우에도, 원문에서 제시하는 방식으로는 불충분 CPU 에러가 발생하였다. 일단 튜토리얼을 무난히 마치고 결과를 보는게 목적인지라 임시방편으로 처리(하기에 방편 제시)하도록 하였으나, 여하튼 실습들이 점점 어려워 지고 있음을 느낀다. 하고픈 것도, 해야 할 것도 점점 많아진다. 잼난다~~~^
Minikube 상에 추가 리소스 할당하여 진행하지만, 메모리 이슈 발생
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | root@zerobig-vm_u:~# minikube start --memory 8192 --cpus 4 Starting local Kubernetes v1.10.0 cluster... Starting VM... Getting VM IP address... Moving files into cluster... Setting up certs... Connecting to cluster... Setting up kubeconfig... Starting cluster components... Kubectl is now configured to use the cluster. Loading cached images from config file. root@zerobig-vm_u:~# minikube status minikube: Running cluster: Running kubectl: Correctly Configured: pointing to minikube-vm at 192.168.99.100 | cs |
메모리 부족 에러 예시
구글 클라우드 작업환경 설정
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | [root@docker-registry ~]# gcloud container clusters get-credentials zerobig-cluster-1 --zone asia-east1-c --project zerobig-k8s-tutorial Fetching cluster endpoint and auth data. kubeconfig entry generated for zerobig-cluster-1. Updates are available for some Cloud SDK components. To install them, please run: $ gcloud components update [root@docker-registry ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION gke-zerobig-cluster-1-default-pool-d22ac19b-4c42 Ready <none> 4d v1.9.7-gke.6 gke-zerobig-cluster-1-default-pool-d22ac19b-7gc1 Ready <none> 4d v1.9.7-gke.6 gke-zerobig-cluster-1-default-pool-d22ac19b-fc6x Ready <none> 4d v1.9.7-gke.6 | cs |
K8S Service는 동일한 작업을 수행하는 Pods 세트를 기술한다.
다음의 "Service"는 K8S 클러스터 이내의 Cassandra Pods와 클라이언트들 사이에서 DNS lookup 을 위해 이용된다.
application/cassandra/cassandra-service.yaml
1 2 3 4 5 6 7 8 9 10 11 12 | apiVersion: v1 kind: Service metadata: labels: app: cassandra name: cassandra spec: clusterIP: None ports: - port: 9042 selector: app: cassandra | cs |
1. manifest 파일들을 다운로드했던 디렉토리에서 터미널 창을 구동시킨다.
2. "cassandra-service.yaml" 파일로부터 모든 Cassandra StatefulSet 노드를 추적하기 위해 Service를 생성한다 :
1 2 3 | [root@docker-registry ~]# kubectl create -f https://k8s.io/examples/application/cassandra/cassandra-service.yaml service/cassandra createdroot@zerobig-vm_u:~# kubectl create -f https://k8s.io/examples/application/cassandra/cassandra-service.yaml service/cassandra created | cs |
Cassandra Service를 확인해 본다.
1 | [root@docker-registry ~]# kubectl get svc cassandra | cs |
그 응답은
1 2 3 | [root@docker-registry ~]# kubectl get svc cassandra NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE cassandra ClusterIP None <none> 9042/TCP 22s | cs |
아무런 반응결과 없이 Service 생성이 실패가 나면, 일반적인 이슈들에 대한 Debug Services을 읽어본다.
아래 포함된, StatefulSet manifest은 3개의 Pod로 구성된 Cassandra 링을 생성한다.
주의: 이 예제는 Minikube를 위해 기본 공급자를 이용한다. 여러분이 작업하고 있는 클라우드를 위해서는 다음의 StatefulSet을 업데이트 하길 바란다.
<참고>
필자는 다음 YAML 파일에서 3,4,100 라인을 4,5,101로 수정하여 진행하였다. 3,4라인은 CPU 에러를 피하기 위함이고, 100라인은 현재 실습환경이 Minikube 환경이 아니기 때문이다.
application/cassandra/cassandra-statefulset.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | 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: 1800 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" cpu: "200m" memory: 1Gi requests: # cpu: "500m" cpu: "200m" 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 provisioner: kubernetes.io/gce-pd parameters: type: pd-ssd | cs |
1. 필요하다면, StatefulSet을 업데이트한다.
2. "cassandra-statefulset.yaml 파일로부터 Cassandra StatefulSet을 생성한다:
1 2 3 | [root@docker-registry ~]# kubectl create -f /home/study/k8s/application/cassandra/cassandra-statefulset.yaml statefulset.apps/cassandra created storageclass.storage.k8s.io/fast created | cs |
1. Cassandra Service를 확인해 본다.
1 | [root@docker-registry ~]# kubectl get statefulset cassandra | cs |
1 2 3 | [root@docker-registry ~]# kubectl get statefulset cassandra NAME DESIRED CURRENT AGE cassandra 3 1 17s | cs |
"StatefulSet 자원은 순차적으로 Pod를 배포한다.
1 | [root@docker-registry ~]# kubectl get pods -l="app=cassandra" | cs |
1 2 3 4 | [root@docker-registry ~]# kubectl get pods -l="app=cassandra" NAME READY STATUS RESTARTS AGE cassandra-0 1/1 Running 0 3m cassandra-1 0/1 Running 0 1m | cs |
3개의 Pod가 모두 배포되는데 수분의 시간이 소요될 수 있다. 배포가 이루어지면, 동일 명령이 반환된다:
1 2 3 4 5 | [root@docker-registry ~]# kubectl get pods -l="app=cassandra" NAME READY STATUS RESTARTS AGE cassandra-0 1/1 Running 0 7m cassandra-1 1/1 Running 0 5m cassandra-2 1/1 Running 0 2m | cs |
(참고로 GCP 상에서 다음과 같이 보다 직관적으로 상세한 상태를 확인 할 수 있다.)
3. 링의 상태를 전시해주는 Casandra nodetool을 구동한다.
1 | [root@docker-registry ~]# kubectl exec -it cassandra-0 -- nodetool status | cs |
그 응답은 다음과 같은 식으로 보여야만 한다.
1 2 3 4 5 6 7 8 9 | [root@docker-registry ~]# kubectl exec -it cassandra-0 -- nodetool status Datacenter: DC1-K8Demo ====================== Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns (effective) Host ID Rack UN 10.52.1.22 104.54 KiB 32 70.5% 5e9d8331-f424-48ea-a488-18c8396961c5 Rack1-K8Demo UN 10.52.2.16 108.9 KiB 32 74.3% 659cdbc5-a6b4-4c85-9fc4-dd2cb6449670 Rack1-K8Demo UN 10.52.0.8 103.81 KiB 32 55.1% 41278014-195c-49cc-bc82-ed2314d10733 Rack1-K8Demo | cs |
Cassandra StatefulSet의 사이즈를 수정하기 위해 "kubectl edit" 을 이용한다.
1. 다음 명령을 수행한다:
1 | [root@docker-registry ~]# kubectl edit statefulset cassandra | cs |
이 명령은 여러분의 터미널에 편집기를 띄워준다. 변경하려는 라인은 "replicas" 필드이다. 다음 샘플은 StatefulSet 파일의 발췌본이다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # Please edit the object below. Lines beginning with a '#' will be ignored, # and an empty file will abort the edit. If an error occurs while saving this file will be # reopened with the relevant failures. # apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 kind: StatefulSet metadata: creationTimestamp: 2016-08-13T18:40:58Z generation: 1 labels: app: cassandra name: cassandra namespace: default resourceVersion: "323" selfLink: /apis/apps/v1/namespaces/default/statefulsets/cassandra uid: 7a219483-6185-11e6-a910-42010a8a0fc0 spec: replicas: 3 | cs |
2. Change the number of replicas의 숫자를 4로 변경하고, manifest을 저장한다.
3. 검증을 위해 Cassandra StatefulSet 을 확인한다:
1 | [root@docker-registry ~]# kubectl get statefulset cassandra | cs |
그 응답은 다음과 같아야 한다.
1 2 3 | [root@docker-registry ~]# kubectl get statefulset cassandra NAME DESIRED CURRENT AGE cassandra 4 4 11m | cs |
StatefulSet의 삭제 또는 스케일 다운은 StatefulSet으로 연계된 볼륨들을 삭제하지 않는다. 모든 관련 StatefulSet 자원들을 자동으로 정리하는 것보다 여러분의 데이터가 더 가치 있기 때문에 이 설정은 여러분의 안전을 위한것이다.
경고: 스토리지 등급과 반환요구 정책에 따라, PersistentVolumeClaims을 삭제하는 것은 연관된 볼륩들을 함께 지우는 결과를 초래할 수 있다. 볼륨 요구가 제거되어지면, 여러분이 데이터 접근을 할 수 있을거라는 가정은 절대하지 말자.
1. Cassandra "StatefulSet"에서 모든 것을 삭제하기 위해 다음 명령들(하나의 명령어 속에 함께 연결되어진)을 수행한다:
1 2 3 4 5 6 7 8 9 10 11 | [root@docker-registry ~]# grace=$(kubectl get po cassandra-0 -o=jsonpath='{.spec.terminationGracePeriodSeconds}') \ > && kubectl delete statefulset -l app=cassandra \ > && echo "Sleeping $grace" \ > && sleep $grace \ > && kubectl delete pvc -l app=cassandra statefulset.apps "cassandra" deleted Sleeping 1800 persistentvolumeclaim "cassandra-data-cassandra-0" deleted persistentvolumeclaim "cassandra-data-cassandra-1" deleted persistentvolumeclaim "cassandra-data-cassandra-2" deleted persistentvolumeclaim "cassandra-data-cassandra-3" deleted | cs |
2. Cassandra Service를 삭제하기 위해 다음 명령을 수행한다:
1 2 | [root@docker-registry ~]# kubectl delete service -l app=cassandra service "cassandra" deleted | cs |