Storage y Datos
Resumen Ejecutivo
Sección titulada «Resumen Ejecutivo»La estrategia de almacenamiento y datos de HERA se basa en un conjunto de servicios de GCP altamente escalables, duraderos y seguros. Utilizamos Cloud Storage para el almacenamiento de objetos, BigQuery como nuestro data warehouse, Memorystore para caché en memoria y Pub/Sub para la mensajería asíncrona, formando un ecosistema de datos robusto y versátil.
Cloud Storage (GCS): Almacenamiento Unificado
Sección titulada «Cloud Storage (GCS): Almacenamiento Unificado»Cloud Storage es nuestro servicio para almacenar “objetos” (archivos) no estructurados. Su versatilidad lo hace fundamental para múltiples casos de uso.
Clases de Almacenamiento y Políticas de Ciclo de Vida
Sección titulada «Clases de Almacenamiento y Políticas de Ciclo de Vida»No todo el almacenamiento es igual. Clasificamos nuestros datos y aplicamos políticas de ciclo de vida para moverlos automáticamente a clases de almacenamiento más económicas a medida que envejecen, optimizando así los costos.
| Clase | Costo almacén | Costo acceso | Uso típico en HERA | Política de ciclo de vida (ej: logs) |
|---|---|---|---|---|
| Standard | Alto | Bajo | Assets públicos (con CDN), uploads de usuarios, datos “calientes”. | 0-30 días |
| Nearline | Medio | Medio | Logs recientes, backups de corto plazo. | 30-90 días |
| Coldline | Bajo | Alto | Backups de DR, datos de acceso poco frecuente. | 90-365 días |
| Archive | Muy Bajo | Muy Alto | Archivado a largo plazo por cumplimiento normativo. | > 365 días |
Estructura de Buckets
Sección titulada «Estructura de Buckets»Tenemos una nomenclatura estandarizada para nuestros buckets que refleja su propósito y ambiente.
| Bucket | Clase por Defecto | Acceso | Propósito |
|---|---|---|---|
herdez-assets-prd | Standard | Público (a través de CDN) | Imágenes, CSS, JS de nuestros sitios web. |
herdez-uploads-prd | Standard | Privado | Archivos subidos por los usuarios. |
herdez-logs-prd | Standard | Privado | Logs de auditoría y de aplicaciones. |
herdez-backups-prd | Nearline | Privado | Backups de bases de datos y VMs. |
herdez-archive-prd | Archive | Privado | Datos retenidos por cumplimiento legal (ej. 7 años). |
BigQuery: Nuestro Data Warehouse Serverless
Sección titulada «BigQuery: Nuestro Data Warehouse Serverless»BigQuery es la pieza central de nuestra estrategia de datos analíticos. Es un data warehouse totalmente gestionado y serverless que nos permite ejecutar consultas SQL sobre terabytes de datos en segundos.
Flujo de Datos hacia BigQuery
Sección titulada «Flujo de Datos hacia BigQuery»- Ingesta: Los datos llegan a BigQuery desde múltiples fuentes, ya sea en tiempo real (streaming) desde Pub/Sub o en lotes (batch) desde Cloud Storage.
- Capa Cruda (
raw_data): Almacenamos los datos tal como llegan, sin transformar. - Capa Analítica (
analytics): Ejecutamos consultas SQL programadas para limpiar, transformar y agregar los datos crudos en tablas optimizadas para el análisis. - Consumo: Los datos limpios se utilizan para crear dashboards en Looker Studio, entrenar modelos de Machine Learning o alimentar APIs.
Memorystore (Redis): Caché de Alta Velocidad
Sección titulada «Memorystore (Redis): Caché de Alta Velocidad»Memorystore nos proporciona una instancia de Redis totalmente gestionada. Lo utilizamos para acelerar las respuestas de nuestras aplicaciones y reducir la carga sobre las bases de datos.
| Caso de Uso | Descripción | TTL Típico |
|---|---|---|
| Caché de Sesiones | Almacenar los datos de sesión de los usuarios autenticados. | 24 horas |
| Caché de Datos | Guardar resultados de consultas de base de datos frecuentes o costosas. | 1 hora |
| Rate Limiting | Implementar límites de velocidad para proteger nuestras APIs del abuso. | 1 minuto |
| Contadores | Contadores en tiempo real para métricas de negocio. | Variable |
Acceso desde workloads — IAM a nivel de bucket
Sección titulada «Acceso desde workloads — IAM a nivel de bucket»La seguridad en Cloud Storage ha evolucionado. En HERA, gestionamos el acceso a los datos utilizando IAM a nivel de bucket en combinación con Workload Identity, eliminando las ACLs (Access Control Lists) heredadas y previniendo la exposición accidental de datos.
Configuración Mandatoria de Seguridad
Sección titulada «Configuración Mandatoria de Seguridad»Todo bucket de Cloud Storage creado en HERA debe cumplir con las siguientes configuraciones de seguridad (enforced vía Terraform):
- Uniform Bucket-Level Access (UBLA): Habilitado. Desactiva las ACLs individuales de objetos y centraliza todo el control de acceso en las políticas IAM del bucket.
- Public Access Prevention (PAP): Enforced. Bloquea cualquier intento (accidental o malicioso) de hacer público el bucket o sus objetos. Únicamente los buckets designados explícitamente para assets públicos (ej. CDN) tienen excepciones.
- Cifrado CMEK (Customer-Managed Encryption Keys): Los buckets que almacenan datos clasificados como Confidencial o Restringido deben usar claves de Cloud KMS gestionadas por HERA, no las claves por defecto de Google.
- Object Versioning y Retention Policies: Para datos críticos (ej. auditoría, financieros), se habilita el versionado para proteger contra sobreescrituras y políticas de retención (WORM) para prevenir borrados antes de tiempo.
Resumen de parámetros obligatorios
Sección titulada «Resumen de parámetros obligatorios»| Parámetro | Valor estándar | Aplicación |
|---|---|---|
uniform_bucket_level_access | true | Todos los buckets — elimina ACLs legacy |
public_access_prevention | enforced | Todos los buckets salvo los explícitamente públicos (CDN) |
versioning | enabled | Buckets con datos críticos (auditoría, financieros, pedidos) |
| Cifrado CMEK (Cloud KMS) | Obligatorio | Datos clasificados como Confidencial o Restringido |
| Retention policy (WORM) | ≥ 30 días | Buckets de auditoría, evidencia de compliance, datos financieros |
| Naming | Prefijo ghdz- | Todos — ver Estándares de Nombramiento GCP |
Lifecycle por defecto (optimización de costos)
Sección titulada «Lifecycle por defecto (optimización de costos)»Los buckets no-críticos aplican transiciones automáticas de clase de storage para reducir costo sin intervención manual:
| Edad del objeto | Clase de destino | Costo relativo |
|---|---|---|
| 0 – 90 días | Standard | 1× |
| 90 – 365 días | Coldline | ~0.4× |
| > 365 días | Archive | ~0.1× |
Los buckets de audit/compliance pueden omitir estas transiciones si la retention policy exige acceso inmediato durante todo el periodo.
Roles Granulares vs Antipatrones
Sección titulada «Roles Granulares vs Antipatrones»El acceso de las aplicaciones a los buckets se otorga asignando roles de IAM al Google Service Account (GSA) de la aplicación, utilizando Workload Identity.
| Rol IAM | Uso Correcto | Antipatrón Bloqueado |
|---|---|---|
roles/storage.objectViewer | Servicios que solo necesitan leer archivos (ej. procesamiento de reportes). | Asignar a toda la GSA si solo necesita leer un bucket. |
roles/storage.objectCreator | Servicios que solo suben archivos pero no necesitan leerlos ni borrarlos (ej. ingesta de logs). | — |
roles/storage.objectUser | Servicios que necesitan leer y escribir (ej. procesamiento de imágenes). | Asignar roles/storage.admin. Las aplicaciones nunca deben poder borrar el bucket ni cambiar sus políticas IAM. |
Patrón de Signed URLs
Sección titulada «Patrón de Signed URLs»Cuando una aplicación necesita que un usuario externo (un cliente web, un partner) suba o descargue un archivo directamente a Cloud Storage sin pasar por el backend (para ahorrar ancho de banda), utilizamos Signed URLs.
Una Signed URL otorga acceso temporal (ej. 15 minutos) para realizar una acción específica sobre un objeto específico.
Para que un microservicio en GKE pueda generar una Signed URL, su GSA necesita el permiso para firmar tokens en nombre propio:
# Otorgar permiso al GSA para firmar URLs (impersonación de sí mismo)gcloud iam service-accounts add-iam-policy-binding \ mi-app-gsa@mi-proyecto.iam.gserviceaccount.com \ --role=roles/iam.serviceAccountTokenCreator \ --member="serviceAccount:mi-app-gsa@mi-proyecto.iam.gserviceaccount.com"Ejemplo de generación en Node.js:
const { Storage } = require('@google-cloud/storage');
// ADC resuelve la identidad automáticamente gracias a Workload Identity// # simplificado para ilustración - En producción, instanciar globalmente y manejar erroresconst storage = new Storage();
async function generateV4UploadSignedUrl(bucketName, fileName) { try { const options = { version: 'v4', action: 'write', expires: Date.now() + 15 * 60 * 1000, // 15 minutos contentType: 'application/octet-stream', };
const [url] = await storage .bucket(bucketName) .file(fileName) .getSignedUrl(options);
return url; } catch (error) { console.error('Error al generar Signed URL:', error); throw error; }}Ejemplo de generación en Python:
from google.cloud import storagefrom datetime import timedelta
# ADC resuelve la identidad automáticamente gracias a Workload Identityclient = storage.Client()
def generate_upload_signed_url(bucket_name: str, blob_name: str) -> str: bucket = client.bucket(bucket_name) blob = bucket.blob(blob_name)
url = blob.generate_signed_url( version="v4", expiration=timedelta(minutes=15), method="PUT", content_type="application/octet-stream", ) return urlChecklist de Seguridad por Bucket
Sección titulada «Checklist de Seguridad por Bucket»Antes de aprovisionar un nuevo bucket, valida:
- UBLA está habilitado (
uniform_bucket_level_access = true). - Public Access Prevention está
enforced(a menos que sea asset público explícito). - La clase de almacenamiento por defecto coincide con el patrón de uso.
- Lifecycle policy configurada para transicionar datos antiguos a Coldline/Archive.
- CMEK configurado si el bucket almacena datos clasificados como Confidencial o Restringido.
- Roles IAM asignados son
objectViewer,objectCreatoroobjectUser— nuncastorage.admin. - Los accesos son a través de Workload Identity (GSA), no cuentas de usuario directas.
- Si el bucket usa Signed URLs, la GSA tiene
roles/iam.serviceAccountTokenCreatorsobre sí misma.
Pub/Sub: El Sistema Nervioso Asíncrono
Sección titulada «Pub/Sub: El Sistema Nervioso Asíncrono»Pub/Sub es un servicio de mensajería global que nos permite desacoplar nuestros servicios y construir arquitecturas robustas y escalables basadas en eventos.
Arquitectura Event-Driven
Sección titulada «Arquitectura Event-Driven»En lugar de que los servicios se llamen directamente entre sí (acoplamiento fuerte), un servicio publica un evento (un mensaje) en un topic. Otros servicios, sin que el publicador lo sepa, se suscriben a ese topic y reaccionan al evento.
Ejemplo: Creación de un Pedido
- El servicio de eCommerce recibe un nuevo pedido.
- Publica un mensaje en el topic
pedidos-creadoscon los detalles del pedido. - Tres servicios diferentes reaccionan a este único evento:
- El servicio de Inventario se suscribe, recibe el mensaje y descuenta el stock.
- El servicio de Notificaciones se suscribe y envía un email de confirmación al cliente.
- El pipeline de Analytics se suscribe y envía el evento a BigQuery.