Saltar al contenido
Kevo Rojas

Emulador de Azure local: cómo usar Floci con Terraform (lo que funciona y lo que no)

KR
Kevo Rojas
6 oct 2026 · 23 min de lectura
Video del tutorial

Floci emula Azure en tu computadora. Lo uso con Terraform: un PostgreSQL real, una VM que no existe y AKS con k3s. Sin cuenta de Azure ni tarjeta.

En resumen: Floci es un emulador de Azure local: corre en Docker y responde como si fuera Azure, así que Terraform y la CLI le hablan a tu computadora en vez de a la nube. Sirve para practicar sin cuenta, sin tarjeta y sin miedo a dejar algo prendido. En esta guía lo levanto con Docker Compose, configuro el provider azurerm y pruebo tres ejemplos copiados de la documentación oficial de Terraform: un PostgreSQL Flexible Server (es un Postgres de verdad), una máquina virtual (dice running, pero no corre nada) y un AKS (por debajo es un k3s). También están los errores que aparecieron y cómo los resolví.

Este artículo acompaña al video de arriba. Si prefieres leer, aquí está todo paso a paso, con los bloques de código listos para copiar. El código completo está en el repositorio: https://github.com/kevorojas/floci-azure-terraform.

Versiones probadas: floci-az 0.13.0, provider azurerm 5.8.0 y Terraform 1.14.3, en macOS con Docker. Floci cambia rápido: si usas otra versión, algunos detalles pueden ser distintos.

¿Qué es Floci y para qué sirve?

Floci es un emulador de nubes que corre en tu computadora. Emula las APIs de AWS, Azure, Google Cloud y Oracle Cloud, cada una en su propio puerto. Tu Terraform, tu CLI o tu SDK creen que le hablan a la nube, pero en realidad le hablan a un contenedor en tu máquina.

NubePuerto por defecto
AWS4566
Azure4577
Google Cloud4588
Oracle Cloud (OCI)4599

Nació como alternativa libre a LocalStack. En esta guía me centro en Azure, que en español casi no tiene material.

¿Para qué sirve? Para aprender y practicar Azure sin una cuenta. Mucha gente no puede poner una tarjeta para abrir una suscripción, y quien sí puede tiene el miedo de siempre: olvidarse algo corriendo y recibir la factura. Con Floci puedes crear, romper y destruir recursos con Terraform todas las veces que quieras, y nada sale de tu computadora.

Lo que no es: no es Azure en tu casa. Algunos servicios son reales (una base de datos PostgreSQL funciona de verdad) y otros solo existen en el "plano de control": la API responde que se crearon, pero no hay nada detrás. Más abajo está el detalle de cada uno.

Qué necesitas antes de empezar

  • Docker (en Mac, Docker Desktop) con Docker Compose.
  • Terraform 1.6 o superior. Yo usé 1.14.3.
  • El provider azurerm 5.x. Terraform lo descarga solo con terraform init.
  • Ninguna cuenta de Azure. Ni az login, ni suscripción, ni tarjeta.
  • Opcional: pgAdmin o psql para el ejemplo de PostgreSQL, y kubectl y jq para el de AKS.
  • Opcional: git, si vas a construir la imagen que necesita AKS (lo explico en su sección).

Sistema operativo: todo lo probé en macOS. El paso del certificado TLS es específico de Mac. En Linux y Windows no lo probé.

Levantar el emulador de Azure local con Docker Compose

Este es el docker-compose.yml mínimo para tener Azure en tu computadora:

name: floci-azure

