paint-brush
クマが正面からメッシュ化 - 知っておくべきことすべて@jesperancinha
707 測定値
707 測定値

クマが正面からメッシュ化 - 知っておくべきことすべて

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

長すぎる; 読むには

Kuma をすぐに学習し始めるには、クラスターが最も重要な要素の 1 つです。次に、Kubernetes (別名 k8s) 内のポッドのステータスを確認するコマンドも必要です。
featured image - クマが正面からメッシュ化 - 知っておくべきことすべて
João Esperancinha HackerNoon profile picture
0-item
1-item

Kuma Meshes を真っ向から攻略する - 初心者向けガイド

Kumaすぐに学習し始めるには、クラスターが最も重要な要素の 1 つです。次に、Kubernetes (別名k8s ) 内のポッドの状態を確認するコマンドも必要で、 Kumaインストールでき、最後に、いくつかのKumaコマンドを発行できることも必要です。


つまり、 Kumaの準備を整えるには、 4 つの必須コマンドをインストールする必要があるということです。これらのコマンドは次のとおりです。

  • kind - これは Docker では Kubernetes とも呼ばれます。これは、 kubectlのみで作成する機能を活用するコマンドです。


  • kubectl - すでにk8sの操作に慣れている場合、おそらくこのリストで最も期待されるものでしょう。これは、 k8sクラスターにコマンドを発行する方法です。


  • helm - Helm を使用すると、 Kumaコントロール プレーンのインストールなど、非常に便利なスクリプトを実行できます。


  • kumactl - このガイドではこのコマンドをあまり使用しませんが、その使用方法を知っておくことは重要です。


このガイドでは、 Ubuntuでこれを行う方法を説明します。これらはすべてUbuntuシステムでテストされています。Mac Mac-OSWindows 、またはお持ちのその他のオペレーティング システムにこれをインストールする方法に関するガイドにご興味がある場合は、私の YouTube チャンネルJESPROTECHコミュニティで声をかけてください。


I. コマンドのインストール


画像の説明


Docker の種類 ( k8s )

