Files
DevOpsLab/scripts/k8s_status.py
Sergey Antropoff 05881e8d74 podman: переход на Podman, Minikube, локальные образы и док для новичков
- Molecule: драйвер delegated, коллекция containers.podman, create/destroy/verify на Podman
- Makefile: все вызовы docker заменены на podman, сокет /run/podman/podman.sock
- Сборка образов: podman build (без buildx), buildall/buildall-image — только локально без push
- Ansible-controller: Podman в образе, docker-compose на podman compose, сокет Podman
- K8s: Kind заменён на Minikube (драйвер podman), скрипты и Makefile обновлены
- Пресеты: проверка локальных образов, без podman pull (registry запрещён)
- Документация: docs/podman.md, docs/quickstart-for-dummies.md (роли, плейбук, линт, тесты, пресеты, инвентори)
- README: ссылка на quickstart-for-dummies

Made-with: Cursor
2026-03-11 19:59:47 +03:00

296 lines
9.9 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Скрипт для детального отчета о состоянии Kubernetes кластера
Автор: Сергей Антропов
Сайт: https://devops.org.ru
"""
import sys
import subprocess
import json
def get_cluster_name():
"""Получает имя текущего контекста (Minikube)."""
result = subprocess.run(
"kubectl config current-context 2>/dev/null", shell=True, capture_output=True, text=True
)
if result.returncode == 0:
return result.stdout.strip()
return None
def run_kubectl_cmd(cmd):
"""Выполняет команду kubectl на хосте (контекст Minikube)."""
full_cmd = f"kubectl {cmd}"
result = subprocess.run(full_cmd, shell=True, capture_output=True, text=True)
return result.stdout
def print_section(title):
"""Выводит заголовок секции"""
print(f"\n{'='*70}")
print(f" {title}")
print(f"{'='*70}\n")
def print_subsection(title):
"""Выводит подзаголовок"""
print(f"\n{''*70}")
print(f" {title}")
print(f"{''*70}\n")
def get_cluster_info():
"""Получает информацию о кластере"""
print_section("📊 ОБЩАЯ ИНФОРМАЦИЯ О КЛАСТЕРЕ")
# Версия Kubernetes
version = run_kubectl_cmd("version --short")
print(version)
def get_nodes_status():
"""Получает статус узлов"""
print_section("🖥️ УЗЛЫ КЛАСТЕРА")
nodes = run_kubectl_cmd("get nodes -o wide")
print(nodes)
# Детальная информация о каждом узле
node_names = run_kubectl_cmd("get nodes -o jsonpath='{.items[*].metadata.name}'")
if node_names.strip():
for node in node_names.strip().split():
print_subsection(f"Узел: {node}")
node_info = run_kubectl_cmd(f"describe node {node}")
print(node_info)
def get_namespaces():
"""Получает список namespace"""
print_section("📁 NAMESPACES")
namespaces = run_kubectl_cmd("get namespaces")
print(namespaces)
def get_pods_by_namespace():
"""Получает поды по namespace"""
print_section("🪟 PODS")
# Получаем список namespace
namespaces_output = run_kubectl_cmd("get namespaces -o json")
try:
namespaces_data = json.loads(namespaces_output)
namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']]
except:
namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease']
for ns in namespaces:
print_subsection(f"Namespace: {ns}")
pods = run_kubectl_cmd(f"get pods -n {ns} -o wide")
if pods.strip():
print(pods)
else:
print(" (пусто)")
def get_services():
"""Получает сервисы"""
print_section("🔗 SERVICES")
namespaces_output = run_kubectl_cmd("get namespaces -o json")
try:
namespaces_data = json.loads(namespaces_output)
namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']]
except:
namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease']
for ns in namespaces:
print_subsection(f"Namespace: {ns}")
services = run_kubectl_cmd(f"get services -n {ns}")
if services.strip():
print(services)
else:
print(" (пусто)")
def get_ingress():
"""Получает Ingress ресурсы"""
print_section("🌐 INGRESS")
namespaces_output = run_kubectl_cmd("get namespaces -o json")
try:
namespaces_data = json.loads(namespaces_output)
namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']]
except:
namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease']
ingress_found = False
for ns in namespaces:
ingress = run_kubectl_cmd(f"get ingress -n {ns} 2>/dev/null")
if ingress.strip() and "No resources found" not in ingress:
ingress_found = True
print_subsection(f"Namespace: {ns}")
print(ingress)
if not ingress_found:
print(" Ingress ресурсы не найдены")
def get_pvcs():
"""Получает PersistentVolumeClaims"""
print_section("💾 VOLUMES (PVC)")
namespaces_output = run_kubectl_cmd("get namespaces -o json")
try:
namespaces_data = json.loads(namespaces_output)
namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']]
except:
namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease']
pvc_found = False
for ns in namespaces:
pvcs = run_kubectl_cmd(f"get pvc -n {ns} 2>/dev/null")
if pvcs.strip() and "No resources found" not in pvcs:
pvc_found = True
print_subsection(f"Namespace: {ns}")
print(pvcs)
if not pvc_found:
print(" PVC не найдены")
def get_deployments():
"""Получает Deployments"""
print_section("🚀 DEPLOYMENTS")
namespaces_output = run_kubectl_cmd("get namespaces -o json")
try:
namespaces_data = json.loads(namespaces_output)
namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']]
except:
namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease']
for ns in namespaces:
print_subsection(f"Namespace: {ns}")
deployments = run_kubectl_cmd(f"get deployments -n {ns}")
if deployments.strip():
print(deployments)
else:
print(" (пусто)")
def get_daemonsets():
"""Получает DaemonSets"""
print_section("🔧 DAEMONSETS")
namespaces_output = run_kubectl_cmd("get namespaces -o json")
try:
namespaces_data = json.loads(namespaces_output)
namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']]
except:
namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease']
for ns in namespaces:
print_subsection(f"Namespace: {ns}")
daemonsets = run_kubectl_cmd(f"get daemonsets -n {ns}")
if daemonsets.strip():
print(daemonsets)
else:
print(" (пусто)")
def get_statefulsets():
"""Получает StatefulSets"""
print_section("🗄️ STATEFULSETS")
namespaces_output = run_kubectl_cmd("get namespaces -o json")
try:
namespaces_data = json.loads(namespaces_output)
namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']]
except:
namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease']
statefulsets_found = False
for ns in namespaces:
statefulsets = run_kubectl_cmd(f"get statefulsets -n {ns} 2>/dev/null")
if statefulsets.strip() and "No resources found" not in statefulsets:
statefulsets_found = True
print_subsection(f"Namespace: {ns}")
print(statefulsets)
if not statefulsets_found:
print(" StatefulSets не найдены")
def get_events():
"""Получает события"""
print_section("📅 СОБЫТИЯ (EVENTS)")
namespaces_output = run_kubectl_cmd("get namespaces -o json")
try:
namespaces_data = json.loads(namespaces_output)
namespaces = [ns['metadata']['name'] for ns in namespaces_data['items']]
except:
namespaces = ['default', 'kube-system', 'kube-public', 'kube-node-lease']
for ns in namespaces:
print_subsection(f"Namespace: {ns}")
events = run_kubectl_cmd(f"get events -n {ns} --sort-by='.lastTimestamp' | tail -20")
if events.strip():
print(events)
else:
print(" (пусто)")
def get_helm_releases():
"""Получает Helm релизы"""
print_section("📦 HELM RELEASES")
helm_output = run_kubectl_cmd("helm list --all-namespaces 2>/dev/null")
if helm_output.strip():
print(helm_output)
else:
print(" Helm релизы не найдены")
def get_resource_usage():
"""Получает использование ресурсов"""
print_section("📈 ИСПОЛЬЗОВАНИЕ РЕСУРСОВ")
try:
# Проверяем наличие metrics-server
top_nodes = run_kubectl_cmd("top nodes 2>/dev/null")
if top_nodes.strip():
print_subsection("Узлы:")
print(top_nodes)
except:
print(" metrics-server не установлен или недоступен")
try:
top_pods = run_kubectl_cmd("top pods --all-namespaces 2>/dev/null")
if top_pods.strip():
print_subsection("Pods (топ-20):")
# Берем только первые 20 строк
lines = top_pods.strip().split('\n')
print('\n'.join(lines[:21])) # + заголовок
except:
pass
def main():
"""Главная функция"""
# Проверяем доступность контейнера
result = subprocess.run("docker ps | grep k8s-controller", shell=True, capture_output=True, text=True)
if result.returncode != 0:
print("❌ Контейнер k8s-controller не запущен")
sys.exit(1)
print("="*70)
print(" ДЕТАЛЬНЫЙ ОТЧЕТ О СОСТОЯНИИ KUBERNETES КЛАСТЕРА")
print("="*70)
get_cluster_info()
get_nodes_status()
get_namespaces()
get_resource_usage()
get_pods_by_namespace()
get_deployments()
get_daemonsets()
get_statefulsets()
get_services()
get_ingress()
get_pvcs()
get_events()
get_helm_releases()
print("\n" + "="*70)
print(" ОТЧЕТ ЗАВЕРШЕН")
print("="*70 + "\n")
if __name__ == '__main__':
main()