services:
  floci-az:
    image: floci/floci-az:0.13.0
    ports:
      - "127.0.0.1:4577:4577"
    volumes:
      # PostgreSQL, AKS (k3s) y las VMs no simuladas son contenedores que Floci crea en tu Docker
      - /var/run/docker.sock:/var/run/docker.sock
      # Guarda el certificado TLS para no tener que volver a confiarlo en cada arranque
      - ./data:/app/data
    environment:
      # El provider de Azure descubre la nube por HTTPS: sin TLS no arranca
      FLOCI_AZ_TLS_ENABLED: "true"
      # Todo en memoria: si el contenedor se reinicia, se pierde todo
      FLOCI_AZ_STORAGE_MODE: memory
      # "true": las VMs son solo plano de control (dicen running, pero no corre nada)
      FLOCI_AZ_SERVICES_VM_MOCKED: "true"

Lo levantas con un comando:

docker compose up -d
docker compose ps

Arranca en un par de segundos.

En el repo (https://github.com/kevorojas/floci-azure-terraform) el compose también levanta los emuladores de AWS, Google Cloud y Oracle, y la interfaz web de Floci, que permite ver los recursos como si fuera una consola. En Settings > Cloud eliges la nube y cada una tiene su consola, con los servicios disponibles y los que todavía no están. No es el portal de Azure, pero sirve para ver qué creaste.

La interfaz web de Floci con el selector de nube.

Dos detalles de seguridad del compose:

  • Los puertos quedan atados a 127.0.0.1. Los emuladores no tienen autenticación, así que no conviene exponerlos a tu red.
  • Floci monta el socket de Docker (/var/run/docker.sock) porque crea contenedores para PostgreSQL y AKS. Eso le da control total sobre tu Docker: úsalo solo en tu máquina de pruebas.

Comprobar que responde

Floci publica los "endpoints" de su nube, igual que Azure. Si responde con direcciones en localhost, está todo bien:

/usr/bin/curl -s "https://localhost:4577/metadata/endpoints?api-version=2022-09-01"

Si este comando falla por el certificado, es normal: lo resolvemos en la sección siguiente. En Mac uso /usr/bin/curl (el del sistema) a propósito: un curl instalado por otro gestor de paquetes puede no leer el llavero de macOS.

Confiar en el certificado TLS de Floci (macOS)

Floci sirve su API por HTTPS con un certificado propio. Terraform no confía en él, así que terraform init funciona, pero el primer terraform plan falla con algo así:

Error: retrieving metadata from endpoint "https://localhost:4577": ...
tls: failed to verify certificate: x509: certificate signed by unknown authority

El error x509 en la terminal.

Agregar el certificado al llavero del sistema

Al arrancar, Floci genera su autoridad certificadora (CA) en ./data/tls/. En macOS hay que agregarla al llavero del sistema:

sudo security add-trusted-cert -d -r trustRoot \
  -k /Library/Keychains/System.keychain ./data/tls/floci-az-selfsigned-ca.crt

Después de eso, terraform plan funciona.

SSL_CERT_FILE no sirve en macOS. La documentación de Floci sugiere esa variable de entorno, pero en Mac Terraform usa el verificador de certificados del sistema y la ignora. Lo probé y el error sigue igual. Lo único que funcionó fue el llavero.

Como el compose monta ./data, el certificado se conserva entre reinicios y no hay que volver a confiarlo. Si borras esa carpeta, Floci genera una CA nueva y hay que repetir el paso.

Quitar el certificado cuando termines

Agregar una CA al llavero del sistema hace que tu Mac confíe en todo lo que esa CA firme. Cuando dejes de usar Floci, quítala. Primero se quita la confianza y después el certificado (la CA de Floci se llama floci-az-ca):

sudo security remove-trusted-cert -d ./data/tls/floci-az-selfsigned-ca.crt
sudo security delete-certificate -c floci-az-ca /Library/Keychains/System.keychain

También puedes hacerlo desde la app Acceso a Llaveros: llavero Sistema, buscar floci-az-ca y eliminarlo. Si confiaste más de una CA de Floci (por ejemplo, porque borraste ./data), delete-certificate -c se queja de que hay más de una; en ese caso es más simple borrarlas desde la app.

Terraform contra Floci: lo único que cambia es el provider

Esta es la idea central: tus recursos de Terraform son los mismos que usarías en Azure real. Lo que cambia es la configuración del provider azurerm.

Primero, el bloque terraform (igual que siempre):

terraform {
  required_version = ">= 1.6"
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 5.0"
    }
  }
}