kind をインストールするには、次のコマンドを発行する必要があります。

 [ $(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 /usr/local/bin/kindにインストールされることに注意してください。これは、Linux ディストリビューション内でもシステムごとに異なる場合があります。


証明書と GPG キーのインストール

helmkubectlコマンドは両方とも、特定のGPGキーが存在している状態でインストールする必要があります。これを Linux aptディストリビューションのローカル リポジトリに追加するには、次の操作を行います。

 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

前の手順が完了すると、 Kubectlのインストールは非常に簡単になります。

 sudo apt-get install -y kubelet kubeadm kubectl


kubeletkubeadmkubectlコマンドは必須ではありませんが、インストールしておくことをお勧めします。


すでにご想像のとおり、 helmインストールも非常に簡単になりました。

 sudo apt-get install -y helm

クマ

Kumaインストールは、手動の手順が 1 つ必要となるため、少し面倒ですが、まず依存関係をダウンロードする必要があります。

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


このコマンドを発行する前に、必ずHOMEフォルダに移動してください。たとえば、Kuma を削除することにした場合など、簡単にアクセスでき、簡単に見つけられる場所にKumaをインストールしておくことが重要です。


それが終わったら、PATH にbinフォルダを追加することも非常に重要です。

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


この行をスタートアップ スクリプトの最後または途中に追加すると、このプロセスが簡単になります。スタートアップ スクリプトは、 .bashrc.zshrc.profileのいずれかになりますが、別の形式になる可能性もあります。


k9s

k9sインストールも他のアプリケーションとはかなり異なります。この場合、 Linuxではpacmanまたはbrew使用できます。私はこれまでMac-OSbrew主に使用しており、Linux ではほとんど必要ありませんでしたが、この場合は brew が非常に必要なので、まずは brew を次のようにインストールする必要があります。

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


brew のインストールが完了したら、 k9s (" kanines ") をインストールするだけです。

 brew install derailed/k9s/k9s


考慮すべき重要な点の 1 つは、 k9sをインストールして初めて実行し始めると、監視対象のクラスターが削除または追加された場合にk9sクラッシュする点に気付くと思います。


II. クラスターの作成

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


最初のコマンドは、 wlsm-mesh-zoneという名前のクラスターを作成します。これは、Kuma をインストールするために使用するクラスターです。2 番目のコマンドは、クラスターのステータスを確認するために使用されます。


III. ローカル Docker レジストリの作成

前に述べたように、Docker レジストリは非常に簡単に作成できます。作成するのは簡単そうに聞こえますが、これを行うためのスクリプトは一握りです。したがって、最善の方法は、Web サイトで既に利用可能なものをコピーして貼り付けることです。ここで、このスクリプトをダウンロードできます。

 #!/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



このスクリプトはプロジェクトのルート フォルダーにあります。ローカル Docker レジストリをインストールするには、この bash スクリプトを実行するだけです。


IV. コードの作成方法

このブログ投稿の例として提供したコードについては、語るべきことがたくさんあるかもしれません。ただし、この場合は、いくつかの重要な側面に焦点を当てましょう。リスナー サービスからコレクター、そしてデータベースへと進みます。サービスをローカルで実行する場合、またはコンテナーを起動するためにdocker-compose構成を使用する場合、通常は、コンテナー名またはhostnameで構成した名前として自動的に割り当てられる DNS 属性名を使用します。


k8sでは、ホスト名をクラスター全体で利用できるようにする一連のルールもあります。リスナーとコレクターの例を見てみましょう。


リスナーの例

リスナーは、 Spring frameworkを使用してJavaで開発されたアプリケーションです。この方法で作成されたすべてのアプリケーションと同様に、 application.propertiesファイルもあります。

 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


これらすべてのプロパティの中で、現時点で最も注目すべきはwslm.url.collectorプロパティです。 default設定では、コンテナ化された環境を使用せずにこのサービスをローカルで実行できます。ただし、 k8sクラスターでは、 collectorにアクセスできる必要があり、そのためには、定義ファイルapplication-prod.propertiesを含むprodプロファイルが必要です。

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


このプロパティは、ホストwlsm-collector-deployment.wlsm-namespace.svc.cluster.localにアクセスしようとします。このファイルは次の構成に従います。

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

ドットで区切られた要素が 5 つあります。最後の 3 つは静的で、最初の 2 つはアクセスしようとしているマシンによって異なります。左側には、サービス名とそれに続く名前空間を配置します。これは、クラスター内でコンテナーが相互にどのように接続されているかを理解するために重要です。


注目すべきコード部分は、もちろんコントローラーとサービスです。コントローラーは次のようになります。

 @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); } }


サービスは次のようになります。

 @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); } }


すでにお気づきかもしれませんが、この最初のアプリケーションは、このリポジトリ内のSpring Frameworkを使用して実装されたすべてのアプリケーションと同様にリアクティブであり、すべてtomcatではなくnettyを使用します。現時点では、このコードでのhazelcastの使用は無視できます。これは、このプロジェクトの後のバージョンで使用されます。


コレクターの例

この時点では、コレクターはリスナーとまったく同じように動作します。現時点での唯一の役割は、リスナーからデータベースにデータを中継することであり、そのためには、コレクターはデータベースがどこにあるかを正確に知る必要があります。 application.properties file of this projectで同じ分析を行ってみましょう。

 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


これらのプロパティは、サービスを開始するために最低限必要なものです。ただし、これはローカルで実行できるようにするためだけのものです。また、このサービスにはprodプロファイル ファイルもあり、ここのapplication-prod.propertiesで確認できます。

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


この場合、データベース接続はデータベースのホストを参照します。

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


これも、以前と同じ分析に従います。左側にはサービス名が表示され、その後に名前空間が続き、最後にsvc.cluster.localが追加されます。


