GNU/Linux >> Znalost Linux >  >> Linux

Aktualizace kontejnerů Docker s nulovým nebo minimálním výpadkem

Předpokládejme, že provozujete službu v kontejneru a prostřednictvím jejich dockeru je k dispozici nová verze služby. V takovém případě byste chtěli aktualizovat kontejner Docker.

Aktualizace ukotvitelného kontejneru není problém, ale aktualizace dokovacího kontejneru bez prostojů je náročná.

Zmatený? Dovolte mi ukázat vám oba způsoby jeden po druhém.

Metoda 1:Aktualizace kontejneru dockeru na nejnovější image (výsledkem je výpadek)

Tato metoda se v zásadě skládá z těchto kroků:

  • Natáhněte nejnovější obrázek dockeru
  • Zastavte a odstraňte kontejner se starým obrazem dockeru
  • Vytvořte nový kontejner s nově vytaženým obrázkem dockeru

Chcete příkazy? Tady to je.

Vypište obrázky dockeru a získejte obrázek dockeru, který má aktualizaci. Získejte nejnovější změny tohoto obrázku pomocí příkazu docker pull:

docker pull image_name

Nyní získejte ID kontejneru nebo název kontejneru, ve kterém je spuštěn starší obrázek dockeru. K tomuto účelu použijte příkaz docker ps. Zastavte tento kontejner:

docker stop container_ID

A vyjměte nádobu:

docker rm container_id

Dalším krokem je spuštění nového kontejneru se stejnými parametry, jaké jste použili pro spuštění předchozího kontejneru. Věřím, že víte, jaké jsou tyto parametry, protože jste je vytvořili na prvním místě.

docker run --name=container_name [options] docker_image

Vidíte v tomto přístupu problém? Musíte zastavit běžící kontejner a poté vytvořit nový. To bude mít za následek výpadek běžící služby.

Výpadek, byť jen minutový, může mít velký dopad, pokud se jedná o kritický projekt nebo webovou službu s vysokou návštěvností.

Chcete znát bezpečnější a lepší přístup k tomuto problému? Přečtěte si další část.

Metoda 2:Aktualizace kontejneru dockeru v reverzním nastavení proxy (s nulové nebo minimální prostoje)

Pokud jste hledali přímočaré řešení, omlouvám se, že vás zklamu, ale nebude, protože zde budete muset nasadit své kontejnery v architektuře reverzního proxy pomocí Docker Compose.

Pokud chcete spravovat kritické služby pomocí kontejnerů dockerů, metoda reverzního proxy vám z dlouhodobého hlediska velmi pomůže.

Dovolte mi uvést tři hlavní výhody nastavení reverzního proxy:

  • Na stejném serveru můžete nasadit více veřejných služeb. Žádné blokování portu.
  • Server Let's Encrypt se postará o nasazení SSL pro všechny služby, všechny kontejnery.
  • Kontejnery můžete aktualizovat, aniž by to ovlivnilo spuštěné služby (pro většinu webových služeb).

Pokud se chcete dozvědět více, můžete se podívat na oficiální glosář Nginx, který zdůrazňuje běžné použití reverzního proxy a jeho srovnání s nástrojem pro vyrovnávání zatížení.

Máme skvělý podrobný návod na nastavení reverzního proxy serveru Nginx pro hostování více než jedné instance webových služeb běžících v kontejnerech na stejném serveru. Nebudu to tu tedy znovu rozebírat. Nejprve byste měli jít a nastavit své kontejnery pomocí této architektury. Věřte mi, stojí to za ty potíže.

V tomto tutoriálu jsem navrhl metodologii krok za krokem, která může být velmi užitečná ve vašich každodenních aktivitách DevOps. Tento požadavek může být nejen velmi nezbytný, když aktualizujete své kontejnery, ale také když chcete provést velmi nezbytnou změnu v kterékoli z vašich spuštěných aplikací, aniž byste obětovali neocenitelnou dobu provozuschopnosti.

Od této chvíle předpokládáme, že své webové aplikace spouštíte pod nastavením reverzního proxy, které by zajistilo, že přesměrování bude pro nový aktuální kontejner fungovat podle očekávání po změnách konfigurace, které se chystáme provést.

Nejprve uvedu kroky této metody a poté ukážu příklad ze skutečného života.

Krok 1:Aktualizujte soubor pro psaní dockeru

Nejprve musíte upravit existující soubor docker compose s číslem verze nejnovějšího obrázku. Lze jej zobrazit na Docker Hub, konkrétně v části aplikace „tags“.

Přesuňte se do adresáře aplikace a upravte soubor docker-compose pomocí textového editoru příkazového řádku. Zde jsem použil Nano.

[email protected]:~/web-app$ nano docker-compose.yml

