Kubernetes 환경에서 ARCUS 캐시 사용하기

잼투인·2024년 4월 23일
0

이전 포스팅에서는 Docker 컨테이너를 활용해서 하나의 장비에 ARCUS 캐시 클러스터를 구성해 보았습니다. 이번 포스팅에서는 쿠버네티스(Kubernetes)를 활용하여 다수의 호스트 장비에 ARCUS 캐시 클러스터를 구성하는 방법을 소개하겠습니다.

Kubernetes

쿠버네티스(k8s 또는 kube라고도 함)는 컨테이너화된 워크로드와 서비스를 관리하기 위한 오픈소스 플랫폼입니다. 여러 호스트 장비를 하나의 쿠버네티스 클러스터로 묶어 관리할 수 있고, 이렇게 구성된 쿠버네티스 클러스터에 서비스를 배포하면 적절한 노드(호스트 장비)에 컨테이너를 분산해서 배치하거나, 문제가 생긴 컨테이너를 교체하거나, 컨테이너 동작에 필요한 설정 관리 등의 동작을 수행합니다.

ARCUS 캐시 클러스터는 가용성과 확장성을 위해 다수의 캐시 노드를 여러 장비에 분산 배치하기 때문에 운영자는 다수의 장비에 프로세스를 적절히 구동하고 설정/관리해 주어야 합니다. 쿠버네티스 환경에서 운영자가 ARCUS 캐시 노드의 수와 분산 배치 전략을 명시하면 쿠버네티스가 그에 맞게 자동으로 분산 배치된 캐시 노드를 구동해주므로 서비스 운영에 드는 노력을 효과적으로 절감할 수 있습니다.

본 포스팅에서는 다수의 장비에 쿠버네티스 클러스터를 구성하는 대신 minikube를 활용하여 가상의 worker node를 구성하고 실습을 진행해 보겠습니다. 만약 이미 구성된 쿠버네티스 클러스터에서 실습을 진행하려는 경우 minikube 파트는 건너뛰어도 됩니다. 원활한 실습을 위해서는 컨트롤 플레인 노드(마스터 노드) 외에 3개 이상의 워커 노드가 있어야 한다는 점을 유의하세요.

minikube는 개발 및 학습이 주 목적이기 때문에, 컨트롤 플레인 노드에도 리소스가 스케줄되도록 기본 설정되어 있으니 참고 바랍니다.

Minikube

실제 운영 환경에서는 다수의 호스트 장비에 걸친 쿠버네티스 클러스터를 구성하고, 각 리소스는 여러 노드에 분산 배치됩니다. 만약 로컬 장비에서 간단한 실습을 진행하려는 경우에는 minikube를 사용하여 다수의 가상 장비를 기반으로 하는 쿠버네티스 클러스터를 구성할 수 있습니다. 실습 환경은 Linux이므로 아래와 같은 명령으로 minikube를 설치할 수 있고, 그 외 환경에서의 설치 방법은 minikube Get Started 문서를 참고해 주세요.

curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube && rm minikube-linux-amd64

설치가 완료된 후에는 minikube start 명령을 통해 minikube 클러스터를 시작할 수 있습니다. 본 포스팅에서는 ARCUS의 각 구성 요소가 분산 배치되는 것을 확인하기 위해, 총 4개 노드로 구성된 minikube 클러스터를 사용하겠습니다.

$ minikube start --nodes=4

구성이 완료된 뒤 kubectl get nodes 명령을 사용하면 1개의 control-plane node와 3개의 worker node를 확인하실 수 있습니다. control plane node는 쿠버네티스 클러스터를 관리하는 노드이고, worker node는 사용자가 배포한 서비스를 실행하기 위한 노드입니다.

$ kubectl get nodes
NAME           STATUS   ROLES           AGE   VERSION
minikube       Ready    control-plane   12m   v1.28.3
minikube-m02   Ready    <none>          11m   v1.28.3
minikube-m03   Ready    <none>          11m   v1.28.3
minikube-m04   Ready    <none>          10m   v1.28.3

