paint-brush
Kuma Meshes Head-On - Mọi thứ bạn cần biếttừ tác giả@jesperancinha
707 lượt đọc
707 lượt đọc

Kuma Meshes Head-On - Mọi thứ bạn cần biết

từ tác giả João Esperancinha27m2024/04/13
Read on Terminal Reader

dài quá đọc không nổi

Để nhanh chóng bắt đầu học Kuma, một trong những điều quan trọng nhất chúng ta cần là cụm. Sau đó, chúng ta cũng cần một lệnh để tìm hiểu trạng thái của các nhóm trong Kubernetes (còn gọi là k8s)
featured image - Kuma Meshes Head-On - Mọi thứ bạn cần biết
João Esperancinha HackerNoon profile picture
0-item
1-item

Kuma Meshes Head-On - Hướng dẫn cho người mới bắt đầu

Để nhanh chóng bắt đầu học Kuma , một trong những điều quan trọng nhất chúng ta cần là cụm. Sau đó, chúng ta cũng cần một lệnh để tìm hiểu trạng thái của các nhóm trong Kubernetes (hay còn gọi là k8s ), chúng ta cũng cần có khả năng cài đặt Kuma và cuối cùng, chúng ta cũng cần có khả năng đưa ra một số lệnh Kuma .


Nói một cách dài dòng rằng chúng ta cần cài đặt 4 lệnh thiết yếu để chuẩn bị mọi thứ cho Kuma . Những lệnh này là:

  • kind - Cái này còn được gọi là Kubernetes trong Docker. Đây là lệnh tận dụng sức nặng của việc tạo nội dung chỉ với kubectl .


  • kubectl - Có lẽ là ứng dụng được mong đợi nhất trong danh sách này, nếu bạn đã quen làm việc với k8s . Đây là cách chúng tôi có thể ra lệnh cho cụm k8s của mình.


  • helm - Helm cho phép chúng tôi thực thi một số tập lệnh rất tiện dụng cho phép, trong số những tập lệnh khác, cài đặt mặt phẳng điều khiển Kuma .


  • kumactl - Chúng tôi sẽ không sử dụng lệnh này thường xuyên trong hướng dẫn này, nhưng điều quan trọng là bạn phải biết cách sử dụng nó.


Hướng dẫn này sẽ cho bạn biết cách thực hiện việc này trong Ubuntu . Tất cả điều này đã được thử nghiệm trong hệ thống Ubuntu . Nếu bạn quan tâm đến hướng dẫn về cách cài đặt tính năng này trong Mac-OS hoặc Windows hoặc bất kỳ hệ điều hành nào khác mà bạn có, vui lòng liên hệ với tôi tại cộng đồng kênh YouTube JESPROTECH của tôi.


I. Cài đặt lệnh


Mô tả hình ảnh


Loại ( k8s ) trong Docker

