paint-brush
Kuma Kafa Başına Meshes - Bilmeniz Gereken Her Şeyile@jesperancinha
586 okumalar
586 okumalar

Kuma Kafa Başına Meshes - Bilmeniz Gereken Her Şey

ile João Esperancinha27m2024/04/13
Read on Terminal Reader

Çok uzun; Okumak

Kuma'yı hızlı bir şekilde öğrenmeye başlamak için ihtiyacımız olan en önemli şeylerden biri kümedir. Daha sonra Kubernetes'teki (diğer adıyla k8s) podlarımızın durumunu öğrenmek için de bir komuta ihtiyacımız var.
featured image - Kuma Kafa Başına Meshes - Bilmeniz Gereken Her Şey
João Esperancinha HackerNoon profile picture
0-item
1-item

Kuma Kafa Başına Örgüler - Yeni Başlayanlar İçin Kılavuz

Kuma hızlı bir şekilde öğrenmeye başlamak için ihtiyacımız olan en önemli şeylerden biri kümedir. Daha sonra Kubernetes'teki (aka k8s ) pod'larımızın durumunu öğrenmek için bir komuta da ihtiyacımız var, ayrıca Kuma kurabilmemiz gerekiyor ve son olarak bazı Kuma komutlarını da verebilmemiz gerekiyor.


Bu, her şeyi Kuma hazır hale getirmek için 4 temel komutu kurmamız gerektiğini söylemenin uzun bir yolu. Bu komutlar şunlardır:

  • kind - Bu aynı zamanda Docker'da Kubernetes olarak da bilinir. Bu, yalnızca kubectl ile bir şeyler oluşturmanın ağırlığından yararlanan bir komuttur.


  • kubectl - Zaten k8s ile çalışmaya alışkınsanız, muhtemelen bu listede en çok beklenenlerden biri. k8s kümemize bu şekilde komut verebiliriz.


  • helm - Helm, diğerlerinin yanı sıra Kuma kontrol düzleminin kurulumuna izin veren bazı çok kullanışlı komut dosyalarını çalıştırmamıza olanak tanır.


  • kumactl - Bu kılavuzda bu komutu çok sık kullanmayacağız, ancak nasıl kullanılacağının farkında olmak önemlidir.


Bu kılavuz, bunu Ubuntu nasıl yapacağınızı size bildirecektir. Bunların hepsi bir Ubuntu sisteminde test edilmiştir. Bunu Mac-OS , Windows veya sahip olabileceğiniz başka bir işletim sistemine nasıl kuracağınıza dair bir kılavuzla ilgileniyorsanız, lütfen YouTube kanalım JESPROTECH topluluğumdan bana ses verin.


I. Komutların Kurulumu


görüntü açıklaması


Docker'da tür ( k8s )