V rámci services: , aktualizujte image: web-app:x.x.x s číslem nejnovější verze a uložte soubor.

Možná se divíte, proč místo ručního zadávání čísla verze nepoužít nejnovější značku? Udělal jsem to záměrně, protože jsem si všiml, že při aktualizaci kontejnerů může docházet k občasnému zpoždění nejnovější značky ve skutečném vyzvednutí nejnovější verze ukotvené aplikace. Když použijete číslo verze přímo, můžete vždy jistě.

Krok 2:Rozšiřte nový kontejner

Když použijete následující příkaz, vytvoří se nový kontejner na základě nových změn provedených v souboru docker compose.

[email protected]:~/web-app$ docker-compose up -d --scale web-app=2 --no-recreate

Všimněte si, že předchozí kontejner je stále v provozu. --scale příznak se používá k vytvoření dalších kontejnerů, jak je uvedeno. Zde web-app byl nastaven jako název služby pro webovou aplikaci.

I když zadáte škálování až na 2 kontejnery, --no-recreate zajistí, že bude přidán pouze jeden, protože váš starý kontejner již běží.

Chcete-li se dozvědět více o --scale a --no-recreate příznak, podívejte se na oficiální stránku dokumentace k docker-compose.

Krok 3:Odstraňte starý kontejner

Po kroku 2 počkejte asi 15–20 sekund, než se nové změny projeví, a poté odstraňte starý kontejner:

[email protected]:~/web-app$ docker rm -f old-web-app

V různých webových aplikacích se projevené změny po spuštění výše uvedeného příkazu v chování liší (o čemž se mluví jako o bonusovém tipu úplně dole v tomto tutoriálu).

Krok 4:Zmenšení na nastavení jednoho kontejneru jako dříve

V posledním kroku se ještě jednou zmenšíte na nastavení jednoho kontejneru:

[email protected]:~/web-app$ docker-compose up -d --scale web-app=1 --no-recreate

Tuto metodu jsem testoval s instancemi Ghost, WordPress, Rocket.Chat a Nextcloud. Kromě toho, že se Nextcloud na několik sekund přepne do režimu údržby, postup funguje velmi dobře pro ostatní tři.

Diskurz je však jiný příběh a může být v tomto případě velmi ošemetnou výjimkou kvůli svému hybridnímu modelu.

Sečteno a podtrženo:čím více webová aplikace při dockeringu využívá standardní postupy dockerů, tím pohodlnější bude každodenní správa všech kontejnerů webových aplikací.

Příklad ze skutečného života:Aktualizace živé instance Ghost bez prostojů

Jak jsem slíbil, ukážu vám příklad ze skutečného života. Ukážu vám, jak aktualizovat Ghost běžící v kontejneru dockeru na novější verzi bez jakéhokoli výpadku.

Ghost je CMS a používáme jej pro Linux Handbook. Zde zobrazený příklad je to, co používáme k aktualizaci naší instance Ghost provozující tento web.

Řekněme, že mám existující konfiguraci založenou na starší verzi na adrese /home/avimanyu/ghost :

version: '3.5'
services:
  ghost:
    image: ghost:3.36
    volumes:
      - ghost:/var/lib/ghost/content
    environment:
      - VIRTUAL_HOST=blog.domain.com
      - LETSENCRYPT_HOST=blog.domain.com
      - url=https://blog.domain.com
      - NODE_ENV=production
    restart: always
    networks:
      - net

volumes:
  ghost:
    external: true

networks:
  net:
    external: true

Všimněte si, že výše uvedená konfigurace dockeru je založena na již existující konfiguraci dockeru Nginx popsané zde, běžící v síti s názvem net . Jeho svazek dockeru byl také vytvořen ručně pomocí docker volume create ghost-blog .

Když to zkontroluji pomocí docker ps :

CONTAINER ID        IMAGE                                    COMMAND                  CREATED             STATUS              PORTS                                      NAMES
2df6c27c1fe3        ghost:3.36                             "docker-entrypoint.s…"   9 days ago          Up 7 days           2368/tcp                                   ghost_ghost-blog_1
89a5a7fdcfa4        jrcs/letsencrypt-nginx-proxy-companion   "/bin/bash /app/entr…"   9 days ago          Up 7 days                                                      letsencrypt-helper
90b72e217516        jwilder/nginx-proxy                      "/app/docker-entrypo…"   9 days ago          Up 7 days           0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   reverse-proxy

V této době psaní se jedná o starší verzi Ghost. Je čas jej aktualizovat na nejnovější verzi 3.37.1! Takže jsem to upravil v sekci obrázků jako:

