Service Fabric očima Kubernetes správce: architektura a kdy co použít

Pro moderní nasazování aplikací jsou dvě výborné technologie, které jsou obě v Azure, obě dostupné v on-premises a jiných cloudech, obě jsou (alespoň částečně a v budoucnu úplně) open source. Jedna je Service Fabric a druhá Kubernetes. Já jsem čas investoval především do té druhé, ale Service Fabric má některé zásadní unikátní výhody. Pokud už trochu znáte Kubernetes pojďme se na Service Fabric podívat jeho očima a terminologií. Dnes začneme pohledem na architekturu a pozicování.

Odkud přišel Service Fabric a odkud Kubernetes

Service Fabric je technologie, kterou si pro sebe vytvořil Microsoft před 10 lety pro provoz aplikací v Azure. Dnes je nasazen asi na třetině corů v Azure, Azure control plane ho využívá (4 service fabric ringy jsou i v Azure Stacku pod kapotou), běží na něm kritické, výkonné a spolehlivé služby jako je Azure SQL nebo Cosmos DB, Event Hub a další Azure služby, ale i SaaS aplikace jako je Intune nebo Cortana. Před pár lety se Microsoft rozhodl tento systém zpřístupnit i pro uživatele a to nejprve v Azure, ale později přišla i možnost nainstalovat si Service Fabric do vašich vlastních VM ať je máte kdekoli. V poslední době přišla i Linux verze Service Fabric. Celý systém byl uveřejněn jako open source s tím, že aktuálně jsou buildovací nástroje pro Linux verzi (Windows zdrojáky jsou, ale ještě nejsou veřejně dostupné nástroje na sestavení): https://github.com/Microsoft/service-fabric

Pod kapotou Service Fabric od začátku byla Windows a výrazné zaměření na .NET. Dnes už je Linux verze, nativní podpora Java i kontejnerů. Pokud ale jdete ze světa Windows a .NET, tam je Service Fabric hodně daleko.

Kubernetes je výrazně mladší a vznikl v Google, kde jeden ze tří zakladatelů, Brendan Burns, je dnes v Microsoftu a stojí za službou AKS, Cloud Shell a dnes i ARM. Google měl a stále má pro své interní účely proprietární systémy Borg a Omega, které jsou svou architekturou docela podobné Service Fabric. Kubernetes na to ale šel výrazně jinak a výsledkem je, že je pro běžné nasazení možná lépe pochopitelný a uživatelsky (alepsoň pro mě) velmi příjemný, což se ale podepisuje na jeho škálovatelnosti (ale to vás dost možná nemusí vůbec trápit).

Pod kapotou Kubernetes je od začátku Linux a zaměření na kontejnery, ať už v nich je cokoli. Microsoft pracuje na Kubernetes s Windows pod kapotou, ale v produkční verzi to ještě není. Pokud jdete ze světa Linuxu, kontejnerů případně .NET Core v Linux kontejnerech, tam je Kubernetes hodně daleko.

Service Fabric i Kubernetes mají velmi odlišnou historii, ale oba své schopnosti postupně doplňují. Kubernetes pracuje na podpoře Windows, Service Fabric se zas naučil Linux. Pro nové aplikace bych řekl, že to velmi brzy nebude limitující faktor.

Jednotka deploymentu

Service Fabric začal jako "velký" systém ještě před Dockerem a podobně jako proprietární Borg či open sourcový Apache Mesos byl postaven na procesech, ne kontejnerech. Pro nasazení do Service Fabric tedy kontejnery nepotřebujete, spouštíte jednotlivé procesy s aplikací respektive pokud se nepletu tak Service Fabric může spustit službu i jako třídu ve sdíleném host procesu. Aplikace jsou typicky integrované (o tom později), tedy využívají funkcí, které pro ně Service Fabric přímo nabízí. Můžete ale spustit i proces tak, že o Service Fabric vůbec neví - tzv. Guest Executable. Později Service Fabric přidal podporu pro kontejnery a ta je dnes plně k dispozici. Platí tedy, že co instance "service" (to je pojmenování jednotky nasazení), to proces nebo kontejner. Objekt service asi v Kubernetes nejlépe odpovídá objektům typu Deployment, DaemonSet nebo StatefulSet. Definujete množství replik, které chcete běžet, a tak podobně.

