Dapr Statestore ile Kubernetes Ortamında Gerçek Zamanlı Durum Yönetimi ve Redis Enterprise Cluster Kurulumu

Dapr Statestore konusunu ile ilgili burada bir yazı paylaşmıştım. Daha önce paylaştığım bu yazımda statestore kavramından bahsettim. Dapr’ a bir statestore Docker-Compose ile nasıl entegre edilir öğrendik. Şimdi de bu işlemi Kubernetes ile gerçekleştirmek istiyorum. Bu işlemi başarılı bir şekilde gerçekleştirmek için aşağıdaki adımları izleyeceğim.

  1. Öncelikle Kubernetes Cluster’rına Dapr kurulumu yapacağım.
  2. Dapr’a statestore olarak entegre edeceğim “Redis Enterprise Cluster” kurulumunu yapacağım.
  3. Redis’e yazdığım dataları görüntüleyebilmek için “Redisinsight” kurulumu yapacağım.
  4. Dapr’ı Redis ile bağlayan component configurasyonlarını hazırlayıp Kubertnetes’e göndereceğim.
  5. Microservislerin Dockerfile ile bir image hazırlayıp Container Registery‘ye yollayacağım.
  6. Kubernetes Deployment providerını kullanabilmek için “yaml” hazırlayacağım.
  7. Hazırlamış olduğum Yaml dosyalarının çalışması ile ortaya çıkacak podlara “Dapr Sidecar” entegre edebilmek için “Deployment” Yaml’larına “Dapr annotations” ekleyeceğim.
  8. Son olarak hazırlamış olduğum Deployment Yaml’larını Kubernetes clusterımda çalıştırdığımda, microservislerimin statestore bağlanabildiğini ve Redisinsight ilede dataları görebilmem gerekiyor.

Yukarıda adım adım sıraladığım gerçekleştirmeye başlayalım.

1. Kubernetes Cluster’ına Dapr Kurulumu.

Bu konuyu daha önce bir yazımda işlemiştim. Kurulum için farklı yöntemler mevcut. Biz, Dapr CLI yeteneklerini kullanarak “dapr init -k” komutu ile basit ve hızlı bir kurulum gerçekleştireceğiz.Kurulum bittiğinde Kubernetes Cluster’ında “dapr-system” isimli bir namespacede aşağıdaki gibi podların oluşmasını bekliyoruz.

2. Redis Enterprise Cluster Kurulumu

Redis’i çok daha basit bir yapıda da kurabilirdim fakat Redis Enterprise Cluster yapısına da değinmek, böyle bir yapının da olduğunu vurgulamak maksadıyla bu kurulumu seçtim. Kubernetes ortamında bu kurulumu yapmak için takip edeceğim dökümantasyon linki burada. Öncelikle kurulumu yapmak istediğim namespace belirleyelim.

kubectl create ns redis-enterprise-cluster

Bu işlemi gerçekleştirdikten sonra “operator bundle” yüklememiz gerekiyor. Bu işlem için aşağıdaki komutları çalıştıralım.

$VERSION = (Invoke-RestMethod -Uri "https://api.github.com/repos/RedisLabs/redis-enterprise-k8s-docs/releases/latest").tag_name

kubectl -n redis-enterprise-cluster apply -f https://raw.githubusercontent.com/RedisLabs/redis-enterprise-k8s-docs/$VERSION/bundle.yaml

Kurulumu yaptıktan sonra aşağıdaki komutu çalıştırarak kurulumu gerçekleştiğini doğrulayalım.

kubectl -n redis-enterprise-cluster get deployment redis-enterprise-operator

Komutun sonucunda görmemiz gereken çıktı şu şekilde.

Redis Enterprise Operator kurulumu tamamlandıktan sonra, RedisEnterpriseCluster Redis Enterprise Cluster (REC) özelliklerini içeren özel bir kaynaktan oluşturacağız. Bu kaynağa ait yaml dosyası “redisenterprisecluster.yaml” ismi ile kaydettiğinizi farz ediyorum.

apiVersion: app.redislabs.com/v1
kind: RedisEnterpriseCluster
metadata:
  name: redis
  namespace: redis-enterprise-cluster
spec:
  nodes: 3
  redisEnterpriseNodeResources:
    limits:
      cpu: 1
      memory: 16Gi
    requests:
      cpu: 1
      memory: 16Gi

Bu yaml dosyasını aşağıdaki komut ile çalıştırmalısınız.

kubectl apply -f redisenterprisecluster.yaml

Bu kurulumda tamamlandığında aşağıdaki gibi podların “redis-enterprise-cluster” namespacesinde çalıştığını aşağıdaki resimde olduğu gibi görmemiz gerekmekte.

Kurulum tamamlandıktan sonra Redis Enterprise Operator kurulumu ile birlikte gelen “redisenterprise UI” ulaşıp bir database oluşturmamız gerekiyor. “redisenterprise UI” ulaşabilmek için Kubernetes’te “port-forward” yöntemini kullanacağız. Öncelikle Redis’ eait Kubernetes Service’lerini görüntüleyelim.