Kind'i kurmak için şu komutları vermemiz gerekiyor:

 [ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.22.0/kind-linux-amd64 chmod +x ./kind sudo mv ./kind /usr/local/bin/kind


kind komutunun /usr/local/bin/kind dizinine kurulacağını unutmamak önemlidir. Bu, Linux dağıtımlarında bile sisteme göre değişiklik gösterebilir.


Sertifikaları ve GPG Anahtarlarını Yükleme

Belirli GPG anahtarlarının varlığıyla hem helm hem de kubectl komutlarının yüklenmesi gerekir. Bunları Linux apt dağıtımımızın yerel deposuna şu şekilde ekleyebiliriz:

 sudo apt-get install -y apt-transport-https ca-certificates curl gpg curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list sudo apt-get update



kubectl

Önceki adım tamamlandıktan sonra Kubectl kurulumu çok kolaydır:

 sudo apt-get install -y kubelet kubeadm kubectl


kubelet , kubeadm ve kubectl komutları zorunlu değildir ancak bunları yüklemek iyi bir fikirdir.


dümen

Tahmin edebileceğiniz gibi helm kurulumu da artık çok kolay:

 sudo apt-get install -y helm

kuma

Kuma kurulumu tek bir manuel adım içerdiğinden biraz hantal olabilir, ancak önce bağımlılıklarımızı indirmemiz gerekiyor:

 cd ~ || exit; curl -L https://kuma.io/installer.sh | VERSION=2.6.1 sh -


Bu komutu vermeden önce HOME klasörünüzde olduğunuzdan emin olun. Kuma , örneğin kaldırmaya karar vermemiz durumunda, kolayca erişilebilecek ve kolayca görülebilecek bir yere kurulması önemlidir.


Bununla işimiz bittiğinde, bin klasörünü PATH'imize eklemek de çok önemlidir:

 export PATH=~/kuma-2.6.1/bin:$PATH;


Bu satırı başlangıç betiğinizin sonuna veya aradaki herhangi bir yere eklemek bu işlemi kolaylaştıracaktır. Başlangıç komut dosyanız bu .bashrc , .zshrc , .profile dosyalarından herhangi biri olabilir ve muhtemelen başka bir biçim alabilir.


k9'lar

k9s kurulumu da diğer uygulamalardan oldukça farklıdır. Bu durumda Linux için ya pacman ya da brew kullanabiliriz. brew çoğunlukla Mac-OS için kullandım ve Linux'ta buna neredeyse hiç ihtiyaç duymadım, ancak bu durumda buna çok ihtiyaç var ve bunu yapmak için ilk önce Brew'i şu şekilde kurmamız gerekiyor:

 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"


Demleme kurulumu tamamlandıktan sonra tek yapmamız gereken k9s (" kanines ") kurmak:

 brew install derailed/k9s/k9s


Dikkate alınması gereken önemli bir nokta ve k9s ilk kez kurup çalıştırmaya başladığınızda muhtemelen bunu fark edeceksiniz; izlediği bir küme kaldırılırsa ve/veya eklenirse k9s çökecektir.


II. Kümeyi Oluşturma

 kind create cluster --name=wlsm-mesh-zone kubectl cluster-info --context kind-wlsm-mesh-zone


İlk komut wlsm-mesh-zone adında bir küme oluşturur. Bu sadece Kuma'yı kurmak için kullanacağımız bir küme. İkinci komut kümenin durumunu kontrol etmek için kullanılır.


III. Yerel Docker Kayıt Defteri Oluşturma

Daha önce de belirttiğim gibi docker kayıt defterini oldukça kolay bir şekilde oluşturabiliyoruz. Bunu oluşturmak kulağa kolay gelse de, bunu yapacak komut dosyası bir avuç dolusu. Bu nedenle yapılacak en iyi şey, web sitelerinde zaten mevcut olan türü kopyalayıp yapıştırmaktır. Buradan bu betiği indirebiliriz:

 #!/bin/sh # Original Source # https://creativecommons.org/licenses/by/4.0/ # https://kind.sigs.k8s.io/docs/user/local-registry/ set -o errexit # 1. Create registry container unless it already exists reg_name='kind-registry' reg_port='5001' if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then docker run \ -d --restart=always -p "127.0.0.1:${reg_port}:5000" --network bridge --name "${reg_name}" \ registry:2 fi # 2. Create kind cluster with containerd registry config dir enabled # TODO: kind will eventually enable this by default and this patch will # be unnecessary. # # See: # https://github.com/kubernetes-sigs/kind/issues/2875 # https://github.com/containerd/containerd/blob/main/docs/cri/config.md#registry-configuration # See: https://github.com/containerd/containerd/blob/main/docs/hosts.md cat <<EOF | kind create cluster --config=- kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 containerdConfigPatches: - |- [plugins."io.containerd.grpc.v1.cri".registry] config_path = "/etc/containerd/certs.d" EOF # 3. Add the registry config to the nodes # # This is necessary because localhost resolves to loopback addresses that are # network-namespace local. # In other words: localhost in the container is not localhost on the host. # # We want a consistent name that works from both ends, so we tell containerd to # alias localhost:${reg_port} to the registry container when pulling images REGISTRY_DIR="/etc/containerd/certs.d/localhost:${reg_port}" for node in $(kind get nodes); do docker exec "${node}" mkdir -p "${REGISTRY_DIR}" cat <<EOF | docker exec -i "${node}" cp /dev/stdin "${REGISTRY_DIR}/hosts.toml" [host."http://${reg_name}:5000"] EOF done # 4. Connect the registry to the cluster network if not already connected # This allows kind to bootstrap the network but ensures they're on the same network if [ "$(docker inspect -f='{{json .NetworkSettings.Networks.kind}}' "${reg_name}")" = 'null' ]; then docker network connect "kind" "${reg_name}" fi # 5. Document the local registry # https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry cat <<EOF | kubectl apply -f - apiVersion: v1 kind: ConfigMap metadata: name: local-registry-hosting namespace: kube-public data: localRegistryHosting.v1: | host: "localhost:${reg_port}" help: "https://kind.sigs.k8s.io/docs/user/local-registry/" EOF



Bu komut dosyasıprojenin kök klasöründe bulunabilir. Ve yerel docker kayıt defterini kurmak için yalnızca bu bash betiğini çalıştırmamız gerekiyor.


IV. Kod Nasıl Oluşturuldu?

Bu blog yazısı için örnek olarak verdiğim kod hakkında söylenecek çok şey olabilir. Ancak bu durumda sadece birkaç önemli noktaya odaklanalım.Dinleyici hizmetinden toplayıcıya ve ardındanveritabanına başlayalım. Hizmetleri yerel olarak çalıştırdığımızda veya hatta kapsayıcıların çalışmasını sağlamak için docker-compose yapılandırmasını kullandığımızda, genellikle kapsayıcı adı veya hostname adı ile yapılandırdığımız ad olarak otomatik olarak atanan DNS ile ilişkilendirilen adları kullanırız.


k8s ile ana bilgisayar adlarının küme genelinde kullanılabilir olmasını sağlayan bir dizi kural da vardır. Dinleyici ve toplayıcı örneklerine bir göz atalım:


Dinleyici Örneği

Dinleyici, Spring framework kullanarak Java geliştirilmiş bir uygulamadır. Bu şekilde oluşturulan tüm uygulamalar gibi bir de application.properties dosyası bulunur:

 spring.application.name=wlsm-listener-service server.port=8080 spring.main.web-application-type=reactive spring.webflux.base-path=/app/v1/listener wslm.url.collector=http://localhost:8081/api/v1/collector


Tüm bu özellikler içerisinde şu an için üzerinde durulması gereken en önemli özellik wslm.url.collector özelliğidir. default konfigürasyon ile herhangi bir konteynerli ortam kullanmaya gerek kalmadan bu hizmeti local olarak çalıştırabiliyoruz. Ancak k8s kümesinde collector erişebilmemiz gerekiyor ve bunun için application-prod.properties tanım dosyasına sahip bir prod profilimiz var:

 wslm.url.collector=http://wlsm-collector-deployment.wlsm-namespace.svc.cluster.local:8081/api/v1/collector


Bu özellik, wlsm-collector-deployment.wlsm-namespace.svc.cluster.local ana bilgisayarına ulaşmaya çalışır. Bu dosya şu yapılandırmayı takip eder:

<Service Name>.<Namespace>.svc.cluster.local

Noktalarla ayrılmış 5 öğemiz var. Son üçü statiktir ve ilk ikisi ulaşmaya çalıştığımız makineye bağlıdır. Sol tarafa hizmet adını ve ardından ad alanını yerleştiriyoruz. Bu, konteynerlerin küme içinde birbirine nasıl bağlandığını anlamak önemlidir.


Kodun ilginç olan kısmı elbette denetleyici ve hizmettir. Denetleyici şuna benzer:

 @RestController @RequestMapping public class ListenerController { private final ListenerService listenerService; ListenerController(ListenerService listenerService) { this.listenerService = listenerService; } @GetMapping("info") public String info() { return "Listener Service V1"; } @PostMapping("create") public Mono<AnimalLocationDto> sendAnimalLocation( @RequestBody AnimalLocationDto animalLocationDto) { return listenerService.persist(animalLocationDto); } }


Ve hizmet şöyle görünüyor:

 @Service public class ListenerService { @Value("${wslm.url.collector:http://localhost:8080}") private String collectorUrl; private final WebClient client = WebClient.create(collectorUrl); HazelcastInstance hazelcastInstance = Hazelcast.newHazelcastInstance(); List<AnimalLocationDto> cache = hazelcastInstance.getList("data"); public Mono<AnimalLocationDto> persist(AnimalLocationDto animalLocationDto) { cache.add(animalLocationDto); return client.post() .uri(collectorUrl.concat("/animals")) .contentType(MediaType.APPLICATION_JSON) .bodyValue(animalLocationDto) .retrieve() .bodyToMono(AnimalLocationDto.class); } }


Fark etmiş olabileceğiniz gibi, bu ilk uygulama, bu depodaki Spring Framework kullanılarak uygulanan tüm uygulamalar gibi reaktiftir ve hepsi tomcat yerine netty kullanır. Şimdilik bu koddaki hazelcast kullanımını göz ardı edebiliriz. . Bu, bu projenin sonraki sürümleri için kullanılacaktır.


Koleksiyoncu Örneği

Bu noktada toplayıcı da dinleyiciyle tamamen aynı şekilde çalışır. Şimdilik tek görevi, verileri dinleyiciden veritabanına aktarmaktır ve bunu yapmak için toplayıcının yalnızca veritabanının tam olarak nerede olduğunu bilmesi gerekir. Aynı analizi application.properties file of this project üzerinde de yapalım:

 spring.application.name=wlsm-collector-service server.port=8081 spring.main.web-application-type=reactive spring.webflux.base-path=/api/v1/collector spring.r2dbc.url=r2dbc:postgresql://localhost:5432/wlsm spring.r2dbc.username=admin spring.r2dbc.password=admin spring.data.r2dbc.repositories.naming-strategy=org.springframework.data.relational.core.mapping.BasicRelationalPersistentEntityNamingStrategy spring.data.r2dbc.repositories.naming-strategy.table=org.springframework.data.relational.core.mapping.SnakeCaseNamingStrategy spring.data.r2dbc.repositories.naming-strategy.column=org.springframework.data.relational.core.mapping.SnakeCaseNamingStrategy


Bu özellikler, hizmetin devam etmesi için gereken minimum özelliklerdir. Ancak bu yalnızca yerel olarak çalıştırılabilir. Bu hizmet için ayrıca prod profil dosyamız var ve buna buradaki application-prod.properties dosyasından bakabiliriz:

 spring.r2dbc.url=r2dbc:postgresql://wlsm-database-deployment.wlsm-namespace.svc.cluster.local:5432/wlsm


Bu durumda veritabanı bağlantısı veritabanının ana bilgisayarına atıfta bulunur:

wlsm-database-deployment.wlsm-namespace.svc.cluster.local


Bu da daha önce gördüğümüz analizin aynısını takip ediyor. Sol tarafta hizmet adını ve ardından bunu sonuna svc.cluster.local ile ekleyen ad alanını görüyoruz.


Ve bu hizmet için ayrıca bir denetleyici ve bir hizmet kullanıyoruz. Denetleyici şuna benzer:

 @RestController @RequestMapping class CollectorController( val collectorService: CollectorService ) { @PostMapping("animals") suspend fun listenAnimalLocation(@RequestBody animalLocationDto: AnimalLocationDto): AnimalLocationDto = run { collectorService.persist(animalLocationDto) animalLocationDto } }


Ve hizmet şöyle görünüyor:

 @Service class CollectorService( val applicationEventPublisher: ApplicationEventPublisher ) { fun persist(animalLocationDto: AnimalLocationDto) = applicationEventPublisher.publishEvent(AnimalLocationEvent(animalLocationDto)) }


Hizmet, applicationEventPublisher adı verilen ve daha sonra bu olay dinleyicisinde işlenecek bir olay akışı mimarisini takip eden bir olay yayıncısını kullanır; bunun reaktif mimari uygulama paradigmalarını korumak için r2dbc kullandığını kolayca görebiliriz:

 @Service class EventHandlerService( val animalLocationDao: AnimalLocationDao ) { @EventListener fun processEvent(animalLocationEvent: AnimalLocationEvent){ println(animalLocationEvent) runBlocking(Dispatchers.IO) { animalLocationDao.save(animalLocationEvent.animalLocationDto.toEntity()) } } }



V. Komut Dosyalarını Dağıtın

Dağıtım normalde k8s ile yapılacak çok basit bir iştir. Ancak hizmetlerimiz için gereken konfigürasyona da göz atmak önemlidir. Örneğin dinleyici uygulamasına bir göz atalım:

 apiVersion: v1 kind: Namespace metadata: name: wlsm-namespace labels: kuma.io/sidecar-injection: enabled --- apiVersion: apps/v1 kind: Deployment metadata: name: wlsm-listener namespace: wlsm-namespace spec: replicas: 1 selector: matchLabels: app: wlsm-listener template: metadata: labels: app: wlsm-listener spec: containers: - name: wlsm-listener-service image: localhost:5001/wlsm-listener-service:latest imagePullPolicy: Always ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: wlsm-listener-deployment namespace: wlsm-namespace spec: selector: app: wlsm-listener ports: - protocol: TCP appProtocol: http port: 8080


Bu konfigürasyonda üç blok bulunmaktadır. İlk blok ad alanı bloğudur. Ad alanı yapılandırması, Kuma'nın politikaları uygulamak için ihtiyaç duyduğu elçi sepetlerini enjekte edebilmesine olanak sağlamak açısından çok önemlidir. Tanımlanmış bir ad alanı olmadan kuma bunu yapamaz. Kuma'yı yapılandırırken dikkat etmemiz gereken diğer husus ise namespace'in kuma'nın tanıyacağı uygun etiketi içermesi gerektiğidir:

kuma.io/sidecar-injection: enabled.


Doğru etikete sahip ad alanı tanımı Kuma'nın çalışması için hayati öneme sahiptir. İkinci blokta dağıtımın tanımını buluyoruz. Podumuzun dağıtımının Kubernetes kümemizde nasıl görüneceğini bu şekilde tanımlıyoruz. Burada odaklanılması gereken önemli şey image , imagePullPolicy ve containerPort . İmaj, kullandığımız Docker imajının tam etiketidir.


kind ile oluşturulan docker kayıt defterimiz için yapılandırılan port 5001'dir ve bu, imajımızın etiketine dahil edilmiştir. Bir etiket olarak çalışır, aynı zamanda Docker kayıt defterimize bağlantı olarak da çalışır. Bu şekilde görüntüleri çekebilir ve Kubernetes ortamımızda çalışacak konteynerimizi oluşturabiliriz.


Ancak elbette görüntüleri kullanabilmek için onları oluşturmamız gerekiyor ve bunun için listener örneğinde ve database örneğinde bunun nasıl yapıldığına bir göz atalım. listener liman işçisi görüntüsü şu şekilde tanımlanır:

 FROM eclipse-temurin:21-jdk-alpine WORKDIR /root ENV LANG=C.UTF-8 COPY entrypoint.sh /root COPY build/libs/wlsm-listener-service.jar /root/wlsm-listener-service.jar ENTRYPOINT ["/root/entrypoint.sh"]


Bunların hepsi eclipse-temurin:21-jdk-alpine adı verilen temel görüntüden başlar. Bundan sonra projeyi inşa ederek oluşturduğumuz jar'ı kopyalayıp imajımıza kopyalıyoruz. Bundan önce entrypoint.sh dosyasını da konteynere kopyalıyoruz ve onu kullanacak ENTRYPOINT tanımlıyoruz. entrypoint basitçe kavanozu şu şekilde çağırır:

 #!/usr/bin/env sh java -jar -Dspring.profiles.active=prod wlsm-listener-service.jar


database hizmeti oldukça farklıdır çünkü açık kaynaklı ve çevrimiçi olarak erişilebilen birkaç komut dosyası kullanır:

 FROM postgres:15 COPY . /docker-entrypoint-initdb.d COPY ./multiple /docker-entrypoint-initdb.d/multiple ENV POSTGRES_USER=admin ENV POSTGRES_PASSWORD=admin ENV POSTGRES_MULTIPLE_DATABASES=wlsm EXPOSE 5432


Bu komut dosyası, aşağıdaki dosya ve klasörün docker başlangıç dizinine bir kopyasını oluşturur: create-multiple-postgresql-databases.sh ve multiple . Son olarak, veritabanımızı ve kullanıcı adı/şifre kombinasyonlarımızı tanımlamak için bu komut dosyalarında kullanılan değişkenleri basitçe tanımlarız.


Veritabanı aşağıdaki şema kullanılarak oluşturulur:

 CREATE TABLE families( id uuid DEFAULT gen_random_uuid(), name VARCHAR(100), PRIMARY KEY(id) ); CREATE TABLE genuses( id uuid DEFAULT gen_random_uuid(), name VARCHAR(100), PRIMARY KEY(id) ); CREATE TABLE species( id uuid DEFAULT gen_random_uuid(), common_name VARCHAR(100), family uuid, genus uuid, PRIMARY KEY(id), CONSTRAINT fk_species FOREIGN KEY(family) REFERENCES families(id), CONSTRAINT fk_genus FOREIGN KEY(genus) REFERENCES genuses(id) ); CREATE TABLE animal ( id uuid DEFAULT gen_random_uuid(), name VARCHAR(100), species_id uuid, PRIMARY KEY(id), CONSTRAINT fk_species FOREIGN KEY(species_id) REFERENCES species(id) ); CREATE TABLE animal_location ( id uuid DEFAULT gen_random_uuid(), animal_id uuid, latitude BIGINT, longitude BIGINT, PRIMARY KEY(id), CONSTRAINT fk_animal FOREIGN KEY(animal_id) REFERENCES animal(id) );


Veri örneği olarak bir hayvanı piquinho adıyla kaydedeceğiz. Piquinho, basitçe dünyayı dolaşan, üzerine bir sensör takılı olan ve biz de sensörün bize gönderdiği verileri okuyan gezgin bir albatros'un adıdır. Türleri tanımlayan iki tablo vardır. Türü tanımlayan tür ve cinstir. Bunlar tablo families ve genuses .


Tablo species hayvanın ait olduğu türü tanımlar. Son olarak hayvanın türünün ve adının kayıtlı olduğu aynı isimli tabloda bir animal tanımlıyoruz. Veritabanı şuna benzer:
Görüntü açıklaması

Görüntüleri oluşturmak, oluşturmak ve projemizi başlatmak için Makefile bulunan aşağıdaki komutları çalıştırabiliriz:

 make make create-and-push-images make k8s-apply-deployment


İlk make sadece bir gradle build komutudur. İkinci komut değişkeni kullandı:

 MODULE_TAGS := aggregator \ collector \ listener \ management \ database


koşmak:

 docker images "*/*wlsm*" --format '{{.Repository}}' | xargs -I {} docker rmi {} @for tag in $(MODULE_TAGS); do \ export CURRENT=$(shell pwd); \ echo "Building Image $$image..."; \ cd "wlsm-"$$tag"-service"; \ docker build . --tag localhost:5001/"wlsm-"$$tag"-service"; \ docker push localhost:5001/"wlsm-"$$tag"-service"; \ cd $$CURRENT; \ done


Bu, her modülün üzerinden geçer ve görüntüleri oluşturmak ve bunları 5001 numaralı bağlantı noktasındaki yerel kayıt defterine göndermek için MODULE_TAGS verilen değere göre değişen standart bir genel komut kullanır. Aynı stratejiyi izleyerek, daha sonra üçüncü komutu konuşlandırmak için kullanabiliriz. kapsüller. Bu üçüncü komut şuna benzeyen farklı bir döngü kullanır:

 @for tag in $(MODULE_TAGS); do \ export CURRENT=$(shell pwd); \ echo "Applying File $$tag..."; \ cd "wlsm-"$$tag"-service"; \ kubectl apply -f $$tag-deployment.yaml --force; \ cd $$CURRENT; \ done


Bu durumda, her dağıtım komut dosyasını hizmetlerin her birine uygular. kubectl get pods --all-namespaces komutunu çalıştırırsak şu çıktıyı almamız gerekir:

 NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-76f75df574-dmt5m 1/1 Running 0 5m21s kube-system coredns-76f75df574-jtrfr 1/1 Running 0 5m21s kube-system etcd-kind-control-plane 1/1 Running 0 5m38s kube-system kindnet-7frts 1/1 Running 0 5m21s kube-system kube-apiserver-kind-control-plane 1/1 Running 0 5m36s kube-system kube-controller-manager-kind-control-plane 1/1 Running 0 5m36s kube-system kube-proxy-njzvl 1/1 Running 0 5m21s kube-system kube-scheduler-kind-control-plane 1/1 Running 0 5m36s kuma-system kuma-control-plane-5f47fdb4c6-7sqmp 1/1 Running 0 17s local-path-storage local-path-provisioner-7577fdbbfb-5qnxr 1/1 Running 0 5m21s wlsm-namespace wlsm-aggregator-64fc4599b-hg9qw 1/1 Running 0 4m23s wlsm-namespace wlsm-collector-5d44b54dbc-swf84 1/1 Running 0 4m23s wlsm-namespace wlsm-database-666d794c87-pslzp 1/1 Running 0 4m22s wlsm-namespace wlsm-listener-7bfbcf799-f44f5 1/1 Running 0 4m23s wlsm-namespace wlsm-management-748cf7b48f-8cjh9 1/1 Running 0 4m23s


Burada burada gözlemlememiz gereken şey kuma-control-plane , kube-controller-manager ve kendi özel wlsm-namespace çalışan tüm servislerin varlığıdır. Kümemiz dışarıdan izole edilmiştir ve farklı bağlantı noktalarına erişebilmek için erişmek istediğimiz her pod için port-forwarding oluşturmamız gerekir. Bunun için şu komutları ayrı sekmelerde verebiliriz:

Buna k9s bakarak da bakabiliriz:

görüntü açıklaması

 kubectl port-forward svc/wlsm-collector-deployment -n wlsm-namespace 8081:8081 kubectl port-forward svc/wlsm-listener-deployment -n wlsm-namespace 8080:8080 kubectl port-forward svc/wlsm-database-deployment -n wlsm-namespace 5432:5432 kubectl port-forward svc/kuma-control-plane -n kuma-system 5681:5681


VI. Uygulamayı Çalıştırma

Uygulamayı çalıştırabilmek için tüm portları açmamız gerekiyor ve hepsi açıldığında ekranlarımızda şöyle bir şey görmeliyiz:

görüntü açıklaması

Veritabanına localhost ve 5432 portunu kullanarak bağlanabiliyoruz. Bağlantı dizesi şudur: jdbc:postgresql://localhost:5432/wlsm . Ve ona erişmek için admin / admin kullanıcı adı/şifre kombinasyonunu kullanırız.


Herhangi bir test yapmadan önce yapmamız gereken ilk şey Piquinho kimliğini bilmektir ve bunu Intellij veritabanı araçlarını aşağıdaki gibi kullanarak yapabiliriz:

görüntü açıklaması

Projenin kök klasöründe test-requests.http adında bir dosya bulunmaktadır. Bu, açık bağlantı noktalarımıza karşı REST istekleri oluşturmaya yönelik bir karalama dosyasıdır:

 ### GET http://localhost:8080/app/v1/listener/info ### POST http://localhost:8080/app/v1/listener/create Content-Type: application/json { "animalId": "2ffc17b7-1956-4105-845f-b10a766789da", "latitude": 52505252, "longitude": 2869152 } ### POST http://localhost:8081/api/v1/collector/animals Content-Type: application/json { "animalId": "2ffc17b7-1956-4105-845f-b10a766789da", "latitude": 52505252, "longitude": 2869152 }


Bu dosyayı kullanabilmek için, bu örnekte yalnızca kimliği 2ffc17b7-1956-4105-845f-b10a766789da d5ad0824-71c0-4786-a04a-ac2b9a032da4 değiştirmemiz gerekiyor. Bu durumda koleksiyoncudan ya da dinleyiciden istekte bulunabiliriz. Her iki istek de çalışmalı ve daha sonra istek başına bu tür bir yanıt görmeliyiz:

 { "animalId": "d5ad0824-71c0-4786-a04a-ac2b9a032da4", "latitude": 52505252, "longitude": 2869152 } Response file saved. > 2024-04-12T001024.200.json Response code: 200 (OK); Time: 7460ms (7 s 460 ms); Content length: 91 bytes (91 B)


Her iki port da açık olduğundan ve bu noktada aynı veri yükünü paylaştıklarından, dinleyiciye ve toplayıcıya aynı istekleri gerçekleştirebiliriz. Bu iki isteği yaptıktan sonra sonuçları animal_locations tablosunda bulmalıyız:

görüntü açıklaması

Yani bu yalnızca kümenin doğru çalıştığını doğrular ve artık politikaları Kuma ağımızla test etmeye hazırız.

VII. MeshTrafficPermission - Bölüm I

MeshTrafficPermission Kuma'da seçebileceğimiz özelliklerden biri ve muhtemelen en çok kullanılanı.


Ama önce Kuma kontrol uçağını keşfetmek için biraz zaman ayıralım. Tüm yönlendirme işlemleri devam ederken localhost:5681/gui adresine gidebilir ve Kuma ağlarımızı görselleştirebiliriz. Ana sayfada şöyle bir şey görmeliyiz:

görüntü açıklaması

Şu anda görülecek pek bir şey yok ama şimdi MeshTrafficPermission uygulayalım:

 echo "apiVersion: kuma.io/v1alpha1 kind: MeshTrafficPermission metadata: namespace: kuma-system name: mtp spec: targetRef: kind: Mesh from: - targetRef: kind: Mesh default: action: Allow" | kubectl apply -f -


Bunu uyguladığımızda şöyle bir yanıt almamız gerekir: meshtrafficpermission.kuma.io/mtp created .

VIII. ağ

Kümemizin kurulumu söz konusu olduğunda ağın uygulanması pek bir şeyi değiştirmez. Yaptığı şey, trafik yönlendirme politikaları oluşturmamıza izin vermektir.


Aralarından seçim yapabileceğimiz pek çok şey var ancak seçebileceğimiz en belirgin şeylerden biri mTLS. Aksi halde karşılıklı TLS olarak anılan bu, çok kısa bir ifadeyle, taraflar arasında kimlik oluşturmak ve şifreli veri trafiği oluşturmak amacıyla sertifikaların karşılıklı olarak kabul edilmesi ve doğrulanması anlamına gelir.


Bu, bu basit Mesh yapılandırmasını kullanarak bizim için otomatik olarak yapılabilir:

 echo "apiVersion: kuma.io/v1alpha1 kind: Mesh metadata: name: default spec: mtls: enabledBackend: ca-1 backends: - name: ca-1 type: builtin" | kubectl apply -f -


Bu politikayı uyguladıktan sonra şuna benzer bir uyarıyla karşılaşabiliriz:

Warning: resource meshes/default is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.

Şimdilik bu uyarıyı görmezden gelebiliriz.

IX MeshTrafficPermission - Bölüm II

Şimdi işin eğlenceli kısmı geliyor ve yapacağımız ilk şey tüm bölmeler arasındaki tüm trafiği devre dışı bırakmak olacak:

 echo " apiVersion: kuma.io/v1alpha1 kind: MeshTrafficPermission metadata: namespace: wlsm-namespace name: mtp spec: targetRef: kind: Mesh from: - targetRef: kind: Mesh default: action: Deny" | kubectl apply -f -


meshtrafficpermission.kuma.io/mtp configured onay mesajını aldıktan sonra, port yönlendirmelerden herhangi birini kullanarak herhangi bir istekte bulunmaya çalışırsak şunu elde ederiz:

 HTTP/1.1 500 Internal Server Error Content-Type: application/json Content-Length: 133 { "timestamp": "2024-04-12T07:09:26.718+00:00", "path": "/create", "status": 500, "error": "Internal Server Error", "requestId": "720749ce-56" } Response file saved. > 2024-04-12T090926.500.json Response code: 500 (Internal Server Error); Time: 10ms (10 ms); Content length: 133 bytes (133 B)


Bu, bölmeler arasındaki tüm trafiğin reddedildiği anlamına gelir. Şu anda sahip olduğumuz şey, kuruluşumuz içindeki olası kötü aktörlere karşı korunan bir dahili sistemdir, ancak artık tüm bölmeler arasındaki trafiği de engelledik. Yani mTLS harika bir şey ama tüm trafiği engellemek hiç de öyle değil.


Bunu mükemmelleştirmenin yolu basitçe tümünü DENY kuralına istisnalar yapmaktır ve bunu yapmak için dinleyici ile toplayıcı ve toplayıcı ile veritabanı arasındaki trafiğe izin verecek bir politikaya ihtiyacımız var. Toplayıcı ve veritabanı arasındaki trafikle başlayalım:

 echo " apiVersion: kuma.io/v1alpha1 kind: MeshTrafficPermission metadata: namespace: kuma-system name: wlsm-database spec: targetRef: kind: MeshService name: wlsm-database-deployment_wlsm-namespace_svc_5432 from: - targetRef: kind: MeshService name: wlsm-collector-deployment_wlsm-namespace_svc_8081 default: action: Allow" | kubectl apply -f -


Bu durumda yaptığımız şey, veri trafiğinin targetRef toplayıcıdan targetRef veritabanına akmasına izin vermektir. Bunu bilmiyorsanız, Kuma'nın tıpkı hostname oluşturma gibi işlevsel amaçlar için de kullanılan name nasıl yorumladığını not etmek önemli olabilir.


Bu name oluşturmanın genel yolu şu şekildedir:

<service name>_<namespace>_svc_<service port>


Bu durumda ayırıcı bir alt çizgidir ve bu şekilde bir ad oluşturmak Kuma tam olarak neye izin verildiğini bilmesini sağlar. Bu durumda, bu politikayı uygularsak şu yanıtı aldıktan sonra toplayıcıya istek gönderebileceğiz: meshtrafficpermission.kuma.io/wlsm-database created .


Ve bunları yaparken, konum kaydının toplayıcıya gönderildiğini doğrulayan yanıt artık 200 olmalıdır:

 POST http://localhost:8081/api/v1/collector/animals HTTP/1.1 200 OK Content-Type: application/json Content-Length: 91 { "animalId": "a3a1bc1c-f284-4876-a84f-f75184b6998f", "latitude": 52505252, "longitude": 2869152 } Response file saved. > 2024-04-12T091754.200.json Response code: 200 (OK); Time: 1732ms (1 s 732 ms); Content length: 91 bytes (91 B)


Ancak dinleyici ile toplayıcı arasındaki trafiğe ilişkin istisnaları hâlâ tanımlamadık; dolayısıyla bu şekilde bir istekte bulunmak şu şekilde sonuçlanacaktır:

 HTTP/1.1 500 Internal Server Error Content-Type: application/json Content-Length: 133 { "timestamp": "2024-04-12T07:18:54.149+00:00", "path": "/create", "status": 500, "error": "Internal Server Error", "requestId": "e8973d33-62" } Response file saved. > 2024-04-12T091854-1.500.json Response code: 500 (Internal Server Error); Time: 10ms (10 ms); Content length: 133 bytes (133 B)


Ve bu elbette bekleniyor. Şimdi bu veri trafiğine başka bir politika uygulayalım:

 echo " apiVersion: kuma.io/v1alpha1 kind: MeshTrafficPermission metadata: namespace: kuma-system name: wlsm-collector spec: targetRef: kind: MeshService name: wlsm-collector-deployment_wlsm-namespace_svc_8081 from: - targetRef: kind: MeshService name: wlsm-listener-deployment_wlsm-namespace_svc_8080 default: action: Allow" | kubectl apply -f -


Artık dinleyiciden toplayıcıya isteklerin gerçekleştirilmesini mümkün kılıyoruz:

 POST http://localhost:8080/app/v1/listener/create HTTP/1.1 200 OK Content-Type: application/json Content-Length: 91 { "animalId": "a3a1bc1c-f284-4876-a84f-f75184b6998f", "latitude": 52505252, "longitude": 2869152 } Response file saved. > 2024-04-12T092039-2.200.json Response code: 200 (OK); Time: 14ms (14 ms); Content length: 91 bytes (91 B)

X - MeshFaultInjection

Son olarak ve örnek olarak başka bir özellik vermek gerekirse, MeshFaultInjection adlı başka bir özelliği de kullanabiliriz; bu, Kuma ile testler yaparken çok faydalı olabilir. Ağımızdaki potansiyel sorunları simüle edebilir ve örneğin hata işlemenin doğru yapılıp yapılmadığını kontrol edebiliriz.


Ayrıca yapılandırmış olabileceğimiz devre kesicilerin hatalı bağlantılara veya yüksek hızlı isteklere nasıl tepki verebileceği gibi diğer şeyleri de kontrol edebiliriz.


Öyleyse deneyelim. MeshFaultInjection uygulamanın bir yolu şudur:

 echo " apiVersion: kuma.io/v1alpha1 kind: MeshFaultInjection metadata: name: default namespace: kuma-system labels: kuma.io/mesh: default spec: targetRef: kind: MeshService name: wlsm-collector-deployment_wlsm-namespace_svc_8081 from: - targetRef: kind: MeshService name: wlsm-listener-deployment_wlsm-namespace_svc_8080 default: http: - abort: httpStatus: 500 percentage: 50" | kubectl apply -f -


Bu politika ile dinleyiciden giden ve toplayıcıya gelen trafiğin %50 başarı şansına sahip olacağını söylüyoruz. İstek sonuçları tahmin edilemez; bu nedenle, bu politikayı uyguladıktan sonra dinleyici uç noktasına hatalar veya başarılı istekler gelmesini bekleyebiliriz.

 POST http://localhost:8080/app/v1/listener/create HTTP/1.1 500 Internal Server Error Content-Type: application/json Content-Length: 133 { "timestamp": "2024-04-12T07:28:00.008+00:00", "path": "/create", "status": 500, "error": "Internal Server Error", "requestId": "2206f29e-78" } Response file saved. > 2024-04-12T092800.500.json Response code: 500 (Internal Server Error); Time: 8ms (8 ms); Content length: 133 bytes (133 B)


 POST http://localhost:8080/app/v1/listener/create HTTP/1.1 200 OK Content-Type: application/json Content-Length: 91 { "animalId": "a3a1bc1c-f284-4876-a84f-f75184b6998f", "latitude": 52505252, "longitude": 2869152 } Response file saved. > 2024-04-12T092819.200.json Response code: 200 (OK); Time: 13ms (13 ms); Content length: 91 bytes (91 B)


Son olarak, ilgimizi çeken bir konu olarak, animal_location tablomuzun şu an nasıl göründüğüne bir göz atabiliriz:

Görüntü açıklaması

XI - Sonuç

Umarım bu makaleyi buraya kadar takip edebilmişsinizdir ve makinenizde çalışan bir kümeye sahip olabilmişsinizdir. Yine de bu makaleyi okuduğunuz ve Kuma'yı anlamak ve hakkında daha fazla bilgi edinmek için biraz zaman ayırdığınız için teşekkür ederiz. Kişisel olarak bunun harika bir kullanım alanı olduğunu ve ağımızı ve çevremizi yapılandırmayı ve çok daha ayrıntılı bir şekilde kontrol altına almayı mümkün kıldığı için Kuma için harika bir gelecek görüyorum.


Kurumsal versiyonu Kong-Mesh oldukça eksiksiz görünüyor. Kuma açık kaynaktır. hem test için hem de kurumsal açıdan harika görünüyor. Ağlar konusunu çok ilginç buluyorum ve Kuma ağların nasıl çalıştığını öğrenmek ve ağımızdaki veri akışını nasıl daha iyi kontrol edebileceğimiz konusunda fikir sahibi olmak için harika bir yol sağladığını düşünüyorum.


Hizmetlerimizin durumunu görmek istiyorsak, şu localhost konumundaki Kuma kontrol düzlemimize gidebiliriz: http://localhost:5681/gui/meshes/default/services?page=1&size=50 :

Görüntü açıklaması

Kuma kontrol düzleminde ayrıca kurulu politikalara bakabilir, bölmelerimizin durumunu kontrol edebilir, arka planda neler olduğunu izleyebilir ve genel olarak ağımızda neler olup bittiğine ve bunların nasıl gerçekleştiğine dair genel bir bakışa sahip olabiliriz. yapılandırılmıştır. Sizi uygulamayı inceleyerek yüklediğimiz politikaların durumunu kontrol edip edemeyeceğinizi görmeye davet ediyorum. Kuma kontrol düzlemi, diğer adıyla GUI, Mesh'imizde anlaşılması ve takip edilmesi kolay olacak şekilde tasarlanmıştır.

XII - Kaynaklar

Ayrıca JESPROTECH YouTube kanalımda da bununla ilgili bir video hazırladım: