使用说明
Dokumentacja projektu z przedmiotu Środowiska Udostępniania Usług
Temat projektu: MCP Grafana (akronim MCP-G)
Autorzy:
- Mateusz Górski
- Mateusz Lampert
- Wojciech Michaluk
- Jan Pawlica
Rok 2025/26, grupa 5 - piątek 13:15
Spis treści
- Wprowadzenie
- Podstawy teoretyczne i stos technologiczny
- Opis studium przypadku
- Architektura rozwiązania
- Opis środowiska
- Sposób instalacji demo
- Integracja Prometheusa, Grafany i serwera MCP
- Przedstawienie działania aplikacji
- Podsumowanie i wnioski
- Referencje
Rozdział 1: Wprowadzenie
Celem tego projektu jest demonstracja wykorzystania serwera MCP dla Grafany do sterowania aplikacją Grafany z poziomu wybranego modelu LLM. Aplikacja demonstracyjna powinna zostać wdrożona w klastrze Kubernetesa w celu generowania danych wizualizowanych przez Grafanę.
Kubernetes
Kubernetes (K8s) to otwartoźródłowa platforma, która ułatwia automatyzację wdrażania, skalowania i zarządzania skonteneryzowanymi aplikacjami. Jest to najpopularniejsze narzędzie w środowiskach DevOps do zarządzania złożonymi aplikacjami rozproszonymi. System ten pozwala na uruchamianie i zarządzanie setkami, a nawet tysiącami kontenerów. Kubernetes cechuje się również samonaprawianiem (self-healing), czyli automatycznym restartem wadliwych kontenerów, które uległy awarii, ewentualnie nawet ich wymianą w razie potrzeby. Jego działanie opiera się na organizacji kontenerów w tzw. pody, czyli logiczne grupy, co ułatwia zarządzanie aplikacją.
Warto wspomnieć, czym Kubernetes nie jest, aby dostrzec pełnię jego zalet. Nie jest to tradycyjny, "zawierający wszystko" system Platform as a Service (PaaS), ale posiada funkcjonalności ogólnego zastosowania, które cechują rozwiązania tego typu. Obejmują one instalacje (deployments), a także skalowanie i balansowanie ruchu, co umożliwia użytkownikom integrację rozwiązań służących do logowania, monitoringu i ostrzegania. Kubernetes również nie jest monolitem - dostarcza elementy, z których można zbudować aplikację, ale są one opcjonalne i funkcjonują na zasadzie wtyczek. Pozostawia to użytkownikowi wybór i elastyczność, bowiem Kubernetes:
- nie ogranicza obsługiwanych typów aplikacji,
- nie wymusza użycia konkretnych systemów zbierania logów, monitorowania ani ostrzegania,
- eliminuje konieczność orchestracji i scentralizowanego zarządzania.
Grafana
Grafana to popularna, również otwartoźródłowa platforma, która służy do wizualizacji danych, monitorowania infrastruktury IT oraz analizy w czasie rzeczywistym. Umożliwia tworzenie interaktywnych dashboardów z np. wykresami, panelami i alertami, a także integrację danych z różnych źródeł, m.in. Prometheus, InfluxDB, MySQL czy ElasticSearch. Rysunek poniżej (źródło) przedstawia panel wyboru źródła danych w Grafanie, obejmujący wiele popularnych baz danych i rozwiązań chmurowych.
Kluczowe cechy i zastosowania Grafany obejmują:
- wizualizację złożonych danych z wykorzystaniem szerokiej gamy wykresów (np. słupkowe, liniowe, heatmapy),
- wsparcie dla wielu źródeł danych (patrz rysunek powyżej),
- monitorowanie w czasie rzeczywistym - np. śledzenie wydajności serwerów, aplikacji i usług,
- alerty - powiadomienia dotyczące m.in. anomalii czy przekroczeniu ustalonych progów,
- elastyczność - możliwość działania na serwerach lokalnych oraz w chmurze, rozbudowa przez wtyczki.
MCP
MCP, czyli Model Context Protocol, to otwarty standard technologiczny, który umożliwia modelom LLM łączyć się w bezpieczny sposób z zewnętrznymi danymi, bazami danych oraz narzędziami programistycznymi. Dzięki temu zyskał dużą popularność, bo rozwiązał kluczowy problem braku standaryzacji w łączeniu modeli z zewnętrznymi danymi i narzędziami. Ułatwia zarządzanie uprawnieniami dzięki ustrukturyzowanemu dostępowi do danych. MCP działa w modelu klient-serwer. Serwer udostępnia zasoby (dane), narzędzia oraz prompty, które pełnią rolę reużywalnych szablonów, instrukcji, z kolei klienci odkrywają i wykorzystują te elementy udostępniane przez serwery. Każdy klient utrzymuje połączenie 1:1 z poszczególnym serwerem. Całość jest zarządzana przez hosta, który pełni rolę koordynatora - tworzy i obsługuje wiele instancji klienta.
Rozdział 2: Podstawy teoretyczne i stos technologiczny
Podstawy teoretyczne
Monitorowanie i obserwowalność
Monitorowanie aplikacji w środowiskach chmurowych polega na zbieraniu i analizie danych telemetrycznych. Kluczowym pojęciem jest tutaj obserwowalność (ang. observability), czyli zdolność do wnioskowania o wewnętrznym stanie systemu na podstawie jego zewnętrznych sygnałów. Wyróżnia się trzy filary obserwowalności:
- metrics - numeryczne wartości reprezentujące stan systemu w czasie (np. użycie CPU, liczba żądań na sekundę, opóźnienie odpowiedzi),
- logs - tekstowe zapisy zdarzeń generowane przez aplikacje,
- traces - rejestracja przepływu żądań przez poszczególne komponenty systemu.
W projekcie skupiamy się przede wszystkim na metrykach zbieranych przez Prometheusa i wizualizowanych w Grafanie.
Integracja LLM z Grafaną przez MCP
Dedykowany serwer MCP umożliwia modelowi językowemu sterowanie Grafaną — przeglądanie dashboardów, odpytywanie źródeł danych czy tworzenie alertów. Przepływ komunikacji wygląda następująco:
- Użytkownik wysyła zapytanie w języku naturalnym do modelu LLM.
- Model rozpoznaje intencję i wywołuje odpowiednie narzędzie udostępniane przez serwer MCP.
- Serwer MCP Grafany wykonuje operację (np. odpytuje Prometheusa) i zwraca wynik.
- Model LLM interpretuje wynik i odpowiada użytkownikowi w języku naturalnym.
Stos technologiczny
Poniżej opisano narzędzia wykorzystane w projekcie. Kubernetes, Grafana oraz MCP zostały przedstawione w rozdziale 1.
Google Cloud Platform (GCP)
Infrastruktura chmurowa projektu opiera się na platformie Google Cloud Platform. W ramach projektu wykorzystamy bezpłatne środki w wysokości 300 USD oferowane przez Google nowym użytkownikom. GCP zapewnia klaster Kubernetes poprzez usługę Google Kubernetes Engine (GKE), która automatyzuje zarządzanie węzłami klastra, aktualizacje oraz skalowanie.
Docker
Docker jest podstawą konteneryzacji wszystkich komponentów systemu. Mikroserwisy aplikacji oraz narzędzia monitoringowe pakowane są jako obrazy kontenerowe zgodne ze standardem OCI. Kubernetes zarządza następnie cyklem życia tych kontenerów w klastrze.
Prometheus
Prometheus to otwartoźródłowy system monitorowania i alarmowania, stanowiący standard w ekosystemie Kubernetes. Działa w modelu pull - cyklicznie pobiera (scrape) metryki z endpointów HTTP udostępnianych przez monitorowane aplikacje. Zebrane metryki przechowuje we wbudowanej bazie danych szeregów czasowych i udostępnia je poprzez język zapytań PromQL. W projekcie Prometheus zbiera metryki ze wszystkich mikroserwisów aplikacji.
Serwer MCP Grafany
Serwer MCP Grafany to osobny projekt otwartoźródłowy, który łączy się z Grafaną przez jej HTTP API. Udostępnia narzędzia pozwalające modelom LLM na sterowanie Grafaną — odpytywanie źródeł danych, zarządzanie dashboardami czy analizę metryk.
OpenAI GPT-4o
GPT-4o to model językowy firmy OpenAI wykorzystywany w projekcie do komunikacji z Grafaną przez protokół MCP. Interpretuje dane monitoringowe i odpowiada użytkownikowi w języku naturalnym. Wybór dostawcy i modelu może ulec zmianie w trakcie realizacji projektu.
Locust
Locust to otwartoźródłowe narzędzie do testów obciążeniowych napisane w języku Python. Pozwala na symulowanie zachowania wielu równoczesnych użytkowników wysyłających żądania HTTP do testowanej aplikacji. W projekcie Locust generuje syntetyczny ruch użytkowników, który umożliwia obserwację zachowania systemu pod obciążeniem w Grafanie.
Rozdział 3: Opis studium przypadku
Wykorzystana aplikacja
Aplikacją wykorzystaną w niniejszym projekcie jest Bank of Anthos, czyli referencyjna aplikacja mikroserwisowa opracowana przez Google, służąca do demonstracji praktyk związanych z wdrażaniem, monitorowaniem oraz analizą aplikacji w środowiskach chmurowych. Bank of Anthos symuluje działanie systemu bankowego, umożliwiając użytkownikom wykonywanie podstawowych operacji finansowych, takich jak przeglądanie salda konta, wykonywanie przelewów i zarządzanie historią transakcji.
| Login | Strona główna |
|---|---|
Aplikacja działa w środowisku Kubernetes i jest uruchamiana jako zestaw kontenerów, a cały projekt został zaprojektowany w architekturze mikroserwisowej i składa się z wielu niezależnych komponentów widocznych poniżej:
Komponenty aplikacji
| Serwis | Język | Opis |
|---|---|---|
| loadgenerator | Python / Locust | Generuje ruch w systemie, symulując zachowanie użytkowników (tworzenie kont, wykonywanie transakcji). |
| frontend | Python | Udostępnia serwer HTTP obsługujący interfejs użytkownika (strona logowania, rejestracji oraz strona główna). |
| user-service | Python | Zarządza kontami użytkowników oraz uwierzytelnianiem. Generuje tokeny JWT wykorzystywane przez inne serwisy. |
| contacts | Python | Przechowuje listę kontaktów użytkownika wykorzystywaną np. przy wykonywaniu przelewów. |
| accounts-db | PostgreSQL | Baza danych przechowująca dane użytkowników. Może być wstępnie zasilona danymi demonstracyjnymi. |
| ledger-writer | Java | Przyjmuje i waliduje transakcje, a następnie zapisuje je w rejestrze (ledger). |
| balance-reader | Java | Zapewnia szybki dostęp do aktualnych sald użytkowników na podstawie danych z bazy ledger-db. |
| transaction-history | Java | Udostępnia historię transakcji użytkownika na podstawie danych z bazy ledger-db. |
| ledger-db | PostgreSQL | Baza danych przechowująca wszystkie transakcje (ledger). Może być wstępnie zasilona danymi demonstracyjnymi. |
Scenariusze testowania aplikacji
W ramach prezentacji działania systemu przewidziano następujące scenariusze testowe:
- Weryfikacja widoczności serwisów w Grafanie
- sprawdzenie, czy wszystkie serwisy postawione w klastrze są monitorowane
- identyfikacja serwisów aplikacyjnych, infrastruktury Kubernetes oraz stosu monitoringowego
- Analiza zużycia pamięci przez wybrany serwis
- odpytanie Prometheusa o metryki pamięci dla
userservicez ostatniej godziny - wizualizacja wykresu oraz interpretacja zaobserwowanych trendów
- Analiza wielu metryk dla wybranego serwisu w zadanym oknie czasowym
- jednoczesne pobranie i wizualizacja zużycia pamięci oraz CPU dla
frontend - weryfikacja poprawności uwzględnienia parametru czasowego podanego w języku naturalnym
Na podstawie powyższych scenariuszy weryfikowane będzie działanie całego systemu, od zbierania metryk przez Prometheusa, przez wizualizację w Grafanie, aż po sterowanie Grafaną z poziomu modelu językowego przez protokół MCP.
Rozdział 4: Architektura rozwiązania
Rozdział 5: Opis środowiska
Ekosystem Google Cloud Platform (GCP)
W realizacji projektu wykorzystujemy środowisko Google Cloud Platform. Wybór GCP jako fundamentu projektu podyktowany był natywnym wsparciem dla technologii kontenerowych i analitycznych. Platforma ta oferuje szereg kluczowych usług w kontekście uruchomienia aplikacji:
-
Google Kubernetes Engine (GKE): zarządzalne środowisko Kubernetes, które zdejmuje z administratora ciężar utrzymania warstwy sprzętowej (Control Plane). GKE pozwala na dynamiczne skalowanie zasobów (w górę i do zera), co jest wykorzystywane w celu optymalizacji kosztów projektu.
-
Zarządzanie tożsamością i dostępem (IAM): wykorzystane do bezpiecznego nadawania uprawnień dla serwera MCP, aby mógł on bezpiecznie komunikować się z API Grafany bez upubliczniania wrażliwych kluczy.
-
Wirtualna chmura prywatna (VPC): zapewnia izolację mikroserwisów aplikacji Bank of Anthos oraz umożliwia wystawienie Load Balancera, przez który serwer MCP łączy się z dashboardami Grafany.
Bardzo ważnym czynnikiem jest również oferta bezpłatnych środków (300 USD) oferowanych przez Google dla nowych użytkowników w połączeniu z możliwościami GKE. Dzięki temu, że możemy "wyłączać" klaster kiedy nie jest on używany, przez ten czas nie są pobierane koszty. Pozwala to na zapewnienie działania klastra wtedy, kiedy jest to wymagane, przez cały czas trwania projektu, nie martwiąc się o przekroczenie limitów.
Bank of Anthos jako referencyjne środowisko
Bank of Anthos to aplikacja typu cloud-native, która idealnie symuluje rzeczywiste środowisko bankowe. W naszym projekcie pełni ona rolę "źródła prawdy", generując różnorodne dane telemetryczne. Zapewnia następujące możliwości:
-
Złożona topologia – dzięki podziałowi na wiele serwisów (Frontend, Ledger, Transaction, User Service) możemy testować, czy LLM przez MCP potrafi poprawnie zidentyfikować przykładowo który konkretnie element systemu uległ awarii czy w największym stopniu obciąża pamięć.
-
Dostarczanie metryk – aplikacja generuje metryki techniczne, takie jak użycie pamięci przez Java VM, opóźnienia bazy danych PostgreSQL itp.
-
Łatwość wstrzykiwania błędów – wykorzystujemy Bank of Anthos do pokazania "inteligencji" MCP – np. celowo wyłączamy jeden z serwisów, a LLM analizując dane z Grafany, informuje nas o tym fakcie w języku naturalnym.
Rozdział 6: Sposób instalacji demo
Aby poprawnie uruchomić aplikację na klastrze Kubernetes w środowisku GCP, wykonaliśmy kolejno kroki z samouczka, który jest udostępniony z poziomu README w repozytorium aplikacji Bank of Anthos.
Uruchomienie samouczka
Aby otworzyć odpowiednio skonfigurowane środowisko Google Cloud Shell, należy kliknąć przycisk "Open in Google Cloud Shell" w sekcji Interactive Quickstart (GKE).
Wczytanie środowiska i utworzenie projektu
Należy chwilę odczekać, aż wszystkie wymagane komponenty się wczytają.
Następnie główną część obszaru roboczego zajmuje Cloud Shell Editor, w którym w następnych krokach będziemy wykonywać właściwe akcje, a w panelu po prawej stronie otwiera się interaktywny samouczek. Wybieramy z jego poziomu "Utwórz nowy projekt".
W nowo otwartym oknie podajemy nazwę projektu i wybieramy "Utwórz".
Po utworzeniu projektu zaznaczamy go w liście wyboru i klikamy "Rozpocznij".
Konfiguracja klastra Kubernetesa
Postępujemy zgodnie z instrukcjami zawartymi w panelu po prawej stronie. Zgodnie ze wcześniejszym opisem, wykorzystujemy Google Kubernetes Engine.
Wykonujemy wskazane kroki z odpowiedniej sekcji instrukcji, zilustrowanej poniżej. Następnie wybieramy "Dalej".
UWAGA! Aby zmieścić się w limitach w ramach oferowanych bezpłatnych zasobów GCP, zmieniliśmy niektóre ustawienia:
- Node count: 3 zamiast 4,
- Machine type: e2-medium zamiast e2-standard-2,
- Rozmiar dysku rozruchowego (w ustawieniach puli węzłów): 30GB zamiast 100GB.
Wdrożenie tokenu JWT
Kolejnym krokiem jest wdrożenie tokenu JWT (JSON Web Token), który jest wykorzystywany przy tworzeniu kont użytkowników i ich autentykacji.
Zawartość pliku jwt-secret.yaml (bez kluczy):
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This secret contains a keypair used to sign and verify JWTs for authentication
# In practice, this should never be checked into version control. It is provided here to simplify deployment
apiVersion: v1
kind: Secret
metadata:
name: jwt-key
type: Opaque
data:
jwtRS256.key: [REDACTED]
jwtRS256.key.pub: [REDACTED]
Uruchomienie aplikacji w klastrze Kubernetesa
Teraz możemy przejść do uruchomienia aplikacji Bank of Anthos w utworzonym wcześniej klastrze Kubernetesa.
Zawartość wspomnianego pliku skaffold.yaml:
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: skaffold/v4beta1
kind: Config
metadata:
name: bank-of-anthos
requires:
- configs:
- accounts
path: src/accounts/skaffold.yaml
- configs:
- ledger
path: src/ledger/skaffold.yaml
- configs:
- frontend
path: src/frontend/skaffold.yaml
- configs:
- loadgenerator
path: src/loadgenerator/skaffold.yaml
- configs:
- accounts-db
path: src/accounts/accounts-db/skaffold.yaml
- configs:
- ledger-db
path: src/ledger/ledger-db/skaffold.yaml
deploy:
tolerateFailuresUntilDeadline: true
Był to ostatni "właściwy" krok do wykonania, bowiem kolejne kroki samouczka opisują sposób usuwania klastra i czyszczenia zasobów po nim, oraz przedstawiają ekran podsumowujący cały proces.
Rozdział 7: Integracja Prometheusa, Grafany i serwera MCP
Przedstawiamy kroki, które wykonaliśmy w celu zbierania metryk z działającej aplikacji, wizualizowania ich w przystępny sposób oraz umożliwienia wykorzystania modelu LLM do pobierania udostępnionych informacji poprzez zapytania w języku naturalnym.
Integracja Prometheusa
Aby zainstalować Prometheusa na klastrze, należy wykonać instrukcje:
> helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
> helm repo update
> helm install monitoring prometheus-community/kube-prometheus-stack --namespace monitoring
> helm install blackbox prometheus-community/prometheus-blackbox-exporter --namespace monitoring
Następnie konieczne były zmiany domyślnych wartości w plikach probes.yaml oraz rules.yaml, aby dostosować je do konkretnych wartości wykorzystywanych w naszym stosie technologicznym.
Plik probes.yaml:
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
---
apiVersion: monitoring.coreos.com/v1
kind: Probe
metadata:
name: frontend-probe
# Dodanie label monitoringu:
# labels:
# release: monitoring
spec:
jobName: frontend
prober:
url: tutorial-kube-prometheus-blackbox-exporter:19115 # zmiana na: blackbox-prometheus-blackbox-exporter.monitoring.svc.cluster.local:9115
path: /probe
module: http_2xx
interval: 60s
scrapeTimeout: 30s
targets:
staticConfig:
labels:
app: bank-of-anthos
static:
- frontend:80 # zmiana na: frontend.default.svc.cluster.local:80
---
apiVersion: monitoring.coreos.com/v1
kind: Probe
metadata:
name: userservice-probe
# Dodanie label monitoringu:
# labels:
# release: monitoring
spec:
jobName: userservice
prober:
url: tutorial-kube-prometheus-blackbox-exporter:19115 # zmiana na: blackbox-prometheus-blackbox-exporter.monitoring.svc.cluster.local:9115
path: /probe
module: http_2xx
interval: 60s
scrapeTimeout: 30s
targets:
staticConfig:
labels:
app: bank-of-anthos
static:
- userservice:8080/ready # zmiana na: userservice.default.svc.cluster.local:8080/ready
---
apiVersion: monitoring.coreos.com/v1
kind: Probe
metadata:
name: balancereader-probe
# Dodanie label monitoringu:
# labels:
# release: monitoring
spec:
jobName: balancereader
prober:
url: tutorial-kube-prometheus-blackbox-exporter:19115 # zmiana na: blackbox-prometheus-blackbox-exporter.monitoring.svc.cluster.local:9115
path: /probe
module: http_2xx
interval: 60s
scrapeTimeout: 30s
targets:
staticConfig:
labels:
app: bank-of-anthos
static:
- balancereader:8080/ready # zmiana na: balancereader.default.svc.cluster.local:8080/ready
---
apiVersion: monitoring.coreos.com/v1
kind: Probe
metadata:
name: contacts-probe
# Dodanie label monitoringu:
# labels:
# release: monitoring
spec:
jobName: contacts
prober:
url: tutorial-kube-prometheus-blackbox-exporter:19115 # zmiana na: blackbox-prometheus-blackbox-exporter.monitoring.svc.cluster.local:9115
path: /probe
module: http_2xx
interval: 60s
scrapeTimeout: 30s
targets:
staticConfig:
labels:
app: bank-of-anthos
static:
- contacts:8080/ready # zmiana na: contacts.default.svc.cluster.local:8080/ready
---
apiVersion: monitoring.coreos.com/v1
kind: Probe
metadata:
name: ledgerwriter-probe
# Dodanie label monitoringu:
# labels:
# release: monitoring
spec:
jobName: ledgerwriter
prober:
url: tutorial-kube-prometheus-blackbox-exporter:19115 # zmiana na: blackbox-prometheus-blackbox-exporter.monitoring.svc.cluster.local:9115
path: /probe
module: http_2xx
interval: 60s
scrapeTimeout: 30s
targets:
staticConfig:
labels:
app: bank-of-anthos
static:
- ledgerwriter:8080/ready # zmiana na: ledgerwriter.default.svc.cluster.local:8080/ready
---
apiVersion: monitoring.coreos.com/v1
kind: Probe
metadata:
name: transactionhistory-probe
# Dodanie label monitoringu:
# labels:
# release: monitoring
spec:
jobName: transactionhistory
prober:
url: tutorial-kube-prometheus-blackbox-exporter:19115 # zmiana na: blackbox-prometheus-blackbox-exporter.monitoring.svc.cluster.local:9115
path: /probe
module: http_2xx
interval: 60s
scrapeTimeout: 30s
targets:
staticConfig:
labels:
app: bank-of-anthos
static:
- transactionhistory:8080/ready # zmiana na: transactionhistory.default.svc.cluster.local:8080/ready
Plik rules.yaml:
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
---
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: uptime-rule
# Dodanie label monitoringu:
# labels:
# release: monitoring
spec:
groups:
- name: Micro services uptime
interval: 60s
rules:
- alert: BalancereaderUnavaiable
expr: probe_success{app="bank-of-anthos",job="balancereader"} == 0
for: 1m
annotations:
summary: Balance Reader Service is unavailable
description: Check Balance Reader pods and it's logs
labels:
severity: "critical"
- alert: ContactsUnavaiable
expr: probe_success{app="bank-of-anthos",job="contacts"} == 0
for: 1m
annotations:
summary: Contacs Service is unavailable
description: Check Contacs pods and it's logs
labels:
severity: "warning"
- alert: FrontendUnavaiable
expr: probe_success{app="bank-of-anthos",job="frontend"} == 0
for: 1m
annotations:
summary: Frontend Service is unavailable
description: Check Frontend pods and it's logs
labels:
severity: "critical"
- alert: LedgerwriterUnavaiable
expr: probe_success{app="bank-of-anthos",job="ledgerwriter"} == 0
for: 1m
annotations:
summary: Ledger Writer Service is unavailable
description: Check Ledger Writer pods and it's logs
labels:
severity: "critical"
- alert: TransactionhistoryUnavaiable
expr: probe_success{app="bank-of-anthos",job="transactionhistory"} == 0
for: 1m
annotations:
summary: Transaction History Service is unavailable
description: Check Transaction History pods and it's logs
labels:
severity: "critical"
- alert: UserserviceUnavaiable
expr: probe_success{app="bank-of-anthos",job="userservice"} == 0
for: 1m
annotations:
summary: User Service is unavailable
description: Check User Service pods and it's logs
labels:
severity: "critical"
Po odpowiednim przygotowaniu powyższych plików aplikujemy je:
> kubectl -n monitoring apply -f bank-of-anthos/extras/prometheus/oss/probes.yaml
> kubectl -n monitoring apply -f bank-of-anthos/extras/prometheus/oss/rules.yaml
Integracja Grafany
Najpierw udostępniliśmy Grafanę z wykorzystaniem Load Balancera:
> kubectl -n monitoring patch svc monitoring-grafana -p '{"spec":{"type":"LoadBalancer"}}'
Prometheus jest automatycznie przyłączony jako data source Grafany i zbierane metryki są w niej dostępne bez dodatkowej konfiguracji.
Następnie przygotowaliśmy i zaimportowaliśmy dashboard, który pozwala na bieżąco śledzić kondycję wszystkich mikroserwisów Bank of Anthos. Wyświetla on dostępność każdego z nich, czas odpowiedzi oraz zwracany kod HTTP, a w ramach uzupełnienia także zużycie zasobów ich podów - CPU, pamięć i liczbę restartów.
{
"title": "Bank of Anthos",
"uid": "bank-of-anthos",
"tags": ["bank-of-anthos"],
"timezone": "browser",
"schemaVersion": 39,
"refresh": "30s",
"time": { "from": "now-1h", "to": "now" },
"templating": {
"list": [
{
"name": "datasource",
"type": "datasource",
"query": "prometheus",
"current": { "text": "Prometheus", "value": "Prometheus" },
"hide": 0
}
]
},
"panels": [
{
"id": 1,
"type": "stat",
"title": "Service Up",
"gridPos": { "x": 0, "y": 0, "w": 24, "h": 4 },
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"targets": [
{
"expr": "probe_success{app=\"bank-of-anthos\"}",
"legendFormat": "{{job}}",
"refId": "A"
}
],
"fieldConfig": {
"defaults": {
"mappings": [
{
"type": "value",
"options": {
"0": { "text": "DOWN", "color": "red" },
"1": { "text": "UP", "color": "green" }
}
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{ "color": "red", "value": null },
{ "color": "green", "value": 1 }
]
},
"color": { "mode": "thresholds" }
}
},
"options": {
"reduceOptions": { "calcs": ["lastNotNull"] },
"colorMode": "background",
"graphMode": "none"
}
},
{
"id": 2,
"type": "timeseries",
"title": "Availability over time",
"gridPos": { "x": 0, "y": 4, "w": 12, "h": 8 },
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"targets": [
{
"expr": "probe_success{app=\"bank-of-anthos\"}",
"legendFormat": "{{job}}",
"refId": "A"
}
],
"fieldConfig": { "defaults": { "min": 0, "max": 1, "unit": "short" } }
},
{
"id": 3,
"type": "timeseries",
"title": "Probe latency",
"gridPos": { "x": 12, "y": 4, "w": 12, "h": 8 },
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"targets": [
{
"expr": "probe_duration_seconds{app=\"bank-of-anthos\"}",
"legendFormat": "{{job}}",
"refId": "A"
}
],
"fieldConfig": { "defaults": { "unit": "s" } }
},
{
"id": 4,
"type": "timeseries",
"title": "HTTP status code per service",
"gridPos": { "x": 0, "y": 12, "w": 12, "h": 8 },
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"targets": [
{
"expr": "probe_http_status_code{app=\"bank-of-anthos\"}",
"legendFormat": "{{job}}",
"refId": "A"
}
]
},
{
"id": 5,
"type": "timeseries",
"title": "DNS lookup time (probe)",
"gridPos": { "x": 12, "y": 12, "w": 12, "h": 8 },
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"targets": [
{
"expr": "probe_dns_lookup_time_seconds{app=\"bank-of-anthos\"}",
"legendFormat": "{{job}}",
"refId": "A"
}
],
"fieldConfig": { "defaults": { "unit": "s" } }
},
{
"id": 6,
"type": "timeseries",
"title": "Pod CPU (default ns)",
"gridPos": { "x": 0, "y": 20, "w": 12, "h": 8 },
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"targets": [
{
"expr": "sum by (pod) (rate(container_cpu_usage_seconds_total{namespace=\"default\", container!=\"\", container!=\"POD\"}[5m]))",
"legendFormat": "{{pod}}",
"refId": "A"
}
],
"fieldConfig": { "defaults": { "unit": "short" } }
},
{
"id": 7,
"type": "timeseries",
"title": "Pod memory (default ns)",
"gridPos": { "x": 12, "y": 20, "w": 12, "h": 8 },
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"targets": [
{
"expr": "sum by (pod) (container_memory_working_set_bytes{namespace=\"default\", container!=\"\", container!=\"POD\"})",
"legendFormat": "{{pod}}",
"refId": "A"
}
],
"fieldConfig": { "defaults": { "unit": "bytes" } }
},
{
"id": 8,
"type": "timeseries",
"title": "Pod restarts (default ns)",
"gridPos": { "x": 0, "y": 28, "w": 24, "h": 6 },
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"targets": [
{
"expr": "sum by (pod) (kube_pod_container_status_restarts_total{namespace=\"default\"})",
"legendFormat": "{{pod}}",
"refId": "A"
}
]
}
]
}
Integracja serwera MCP
Poniżej opisane są kolejne czynności wykonane w celu integracji serwera MCP z Grafaną.
- Pobranie hasła do dashboardu Grafany
> kubectl get secret monitoring-grafana -n monitoring -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
- Dodanie Grafany MCP
W zawartej poniżej komendzie <GRAFANA_API_KEY> to klucz powiązany z kontem dla serwisu mcp.
> brew install helm
> helm repo add grafana-community https://grafana-community.github.io/helm-charts
> helm repo update
> helm install grafana-mcp grafana-community/grafana-mcp --namespace monitoring --set grafana.url=http://monitoring-grafana.monitoring.svc.cluster.local --set grafana.apiKey=<GRAFANA_API_KEY>
- Połączenie z Claude Desktop
> kubectl port-forward svc/grafana-mcp 8000:8000 -n monitoring
> npx mcp-remote http://localhost:8000/sse
Następnie należy otworzyć plik claude_desktop_config.json i dodać na końcu:
{
... dotychczasowa zawartość ...
"mcpServers": {
"grafana": {
"command": "npx",
"args": [
"mcp-remote",
"http://localhost:8000/sse"
]
}
}
}
Po zrestartowaniu aplikacji Claude Desktop wtyczka grafana powinna być domyślnie włączona.
Rozdział 8: Przedstawienie działania aplikacji
Przebieg wykonania
Po uruchomieniu aplikacji Bank of Anthos w klastrze Kubernetes oraz skonfigurowaniu Prometheusa, Grafany i serwera MCP, przeprowadziliśmy demonstrację działania systemu w realnych scenariuszach testowych. Do interakcji z modelem językowym oraz serwerem MCP wykorzystana została aplikacja Claude Desktop z podłączoną wtyczką grafana.
Dzięki udostępnieniu informacji z Grafany poprzez serwer MCP, możliwe jest odpytywanie Grafany o stan monitorowanych serwisów w języku naturalnym. W ramach przeprowadzonych demostracji model trafnie rozpoznawał intencje użytkownika, dobierał odpowiednie narzędzia udostępnione przez serwer MCP i zwracał wyniki w czytelnej formie adekwatnej dla danego zadania (zarówno tekstowej, jak i graficznej).
Wyniki
Scenariusz 1: Lista śledzonych serwisów
Scenariusz ten miał na celu zweryfikowanie czy wszystkie serwisy postawione w klastrze Kubernetesa są widoczne oraz monitorowane przez Grafanę. W ramach tego eksperymentu użytkownik pyta LLMa o wszystkie dostępne w Grafanie serwisy.
W celu sformułowania odpowiedzi model językowy wykorzystał dwa narzędzia MCP oraz zwrócił listę wszystkich serwisów widocznych obserwowanych w Prometheusie i dostępnych w Grafanie:
- Serwisy aplikacyjne:
frontend,contacts,userservice,ledgerwriter,balancereader,transactionhistory - Infrastruktura Kubernetes:
apiserver,kube-controller-manager,kube-scheduler,kube-proxy,kube-state-metrics,kubelet,coredns - Stos monitoringowy:
monitoring-grafana,monitoring-kube-prometheus-prometheus,monitoring-kube-prometheus-operator,monitoring-kube-prometheus-alertmanager,node-exporter
Odpowiedź uzyskana w ramach zapytania była spójna ze stanem faktycznym.
Scenariusz 2: Analiza zużycia pamięci przez userservice
Scenariusz ten miał na celu sprawdzenie, czy model językowy jest w stanie pobrać dane telemetryczne dotyczące konkretnego serwisu i przedstawić je w czytelnej formie graficznej wraz z analizą. Użytkownik poprosił o wyrysowanie wykresu zużycia pamięci przez userservice z ostatniej godziny.
Model odpytał Grafanę przez serwer MCP i wygenerował interaktywny wykres wraz ze statystykami podsumowującymi (wartość bieżąca, minimum, maksimum oraz zmiana względem początku okresu). Zaobserwowano następujące fazy:
- pierwsze ~12 minut: wysoki poziom (~119 MB) z krótkim lokalnym maksimum wynoszącym 120,1 MB,
- kolejne ~18 minut: wyraźny spadek z ~120 MB do ~113 MB, zinterpretowany przez model jako garbage collection uwalniający wcześniej zaalokowaną pamięć,
- po ~30 minucie: stabilizacja na poziomie 112–113 MB bez dalszego wzrostu.
Model ocenił stan serwisu jako prawidłowy — wcześniejszy wzrost zużycia pamięci został zniwelowany przez GC, a serwis utrzymuje się na stabilnym, niskim poziomie.
Scenariusz 3: Analiza zasobów frontend z ostatnich 2 godzin
Scenariusz ten miał na celu zweryfikowanie dwóch aspektów:
- czy model językowy potrafi jednocześnie pobrać i zwizualizować kilka różnych rodzajów metryk dla tego samego serwisu,
- czy model poprawnie uwzględnia przekazane przez użytkownika parametry (w tym przypadku było to podane przez użytkownika okno czasowe).
Użytkownik zlecił jednoczesne wykreślenie zużycia pamięci oraz CPU przez serwis frontend z ostatnich 2 godzin.
Model użył pięciu narzędzi MCP i wygenerował dwa oddzielne wykresy obejmujące przedział czasowy zgodny z żądaniem użytkownika. Do wykresów dołączone zostały statystyki podsumowujące oraz analiza tekstowa:
- Pamięć: stabilna w przedziale 87–93 MB, z krótkim spikiem do ~93 MB na początku okna obserwacji, następnie ustabilizowana na poziomie ~91 MB; brak trendu wzrostowego,
- CPU: konsekwentnie niskie zużycie rzędu 4–5% rdzenia przez cały obserwowany okres; nieznaczny wzrost do ~5,3% w ostatnich ~20 minutach, oceniony przez model jako normalna zmienność ruchu.
Model podsumował, że frontend działa stabilnie i mieści się w normalnych granicach operacyjnych. Scenariusz potwierdził zarówno zdolność modelu do jednoczesnej analizy wielu metryk i ich korelowania w ramach jednej spójnej odpowiedzi, jak i poprawne respektowanie parametru czasowego przekazanego w zapytaniu w języku naturalnym.
Rozdział 9: Podsumowanie i wnioski
W ramach projektu zrealizowany został postawiony cel, którym było zademonstrowanie wykorzystania serwera MCP dla Grafany do sterowania monitoringiem aplikacji mikroserwisowej z poziomu modelu LLM w języku naturalnym.
Przeprowadzone scenariusze potwierdziły poprawne działanie całego stosu — od zbierania metryk przez Prometheusa, przez ich wizualizację w Grafanie, aż po sterowanie Grafaną z poziomu modelu językowego przez protokół MCP. Model nie tylko pobierał dane, ale potrafił je interpretować: rozróżniał między spikiem pamięci spowodowanym garbage collection a realnym wzrostem zużycia, identyfikował normalne wahania CPU oraz poprawnie uwzględniał parametry czasowe przekazane w zapytaniu w języku naturalnym.
W trakcie realizacji projektu napotkaliśmy kilka wyzwań:
- konieczność ręcznej modyfikacji domyślnych plików konfiguracyjnych (
probes.yaml,rules.yaml) dostarczanych z repozytorium Bank of Anthos, - ograniczenia budżetowe GCP wymusiły obniżenie specyfikacji klastra (mniejsza liczba węzłów, mniejszy dysk rozruchowy),
- serwer MCP Grafany wymaga lokalnego przekierowania portów (
port-forward), co w środowisku produkcyjnym wymagałoby dodatkowego zabezpieczenia.
Naturalnym kierunkiem rozwoju projektu byłoby wdrożenie scenariuszy awarii z aktywnym alertingiem przez MCP, integracja z narzędziami do automatycznej remediacji (np. restart podu inicjowany przez model), a także zastąpienie lokalnego przekierowywania portów bezpiecznym, publicznie dostępnym endpointem z uwierzytelnianiem.
Sam serwer Grafana MCP działa bardzo dobrze w połączeniu z odpowiednim modelem językowym, a całość systemu prezentowała się zaskakująco dobrze.
Rozdział 10: Referencje
- Dokumentacja Kubernetes — https://kubernetes.io/docs/
- Dokumentacja Grafany — https://grafana.com/docs/
- Model Context Protocol (MCP) — https://modelcontextprotocol.io/
- Grafana MCP Server — https://github.com/grafana/mcp-grafana
- Bank of Anthos — https://github.com/GoogleCloudPlatform/bank-of-anthos
- Dokumentacja Prometheusa — https://prometheus.io/docs/
- Google Kubernetes Engine — https://cloud.google.com/kubernetes-engine/docs
- Locust — https://locust.io/
- Helm — https://helm.sh/docs/