このサービスでは、コントローラーとサービスも使用します。コントローラーは次のようになります。

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


サービスは次のようになります。

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


このサービスは、 applicationEventPublisherと呼ばれるイベント パブリッシャーを使用します。これは、このイベント リスナーで後で処理されるイベント ストリーミング アーキテクチャに従います。リアクティブ アーキテクチャ実装パラダイムを維持するためにr2dbcが使用されていることがすぐにわかります。

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



V. スクリプトの展開

k8sを使用したデプロイは通常非常に簡単な作業です。ただし、サービスに必要な構成を確認することも重要です。たとえば、リスナーの実装を見てみましょう。

 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


この構成には 3 つのブロックがあります。最初のブロックは名前空間ブロックです。名前空間構成は、ポリシーを適用するために必要な Envoy サイドカーを Kuma が挿入できるようにするために重要です。定義された名前空間がないと、 kumaこれを実行できません。kuma を構成するときに注意する必要があるもう 1 つの点は、名前空間に kuma が認識する適切なラベルが含まれている必要があることです。

kuma.io/sidecar-injection: enabled.


正しいラベルを持つ名前空間の定義は、Kuma を動作させるために不可欠です。2 番目のブロックには、デプロイメントの定義があります。これは、Kubernetes クラスター内でのポッドのデプロイメントがどのようになるかを定義する方法です。ここで注目すべき重要な点は、 imageimagePullPolicy 、およびcontainerPortです。image は、使用している Docker イメージの完全なタグです。


kindで作成された Docker レジストリ用に設定されるポートは 5001 で、これはイメージのタグに含まれています。これはタグとして機能するだけでなく、Docker レジストリへの接続としても機能します。これにより、イメージをプルして、Kubernetes 環境で実行するコンテナーを作成できます。


しかし、もちろん、イメージを使用するには、イメージを作成する必要があります。そのためには、 listener例とdatabase例でそれがどのように行われるかを見てみましょう。 listenerの Docker イメージは次のように定義されています。

 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"]


これはすべてeclipse-temurin:21-jdk-alpineというベースイメージから始まります。その後は、プロジェクトをビルドして作成された jar をコピーし、それをイメージにコピーします。その前に、 entrypoint.shもコンテナーにコピーし、それを使用するENTRYPOINTを定義します。 entrypoint 、次のように jar を呼び出すだけです。

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


databaseサービスは、オープンソースでオンラインで利用できるいくつかのスクリプトを使用するため、かなり異なります。

 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


このスクリプトは、次のファイルとフォルダーのコピーを docker init ディレクトリに作成します: create-multiple-postgresql-databases.shおよびmultiple 。最後に、これらのスクリプトで使用される変数を定義して、データベースとユーザー名/パスワードの組み合わせを定義します。


データベースは次のスキーマを使用して作成されます。

 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) );


そして、データの例として、 piquinhoという名前の動物を 1 匹登録します。 Piquinho は、世界中を旅するアホウドリの名前です。このアホウドリにはセンサーが取り付けられており、センサーから送信されるデータを読み取ります。種を定義するテーブルが 2 つあります。種を定義するのは、種と属です。これらは、 familiesgenusesというテーブルです。


テーブル「 species 、動物が属する種を定義します。最後に、種と動物の名前が登録される同じ名前のテーブルにanimalを定義します。データベースは次のようになります。
画像の説明

ビルドしてイメージを作成し、プロジェクトを開始するには、 Makefileで使用可能な次のコマンドを実行します。

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


最初の make は単なるgradle buildコマンドです。2 番目のコマンドでは変数が使用されました。

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


走る:

 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


これは単純にすべてのモジュールを調べ、 MODULE_TAGSで指定された値ごとに変化する標準の汎用コマンドを使用してイメージを作成し、ポート 5001 のローカル レジストリにプッシュします。同じ戦略に従って、3 番目のコマンドを使用してポッドをデプロイできます。この 3 番目のコマンドは、次のような異なるループを使用します。

 @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