ZooKeeper ensemble 구성

쿠버네티스 클러스터를 준비한 뒤에는 쿠버네티스 환경에서 ARCUS 캐시의 메타 정보를 관리하는 ZooKeeper ensemble을 먼저 구축합니다. 쿠버네티스 튜토리얼인 Running ZooKeeper, A Distributed System Coordinator에서 제공하는 manifest 파일을 사용하여 3개 서버로 구성되고 각각은 서로 다른 워커 노드에 배치되는 ZooKeeper ensemble을 구축합니다. 이와 같은 ZooKeeper 서버의 분산 배치를 위하여 쿠버네티스 클러스터에는 3개 이상의 워커 노드가 존재해야 합니다.

$ kubectl apply -f https://k8s.io/examples/application/zookeeper/zookeeper.yaml
service/zk-hs created
service/zk-cs created
poddisruptionbudget.policy/zk-pdb created
statefulset.apps/zk created

manifest 파일에 의해 생성되는 리소스를 살펴보면 다음과 같습니다.

  • zk-hs: ZooKeeper 서버 간 통신을 위한 service
  • zk-cs: 클라이언트 요청을 처리하기 위한 service
  • zk-pdb: 동시에 여러 서버가 Unavailable 상태가 되는 것을 방지하는 PodDisruptionBudget
  • zk: Pod를 관리하는 Statefulset

모든 리소스가 구동되고 나면 kubectl get pods 명령으로 상태를 확인할 수 있습니다. 정상 구동되었다면 3개 Pod가 Ready(1/1), Running 상태일 것입니다. 만약 그 외의 상태에서 장시간 진행되지 않는 Pod가 있다면, kubectl describe pod <pod-name>명령을 통해 문제 원인을 파악하고 조치를 취해야 합니다.

$ kubectl get pods -o wide
NAME   READY   STATUS    RESTARTS   AGE     IP           NODE           NOMINATED NODE   READINESS GATES
zk-0   1/1     Running   0          2m43s   10.244.0.6   minikube       <none>           <none>
zk-1   1/1     Running   0          2m23s   10.244.3.6   minikube-m04   <none>           <none>
zk-2   1/1     Running   0          2m1s    10.244.1.5   minikube-m02   <none>           <none>

ARCUS cluster 구성

ZooKeeper ensemble이 정상 동작하는 상태에서, 다음과 같은 yaml 파일을 적용하여 현재 namespace에 3개 노드로 구성된 ARCUS 캐시 클러스터를 구성할 수 있습니다. 아래 파일은 default namespace를 기준으로 작성되었으며, 다른 namespace를 사용하는 경우 zk conn strserver fqdndefault.svc 부분을 <namespace>.svc와 같이 변경해 주어야 합니다.

apiVersion: v1
kind: Service
metadata:
  name: arcus-mc
  labels:
    app: arcus-memcached
    service-code: test
spec:
  ports:
  - port: 11211
    name: arcus-mc
  selector:
    app: arcus-memcached
    service-code: test
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: arcus-mc
spec:
  selector:
    matchLabels:
      app: arcus-memcached
      service-code: test
  serviceName: arcus-mc
  replicas: 3
  template:
    metadata:
      name: arcus-memcached
      labels:
        app: arcus-memcached
        service-code: test
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: "service-code"
                  operator: In
                  values:
                  - test
              topologyKey: "kubernetes.io/hostname"
      containers:
      - name: memcached
        image: jam2in/arcus-memcached:1.13.5
        args:
        - "-v"
        - "-m"
        - "100"
        - "-z"
        - "zk-cs.default.svc.cluster.local:2181" # zk conn str
      initContainers:
      - name: arcus-tool
        image: jam2in/zkcli:python
        args:
          - "arcus.memcached"
          - "add"
          - "zk-cs.default.svc.cluster.local:2181" # zk conn str
          - "$(POD_NAME).mc.default.svc.cluster.local:11211" # server fqdn
          - "test" # service-code
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name