Así se ve un provider normal, contra Azure real:

provider "azurerm" {
  features {}

  subscription_id = "<tu-subscription-id>"
  # La autenticación sale de tu sesión de `az login`
  # (o de un service principal u OIDC en un pipeline)
}

Y así se ve apuntando a Floci:

provider "azurerm" {
  features {}

  # 1. Las direcciones de la nube se las pide a Floci, en localhost
  metadata_host = "localhost:4577"

  # 2. No usa tu sesión de `az login`
  use_cli = false

  # 3. No intenta registrar resource providers
  resource_provider_registrations = "none"

  # 4. Credenciales falsas: Floci no las valida y Azure real las rechazaría
  subscription_id = "00000000-0000-0000-0000-000000000001"
  tenant_id       = "00000000-0000-0000-0000-000000000002"
  client_id       = "00000000-0000-0000-0000-000000000003"
  client_secret   = "fake-secret"
}

El provider de Azure real y el de Floci, lado a lado.

Las cuatro diferencias, una por una

  1. metadata_host. El provider de Azure arranca pidiendo la lista de direcciones de la nube (dónde está Resource Manager, dónde está el login, dónde está el storage). Con metadata_host se la pide a Floci en localhost:4577 en lugar de a la nube pública. La documentación de Floci también agrega environment = "stack", pero el provider lo ignora cuando hay metadata_host, así que lo dejé afuera.
  2. use_cli = false. Si no le das credenciales, el provider usa por defecto las de tu Azure CLI. Lo apago para que no haya forma de que use tu sesión real, aunque tengas un az login abierto.
  3. resource_provider_registrations = "none". Evita que el provider intente registrar resource providers en la suscripción. En azurerm 5.x ya es el valor por defecto, así que puedes omitirlo; en 4.x hay que ponerlo.
  4. Credenciales falsas. Floci no valida credenciales. Y si por un error Terraform terminara hablando con Azure real, estas credenciales fallarían. Es una segunda red de seguridad.

Ojo con la documentación de Floci. Hoy trae skip_provider_registration = true. Ese argumento ya no existe en azurerm 4 y 5, y si lo copias tal cual, Terraform responde An argument named "skip_provider_registration" is not expected here. Si usas azurerm 3.x, ese sí es el argumento correcto.

Una regla más: no tengas exportadas variables ARM_* de una suscripción real en la terminal donde trabajas con Floci.

Cinturón extra (opcional). Si en lugar de escribir el host a mano usas una variable, puedes impedir que apunte a otra cosa que no sea tu computadora:

variable "floci_host" {
  description = "host:puerto de floci-az"
  type        = string
  default     = "localhost:4577"

  validation {
    condition     = can(regex("^(localhost|127\\.0\\.0\\.1):[0-9]+$", var.floci_host))
    error_message = "Solo se permite apuntar al emulador local (localhost:PUERTO)."
  }
}

Y en el provider: metadata_host = var.floci_host.

Ejemplo 1: PostgreSQL Flexible Server, una base de datos real

El primer ejemplo sale de la documentación oficial del recurso azurerm_postgresql_flexible_server en el registry de Terraform. La doc arma un servidor privado con VNet, subnet delegada y DNS privado; lo simplifiqué a un servidor con acceso público, y saqué el bloque provider que trae el ejemplo porque ya está en providers.tf (si lo dejas, Terraform falla con Duplicate provider configuration).

Carpeta 01-postgresql/main.tf:

resource "azurerm_resource_group" "rg" {
  name     = "rg-floci-demo"
  location = "West Europe"
}