kubectl get svc -n redis-enterprise-cluster

Bu komut ile gelen Service listesinde “redis-ui” olduğunu görüyoruz. Bu service “port-forward” yöntemini uygularsak ara yüze ulaşabiliriz.

kubectl -n redis-enterprise-cluster port-forward service/redis-ui 28015:8443

Arayüze “https://localhost:28015” urli ile aşağıda görüldüğü gibi ulaşabilirsiniz.

Şimdi sırada bu ara yüzü kullanarak bir Redis Database oluşturmakta. Peki username, password bilgilerine nasıl ulaşırım. Redis Enterprise Operator kurulumu ile birlikte gelen bu UI ait username, password bilgileride Kubernetes Secret’larda saklanmakta. Aşağıdaki komut ile görevbiliriz.

kubectl get secret -n redis-enterprise-cluster

“redis” isimli Secret’ ta saklana username, password bilgilerini Base64 formatında aşağıdaki komut ile görüntüleyebiliriz.

kubectl edit secret redis -n redis-enterprise-cluster

Base64 ile encode edilmiş username, password bilgisini aşağıdaki powershell script ile decode edebilirsiniz.

$encodedText = "ZGVtb0ByZWRpcy5jb20="
$decodedText = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($encodedText))
Write-Host $decodedText

Artık username, password öğrendiğimize göre arayüze giriş yapıp database oluşturabiliriz.

Görüldüğü gibi “statestore” isimli bir database oluşturuyorum. Active düğmesine tıkladığımızda database aktif edilmiş olacak. Bu işlemin sonunda aşağıdaki resimde görüldüğü gibi “redis-enterprise-cluster” namespacesinde “statestore” isimli bir Service oluşmalı. Bu database Kubernete içerisinden “http://statestore.redis-enterprise-cluster.svc.cluster.local:12004” adresi ile ulaşabiliriz. Yani artık bağlanmamız gerek redis host adresi tam olarak biraz önce verdiğim URL.

Artık Redis Database hazır. Bir sonraki aşama olan dataları görüntüleyebileceğimiz “Redisinsight” kurulumuna başlayabiliriz. Bu kurulum için Deployment ve Service yaml dosyasını paylaşacağım. Aşağıdaki yaml formatını “redisinsight.yaml” ismiyle kaydettiğinizi farz ediyorum.


apiVersion: apps/v1
kind: Deployment
metadata:
  name: redisinsight
  labels:
    app: redisinsight
  namespace: redis-enterprise-cluster
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redisinsight
  template:
    metadata:
      labels:
        app: redisinsight
    spec:
      imagePullSecrets:
      - name: default-secret
      containers:
      - name: redisinsight
        image: redislabs/redisinsight:latest
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: db
          mountPath: /db
        ports:
        - containerPort: 8001
          protocol: TCP
        resources:
          limits:
            cpu: 500m
            memory: 1024Mi
          requests:
            cpu: 500m
            memory: 1024Mi
      volumes:
      - name: db
        emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: redisinsight-service
  namespace: redis-enterprise-cluster
spec:
  type: ClusterIP
  ports:
  - port: 8080
    targetPort: 8001
  selector:
    app: redisinsight

Aşağıdaki komutu çalıştırarak “redisinsight” hazır hale getirebilirsiniz.

kubectl apply -f redisinsight.yaml

Redisenterprise UI görüntülemek için kullandığımız “port-forward” yöntemini “redisinsight” içinde uygulayarak arayüzüne ulaşabiliriz. Arayüzde gördüğünüz port değişiklik gösterebilir. Kubernetes Cluster’ında “statestore” isimli servisin portunu temsil etmekte.

kubectl -n redis-enterprise-cluster port-forward service/redisinsight-service 28016:8080

Redisinsight kurulumunu da tamamladığımıza göre bir sonraki aşama olan Dapr statestore componentini oluşturabiliriz. Aşağıdaki componentin detaylarını paylaştığım makalem burada.

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
  namespace: daprdotnetjourney
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: statestore.redis-enterprise-cluster.svc.cluster.local:12004
  - name: redisPassword
    value: ""
  - name: actorStateStore
    value: "true"
scopes:
  - basket-api

Oluşturduğumuz componenti Kubernetes’e aşağıda komut ile göndeceğiz.

kubectl apply -f statestore.yaml

Oluşturduğumuz component Kubernetes’te Custom Resource Defination olarak isimlendirilen bir yapı. Görüntüleyebilmek için aşağıdaki komutu kullanabilirsiniz.

kubectl get components.dapr.io

Şimdi sırada microservisleri Container Registery göndermekte. Bunun için öncelikle uygulamaya özel Dockerfile kullanarak bir image oluşturmak. Ben Basket Api’ ye ait Dockerfile “Dockerfile.BasketApi” ismi ile, Aggragator Api’sine ait Dockerfile ise “Dockerfile.Aggregator” ismi ile oluşturdum.

Aşağıdaki komutları kullanarak image oluşturuyorum.

