Grafana MCP服务器

Grafana MCP服务器是一款将Grafana与大型语言模型连接的服务,通过Model Context Protocol使用户能以自然语言查询仪表盘、数据源和告警并分析监控指标,适用于Kubernetes环境下云原生应用的可观测性与运维监控场景。

  • by Ziomiu
  • Java
  • 混合部署
  • 2 星标
  • 更新于
在 GitHub 查看 Ziomiu/MCP_Grafana

使用说明

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

  1. Wprowadzenie
    1. Kubernetes
    2. Grafana
    3. MCP
  2. Podstawy teoretyczne i stos technologiczny
    1. Podstawy teoretyczne
      1. Monitorowanie i obserwowalność
      2. Integracja LLM z Grafaną przez MCP
    2. Stos technologiczny
      1. Google Cloud Platform (GCP)
      2. Docker
      3. Prometheus
      4. Serwer MCP Grafany
      5. OpenAI GPT-4o
      6. Locust
  3. Opis studium przypadku
    1. Wykorzystana aplikacja
    2. Komponenty aplikacji
    3. Scenariusze testowania aplikacji
  4. Architektura rozwiązania
  5. Opis środowiska
    1. Ekosystem Google Cloud Platform (GCP)
    2. Bank of Anthos jako referencyjne środowisko
  6. Sposób instalacji demo
    1. Uruchomienie samouczka
    2. Wczytanie środowiska i utworzenie projektu
    3. Konfiguracja klastra Kubernetesa
    4. Wdrożenie tokenu JWT
    5. Uruchomienie aplikacji w klastrze Kubernetesa
  7. Integracja Prometheusa, Grafany i serwera MCP
    1. Integracja Prometheusa
    2. Integracja Grafany
    3. Integracja serwera MCP
  8. Przedstawienie działania aplikacji
    1. Przebieg wykonania
    2. Wyniki
      1. Scenariusz 1
      2. Scenariusz 2
      3. Scenariusz 3
  9. Podsumowanie i wnioski
  10. 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:

  1. Użytkownik wysyła zapytanie w języku naturalnym do modelu LLM.
  2. Model rozpoznaje intencję i wywołuje odpowiednie narzędzie udostępniane przez serwer MCP.
  3. Serwer MCP Grafany wykonuje operację (np. odpytuje Prometheusa) i zwraca wynik.
  4. 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:

  1. 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
  1. Analiza zużycia pamięci przez wybrany serwis
  • odpytanie Prometheusa o metryki pamięci dla userservice z ostatniej godziny
  • wizualizacja wykresu oraz interpretacja zaobserwowanych trendów
  1. 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ą.

  1. Pobranie hasła do dashboardu Grafany
> kubectl get secret monitoring-grafana -n monitoring -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
  1. 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>
  1. 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

  1. Dokumentacja Kubernetes — https://kubernetes.io/docs/
  2. Dokumentacja Grafany — https://grafana.com/docs/
  3. Model Context Protocol (MCP) — https://modelcontextprotocol.io/
  4. Grafana MCP Server — https://github.com/grafana/mcp-grafana
  5. Bank of Anthos — https://github.com/GoogleCloudPlatform/bank-of-anthos
  6. Dokumentacja Prometheusa — https://prometheus.io/docs/
  7. Google Kubernetes Engine — https://cloud.google.com/kubernetes-engine/docs
  8. Locust — https://locust.io/
  9. Helm — https://helm.sh/docs/