resource "azurerm_postgresql_flexible_server" "psql" {
  name                          = "example-psqlflexibleserver"
  resource_group_name           = azurerm_resource_group.rg.name
  location                      = azurerm_resource_group.rg.location
  version                       = "12"
  public_network_access_enabled = true
  administrator_login           = "psqladmin"
  administrator_password        = "H@Sh1CoR3!"
  zone                          = "1"

  storage_mb   = 32768
  storage_tier = "P4"

  sku_name   = "B_Standard_B1ms"
  depends_on = [azurerm_resource_group.rg]
}

Sobre la contraseña: es la del ejemplo de la documentación y aquí no importa, porque todo queda en tu computadora. En un proyecto real va en una variable sensible o en un Key Vault, nunca escrita en el código.

cd 01-postgresql
terraform init
terraform plan     # 2 recursos: el resource group y el servidor
terraform apply

El apply no es instantáneo: espera uno o dos minutos. Cuando termina, la interfaz de Floci muestra el servidor y su JSON, con la misma forma que tendría en Azure.

El servidor PostgreSQL en la interfaz de Floci, con su JSON.

Es un PostgreSQL de verdad

Aquí está lo interesante: no es una simulación. Floci levanta un contenedor de PostgreSQL en tu Docker:

docker ps --filter name=floci-az-pg-

El contenedor se llama floci-az-pg- más el nombre del servidor. Docker le asigna un puerto al azar en tu máquina; para saber cuál es:

docker port floci-az-pg-example-psqlflexibleserver 5432

Floci también informa un host de conexión, pero es el nombre interno del contenedor en Docker y no sirve desde tu computadora. Usa localhost y el puerto que te da docker port.

Conectarte con pgAdmin

En pgAdmin, registra un servidor nuevo con estos datos:

CampoValor
Hostlocalhost
Puertoel que devolvió docker port
Base de mantenimientopostgres
Usuariopsqladmin
ContraseñaH@Sh1CoR3!

Se conecta, y puedes crear tablas, insertar filas y consultar como en cualquier PostgreSQL. Si creas una tabla desde pgAdmin y refrescas la interfaz de Floci, aparece ahí también: es la misma base.

Con psql es lo mismo:

psql "host=127.0.0.1 port=<PUERTO> dbname=postgres user=psqladmin password=H@Sh1CoR3! sslmode=disable"

pgAdmin conectado al PostgreSQL que creó Terraform.

Un detalle curioso: en Terraform pedí la versión 12, y Terraform y la API dicen "12". Pero si le preguntas a la base con SELECT version();, en mi prueba respondió PostgreSQL 17.11. Floci usa la imagen postgres:17-alpine sin importar la versión que pidas.

Como es un Postgres real, puedes ir más lejos: sumar el provider de PostgreSQL de Terraform y crear bases, roles o esquemas con infraestructura como código, todo sin gastar nada.

Ejemplo 2: una máquina virtual que dice running y no existe

El segundo ejemplo es una VM Linux, también de la documentación oficial (azurerm_linux_virtual_machine). No creo otro resource group: uso el del ejemplo 1 con un bloque data. Por eso esta carpeta se aplica después de 01-postgresql.

Carpeta 02-vm/main.tf:

data "azurerm_resource_group" "rg" {
  name = "rg-floci-demo"
}

resource "azurerm_virtual_network" "example" {
  name                = "example-network"
  address_space       = ["10.0.0.0/16"]
  location            = data.azurerm_resource_group.rg.location
  resource_group_name = data.azurerm_resource_group.rg.name
}

resource "azurerm_subnet" "example" {
  name                 = "internal"
  resource_group_name  = data.azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.example.name
  address_prefixes     = ["10.0.2.0/24"]
}

resource "azurerm_network_interface" "example" {
  name                = "example-nic"
  location            = data.azurerm_resource_group.rg.location
  resource_group_name = data.azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.example.id
    private_ip_address_allocation = "Dynamic"
  }
}