Kubernetes používá koncept Podů. Jednotkou nasazení je vždy jeden a více kontejnerů, které dohromady tvoří Pod. To umožňuje některé velmi zajímavé scénáře (třeba side-car pattern pro ambassador nebo adapter). Osobně se mi tento koncept velmi líbí, na druhou stranu je tu nutnost kontejnerizace, která pro klasické aplikace může znamenat nějaké obtíže do začátku. Samotný Pod nenabízí redundanci, takže nejpodobnější objektu service v Service Fabric bude asi Deployment (počet replik), DaemonSet (jedna instance na každém nodu - v Service Fabric definováno jako -1 instancí) případně StatefulSet (o tom později).

Osobně mám raději Pody v Kubernetes, je to dobrý koncept nad kterým se dá postavit prakticky cokoli a v Service Fabric mi chybí. Na druhou stranu schopnost vzít starý Windows exáč nebo .NET Framework aplikaci a jednoduše ji "bouchnout" do Service Fabric se určitě pro některé situace hodí.

Jednotka nasazení celé aplikace

Service Fabric dovoluje všechny součástky aplikace (service) uspořádat do ApplicationType. To je definice zahrnující všechny služby (třeba kontejnery), které aplikaci tvoří. Tento ApplicationType pak lze nasadit a parametrizovat. Životní cyklus celých aplikací je tedy přímo součástí Service Fabric.

Kubernetes sám v sobě koncept nasazování několika Deploymentů tvořících jednu aplikaci nemá. Nicméně existují nástroje nad ním, které to řeší, a které považuji za nutnou komponentu jakéhokoli vážné používání Kubernetes. Typickým řešením je tady Helm, který řeší něco velmi podobného jako ApplicationType v Service Fabric.

Tady musím říct, že Service Fabric má model nasazení aplikace od začátku dobře rozmyšlen, zatímco Kubernetes musel tuhle potřebu adresovat jinými projekty. Helm to v pohodě dorovnává, ale je vidět, že je to k tomu dodatečně přidaný (template jazyk nad Kubernetes).

Scheduler a orchestrační schopnosti

