목적

  • kubernentes 에서 redis cluster를 쉽게 배포해보자
  • Horizontal Pod Autoscaler (HPA) 기능을 이용하여 redis cluster를 autoscaling 해보자

왜 쿠버네티스 ?

  • resource limit & request 설정으로 Redis Container를 kubernetes Node에 효율적인 분산 배치 가능
  • 장애 시엔 자동화된 프로세스에 의해 복구됨 (auto healing)
  • Memory 부족 등, 필요한 경우 Scale up 뿐만 아니라 Scale out 까지 가능
  • 모든 작업을 ‘선언적’으로 자동화할 수 있음

Prerequisites

  • kubernetes 1.20 이상
    • 1.20 이상부터 HPA metric으로 memory 추가됨
  • helm 3.0.1 이상
  • bitnami 에서 제공하는 redis cluster helm chart
  • NHN Cloud kubernetes 서비스
    • NHN Cloud 지원 kubernetes 버전은 v1.17 으로 HPA metric memory 사용 불가능
    • 이 포스팅에서는 설치 및 아키텍처 소개는 NHN cloud, memory 사용에 따른 autoscale은 개인 PC환경에서 다루고 있음

설치

kubernetes 설치

  • NHN cloud Container 서비스 탭에서 kubernetes cluster를 간단히 생성할 수 있음
  • worker node 3개 짜리 kubernetes cluster를 생성함

설치한 kubernetes에 접속해보자

### 다운받은 kubeconfig 파일을 환경변수로 설정함
$ export KUBECONFIG=kimdubi-test_kubeconfig.yaml

### 설치한 kubernetes 접속 확인

$ kubectl get all
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.254.0.1   <none>        443/TCP   46m

$ kubectl get nodes
NAME                                         STATUS   ROLES    AGE   VERSION
kimdubi-test-default-w-46niimovcith-node-0   Ready    <none>   43m   v1.17.6
kimdubi-test-default-w-46niimovcith-node-1   Ready    <none>   42m   v1.17.6
kimdubi-test-default-w-46niimovcith-node-2   Ready    <none>   42m   v1.17.6

storageClass 생성

### 처음 구성 시 storage class가 없음

$ kubectl get sc
No resources found


$ cat storage_class.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: kimdubi-test
provisioner: kubernetes.io/cinder
parameters:
  type: General HDD
  availability: kr-pub-b

### Storage class 생성

$ kubectl apply -f storage_class.yaml
storageclass.storage.k8s.io/kimdubi-test created

$ kubectl get sc
NAME           PROVISIONER            RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
kimdubi-test   kubernetes.io/cinder   Delete          Immediate           false                  2s
  • Pod 에 PVC 를 연결해서 사용하기 위해서는 storageClass 가 있어야함
  • 처음 세팅 후엔 storageClass 가 없기 때문에 provisioner: kubernetes.io/cinder 를 사용하는 Storage class를 생성해준다
  • 생성하지 않으면 아래부터 진행할 redis pod 생성이 PVC 생성 실패로 pending 됨
  • 아래 링크에서 NHN cloud에서 제공하는 Storage type과 생성 조건을 확인

helm chart 받아오기

$ helm repo add bitnami https://charts.bitnami.com/bitnami
$ helm fetch bitnami/redis-cluster

helm chart 살펴보자

