Azure Kubernetes Service'te (AKS) Valkey kümesinin dayanıklılığını doğrulama

Bu kılavuzda, Locust yük testi çerçevesi kullanılarak Azure Kubernetes Service'te (AKS) dağıtılan bir Valkey kümesinin dayanıklılığının nasıl doğrulanması gösterilmektedir. Test istemcisi oluşturma, AKS'ye dağıtma, hataların simülasyonu yapma ve küme davranışını analiz etme adımları gösterilir.

Note

Bu makale, Microsoft'un artık kullanmadığı bir terim olan ana (birincil) terimine başvurular içerir. Terim Valkey yazılımından kaldırıldığında, bu makaleden kaldıracağız.

Valkey için örnek istemci uygulaması oluşturma

Aşağıdaki adımlarda, Valkey için örnek bir istemci uygulamasının nasıl derlenmesi gösterilmektedir.

Örnek istemci uygulaması, yapılandırdığınız ve dağıtılan Valkey kümesindeki bir iş yükünün benzetimini yapmak için Locust yük testi çerçevesini kullanır. Python kodu, Valkey kümesine bağlanan ve set etme ve alma işlemi gerçekleştiren bir Locust User sınıfı uygular. Daha karmaşık işlemler uygulamak için bu sınıfı genişletebilirsiniz.

Note

Kullanılabilir en güvenli kimlik doğrulama akışını kullanmanızı öneririz. Bu yordamda açıklanan kimlik doğrulama akışı, uygulamada çok yüksek düzeyde güven gerektirir ve diğer akışlarda mevcut olmayan riskleri taşır. Bu akışı yalnızca yönetilen kimlikler gibi diğer daha güvenli akışlar uygun olmadığında kullanmalısınız.

  1. Aşağıdaki komutları kullanarak Dockerfile dosyasını oluşturun ve requirements.txt yeni bir dizine yerleştirin:

    mkdir valkey-client
    cd valkey-client
    
    cat > Dockerfile <<EOF
    FROM python:3.10-slim-bullseye
    COPY requirements.txt .
    COPY locustfile.py .
    RUN pip install --upgrade pip && pip install --no-cache-dir -r requirements.txt
    EOF
    
    cat > requirements.txt <<EOF
    valkey
    locust
    EOF
    
  2. locustfile.py Valkey istemci uygulama kodunu içeren dosyayı oluşturun:

    cat > locustfile.py <<EOF
    import time
    from locust import between, task, User, events,tag, constant_throughput
    from valkey import ValkeyCluster
    from random import randint
    
    class ValkeyLocust(User):
        wait_time = constant_throughput(50)
        host = "valkey-cluster.valkey.svc.cluster.local"
        def __init__(self, *args, **kwargs):
            super(ValkeyLocust, self).__init__(*args, **kwargs)
            self.client = ValkeyClient(host=self.host)
        def on_stop(self):
            self.client.close()
        @task
        @tag("set")
        def set_value(self):
            self.client.set_value("set_value")
        @task
        @tag("get")
        def get_value(self):
            self.client.get_value("get_value")
    
    class ValkeyClient(object):
        def __init__(self, host, *args, **kwargs):
            super().__init__(*args, **kwargs)
            with open("/etc/valkey-password/valkey-password-file.conf", "r") as f:
                self.password = f.readlines()[0].split(" ")[1].strip()
            self.host = host
            self.vc = ValkeyCluster(host=self.host,
                                    port=6379,
                                    password=self.password,
                                    username="default",
                                    cluster_error_retry_attempts=0,
                                    socket_timeout=2,
                                    keepalive=1
                                    )
    
        def set_value(self, key, command='SET'):
            start_time = time.perf_counter()
            try:
                result = self.vc.set(randint(0, 1000), randint(0, 1000))
                if not result:
                    result = ''
                length = len(str(result))
                total_time = (time.perf_counter()- start_time) * 1000
                events.request.fire(
                    request_type=command,
                    name=key,
                    response_time=total_time,
                    response_length=length,
                )
            except Exception as e:
                total_time = (time.perf_counter()- start_time) * 1000
                events.request.fire(
                    request_type=command,
                    name=key,
                    response_time=total_time,
                    response_length=0,
                    exception=e
                )
                result = ''
            return result
        def get_value(self, key, command='GET'):
            start_time = time.perf_counter()
            try:
                result = self.vc.get(randint(0, 1000))
                if not result:
                    result = ''
                length = len(str(result))
                total_time = (time.perf_counter()- start_time) * 1000
                events.request.fire(
                    request_type=command,
                    name=key,
                    response_time=total_time,
                    response_length=length,
                )
            except Exception as e:
                total_time = (time.perf_counter()- start_time) * 1000
                events.request.fire(
                    request_type=command,
                    name=key,
                    response_time=total_time,
                    response_length=0,
                    exception=e
                )
                result = ''
            return result
    EOF
    