Để cài đặt loại, chúng ta cần đưa ra các lệnh sau:

 [ $(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


Điều quan trọng cần lưu ý là kind lệnh sẽ được cài đặt trong bạn /usr/local/bin/kind . Điều này có thể khác nhau tùy theo hệ thống, ngay cả trong các bản phân phối Linux.


Cài đặt chứng chỉ và khóa GPG

Cả hai lệnh helmkubectl đều cần được cài đặt với sự hiện diện của một số khóa GPG nhất định. Đây là cách chúng tôi có thể thêm chúng vào kho lưu trữ cục bộ của bản phân phối apt Linux của chúng tôi:

 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

Việc cài đặt Kubectl rất dễ dàng sau khi hoàn tất bước trước:

 sudo apt-get install -y kubelet kubeadm kubectl


Các lệnh kubelet , kubeadmkubectl không bắt buộc nhưng bạn nên cài đặt chúng.


cầm lái

Như bạn có thể đã đoán, helm giờ đây cũng rất dễ cài đặt:

 sudo apt-get install -y helm

kuma

Quá trình cài đặt Kuma có thể hơi phức tạp vì nó bao gồm một bước thủ công, nhưng trước tiên, chúng ta cần tải xuống các phần phụ thuộc của mình:

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


Hãy chắc chắn có trong thư mục HOME của bạn trước khi ban hành lệnh này. Điều quan trọng là phải cài đặt Kuma ở nơi dễ tiếp cận và dễ dàng phát hiện, chẳng hạn như nếu chúng tôi quyết định gỡ bỏ nó.


Khi chúng ta đã hoàn thành việc đó, việc thêm thư mục bin vào PATH của chúng ta cũng rất quan trọng:

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


Việc thêm dòng này vào cuối hoặc bất kỳ vị trí nào ở giữa tập lệnh khởi động của bạn sẽ giúp quá trình này trở nên dễ dàng. Tập lệnh khởi động của bạn có thể là bất kỳ tập lệnh nào trong số này .bashrc , .zshrc , .profile và có thể có dạng khác.


k9s

Việc cài đặt k9s cũng khá khác biệt so với các ứng dụng khác. Trong trường hợp này, chúng ta có thể sử dụng pacman hoặc brew cho Linux . Tôi chủ yếu sử dụng brew cho Mac-OS và hiếm khi cần đến nó trong Linux, nhưng trong trường hợp này, nó rất cần thiết và vì vậy, để làm điều đó trước tiên, chúng ta cần cài đặt brew như thế này:

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


Sau khi quá trình cài đặt brew hoàn tất, tất cả những gì chúng ta phải làm là cài đặt k9s (" kanines "):

 brew install derailed/k9s/k9s


Một điều quan trọng cần tính đến và có thể bạn sẽ nhận thấy điều này khi cài đặt và bắt đầu chạy k9s lần đầu tiên, đó là k9s sẽ gặp sự cố nếu cụm mà nó đang giám sát bị xóa và/hoặc thêm vào.


II. Tạo cụm

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


Lệnh đầu tiên tạo một cụm có tên wlsm-mesh-zone . Đây chỉ là một cụm mà chúng tôi sẽ sử dụng để cài đặt Kuma. Lệnh thứ hai được sử dụng để kiểm tra trạng thái của cụm.


III. Tạo một sổ đăng ký Docker cục bộ

Như tôi đã đề cập trước đó, chúng ta có thể tạo docker register khá dễ dàng. Nghe có vẻ dễ dàng nhưng kịch bản để thực hiện việc này lại rất ít. Vì vậy, điều tốt nhất nên làm là chỉ sao chép và dán loại đã có sẵn trên trang web của họ. Tại đây, chúng ta có thể tải xuống tập lệnh này:

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



Tập lệnh này có thể được tìm thấy trongthư mục gốc của dự án . Và để cài đặt sổ đăng ký docker cục bộ, chúng ta chỉ cần chạy tập lệnh bash này.


IV. Mã đã được tạo như thế nào

Có thể có rất nhiều điều để nói về đoạn mã mà tôi đã cung cấp làm ví dụ cho bài đăng trên blog này. Tuy nhiên, trong trường hợp này, chúng ta hãy chỉ tập trung vào một vài khía cạnh chính. Hãy bắt đầu từdịch vụ nghe đến bộ sưu tập và sau đó đếncơ sở dữ liệu . Thông thường, khi chúng tôi chạy các dịch vụ cục bộ hoặc thậm chí sử dụng cấu hình docker-compose để vận hành các vùng chứa, chúng tôi sử dụng các tên được phân bổ DNS tự động được gán làm tên vùng chứa hoặc tên mà chúng tôi định cấu hình bằng hostname .


Với k8s , cũng có một bộ quy tắc giúp tên máy chủ có sẵn trong toàn cụm. Chúng ta hãy xem các ví dụ về người nghe và người sưu tập:


Ví dụ về người nghe

Trình nghe là một ứng dụng được phát triển bằng Java sử dụng Spring framework . Giống như tất cả các ứng dụng được tạo theo cách này, cũng có tệp 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


Trong tất cả các thuộc tính này, thuộc tính quan trọng nhất cần tập trung vào lúc này là thuộc tính wslm.url.collector . Với cấu hình default , chúng ta có thể chạy dịch vụ này cục bộ mà không cần sử dụng bất kỳ môi trường được chứa trong container nào. Tuy nhiên, trong cụm k8s , chúng ta cần có khả năng truy cập vào bộ collector và để làm được điều đó, chúng ta có một hồ sơ prod với tệp định nghĩa application-prod.properties :

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


Thuộc tính này cố gắng truy cập máy chủ wlsm-collector-deployment.wlsm-namespace.svc.cluster.local . Tệp này tuân theo cấu hình này:

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

Chúng ta có 5 phần tử được phân cách bằng dấu chấm. Ba cái cuối cùng là tĩnh và hai cái đầu tiên phụ thuộc vào máy mà chúng tôi đang cố gắng tiếp cận. Ở bên trái, chúng tôi đặt tên dịch vụ theo sau là không gian tên. Điều quan trọng là phải hiểu cách các vùng chứa được kết nối với nhau trong cụm.


Tất nhiên, phần mã thú vị để xem xét là bộ điều khiển và dịch vụ. Bộ điều khiển trông như thế này:

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


Và dịch vụ trông như thế này:

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


Như bạn có thể đã nhận thấy, ứng dụng đầu tiên này, giống như tất cả các ứng dụng được triển khai bằng Spring Framework trong kho lưu trữ này, đều có tính phản ứng và tất cả chúng đều sử dụng netty thay vì tomcat . Hiện tại, chúng ta có thể bỏ qua việc sử dụng hazelcast trong mã này . Điều này sẽ được sử dụng cho các phiên bản sau của dự án này.


Ví dụ về người sưu tầm

Collector hoạt động theo cách giống hệt như Listener tại thời điểm này. Nhiệm vụ duy nhất của nó bây giờ là chuyển tiếp dữ liệu từ trình nghe đến cơ sở dữ liệu và để làm điều đó, trình thu thập chỉ cần biết chính xác cơ sở dữ liệu ở đâu. Hãy thực hiện phân tích tương tự trên 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


Những thuộc tính này là yêu cầu tối thiểu để dịch vụ có thể hoạt động. Tuy nhiên, điều này chỉ có thể chạy nó cục bộ. Và đối với dịch vụ này, chúng tôi cũng có tệp hồ sơ prod và chúng tôi có thể xem nó trong application-prod.properties tại đây:

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


Kết nối cơ sở dữ liệu trong trường hợp này đề cập đến máy chủ của cơ sở dữ liệu:

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


Điều này một lần nữa tuân theo phân tích tương tự như chúng ta đã thấy trước đây. Ở bên trái, chúng ta thấy tên dịch vụ, theo sau là không gian tên gắn thêm svc.cluster.local vào cuối.


Và đối với dịch vụ này, chúng tôi cũng sử dụng bộ điều khiển và dịch vụ. Bộ điều khiển trông như thế này:

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


Và dịch vụ trông như thế này:

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


Dịch vụ này sử dụng một nhà xuất bản sự kiện có tên là applicationEventPublisher , tuân theo kiến trúc truyền phát sự kiện sẽ được xử lý sau này trong trình xử lý sự kiện này. Chúng ta có thể dễ dàng thấy rằng nó sử dụng r2dbc để duy trì các mô hình triển khai kiến trúc phản ứng:

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



V. Triển khai tập lệnh

Triển khai thường là một nhiệm vụ rất đơn giản để thực hiện với k8s . Tuy nhiên, điều quan trọng là phải xem cấu hình cần thiết cho các dịch vụ của chúng tôi. Ví dụ: chúng ta hãy xem cách triển khai trình nghe:

 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


Có ba khối trong cấu hình này. Khối đầu tiên là khối không gian tên. Cấu hình không gian tên rất quan trọng để cho phép Kuma có thể đưa vào các phương tiện hỗ trợ đặc phái viên mà nó cần để áp dụng các chính sách. Nếu không có không gian tên được xác định, kuma sẽ không thể thực hiện được điều này. Một điều khác mà chúng ta cần chú ý khi định cấu hình kuma là không gian tên phải chứa nhãn thích hợp mà kuma sẽ nhận ra:

kuma.io/sidecar-injection: enabled.


Định nghĩa không gian tên với nhãn chính xác là rất quan trọng để Kuma hoạt động. Trong khối thứ hai, chúng ta tìm thấy định nghĩa về việc triển khai. Đây là cách chúng tôi xác định cách triển khai nhóm của chúng tôi trong cụm Kubernetes. Điều quan trọng cần tập trung ở đây là image , imagePullPolicycontainerPort . Hình ảnh là thẻ hoàn chỉnh của hình ảnh Docker mà chúng tôi đang sử dụng.


Cổng được định cấu hình cho sổ đăng ký docker của chúng tôi được tạo bằng kind là 5001 và cổng này được bao gồm trong thẻ cho hình ảnh của chúng tôi. Nó hoạt động như một thẻ nhưng cũng như một kết nối với sổ đăng ký Docker của chúng tôi. Bằng cách đó, chúng ta có thể kéo hình ảnh và tạo vùng chứa để chạy trong môi trường Kubernetes.


Tuy nhiên, tất nhiên, để có thể sử dụng hình ảnh, chúng ta cần tạo chúng và để làm được điều đó, hãy xem cách thực hiện điều đó trong ví dụ listener và ví dụ database . Hình ảnh docker cho listener được định nghĩa như thế này:

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


Tất cả điều này bắt đầu từ một hình ảnh cơ sở có tên là eclipse-temurin:21-jdk-alpine . Sau đó, chúng ta chỉ cần sao chép cái lọ được tạo bằng cách xây dựng dự án và sau đó tạo một bản sao của nó vào hình ảnh của chúng ta. Trước đó, chúng tôi cũng sao chép entrypoint.sh vào vùng chứa và xác định ENTRYPOINT để sử dụng nó. entrypoint chỉ cần gọi jar như thế này:

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


Dịch vụ database khá khác biệt vì nó sử dụng một số tập lệnh mã nguồn mở và có sẵn trực tuyến:

 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


Tập lệnh này tạo một bản sao của tệp và thư mục sau vào thư mục docker init: create-multiple-postgresql-databases.shmultiple . Cuối cùng, chúng tôi chỉ cần xác định các biến được sử dụng trong các tập lệnh đó để xác định kết hợp cơ sở dữ liệu và tên người dùng/mật khẩu của chúng tôi.


Cơ sở dữ liệu được tạo bằng lược đồ sau:

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


Và, làm ví dụ về dữ liệu, chúng tôi sẽ đăng ký một con vật có tên piquinho . Piquinho đơn giản là tên của một con chim hải âu đang di chuyển vòng quanh thế giới, nó có gắn một cảm biến và chúng ta đang đọc dữ liệu mà cảm biến đó gửi cho chúng ta. Có hai bảng xác định loài. Đó là loài và chi xác định loài. Đây là các bảng familiesgenuses .


species loài xác định loài mà động vật thuộc về. Cuối cùng, chúng tôi xác định một animal trong bảng cùng tên nơi đăng ký loài và tên của con vật đó. Cơ sở dữ liệu trông như thế này:
Mô tả hình ảnh

Để xây dựng, tạo hình ảnh và bắt đầu dự án của mình, chúng tôi có thể chạy các lệnh sau có sẵn trong Makefile :

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


Lần thực hiện đầu tiên chỉ là lệnh gradle build . Lệnh thứ hai sử dụng biến:

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


chạy:

 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


Điều này chỉ đơn giản đi qua mọi mô-đun và sử dụng lệnh chung tiêu chuẩn thay đổi theo giá trị được cung cấp trong MODULE_TAGS để tạo hình ảnh và đẩy chúng đến sổ đăng ký cục bộ trên cổng 5001. Theo chiến lược tương tự, sau đó chúng ta có thể sử dụng lệnh thứ ba để triển khai vỏ quả. Lệnh thứ ba này sử dụng một vòng lặp khác trông như thế này:

 @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


Trong trường hợp này, nó áp dụng mọi tập lệnh triển khai cho từng dịch vụ. Nếu chúng ta chạy lệnh kubectl get pods --all-namespaces , chúng ta sẽ nhận được kết quả này:

 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


Điều chúng ta nên quan sát ở đây vào thời điểm này là sự hiện diện của kuma-control-plane , kube-controller-manager và tất cả các dịch vụ đang chạy trong wlsm-namespace tùy chỉnh của riêng chúng ta. Cụm của chúng tôi được cách ly với bên ngoài và để có thể truy cập vào các cổng khác nhau, chúng tôi cần tạo port-forwarding cho mọi nhóm mà chúng tôi muốn truy cập. Vì thế, chúng ta có thể đưa ra các lệnh này trong các tab riêng biệt:

Chúng ta cũng có thể xem xét điều này bằng cách xem k9s :

Mô tả hình ảnh

 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. Chạy ứng dụng

Để chạy ứng dụng, chúng ta nên mở tất cả các cổng và khi tất cả chúng đều mở, chúng ta sẽ thấy một cái gì đó như thế này trên màn hình của mình:

Mô tả hình ảnh

Chúng ta có thể kết nối với cơ sở dữ liệu bằng localhost và cổng 5432 . Chuỗi kết nối là chuỗi này: jdbc:postgresql://localhost:5432/wlsm . Và để truy cập nó, chúng tôi sử dụng kết hợp tên người dùng/mật khẩu của admin / admin .


Điều đầu tiên chúng ta cần làm trước khi thực hiện bất kỳ thử nghiệm nào là biết id của Piquinho và chúng ta có thể làm điều đó bằng cách sử dụng các công cụ cơ sở dữ liệu Intellij như thế này:

Mô tả hình ảnh

Trong thư mục gốc của dự án có một tệp có tên test-requests.http . Đây là tệp sơ khai để tạo các yêu cầu REST đối với các cổng đang mở của chúng tôi:

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


Để có thể sử dụng file này, chúng ta chỉ cần thay thế ID, trong ví dụ này là từ 2ffc17b7-1956-4105-845f-b10a766789da thành d5ad0824-71c0-4786-a04a-ac2b9a032da4 . Trong trường hợp này, chúng ta có thể đưa ra yêu cầu từ người thu thập hoặc người nghe. Cả hai yêu cầu đều hoạt động và sau đó chúng ta sẽ thấy loại phản hồi này cho mỗi yêu cầu:

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


Vì cả hai cổng đều được mở và tại thời điểm này, chúng chia sẻ cùng loại tải trọng nên chúng tôi có thể thực hiện các yêu cầu giống nhau cho người nghe và người thu thập. Sau khi thực hiện hai yêu cầu đó, chúng ta sẽ tìm thấy kết quả trong bảng animal_locations :

Mô tả hình ảnh

Vì vậy, điều này chỉ xác nhận rằng cụm đang chạy chính xác và hiện tại, chúng tôi đã sẵn sàng thử nghiệm các chính sách với lưới Kuma của mình.

VII. MeshTrafficPermission - Phần I

MeshTrafficPermission là một trong những tính năng chúng ta có thể chọn ở Kuma và có lẽ đây là tính năng được sử dụng nhiều nhất.


Nhưng trước tiên, chúng ta hãy dành chút thời gian để khám phá máy bay điều khiển Kuma. Với tất cả tính năng chuyển tiếp được bật, chúng ta chỉ cần truy cập localhost:5681/gui và trực quan hóa các lưới Kuma của mình. Trên trang chính, chúng ta sẽ thấy một cái gì đó như thế này:

Mô tả hình ảnh

Hiện tại không có gì nhiều để xem, nhưng bây giờ hãy áp dụng 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 -


Sau khi áp dụng điều này, chúng tôi sẽ nhận được phản hồi như thế này: meshtrafficpermission.kuma.io/mtp created .

VIII. Lưới thép

Việc áp dụng lưới không thay đổi nhiều khi thiết lập cụm của chúng tôi. Những gì nó làm là cho phép chúng tôi thiết lập các chính sách định tuyến lưu lượng truy cập.


Có rất nhiều thứ chúng ta có thể chọn, nhưng một trong những thứ rõ ràng nhất chúng ta có thể chọn là mTLS. Mặt khác được gọi là TLS chung, trong thời gian rất ngắn có nghĩa là các chứng chỉ được chấp nhận và xác thực lẫn nhau để thiết lập danh tính giữa các bên và thiết lập lưu lượng dữ liệu được mã hóa.


Điều này có thể được thực hiện tự động cho chúng tôi bằng cách sử dụng cấu hình Mesh đơn giản này:

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


Sau khi áp dụng chính sách này, chúng tôi có thể gặp một cảnh báo như thế này:

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.

Hiện tại, chúng ta có thể bỏ qua cảnh báo này.

IX MeshTrafficPermission - Phần II

Bây giờ, đến phần thú vị và điều đầu tiên chúng ta sẽ làm là vô hiệu hóa tất cả lưu lượng truy cập giữa tất cả các nhóm:

 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 -


Và sau khi chúng tôi nhận được thông báo xác nhận, meshtrafficpermission.kuma.io/mtp configured , nếu chúng tôi cố gắng thực hiện bất kỳ yêu cầu nào bằng cách sử dụng bất kỳ chuyển tiếp cổng nào, chúng tôi sẽ nhận được:

 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)


Điều này có nghĩa là tất cả lưu lượng truy cập giữa các nhóm đang bị từ chối. Những gì chúng tôi hiện có là một hệ thống nội bộ được bảo vệ khỏi các tác nhân xấu có thể xảy ra trong tổ chức của chúng tôi, nhưng chúng tôi hiện cũng đã chặn lưu lượng truy cập giữa tất cả các nhóm. Vì vậy, mTLS là một điều tuyệt vời, nhưng chặn tất cả lưu lượng truy cập thì không hề.


Cách để làm cho điều này trở nên hoàn hảo chỉ đơn giản là tạo ra các ngoại lệ cho quy tắc DENY tất cả đó và để làm được điều đó, chúng ta cần một chính sách cho phép lưu lượng truy cập giữa trình nghe và trình thu thập cũng như trình thu thập và cơ sở dữ liệu. Hãy bắt đầu với lưu lượng giữa bộ thu thập và cơ sở dữ liệu:

 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 -


Trong trường hợp này, những gì chúng tôi đang làm là cho phép lưu lượng dữ liệu truyền từ bộ thu thập targetRef đến cơ sở dữ liệu targetRef . Nếu bạn không biết điều này, có lẽ điều quan trọng cần lưu ý là cách Kuma diễn giải name này, giống như việc tạo hostname , cũng được sử dụng cho các mục đích chức năng.


Cách chung để xây dựng name s này là như thế này:

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


Trong trường hợp này, dấu phân cách là dấu gạch dưới và việc tạo tên theo cách này sẽ giúp Kuma biết chính xác những gì được phép. Trong trường hợp này, nếu áp dụng chính sách này, chúng tôi sẽ có thể gửi yêu cầu đến người thu thập sau khi nhận được phản hồi sau: meshtrafficpermission.kuma.io/wlsm-database created .


Và khi thực hiện chúng, phản hồi bây giờ sẽ là 200 xác nhận rằng bản ghi vị trí đã được gửi đến người thu thập:

 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)


