Proč používat Kubernetes

S rostoucí popularitou Dockeru roste i popularita nástrojů pro orchestraci kontejnerů. Mezi všemi nástroji tak trochu vyčnívá Kubernetes. Zde je například vývoj zmínek o Kubernetes v otázkách na Stack Overflow:

Ke Kubernetes jsem se dostal při deploymentu nové verze portálu atoto.cz a ve srovnání s nástroji, které jsem používal předtím (Docker Cloud, Swarm, Docker Compose) mi připadal jako něco obřího a komplikovaného. S tím, jak přibývaly problémy, které bylo třeba řešit, začalo se ukazovat, jak je tato platforma promyšlená a proč je o ni stále rostoucí zájem.

V tomto článku se pokusím vypíchnout ty nejzásadnější body, které považuji za killer-features jsou to dle mého důvody, kvůli kterým stojí za to Kubernetes alespoň vyzkoušet.

Škálování, vysoká dostupnost

Klíčovou vlastností Kubernetes je to že sám řeší nasazování kontejnerů, sleduje jejich dostupnost a snaží se efektivně využít dostupné výpočetní kapacity a udržet tak aplikaci co nejdostupnější. Kubernetes vytváří abstrakci nad dostupným hradwarem, všechny připojené servery jsou dostupné jako by se jednalo o jeden stroj.

Využívá k tomu objekty, které mají různý účel. Na nejnižší úrovni se pracuje s pody, což je nejmenší samostatně nasaditelná část aplikace. V jejich rámci jsou provozovány kontejnery, které jsou vždy nasazeny společně. Pro optimální distribuci zátěže je možné definovat, kolik replik (podů) bude mít každá služba. Ty jsou pak rozloženy napříč jednotlivými servery (nody). V rámci clusteru pak může existovat více namespaců, lze tak nasazovat více nezávislých aplikací na jeden cluster.

Zero downtime deployment

Pokud nasazujete kontejnery do produkce, je třeba vymyslet mechanismus, jakým přepnout ze staré verze aplikace na novou. V případě samotného Dockeru je to poměrně obtížné - je třeba nakonfigurovat proxy, která směruje traffic na správný kontejner, poté nastartovat nový, následně přepnout proxy, pak ten starý odstranit... Nebo se prostě smířit s krátkým výpadkem.

V Kubernetes lze nasadit bez výpadku už jen pomocí správné konfigurace. Jednak je třeba nastavit readinessProbe (dokumentace). Pomocí této kontroly Kubernetes pozná, že je pod spuštěn (je nastartován web server atd.) a může na něj směřovat traffic. Druhou věcí je provedení Rolling Update. Pomocí tohoto nastavení Kubernetes ví, že má nejprve spouštět nové pody a průběžně vypínat ty staré, přičemž je definováno, kolik nejméně jich musí být v každou chvíli dostupných. Celá konfigurace deploymentu by pak vypadala následovně:

kind: Deployment  
apiVersion: extensions/v1beta1  
metadata:  
  name: rolling-update-deploy
spec:  
  replicas: 1
  template:
    metadata:
      labels:
        app: rolling-update-deploy
    spec:
      containers:
      - name: rolling-update-deploy
        image: gcr.io/google_containers/liveness
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
  minReadySeconds: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0

V tomto útržku kódu je důležité:

  • Je použit image gcr.io/google_containers/liveness, pravděpodobně ale bude chtít použít svůj vlastní
  • Kontrola probíhá zasláním HTTP požadavku na port 8080 a cestu /health, pro úspěch musí server vrátit kód 200
  • Rolling update je pomocí maxSurge a maxUnavailable nastaven tak, že je vždy jeden funkční pod k dispozici

Samotný update aplikace pak probíhá následovně

  • Je spuštěn nový pod
  • Každých 5 s se posílá HTTP request na :8080/healthz
  • Jakmile request vrátí kód 200, Kubernetes service směřuje komunikaci na nový pod
  • Starý pod je odstraněn

Sdílení konfigurací, hesel, klíčů

V samotném Dockeru je problém s tím, jak hesla, tokeny nebo klíče. Lze je buď přímo psát do kódu aplikace, nebo ukládat do ENV prověnných, vždy je ale trochu problematické je sdílet napříč kontejnery.

Kubernetes využívá pro tento účel secrets, což jsou konfigurační soubory uložené v clusteru. Ty je pak možné připojit do kontejnerů jako volume dále s nimi pracovat.

Persistence dat, volumes

