Kuma
すぐに学習し始めるには、クラスターが最も重要な要素の 1 つです。次に、Kubernetes (別名k8s
) 内のポッドの状態を確認するコマンドも必要で、 Kuma
インストールでき、最後に、いくつかのKuma
コマンドを発行できることも必要です。
つまり、 Kuma
の準備を整えるには、 4 つの必須コマンドをインストールする必要があるということです。これらのコマンドは次のとおりです。
kind
- これは Docker では Kubernetes とも呼ばれます。これは、 kubectl
のみで作成する機能を活用するコマンドです。
kubectl
- すでにk8s
の操作に慣れている場合、おそらくこのリストで最も期待されるものでしょう。これは、 k8s
クラスターにコマンドを発行する方法です。
helm
- Helm を使用すると、 Kuma
コントロール プレーンのインストールなど、非常に便利なスクリプトを実行できます。
kumactl
- このガイドではこのコマンドをあまり使用しませんが、その使用方法を知っておくことは重要です。
このガイドでは、 Ubuntu
でこれを行う方法を説明します。これらはすべてUbuntu
システムでテストされています。Mac Mac-OS
やWindows
、またはお持ちのその他のオペレーティング システムにこれをインストールする方法に関するガイドにご興味がある場合は、私の YouTube チャンネルJESPROTECH
コミュニティで声をかけてください。
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 ディストリビューション内でもシステムごとに異なる場合があります。
helm
とkubectl
コマンドは両方とも、特定の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
のインストールは非常に簡単になります。
sudo apt-get install -y kubelet kubeadm kubectl
kubelet
、 kubeadm
、 kubectl
コマンドは必須ではありませんが、インストールしておくことをお勧めします。
すでにご想像のとおり、 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
インストールも他のアプリケーションとはかなり異なります。この場合、 Linux
ではpacman
またはbrew
使用できます。私はこれまでMac-OS
でbrew
主に使用しており、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
クラッシュする点に気付くと思います。
kind create cluster --name=wlsm-mesh-zone kubectl cluster-info --context kind-wlsm-mesh-zone
最初のコマンドは、 wlsm-mesh-zone
という名前のクラスターを作成します。これは、Kuma をインストールするために使用するクラスターです。2 番目のコマンドは、クラスターのステータスを確認するために使用されます。
前に述べたように、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 スクリプトを実行するだけです。
このブログ投稿の例として提供したコードについては、語るべきことがたくさんあるかもしれません。ただし、この場合は、いくつかの重要な側面に焦点を当てましょう。リスナー サービスからコレクター、そしてデータベースへと進みます。サービスをローカルで実行する場合、またはコンテナーを起動するために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()) } } }
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 クラスター内でのポッドのデプロイメントがどのようになるかを定義する方法です。ここで注目すべき重要な点は、 image
、 imagePullPolicy
、および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 つあります。種を定義するのは、種と属です。これらは、 families
とgenuses
というテーブルです。
テーブル「 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-plane
、 kube-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
アプリケーションを実行するには、すべてのポートを開く必要があります。すべてのポートが開くと、画面に次のような表示がされます。
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 メッシュでポリシーをテストする準備が整いました。
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
のような応答が返されるはずです。
メッシュを適用しても、クラスターのセットアップに関しては大きな変化はありません。メッシュによってトラフィック ルーティング ポリシーを設定できるようになります。
選択できるものはたくさんありますが、最も明白なものの 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.
今のところ、この警告は無視できます。
さて、ここからが楽しい部分です。まず最初に、すべてのポッド間のすべてのトラフィックを無効にします。
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)
最後に、別の機能を例として挙げると、 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
テーブルが現在どのようになっているかを見てみましょう。
ここまでこの記事を読んでいただき、マシン上でクラスターを実行できたことを願っています。この記事を読んでいただき、Kuma について理解を深めるために時間を割いていただき、ありがとうございました。個人的には、 Kuma
はネットワークと環境をより細かく構成および制御できるようになるため、非常に有効に活用でき、将来性も高いと考えています。
エンタープライズ版のKong-Mesh
はかなり完成度が高いようです。Kuma はオープンソースで、テストにもエンタープライズにも最適のようです。メッシュというテーマは非常に興味深いと思います。Kuma Kuma
メッシュの仕組みを学び、ネットワーク内のデータフローをより適切に制御する方法を理解するための優れた方法を提供していると思います。
サービスのステータスを確認したい場合は、次のlocalhost
の場所にあるKuma
コントロール プレーンに移動するだけです: http://localhost:5681/gui/meshes/default/services?page=1&size=50 :
Kuma コントロール プレーンでは、インストールされているポリシーを確認したり、ポッドの状態を確認したり、バックグラウンドで何が起こっているかを監視したり、一般的にメッシュで何が起こっているか、どのように構成されているかの概要を把握したりすることもできます。アプリケーションを試してみて、インストールしたポリシーの状態を確認できるかどうかを確認してください。Kuma コントロール プレーン (GUI) は、メッシュを簡単に理解して追跡できるように作られています。
これに関するビデオも私のJESPROTECH YouTube チャンネルで作成しました。