주요 설정은 다음과 같습니다.

  • replicas: 구동하려는 Pod 수 입니다.
  • podAntiAffinity: 각 Pod가 가능한 서로 다른 장비에 배치되도록 합니다.
  • initContainer: arcus-memcached가 실행되기 전에 ZooKeeper에 Znode를 생성하는 작업을 수행합니다.

ZooKeeper 프로세스를 PM 또는 VM 환경에 직접 구동하고 ARCUS 캐시 서버만 Kubernetes 환경에서 동작시키는 형태의 구성도 가능합니다. 이렇게 구성하려면 yaml 내용 중 zk conn str 부분에 해당 ZooKeeper 주소를 입력하면 됩니다.

이렇게 yaml 파일을 작성한 뒤에는 kubectl apply 명령으로 현재 Kubernetes context에 적용할 수 있습니다.

$ kubectl apply -f <arcus-memcached.yaml>
service/mc created
statefulset.apps/mc created

ZooKeeper와 마찬가지로, 각 Pod가 모두 구동되고 나면 kubectl get pods 명령으로 상태를 확인할 수 있습니다.

$ kubectl get pods -o wide
NAME   READY   STATUS    RESTARTS   AGE     IP           NODE           NOMINATED NODE   READINESS GATES
mc-0   1/1     Running   0          2m36s   10.244.2.5   minikube-m03   <none>           <none>
mc-1   1/1     Running   0          2m33s   10.244.1.6   minikube-m02   <none>           <none>
mc-2   1/1     Running   0          69s     10.244.3.7   minikube-m04   <none>           <none>
zk-0   1/1     Running   0          23m     10.244.0.6   minikube       <none>           <none>
zk-1   1/1     Running   0          23m     10.244.3.6   minikube-m04   <none>           <none>
zk-2   1/1     Running   0          23m     10.244.1.5   minikube-m02   <none>           <none>

busybox

이제 총 3개 Pod로 구성된 ARCUS 캐시 클러스터가 구동되었습니다. 이번에는 각 프로세스가 잘 동작하고 있는지 확인해 보겠습니다. Kubernetes 환경에서 실행 중인 서비스 디버깅을 위해서 busybox를 사용할 수 있습니다. 자세한 내용은 Debug Services 문서를 참고 바랍니다.

kubectl run -it --rm --restart=Never busybox --image=gcr.io/google-containers/busybox sh

busybox 컨테이너에서 nc, telnet등의 명령을 통해 각 프로세스에 명령을 전송하고 응답을 확인할 수 있습니다. 아래 예시에서 IP 주소 대신 Pod의 FQDN을 사용해도 됩니다.

/ # echo srvr | nc 10.244.0.6 2181
Zookeeper version: 3.4.10-39d3a4f269333c922ed3db283be479f9deacaa0f, built on 03/23/2017 10:13 GMT
Latency min/avg/max: 0/0/39
Received: 150651
Sent: 150650
Connections: 2
Outstanding: 0
Zxid: 0x200000025
Mode: follower
Node count: 23

/ # echo version | nc 10.244.2.5 11211
VERSION 1.13.5

마치며

지금까지 쿠버네티스 환경에서 ARCUS 캐시 클러스터를 구동하는 방법에 대해 간단히 알아보았습니다. 쿠버네티스는 컨테이너를 활용한 배포 시 사실상 표준(de facto)으로 사용되고 있습니다. 본 포스팅에서 안내드린 내용만으로도 기본적인 클러스터 구성 및 사용이 가능하지만, ARCUS 서버 재구동 없이 설정을 변경하거나 다양한 이벤트 발생 시 유연한 처리가 어렵습니다. ARCUS Enterprise Edition을 구독한 고객에게는 최상의 안정성과 고가용성을 보장하기 위해 ARCUS Operator를 제공하고 있습니다. 본 포스트 또는 ARCUS Operator에 대한 문의 사항이 있다면 contact@jam2in.com 으로 연락 바랍니다.

0개의 댓글