- Дата публикации
Как запустить автономного ИИ-агента OpenClaw на AKS и не сжечь прод: микровиртуалки Kata против побегов из контейнеров
Что нового
Microsoft показала готовый рецепт, как «закалить» автономного ИИ-агента OpenClaw на Azure Kubernetes Service (AKS), чтобы один зловредный скилл не превратил кластер в решето.
Ключевые новшества по сравнению с обычным запуском OpenClaw в контейнере:
- Изоляция через microVM, а не только через namespaces cgroups:
- каждый pod с OpenClaw работает внутри отдельной микровиртуалки Kata Containers;
- граница безопасности — гипервизор (KVM / MSHV), а не только ядро Linux на ноде.
- Специальный node pool в AKS под Kata:
- создаётся пул с
--workload-runtime KataMshvVmIsolation; - в нём включён runtimeClass
kata-vm-isolation; - используются VM‑типы с поддержкой nested virtualization (D‑series v3/v5, E‑series v3/v5 и др.).
- создаётся пул с
- Полноценная прод-конфигурация для OpenClaw:
- два реплики gateway с rolling update;
- постоянное хранилище на Azure Files NFS (PV + PVC,
ReadWriteMany); - ConfigMap с конфигом
openclaw.jsonи CORS; - Secret с токеном авторизации, прокинутым в контейнер как
AUTH_TOKEN; - TLS‑терминация на Application Gateway for Containers через Gateway API (
Gateway+HTTPRoute).
- Проверка реальной изоляции:
- демонстрация, что внутри pod нельзя «дотянуться» до корня файловой системы хоста через
/proc/1/root; - в обычном контейнере это даёт доступ к
/etc/kubernetesи другим чувствительным данным, в microVM — нет.
- демонстрация, что внутри pod нельзя «дотянуться» до корня файловой системы хоста через
Это не новый продукт, а именно практическая схема: как безопасно запускать OpenClaw, который по своей природе требует «God Mode» доступ к файловой системе и API, но при этом не должен становиться точкой входа в вашу внутреннюю сеть.
Как это работает
Проблема: OpenClaw как «God Mode» агент
OpenClaw — это open‑source автономный ИИ‑агент для продвинутых пользователей и разработчиков. Он умеет через чат‑клиенты вроде WhatsApp или Telegram:
- читать и разбирать почту;
- работать с файлами;
- планировать задачи и встречи;
- выполнять произвольные «Skills» (плагины, задания, код).
Чтобы всё это работало, OpenClaw часто запускают:
- с широкими правами к файловой системе пользователя;
- с доступом к внутренним API и секретам;
- нативно на машине, без жёсткого sandbox.
Отсюда парадокс: агент полезен только тогда, когда у него почти полный доступ. Но один злонамеренный скилл или успешная prompt‑инъекция способны превратить его в точку полного компромисса системы. В оригинальном материале это связывают с уязвимостями уровня CVE‑2026‑25253: одна брешь — и агент становится каналом для lateral movement и утечки данных в вашей сети.
Почему контейнеров мало
Если вы запускаете OpenClaw в Kubernetes, кажется, что контейнер уже даёт изоляцию. На практике граница безопасности гораздо тоньше, чем у виртуальной машины:
-
Общее ядро:
- контейнеры делят ядро хоста;
- уязвимость в ядре (privilege escalation) позволяет процессу внутри контейнера получить root‑доступ к ноде.
-
Избыточные привилегии и неправильная конфигурация:
--privileged;- широкие Linux‑capabilities;
hostPath‑монтирования;- доступ к Docker‑сокету;
- проброс устройств вроде
/dev/kvm,/dev/fuse.
Всё это открывает прямой путь к управлению хостом.
-
Пробои границ файловой системы и namespaces:
- ошибки с
mount‑namespaces; - запись в host‑монтирования;
- неправильная работа с
chroot/pivot_root.
В результате контейнер начинает видеть файлы и креденшелы хоста.
- ошибки с
-
Риски supply chain:
- зловредный образ или зависимость стартуют внутри контейнера и дальше пытаются вылезти наружу.
-
Большой blast radius:
- после компромисса ноды атакующий получает:
- токены сервис‑аккаунтов;
- креденшелы к реестрам;
- доступ к kubelet и runtime;
- возможность читать трафик и ходить по другим pod’ам и кластерам.
- после компромисса ноды атакующий получает:
Для OpenClaw это особенно опасно: он запускает код и плагины от разных команд и даже сторонних разработчиков. Мягкая изоляция контейнеров здесь не выдерживает модель угроз, где вы заранее предполагаете враждебный код.
Решение: microVM и Kata Containers
MicroVM — это облегчённые виртуальные машины, оптимизированные под контейнероподобные нагрузки:
- используют аппаратную виртуализацию (KVM / MSHV);
- урезанный device‑model и короткий путь загрузки;
- меньше overhead, чем у «полноценной» VM, но при этом есть гипервизорная граница.
Kata Containers реализуют идею «OCI‑контейнеры внутри VM»:
- для Kubernetes это выглядит как обычный контейнерный runtime;
- каждый pod‑sandbox получает свою microVM с гостевым ядром Linux;
- изоляция строится не только на namespaces/cgroups, а на гипервизоре.
Что это даёт для OpenClaw:
-
Сильная граница изоляции:
- эксплойт ядра Linux внутри агента бьёт по гостевому ядру microVM, а не по ядру ноды;
- чтобы добраться до хоста, атакующему нужно ещё и прорвать гипервизор.
-
Суженный blast radius:
- компромисс ограничен конкретной microVM и pod’ом;
- переход к соседним нагрузкам на ноде сильно усложняется.
-
Контролируемая поверхность атаки:
- минимальный набор устройств;
- меньше host‑монтирований и проброшенных девайсов;
- жёстче дефолтные привилегии.
-
Defense‑in‑depth:
- внутри microVM вы по‑прежнему можете включать:
- seccomp‑профили;
- drop‑capabilities;
- read‑only rootfs;
- LSM (AppArmor/SELinux);
- но поверх этого есть ещё и гипервизор.
- внутри microVM вы по‑прежнему можете включать:
-
Лучше подходит для враждебных multi‑tenant сценариев:
- когда OpenClaw исполняет сторонние плагины, задания и код, Kata‑sandbox выглядит гораздо разумнее, чем «голый» контейнер.
Архитектура решения на AKS
Архитектура строится вокруг Kubernetes и Kata Containers, но для разработчика всё остаётся в контейнерной парадигме: OCI‑образы, Deployment, Service, Gateway API.
Ключевые элементы:
-
Application Gateway for Containers (ALB)
- принимает HTTPS‑трафик от клиентов (WhatsApp, Discord и др. через интеграции);
- реализует TLS‑терминацию на уровне
Gatewayресурса.
-
AKS как оркестратор
- управляет жизненным циклом pod’ов OpenClaw и его Skills;
- применяет политики и распределяет нагрузку.
-
containerd + Kata runtimeClass
- containerd настроен на использование
kata-vm-isolationдля нужных pod’ов; - каждый такой pod запускается внутри microVM.
- containerd настроен на использование
-
KVM‑бэкенд для microVM
- на нодах используется AzureLinux с поддержкой KVM/МSHV;
- node pool создаётся с
--workload-runtime KataMshvVmIsolation.
-
Azure Files NFS для стейта
- PersistentVolume на базе Azure Files NFS с
ReadWriteMany; - хранит рабочее пространство OpenClaw: историю диалогов, конфиги, загруженные файлы.
- PersistentVolume на базе Azure Files NFS с
Поток запросов:
- Пользователь отправляет запрос (например, через WhatsApp‑бота).
- Трафик попадает в Azure Application Gateway for Containers.
Gatewayресурс в Kubernetes принимает HTTPS‑соединение и поHTTPRouteотдаёт его вopenclaw-gateway-service.- Service направляет запрос в один из pod’ов
openclaw-gateway, которые работают внутри Kata microVM. - Агент читает/пишет данные в Azure Files через PV/PVC.
- Ответ возвращается пользователю через тот же Application Gateway.
С точки зрения безопасности самое важное: даже если злоумышленник добился выполнения кода в контейнере OpenClaw, ему нужно ещё взломать границу microVM, чтобы добраться до ноды и других pod’ов.
Что это значит для вас
Кому это реально нужно
Этот подход полезен, если вы:
- запускаете OpenClaw в корпоративной среде с чувствительными данными;
- даёте агенту доступ к внутренним API, CRM, хранилищам документов;
- позволяете сторонним командам или внешним разработчикам писать свои Skills/плагины;
- используете общий AKS‑кластер для нескольких продуктов и не хотите, чтобы один агент стал точкой входа в остальное.
В таких сценариях запуск OpenClaw «просто в контейнере» — слабое звено. MicroVM‑изоляция через Kata уменьшает вероятность того, что один успешный побег из контейнера превратится в компромисс всей ноды и кластера.
Когда можно обойтись без этого
Если вы:
- запускаете OpenClaw локально на личной машине только для себя;
- используете его в отдельном тестовом кластере, полностью изолированном от прод‑ресурсов;
- не даёте агенту доступ к внутренним сетям и важным данным,
то сложность с AKS, Kata и Application Gateway может быть избыточной. В таких случаях проще и дешевле ограничиться классическим hardening контейнера:
- минимальные образы;
- отключённый
--privileged; - строгие seccomp‑профили;
- отсутствие
hostPathи доступа к Docker‑сокету.
На что обратить внимание при внедрении
Плюсы подхода:
- сильная изоляция между OpenClaw и остальными ворклоадами на ноде;
- понятная модель угроз: чтобы добраться до кластера, нужно взломать и OpenClaw, и microVM/hypervisor;
- сохраняется привычный DevOps‑флоу: Docker‑образы, Helm‑чарты, Kubernetes‑манифесты.
Минусы и ограничения:
- вам нужен AKS и Azure‑инфраструктура (NFS Files, Application Gateway for Containers);
- нужен node pool с nested virtualization (не все VM‑типы подойдут);
- microVM‑подход почти всегда даёт чуть больший overhead по старту pod’ов и ресурсам, чем «голые» контейнеры;
- конфигурация сложнее: PV/PVC, Gateway API, TLS, Secrets, ConfigMap, отдельный пул под Kata.
Если вы работаете из России, нужно учитывать:
- доступ к Azure и AKS может потребовать VPN и юридическую проработку;
- без стабильного доступа к Azure этот сценарий не взлетит.
Практический вывод
- Для прод‑запуска OpenClaw с реальными пользователями и доступом к данным: имеет смысл сразу проектировать архитектуру с microVM‑изоляцией.
- Для прототипов и pet‑projects: можно стартовать в обычных контейнерах, но держать в голове, что в момент выхода в прод придётся переехать на более жёсткий sandbox.
Место на рынке
Речь идёт не о новой ИИ‑модели, а об архитектурном паттерне для запуска автономных агентов. Прямых «конкурентов» здесь несколько типов:
-
Обычные контейнеры в Kubernetes
- плюс: минимальные накладные расходы, простота;
- минус: общая поверхность атак ядра, высокая цена ошибки при побеге из контейнера.
-
Отдельные виртуальные машины под каждый агент
- плюс: сильная изоляция;
- минус: тяжёлые, дорогие, медленно стартуют, неудобны для оркестрации множества короткоживущих задач.
-
Специализированные sandbox‑решения (gVisor, Firecracker и др.)
- дают разные варианты усиленной изоляции контейнеров;
- интеграция и поддержка сильно зависят от конкретного облака и стеков.
Kata Containers в AKS занимают промежуточную позицию:
- изоляция ближе к отдельным VM, чем к стандартным контейнерам;
- при этом сохраняется Kubernetes‑оркестрация и OCI‑образ;
- решение глубоко интегрировано в Azure (AKS + Application Gateway for Containers + Azure Files).
Точных чисел по сравнению производительности с обычными контейнерами или отдельными VM в материале нет. Можно лишь сказать, что microVM‑подход проектировался как компромисс: безопасность уровня VM при накладных расходах, приемлемых для контейнерных ворклоадов.
Установка
Ниже — полный путь развертывания решения на AKS. Команды из оригинального гайда сохранены без изменений.
Предварительные требования
Вам нужно заранее подготовить:
- AKS‑кластер в Azure;
- Azure NFS File Share c включённым private link;
- Application Gateway for Containers, управляемый ALB‑контроллером;
- настроенный
kubectl, указывающий на ваш кластер; - авторизованный
azCLI с нужной подпиской.
Инициализация переменных окружения
export cluster_name=<CLUSTER_NAME>
export resource_group=<RESOURCE_GROUP>
Создаём AKS node pool с Kata VM Isolation
Pod’ы OpenClaw gateway требуют runtimeClassName: kata-vm-isolation. Нужен отдельный пул нод с поддержкой этого runtime.
az aks nodepool add \
--resource-group $resource_group \
--cluster-name $cluster_name \
--name katanp \
--node-count 2 \
--node-vm-size Standard_D4s_v3 \
--os-sku AzureLinux \
--workload-runtime KataMshvVmIsolation \
--labels agentpool=katanp
Важно:
--workload-runtime KataMshvVmIsolationвключает runtimeClasskata-vm-isolationна пуле нод.- Размер VM должен поддерживать nested virtualization (D‑series v3/v5, E‑series v3/v5 и т.п.).
Создаём NFS Persistent Volume
Используется Azure Files NFS для постоянного хранилища рабочего пространства OpenClaw. Сначала создаём PV.
Замените volumeHandle и volumeAttributes на свои значения Azure Files.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolume
metadata:
name: openclaw-nfs-pv
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
mountOptions:
- sec=sys
- noresvport
- actimeo=30
csi:
driver: file.csi.azure.com
volumeHandle: <resource-group>#<storage-account>#<share-name>
volumeAttributes:
resourceGroup: <resource-group>
shareName: <share-name>
protocol: nfs
server: <storage-account>.privatelink.file.core.windows.net
EOF
Проверяем, что PV создан:
kubectl get pv openclaw-nfs-pv
Создаём NFS PersistentVolumeClaim
PVC привязывается к созданному PV. Deployment использует PVC pvc-openclaw-nfs.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
# The name of the PVC
name: pvc-openclaw-nfs
spec:
accessModes:
- ReadWriteMany
resources:
requests:
# The real storage capacity in the claim
storage: 50Gi
# This field must be the same as the storage class name in StorageClass
storageClassName: ""
volumeName: openclaw-nfs-pv
EOF
Убедитесь, что PVC в статусе Bound.
Создаём ConfigMap с конфигом OpenClaw
ConfigMap отдаёт pod’ам файл openclaw.json с настройками CORS и токена gateway. Замените allowedOrigins на свой фронтенд ALB.
Важно: токен храните как переменную, не в открытом виде в манифесте.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: openclaw-config
data:
openclaw.json: |
{
"gateway": {
"auth": {
"token": "${AUTH_TOKEN}"
},
"controlUi": {
"allowedOrigins": [
"https://<YOUR ALB FRONTEND URL>.alb.azure.com"
]
}
}
}
EOF
Создаём Secret с токеном авторизации
Gateway OpenClaw требует токен для доступа. Deployment читает его из Secret openclaw-auth-token и прокидывает в переменную AUTH_TOKEN.
Генерируем токен и создаём Secret:
# Generate a random 32-byte hex token
AUTH_TOKEN=$(openssl rand -hex 32)
echo "$AUTH_TOKEN" # save this — you'll need it to authenticate with the gateway
kubectl create secret generic openclaw-auth-token \
--from-literal=token="$AUTH_TOKEN"
Если Secret не существует к моменту применения Deployment, pod’ы упадут с CreateContainerConfigError.
Деплой OpenClaw Gateway
Это основной Deployment приложения. Он зависит от:
- Kata node pool (
runtimeClassName: kata-vm-isolation,nodeSelector: agentpool=katanp); - PVC
pvc-openclaw-nfs; - ConfigMap
openclaw-config.
Особенности:
- 2 реплики с rolling update;
- init‑контейнер копирует конфиг в writable volume;
- порт 18789;
- liveness/readiness‑пробы на
/health; - запросы ресурсов: 500m CPU, 2Gi RAM;
- лимиты: 1000m CPU, 4Gi RAM.
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: openclaw-gateway
spec:
replicas: 2
selector:
matchLabels:
app: openclaw-gateway
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: openclaw-gateway
spec:
runtimeClassName: kata-vm-isolation
nodeSelector:
agentpool: katanp
securityContext:
fsGroup: 1000
initContainers:
- name: copy-openclaw-config
image: alpine/openclaw:latest
env:
- name: HOME
value: /writable
command:
- sh
- -c
- |
cp /config/openclaw.json /writable/openclaw.json \
&& chown 1000:1000 /writable/openclaw.json \
&& echo "--- Config file contents ---" \
&& cat /writable/openclaw.json
volumeMounts:
- name: openclaw-config-volume
mountPath: /config
- name: openclaw-writable
mountPath: /writable
containers:
- name: gateway
image: alpine/openclaw:latest
ports:
- containerPort: 18789
env:
- name: NODE_OPTIONS
value: "--max-old-space-size=4096"
- name: AUTH_TOKEN
valueFrom:
secretKeyRef:
name: openclaw-auth-token
key: token
# Start gateway the way the tutorial indicates
command: ["openclaw", "gateway"]
args: ["run", "--allow-unconfigured", "--bind", "lan"]
volumeMounts:
- name: openclaw-writable
mountPath: /home/node/.openclaw
- name: openclaw-data
mountPath: /home/node/workspace
subPath: workspace
resources:
requests:
cpu: "500m"
memory: "2Gi"
limits:
cpu: "1000m"
memory: "4Gi"
livenessProbe:
httpGet:
path: /health
port: 18789
initialDelaySeconds: 60
periodSeconds: 15
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 18789
initialDelaySeconds: 10
periodSeconds: 5
volumes:
- name: openclaw-data
persistentVolumeClaim:
claimName: pvc-openclaw-nfs
- name: openclaw-config-volume
configMap:
name: openclaw-config
items:
- key: openclaw.json
path: openclaw.json
- name: openclaw-writable
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: openclaw-gateway-service
spec:
type: ClusterIP
selector:
app: openclaw-gateway
ports:
- protocol: TCP
port: 18789
targetPort: 18789
EOF
Проверяем, что Deployment поднялся и pod’ы в статусе Running и READY 2/2:
kubectl get deployment openclaw-gateway
kubectl get pods -l app=openclaw-gateway
Создаём TLS‑секрет для HTTPS
Application Gateway for Containers использует Secret gateway-tls-secret для TLS‑терминации. В гайде — self‑signed сертификат, в проде используйте сертификат от доверенного CA.
kubectl create secret tls gateway-tls-secret \
--cert=<path-to-tls-cert> \
--key=<path-to-tls-key>
Создаём Gateway (Gateway API)
Gateway описывает HTTPS‑листенер на ALB. Обновите аннотацию alb.network.azure.com/application-gateway-id под свой ресурс ALB.
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: https
annotations:
alb.network.azure.com/application-gateway-id: /subscriptions/<subscription id>/resourceGroups/mc_openclaw_openclaw-cluster_centralus/providers/Microsoft.ServiceNetworking/trafficControllers/<alb id>
alb.networking.azure.io/alb-namespace: default
alb.networking.azure.io/alb-name: alb-openclaw
spec:
gatewayClassName: azure-alb-external
listeners:
- name: https
protocol: HTTPS
port: 443
allowedRoutes:
namespaces:
from: All
tls:
mode: Terminate
certificateRefs:
- kind: Secret
group: ""
name: gateway-tls-secret
EOF
kubectl get gateway https
Ждём, пока у Gateway появится Programmed=True.
Создаём HTTPRoute
HTTPRoute связывает Gateway с backend‑сервисом. Весь трафик (/) с HTTPS‑Gateway уходит в openclaw-gateway-service на порт 18789.
cat <<EOF | kubectl apply -f -
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: http-route
spec:
parentRefs:
- name: https
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: openclaw-gateway-service
kind: Service
namespace: default
port: 18789
EOF
Как запустить и проверить
Получаем внешний endpoint
kubectl get gateway https -o jsonpath='{.status.addresses[0].value}'
Откройте этот адрес в браузере. Если вы используете self‑signed сертификат, браузер покажет предупреждение «Not secure» — перейдите через Advanced.
Аутентификация и pairing
На экране логина введите Gateway Token (тот самый AUTH_TOKEN). OpenClaw ответит ошибкой pairing required — это ожидаемо.
OpenClaw требует pairing при первом подключении нового устройства, браузера или CLI‑клиента к gateway.
Одобряем pairing для обоих pod’ов:
POD=$(kubectl get pod -l app=openclaw-gateway -o jsonpath='{.items[0].metadata.name}')
POD2=$(kubectl get pod -l app=openclaw-gateway -o jsonpath='{.items[1].metadata.name}')
TOKEN=$(kubectl get secret openclaw-auth-token -o jsonpath='{.data.token}' | base64 -d)
kubectl exec "$POD" -c gateway -- openclaw devices approve --latest --token "$TOKEN"
kubectl exec "$POD2" -c gateway -- openclaw devices approve --latest --token "$TOKEN"
После сообщения об успешном pairing можно снова открыть веб‑интерфейс OpenClaw и начать работу.
Тестируем изоляцию microVM
Проверим, видит ли pod корневую файловую систему ноды через /proc/1/root.
kubectl exec -it "$POD" -c gateway -- ls /proc/1/root/etc/kubernetes 2>&1
Ожидаемый результат — ошибка вида:
ls: cannot access '/proc/1/root/etc/kubernetes': No such file or directory
В обычном контейнере PID 1 внутри контейнера — это процесс на ядре хоста, и /proc/1/root указывает на root‑файловую систему ноды, включая /etc/kubernetes с креденшелами kubelet. В случае Kata PID 1 живёт внутри гостевой ОС microVM, и до файлов хоста таким способом не дотянуться.
Это и есть практическое подтверждение: OpenClaw работает в изолированной microVM, а не на общем ядре ноды.