Runbook de incidentes nocturnos en AKS para responsables TI de cuidados
Valida el JSON de Azure Monitor y separa decisiones durante incidentes nocturnos de una aplicación asistencial.
A las 23:40 llama la responsable nocturna del centro: la pantalla de reservas abre, pero no se guarda el registro asistencial. Hay un correo de Azure, aunque el traspaso no indica el recurso afectado, la severidad ni si la alerta sigue activa. Además, el borrador dirigido al proveedor TI contiene el nombre de un residente. La persona responsable de operaciones y TI debe frenar a la vez el retraso de la investigación y la difusión secundaria de datos personales.
Este artículo se dirige a quien responde por la aplicación de reservas y cuidados del centro en Azure y por su escalado nocturno. No es un manual para el personal asistencial de primera línea. El objetivo es un runbook que conserve una cronología común, pero separe las decisiones de continuidad del centro de la investigación de AKS.
Azure Kubernetes Service (AKS) es el servicio administrado de Kubernetes en Azure para desplegar y gestionar aplicaciones en contenedores. Kubernetes programa, reinicia y escala grupos de contenedores; Azure asume la carga operativa del plano de control de AKS. Azure no decide el impacto en el centro, no investiga por sí solo cada carga de trabajo ni define el orden de llamadas nocturnas.
Puntos clave
- No conviertas
severityde Azure directamente en el nivel del incidente asistencial; evalúa reservas, registros, relevo y seguridad por separado. - Antes de usar Claude Code, depura el JSON de Common Alert Schema y valida localmente campos obligatorios y datos personales directos.
- Separa tareas de Claude Code, decisiones del operador Azure/TI y decisiones del responsable del centro.
- Sin credenciales de Azure, el resultado es una prueba del contrato de traspaso, no una prueba de AKS ni de entrega de alertas.
- Mide el ROI con marcas de tiempo, rechazos y minutos de trabajo de incidentes comparables, sin porcentajes inventados.
Convertir el incidente nocturno en un único flujo de traspaso
Si las llamadas, alertas de Azure, pantallas afectadas y tablas de contacto quedan en notas distintas, el hecho de las 23:40 cambia según quien lo cuente. La primera tabla debe decir: “la búsqueda de reservas funciona”, “falla el guardado del registro”, “se ha activado el papel” y “próxima actualización a las 00:10”. Los estados de Pod, Node y Deployment aparecen después como evidencia técnica.
Azure Monitor es el servicio unificado de observabilidad de Microsoft para recopilar, analizar y usar métricas, registros, trazas y eventos de entornos cloud e híbridos. Azure Monitor Common Alert Schema, o esquema común de alertas, es la estructura JSON normalizada para consumir distintos avisos de Azure Monitor. data.essentials contiene metadatos comunes como la severidad; data.alertContext cambia según la señal y aporta contexto de investigación.
Microsoft Learn documenta severity de Sev0 a Sev4, signalType como Metric, Log o Activity Log, y monitorCondition como Fired o Resolved. alertTargetIDs es la lista de identificadores de Azure Resource Manager afectados. Estos campos sirven para enrutar el traspaso, pero no deciden la seguridad de los residentes, el uso de papel ni la declaración de recuperación del centro.
Las fuentes primarias comprobadas el 23 de julio de 2026 son Qué es AKS, Introducción a Azure Monitor, Common Alert Schema, Supervisar AKS y Alertas de Service Health. Como material interno relacionado, consulta la guía de despliegue con Kubernetes y la lista de seguridad para Claude Code.
flowchart TD
A["Recibir alerta de Azure Monitor"] --> B["Guardar fixture JSON depurada"]
B --> C{"Pasa el validator local?"}
C -- "No" --> D["Eliminar datos personales o reponer campos"]
D --> B
C -- "Sí" --> E["Claude Code ordena el traspaso"]
E --> F["Azure/TI decide la investigación técnica"]
E --> G["El centro decide la continuidad asistencial"]
F --> H["Unir evidencias en la próxima actualización"]
G --> H
H --> I{"Se cumplen ambos cierres?"}
I -- "No" --> H
I -- "Sí" --> J["Registrar la revisión posterior"]
Service Health aporta otra evidencia sobre notificaciones que coinciden con suscripciones, servicios, regiones y tipos configurados. Una vista vacía no demuestra que la aplicación esté sana. Del mismo modo, una alerta AKS en Resolved no completa la conciliación de registros en papel ni la revisión de reservas.
Qué hace Claude Code y qué deciden las personas
La tabla de traspaso debe nombrar entradas, salidas, prohibiciones y responsables de aprobación. Tratar a Claude Code como dueño de la recuperación mezcla diagnósticos sin respaldo y comandos de cambio en una misma conversación. Aquí solo organiza evidencia aprobada.
Tareas de Claude Code
- Extraer
severity,signalType,monitorCondition,alertTargetIDsy horas desde un fixture ya validado. - Separar hechos confirmados, incógnitas y decisiones humanas pendientes; señalar una próxima actualización ausente.
- Redactar notas separadas para el centro y el proveedor bajo un mismo incident ID.
- Proponer comandos de observación sin ejecutarlos, indicando la evidencia y los permisos necesarios.
Decisiones del operador Azure/TI
- Elegir el orden para revisar regla de alerta, recurso objetivo, monitorización, cambios recientes y telemetría de AKS.
- Decidir si obtiene más evidencia en Azure Portal, Container insights, Log Analytics o un terminal autorizado.
- Aprobar o rechazar reinicio, escalado, rollback y escalado técnico.
- Decidir si
Resolvedbasta como evidencia técnica o se mantiene la observación.
Decisiones del responsable del centro
- Pausar reservas, pasar los registros a papel o priorizar un proceso asistencial.
- Dirigir comprobaciones de seguridad, relevo, carga posterior y comunicaciones con familias o terceros.
- Aprobar la información compartible, la siguiente comunicación interna y la recuperación operativa.
- Asignar quién concilia registros pendientes o reservas duplicadas después de la recuperación técnica.
Esto no es asesoramiento jurídico individual. La clasificación, conservación, comunicación y notificación de datos personales deben seguir las políticas, contratos y responsables del centro.
Tres casos de uso
Caso de uso 1: Traspasar un fallo nocturno de la API de reservas
- Entrada: fixture de Common Alert Schema depurado, prueba de pantalla, hora del incidente y próxima actualización.
- Salida: una hoja que separa IDs de Azure e impacto del centro, incógnitas y petición al proveedor.
- Revisión humana: Azure/TI aprueba la investigación; el centro aprueba el canal alternativo y la comprobación de duplicados.
Sev1 no justifica por sí solo cerrar todos los canales. Un fallo de lectura y un riesgo de escritura duplicada exigen actuaciones distintas. Claude Code separa observaciones y aprobaciones pendientes, sin tomar la decisión.
Caso de uso 2: Escalar retrasos al guardar registros asistenciales
- Entrada: fixture válido, función afectada, cantidad depurada, intervalo y existencia de una versión reciente.
- Salida: nota técnica con campos de enrutado, condiciones de reproducción sin datos directos y evidencias pendientes.
- Revisión humana: Azure/TI decide registros y rollback; el centro decide papel y conciliación posterior.
No envíes a Claude Code capturas o logs con nombres de residentes. El validator bloquea claves identificativas explícitas, correos y teléfonos, pero no reconoce todos los nombres sin etiqueta, imágenes o identificadores codificados. La revisión visual sigue siendo una aprobación humana.
Caso de uso 3: Cerrar la recuperación operativa después de Resolved
- Entrada: fixture con
monitorCondition: "Resolved", conectividad, registros pendientes, reservas duplicadas e historial de contactos. - Salida: listas separadas de cierre técnico y operativo, tareas restantes y responsable de la mañana.
- Revisión humana: Azure/TI cierra la monitorización; el centro declara la recuperación tras conciliar registros y reservas.
En Common Alert Schema, Resolved significa que desapareció la condición que disparó la alerta. No confirma que el papel se haya cargado ni que las devoluciones de llamada hayan terminado. Dos condiciones de cierre evitan ocultar trabajo operativo tras una recuperación técnica.
Validator de traspaso listo para copiar y ejecutar
El siguiente validator usa solo la biblioteca estándar de Node.js y lee la ruta JSON indicada en la línea de comandos. No inicia sesión en Azure ni llama a AKS, Azure Monitor o kubectl. Solo prueba la forma documentada de Common Alert Schema y el contrato de depuración de este runbook.
// validate-azure-alert-handoff.mjs
import { readFileSync } from "node:fs";
const REQUIRED = ["severity", "signalType", "monitorCondition", "alertTargetIDs"];
const ALLOWED = {
severity: new Set(["Sev0", "Sev1", "Sev2", "Sev3", "Sev4"]),
signalType: new Set(["Metric", "Log", "Activity Log"]),
monitorCondition: new Set(["Fired", "Resolved"]),
};
const DIRECT_PERSONAL_DATA_KEYS = new Set([
"residentname", "patientname", "carerecipientname", "serviceusername",
"staffname", "employeename", "familyname", "guardianname",
"phone", "phonenumber", "telephone", "mobile",
"email", "emailaddress", "streetaddress", "postaladdress",
"dateofbirth", "birthdate", "medicalrecordid", "carerecordid",
"residentid", "patientid",
]);
const EMAIL = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i;
const PHONE = /(?:^|[^A-Za-z0-9])(?:\+\d{1,3}[ .-]?)?(?:\(\d{2,4}\)|\d{2,4})[ .-]\d{2,4}[ .-]\d{3,4}(?:$|[^A-Za-z0-9])/;
const LABELED_NAME = /(?:resident|patient|care recipient|staff|employee|family|guardian|利用者|入居者|患者|職員|家族)(?:\s+name|氏名|名)\s*[:=:]\s*\S+/iu;
const ARM_RESOURCE_ID_PATH = /^\$\.data\.essentials\.(?:alertId|alertRuleId|alertTargetIDs\[\d+\])$/;
function normalizeKey(key) {
return key.replace(/[^a-z0-9]/gi, "").toLowerCase();
}
function findDirectPersonalData(value, path = "$", findings = []) {
if (Array.isArray(value)) {
value.forEach((item, index) => findDirectPersonalData(item, `${path}[${index}]`, findings));
return findings;
}
if (value && typeof value === "object") {
for (const [key, child] of Object.entries(value)) {
const childPath = `${path}.${key}`;
if (DIRECT_PERSONAL_DATA_KEYS.has(normalizeKey(key))) {
findings.push(`${childPath} uses a prohibited direct-personal-data key`);
}
findDirectPersonalData(child, childPath, findings);
}
return findings;
}
if (typeof value === "string") {
if (EMAIL.test(value)) findings.push(`${path} contains an email address`);
if (!ARM_RESOURCE_ID_PATH.test(path) && PHONE.test(value)) {
findings.push(`${path} contains a phone number`);
}
if (LABELED_NAME.test(value)) findings.push(`${path} contains a labeled person name`);
}
return findings;
}
export function validate(payload) {
const errors = [];
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
throw new Error("payload must be a JSON object");
}
if (payload.schemaId !== "azureMonitorCommonAlertSchema") {
errors.push('schemaId must be "azureMonitorCommonAlertSchema"');
}
const essentials = payload.data?.essentials;
if (!essentials || typeof essentials !== "object" || Array.isArray(essentials)) {
errors.push("data.essentials must be an object");
} else {
for (const field of REQUIRED) {
if (!(field in essentials)) errors.push(`missing data.essentials.${field}`);
}
for (const [field, allowed] of Object.entries(ALLOWED)) {
if (field in essentials && !allowed.has(essentials[field])) {
errors.push(`data.essentials.${field} has an undocumented value`);
}
}
if ("alertTargetIDs" in essentials) {
if (!Array.isArray(essentials.alertTargetIDs) ||
essentials.alertTargetIDs.length === 0 ||
essentials.alertTargetIDs.some((id) => typeof id !== "string" || id.trim() === "")) {
errors.push("data.essentials.alertTargetIDs must be a non-empty string array");
}
}
}
errors.push(...findDirectPersonalData(payload));
if (errors.length > 0) throw new Error(errors.join("; "));
return true;
}
function loadJson(filePath) {
return JSON.parse(readFileSync(filePath, "utf8"));
}
function runSelfTest() {
const base = loadJson("sanitized-alert.json");
validate(base);
const cases = [
["direct personal data", (p) => { p.data.customProperties.residentName = "Example Resident"; }],
["missing severity", (p) => { delete p.data.essentials.severity; }],
["missing signalType", (p) => { delete p.data.essentials.signalType; }],
["missing monitorCondition", (p) => { delete p.data.essentials.monitorCondition; }],
["missing alertTargetIDs", (p) => { delete p.data.essentials.alertTargetIDs; }],
];
let rejected = 0;
for (const [label, mutate] of cases) {
const candidate = structuredClone(base);
mutate(candidate);
try {
validate(candidate);
console.error(`FAIL self-test: accepted ${label}`);
process.exitCode = 1;
} catch {
console.log(`PASS self-test: rejected ${label}`);
rejected += 1;
}
}
if (!process.exitCode) console.log(`PASS self-test: ${rejected} rejection cases`);
}
if (process.argv[2] === "--self-test") {
runSelfTest();
} else {
const filePath = process.argv[2];
if (!filePath) {
console.error("Usage: node validate-azure-alert-handoff.mjs <fixture.json> | --self-test");
process.exit(2);
}
try {
validate(loadJson(filePath));
console.log(`PASS fixture: ${filePath}`);
} catch (error) {
console.error(`FAIL fixture: ${error.message}`);
process.exit(1);
}
}
Guarda el fixture completo como sanitized-alert.json junto al validator. Los ID, horas y nombres de regla son datos de prueba, no resultados de un incidente real. customProperties es un punto de extensión documentado; aquí deja visible la declaración de depuración.
{
"schemaId": "azureMonitorCommonAlertSchema",
"data": {
"essentials": {
"alertId": "/subscriptions/00000000-0000-4000-8000-000000000000/providers/Microsoft.AlertsManagement/alerts/11111111-1111-4111-8111-111111111111",
"alertRule": "care-api-availability",
"alertRuleId": "/subscriptions/00000000-0000-4000-8000-000000000000/resourceGroups/rg-care-prod/providers/microsoft.insights/metricAlerts/care-api-availability",
"severity": "Sev1",
"signalType": "Metric",
"monitorCondition": "Fired",
"monitoringService": "Platform",
"alertTargetIDs": [
"/subscriptions/00000000-0000-4000-8000-000000000000/resourceGroups/rg-care-prod/providers/Microsoft.ContainerService/managedClusters/aks-care-prod"
],
"configurationItems": [
"aks-care-prod"
],
"originAlertId": "sanitized-night-incident-001",
"firedDateTime": "2026-07-23T14:40:00Z",
"description": "The production booking and care-record API crossed its approved availability threshold.",
"essentialsVersion": "1.0",
"alertContextVersion": "1.0"
},
"alertContext": {
"properties": null
},
"customProperties": {
"environment": "production",
"service": "booking-care-api",
"sanitized": "true",
"runbook": "night-incident-v1"
}
}
}
Ejecuta estos comandos exactos con Node.js 17 o posterior. El primero lee el fixture válido. El segundo demuestra el rechazo de datos personales directos y de cada uno de los cuatro campos obligatorios ausentes.
node validate-azure-alert-handoff.mjs sanitized-alert.json
node validate-azure-alert-handoff.mjs --self-test
Esta es la salida exacta obtenida con el código y el fixture publicados el 23 de julio de 2026, no una estimación.
PASS fixture: sanitized-alert.json
PASS self-test: rejected direct personal data
PASS self-test: rejected missing severity
PASS self-test: rejected missing signalType
PASS self-test: rejected missing monitorCondition
PASS self-test: rejected missing alertTargetIDs
PASS self-test: 5 rejection cases
Superar la prueba no demuestra la configuración de Azure, la entrega real, la salud de AKS ni la recuperación. Una prueba conectada necesita Common Alert Schema habilitado en el Action Group, receptor, credenciales, red, permisos y una alerta de prueba. Aquí no se usaron credenciales; solo se probó el contrato documentado de traspaso.
Errores y riesgos: no llames prueba operativa a un objeto fijo
El primer error es validar un objeto incrustado en el script y afirmar que la implementación está lista. La causa es no ejecutar lectura de archivo, JSON incorrecto, campos ausentes ni salidas de rechazo. La corrección es leer un fixture local y ejecutar casos de éxito y fallo en cada revisión del runbook.
El segundo error es llamar prueba de conectividad AKS a un validator correcto. La causa es dar el mismo nombre al contrato de entrada y al acceso cloud. Registra “handoff contract passed” y separa entrega, monitorización y evidencia AKS.
El tercer error es convertir Sev0 a Sev4 en niveles de seguridad asistencial. Son escalas diferentes. Aprueba por separado severidad Azure, impacto en reservas, impacto en registros, seguridad y papel.
El cuarto error es anunciar automáticamente el cierre con Resolved. La condición puede desaparecer mientras quedan registros pendientes. Mantén abierto el incident ID hasta completar el cierre técnico y el del centro.
El quinto error es usar el validator como garantía de ausencia de datos personales. Los patrones no detectan todas las imágenes, identificadores opacos o nombres sin etiqueta. Minimiza entradas, revisa texto libre y adjuntos, y aplica el gobierno de información del centro.
Medir el ROI con incidentes comparables
Construye la tabla con incident ID, marcas de tiempo y minutos de trabajo. Compara rangos de severidad, horario nocturno e impacto similares. Si hay pocos casos, muestra cronologías individuales en vez de afirmar una tasa.
| Métrica | Método de registro | Pregunta |
|---|---|---|
| Tiempo de traspaso TI | Primera alerta hasta recepción de fixture válido | ¿Cuánta espera causan los defectos del contrato? |
| Tiempo de confirmar impacto | Alerta hasta aprobar reservas, registros y relevo | ¿Cuántas idas y vueltas hay entre tecnología y operación? |
| Tasa de rechazo del fixture | Envíos fallidos ÷ todos los envíos | ¿Se normalizan campos y depuración? |
| Aceptación al primer envío | Escalados sin preguntas ÷ todos los escalados | ¿El traspaso permite investigar? |
| Tiempo manual | Minutos por rol en transcribir, comprobar y recargar | ¿Qué trabajo queda de noche y por la mañana? |
Para expresarlo en dinero, multiplica minutos ahorrados por costes laborales aprobados, añade retrabajo evitado aprobado y resta diseño, revisión, simulacro y mantenimiento. Divide el beneficio neto por la inversión. Sin línea base, periodo y exclusiones, informa de tiempos y rechazos sin llamarlos ROI.
Preguntas frecuentes
Q. ¿Este validator conecta con Azure Monitor o AKS?
A. No. Solo lee JSON local y no prueba entrega, credenciales ni estado del clúster.
Q. ¿Por qué exige cuatro campos de essentials?
A. El enrutado nocturno necesita severidad, tipo de señal, estado y objetivos. No convierte todos los campos del esquema en obligatorios privados.
Q. ¿Un resultado correcto demuestra que no hay datos personales?
A. No. Rechaza claves explícitas, correos, teléfonos y nombres etiquetados. Imágenes y texto sin etiqueta exigen revisión humana.
Q. ¿Debe Claude Code ejecutar cambios en Azure?
A. No en este runbook. Azure/TI revisa permisos, impacto, rollback y aprobación, y usa el procedimiento existente.
Q. ¿Service Health vacío demuestra que AKS está sano?
A. No. Refleja criterios configurados y debe combinarse con evidencia de aplicación, carga, red y monitorización.
CTA de consultoría: incident runbook review
En la página de formación y consultoría de ClaudeCodeLab, solicita un “incident runbook review” para el flujo nocturno de reservas o registros. El entregable incluye comentarios sobre el runbook actual, contrato Common Alert Schema, tabla de decisiones de tres roles, procedimiento de prueba y riesgos pendientes. Lleva solo una alerta depurada, la tabla de contactos y una cronología reciente, sin credenciales ni datos personales.
Resultado de la prueba real
El 23 de julio de 2026 extrajimos validate-azure-alert-handoff.mjs y sanitized-alert.json a una carpeta temporal y ejecutamos los dos comandos mostrados. El fixture válido terminó con código 0. El autotest rechazó datos personales directos y la ausencia de severity, signalType, monitorCondition y alertTargetIDs: cinco casos de rechazo. Las comprobaciones del repositorio cubren frontmatter, enlaces internos, URL oficiales, bloques de código y el slug común de diez idiomas. No usamos credenciales Azure, de modo que el acceso AKS, Action Group y entrega real siguen sin probarse. El siguiente paso es depurar una alerta del centro y ejecutar estos dos comandos como primera revisión del runbook.
Artículos relacionados
Revisar despliegues de Azure Container Apps para sitios de empleo
Claude Code revisa URL pública, variables, formulario, secrets y revisions antes de publicar.
Cafetería: responde reseñas y anuncia el menú de temporada en la mitad del tiempo con IA
Para dueños de cafetería: redacta respuestas a reseñas y anuncios de temporada con IA, con prompts y script de verificación listos.
Fichas de consulta y emails de seguimiento para tu centro de estética con IA
Crea fichas de consulta y emails de seguimiento para tu centro de estética con Claude Code: prompts, checklist y datos personales.
PDF gratis: cheatsheet de Claude Code
Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.
Cuidamos tus datos y no enviamos spam.
Sobre el autor
Masa
Ingeniero enfocado en workflows prácticos con Claude Code.