version: '3.5'
services:
  ghost-blog:
    image: ghost:3.37.1
    volumes:
      - ghost-blog:/var/lib/ghost/content
    environment:
      - VIRTUAL_HOST=blog.domain.com
      - LETSENCRYPT_HOST=blog.domain.com
      - url=https://blog.domain.com
      - NODE_ENV=production
    restart: always
    networks:
      - net

volumes:
  ghost-blog:
    external: true

networks:
  net:
    external: true

Nyní k dobrému využití metody škálování:

[email protected]:~/ghost$ docker-compose up -d --scale ghost-blog=2 --no-recreate

S výše uvedeným příkazem zůstane starší kontejner nedotčen, ale připojí se nový se stejnou konfigurací, ale na základě nejnovější verze Ghost:

[email protected]:~/ghost$ docker-compose up -d --scale ghost-blog=2 --no-recreate
Pulling ghost (ghost:3.37.1)...
3.37.1: Pulling from library/ghost
bb79b6b2107f: Already exists
99ce436c3449: Already exists
f7bdc31da5f5: Already exists
7a1300b9ff59: Already exists
a495c68fa838: Already exists
6e362a39ec35: Already exists
b68b4f3c36f7: Already exists
41f8b02d4a71: Pull complete
3ecc736ea4e5: Pull complete
Digest: sha256:595c759980cd22e99037811397012908d89efb799776db222a4be6d4d892917c
Status: Downloaded newer image for ghost:3.37.1
Starting ghost_ghost-blog_1 ... done
Creating ghost_ghost-blog_2 ... done

Kdybych použil konvenční přístup s docker-compose up -d místo toho bych se nemohl vyhnout tomu, aby stávající kontejner byl založen na nejnovějším obrázku Ghost.

Rekreace zahrnuje odstranění staršího kontejneru a vytvoření nového na jeho místě se stejným nastavením. V tomto případě dojde k výpadku a stránka se stane nepřístupnou.

To je důvod, proč byste měli používat --no-recreate příznak při zvětšování.

Takže teď mám dva kontejnery spuštěné na základě stejné konfigurace duchů. Toto je klíčová část, kde se vyhýbáme prostojům:

[email protected]:~/ghost$ docker ps
CONTAINER ID        IMAGE                                    COMMAND                  CREATED             STATUS              PORTS                                      NAMES
f239f677de54        ghost:3.37.1                               "docker-entrypoint.s…"   2 minutes ago       Up 2 minutes        2368/tcp                                   ghost_ghost-blog_2
2df6c27c1fe3        ghost:3.36                             "docker-entrypoint.s…"   9 days ago          Up 7 days           2368/tcp                                   ghost_ghost-blog_1
89a5a7fdcfa4        jrcs/letsencrypt-nginx-proxy-companion   "/bin/bash /app/entr…"   9 days ago          Up 7 days                                                      letsencrypt-helper
90b72e217516        jwilder/nginx-proxy                      "/app/docker-entrypo…"   9 days ago          Up 7 days           0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   reverse-proxy

Všimněte si, že název staršího kontejneru je ghost_ghost-blog_1 . Zkontrolujte název své domény a zjistíte, že je stále přístupná na adrese blog.domain.com . Pokud obnovíte administrátorský panel Ghost, který je na adrese blog.domain.com/ghost po zvětšení by se stále pokoušel načíst, dokud neodstraníte starý kontejner:

[email protected]:~/ghost$ docker rm -f ghost_ghost-blog_1

Ale pro samotný blog Ghost neexistují žádné prostoje! Tímto způsobem tedy můžete zajistit nulové prostoje při aktualizaci blogů Ghost.

Nakonec zmenšete konfiguraci na původní nastavení:

[email protected]:~/ghost$ docker-compose up -d --scale ghost-blog=1 --no-recreate
Starting ghost_ghost-blog_2 ... done

Jak již bylo zmíněno dříve, po odstranění starých kontejnerů se změny projeví v příslušných webových aplikacích, ale zjevně se chovají odlišně kvůli různým návrhům aplikací.

Zde je několik postřehů:

Na WordPress :Ujistěte se, že jste přidali define( 'AUTOMATIC_UPDATER_DISABLED', true ); jako spodní řádek v souboru wp-config.php umístěném na /var/www/html a připojte /var/www/html/wp-content místo /var/www/html jako svazek. Podrobnosti naleznete zde. Po kroku 3 by administrátorský panel WordPress ukázal, že váš WordPress je aktuální, a požádá vás, abyste pokračovali a aktualizovali svou databázi. Aktualizace proběhne rychle bez výpadků na webu WordPress a je to!

Na Rocket.Chat :Admin>Info může trvat přibližně 15–20 sekund stránku, která ukáže, že používáte nejnovější verzi ještě před provedením kroku 3. Už žádné prostoje!