$ tree redis-cluster
redis-cluster
├── Chart.lock
├── Chart.yaml
├── README.md
├── charts
│   └── common
│       ├── Chart.yaml
│       ├── README.md
│       ├── templates
│       │   ├── _affinities.tpl
│       │   ├── _capabilities.tpl
│       │   ├── _errors.tpl
│       │   ├── _images.tpl
│       │   ├── _ingress.tpl
│       │   ├── _labels.tpl
│       │   ├── _names.tpl
│       │   ├── _secrets.tpl
│       │   ├── _storage.tpl
│       │   ├── _tplvalues.tpl
│       │   ├── _utils.tpl
│       │   ├── _warnings.tpl
│       │   └── validations
│       │       ├── _cassandra.tpl
│       │       ├── _mariadb.tpl
│       │       ├── _mongodb.tpl
│       │       ├── _postgresql.tpl
│       │       ├── _redis.tpl
│       │       └── _validations.tpl
│       └── values.yaml
├── img
│   ├── redis-cluster-topology.png
│   └── redis-topology.png
├── templates
│   ├── NOTES.txt
│   ├── _helpers.tpl
│   ├── configmap.yaml
│   ├── extra-list.yaml
│   ├── headless-svc.yaml
│   ├── init-cluster.yaml
│   ├── metrics-prometheus.yaml
│   ├── metrics-svc.yaml
│   ├── networkpolicy.yaml
│   ├── poddisruptionbudget.yaml
│   ├── prometheusrule.yaml
│   ├── psp.yaml
│   ├── redis-role.yaml
│   ├── redis-rolebinding.yaml
│   ├── redis-serviceaccount.yaml
│   ├── redis-statefulset.yaml
│   ├── redis-svc.yaml
│   ├── scripts-configmap.yaml
│   ├── secret.yaml
│   ├── svc-cluster-external-access.yaml
│   └── update-cluster.yaml
└── values.yaml
  • object, controller에 공통으로 적용될 설정은 .charts.common.templates, .chrats.common.values.yaml 에 정의됨
  • redis cluster를 구성하는 template과 설정은 .templates, .values.yaml에 정의되어 있음
  • customizing이 필요한 부분은 .values.yaml에서 값을 수정하여 helm을 재배포하면 됨

helm chart values 수정

간단히 redis Pod의 리소스 사용률을 제한하는 부분과 PV, redis.conf 만 수정하겠음

  • resource requests / limits 수정
$ vi helm위치/values.yaml 

177   resources:
178     requests:
179       memory: 50Mi
180       cpu: 50m
181     limits:
182       memory: 100Mi
183       cpu: 100m


383   resources:
384     ## We usually recommend not to specify default resources and to leave this as a conscious
385     ## choice for the user. This also increases chances charts run on environments with little
386     ## resources, such as Minikube. If you do want to specify resources, uncomment the following
387     ## lines, adjust them as necessary, and remove the curly braces after 'resources:'.
388     ##
389     limits: 
390       cpu: 100m
391       memory: 100Mi
392     ##
393     requests: 
394       cpu: 50m
395       memory: 50Mi
396     ##
  • redis physical volume size 수정
$ vi helm위치/values.yaml 

705   storageClass: kimdubi-test
706   accessModes:
707     - ReadWriteOnce
708   size: 2Gi    

=> storageClass 지정 및 size: 8Gi -> 2Gi 수정

  • configmap 수정 (redis.conf)
$ vi helm위치/templates/configmap.yaml
    
maxmemory 80M
maxmemory-policy allkeys-lru

helm install

$ helm install kimdubi-test ./redis-cluster

$ helm install kimdubi-test ./redis-cluster
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /Users/mac/Downloads/kimdubi-test_kubeconfig.yaml
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /Users/mac/Downloads/kimdubi-test_kubeconfig.yaml

NAME: kimdubi-test
LAST DEPLOYED: Sun Feb 21 16:33:55 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
** Please be patient while the chart is being deployed **


To get your password run:
    export REDIS_PASSWORD=$(kubectl get secret --namespace default kimdubi-test-redis-cluster -o jsonpath="{.data.redis-password}" | base64 --decode)

You have deployed a Redis(TM) Cluster accessible only from within you Kubernetes Cluster.INFO: The Job to create the cluster will be created.To connect to your Redis(TM) cluster:

1. Run a Redis(TM) pod that you can use as a client:
kubectl run --namespace default kimdubi-test-redis-cluster-client --rm --tty -i --restart='Never' \
 --env REDIS_PASSWORD=$REDIS_PASSWORD \
--image docker.io/bitnami/redis-cluster:6.0.10-debian-10-r5 -- bash

2. Connect using the Redis(TM) CLI:

redis-cli -c -h kimdubi-test-redis-cluster -a $REDIS_PASSWORD

redis cluster 구성 확인