Docker görüntüsünü derleme ve ACR'ye gönderme

  1. Komutunu kullanarak az acr build Docker görüntüsünü derleyin ve Azure Container Registry'ye (ACR) yükleyin.

    az acr build --image valkey-client --registry ${MY_ACR_REGISTRY} .
    
  2. az acr repository list komutunu kullanarak görüntünün başarıyla gönderildiğini doğrulayın.

    az acr repository list --name ${MY_ACR_REGISTRY} --output table
    

    Çıktı, aşağıdaki örnekte olduğu gibi valkey-client görüntüyü göstermelidir.

    Result
    ----------------
    valkey-client
    

Örnek istemci podunu AKS'ye dağıtın

  1. komutunu kullanarak önceki adımda oluşturulan Valkey istemci görüntüsünü kullanan Pod bir kubectl apply oluşturun. Pod belirtimi, istemcinin Valkey kümesine bağlanmak için kullandığı Valkey parolası ile Gizli Depolama CSI birimini içerir.

    kubectl apply -f - <<EOF
    ---
    kind: Pod
    apiVersion: v1
    metadata:
      name: valkey-client
      namespace: valkey
    spec:
        affinity:
          nodeAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
              nodeSelectorTerms:
              - matchExpressions:
                - key: agentpool
                  operator: In
                  values:
                  - nodepool1
        containers:
        - name: valkey-client
          image: ${MY_ACR_REGISTRY}.azurecr.io/valkey-client
          command: ["locust", "--processes", "4"]
          volumeMounts:
            - name: valkey-password
              mountPath: "/etc/valkey-password"
        volumes:
        - name: valkey-password
          csi:
            driver: secrets-store.csi.k8s.io
            readOnly: true
            volumeAttributes:
              secretProviderClass: "valkey-password"
    EOF
    
  2. Bağlantı noktası, komutunu kullanarak yerel makinenizdeki Locust web arabirimine erişmek için 8089 numaralı bağlantı noktasını iletin kubectl port-forward .

    kubectl port-forward -n valkey valkey-client 8089:8089
    
  3. adresinden Locust web arabirimine http://localhost:8089 erişin ve testi başlatın. Valkey kümesindeki bir iş yükünün benzetimini yapmak için kullanıcı sayısını ve oluşturma oranını ayarlayabilirsiniz. Aşağıdaki grafikte 100 kullanıcı ve 10 oluşturma oranı kullanılır:

    Locust test panosunu gösteren bir web sayfasının ekran görüntüsü.