Na Nextcloud :Po kroku 2 se Nextcloud na několik sekund přepne do režimu údržby a poté znovu načte vaše soubory. V části Administration > Overview > Security & setup warnings , může se zobrazit varování jako:„Váš webový server není správně nastaven pro vyřešení problému „./well-known/carddav“. Důvodem je, že váš starý kontejner stále běží. Jakmile jej odstraníte pomocí kroku 3, toto upozornění již neexistuje. Ujistěte se, že tomu dáte nějaký čas, než přistoupíte na adresu URL Nextcloud, protože by mohla ukazovat chybu brány 502, dokud váš kontejner Nginx neuvidí nově škálovaný kontejner Nextcloud založený na nejnovější verzi.

Bonusové tipy

Zde je několik tipů a věcí, které je třeba mít na paměti při používání této metody.

Tip 1

Chcete-li udržet prostoje v různých aplikacích na minimu na nule, ujistěte se, že poskytujete dostatek času nově upraveným a aktuálním kontejnerům, aby je kontejnery Nginx mohly konečně potvrdit, než v kroku 2 odstraníte staré.

Než přejdete ke kroku 2 popsanému výše, je vhodné po provedení kroku 1 sledovat chování vaší aplikace ve vašem prohlížeči (jak jako obnovení stránky po přihlášení, tak jako nový přístup na stránku v soukromém okně prohlížeče bez mezipaměti).

Vzhledem k tomu, že každá aplikace je navržena jinak, toto opatření by se ukázalo jako velmi užitečné, než odložíte své staré kontejnery.

Tip 2

I když to může být velmi vynalézavá metoda aktualizace vašich kontejnerů na nejnovější verze aplikací, které provozují, mějte na paměti, že stejnou metodu můžete použít také k provádění jakýchkoli změn konfigurace nebo úprav nastavení prostředí, aniž byste čelili problémům s prostojem.

To může být zásadní, pokud musíte vyřešit problém nebo provést změnu, kterou můžete považovat za nezbytnou v živém kontejneru, ale nechcete ji přitom rušit. Poté, co provedete změny a budete si jisti, že je problém vyřešen, můžete ten starší snadno odstranit.

Sami jsme tomu čelili, když jsme zjistili, že rotace protokolu nebyla povolena v jednom z našich živých kontejnerů. Provedli jsme nezbytné změny, abychom to umožnili, a zároveň jsme se při této metodě vyhnuli jakýmkoli prostojům.

Tip 3

Pokud jste svůj kontejner konkrétně pojmenovali v souboru YML pomocí container_name , metoda nebude fungovat podle očekávání, protože zahrnuje vytvoření nového názvu kontejneru.

Tomuto konfliktu se můžete vyhnout tím, že přenecháte úkol pojmenování kontejneru na Docker Compose (provádí se automaticky podle jeho konvence pojmenování). Docker Compose pojmenovává své kontejnery jako directory-name_service-name_1 . Číslo na konci by se zvýšilo pokaždé, když je kontejner aktualizován (dokud z nějakého důvodu nepoužijete docker-compose down).

V případě, že již používáte službu pomocí vlastních pojmenovaných kontejnerů v souboru sestavy dockeru, použijte tuto metodu tak, že zakomentujete řádek (s předponou #), který obsahuje container_name uvnitř definice služby.

Po vytvoření nového kontejneru pro výše uvedené pomocí kroku 1, jak je popsáno v tomto tutoriálu, pro krok 2 bude název starého kontejneru (který nebyl zastaven, aby se předešlo prostojům) tak, jak byl zadán dříve pomocí container_name (lze také zkontrolovat pomocí `docker ps ` před odstraněním staré nádoby).

Naučili jste se něco nového?

Vím, že tento článek je trochu zdlouhavý, ale doufám, že pomůže naší komunitě DevOps při řešení problémů s výpadky produkčních serverů, na kterých běží dockerizované webové aplikace. Prostoje mají obrovský dopad na individuální i komerční úrovni, a proto bylo pokrytí tohoto tématu naprostou nutností.

Zapojte se prosím do diskuze a podělte se o své myšlenky, zpětnou vazbu nebo návrhy v sekci komentářů níže.


Linux
  1. Jak nainstalovat WordPress s Dockerem na Ubuntu

  2. Nainstalujte ModSecurity s Apache v kontejneru Docker

  3. 7 zábavných funkcí pro přenos kontejnerů/obrázků v Linuxu

  1. Jak nasadit kontejner nginx s Dockerem na Linode

  2. Jak vypsat Docker kontejnery

  3. Jak aktualizovat kontejner Docker s nulovým výpadkem

  1. Aktualizace nasazeného kontejneru na základě obrazu Dockeru

  2. Docker neaktualizuje změny v adresáři

  3. LXD kontejnery a sítě se statickou IP