docker build -f Dockerfile.BasketApi -t cahityusuf/basket-api:v1.0.3 .
docker build -f Dockerfile.Aggregator -t cahityusuf/aggregator-api:v1.0.2 .

Şimdi oluşturduğumuz imageları aşağıdaki komut ile Container Registry yollayabiliriz.

docker push docker.io/cahityusuf/basket-api:v1.0.3
docker push docker.io/cahityusuf/aggregator-api:v1.0.2

Image’ları Public Container Registery yolladığımıza göre artık bir sonraki aşama olan Kubernetes Deployment yaml hazırlamakta. Daha önce service invocation yöntemini anlattığım bir makalemde bu yamlların detaylarını anlattım makalem burada.

Aggregator Api Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: aggregator-deployment
  namespace: daprdotnetjourney
  labels:
    app: aggregator
spec:
  replicas: 1
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
  selector:
    matchLabels:
      service: aggregator
  template:
    metadata:
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: aggregator-api
        dapr.io/app-port: "80"
        dapr.io/config: "config"
      labels:
        app: aggregator
        service: aggregator
    spec:
      containers:
      - name: aggregator
        image: docker.io/cahityusuf/aggregator-api:v1.0.2
        imagePullPolicy: Always
        ports:
        - containerPort: 80
          protocol: TCP
        resources:
          requests:
            memory: "500Mi"
            cpu: "0.3"
          limits:
            memory: "500Mi"
            cpu: "0.5"
        env:
        - name: ASPNETCORE_ENVIRONMENT
          value: Development
        - name: ASPNETCORE_URLS
          value: http://+:80

Aggregator Api Service

apiVersion: v1
kind: Service
metadata:
  name: aggregator-svc
  namespace: daprdotnetjourney
  labels:
    app: aggregator
    service: aggregator
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    service: aggregator

Basket Api Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: basketapi-deployment
  namespace: daprdotnetjourney
  labels:
    app: basketapi
spec:
  replicas: 1
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
  selector:
    matchLabels:
      service: basketapi
  template:
    metadata:
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: basket-api
        dapr.io/app-port: "80"
        dapr.io/config: "config"
      labels:
        app: basketapi
        service: basketapi
    spec:
      containers:
      - name: basketapi
        image: docker.io/cahityusuf/basket-api:v1.0.3
        imagePullPolicy: Always
        ports:
        - containerPort: 80
          protocol: TCP
        resources:
          requests:
            memory: "500Mi"
            cpu: "0.3"
          limits:
            memory: "500Mi"
            cpu: "0.5"
        env:
        - name: ASPNETCORE_ENVIRONMENT
          value: Development
        - name: ASPNETCORE_URLS
          value: http://+:80

Basket Api Service

apiVersion: v1
kind: Service
metadata:
  name: basket-svc
  namespace: daprdotnetjourney
  labels:
    app: basketapi
    service: basketapi
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    service: basketapi

Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: daprdotnetjourney-ingress
  namespace: daprdotnetjourney
  annotations:
    ingress.class: "nginx"
spec:
  ingressClassName: nginx
  rules:
  - host: basket.daprdotnetjourney.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: basket-svc
            port:
              number: 80
  - host: aggregator.daprdotnetjourney.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: aggregator-svc
            port:
              number: 80

Yukarıda vermiş olduğum configurasyonları Kubernetes’e gönderdiğinizde uygulamalar ayağa kalkacaktır. Uygulamalar ile iletişim kurabilmek için Service ve Ingress configurasyonlarıda yaptığımı fark etmişsinizdir. Aşağıdaki komut ile mevcut Ingress’leri görüntüleyeceğiz ve karşımıza çıkan listedeki host name ile adress bilgilerini local host dosyamıza kaydettiğimizde apilere ulaşmış olacağız.

kubectl get ingress -n daprdotnetjourney

Bu işlemi kısa yoldan daha önce de yaptığımız gibi port-forward yöntemi ile de yapabilirdik fakat ingress tanımını da göstermek istedim. Host kaydımızı yaptıysak “http://aggregator.daprdotnetjourney.com/swagger/index.html” adresinden ilgili endpointi bulalım var Aggragator Api üzerinden Basket Api’ ye isteğimizi atalım. Basket datasının belirlediğimiz statestora yazıldığını görmeliyiz.

Resimde görüldüğü gibi isteğimizi attık ve aşağıda görüldüğü gibi Basket datasını Redis statestora Dapr aracılığı ile yazıldı.

Tüm yazı sonunda öncelikle Kubernetes ortamında Redis Enterprise Cluster nasıl kurulur, Dapr ile bağlantısı nasıl sağlanır ve yine Dapr aracılığı ile datamızı statestore nasıl yazarız öğrenmiş olduk.

Projenin linkini buraya bırakıyorum.

Tekrar görüşmek dileğiyle.

İnternet sitesi http://cahityusuf.com
Yazı oluşturuldu 6

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Benzer yazılar

Aramak istediğinizi üstte yazmaya başlayın ve aramak için enter tuşuna basın. İptal için ESC tuşuna basın.

Üste dön