Hata simülasyonu ve Valkey kümesi davranışını gözlemleme

  1. komutunu bayrağıyla birlikte kullanarak StatefulSet silerek kubectl delete bir kesintinin simülasyonunu gerçekleştirin--cascade=orphan. Amaç, StatefulSet silinen podun hemen yeniden oluşturulmasına izin vermeden tek bir podu silebilmektir.

    kubectl delete statefulset valkey-masters --cascade=orphan
    
  2. kubectl delete pod komutunu kullanarak valkey-masters-0 podunu silin.

    kubectl delete pod valkey-masters-0
    
  3. komutunu kullanarak kubectl get pods pod listesini denetleyin.

    kubectl get pods
    

    Çıktı, pod'un valkey-masters-0 silindiğini göstermelidir. Aşağıdaki örnekte gösterildiği gibi diğer podların Running durumda olması gerekir.

    NAME                READY   STATUS    RESTARTS   AGE
    valkey-client       1/1     Running   0          6m34s
    valkey-masters-1    1/1     Running   0          16m
    valkey-masters-2    1/1     Running   0          16m
    valkey-replicas-0   1/1     Running   0          16m
    valkey-replicas-1   1/1     Running   0          16m
    valkey-replicas-2   1/1     Running   0          16m
    
  4. valkey-replicas-0 podunun günlüklerini kubectl logs valkey-replicas-0 komutunu kullanarak alın.

    kubectl logs valkey-replicas-0
    

    Çıktıda, olayın tamamının yaklaşık 18 saniye sürdüğünü gözlemliyoruz:

    1:S 05 Nov 2024 12:18:53.961 * Connection with primary lost.
    1:S 05 Nov 2024 12:18:53.961 * Caching the disconnected primary state.
    1:S 05 Nov 2024 12:18:53.961 * Reconnecting to PRIMARY 10.224.0.250:6379
    1:S 05 Nov 2024 12:18:53.961 * PRIMARY <-> REPLICA sync started
    1:S 05 Nov 2024 12:18:53.964 # Error condition on socket for SYNC: Connection refused
    1:S 05 Nov 2024 12:18:54.910 * Connecting to PRIMARY 10.224.0.250:6379
    1:S 05 Nov 2024 12:18:54.910 * PRIMARY <-> REPLICA sync started
    1:S 05 Nov 2024 12:18:54.912 # Error condition on socket for SYNC: Connection refused
    1:S 05 Nov 2024 12:18:55.920 * Connecting to PRIMARY 10.224.0.250:6379
    [..CUT..]
    1:S 05 Nov 2024 12:19:10.056 * Connecting to PRIMARY 10.224.0.250:6379
    1:S 05 Nov 2024 12:19:10.057 * PRIMARY <-> REPLICA sync started
    1:S 05 Nov 2024 12:19:10.058 # Error condition on socket for SYNC: Connection refused
    1:S 05 Nov 2024 12:19:10.709 * Node c44d4b682b6fb9b37033d3e30574873545266d67 () reported node 9e7c43890613cc3ad4006a9cdc0b5e5fc5b6d44e     () as not reachable.
    1:S 05 Nov 2024 12:19:10.864 * NODE 9e7c43890613cc3ad4006a9cdc0b5e5fc5b6d44e () possibly failing.
    1:S 05 Nov 2024 12:19:11.066 * 10000 changes in 60 seconds. Saving...
    1:S 05 Nov 2024 12:19:11.068 * Background saving started by pid 29
    1:S 05 Nov 2024 12:19:11.068 * Connecting to PRIMARY 10.224.0.250:6379
    1:S 05 Nov 2024 12:19:11.068 * PRIMARY <-> REPLICA sync started
    1:S 05 Nov 2024 12:19:11.069 # Error condition on socket for SYNC: Connection refused
    29:C 05 Nov 2024 12:19:11.090 * DB saved on disk
    29:C 05 Nov 2024 12:19:11.090 * Fork CoW for RDB: current 0 MB, peak 0 MB, average 0 MB
    1:S 05 Nov 2024 12:19:11.169 * Background saving terminated with success
    1:S 05 Nov 2024 12:19:11.884 * FAIL message received from ba36d5167ee6016c01296a4a0127716f8edf8290 () about     9e7c43890613cc3ad4006a9cdc0b5e5fc5b6d44e ()
    1:S 05 Nov 2024 12:19:11.884 # Cluster state changed: fail
    1:S 05 Nov 2024 12:19:11.974 * Start of election delayed for 510 milliseconds (rank #0, offset 7225807).
    1:S 05 Nov 2024 12:19:11.976 * Node d43f370a417d299b78bd1983792469fe5c39dcdf () reported node 9e7c43890613cc3ad4006a9cdc0b5e5fc5b6d44e     () as not reachable.
    1:S 05 Nov 2024 12:19:12.076 * Connecting to PRIMARY 10.224.0.250:6379
    1:S 05 Nov 2024 12:19:12.076 * PRIMARY <-> REPLICA sync started
    1:S 05 Nov 2024 12:19:12.076 * Currently unable to failover: Waiting the delay before I can start a new failover.
    1:S 05 Nov 2024 12:19:12.078 # Error condition on socket for SYNC: Connection refused
    1:S 05 Nov 2024 12:19:12.581 * Starting a failover election for epoch 15.
    1:S 05 Nov 2024 12:19:12.616 * Currently unable to failover: Waiting for votes, but majority still not reached.
    1:S 05 Nov 2024 12:19:12.616 * Needed quorum: 2. Number of votes received so far: 1
    1:S 05 Nov 2024 12:19:12.616 * Failover election won: I'm the new primary.
    1:S 05 Nov 2024 12:19:12.616 * configEpoch set to 15 after successful failover
    1:M 05 Nov 2024 12:19:12.616 * Discarding previously cached primary state.
    1:M 05 Nov 2024 12:19:12.616 * Setting secondary replication ID to c0b5b2df8a43b19a4d43d8f8b272a07139e0ca34, valid up to offset:     7225808. New replication ID is 029fcfbae0e3e4a1dccd73066043deba6140c699
    1:M 05 Nov 2024 12:19:12.616 * Cluster state changed: ok
    

    18 saniyelik bu süre boyunca, silinen pod'a ait parçaya yapılan yazma işlemlerinin başarısız olduğunu ve Valkey kümesinin yeni bir ana düğüm seçtiğini gözlemliyoruz. bu zaman penceresi boyunca istek gecikme süresi 60 ms'ye yükseldi.

    İstek gecikme sürelerinin 60 ms'ye yükselerek 95. yüzdebirlik dilimini gösteren grafiğin ekran görüntüsü.

    Yeni birincil seçim yapıldıktan sonra Valkey kümesi yaklaşık 2 ms gecikme süresiyle isteklere hizmet etmeye devam eder.

Sonraki adım

Contributors

Microsoft bu makaleyi korur. Başlangıçta aşağıdaki katkıda bulunanlar yazdı:

  • Nelly Kiboi | Hizmet Mühendisi
  • Saverio Proto | Baş Müşteri Deneyimi Mühendisi