resource "azurerm_linux_virtual_machine" "example" {
  name                = "example-machine"
  resource_group_name = data.azurerm_resource_group.rg.name
  location            = data.azurerm_resource_group.rg.location
  size                = "Standard_D4_v5"
  admin_username      = "adminuser"
  network_interface_ids = [
    azurerm_network_interface.example.id,
  ]

  admin_ssh_key {
    username   = "adminuser"
    public_key = file("${path.module}/demo_id_rsa.pub")
  }

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "0001-com-ubuntu-server-jammy"
    sku       = "22_04-lts"
    version   = "latest"
  }
}

La documentación usa file("~/.ssh/id_rsa.pub"), tu llave personal. Para practicar prefiero una llave descartable dentro de la carpeta, que no se mezcla con las tuyas:

cd ../02-vm
ssh-keygen -t rsa -b 4096 -f ./demo_id_rsa -N ""
terraform init
terraform apply    # 4 recursos: red, subnet, interfaz de red y VM

El apply termina bien y la interfaz de Floci muestra la VM en running. Pero si miras tus contenedores:

docker ps

Están los mismos que antes. No se creó ninguna máquina. Con la configuración por defecto, la VM es solo plano de control: la API dice que existe y que está encendida, y no hay nada detrás.

La VM en running en la interfaz de Floci, y docker ps sin ningún contenedor nuevo.

La red tampoco hace nada. La subnet es 10.0.2.0/24, pero en mi prueba la interfaz de red de la VM recibió la IP 10.0.0.4: ni siquiera está dentro de su propia subnet. VNets, subnets y grupos de seguridad existen para Terraform, pero no aíslan nada.

Si quieres que la VM sea algo: con FLOCI_AZ_SERVICES_VM_MOCKED: "false" en el compose, cada VM pasa a ser un contenedor ubuntu:22.04. Sigue sin ser una VM: no tiene kernel propio, no está tu usuario, no está la llave SSH y no hay sshd. Encender y apagar la VM sí arranca y detiene el contenedor.

¿Sirve entonces? Sí, para lo que es: practicar la sintaxis de Terraform, las dependencias entre recursos y el ciclo plan, apply y destroy. No sirve para probar qué pasa dentro de la máquina.

Ejemplo 3: AKS, que en realidad es un k3s

El tercer ejemplo es un cluster de Kubernetes con azurerm_kubernetes_cluster, también copiado de la documentación. Floci no crea un AKS, claro: levanta un contenedor de k3s (una distribución liviana de Kubernetes) y lo presenta como si fuera AKS. Es un Kubernetes real: kubectl get nodes responde y puedes desplegar pods.