Tuy nhiên, chúng tôi vẫn chưa xác định các ngoại lệ đối với lưu lượng truy cập giữa người nghe và người thu thập, vì vậy việc thực hiện yêu cầu theo cách đó sẽ dẫn đến kết quả sau:

 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)


Và điều này tất nhiên là được mong đợi. Bây giờ hãy áp dụng một chính sách khác cho lưu lượng dữ liệu này:

 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 -


Làm cho nó có thể thực hiện các yêu cầu từ người nghe đến người thu thập:

 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

Cuối cùng và chỉ để cung cấp một tính năng khác làm ví dụ, chúng ta cũng có thể sử dụng một tính năng khác có tên MeshFaultInjection , tính năng này có thể rất hữu ích khi thực hiện kiểm tra với Kuma . Ví dụ: chúng tôi có thể mô phỏng các sự cố tiềm ẩn trong lưới của mình và kiểm tra xem việc xử lý lỗi có được thực hiện chính xác hay không.


Chúng tôi cũng có thể kiểm tra những thứ khác như cách bộ ngắt mạch mà chúng tôi đã định cấu hình có thể phản ứng với các kết nối bị lỗi hoặc yêu cầu tốc độ cao.


Vì vậy, hãy thử nó. Một cách để áp dụng MeshFaultInjection là như thế này:

 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 -