この場合、すべてのデプロイメント スクリプトがすべてのサービスに適用されます。コマンドkubectl get pods --all-namespacesを実行すると、次の出力が表示されます。

 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


この時点で注目すべきは、 kuma-control-planekube-controller-manager 、および独自のカスタムwlsm-namespaceで実行されているすべてのサービスの存在です。クラスターは外部から分離されており、さまざまなポートにアクセスできるようにするには、アクセスするすべてのポッドに対してport-forwardingを作成する必要があります。そのためには、別々のタブで次のコマンドを発行します。

k9sを見てもこれを確認することができます:

画像の説明

 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. アプリケーションの実行

アプリケーションを実行するには、すべてのポートを開く必要があります。すべてのポートが開くと、画面に次のような表示がされます。

画像の説明

localhostとポート5432を使用してデータベースに接続できます。接続文字列はjdbc:postgresql://localhost:5432/wlsmです。これにアクセスするには、ユーザー名とパスワードの組み合わせadmin / adminを使用します。


テストを実行する前に最初に行う必要があるのは、 Piquinhoの ID を知ることです。これは、次のような Intellij データベース ツールを使用して行うことができます。

画像の説明

プロジェクトのルート フォルダーには、 test-requests.httpというファイルがあります。これは、開いているポートに対して REST リクエストを作成するためのスクラッチ ファイルです。

 ### 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 }


このファイルを使用できるようにするには、ID を、この例では2ffc17b7-1956-4105-845f-b10a766789daからd5ad0824-71c0-4786-a04a-ac2b9a032da4に置き換えるだけです。この場合、コレクターまたはリスナーからリクエストを行うことができます。両方のリクエストが機能し、その後、リクエストごとに次のような応答が表示されます。

 { "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)


両方のポートが開かれており、この時点では同じペイロード タイプを共有しているため、リスナーとコレクターに対して同じリクエストを実行できます。これら 2 つのリクエストを実行すると、テーブルanimal_locationsに結果が表示されます。

画像の説明

したがって、これはクラスターが正しく実行されていることのみを確認し、Kuma メッシュでポリシーをテストする準備が整いました。

VII. メッシュトラフィック許可 - パート I

MeshTrafficPermission 、Kuma で選択できる機能の 1 つであり、おそらく最もよく使用される機能です。


しかし、まずは Kuma コントロール プレーンを少し調べてみましょう。転送がすべてオンになっているので、 localhost:5681/guiにアクセスして Kuma メッシュを視覚化できます。メイン ページには、次のようなものが表示されます。

画像の説明

現時点では特に見るものはありませんが、 MeshTrafficPermissionを適用してみましょう。

 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 -


これを適用すると、 meshtrafficpermission.kuma.io/mtp createdのような応答が返されるはずです。

VIII. メッシュ

メッシュを適用しても、クラスターのセットアップに関しては大きな変化はありません。メッシュによってトラフィック ルーティング ポリシーを設定できるようになります。


選択できるものはたくさんありますが、最も明白なものの 1 つはmTLS.これは相互 TLS とも呼ばれ、簡単に言えば、当事者間の ID を確立し、暗号化されたデータ トラフィックを確立するために、証明書が相互に受け入れられ、検証されることを意味します。


これは、次のシンプルなMesh構成を使用して自動的に実行できます。

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


このポリシーを適用すると、次のような警告が表示される場合があります。

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.

今のところ、この警告は無視できます。

IX メッシュトラフィック許可 - パート II

さて、ここからが楽しい部分です。まず最初に、すべてのポッド間のすべてのトラフィックを無効にします。

 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後、いずれかのポート転送を使用してリクエストを送信しようとすると、次のメッセージが表示されます。

 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)