Přestože je Docker ideální pro běh bezstavových služeb, nevyhneme se nutnosti perzistence dat. Příkladem jsou databáze, u kterých je žádoucí, aby data v nich uložená přežila restart kontejneru.

V kuberntes je možné definovat volumes, které mohou být následně do kontejneru připojeny. Data tak mohou být uloženy na úložišti mimo cluster a není třeba se starat o to, na kterém serveru fyzicky existují. Takovým úložištěm může být GCE Persistent Disk, AWS EBS Volume nebo některé z dalších podporovaných úložišť.

Cron jobs, tasks

V praxi je kromě stále běžících služeb (databáze nebo webový server) nutné nasazovat skripty, které jsou pouštěny jednou, nebo v pravidelných intervalech. Na fyzickém serveru je pro tento účel typicky využit Cron, ve světě kontejnerů je však situace složitější. Možností je instalovat Cron přímo do kontejnerů, Kubernetes však tuto funkcionalitu nabízí sám o sobě.

V případě jednou spouštěných příkazů lze využít Jobs. V nich je definován kontejner, který běží do svého ukončení. Jejich speciální variantou jsou Cron Jobs, které navíc obsahují definici časů, kdy se mají spouštět.

Komunita, dokumentace

Kubernetes disponuje obsáhlou dokumentací, která popisuje veškerou dostupnou funkčnost. Ta je doplněna řadou tutoriálů, které usnadňují první kroky při seznamování s Kubernetes.

Díky stále rostoucí populárnosti Kubernetes existuje řada návodů, které oficiální materiály doplňují a popisují řešení konkrétních problémů. Na GitHubu je pak možné sledovat rapidní vývoj této platformy a řešit případné problémy.

Nevýhody

Samozřejmě, že Kubernetes neřeší všechny problémy jen tak a je třeba počítat s jistými nevýhodami, nebo spíše vlastnostmi tohoto nástroje. Každý už si musí zvážit, jestli pro jeho situaci bude vhodné použít Kubernetes, nebo se poohlédnout po jiném řešení.

Komplexnost

Kubernetes je rozsáhlý systém a jaho pochopení zabere nějaký čas. S tím je třeba počítat. Dokumentace je sice přesná a lze v ní nalézt vše potřebné, nicméně i její načtení nějaký čas zabere.

Může se také zdát, že triviální spuštění jednoho kontejneru je složité oproti spouštění přes Docker Compose. To, co v docker-compose.yml zabere pár řádků znamená v konfiguraci Kubernetes vytvoření deploymentu s šablonou podu, vytvoření service, případně dalších pomocných objektů.

Problém s komplexností se snaží řešit projekt Rancher, který tvoří jakousi obálku nad API Kubernetes a umožňuje s ním komunikovat skrz pěkné uživatelské rozhraní, které je navíc kompatibilní s konfiguračními soubory pro Docker Compose.

Nekompatibilita s Docker CLI a Compose

S komplexností systému souvisí i to, že je Kubernetes nekompatibilní se soubory docker-compose.yml a příkazy jako docker run .... To nebylo možné použít vzhledem k množství funkcí a konfigurací, které má Kubernetes navíc. Příkaz kubectl se prostě chová jinak a musíte se jej naučit používat. To může být problém, pokud používáte Docker na lokále i na produkci - najednou je třeba mít vše dvakrát.

Řešení jsou vzásadě tři - buď se naučit pracovat s kubectl a jiným formátem konfiguračních soborů, což je dle mého nejlepší řešení. Další možností je spustit si Kubernetes lokálně pomocí Minikube, v tu chvíli používám jeden nástroj u sebe i na produkci. Třetí možností je opět komunikovat s Kubernetes skrz Rancher. a použít tak stávající soubory docker-compose.yml.

Cena

Posledním aspektem, který je třeba zvážit, je cena provozu clusteru. Pokud si Kubernetes spouštíte na svém železe, nic se nemění, samotný Kubernetes je zdarma. Ve chvíli, kdy se člověk rozhodne přejít do cloudu, je cena za provoz serverů prostě vyšší - je třeba zvážit, zda je cena za přechod adekvátní.

Konkrétně přechod do Google Cloudu má řadu pozitiv - cluster je spuštěn během chvíle, není třeba se starat o provoz master nodu, aktualizace. Vše je snadno napojitelné na zbytek cloudu (úložiště, load balancery), snadno lze nastavit automatické škálování. Cena oproti stejně výkonnému serveru hostovanému u levnějšího providera je ale vyšší.

Zdroje