Với chính sách này, chúng tôi đang nói rằng lưu lượng truy cập đi từ người nghe và đi đến người thu thập sẽ có 50% cơ hội thành công. Kết quả yêu cầu không thể dự đoán được nên sau khi áp dụng chính sách này, chúng tôi có thể dự kiến sẽ xảy ra lỗi hoặc yêu cầu thành công đối với điểm cuối của trình nghe.

 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)


Cuối cùng, vì hứng thú, chúng ta có thể xem bảng animal_location của chúng ta trông như thế nào bây giờ:

Mô tả hình ảnh

XI - Kết luận

Tôi hy vọng bạn có thể theo dõi bài viết này cho đến nay và bạn có thể có một cụm chạy trên máy của mình. Dù sao cũng cảm ơn bạn đã đọc bài viết này và đã dành chút thời gian để hiểu và tìm hiểu thêm một chút về Kuma. Cá nhân tôi thấy cách sử dụng tuyệt vời này và một tương lai tuyệt vời cho Kuma vì nó cho phép định cấu hình và kiểm soát chi tiết hơn nhiều đối với mạng và môi trường của chúng tôi.


Phiên bản doanh nghiệp của nó, Kong-Mesh , có vẻ khá hoàn chỉnh. Kuma là nguồn mở. và có vẻ như nó rất tốt cho việc thử nghiệm cũng như cho doanh nghiệp. Tôi thấy chủ đề về lưới rất thú vị và tôi nghĩ Kuma cung cấp một cách tuyệt vời để tìm hiểu về cách hoạt động của lưới cũng như giúp chúng ta có thể kiểm soát luồng dữ liệu trong mạng của mình tốt hơn.


Nếu muốn xem trạng thái dịch vụ của mình, chúng ta chỉ cần đi đến mặt phẳng điều khiển Kuma ở vị trí localhost này: http://localhost:5681/gui/meshes/default/services?page=1&size=50 :

Mô tả hình ảnh

Trong mặt phẳng điều khiển Kuma, chúng ta cũng có thể xem các chính sách được cài đặt, kiểm tra trạng thái của nhóm, theo dõi những gì đang diễn ra ở chế độ nền và nói chung, chỉ cần có cái nhìn tổng quan về những gì đang xảy ra trong lưới của chúng ta và cách thức nó diễn ra. được cấu hình. Tôi mời bạn chỉ cần xem qua ứng dụng và xem liệu bạn có thể kiểm tra trạng thái của các chính sách mà chúng tôi đã cài đặt hay không. Mặt phẳng điều khiển Kuma, hay còn gọi là GUI, được thiết kế chính xác để dễ hiểu và dễ theo dõi trên Lưới của chúng tôi.

XII - Tài nguyên

Tôi cũng đã làm một video về nó trên kênh YouTube JESPROTECH của mình ngay tại đây: