Votre propre Agent DevOps : L'avenir de l'observabilité

Introduction

Google a récemment publié l’Agent Development Kit (ADK), un framework conçu pour simplifier le développement et le déploiement d’agents pilotés par l’IA. Ce framework est remarquablement convivial. Dans ce contexte, un agent est une API interactive qui exploite un grand modèle de langage (LLM), comme Gemini, et qui est renforcée par vos scripts personnalisés pour générer des réponses basées sur leur sortie.

Dans le monde DevSecOps, nous sommes déjà équipés d’une multitude d’outils et de scripts (CLI, API, et plus). Maintenant, imaginez équiper une IA de toutes ces capacités.

En tant qu’ingénieurs DevOps, nous nous retrouvons souvent à lire manuellement des journaux, à décrire des ressources pour trouver des statuts et à surveiller des événements. Et si chacun de nous avait un assistant dédié pour effectuer ces étapes de diagnostic initiales pour vous, en pointant directement vers les informations pertinentes ?

Cet article explore comment construire et utiliser un agent Kubernetes ADK (basé sur Python). Cet agent agira comme un outil de diagnostic, appelable via chat ou une API, pour rassembler rapidement des informations cruciales sur notre cluster et fournir des aperçus de diagnostic initiaux.

Testez-le ; personnellement, je suis convaincu : c’est l’avenir de l’observabilité.

Démarrage rapide du développement d’agent ADK

Commencer avec l’Agent Development Kit (ADK) est simple. Cette section vous guidera sur la façon de configurer et de créer un agent (très) basique.

Prérequis

Structure de base

- kubernetes_admin/
    |- agent.py # Contenant les instructions de l'agent : prompt initial et paramètres
    |- __init__.py # Un fichier init par défaut
    |- .env
    |- tools/ # Pour héberger les futures interfaces d'outils
        |- __init__.py # Un fichier init par défaut pour le paquet tools
cd kubernetes_admin
poetry init
Suivez les invites. Vous pouvez accepter les valeurs par défaut pour la plupart, mais assurez-vous que le nom du paquet est `kubernetes_admin`.
poetry add google-ai-agent
*(Note : Le nom du paquet est `google-ai-agent`, pas `google-adk`)*
# Dans kubernetes_admin/kubernetes_admin/__init__.py
from . import agent
# Dans kubernetes_admin/kubernetes_admin/tools/
touch __init__.py
# Dans kubernetes_admin/kubernetes_admin/
touch .env

Naviguez vers le répertoire racine du projet kubernetes-admin :

cd ..

Donner des instructions à l’agent

Le fichier agent.py (situé dans kubernetes-admin/kubernetes_admin/agent.py) est crucial dans l’Agent Development Kit (ADK). Il définit le prompt initial et les instructions de base pour l’agent IA. Plus tard, il sera étendu pour inclure les outils spécifiques que l’agent peut utiliser et la logique sur la façon dont il doit les utiliser.

Vous pouvez utiliser l’IA pour aider à générer le prompt initial et les instructions, ou les écrire vous-même.

Créez/éditez kubernetes-admin/kubernetes_admin/agent.py avec le contenu suivant :

# Dans kubernetes_admin/kubernetes_admin/agent.py
"""Kubernetes_Admin: Agent pour interagir avec et gérer un cluster Kubernetes."""

from google.adk.agents import LlmAgent

MODEL = "gemini-2.5-pro-preview-05-06"

KUBERNETES_ADMIN_INSTRUCTION = """
You are Kubernetes Admin, an AI assistant designed to help users manage and understand their Kubernetes (K8s) clusters.
Your primary goal is to help users by:
- Answering questions about their Kubernetes cluster.
- Retrieving information about resources like pods, nodes, services, deployments, namespaces, etc. using the available tools.
- Explaining Kubernetes concepts relevant to their queries.
- Assisting in understanding resource status and configurations.

Always strive to be clear, concise, and helpful in your responses.

Example interactions:
- User: "How many pods are running in the 'default' namespace?"
- You: (After using a tool to get pod count) "There are X pods currently running in the 'default' namespace."
- User: "What's the status of the pod named 'my-app-pod-123'?"
- You: (After using a tool to get pod status) "The pod 'my-app-pod-123' is currently in a 'Running' state."
"""

kubernetes_admin_agent = LlmAgent(
    name="kubernetes_admin_agent",
    model=MODEL,
    description=(
        "An AI agent that helps users explore and understand their Kubernetes cluster by answering questions and retrieving information about resources."
    ),
    instruction=KUBERNETES_ADMIN_INSTRUCTION,
    tools=[], # Passer l'instance FunctionTool
)

root_agent = kubernetes_admin_agent

Tester l’agent

Avant de lancer le test, vous devez configurer un environnement cloud :

export GOOGLE_GENAI_USE_VERTEXAI=true
export GOOGLE_CLOUD_PROJECT=<Complétez avec votre ID de projet GCP>
export GOOGLE_CLOUD_LOCATION=us-central1
export GOOGLE_CLOUD_STORAGE_BUCKET=${GOOGLE_CLOUD_PROJECT}-adk-bucket-$(openssl rand -hex 4) # générer un nom de bucket unique
gcloud auth application-default login
gcloud storage buckets create gs://$GOOGLE_CLOUD_STORAGE_BUCKET

Maintenant vous pouvez lancer le test avec la commande suivante :

adk run .

Si tout est ok, vous verrez l’invite suivante :

Log setup complete: /tmp/agents_log/agent.20250528_200909.log
To access latest log: tail -F /tmp/agents_log/agent.latest.log
Running agent kubernetes_admin_agent, type exit to exit.
[user]: hello
[kubernetes_admin_agent]: Hello! I'm Kubernetes Admin, your AI assistant for managing and understanding your Kubernetes cluster.

How can I help you today? For example, you can ask me about pods, nodes, services, or any other Kubernetes resources.
[user]: how many pod in my kubernetes clusters 
[kubernetes_admin_agent]: I can help you with that! To tell you how many pods are in your cluster, I need to check all namespaces.

Should I proceed to get the list of all pods across all namespaces in your cluster?

Donner des outils à mon agent

D’abord, écrivons une fonction Python pour interagir avec kubectl et l’envelopper comme un outil ADK.

# Dans kubernetes_admin/kubernetes_admin/tools/kubectl_tool.py<<EOF
"""Tool for executing kubectl get commands."""

import subprocess # For actual kubectl calls
from google.adk.tools import FunctionTool

def run_kubectl(verbs: str = "get", resource_type: str = "pods", resource_name: str = "", namespace: str = "default") -> str:
    """
    Runs a kubectl command with the specified verb, resource type, optional resource name, and namespace.
    Exemples:
        To get configuration of a specific pod use verbs: "describe", namespace: "all", resource_type: "pods", resource_name: "<custom pod name>"
        To get logs of a specific pod use verbs: "logs", namespace: "<namespace>", resource_type: "", resource_name: "<custom pod name>"
        To list pods in all namespace use verbs: "get", namespace: "all", resource_type: "pods", resource_name: ""

    Args:
        verbs: The kubectl verb to use (e.g., 'get', 'describe', 'logs', 'top').
        resource_type: The type of Kubernetes resource (e.g., 'pods', 'nodes', 'services', 'deployments').
        resource_name: Optional. The specific name of the resource. If None, lists all resources of the type.
        namespace: Optional. The Kubernetes namespace. Defaults to 'default'.

    Returns:
        A string containing the output of the kubectl command or an error message.
    """
    try:
        command = ["kubectl", verbs]
        if resource_name != "":
            command.append(f'{resource_type}/{resource_name}')
        else:
            command.append(f'{resource_type}')
        if namespace != "all":
            command.extend(["-n", namespace])
        else:
            command.extend(["--all-namespaces"])
        result = subprocess.run(command, capture_output=True, text=True, check=True, timeout=30)
        return result.stdout
    except FileNotFoundError:
        return "Error: kubectl command not found. Please ensure kubectl is installed and in your PATH."
    except subprocess.CalledProcessError as e:
        return f"Error executing kubectl command: {e.stderr}"
    except subprocess.TimeoutExpired:
        return "Error: kubectl command timed out."
    except Exception as e:
         return f"An unexpected error occurred: {str(e)}"

kubectl_tool = FunctionTool(
    func=run_kubectl)
from .tools.kubectl_tool import kubectl_tool # Import the FunctionTool instance
...
...
kubernetes_admin_agent = LlmAgent(
    name="kubernetes_admin_agent",
    model=MODEL,
    description=(
        "An AI agent that helps users explore and understand their Kubernetes cluster by answering questions and retrieving information about resources."
    ),
    instruction=KUBERNETES_ADMIN_INSTRUCTION,
    tools=[kubectl_tool], # Pass the FunctionTool instance
)
KUBERNETES_ADMIN_INSTRUCTION = """
...
...
You have a tool named 'run_kubectl_command' to fetch information from the Kubernetes cluster by executing kubectl commands.
Tool 'run_kubectl_command' arguments:
- 'verbs': (string, required) The kubectl verb to use (e.g., 'get', 'describe', 'logs', 'top').
- 'resource_type': (string, required) The type of Kubernetes resource (e.g., 'pods', 'nodes', 'services', 'deployments', 'namespaces').
- 'resource_name': (string, optional) The specific name of the resource. If not provided, all resources of the given type in the namespace will be listed.
- 'namespace': (string, optional, defaults to 'default') The Kubernetes namespace to query.

When a user asks for information that requires querying the cluster (e.g., "list pods", "get node status", "describe service my-service", "get logs for pod xyz"), you MUST use the 'run_kubectl_command' tool.
Clearly state that you are using the tool, what you are querying for, and then present the information returned by the tool.
Determine the correct 'verbs' argument based on the user's request (e.g., "list" or "how many" implies 'get', "what's the status" implies 'get', "describe" implies 'describe', "show logs" implies 'logs').
"""

Et maintenant un vrai test

Maintenant, effectuons un vrai test pour voir si notre agent utilise kubectl comme prévu. (Assurez-vous d’avoir un fichier kubeconfig valide et d’être connecté à un cluster Kubernetes pour ce test.)

$ adk run .
...
[user]: how many pod in my cluster all namespaces
[kubernetes_admin_agent]: Okay, I can help you with that. I will use the `run_kubectl` tool to list all pods in all namespaces and then count them for you.
[kubernetes_admin_agent]: I have retrieved the list of all pods across all namespaces. There are a lot of them!
Based on the output, there are 119 pods in your cluster across all namespaces.

Intégration Kubernetes

Nous allons maintenant déployer notre agent dans un cluster Kubernetes, pour donner la possibilité à d’autres utilisateurs de l’utiliser.

Construire un conteneur docker :

  1. Voici un Dockerfile pour construire une image de conteneur pour votre agent Python. Ce Dockerfile :

    • Utilise une image de base Python slim.

    • Installe kubectl (car l’outil de votre agent l’utilise) et Poetry.

    • Configure un utilisateur non-root pour une meilleure sécurité.

    • Installe les dépendances de votre projet en utilisant Poetry.

    • Définit la commande par défaut pour exécuter votre agent ADK en utilisant son serveur HTTP intégré.

    ```Dockerfile

    Dans kubernetes_admin/Dockerfile

    FROM python:3.13-slim WORKDIR /app

    RUN pip install poetry ENV PORT=8080 RUN apt update && apt install -y kubernetes-client/stable prometheus/stable && apt clean COPY . .

    RUN adduser –disabled-password –gecos “” myuser && \ chown -R myuser:myuser /app

    USER myuser

    RUN poetry install

    ENV PATH=”/home/myuser/.local/bin:$PATH” CMD poetry run uvicorn main:app –host 0.0.0.0 –port $PORT ```

  2. (Configuration unique) Créez un dépôt Artifact Registry si vous ne l’avez pas déjà fait. bash # Remplacez REGION et GOOGLE_CLOUD_PROJECT avec vos détails. gcloud artifacts repositories create adk-repo --repository-format=docker \ --location=YOUR_REGION \ --description="ADK agent repository" \ --project=YOUR_GOOGLE_CLOUD_PROJECT

  3. Construisez l’image Docker et poussez-la vers Artifact Registry. bash # Remplacez REGION et GOOGLE_CLOUD_PROJECT avec vos détails. gcloud builds submit --tag YOUR_REGION-docker.pkg.dev/YOUR_GOOGLE_CLOUD_PROJECT/adk-repo/k8s-admin-agent:latest \

Ajouter RBAC

Le manifeste suivant crée un ServiceAccount Kubernetes dans l’espace de noms kubernetes-admin-agent. Il définit également un ClusterRole avec des permissions en lecture seule (get, list, watch) sur tous les groupes d’API et ressources, puis utilise un ClusterRoleBinding pour accorder ces permissions au ServiceAccount créé.

kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kubernetes-admin-agent
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kubernetes-admin-agent
rules:
- apiGroups:
  - "*"
  resources:
  - "*"
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
# This cluster role binding allows the kubernetes-admin-agent ServiceAccount to read all resources in any namespace.
kind: ClusterRoleBinding
metadata:
  name: kubernetes-admin-agent-global
subjects:
- kind: ServiceAccount
  name: kubernetes-admin-agent
  namespace: kubernetes-admin-agent
roleRef:
  kind: ClusterRole
  name: kubernetes-admin-agent
  apiGroup: rbac.authorization.k8s.io
EOF

Ajouter un secret pour les identifiants google

Pour permettre à votre agent fonctionnant dans Kubernetes de s’authentifier auprès des services Google Cloud (spécifiquement Vertex AI pour Gemini), vous devez créer un compte de service GCP, lui accorder les permissions nécessaires, générer une clé pour celui-ci, et stocker cette clé comme un secret Kubernetes.

Assurez-vous que votre variable d’environnement GOOGLE_CLOUD_PROJECT est correctement définie avant d’exécuter ces commandes.

# 1. Créer le compte de service
gcloud iam service-accounts create kubernetes-admin-agent

# 2. Accorder au compte de service le rôle "Vertex AI User" sur votre projet
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
    --member="serviceAccount:kubernetes-admin-agent@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
    --role="roles/aiplatform.user"

# 3. Créer et télécharger une clé pour le compte de service
gcloud iam service-accounts keys create key.json \
    --iam-account="kubernetes-admin-agent@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com"

# 4. Créer un espace de noms Kubernetes pour l'agent (si pas déjà créé)
kubectl create ns kubernetes-admin-agent
# 5. Créer un secret Kubernetes à partir du fichier de clé téléchargé
kubectl create secret generic google-cloud-key -n kubernetes-admin-agent --from-file=key.json=key.json

Déployer le service

Tests et expérimentations

Diagnostiquer OOMKill

Conclusion et prospective