WebAssembly Çalıştıran Bir Unikernel Oluşturmak - Bölüm 1
(flavio.castelli.me)- SUSE Hackweek 22 kapsamında WebAssembly modülleri çalıştıran bir unikernel POC’si oluşturuldu ve uygulama süreci birkaç bölüme ayrılarak özetlendi
- Genel uygulamaları doğrudan bir unikernel’e port etmek için bağımlılıkları da uyumlu hale getirmek gerekir; ancak WebAssembly platformunda çalışma zamanının sağlayacağı işlevlerin sınırları daha belirgindir
- Spiderlightning uygulamaları yalnızca Key/Value gibi işlevler ister; host bunu Redis ya da Azure Cosmos DB ile uygulasın, aynı
.wasmmodülünün farkı bilmesine gerek yoktur - Temel olarak Rust unikernel’i RustyHermit kullanıldı; Wasmtime ve Wasmer derlenemediği için saf Rust çalışma zamanı wasmi seçildi
- Component Model ve WIT ile uyum sağlamak için wit-bindgen’e wasmi desteği eklendi, ardından host tarafındaki Key/Value işlevi iskele haline getirilerek
keyvalue-demoçalıştırıldı
Hackweek projesi ve hedef
- SUSE’nin Hackweek 22 döneminde WebAssembly çalıştıran bir unikernel oluşturma projesi yürütüldü
- Tüm uygulama süreci tek bir yazıya sığmayacak kadar uzun olduğu için birkaç yazıya bölündü; bu yazı ilk bölüm
- POC kodu ayrı bir yerde yayımlanmış olsa da, sağlanan metinde gerçek bağlantı URL’si yok
Unikernel ve WebAssembly’yi birlikte kullanma nedeni
- Uygulama geliştiricileri için unikernel’e port etme ciddi bir yük oluşturur
- Uygulamanın ve tüm bağımlılıklarının hedef unikernel’i desteklemesi gerekir
- Tüm uygulama yığını içinde yamalar gerekebilir
- Unikernel bakımcıları da rastgele uygulamaların sorunsuz çalışmasını sağlamak için çok enerji harcamak zorunda kalır
- Çünkü kullanıcı uygulamalarının hangi sistem primitive’lerini kullanacağını öngörmek zordur
- Buna karşılık Spin veya Spiderlightning gibi WebAssembly platformlarını hedeflediğinizde, çalışma zamanının sağlaması gereken işlev kümesi netleşir
- Spiderlightning senaryosunda uygulama, çalışma zamanından Key/Value depolama işlevi isteyebilir
- Host bu işlevi Redis ile de uygulasa Azure Cosmos DB ile de uygulasa, bu uygulama için saydamdır
- Aynı
.wasmmodülü farklı host uygulamaları üzerinde çalıştırılabilir
Hedef mimari
- Bir unikernel uygulaması WebAssembly modülleri çalıştırır ve Spiderlightning API kümesini desteklerse, aynı Spiderlightning uygulaması hem genel
slightçalışma zamanında hem de bu unikernel üzerinde çalıştırılabilir - Uygulama geliştiricisinin ek iş yapmasına gerek kalmaz; Wasm modülünün de nerede çalıştığını bilmesi gerekmez
- Karmaşıklık unikernel geliştiricisine yoğunlaşır; ancak uygulanması gereken kapsam, “tüm uygulamaların çalıştırılmasını desteklemekten” çok daha nettir
RustyHermit tabanlı uygulama
- Temel olarak RustyHermit seçildi
- Rust ile yazılmış bir unikernel’dir
- Rust nightly’ye dahil olduğu için normal bir Rust uygulaması yazmaya benzer bir geliştirme deneyimi sunar
- RustyHermit uygulaması derlemek görece anlaşılırdır
- Dokümantasyon biraz dağınık olsa da kalitelidir ve örnekler çok yardımcı olur
- Her Rust crate’inin RustyHermit üzerinde olduğu gibi çalışması beklenemez; bu kısıt POC geliştirmesini etkiledi
WebAssembly çalışma zamanı seçimi
- Tercih edilen Wasmtime, RustyHermit üzerinde derlenemedi
- Birçok bağımlılık
libcveya başka düşük seviyeli kütüphaneler bekliyor
- Birçok bağımlılık
- wasmer için de aynı sorun geçerli
- WebAssembly Micro Runtime da değerlendirildi; ancak “tam RustyHermit deneyimini” korumak için Rust ile yazılmış bir çalışma zamanı kullanmaya karar verildi
- Sonuçta saf Rust WebAssembly çalışma zamanı wasmi seçildi
- RustyHermit üzerinde iyi çalışıyor
- Tasarımı Wasmtime’dan ilham aldığı için mevcut bilginin büyük kısmı yeniden kullanılabildi
WebAssembly Component Model ve WIT
- Spiderlightning, WebAssembly Component Model önerisini kullanır
- WebAssembly guest’lerine işlev sağlar
- Host’un, WebAssembly guest’inin sunduğu işlevleri tüketmesini sağlar
- Host ile guest arasındaki iletişim, Wasm Interface Type ile tanımlanan türleri kullanır
- Demo, Component Model’i şu akışla kullanır
- Guest, host’tan HTTP sunucusu başlatmasını ister ve kaydedilecek HTTP route’larını ve dahili handler fonksiyonlarının adlarını iletir
http-servertürü kullanılır ve guest, host tarafından sağlanan işlevi kullanır
- Host, guest’in verdiği yönlendirme bilgileriyle gelen HTTP isteklerini işler
- HTTP handler, WebAssembly guest’inin dışa açtığı bir fonksiyondur
- Sunucu, guest tarafından sağlanan işlevi tüketir ve
http-handlertürüyle iletişim kurar
- Bazı HTTP handler’ları Key/Value depolama ile etkileşime girer
- Bu durumda da guest, host tarafından sağlanan işlevi kullanır ve bu işlev
keyvaluetürüyle tanımlanır
- Bu durumda da guest, host tarafından sağlanan işlevi kullanır ve bu işlev
- Guest, host’tan HTTP sunucusu başlatmasını ister ve kaydedilecek HTTP route’larını ve dahili handler fonksiyonlarının adlarını iletir
wit-bindgen’i genişletme ve demoyu çalıştırma
- Çeşitli WIT türlerinin her biri için guest tarafında SDK niteliğinde kod ve host tarafında uygulama kodu gerekir
- wit-bindgen,
.witdosyalarından host/guest kodu üreten bir CLI aracıdır - Bu POC’de yalnızca unikernel içinde host tarafı arayüzü uygulamak yeterlidir
wit-bindgentarafından üretilen kod, düşük seviyeli işleri yapmak için WebAssembly çalışma zamanını kullanır- Üretilen kod programlama diline ve host tarafındaki WebAssembly çalışma zamanına bağımlıdır
wasmi,wit-bindgentarafından desteklenmediği içinwit-bindgengenişletilerek wasmi’yi işlemesi sağlandı- Kod, wasmi dalındaki fork’ta bulunuyor
- Ardından Key/Value işlevi için host tarafı kod iskele haline getirildi ve basit bir host trait uygulaması eklendi
- Host kodu debug bilgisi yazdıracak düzeydeydi
- Bu durumda Spiderlightning projesinin keyvalue-demo örneği değişiklik yapılmadan çalıştırılabildi
Sonraki bölüme dair
- Unikernel uygulamasının Spiderlightning
http-serverdemosunu çalıştırdığı bir kayıt var - Sonraki bölümde Rust async, Redis ve bazı garip hatalar ele alınacak
1 yorum
Hacker News yorumları
Aklınıza hemen https://www.destroyallsoftware.com/talks/the-birth-and-death... gelmiyor mu?
Bir işletim sistemi korsanı olmayan biri unikernel istiyorsa, en sağlam yaklaşım ne olur?
Aklıma gelen seçenekler; uygulamayı bir Linux çekirdek modülü olarak yapıp normal çekirdeğin üstüne koymak ve kullanıcı alanını yok saymak, Linux’u agresif biçimde küçültüp kendi kodunu eklemek, GitHub’daki unikernel projelerinden başlamak ya da FreeBSD gibi başka bir işletim sistemini budayıp inceltmek.
Ağ kartına bağlı bir VM içinde bir x64 makinenin genel amaçlı hesaplama kaynağı gibi çalışması ve işlerin ağ üzerinden veri gönderilerek atanması fikri hoşuma gidiyor. Kullanıcı alanı daemon’larına göre daha zahmetli olduğu için şimdilik çok değerli görünmüyordu ama bir gün zaman bulursam işletim sistemi seviyesinde hacklemeye nereden başlamanın iyi olacağını merak ediyorum.
Unikernel Linux (UKL), Linux’un yapılandırılabilirliğinden yararlanma girişimi olarak başladı ve genel amaçlı işletim sistemlerinden uygulama ve donanıma özel unikernel’lere kadar uzanan bir çekirdeği hedefliyor. İlgili alanlar olarak io_uring ve eBPF de anılıyor; io_uring sistem çağrısı maliyetini dağıtıyor, eBPF ise sınırlı da olsa çekirdek alanında kod çalıştırmanın başka bir yolu.
Kod: https://github.com/unikernelLinux/ukl
UKL, Linux ve glibc için küçük bir yama seti; birçok programın değiştirilmeden unikernel olarak derlenmesini sağlıyor. Program, Linux çekirdeği ve son vmlinuz ile linklenip çekirdek alanında çalışıyor, bare metal ya da VM üzerinde boot edebiliyor ve Linux’un neredeyse tüm özellikleriyle sürücülerini kullanabiliyor.
/initdiye adlandırıp çekirdeğe bağlayarak boot etmek yeterli.Böylece uygulama PID 1 ve fiilen tek süreç oluyor; birkaç çekirdek iş parçacığı dışında istediğinizi yapabiliyorsunuz.
Birden fazla dil ve uygulama, x86/ARM64, QEMU/Firecracker destekliyor; ayrıca Linux’ta derlenmiş ELF’leri de unikernel olarak çalıştırabiliyor: https://unikraft.org/guides/bincompat
Discord adresi: https://unikraft.org/discord
OCaml öğrenmek istiyorsanız ve aynı zamanda unikernel de istiyorsanız, bu mümkün bir yol.
Ayrıntılar Unikraft belgelerinde görülebilir: https://unikraft.org/docs/concepts/design-principles#approac...
Güzel bir proje. WASM, daha en baştan sandbox ve taşınabilirlik düşünülerek tasarlandığı için hoşuma gidiyor.
90’larda JavaScript yerine WASM çıksaydı keşke; sanki WASM dünyayı ele geçirecekmiş gibi geliyor. En çok istediğim şey kalıcılık. Şu anda artık çalıştıramadığımız çok sayıda program var; eski oyunlar bunun başlıca örneği. Basit bir spesifikasyonun uzun ömürlü olma ihtimali daha yüksek, bu yüzden yeni özellik ekleme fikri biraz tedirgin edici ama binary’lerin geleceği ilginç görünüyor.
JS’nin başlangıçta tıklama işleyicileri veya form doğrulama gibi temel script işlerine sınırlanmasının bir nedeni vardı. Başka bir şeye dönüşmesi yalnızca JS’nin tasarım kusurlarından değil, zorla içine itildiği kullanım alanlarından da kaynaklandı. Tarayıcıyı bu tür uygulamaların dağıtım mekanizması olarak kullanmak, Tim Berners-Lee ya da Marc Andreesen’in hayal ettiği şeyden epey uzak.
O dönemde “ağ bilgisayardır” kampı, daha zengin uygulamalar için ince X istemcileri sunuyordu: https://en.wikipedia.org/wiki/Network_Computer
WASM konusunda hislerim karışık. Şu anda etrafında büyük bir hype ve yenilik perdesi var. Web tarayıcılarını yalnızca UI tasarımcıları ve geliştiricilerin o anda tercih ettiği dil fantezisinin görüntüleme penceresi gibi görmek, erişilebilirlik ve ekran okuyucular gibi alanlarda pek çok kötü sonuca yol açıyor.
Tarayıcı dışında WASM’i evrensel bir VM olarak ele alma yönelimi de aslında 30 yıl önce gidilmiş bir yol. JVM’nin yapmaya çalıştığı şey buydu ama artık “cool” görünmüyor sanırım.
Aradaki bölgenin nasıl görünmesi gerektiğini ya da neden istenmesi gerektiğini pek bilmiyorum. Ama gerçekçi olarak WASM muhtemelen belge içeriğini de yutacak ve o zaman reklam engelleyicilerle okuma modu büyük ihtimalle mahvolacak.
Buna gerçekten bayıldım. Bağlantısı verilen teknolojiler arasında daha önce görmediklerim de epey vardı; hepsini yer imlerine ekledim
Sırada hiper yöneticide WireGuard bağlantısı kurmayı denemek var. Bağlantı kurulumu Tailscale gibi bir şey üzerinden de geçebilir
Böylece bu makinedeki WebAssembly, şu makinedeki WebAssembly ile doğrudan konuşur. Süreçlerin rastgele bir konuma TCP bağlantısı açması yerine, iletilen yapılandırma ve yetkilere dayalı bir iletişim yapısı olur
Geç kaldım ama Zephyr’ı unikernel olarak çalıştırmayı düşünen oldu mu? https://docs.zephyrproject.org/latest/boards/x86/acrn/doc/in...
Özel WASM donanımı çıkması ne kadar sürer?
Ama “dışarıdan wasm gibi görünüp altta aslında RISC-V olan” türden bir şeyi birileri yapabilir gibi geliyor
Ama böyle donanımların her zaman niş kalacağını düşünüyorum. Çünkü genel amaçlı hazır donanım üzerinde WASM çalıştırmak çoğu durumda daha hızlı olacaktır. WASM zaten mevcut donanımda hızlı çalışsın diye tasarlandı ve genel amaçlı işlemcilerde ölçek ekonomisi çok daha güçlü
International Conference on Functional Programming de ilk başta Functional Programming and Computer Architecture adlı bir konferanstı, ama sonrasında Haskell gibi tembel değerlendirmeli fonksiyonel dilleri mevcut donanımda verimli derlemenin yolları bulundu
Lisp ve Java makinelerinde de benzer bir durum var. Artık bu tür şeyleri pek görmememizin nedenlerinden biri de derleyici teknolojisinin yetişmiş olması
Unikernel ve WASM için kullanım senaryoları neler olabilir?
Unikernel’in değeri bence 1) performans: gereksiz olanları atıp gerekli olanı “ring 0”a çekerek birkaç çevrim daha sıkıştırmak, 2) sadeleşme: gereksiz parçaları atarak karmaşıklığı azaltma ihtimali, 3) güvenlik: yine gereksiz olanları azaltarak saldırı yüzeyini değiştirme ihtimali
Ama bunun, bu forumdaki birçok kişinin yaptığı mikroservis ya da web uygulaması yazımına uygun bir yaklaşım olduğunu sanmıyorum. Kullanım alanı daha çok veritabanı, yük dengeleyici gibi altyapı bileşenleri üretmeye yakın
Bu yüzden bazı edge bulut sağlayıcıları Docker imajlarını çalıştırırken onları microVM’e dönüştürüyor
Ancak edge tarafında microVM içindeki WASM’ın, edge’in sandbox’lanmış WASM’ı ile rekabet etmesi zor olabilir. Sağlayıcı açısından ikincisine faydalı sınır özellikleri ve entegrasyonlar eklemek muhtemelen daha kolaydır
Uzun zaman önceki Birth & Death of Javascript'te “önceden haber verildiği” gibi, bir gün çekirdek alanında güvenli bir çöp toplama çalışma zamanı çalıştıran bir unikernel çıkacak ve böylece CPU'dan sanal bellek eşleme desteği kaldırılarak sistem daha hızlı hale getirilebilecekti
2014'te yazar JS ve asm.js'i öngörmüştü, ama şimdi bu yolun WASM gibi göründüğünü düşünüyor. Heyecan verici, haha
https://www.destroyallsoftware.com/talks/the-birth-and-death...
Ancak sonradan tek süreçli tarayıcıların bir güvenlik kâbusu olduğunu öğrendik ve günümüz tarayıcıları düzgün sandboxing için artık tek süreçli değil
Yine de o videonun doğruya ne kadar yaklaştığını görmek güzel, hangi açılardan yanıldığını görmek de ilginç
Tam olarak açıklaması zor ama bir yerden tanıdık geliyor. İpucu: onun adı da “J” ile başlıyor
https://en.wikipedia.org/wiki/JavaStation
Bir sürecin sanal kullanım miktarı, takas olmasa bile RSS'yi aşabilir ve işletim sistemi ile allocator birlikte çalışarak bunu genel durumda oldukça akıllıca yönetir
Bu yüzden bunu kaldırmanın otomatik olarak bir performans kazancı getireceğini söylemek zor. Özellikle de arada oldukça yavaş bir WASM VM katmanı varsa
Veritabanları gibi bazı uygulamalarda, unikernel üzerinde çalışmak ya da çekirdeğe daha yakın olup MMU'ya doğrudan erişmek büyük fayda sağlayabilir: https://github.com/tuhhosg/exmap & https://github.com/viktorleis/vmcache & https://www.cs.cit.tum.de/fileadmin/w00cfj/dis/_my_direct_up...
Ama POSIX standardını varsayan ya da çalışma ortamının modern, genel amaçlı bir bilgisayar gibi görüneceğini kabul eden genel uygulamalar için bu şüpheli. Sonuçta VMM katmanının yaptığı işlerin çoğunu kullanıcı kodunda yeniden yazmak gerekecek gibi görünüyor
JS motorları VMM'ye bağımlıdır ve WASM da çeşitli şekillerde öyledir. Gömülü sistemler dışındaki neredeyse tüm kayda değer programlar, ince biçimlerde VMM varsayımına dayanır. Özellikle microVM çevresindeki bazı VM teknolojileri de VMM kullanır ve unikernel ancak VM olarak kullanıldığında gerçekten anlam kazanır