Primero, la imagen correcta (bug #264)

Con la imagen oficial floci/floci-az:0.13.0, el apply de AKS nunca termina: el contenedor de k3s arranca y funciona, pero Floci no se da cuenta y el cluster queda en Creating para siempre. Es el bug floci-az#264, abierto cuando escribo esto. La causa es que la imagen nativa no tiene habilitado HTTPS en una librería de Java que usa para chequear que k3s esté listo.

Lo que funcionó: construir la imagen JVM desde el código de la versión 0.13.0. Tarda unos 6 minutos:

git clone --depth 1 --branch 0.13.0 https://github.com/floci-io/floci-az.git /tmp/floci-az
docker build -t floci-az-jvm-local:0.13.0 -f /tmp/floci-az/docker/Dockerfile /tmp/floci-az

Y en el compose, cambia la imagen:

    image: floci-az-jvm-local:0.13.0

Hazlo antes de empezar. Cambiar la imagen recrea el contenedor de Floci, y como el estado vive en memoria, pierdes todo lo que tenías creado. Si vas a probar AKS, arranca con la imagen JVM desde el principio; los otros ejemplos funcionan igual con ella.

El código

Carpeta 03-aks/main.tf:

data "azurerm_resource_group" "rg" {
  name = "rg-floci-demo"
}

resource "azurerm_kubernetes_cluster" "example" {
  name                = "example-aks1"
  location            = data.azurerm_resource_group.rg.location
  resource_group_name = data.azurerm_resource_group.rg.name
  dns_prefix          = "exampleaks1"

  node_provisioning_profile {
    mode = "Manual"
  }

  default_node_pool {
    name       = "default"
    node_count = 1
    vm_size    = "Standard_D2_v2"
  }

  identity {
    type = "SystemAssigned"
  }

  tags = {
    Environment = "Production"
  }
}

output "cluster_id" {
  value = azurerm_kubernetes_cluster.example.id
}

Dos diferencias con la documentación:

  • node_provisioning_profile. El ejemplo de la doc de azurerm 5.8.0 no valida contra el propio provider: falla con Insufficient node_provisioning_profile blocks. No es culpa de Floci; con Azure real pasaría lo mismo. Se arregla agregando el bloque con mode = "Manual".
  • Sin los outputs de kube_config. La doc trae outputs con kube_config[0].client_certificate y kube_config_raw. Con Floci 0.13.0 fallan con Invalid index, porque Floci devuelve el kubeconfig con un nombre distinto del que busca el provider, y kube_config queda vacío. Los reemplacé por el ID del cluster, que sirve para pedir el kubeconfig a mano.
cd ../03-aks
terraform init
terraform apply

La primera vez, Docker descarga la imagen rancher/k3s (en mi prueba, casi 2 minutos). Con la imagen ya descargada, el apply tardó unos 30 segundos.

El contenedor de k3s que Floci levantó para el AKS.

Obtener el kubeconfig y usar kubectl

Como el provider no recibe el kubeconfig, se lo pido a Floci por su API y cambio la dirección del servidor a 127.0.0.1:

ID=$(terraform output -raw cluster_id)

/usr/bin/curl -s -X POST "https://localhost:4577${ID}/listClusterAdminCredential?api-version=2025-07-01" \
  | jq -r '.kubeconfigs[0].value' | base64 -d \
  | sed -E 's#server: https://[^:]+:([0-9]+)#server: https://127.0.0.1:\1#' > kubeconfig-floci

kubectl --kubeconfig kubeconfig-floci get nodes
kubectl --kubeconfig kubeconfig-floci create deployment hola --image=nginx:alpine
kubectl --kubeconfig kubeconfig-floci get pods

En mi prueba, get nodes mostró un nodo Ready con k3s v1.34.1, y el deployment de nginx quedó en Running. Con esto puedes practicar un flujo completo: crear el cluster con Terraform y después desplegar cosas encima con el provider de Kubernetes.

Errores reales y cómo los resolví

Ninguno de los ejemplos funcionó copiado tal cual. Estos son los errores que aparecieron, en orden:

ErrorCausaSolución
An argument named "skip_provider_registration" is not expected hereEl provider de la doc de Floci está escrito para azurerm 3.xresource_provider_registrations = "none" (en 5.x ya es el default)
x509: certificate signed by unknown authorityTerraform no confía en el certificado de FlociAgregar la CA al llavero del sistema. En macOS SSL_CERT_FILE no sirve
Duplicate provider configurationEl ejemplo de PostgreSQL de la doc trae su propio bloque providerBorrarlo: ya está en providers.tf
Can't configure a value for "location": its value will be decided automatically...Copié el resource group como data y le dejé el argumento location. En un data source, location es un dato que se lee, no se declaraDejar en el bloque data solo name
Unsupported attribute en una referencia a locationAl pasar el resource group a data, quedó una referencia mal escritaTodas las referencias pasan a data.azurerm_resource_group.rg.<atributo>
Insufficient node_provisioning_profile blocksEl ejemplo de AKS de la doc 5.8.0 no valida contra su propio providerAgregar node_provisioning_profile { mode = "Manual" }
AKS en Still creating... para siempreBug #264 de la imagen nativa de FlociImagen JVM construida desde el tag 0.13.0
Invalid index en kube_config[0]Floci devuelve el kubeconfig con otro nombre y el provider lo deja vacíoQuitar esos outputs y pedir el kubeconfig por la API

Planes que nunca quedan limpios

Hay otro detalle que no es un error, pero molesta: después del apply, el siguiente terraform plan no siempre dice "No changes". Floci no guarda algunos campos, y Terraform quiere volver a ponerlos:

  • PostgreSQL: zone = "1" vuelve a aparecer en cada plan.
  • VM: additional_capabilities queda con "1 to change".
  • AKS: el tipo del node pool, identity y otros campos. Este es el más serio: el plan quiere destruir y recrear el cluster.

Para practicar, se resuelve con lifecycle { ignore_changes = [...] }. Por ejemplo, en el servidor de PostgreSQL:

  lifecycle {
    ignore_changes = [zone]
  }

Y en el AKS:

  lifecycle {
    ignore_changes = [
      default_node_pool[0].type,
      identity,
      node_provisioning_profile,
      oidc_issuer_enabled,
      support_plan,
      node_os_upgrade_channel,
    ]
  }

Ojo: esos ignore_changes existen solo por el emulador. Si después llevas el mismo código a Azure real, sácalos.

Qué funciona y qué no en Floci para Azure

Esto es lo que probé con floci-az 0.13.0. Floci emula muchos más servicios, pero aquí solo afirmo lo que vi funcionar.

Servicio¿Qué es por debajo?Veredicto
Resource groupsPlano de controlFunciona
PostgreSQL Flexible ServerUn contenedor PostgreSQL real (17.11)Real: conectas, creas tablas, consultas
Máquina virtual LinuxNada (o un contenedor Ubuntu si desactivas la simulación)Dice running, pero no corre nada
VNet, subnet, interfaz de redPlano de controlExisten para Terraform, no aíslan nada
AKSUn contenedor k3s realReal, con la imagen JVM (bug #264)
Storage (blob)Un blob storage realSubir, listar y bajar archivos funciona, pero crear contenedores y blobs con Terraform falla hoy (ver abajo)

Sobre Storage, porque tiene una trampa: Floci informa los endpoints de storage con el dominio real de Azure (<cuenta>.blob.core.windows.net). Y el nombre de cuenta del ejemplo oficial de azurerm_storage_blob existe en Azure real: al crear la cuenta, azurerm 4.x consulta esos endpoints (lo vi en mi prueba; con 5.8.0 no lo observé), así que copiar ese ejemplo sin cambiar el nombre puede terminar mandando peticiones a la cuenta de otra persona. Si pruebas storage, usa un nombre de cuenta propio y raro. Además, con azurerm 5.x, azurerm_storage_container falla siempre contra Floci, y azurerm_storage_blob sube el archivo y después falla con un 501 Not Implemented. En mi prueba, el contenedor y el blob los creé con la Azure CLI apuntando a Floci. Por eso storage no entró en el video.

¿Cuándo conviene usar Floci y cuándo no?

Conviene para:

  • Aprender Azure y Terraform sin cuenta, sin tarjeta y sin miedo a una factura.
  • Iterar módulos de Terraform: probar la sintaxis, las dependencias y el ciclo plan/apply/destroy muchas veces y rápido.
  • Pruebas con bases de datos reales: el PostgreSQL es de verdad, así que puedes probar scripts, migraciones o el provider de PostgreSQL.
  • Practicar Kubernetes sobre algo que se crea como un AKS.

No conviene para:

  • Permisos. No hay RBAC real: Floci acepta cualquier credencial.
  • Red privada y aislamiento. Las VNets, subnets y reglas de red no hacen nada.
  • Máquinas virtuales. No hay VM detrás.
  • Pruebas de seguridad de cualquier tipo.
  • Validar que tu código funciona en Azure. Los ignore_changes y los ajustes de esta guía son solo para el emulador. Lo que vayas a llevar a producción, pruébalo en Azure real.

Ojalá hubiera tenido algo así cuando estaba aprendiendo.

Todo vive en memoria

Con FLOCI_AZ_STORAGE_MODE: memory, el estado de Floci vive en la memoria del contenedor. Si el contenedor se reinicia, se pierde todo lo que creaste. Tu terraform.tfstate, en cambio, sigue diciendo que los recursos existen; un terraform apply los vuelve a crear.

Floci tiene modos de persistencia. Probé el modo hybrid y para practicar fue peor: después de un reinicio se perdieron los resource groups y las redes, pero quedó el servidor PostgreSQL a medias, en Creating y sin contenedor. Para practicar, me quedo con memoria.

Limpieza: dejar tu computadora como estaba

Destruye en orden inverso, porque 02-vm y 03-aks dependen del resource group de 01-postgresql:

cd 03-aks && terraform destroy
cd ../02-vm && terraform destroy
cd ../01-postgresql && terraform destroy
cd .. && docker compose down

Floci crea contenedores fuera del compose (el de PostgreSQL, el de k3s y, si desactivaste la simulación, los de las VMs). Al apagar Floci, el de PostgreSQL se borra, pero los de k3s y las VMs pueden quedar huérfanos (el de k3s, incluso corriendo). Todos llevan la etiqueta floci_emulator=floci-az:

docker ps -a --filter label=floci_emulator=floci-az
docker rm -f $(docker ps -aq --filter label=floci_emulator=floci-az)

Si tienes otro Floci corriendo en la misma máquina, ese filtro también encuentra sus contenedores. Revisa la lista antes de borrar.

Mientras están vivos, los contenedores de PostgreSQL y de k3s publican sus puertos en todas las interfaces de red (0.0.0.0), no solo en 127.0.0.1. Con la contraseña del ejemplo, cualquiera en tu misma red podría conectarse a ese Postgres. No los dejes prendidos en una red pública, y bórralos al terminar.

Por último, si no vas a volver a usar Floci, quita el certificado del llavero (los comandos están en la sección del certificado) y, si quieres liberar espacio, borra las imágenes floci-az-jvm-local:0.13.0, rancher/k3s y postgres:17-alpine.

Preguntas frecuentes

¿Necesito una cuenta de Azure para usar Floci? No. El provider usa credenciales falsas y use_cli = false, y Floci no valida credenciales. No hace falta suscripción, az login ni tarjeta.

¿Floci funciona con Terraform y el provider azurerm 5? Sí. Lo probé con azurerm 5.8.0 y Terraform 1.14.3. Hay que usar metadata_host, y en lugar de skip_provider_registration (que ya no existe en 4 y 5) va resource_provider_registrations = "none".

¿Los recursos que crea Floci son reales? Depende del servicio. PostgreSQL y AKS levantan contenedores reales (Postgres y k3s). Las VMs y las redes son solo plano de control: la API dice que existen, pero no hay nada detrás.

¿Funciona en Windows o Linux? Floci corre en Docker, pero yo solo lo probé en macOS. El paso del certificado TLS es distinto en cada sistema operativo y no lo verifiqué fuera de Mac.

¿Se guarda lo que creo si reinicio Floci? No, con la configuración de esta guía todo vive en memoria. Un terraform apply lo vuelve a crear.

Próximos pasos

Con esto ya tienes un Azure de práctica en tu computadora. La idea que quiero seguir explorando es usar el emulador como primer paso: escribir y probar el Terraform localmente todo lo que se pueda, y después llevar esa misma configuración a Azure real.

Ese es el plan para la serie de Terraform que estoy armando: una arquitectura privada en Azure Container Apps, construida capa por capa con Terraform.

El código de esta guía está en https://github.com/kevorojas/floci-azure-terraform. Y si hay un servicio de Azure que quieras ver probado en Floci, déjalo en los comentarios del video.

Recibe los tutoriales nuevos por correo

Te aviso cuando publico un tutorial o un video. Sin spam; puedes cancelar cuando quieras.