- CoreOS – moderní clusterovaný OS pro datová centra (1) – Úvod a instalace
- CoreOS – moderní clusterovaný OS pro datová centra (2) – Etcd, distribuovaný state
- CoreOS – moderní clusterovaný OS pro datová centra (3) – Etcd a konzistence
- CoreOS – moderní clusterovaný OS pro datová centra (4) – Fleet
- CoreOS – moderní clusterovaný OS pro datová centra (5) – pokročilý Fleet
- CoreOS – moderní clusterovaný OS pro datová centra (6) – je to Docker orchestrátor?
Zatím jsme v seriálu o moderním operačním systému specializovaném pro kontejnerizované aplikace probrali možnosti samotného CoreOS a jeho klíčové komponenty pro distribuovaný konsenzus – Etcd. Dnes si ukážeme další distribuovanou vlastnost CoreOS, která na to navazuje – Fleet.
Flotila systémů aneb distribuovaný systemd
Mnoho moderních Linux distribucí používá systemd jako svůj init proces, tedy zavaděč a správce procesů v user space. CoreOS je nativně clusterovaný operační systém a přichází s distribuovanou verzí téhož. Fleet je systemd pro celý cluster. Jak si udržuje informace? Potřebovali bychom něco, co umožňuje distribuovaný consensus, service discovery a vysokou míru konzistence. Přimíná vám to něco? Jasně – na to CoreOS používá Etcd.
Nejprve se podívejme na instance CoreOS v clusteru.
core@core-01 ~ $ fleetctl list-machines MACHINE IP METADATA 89a25131... 172.17.8.102 - 9d9f5e11... 172.17.8.101 - d58d7490... 172.17.8.103 -
Vytvořme si soubor popisující službu, který bude v prakticky stejném formátu, jako normální systemd. Popíšeme v něm jeho pořadí v rámci init procesu (třeba musí se spustit až po něčem nebo potřebuje ke svému spuštění jiný běžící proces). V našem případě ale tento proces bude spuštění Docker kontejneru! V popisu služby musíme vysvětlit, jakým způsobem se má nastartovat a jak vypnout. V části ExecStartPre například vyčistíme případné zbytky předchozího spuštění (sestřelíme kontejner, vymažeme případně si předstáhneme image). V ExecStart spouštíme naší službu (docker run příkaz – abychom měli něco v logu spouštíme ping na loopback) a v ExecStop kontejner zastavujeme (docker stop). Výsledek uložte třeba do souboru mujtest.service:
[Unit] Description=MujTest After=docker.service Requires=docker.service [Service] TimeoutStartSec=0 ExecStartPre=-/usr/bin/docker kill mujtest ExecStartPre=-/usr/bin/docker rm mujtest ExecStartPre=/usr/bin/docker pull busybox ExecStart=/usr/bin/docker run --name mujtest busybox ping 127.0.0.1 ExecStop=/usr/bin/docker stop mujtest
Služba je připravena, můžeme ji nastartovat. Místo systemctl (zaveděč na úrovni jednoho OS) využijeme příkaz fleetctl, když mluvíme k celému clusteru.
core@core-01 ~ $ fleetctl start mujtest Unit mujtest.service inactive Unit mujtest.service launched on 89a25131.../172.17.8.102
Fleet spustil službu (v našem případě kontejner) na některém z nodů clusteru.
Vypišme si všechny takto spuštěné služby.
core@core-01 ~ $ fleetctl list-units UNIT MACHINE ACTIVE SUB mujtest.service 89a25131.../172.17.8.102 active running
Podívejme se do logu služby.
core@core-01 ~ $ fleetctl journal mujtest -- Logs begin at Tue 2016-03-29 04:16:14 UTC, end at Tue 2016-03-29 17:43:55 UTC. -- Mar 29 17:43:46 core-01 docker[2237]: 64 bytes from 127.0.0.1: seq=2189 ttl=64 time=0.096 ms Mar 29 17:43:47 core-01 docker[2237]: 64 bytes from 127.0.0.1: seq=2190 ttl=64 time=0.092 ms Mar 29 17:43:48 core-01 docker[2237]: 64 bytes from 127.0.0.1: seq=2191 ttl=64 time=0.194 ms Mar 29 17:43:49 core-01 docker[2237]: 64 bytes from 127.0.0.1: seq=2192 ttl=64 time=0.091 ms Mar 29 17:43:50 core-01 docker[2237]: 64 bytes from 127.0.0.1: seq=2193 ttl=64 time=0.126 ms Mar 29 17:43:51 core-01 docker[2237]: 64 bytes from 127.0.0.1: seq=2194 ttl=64 time=0.097 ms Mar 29 17:43:52 core-01 docker[2237]: 64 bytes from 127.0.0.1: seq=2195 ttl=64 time=0.130 ms Mar 29 17:43:53 core-01 docker[2237]: 64 bytes from 127.0.0.1: seq=2196 ttl=64 time=0.271 ms Mar 29 17:43:54 core-01 docker[2237]: 64 bytes from 127.0.0.1: seq=2197 ttl=64 time=0.122 ms Mar 29 17:43:55 core-01 docker[2237]: 64 bytes from 127.0.0.1: seq=2198 ttl=64 time=0.245 ms
Vysoká dostupnost
Systemd v Linux OS služby hlídá a pokud upadnou, restartuje je. V clusteru můžeme tuto situaci demonstrovat havárií celého nodu.
Abychom to nemuseli opravdu vypínat, shodíme pouze proces fleet (tedy efektivně odřízneme node z clusteru).
core@core-02 ~ $ sudo systemctl stop fleet
Po chvilce zjistíte, že se nám služba (v našem případě kontejner) rozjela na jiném nodu.
core@core-01 ~ $ fleetctl list-units UNIT MACHINE ACTIVE SUB mujtest.service 9d9f5e11.../172.17.8.101 active running
Nahoďte na našem nodu znovu Fleet. Ten se začlení do clusteru a zjistí, že tato služba už se mezitím rozběhla někde jinde – a to nechceme. Díky distribuovanému konsenzu v Etcd ovšem pochopí, že nevyhrál a službu si sestřelí. Ověřte to přes docker ps.
core@core-02 ~ $ sudo systemctl start fleet core@core-02 ~ $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Globální služby
A co když potřebujeme, aby služba byla globálního charakteru a běžela na každém nodu clusteru? Stačí ve službe definovat X-Fleet dodatečné parametry (ty už jsou Fleet specifické nad rámec systemd) a říct, že je globální. Fleet zajistí spuštění na všech nodech a tento desired state pro nás bude držet (když služba někde vypadne, spustí ji znova, když se objeví nový člen cluster, kde neběží, spustí ji tam).
Zkopírujme si soubor předchozí služby a tentokrát ji udělejme globální.
[Unit] Description=MojeGlobal After=docker.service Requires=docker.service [Service] TimeoutStartSec=0 ExecStartPre=-/usr/bin/docker kill MojeGlobal ExecStartPre=-/usr/bin/docker rm MojeGlobal ExecStartPre=/usr/bin/docker pull busybox ExecStart=/usr/bin/docker run --name MojeGlobal busybox ping 127.0.0.1 ExecStop=/usr/bin/docker stop MojeGlobal [X-Fleet] Global=true
Nastartujte službu global.
core@core-01 ~ $ fleetctl start global Unit global.service Triggered global unit global.service start
Kde všude běží? Všude 🙂
core@core-01 ~ $ fleetctl list-units UNIT MACHINE ACTIVE SUB global.service 89a25131.../172.17.8.102 active running global.service 9d9f5e11.../172.17.8.101 active running global.service d58d7490.../172.17.8.103 active running
Pojďme ji teď naopak globálně zlikvidovat.
core@core-01 ~ $ fleetctl destroy global Destroyed global.service