Kuma Meshes Head-On - 新手指南 为了快速开始学习 ,我们需要的最重要的东西之一就是集群。然后,我们还需要一个命令来找出 Kubernetes(又名 )中 pod 的状态,我们还需要能够安装 ,最后,我们还需要能够发出一些 命令。 Kuma k8s Kuma Kuma 简而言之,我们需要安装 4 个基本命令,以便为 做好一切准备。这些命令是: Kuma - 在 Docker 中也称为 Kubernetes。这是一个利用仅使用 创建内容的权重的命令。 kind kubectl - 如果你已经习惯使用 ,那么这可能是此列表中最受期待的一个。这就是我们可以向 集群发出命令的方式。 kubectl k8s k8s -Helm 允许我们执行一些非常方便的脚本,其中包括安装 控制平面。 helm Kuma - 我们不会在本指南中频繁使用此命令,但了解如何使用它很重要。 kumactl 本指南将告诉您如何在 中执行此操作。所有这些都已在 系统中进行了测试。如果您对如何在 或 或您可能拥有的任何其他操作系统中安装此软件的指南感兴趣,请在我的 YouTube 频道 中给我留言。 Ubuntu Ubuntu Mac-OS Windows JESPROTECH 社区 一、安装命令 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 需要注意的是,命令 将安装在 中。这可能因系统而异,即使在 Linux 发行版中也是如此。 kind /usr/local/bin/kind 安装证书和 GPG 密钥 和 命令都需要在某些 密钥存在的情况下进行安装。我们可以这样将它们添加到我们的 Linux 发行版的本地存储库中: helm kubectl GPG 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 cd ~ || exit; curl -L https://kuma.io/installer.sh | VERSION=2.6.1 sh - 发出此命令之前,请确保位于 文件夹中。将 安装在易于访问且易于发现的位置非常重要,例如,如果我们决定删除它。 HOME Kuma 完成后,将 文件夹添加到我们的 PATH 中也非常重要: bin export PATH=~/kuma-2.6.1/bin:$PATH; 将此行添加到启动脚本的末尾或中间的任何地方将使此过程变得简单。您的启动脚本可能是 、 、 中的任何一个,也可能采用其他形式。 .bashrc .zshrc .profile k9s 安装 也与其他应用程序有很大不同。在这种情况下,我们可以使用 或 for 。我主要在 上使用 ,在 Linux 中几乎不需要它,但在这种情况下,它非常需要,因此首先,我们需要像这样安装 brew: k9s pacman brew Linux Mac-OS brew /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 一旦 brew 安装完成,我们要做的就是安装 (“ ”): k9s kanines brew install derailed/k9s/k9s 需要考虑的一件重要的事情是,当您第一次安装并开始运行 时您可能会注意到这一点,那就是如果它监控的集群被删除和/或添加, 将崩溃。 k9s k9s 二、创建集群 kind create cluster --name=wlsm-mesh-zone kubectl cluster-info --context kind-wlsm-mesh-zone 第一个命令创建一个名为 集群。这只是我们将用来安装 Kuma 的集群。第二个命令用于检查集群的状态。 wlsm-mesh-zone III. 创建本地 Docker 注册表 正如我之前提到的,我们可以非常轻松地创建一个 docker 注册表。虽然创建它听起来很容易,但执行此操作的脚本却很繁琐。因此,最好的办法就是复制并粘贴他们网站上已有的脚本。在这里,我们可以下载此 : 脚本 #!/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 registry,我们只需要运行这个bash脚本。 项目的根文件夹 四、本法典是如何制定的 关于我为本博文示例提供的代码可能有很多话要说。但是,在这种情况下,我们只关注几个关键方面。让我们从 开始,到 ,再到 。当我们在本地运行服务或甚至使用 配置来启动容器时,通常,我们使用 DNS 属性名称,这些名称会自动分配为容器名称或我们使用 配置的名称。 侦听器服务 收集器 数据库 docker-compose hostname 使用 ,还有一组规则使主机名在整个集群中可用。让我们看一下侦听器和收集器示例: 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 prod application-prod.properties 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 个以点分隔的元素。最后三个是静态的,前两个取决于我们尝试访问的机器。在左侧,我们放置服务名称,后跟命名空间。这对于了解集群内容器如何相互连接非常重要。 代码中最值得关注的部分当然是控制器和服务。控制器如下所示: @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 netty tomcat 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 此配置中有三个块。第一个块是命名空间块。命名空间配置对于允许 Kuma 能够注入应用策略所需的 Envoy Sidecar 至关重要。如果没有定义的命名空间, 将无法执行此操作。配置 kuma 时我们需要注意的另一件事是,命名空间必须包含 kuma 将识别的正确标签: kuma kuma.io/sidecar-injection: enabled. 具有正确标签的命名空间定义对于 Kuma 的运行至关重要。在第二个块中,我们找到了部署的定义。这就是我们定义 Pod 在 Kubernetes 集群中的部署方式的方式。这里需要重点关注的是 、 和 是我们正在使用的 Docker 镜像的完整标签。 image imagePullPolicy containerPort 使用 创建的 Docker 注册表配置的端口是 5001,它包含在我们镜像的标签中。它既可以用作标签,也可以用作与 Docker 注册表的连接。这样,我们就可以提取镜像并创建容器以在 Kubernetes 环境中运行。 kind 但是,当然,为了能够使用图像,我们需要创建它们,为此,让我们看看如何在 示例和 示例中完成此操作。 的 docker 映像定义如下: listener database listener 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"] 这一切都从名为 基础镜像开始。之后,我们只需复制通过构建项目创建的 jar,然后将其复制到我们的镜像中。在此之前,我们还将 复制到容器中并定义 以使用它。 只需像这样调用 jar: eclipse-temurin:21-jdk-alpine entrypoint.sh ENTRYPOINT entrypoint #!/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 只是一种环游世界的旅行信天翁的名字,它身上附有传感器,我们正在读取传感器发送给我们的数据。有两个定义物种的表。即物种和定义物种的属。这些是 和 表。 piquinho families genuses 表 定义了动物所属的物种。最后,我们在同名表中定义一种 ,其中注册了动物的物种和名称。数据库如下所示: species animal 为了构建、创建图像并启动我们的项目,我们可以运行 中提供的以下命令: Makefile make make create-and-push-images make k8s-apply-deployment 第一个 make 只是一个 命令。第二个命令使用了变量: gradle build 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 这只是遍历每个模块并使用标准通用命令(该命令根据 中给出的每个值进行更改)来创建映像并将其推送到端口 5001 上的本地注册表。按照相同的策略,我们可以使用第三个命令来部署我们的 pod。第三个命令使用不同的循环,如下所示: MODULE_TAGS @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 此时我们应该观察到 、 和在我们自己的自定义 中运行的所有服务的存在。我们的集群与外界隔离,为了能够访问不同的端口,我们需要为想要访问的每个 pod 创建 。为此,我们可以在单独的选项卡中发出以下命令: 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 VI. 运行应用程序 为了运行该应用程序,我们应该打开所有端口,当所有端口都打开时,我们应该在屏幕上看到如下内容: 我们可以使用 和端口 连接到数据库。连接字符串如下: 。然后,为了访问它,我们使用用户名/密码组合 / 。 localhost 5432 jdbc:postgresql://localhost:5432/wlsm admin admin 在进行任何测试之前,我们需要做的第一件事就是知道 的 id,我们可以通过使用 Intellij 数据库工具来完成此操作,如下所示: Piquinho 在项目的根文件夹中,有一个名为 文件。这是一个针对我们开放的端口创建 REST 请求的临时文件: test-requests.http ### 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) 由于两个端口都已打开,并且此时它们共享相同的有效负载类型,因此我们可以向侦听器和收集器执行相同的请求。发出这两个请求后,我们应该在表 中找到结果: animal_locations 因此,这仅确认集群正在正确运行,现在,我们准备使用 Kuma 网格测试策略。 VII. MeshTrafficPermission - 第一部分 是我们可以在 Kuma 中选择的功能之一,而且它可能是最常用的功能。 MeshTrafficPermission 但首先,让我们花点时间探索一下 Kuma 控制平面。启用所有转发后,我们只需转到 并可视化我们的 Kuma 网格。在主页上,我们应该看到类似以下内容: localhost:5681/gui 目前还没有什么可看的,但是现在让我们应用 : 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 八、网格 在集群设置方面,应用网格不会带来太大变化。它的作用是让我们设置流量路由策略。 我们可以选择的东西有很多,但最明显的选择之一是 也称为相互 TLS,简而言之,这意味着证书被相互接受和验证,以便在各方之间建立身份并建立加密数据流量。 mTLS. 使用这个简单的 配置我们可以自动完成这一点: 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 MeshTrafficPermission - 第二部分 现在到了有趣的部分,我们要做的第一件事就是禁用所有 pod 之间的所有流量: 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) 这意味着 Pod 之间的所有流量都被拒绝。我们现在拥有一个内部系统,可以防止组织内可能的不良行为者,但我们现在也阻止了所有 Pod 之间的流量。因此, 是一件好事,但阻止所有流量则完全不是好事。 mTLS 实现此目的的方法很简单,就是对 all 规则进行例外处理,为此,我们需要一个策略来允许侦听器和收集器以及收集器和数据库之间的通信。让我们从收集器和数据库之间的通信开始: 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 - 在这种情况下,我们所做的是允许数据流量从 收集器流向 数据库。如果您不知道这一点,也许重要的是注意 Kuma 如何解释 ,就像 创建一样,它也用于功能目的。 targetRef targetRef name hostname 构建这些 的通用方法是这样的: 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 最后,仅提供另一个功能作为示例,我们还可以使用另一个名为 的功能,该功能在使用 执行测试时非常有用。例如,我们可以模拟网格中的潜在问题,并检查错误处理是否正确完成。 MeshFaultInjection Kuma 我们还可以检查其他事项,例如我们配置的断路器如何对故障连接或高速率请求做出反应。 那么,让我们尝试一下。应用 的一种方法如下: MeshFaultInjection 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 它的企业版本 似乎相当完善。Kuma 是开源的。它非常适合测试,也非常适合企业。我发现网格这个主题非常有趣,我认为 提供了一种很好的方式来了解网格的工作原理,并让我们了解如何更好地控制网络内的数据流。 Kong-Mesh Kuma 如果我们想要查看服务状态,我们可以直接转到此 位置的 控制平面: : localhost Kuma http://localhost:5681/gui/meshes/default/services?page=1&size=50 在 Kuma 控制平面中,我们还可以查看已安装的策略、检查 Pod 的状态、监视后台正在发生的事情,并且通常只需概览一下网格中正在发生的事情及其配置方式。我邀请您浏览该应用程序,看看您是否可以检查已安装策略的状态。Kuma 控制平面(又称 GUI)的设计非常精确,易于理解和跟踪我们的网格。 XII-资源 什么是相互 TLS (mTLS)? K9 南北交通 东西向流量 Kuma Service Mesh 入门 在 Kubernetes 上部署 Kuma 本地注册表 我还在我的 YouTube 频道上制作了有关它的视频: JESPROTECH https://youtu.be/KE3VTYtLvnI?embedable=true