When Pooled Memory Stopped Behaving Like Memory: Tracing a Fleet-Wide Stall to an Interleaving Assumption
An estimated few hundred guests froze in the same second across dozens of hosts. They did not share a host, a rack power feed or a hypervisor build. They did share a pooled CXL memory device behind one switch, along with a placement policy that had striped their pages across that device for bandwidth. A retrain on that device's link was the trigger, but the cause was older: the platform had been designed as if attached memory could not fail on its own.
The trigger, kept in its place
A scheduled firmware activation on a multi-logical memory device forced its upstream link through a retrain, and for roughly 900 ms the device returned no completions to any host bound to its logical slices. On a PCIe storage path that would have been a latency spike, absorbed by queues and retries. On CXL.mem it is a load instruction that never retires. The core stalls, the host's completion timeout eventually fires, and the error surfaces as a machine check against a physical range where the kernel had placed anonymous memory and, on some hosts, page tables. The activation followed the documented procedure to the letter. If you name it as the root cause, the fix becomes a ban on online activation, and the next link flap, cable fault or device reset still has exactly the same blast radius.
The assumption that stopped holding
The placement layer was written when CXL capacity meant a direct-attached expander per host. In that world the expander shared the host's failure domain completely, because if it died the host was already in trouble. When the fleet moved to switched pools, the scheduler kept that model and went on interleaving tenant memory across two devices to double usable bandwidth, a choice that looked like it was only about performance. It wasn't. Interleaving turns the failure of any one device into the failure of every tenant whose address range touches it, and pooling multiplies the number of hosts that can touch it. Multi-tenant isolation had been engineered carefully for confidentiality, with per-tenant logical devices, decoders programmed by the fabric manager and a memory encryption key per guest. Nobody had written an isolation requirement for availability, so the design never asked whose failure lands on whom.
Why some hosts rode it out
The hosts that survived weren't luckier, just configured differently: they had onlined pooled capacity only into movable zones, kept kernel allocations and page tables in local DRAM, and mapped device poison to a contained per-page error instead of a viral signal that escalates to the whole host, so the stall cost them a few killed guest processes rather than a reboot.
The rule the redesign enforces
The remediation is a placement constraint, not a procedure change. A tenant's pooled pages may span more than one device only if losing any single device is a loss that tenant's availability contract already absorbs. Otherwise the allocation is pinned to one logical device, and bandwidth comes from local tiering rather than striping. Maintenance becomes a fabric operation. Driven through fabric management standards such as DMTF Redfish and the CXL Fabric Manager API, the fabric manager drains a device by migrating hot pages back to local memory before any retrain is allowed, and it refuses activation while a non-movable range is still bound. The cost is real: pinned allocations strand capacity, and an estimated 10 to 20 percent of the pool that used to be fungible now sits in reserve as failover headroom. The open decision is whether to win back that bandwidth by adding devices per failure domain, or to accept the loss as the price of a pool that can lose a member without losing tenants.
Technical FAQ: Should pooled CXL memory be onlined as system RAM at all?
Yes, but only into movable zones. That way the kernel can migrate pages off the device and never puts its own structures there. Treating pooled memory as general-purpose RAM is what turns a device fault into a host fault.
More Technical Articles on cxlcloud.com
Quando a memória em pool deixou de se comportar como memória: o travamento da frota e a premissa de interleaving por trás dele
Por estimativa, algumas centenas de máquinas virtuais congelaram no mesmo segundo, espalhadas por dezenas de hosts. Não tinham em comum host, alimentação de rack ou versão de hipervisor. Tinham em comum um dispositivo de memória CXL em pool atrás de um único switch e uma política de alocação que distribuía suas páginas por ele para ganhar banda. O retreino do link desse dispositivo foi o gatilho, mas a causa era anterior: a plataforma foi projetada como se memória anexada não pudesse falhar por conta própria.
O gatilho no seu devido lugar
Uma ativação de firmware agendada num dispositivo de memória multilógico obrigou o link upstream a retreinar, e durante cerca de 900 ms o dispositivo não devolveu nenhuma completion aos hosts ligados às suas fatias lógicas. Num caminho de armazenamento PCIe, isso seria um pico de latência que filas e retentativas absorvem. Em CXL.mem, é uma instrução de load que nunca se completa. O núcleo trava, o timeout de completion do host acaba estourando e o erro aparece como machine check numa faixa física onde o kernel tinha colocado memória anônima e, em alguns hosts, tabelas de páginas. A ativação seguiu o procedimento documentado à risca. Apontá-la como causa raiz levaria a proibir a ativação online, e o próximo flap de link, cabo com defeito ou reset de dispositivo continuaria com exatamente o mesmo raio de impacto.
A premissa que deixou de valer
A camada de alocação foi escrita quando capacidade CXL significava um expansor ligado diretamente a cada host. Naquele cenário, o expansor compartilhava totalmente o domínio de falha do host: se ele morresse, o host já estava com problema. Quando a frota migrou para pools comutados, o escalonador manteve o mesmo modelo e continuou intercalando a memória dos tenants entre dois dispositivos para dobrar a banda útil, uma escolha que parecia ser só de desempenho. Não era. O interleaving transforma a falha de qualquer dispositivo na falha de todo tenant cujo espaço de endereços encosta nele, e o pooling multiplica a quantidade de hosts que encostam. O isolamento multi-tenant foi bem projetado para confidencialidade, com dispositivos lógicos por tenant, decodificadores programados pelo fabric manager e uma chave de criptografia de memória por convidado. Ninguém escreveu um requisito de isolamento para disponibilidade, então o projeto nunca perguntou sobre quem cai a falha de quem.
Por que alguns hosts aguentaram
Os hosts que resistiram não tiveram mais sorte, só estavam configurados de outro jeito: só tinham colocado a capacidade do pool online em zonas móveis, mantinham as alocações do kernel e as tabelas de páginas na DRAM local e tratavam o poison do dispositivo como erro contido por página, em vez de sinal viral que derruba o host inteiro, e por isso o travamento custou alguns processos de convidados encerrados, não um reboot.
A regra que o novo desenho impõe
A correção é uma restrição de alocação, não uma mudança de procedimento. As páginas de um tenant só podem ficar em mais de um dispositivo se perder qualquer um deles for uma perda que o contrato de disponibilidade desse tenant já absorve. Caso contrário, a alocação fica presa a um único dispositivo lógico, e a banda vem de tiering local, não de striping. A manutenção vira operação de fabric. Comandado por padrões de gerenciamento de fabric como DMTF Redfish e a API do CXL Fabric Manager, o fabric manager esvazia o dispositivo migrando as páginas quentes de volta para a memória local antes de autorizar qualquer retreino, e recusa a ativação enquanto ainda houver uma faixa não móvel vinculada. O custo existe: alocações presas deixam capacidade ociosa, e por estimativa de 10 a 20 por cento do pool, que antes era intercambiável, agora fica reservado como folga de failover. Falta decidir se essa banda volta com mais dispositivos por domínio de falha ou se fica aceita como o preço de um pool que perde um membro sem perder tenants.
FAQ Técnica: Vale a pena colocar a memória CXL em pool online como RAM do sistema?
Vale, desde que só em zonas móveis. Assim o kernel pode migrar páginas para fora do dispositivo e nunca coloca suas próprias estruturas ali. Tratar o pool como RAM de uso geral é o que transforma uma falha de dispositivo em falha de host.
Mais Artigos Técnicos em cxlcloud.com
Cuando la memoria en pool dejó de comportarse como memoria: el bloqueo de toda la flota y la premisa de entrelazado que lo explica
Según una estimación, unos cientos de máquinas virtuales se congelaron en el mismo segundo, repartidas en decenas de hosts. No compartían host, alimentación de rack ni versión de hipervisor. Compartían un dispositivo de memoria CXL en pool detrás de un único switch y una política de ubicación que entrelazaba sus páginas en él para ganar ancho de banda. El reentrenamiento del enlace de ese dispositivo fue el disparador, pero la causa venía de antes: la plataforma se diseñó como si la memoria conectada no pudiera fallar por sí sola.
El disparador, en su sitio
Una activación de firmware programada en un dispositivo de memoria multilógico obligó a reentrenar su enlace ascendente, y durante unos 900 ms el dispositivo no devolvió ninguna completion a los hosts asociados a sus particiones lógicas. En una ruta de almacenamiento PCIe habría sido un pico de latencia que las colas y los reintentos absorben. En CXL.mem es una instrucción de carga que nunca termina. El núcleo se detiene, el timeout de completion del host acaba disparándose y el error aflora como machine check sobre un rango físico donde el kernel había colocado memoria anónima y, en algunos hosts, tablas de páginas. La activación siguió al pie de la letra el procedimiento documentado. Declararla causa raíz llevaría a prohibir la activación en caliente, y el siguiente flap de enlace, cable defectuoso o reset de dispositivo tendría exactamente el mismo radio de impacto.
La premisa que dejó de cumplirse
La capa de ubicación se escribió cuando la capacidad CXL significaba un expansor conectado directamente a cada host. En ese mundo, el expansor compartía por completo el dominio de fallo del host: si moría, el host ya tenía un problema. Al pasar a pools conmutados, el planificador conservó ese modelo y siguió entrelazando la memoria de los tenants entre dos dispositivos para duplicar el ancho de banda útil, una decisión que parecía solo de rendimiento. No lo era. El entrelazado convierte el fallo de cualquier dispositivo en el fallo de todo tenant cuyo rango de direcciones lo toca, y el pooling multiplica el número de hosts que lo tocan. El aislamiento multi-tenant estaba bien resuelto para la confidencialidad, con dispositivos lógicos por tenant, decodificadores programados por el fabric manager y una clave de cifrado de memoria por invitado. Nadie había escrito un requisito de aislamiento para la disponibilidad, así que el diseño nunca se planteó a quién le cae el fallo de quién.
Por qué algunos hosts aguantaron
Los hosts que sobrevivieron no tuvieron más suerte, solo otra configuración: habían puesto en línea la capacidad del pool únicamente en zonas movibles, mantenían las asignaciones del kernel y las tablas de páginas en la DRAM local y trataban el poison del dispositivo como un error contenido por página, en lugar de una señal viral que se propaga a todo el host, de modo que el bloqueo les costó unos pocos procesos invitados terminados y no un reinicio.
La regla que impone el rediseño
La corrección es una restricción de ubicación, no un cambio de procedimiento. Las páginas de un tenant solo pueden repartirse entre varios dispositivos si perder cualquiera de ellos es una pérdida que su contrato de disponibilidad ya absorbe. Si no, la asignación queda fijada a un único dispositivo lógico, y el ancho de banda sale del tiering local, no del striping. El mantenimiento se convierte en una operación del fabric. Dirigido mediante estándares de gestión de fabric como DMTF Redfish y la API del CXL Fabric Manager, el fabric manager vacía el dispositivo migrando las páginas calientes a la memoria local antes de autorizar cualquier reentrenamiento, y rechaza la activación mientras quede un rango no movible asociado. El coste es real: las asignaciones fijadas dejan capacidad varada, y según una estimación entre el 10 y el 20 por ciento del pool, antes intercambiable, queda ahora reservado como margen de failover. Queda por decidir si ese ancho de banda se recupera con más dispositivos por dominio de fallo o se acepta como el precio de un pool capaz de perder un miembro sin perder tenants.
Preguntas Frecuentes Técnicas: ¿Conviene poner en línea la memoria CXL en pool como RAM del sistema?
Sí, pero solo en zonas movibles. Así el kernel puede migrar páginas fuera del dispositivo y nunca coloca allí sus propias estructuras. Usar el pool como RAM de propósito general es lo que convierte un fallo de dispositivo en un fallo de host.
Más Artículos Técnicos en cxlcloud.com
Quand la mémoire mutualisée a cessé de se comporter comme de la mémoire : remonter d'un gel de flotte à une hypothèse d'entrelacement
Selon une estimation, quelques centaines de machines virtuelles se sont figées dans la même seconde, réparties sur des dizaines d'hôtes. Elles ne partageaient ni hôte, ni alimentation de baie, ni version d'hyperviseur. Elles partageaient un équipement mémoire CXL mutualisé derrière un seul switch, et une politique de placement qui y entrelaçait leurs pages pour gagner en bande passante. Le réentraînement du lien de cet équipement a été le déclencheur, mais la cause remonte plus loin: la plateforme a été conçue comme si la mémoire attachée ne pouvait pas tomber en panne d'elle-même.
Remettre le déclencheur à sa place
Une activation de firmware planifiée sur un équipement mémoire multi-logique a forcé le réentraînement de son lien montant, et pendant environ 900 ms l'équipement n'a renvoyé aucune complétion aux hôtes rattachés à ses tranches logiques. Sur un chemin de stockage PCIe, cela aurait donné un pic de latence absorbé par les files et les relances. Sur CXL.mem, c'est une instruction de chargement qui ne se termine jamais. Le cœur se bloque, le délai de complétion de l'hôte finit par expirer, et l'erreur remonte en machine check sur une plage physique où le noyau avait placé de la mémoire anonyme et, sur certains hôtes, des tables de pages. L'activation a suivi la procédure documentée à la lettre. En faire la cause racine mènerait à interdire l'activation à chaud, et le prochain flap de lien, câble défectueux ou reset d'équipement aurait exactement le même rayon d'impact.
L'hypothèse qui a cédé
La couche de placement a été écrite à l'époque où la capacité CXL voulait dire un expandeur relié directement à chaque hôte. Dans ce monde-là, l'expandeur partageait entièrement le domaine de panne de l'hôte: s'il lâchait, l'hôte était déjà en difficulté. Lors du passage aux pools commutés, l'ordonnanceur a conservé ce modèle et a continué d'entrelacer la mémoire des locataires sur deux équipements pour doubler la bande passante utile, un choix qui semblait ne relever que de la performance. Ce n'était pas le cas. L'entrelacement transforme la panne de n'importe quel équipement en panne de tous les locataires dont la plage d'adresses le touche, et la mutualisation multiplie le nombre d'hôtes qui le touchent. L'isolation multi-locataire avait été soignée côté confidentialité, avec des équipements logiques par locataire, des décodeurs programmés par le fabric manager et une clé de chiffrement mémoire par invité. Personne n'avait écrit d'exigence d'isolation pour la disponibilité, si bien que la conception ne s'est jamais demandé sur qui retombe la panne de qui.
Pourquoi certains hôtes ont tenu
Les hôtes qui ont survécu n'avaient pas plus de chance, seulement une autre configuration: ils n'avaient mis en ligne la capacité du pool que dans des zones déplaçables, gardaient les allocations du noyau et les tables de pages en DRAM locale, et traitaient le poison de l'équipement comme une erreur confinée à la page plutôt que comme un signal viral qui contamine tout l'hôte, si bien que le gel leur a coûté quelques processus invités tués, pas un redémarrage.
La règle qu'impose la refonte
Le correctif est une contrainte de placement, pas une modification de procédure. Les pages d'un locataire ne peuvent s'étendre sur plusieurs équipements que si la perte de l'un d'eux est une perte que son contrat de disponibilité absorbe déjà. Sinon, l'allocation est épinglée à un seul équipement logique, et la bande passante vient du tiering local plutôt que de l'entrelacement. La maintenance devient une opération de fabric. Piloté au moyen de normes de gestion de fabric comme DMTF Redfish et l'API CXL Fabric Manager, le fabric manager vide l'équipement en rapatriant les pages chaudes vers la mémoire locale avant d'autoriser tout réentraînement, et refuse l'activation tant qu'une plage non déplaçable y reste rattachée. Le coût est réel: les allocations épinglées immobilisent de la capacité, et selon une estimation 10 à 20 % du pool, autrefois fongible, dort désormais en réserve comme marge de bascule. Reste à décider s'il faut retrouver cette bande passante en ajoutant des équipements par domaine de panne, ou l'accepter comme le prix d'un pool capable de perdre un membre sans perdre de locataires.
FAQ Technique: Faut-il mettre en ligne la mémoire CXL mutualisée comme RAM système?
Oui, mais uniquement dans des zones déplaçables. Le noyau peut ainsi migrer les pages hors de l'équipement et n'y place jamais ses propres structures. Traiter le pool comme de la RAM généraliste, c'est ce qui transforme une panne d'équipement en panne d'hôte.
Plus d'Articles Techniques sur cxlcloud.com
Quando la memoria in pool ha smesso di comportarsi da memoria: dal blocco della flotta a un'ipotesi di interleaving
Secondo una stima, qualche centinaio di macchine virtuali si sono bloccate nello stesso secondo, distribuite su decine di host. Non avevano in comune l'host, l'alimentazione del rack o la versione dell'hypervisor. Avevano in comune un dispositivo di memoria CXL in pool dietro un unico switch e una politica di allocazione che vi distribuiva le loro pagine per guadagnare banda. Il retraining del link di quel dispositivo è stato il fattore scatenante, ma la causa era più vecchia: la piattaforma era stata progettata come se la memoria collegata non potesse guastarsi da sola.
Il fattore scatenante, al suo posto
Un'attivazione firmware programmata su un dispositivo di memoria multi-logico ha costretto il link upstream a un retraining, e per circa 900 ms il dispositivo non ha restituito alcuna completion agli host collegati alle sue partizioni logiche. Su un percorso di storage PCIe sarebbe stato un picco di latenza, assorbito da code e ritentativi. Su CXL.mem è un'istruzione di load che non si completa mai. Il core si blocca, il timeout di completion dell'host alla fine scatta e l'errore emerge come machine check su un intervallo fisico in cui il kernel aveva messo memoria anonima e, su alcuni host, tabelle delle pagine. L'attivazione aveva seguito alla lettera la procedura documentata. Indicarla come causa radice porterebbe a vietare l'attivazione a caldo, e il prossimo flap del link, cavo difettoso o reset del dispositivo avrebbe lo stesso identico raggio d'impatto.
L'ipotesi che non ha più retto
Lo strato di allocazione era stato scritto quando capacità CXL voleva dire un espansore collegato direttamente a ogni host. In quel mondo l'espansore condivideva per intero il dominio di guasto dell'host: se moriva, l'host era già nei guai. Con il passaggio ai pool commutati, lo scheduler ha conservato quel modello e ha continuato a fare interleaving della memoria dei tenant su due dispositivi per raddoppiare la banda utile, una scelta che sembrava riguardare solo le prestazioni. Non era così. L'interleaving trasforma il guasto di un qualsiasi dispositivo nel guasto di ogni tenant il cui spazio di indirizzi lo tocca, e il pooling moltiplica gli host che lo toccano. L'isolamento multi-tenant era stato curato bene sul fronte della riservatezza, con dispositivi logici per tenant, decoder programmati dal fabric manager e una chiave di cifratura della memoria per ogni guest. Nessuno aveva scritto un requisito di isolamento per la disponibilità, e così il progetto non si è mai chiesto su chi ricade il guasto di chi.
Perché alcuni host hanno retto
Gli host sopravvissuti non sono stati più fortunati, erano solo configurati in un altro modo: avevano messo online la capacità del pool soltanto in zone movibili, tenevano le allocazioni del kernel e le tabelle delle pagine nella DRAM locale e gestivano il poison del dispositivo come errore confinato alla singola pagina, invece che come segnale virale esteso all'intero host, quindi il blocco è costato loro qualche processo guest terminato e non un riavvio.
La regola imposta dalla riprogettazione
La correzione è un vincolo di allocazione, non una modifica di procedura. Le pagine di un tenant possono stare su più dispositivi solo se la perdita di uno qualsiasi di essi è una perdita che il suo contratto di disponibilità già assorbe. Altrimenti l'allocazione resta vincolata a un solo dispositivo logico, e la banda arriva dal tiering locale invece che dallo striping. La manutenzione diventa un'operazione di fabric. Pilotato attraverso standard di gestione del fabric come DMTF Redfish e l'API del CXL Fabric Manager, il fabric manager svuota il dispositivo riportando le pagine calde nella memoria locale prima di autorizzare qualsiasi retraining, e rifiuta l'attivazione finché resta collegato un intervallo non movibile. Il costo c'è: le allocazioni vincolate lasciano capacità inutilizzata, e secondo una stima tra il 10 e il 20 per cento del pool, prima fungibile, resta ora in riserva come margine di failover. Resta da decidere se recuperare quella banda con più dispositivi per dominio di guasto o accettarla come prezzo di un pool che può perdere un membro senza perdere tenant.
FAQ Tecnica: Ha senso mettere online la memoria CXL in pool come RAM di sistema?
Sì, ma solo in zone movibili. Così il kernel può migrare le pagine fuori dal dispositivo e non vi colloca mai le proprie strutture. Usare il pool come RAM generica è proprio ciò che trasforma un guasto del dispositivo in un guasto dell'host.
Altri Articoli Tecnici su cxlcloud.com
Als gepoolter Speicher aufhörte, sich wie Speicher zu verhalten: vom flottenweiten Stillstand zur Interleaving-Annahme
Schätzungsweise einige hundert Gäste froren in derselben Sekunde ein, verteilt über Dutzende Hosts. Sie teilten weder Host noch Rack-Stromversorgung noch Hypervisor-Build. Gemeinsam war ihnen ein gepooltes CXL-Speichergerät hinter einem einzigen Switch und eine Platzierungsrichtlinie, die ihre Seiten der Bandbreite wegen darüber verteilte. Das Retraining des Links dieses Geräts war der Auslöser, die Ursache aber älter: Die Plattform war so entworfen, als könne angebundener Speicher nicht von sich aus ausfallen.
Der Auslöser, richtig eingeordnet
Eine geplante Firmware-Aktivierung auf einem Multi-Logical-Speichergerät zwang den Upstream-Link in ein Retraining, und für rund 900 ms lieferte das Gerät keinem Host, der an seine logischen Slices gebunden war, eine einzige Completion. Auf einem PCIe-Speicherpfad wäre das eine Latenzspitze gewesen, die Queues und Retries abfangen. Unter CXL.mem ist es ein Load-Befehl, der nie abschließt. Der Kern hängt, irgendwann greift der Completion-Timeout des Hosts, und der Fehler erscheint als Machine Check auf einem physischen Bereich, in den der Kernel anonymen Speicher und auf manchen Hosts auch Seitentabellen gelegt hatte. Die Aktivierung lief exakt nach dokumentiertem Verfahren. Wer sie zur Grundursache erklärt, landet bei einem Verbot der Online-Aktivierung, und der nächste Link-Flap, das nächste defekte Kabel oder der nächste Geräte-Reset hätte genau denselben Wirkungsradius.
Die Annahme, die nicht mehr trug
Die Platzierungsschicht entstand, als CXL-Kapazität einen direkt angebundenen Expander pro Host bedeutete. In dieser Welt teilte der Expander die Fehlerdomäne des Hosts vollständig: Fiel er aus, steckte der Host ohnehin schon in Schwierigkeiten. Beim Wechsel zu geswitchten Pools behielt der Scheduler dieses Modell bei und verschränkte Mandantenspeicher weiterhin über zwei Geräte, um die nutzbare Bandbreite zu verdoppeln, eine Entscheidung, die nach reiner Performance aussah. Das war sie nicht. Interleaving macht aus dem Ausfall eines beliebigen Geräts den Ausfall jedes Mandanten, dessen Adressbereich es berührt, und Pooling vervielfacht die Zahl der Hosts, die es berühren. Die Mandantentrennung war für Vertraulichkeit sorgfältig gebaut, mit logischen Geräten pro Mandant, vom Fabric Manager programmierten Decodern und einem Speicherschlüssel pro Gast. Eine Isolationsanforderung für Verfügbarkeit hatte niemand formuliert, also stellte der Entwurf nie die Frage, wessen Ausfall wen trifft.
Warum manche Hosts durchhielten
Die überlebenden Hosts hatten nicht mehr Glück, sondern eine andere Konfiguration: Sie hatten Pool-Kapazität nur in verschiebbare Zonen eingebunden, Kernel-Allokationen und Seitentabellen im lokalen DRAM belassen und Poison vom Gerät als auf die Seite begrenzten Fehler behandelt statt als viralen Zustand, der den ganzen Host erfasst, weshalb sie der Stillstand ein paar beendete Gastprozesse kostete und keinen Neustart.
Die Regel, die das Redesign durchsetzt
Die Abhilfe ist eine Platzierungsregel, keine Verfahrensänderung. Die gepoolten Seiten eines Mandanten dürfen nur dann mehrere Geräte umfassen, wenn der Verlust eines einzelnen Geräts ein Verlust ist, den sein Verfügbarkeitsvertrag ohnehin abdeckt. Andernfalls wird die Allokation an ein logisches Gerät gebunden, und Bandbreite kommt aus lokalem Tiering statt aus Striping. Wartung wird zur Fabric-Operation. Gesteuert über Fabric-Management-Standards wie DMTF Redfish und die CXL Fabric Manager API, leert der Fabric Manager ein Gerät, indem er heiße Seiten in den lokalen Speicher zurückmigriert, bevor ein Retraining erlaubt wird, und er verweigert die Aktivierung, solange noch ein nicht verschiebbarer Bereich gebunden ist. Das kostet etwas: Gebundene Allokationen lassen Kapazität brachliegen, und schätzungsweise 10 bis 20 Prozent des früher frei verschiebbaren Pools liegen jetzt als Failover-Reserve still. Offen bleibt, ob man diese Bandbreite mit mehr Geräten pro Fehlerdomäne zurückholt oder sie als Preis für einen Pool akzeptiert, der ein Mitglied verlieren kann, ohne Mandanten zu verlieren.
Technische FAQ: Sollte man gepoolten CXL-Speicher überhaupt als System-RAM einbinden?
Ja, aber nur in verschiebbare Zonen. Dann kann der Kernel Seiten vom Gerät wegmigrieren und legt seine eigenen Strukturen nie dort ab. Erst wenn man den Pool als Allzweck-RAM behandelt, wird aus einem Gerätefehler ein Hostausfall.
Weitere Fachartikel auf cxlcloud.com
池化内存不再像内存:从全集群卡死追溯到交织策略背后的设计假设
估计有数百台虚拟机在同一秒内同时冻结,分布在几十台主机上。它们不共享主机,不共享机柜供电,也不共享同一版 Hypervisor。它们的共同点是同一台交换机后面的一个池化 CXL 内存设备,以及一条为了带宽把它们的页面交织到该设备上的放置策略。触发事件是这台设备的链路重训练,但根因早已存在:平台在设计时默认挂载的内存不会自己出故障。
触发事件只是触发事件
一台多逻辑内存设备按计划激活固件,迫使其上行链路重训练,大约 900 ms 内,该设备没有向任何绑定其逻辑分片的主机返回 completion。如果发生在 PCIe 存储路径上,这只是一次能被队列和重试吸收的延迟尖峰。但在 CXL.mem 上,这意味着一条永远无法完成的 load 指令。核心停顿,主机的 completion 超时最终触发,错误以 machine check 的形式出现在一段物理地址上,而内核在那里放了匿名内存,部分主机上甚至放了页表。固件激活完全按照文档流程执行。把它定为根因,结论就会是禁止在线激活,而下一次链路抖动、线缆故障或设备复位造成的影响范围不会有任何缩小。
失效的假设
放置层是在 CXL 容量还意味着每台主机直连一块扩展卡的年代写成的。那时扩展卡与主机完全处于同一个故障域:扩展卡坏了,主机本来就已经出问题了。集群转向交换式内存池后,调度器沿用了这套模型,继续把租户内存交织到两台设备上以使可用带宽翻倍,这个决定看起来纯粹关乎性能。实际上并非如此。交织会把任何一台设备的故障变成所有地址范围触及它的租户的故障,而池化又成倍增加了能触及它的主机数量。多租户隔离在机密性上做得很细致,有按租户划分的逻辑设备、由 fabric manager 编程的解码器,以及每台虚拟机独立的内存加密密钥。但从没有人为可用性写下隔离要求,因此设计中从未问过一个问题:谁的故障会落到谁头上。
为什么有些主机挺了过来
挺过来的主机并不是运气更好,而是配置不同:它们只把池化容量上线到可迁移区域,把内核分配和页表留在本地 DRAM,并把设备 poison 处理为限于单页的错误,而不是会扩散到整台主机的 viral 信号,所以这次停顿只让它们损失了几个被终止的虚拟机进程,而不是一次重启。
重新设计强制执行的规则
修复手段是一条放置约束,而不是流程变更。只有当失去其中任意一台设备是该租户的可用性承诺本就能承受的损失时,租户的池化页面才允许跨越多台设备。否则就把分配固定在单个逻辑设备上,带宽改由本地分层获得,而不是靠条带化。维护变成了一项 fabric 操作。fabric manager 通过 DMTF Redfish 和 CXL Fabric Manager API 这类 fabric 管理标准驱动,在允许任何重训练之前,先把热页迁回本地内存以腾空设备,只要还有不可迁移的地址范围绑定在上面,就拒绝激活。代价是实实在在的:固定分配会让容量闲置,估计池中原本可自由调配的 10% 到 20% 现在作为故障切换余量被预留。尚待决定的是,究竟通过在每个故障域内增加设备把这部分带宽找回来,还是把它当作代价接受下来,换取一个失去某个成员也不会失去租户的内存池。
技术常见问题 (FAQ): 池化 CXL 内存还应该作为系统内存上线吗?
应该,但只能上线到可迁移区域。这样内核可以把页面迁出设备,也永远不会把自身的数据结构放在那里。把内存池当作通用内存使用,正是设备故障演变成主机故障的原因。
更多技术文章: cxlcloud.com
プールされたメモリがメモリらしく振る舞わなくなったとき:フリート全体の停止をインターリーブの前提までさかのぼる
推定で数百台のゲストが、数十台のホストにまたがって同じ一秒のうちに固まった。ホストもラック電源もハイパーバイザのビルドも共有していない。共通していたのは、一台のスイッチの背後にあるプール型 CXL メモリデバイスと、帯域を稼ぐためにゲストのページをそのデバイスへインターリーブしていた配置ポリシーだった。引き金はそのデバイスのリンク再トレーニングだったが、原因はもっと前からあった。プラットフォームは、接続されたメモリが単独で故障することはないという前提で設計されていた。
トリガーはトリガーとして扱う
マルチロジカル型メモリデバイスで予定どおりファームウェアを有効化したところ、上流リンクが再トレーニングに入り、約 900 ms のあいだ、論理スライスに紐づくどのホストにもデバイスから completion が返らなかった。PCIe のストレージ経路であれば、キューとリトライが吸収するレイテンシのスパイクで済む。CXL.mem では、完了しない load 命令になる。コアがストールし、やがてホスト側の completion タイムアウトが発火して、エラーはマシンチェックとして表面化する。その物理範囲には、カーネルが匿名メモリを、一部のホストではページテーブルまで置いていた。ファームウェアの有効化は文書化された手順どおりに行われている。これを根本原因とすれば、対策はオンライン有効化の禁止になるが、次のリンクフラップやケーブル障害、デバイスリセットでも影響範囲はまったく同じままになる。
崩れた前提
配置レイヤーが書かれたのは、CXL の容量といえばホストごとに直結した拡張デバイスを指していた時代だった。その世界では拡張デバイスとホストは完全に同じ障害ドメインにあり、拡張デバイスが壊れればホストもすでに無事ではなかった。スイッチ経由のプールに移行してもスケジューラはこのモデルを引き継ぎ、使える帯域を倍にするためにテナントのメモリを二台のデバイスへインターリーブし続けた。性能だけの判断に見えたが、そうではなかった。インターリーブは、どれか一台のデバイスの故障を、そのデバイスにアドレス範囲がかかるすべてのテナントの故障に変える。そしてプール化によって、そのデバイスにかかるホストの数は何倍にも増える。マルチテナント分離は、テナントごとの論理デバイス、fabric manager がプログラムするデコーダ、ゲストごとのメモリ暗号鍵と、機密性については丁寧に作り込まれていた。しかし可用性についての分離要件は誰も書いておらず、誰の故障が誰に及ぶのかという問いは設計の中で一度も立てられなかった。
持ちこたえたホストの違い
生き残ったホストは運が良かったのではなく設定が違っただけで、プール容量を移動可能ゾーンにだけオンライン化し、カーネルの割り当てとページテーブルはローカル DRAM に残し、デバイスからの poison をホスト全体に波及する viral 信号ではなくページ単位に閉じたエラーとして扱っていたため、停止の代償は再起動ではなく、強制終了された数個のゲストプロセスで済んだ。
再設計が課すルール
対策は手順の変更ではなく配置の制約である。テナントのプール上のページが複数のデバイスにまたがってよいのは、どれか一台を失っても、そのテナントの可用性契約がすでにその損失を織り込んでいる場合に限る。そうでなければ割り当ては一つの論理デバイスに固定し、帯域はストライピングではなくローカルの階層化でまかなう。保守はファブリック上の操作になる。DMTF Redfish や CXL Fabric Manager API といったファブリック管理の標準を通じて動く fabric manager は、再トレーニングを許可する前にホットページをローカルメモリへ戻してデバイスを空にし、移動不能な範囲が紐づいている間は有効化を拒否する。代償は確かにある。固定割り当ては容量を遊ばせ、推定で以前は融通の利いたプールの 10〜20 パーセントがフェイルオーバー用の余裕として予約されたままになる。残っている判断は、障害ドメインあたりのデバイスを増やしてこの帯域を取り戻すのか、それともメンバーを一台失ってもテナントを失わないプールの代価として受け入れるのか、である。
技術FAQ: プール型 CXL メモリをそもそもシステム RAM としてオンライン化すべきか。
すべきだが、移動可能ゾーンに限る。そうすればカーネルはページをデバイスの外へ移行でき、自身のデータ構造をそこに置くこともない。プールを汎用 RAM として扱うことこそが、デバイス障害をホスト障害に変えてしまう。
その他の技術記事: cxlcloud.com
풀링된 메모리가 더 이상 메모리처럼 동작하지 않을 때: 플릿 전체 정지를 인터리빙 가정까지 추적하다
추정치로 수백 대의 게스트가 수십 대의 호스트에 걸쳐 같은 1초 안에 멈췄다. 이들은 호스트도, 랙 전원도, 하이퍼바이저 빌드도 공유하지 않았다. 공통점은 스위치 하나 뒤에 놓인 풀링 CXL 메모리 디바이스, 그리고 대역폭을 위해 게스트 페이지를 그 디바이스에 인터리빙하던 배치 정책이었다. 트리거는 그 디바이스의 링크 재트레이닝이었지만 원인은 그보다 오래됐다. 플랫폼은 연결된 메모리가 혼자서는 고장 나지 않는다는 전제로 설계되어 있었다.
트리거는 트리거일 뿐
멀티 로지컬 메모리 디바이스에서 예정된 펌웨어 활성화가 업스트림 링크를 재트레이닝으로 몰아넣었고, 약 900 ms 동안 디바이스는 자신의 논리 슬라이스에 바인딩된 어떤 호스트에도 completion을 돌려주지 않았다. PCIe 스토리지 경로였다면 큐와 재시도가 흡수하는 지연 스파이크로 끝났을 것이다. CXL.mem에서는 끝나지 않는 load 명령이 된다. 코어가 멈추고, 결국 호스트의 completion 타임아웃이 발동하며, 오류는 머신 체크로 드러난다. 문제의 물리 주소 범위에는 커널이 익명 메모리를, 일부 호스트에서는 페이지 테이블까지 올려 두고 있었다. 펌웨어 활성화는 문서화된 절차를 그대로 따랐다. 이를 근본 원인으로 지목하면 대책은 온라인 활성화 금지가 되고, 다음 링크 플랩이나 케이블 결함, 디바이스 리셋의 영향 범위는 전혀 줄어들지 않는다.
무너진 가정
배치 계층은 CXL 용량이 곧 호스트마다 직결된 확장 장치를 뜻하던 시절에 작성됐다. 그때는 확장 장치가 호스트와 장애 도메인을 완전히 공유했고, 확장 장치가 죽으면 호스트도 이미 문제가 생긴 상태였다. 스위치 기반 풀로 넘어간 뒤에도 스케줄러는 이 모델을 그대로 유지했고, 가용 대역폭을 두 배로 늘리려고 테넌트 메모리를 두 디바이스에 계속 인터리빙했다. 순전히 성능 문제로 보이는 결정이었다. 그렇지 않았다. 인터리빙은 어느 한 디바이스의 장애를 그 디바이스에 주소 범위가 닿는 모든 테넌트의 장애로 바꾸고, 풀링은 그 디바이스에 닿는 호스트 수를 몇 배로 늘린다. 멀티테넌트 격리는 테넌트별 논리 디바이스, fabric manager가 프로그래밍하는 디코더, 게스트별 메모리 암호화 키까지 기밀성 측면에서는 꼼꼼하게 설계되어 있었다. 하지만 가용성에 대한 격리 요구사항은 아무도 문서로 남기지 않았고, 그래서 설계는 누구의 장애가 누구에게 떨어지는지를 한 번도 묻지 않았다.
일부 호스트가 버틴 이유
살아남은 호스트는 운이 좋았던 것이 아니라 구성이 달랐을 뿐으로, 풀 용량을 이동 가능 영역에만 온라인으로 올렸고, 커널 할당과 페이지 테이블은 로컬 DRAM에 두었으며, 디바이스 poison을 호스트 전체로 번지는 viral 신호가 아니라 페이지 단위로 격리된 오류로 처리했기 때문에, 정지의 대가는 재부팅이 아니라 종료된 게스트 프로세스 몇 개에 그쳤다.
재설계가 강제하는 규칙
해결책은 절차 변경이 아니라 배치 제약이다. 테넌트의 풀 페이지는 디바이스 하나를 잃는 것이 그 테넌트의 가용성 계약이 이미 감당하는 손실일 때에만 여러 디바이스에 걸칠 수 있다. 그렇지 않으면 할당을 하나의 논리 디바이스에 고정하고, 대역폭은 스트라이핑이 아니라 로컬 티어링으로 확보한다. 유지보수는 패브릭 작업이 된다. DMTF Redfish와 CXL Fabric Manager API 같은 패브릭 관리 표준으로 구동되는 fabric manager는 재트레이닝을 허용하기 전에 핫 페이지를 로컬 메모리로 되돌려 디바이스를 비우고, 이동 불가능한 범위가 아직 바인딩되어 있으면 활성화를 거부한다. 비용은 분명히 있다. 고정 할당은 용량을 놀리게 만들고, 추정치로 예전에는 자유롭게 돌려 쓰던 풀의 10~20퍼센트가 이제 페일오버 여유분으로 묶여 있다. 남은 결정은 장애 도메인당 디바이스를 늘려 이 대역폭을 되찾을지, 아니면 구성원 하나를 잃어도 테넌트를 잃지 않는 풀의 대가로 받아들일지다.
기술 FAQ: 풀링된 CXL 메모리를 시스템 RAM으로 온라인화해도 되는가?
된다. 다만 이동 가능 영역에만 올려야 한다. 그래야 커널이 페이지를 디바이스 밖으로 옮길 수 있고, 자신의 자료구조를 그곳에 두지 않는다. 풀을 범용 RAM처럼 다루는 것이 바로 디바이스 장애를 호스트 장애로 키우는 원인이다.