Service Fabric podobně jako třeba Borg na to jde opravdu ve velkém. Architektura je velmi distribuovaná a nemá jedno centrální místo pro state či API. Díky tomu dokáže neuvěřitelně škálovat a to podsatně víc, než Kubernetes. Nemá problém s tisíci nody a miliony kontejnerů (na tomto videu od 28. minuty se podívejte na cluster s 3500 nody, který nasadí 1 000 000 kontejnerů za dvě minuty: https://www.youtube.com/watch?v=OjhOZkql4uE). Samozřejmostí jsou věci jako filtrování co na jaký node smí přijít stejně jako affinita služeb (tohle nasaď vedle sebe apod.). Zásadní výhodou Service Fabric je schopnost velmi rychle detekovat selhání nodu, což je něco, co v Kubernetes může trvat i 5 minut (Kubernetes po chvilce přestane dávat na divný Node nové Pody, ale není si jistý, kdy je to opravdu mrtvé). Tohle je zásadní pro stavové aplikace, jak si řekneme později. Service Fabric má zabudovaný rebalancing. Pokud tedy přidáte nové nody rozloží na ně existující zátěž.

Service Fabric má architekturu udělanou tak, aby na něm mohl běžet Azure. Je to fascinující, ale pro vašich pár desítek či stovek serverů v clusteru to asi není nic tak důležitého (až na stavové aplikace viz později).

Kubernetes má koncept centrálního uložení state v Etcd (distribuovaná databáze s Raft mechanismem pro silnou konzistenci) kolem kterého se všechno točí. Také má API Server, který komunikuje se všemi Nody. To omezuje jeho maximální škálu, ale jak už jsem říkal, dost možná to pro váš případ vůbec nevadí. Kubernetes v současné produkční podobě neumí rebalancing, tedy po přidání nodu na něj automaticky přesunout existující zátěž (tomu se věnuje projekt descheduler, který je ale v ranné fázi).

K Service Fabric architektuře mám obrovský respekt, ale zejména pro stateless použití to pro velikosti clusterů mých zákazníků není oproti Kubernetes reálná výhoda. Nastavení scheduleru je komplexní v obou případech a je to spíše otázka zvyku. Rebalancing v plně produkčním stavu je určitě výhodou Service Fabric.

Geografická redundance

Service Fabric tím, že je hluboce distribuovaný je možné nasadit i geografickým způsobem. Disaster recovery (tedy řekněme druhý cluster běžící v jiném regionu a procesy na přenasazení aplikací do něj, když dojde k problémům) je velmi podobné jako v Kubernetes, ale redundanci Service Fabric je možné roztáhnout na regiony, nicméně za dodržení stejných konceptů. Potřebujete tedy minimálně 3 regiony, ideálně ale 5. V takovém modelu je havárie celého regionu pouze naprosto standardní událost stejně, jako třeba havárie jednoho nodu.

Kubernetes díky centralizovanější architektuře není dělaný na roztažení control plane po planetě (zejména díky limitům Etcd) a obvykle se tak nenasazuje. Spíše jedete dva nezávislé clustery a nad tím používáte nějakou logiku pro disaster recovery. Jedním z přístupů je Kubernetes Federation. To je koncept, který je dnes ve v1 a dál už se nerozvíjí a pracuje se na přepracování do v2, které ale není k dispozici (pokud vím něco podobného Service Fabric nenabízí). Druhý přístup je disaster recovery, tedy přenasazení jinde v případě potřeby.

Service Fabric je v tomto ohledu asi dál, ale zákazníků, kteřá potřebují nasadit jeden cluster přes 5 regionů není mnoho.

Networking

Oblast síťování je nesmírně důležitá. Ostatně žádný compute zdroj není k ničemu, když se do něj nedostanete síťově. V této oblasti je Service Fabric myslím postaven na klasičtějších konceptech a to mi vyhovuje méně, než Kubernetes. Všechny objekty (například kontejner) se nasazují tak, že komunikace mezi nimi probíhá přes vystavení (NAT) na node IP adresu. To s sebou nese správu portů. Tak například pokud chcete mít něco dostupné zvenku, musíte to nasadit na Node porty a balancovat to zvenku (Azure LB). Venkovní balancer ale musíte konfigurovat ručně a to včetně Health probe. Discovery služeb uvnitř clusteru probíhá na úrovni Name Service, která vyžaduje úpravu aplikace. Druhou možností je DNS, která ale vrátí konkrétní IP, nikoli virtuální IP vnitřního balanceru. Pro účely vnitřního balancování (virtuální IP na kterou se mohu připojit a ta to rozhazuje na instance třeba kontejneru, tak jak to dělá Kubernetes Service s ClusterIP) tady slouží Reverse Proxy (na rozdíl od Service v Kubernetes tahle funguje na L7, což má určitá specifika). Reverse Proxy by mohla připodobňovat Ingress v Kubernetes, ale není to dobré srovnání - nemáte (pokud vím) možnost ovlivnit routování a všechny služby jsou přes Reverse Proxy dostupné, tedy i ty, které nechcete publikovat ven (dát venkovnímu světu přístup na Reverse Proxy tedy nemusí být bezpečnostně vhodné). To celé pravděpodobně povede na vytvoření několika NodeType s tím, že jedna skupina VM je pro backend služby a druhá pro externě přístupné služby.

Na druhou stranu Service Fabric přináší některé komunikační koncepty ve formě SDK pro přímé zabudování do aplikace. Pokud používáte RPC, HTTP API nebo WCF, můžete využít Service Fabric SDK, které pro vás komunikaci zprostředkuje včetně retry logiky. Do vašeho kódu ale musíte tyto změny (SDK) zapracovat.

Kubernetes přinesl koncept IP per Pod s možností komunikovat mezi sebou s využitím například overlay sítě. To je skvělý nápad. Pokud chcete balancovat, Kubernetes Service vytvoří virtuální IP adresu, která se chová jako L4 balancer, což je rovněž velmi příjemné. Kromě toho je název Service resolvovatelný v clusteru přes DNS dotaz, který pak nevede na seznam instancí, ale virtuální adresu. Navíc pokud tuto Kubernetes Service chcete publikovat ven, dáte jí typ LoadBalancer a Kubernetes zajístí automatickou konfiguraci Azure LB. Jinak řečeno dokážete Service publikovat na interní či public IP aniž byste museli v Azure ručně cokoli nastavovat. Navíc Kubernetes díky konceptu Ingress počítá i s Reverse Proxy pro účely publikování třeba front end části aplikace. Můžete si dosadit libovolný počet certifikátů (ne jen jeden), namapovat aplikace na různá host name nebo URL cesty a máte plně pod kontrolou jaká URL kam vede. To všechno s využitím Kubernetes konstruktů. Dále můžete v Kubernetes implementovat síťové politiky (třeba s Calico či kube-router) nebo nasadit service mesh řešení jako je Istio.

Networking je zásadní oblast, ve které je myslím Kubernetes daleko dál. Je to asi tím, že vznikl později a díky tomu má koncept IP per Pod a nad tím postavené konstrukty Service a Ingress. Kubernetes je od začátku koncipován tak, že hostuje zapouzdřené kontejnery, zatímco Service Fabric je historicky o integraci SDK do aplikací a "guest" procesy a kontejnery přišly teprve později. Kubernetes na to tedy jde infrastrukturně, transparentně vůči aplikacím a to mě velmi vyhovuje.

SDK pro aplikace

Service Fabric je aplikační platforma a jako takový nabízí SDK do C# a Java, které můžete zakomponovat do svých aplikací. Pomáhá se service discovery, implementací stavových služeb a dokonce speciálními distribuovanými aplikačními modely jako je Reliable Actor model. Service Fabric tedy není jen o orchestraci procesů a kontejnerů, ale přináší i aplikační konstrukty.

Kubernetes nemá ambici zasahovat do aplikací a všechno řeší řekněme infrastrukturně. Pokud chcete pomoci třeba s budováním kontejnerů, může vám k tomu posloužit OpenShift, Visual Studio nebo Azure DevSpaces. Pokud potřebujete Actor model, musíte si takovou platformu nasadit nad Kubernetes sami, například s Akka, Actor4J nebo Orleans.

Schopnost aplikace napojit se přímo na Service Fabric může být velmi přínosná zejména, pokud potřebujete právě třeba Actor model. Deployment samostatně například s Orleans znamená dost práce navíc. Na druhou stranu většina projektů, s kterými se u zákazníků setkávám, tyto požadavky aktuálně nemá.

Stavové aplikace, například databáze

Snažil bych se většinu mikroslužeb stavět jako stateless. Perfektně to škáluje, snadno se s tím pracuje a je to ideální. Pokud nějaký stav potřebujete, jak na to? V zásadě máte tři možnosti. Externalizovat stav do PaaS v Azure, třeba do Cosmos DB. Druhou možností je držet stav uvnitř clusteru jednoduše s pomocí singletonu (bez HA). Třetí možnost je implementovat distribuovaný stav uvnitř clusteru.

Externalizovaný stav

Moje preference by byla primárně k variantě externalizovat stav ven do platformní služby v Azure. Ta je pro mne připravena a spravována Microsoftem, neřeším její upgrady, HA ani zálohování, nemusím ji sestavovat a trápit se s tím. Na výběr mám mimo jiné Azure SQL, MySQL, PostgreSQL, Cosmos DB (včetně různých API jako je SQL, Mongo DB, Cassandra, OData nebo Gremlin), Service Bus, Event Hub, Event Grid a řadu dalších.

Jak zdroje v Azure vytvořit a připojit na věci v clusteru? Buď to udělám ručně a poskytnu connection string aplikaci sám nebo bych využil Service Catalog. Jde o schopnost vyžádat si zdroj v Azure prostředky orchestrační platformy. Je to dostupné jak pro Service Fabric tak Kubernetes.

Má tato cesta nějaké nevýhody? Data jsou mimo cluster, takže musíme očekávat určitou latenci. Nic zásadního, ale oproti držení něčeho přímo v paměti to samozřejmě je podstatný rozdíl. Pro některé scénáře velmi náročné na latenci to tedy může být problém.

Pokud jde o externalizaci stavu je na tom Service Fabric a Kubernetes prakticky stejně. Tuto cestu doporučuji.

Stavové singletony

Druhou možností je stav držet uvnitř clusteru, ale pouze v jedné instanci (singleton). To má samozřejmě zásadní vliv na dostupnost, protože v případě havárie instance bude nějakou dobu trvat, než se z toho oklepe. Aby to bylo možné je nutné stav udržovat na storage systému (samozřejmě ale s možnou cache v paměti) mimo cluster samotný, například v Azure Files nebo Azure Disk, které jsou redundantní a vysoce dostupnou službou. Problém tedy neřešíme implementací vysoké dostupnosti, ale spíše schopnosti se z havárie dostat a pokračovat jinde.

Tady je ve výhodě Service Fabric, který má velmi rychlou detekci selhaného nodu a tím i schopnost rychle se překlopit. Zjednodušeně řečeno pokud dojde k výpadku, bude třeba v řádu 30 vteřin. Kubernetes má určitou prodlevu, než pochopí, že je Node odstřižen. Tato prodleva je daná architekturou a souvisí hodně s rizikem, že se vám pak instance spustí na dvou místech, což by poškodilo konzistenci dat (proto se musí získat opravdu jistota, že co se nehýbe je skutečně mrtvé). V kombinaci s Azure Disk, které trvá nějakou dobu než se přepojí, může takový výpadek v Kubernetes trvat klidně i 5 a více minut. Kubernetes tohle řeší konceptem StatefulSet, tedy zajistí, že Pod se objeví jinde se stejným jménem a stejným připojeným diskem, ale nějakou dobu to může trvat.

Singleton funguje jak v Service Fabric, tak v Kubernetes. V prvním případě bych se odvážil ho nasadit i pro produkční řešení tam, kde výpadek 30 vteřin nepovažuji za nějak kritický. Kubernetes může mít časy podsatně delší a to už je riziko, které bych do produkce nedával. Pro Dev/Test prostředí ale v pohodě.

Distribuovaný stav

To je oblast, ve které Service Fabric naprosto exceluje. Jeho součástí jsou totiž stavové služby. V zásadě vytvoříte třeba tři instance a v nich si v paměti držíte nějakou kolekci informací (IReliableDictionary). Service Fabric vám zajišťuje replikaci mezi nody (stav je replikován do paměti všech instancí) a silnou konzistenci (jen jeden je zapisovací, ale čtecí mohou být všechny). V zásadě jde tedy o silně konzistentní in-memory databázi běžící uvnitř clusteru. Výkonnostní senzace. Kromě jednoduché kolekce je k dispozici i fronta a perzistentní replikovaná vrstva pro Actor model. A to ještě není všechno. Service Fabric podporuje partition, či chcete-li sharding. Můžete tedy svoje data rozděli třeba na 9 partition podle nějakého klíče (zjednodušeně řešeno třeba podle prvního písmenka ve jménu) a v každé partition mít 3 instance (jeden zapisovací master a dvě kopie) a výkonnostně tak škálovat. To všechno je součástí Service Fabric. Dá se tedy říci, že distribuovaná databáze je přímo jeho součástí a běží na stejných zdrojích a nabízí tak fantastickou rychlost. To je důvod, proč je na této technologii postaven i Azure SQL a Cosmos DB.

Kubernetes sám o sobě žádné takové řešení nenabízí. StatefulSet je pouze infrastrukturní konstrukt, ale nějakou replikaci dat a podobné záležitosti si musíte vyřešit sami aplikačně. Můžete třeba nasadit Etcd v několika instancích Podů a tak zajistit transakční silně konzistentní ukládání dat jako v Service Fabric. Může to být třeba Galera cluster pro MySQL. Vždy je to ale složité a na vašich bedrech.

Pokud chcete držet stav co nejblíž svým aplikacím, to je nejzásadnější výhoda Service Fabric z mého pohledu.

Komunita

Oba systémy jsou dnes open source a mají silnou uživatelskou základnu. Pokud se ale podíváte na LinkedIn, najdete tam víc lidí, co se hrabou v Kubernetes, než v Service Fabric.

Přestože na oba systémy najdete na Internetu hodně zdrojů, pokud hledáte hotového člověka, je asi pravděpodobnější, že těch se znalostí Kubernetes bude víc.

Serverless clustery

Hitem a budoucností těchto platforem je cluster-less (nebo také můžeme říct server-less) deployment. Máte tedy control plane, ale jednotlivé kontejnery (ty jsou tady nutností) nespouštíte na nějakých nodech, které máte ve správě, ale přímo v Azure s využitím Azure Container Instances. Nemusíte tak řešit kapacitní plánování clusteru a přináší to spoustu velmi zajímavých výhod. Na druhou stranu jsou tu i nevýhody, například omezené hardwarové varianty (ACI například dnes nepodporuje GPU třeba pro nějaké machine learning počítání) a nedokonalá síťařina (podpora VNETů, balancerů apod.). Ale to je jen otázka času - server-less clustery jsou velmi zajímavá možnost. Nezaměňujme to ale s serverless ve smyslu Functions as a Service (například Azure Functions). Ty jsou o událostně řízeném programování bez serverů, zatímco tady mluvíme o orchestračním clusteru bez předem dedikovaných serverů. Azure Functions mimochodem můžete co do runtime nasadit na Service Fabric i Kubernetes.

Service Fabric tohle řeší produktem, který je aktuálně v preview: Service Fabric Mesh. Kubernetes to dělá přes projekt Virtual Kubelet a driver pro ACI. Ani jedno není ještě produkční, ale oba jdou tímto směrem.

Service Fabric i Kubernetes pracují na server-less konceptech.

Kdo tedy vyhrává?

Kdo je vítězem? Azure.

Azure nabízí perfektní služby na obou systémech - Azure Kubernetes Service, Azure Service Fabric i Service Fabric Mesh. Template pro oba systémy je dostupná pro Azure Stack (unmanaged varianta) a na veřejné roadmapě jsou vidět i managed varianty (například AKS, kdy control-plane je v Azure, ale aplikace běží na nodech v Azure Stack). Jak Service Fabric tak Kubernetes můžete rozjet i mimo cloud.

Hlavní výhody Service Fabric? Plně produkční podpora starších .NET Framework aplikací, speciální programovací modely včetně Actor model, rebalancing a velmi dobrá podpora stavových aplikací.

Hlavní výhody Kubernetes? Pefektní networking a kontejnerová strategie, spousta navazujících a rozšiřujících projektů, silná komunita a znalosti na trhu.

Ať už půjdete do Service Fabric nebo Kubernetes, Azure je skvělé místo pro jejich provoz a to včetně managed variant. V příštích článcích se podívám na některé konstrukty Service Fabric očima Kubernetes administrátora ve snaze najít podobnosti, rozdíly a sladit terminologii.



Nový Cold tier Azure Blob storage - kolik stojí premium, hot, cool, cold, archive Kubernetes
AKS má v preview spravované Istio - jak to souvisí s Open Service Mesh, proč to nebylo dřív, proč se ani tak netřeba plašit, ale proč je ambient mesh super? Kubernetes
Multi-tenant AKS - proč ano, proč ne a co udělat pro to, aby společné WC na chodbě tolik nevadilo Kubernetes
Azure, Kubernetes, FinOps a strategie účtování nákladů Kubernetes
Máte rádi Prometheus a Grafana pro váš Kubernetes? Jak na to všechno v plně managed formě v Azure? Kubernetes