これは、ポッド間のすべてのトラフィックが拒否されていることを意味します。これで、組織内の潜在的な悪意のある行為者から保護された内部システムが得られましたが、すべてのポッド間のトラフィックもブロックされました。つまり、 mTLSは素晴らしいものですが、すべてのトラフィックをブロックするのはまったくもって素晴らしいことではありません。


これを完璧にするには、単に「すべてDENYルールに例外を設けるだけです。そのためには、リスナーとコレクターの間、コレクターとデータベースの間のトラフィックを許可するポリシーが必要です。まずは、コレクターとデータベースの間のトラフィックから始めましょう。

 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 -


この場合、私たちが行っていることは、データ トラフィックがtargetRefコレクターからtargetRefデータベースに流れるようにすることです。これを知らない場合は、 hostname作成と同様に機能目的で使用されるnameを Kuma がどのように解釈するかに注意することが重要です。


これらのnameを構築する一般的な方法は次のとおりです。

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


この場合、区切り文字はアンダースコアであり、このように名前を作成するとKuma何が許可されているかを正確に知らせることができます。この場合、このポリシーを適用すると、 meshtrafficpermission.kuma.io/wlsm-database createdという応答を受け取った後、コレクターにリクエストを送信できるようになります。


そして、それらを作成すると、応答は、場所レコードがコレクターに送信されたことを確認する200になるはずです。

 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)


ただし、リスナーとコレクター間のトラフィックに対する例外はまだ定義されていないため、そのようにリクエストを行うと、次の結果になります。

 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)


これは当然予想されたことです。では、このデータ トラフィックに別のポリシーを適用してみましょう。

 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 -


リスナーからコレクターへのリクエストを実行できるようになりました。

 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という別の機能も使用できます。これは、 Kumaでテストを実行するときに非常に便利です。たとえば、メッシュ内の潜在的な問題をシミュレートし、エラー処理が正しく行われているかどうかを確認できます。


また、設定したサーキットブレーカーが不良な接続や高レートのリクエストにどのように反応するかなど、他のことも確認できます。


それでは試してみましょう。MeshFaultInjection MeshFaultInjection適用する 1 つの方法は次のとおりです。

 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 -


このポリシーでは、リスナーからの送信トラフィックとコレクターへの受信トラフィックが 50% の確率で成功するとしています。リクエストの結果は予測できないため、このポリシーを適用した後、リスナー エンドポイントへのリクエストでエラーが発生するか、リクエストが成功するかが予想されます。

 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)


最後に、興味深いことに、 animal_locationテーブルが現在どのようになっているかを見てみましょう。

画像の説明

XI - 結論

ここまでこの記事を読んでいただき、マシン上でクラスターを実行できたことを願っています。この記事を読んでいただき、Kuma について理解を深めるために時間を割いていただき、ありがとうございました。個人的には、 Kumaはネットワークと環境をより細かく構成および制御できるようになるため、非常に有効に活用でき、将来性も高いと考えています。


エンタープライズ版のKong-Meshはかなり完成度が高いようです。Kuma はオープンソースで、テストにもエンタープライズにも最適のようです。メッシュというテーマは非常に興味深いと思います。Kuma Kumaメッシュの仕組みを学び、ネットワーク内のデータフローをより適切に制御する方法を理解するための優れた方法を提供していると思います。


サービスのステータスを確認したい場合は、次のlocalhostの場所にあるKumaコントロール プレーンに移動するだけです: http://localhost:5681/gui/meshes/default/services?page=1&size=50 :

画像の説明

Kuma コントロール プレーンでは、インストールされているポリシーを確認したり、ポッドの状態を確認したり、バックグラウンドで何が起こっているかを監視したり、一般的にメッシュで何が起こっているか、どのように構成されているかの概要を把握したりすることもできます。アプリケーションを試してみて、インストールしたポリシーの状態を確認できるかどうかを確認してください。Kuma コントロール プレーン (GUI) は、メッシュを簡単に理解して追跡できるように作られています。

XII - リソース

これに関するビデオも私のJESPROTECH YouTube チャンネルで作成しました。