dori:helm mac$ kubectl get all
NAME                                                  READY   STATUS      RESTARTS   AGE
pod/kimdubi-test-redis-cluster-0                      1/1     Running     0          5m19s
pod/kimdubi-test-redis-cluster-1                      1/1     Running     0          5m19s
pod/kimdubi-test-redis-cluster-2                      1/1     Running     2          5m19s
pod/kimdubi-test-redis-cluster-3                      1/1     Running     1          5m19s
pod/kimdubi-test-redis-cluster-4                      1/1     Running     1          5m19s
pod/kimdubi-test-redis-cluster-5                      1/1     Running     1          5m19s
pod/kimdubi-test-redis-cluster-cluster-create-gjwsk   0/1     Completed   0          5m19s

NAME                                          TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)              AGE
service/kimdubi-test-redis-cluster            ClusterIP   10.254.8.60   <none>        6379/TCP             5m19s
service/kimdubi-test-redis-cluster-headless   ClusterIP   None          <none>        6379/TCP,16379/TCP   5m19s
service/kubernetes                            ClusterIP   10.254.0.1    <none>        443/TCP              115m

NAME                                          READY   AGE
statefulset.apps/kimdubi-test-redis-cluster   6/6     5m19s

NAME                                                  COMPLETIONS   DURATION   AGE
job.batch/kimdubi-test-redis-cluster-cluster-create   1/1           59s        5m19s
dori:helm mac$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                             STORAGECLASS   REASON   AGE
pvc-10412da7-46bb-43e0-b791-a810774b7c87   2Gi        RWO            Delete           Bound    default/redis-data-kimdubi-test-redis-cluster-1   kimdubi-test            5m24s
pvc-3b7c88ff-6e56-428a-885f-58301e05478f   2Gi        RWO            Delete           Bound    default/redis-data-kimdubi-test-redis-cluster-0   kimdubi-test            5m11s
pvc-6a5aa328-8ca2-4450-a308-1c07cc7aab60   2Gi        RWO            Delete           Bound    default/redis-data-kimdubi-test-redis-cluster-2   kimdubi-test            5m24s
pvc-92e41155-d644-4799-b974-2a35c19ada8b   2Gi        RWO            Delete           Bound    default/redis-data-kimdubi-test-redis-cluster-4   kimdubi-test            5m24s
pvc-b198c891-2d0c-474e-9113-2ad0f198a336   2Gi        RWO            Delete           Bound    default/redis-data-kimdubi-test-redis-cluster-3   kimdubi-test            5m24s
pvc-b2fe7621-e748-4cc7-aa4c-2efee2fc0cd8   2Gi        RWO            Delete           Bound    default/redis-data-kimdubi-test-redis-cluster-5   kimdubi-test            5m24s
dori:helm mac$ kubectl get pvc
NAME                                      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
redis-data-kimdubi-test-redis-cluster-0   Bound    pvc-3b7c88ff-6e56-428a-885f-58301e05478f   2Gi        RWO            kimdubi-test   5m28s
redis-data-kimdubi-test-redis-cluster-1   Bound    pvc-10412da7-46bb-43e0-b791-a810774b7c87   2Gi        RWO            kimdubi-test   5m28s
redis-data-kimdubi-test-redis-cluster-2   Bound    pvc-6a5aa328-8ca2-4450-a308-1c07cc7aab60   2Gi        RWO            kimdubi-test   5m28s
redis-data-kimdubi-test-redis-cluster-3   Bound    pvc-b198c891-2d0c-474e-9113-2ad0f198a336   2Gi        RWO            kimdubi-test   5m28s
redis-data-kimdubi-test-redis-cluster-4   Bound    pvc-92e41155-d644-4799-b974-2a35c19ada8b   2Gi        RWO            kimdubi-test   5m28s
redis-data-kimdubi-test-redis-cluster-5   Bound    pvc-b2fe7621-e748-4cc7-aa4c-2efee2fc0cd8   2Gi        RWO            kimdubi-test   5m28s
dori:helm mac$ kubectl get configmap
NAME                                 DATA   AGE
kimdubi-test-redis-cluster-default   1      5m34s
kimdubi-test-redis-cluster-scripts   2      5m34s