Blue-Green Deployment pÔhimÔtetest

Selles artiklis korraldame bash, ssh, docker ja nginx sujuva veebirakenduse juurutamise. Blue-green deployment on tehnika, mis vĂ”imaldab rakendust kohe vĂ€rskendada, katkestamata ĂŒhtegi pĂ€ringut. See on ĂŒks zero downtime deployment strateegiaid ja sobib kĂ”ige paremini rakendustele, millel on ĂŒks instants, kuid vĂ”imalus laadida kĂ”rval teist, töövalmis instantsi.

Kujutage ette, et teil on veebirakendus, millega töötab aktiivselt palju kliente, ja seda ei saa mingil juhul paariks sekundiks peatada. Samas on teil hĂ€dasti vaja vĂ€lja tuua teegi uuendus, vigade parandamine vĂ”i uus Ă€ge funktsioon. Tavalistes olukordades oleks vajalik rakendus peatada, see vĂ€lja vahetada ja taas kĂ€ivitada. Docker'i puhul saab esmalt vahetada ja seejĂ€rel taaskĂ€ivitada, kuid siiski on periood, mil pĂ€ringud rakendusele ei saa töödeldud, kuna rakenduse esmakordne laadimine vĂ”tab tavaliselt aega. Ja mis siis, kui see kĂ€ivitub, kuid osutub mitte töötavaks? Selline ĂŒlesanne, lahendame selle minimaalsete vahenditega ja vĂ”imalikult elegantselt.

EELTUS: Suur osa artiklist on esitatud eksperimentaalses formaadis — nagu konsooli sessiooni salvestus. Loodan, et see pole liiga keeruline jĂ€lgida ning see kood dokumenteerib end piisavalt hĂ€sti. AtmosfÀÀri loomiseks, kujutage ette, et need pole lihtsalt koodilĂ”igud, vaid paber «raudsetelt» teletĂŒĂŒpijatelt.

Blue-Green Deployment pÔhimÔtetest

Huvitavad tehnikad, mida on keeruline lihtsalt koodi lugedes leida, on iga jaotise alguses kirjeldatud. Kui midagi jÀÀb arusaamatuks — googeldage ja kontrollige explainshell (vĂ€hemalt töötab see jĂ€lle, tĂ€nu telegrammi blokeeringu eemaldamisele). Kui midagi ei leia, kĂŒsige kommentaarides. TĂ€iendaksin hea meelega vastavat jaotist «Huvitavad tehnikad».

Alustame.

$ mkdir blue-green-deployment && cd $_

Teenuse

Teeme katse teenuse ja paneme selle konteinerisse.

Huvitavad tehnikad

  • cat < file-name (Here Document + I/O Redirection) — meetod, kuidas luua mitmerealine fail ĂŒhe kĂ€suga. KĂ”ik, mida bash loeb /dev/stdin selle reana ja kuni reale EOF salvestatakse file-name.
  • wget -qO- URL (explainshell) — vĂ€ljastada HTTP kaudu saadud dokument /dev/stdout (sarnane curl URL).

Prindikommando

Ma spetsiaalselt katkestan snipeti, et lisada Python’i esiletĂ”stmine. LĂ”pus tuleb veel ĂŒks selline tĂŒkk. Arvake, et nendes kohtades on paber lĂ”igatud, et toimetada highlightimise osakonda (kus kood tĂ”steti esile kĂ€sitsi markup'iga) ning seejĂ€rel need tĂŒkid liimitakse tagasi.

$ cat < uptimer.py
from http.server import BaseHTTPRequestHandler, HTTPServer
from time import monotonic

app_version = 1
app_name = f'Uptimer v{app_version}.0'
loading_seconds = 15 - app_version * 5

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            try:
                t = monotonic() - server_start
                if t &lt; loading_seconds:
                    self.send_error(503)
                else:
                    self.send_response(200)
                    self.send_header(&#039;Content-Type&#039;, &#039;text/html&#039;)
                    self.end_headers()
                    response = f&#039;<h2>{app_name} töötab {t:3.1f} sekundit.</h2>n'
                    self.wfile.write(response.encode('utf-8'))
            except Exception:
                self.send_error(500)
        else:
            self.send_error(404)

httpd = HTTPServer(('', 8080), Handler)
server_start = monotonic()
print(f'{app_name} (laeb {loading_seconds} sek.) käivitatud.')
httpd.serve_forever()
EOF

$ cat << EOF > Dockerfile
FROM python:alpine
EXPOSE 8080
COPY uptimer.py app.py
CMD [ "python", "-u", "./app.py" ]
EOF

$ docker build --tag uptimer .
Sending build context to Docker daemon  39.42kB
Step 1/4 : FROM python:alpine
 ---&gt; 8ecf5a48c789
Step 2/4 : EXPOSE 8080
 ---&gt; Using cache
 ---&gt; cf92d174c9d3
Step 3/4 : COPY uptimer.py app.py
 ---&gt; a7fbb33d6b7e
Step 4/4 : CMD [ "python", "-u", "./app.py" ]
 ---&gt; Running in 1906b4bd9fdf
Removing intermediate container 1906b4bd9fdf
 ---&gt; c1655b996fe8
Successfully built c1655b996fe8
Successfully tagged uptimer:latest

$ docker run --rm --detach --name uptimer --publish 8080:8080 uptimer
8f88c944b8bf78974a5727070a94c76aa0b9bb2b3ecf6324b784e782614b2fbf

$ docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                    NAMES
8f88c944b8bf        uptimer             "python -u ./app.py"   3 seconds ago       Up 5 seconds        0.0.0.0:8080-&gt;8080/tcp   uptimer

$ docker logs uptimer
Uptimer v1.0 (laebib 10 sek.) käivitus.

$ wget -qSO- http://localhost:8080
  HTTP/1.0 503 Teenus ei ole saadaval
  Server: BaseHTTP/0.6 Python/3.8.3
  Date: Sat, 22 Aug 2020 19:52:40 GMT
  Connection: close
  Content-Type: text/html;charset=utf-8
  Content-Length: 484

$ wget -qSO- http://localhost:8080
  HTTP/1.0 200 OK
  Server: BaseHTTP/0.6 Python/3.8.3
  Date: Sat, 22 Aug 2020 19:52:45 GMT
  Content-Type: text/html
<h2>Uptimer v1.0 töötab 15.4 sekundi jooksul.</h2>

$ docker rm --force uptimer
uptimer

Tagurpidi-proksi

Kuna meie rakendusel peab olema vĂ”imalus mĂ€rkamatult vahetuda, peab selle ees olema mingi muu element, mis peidab selle vahetuse. See vĂ”ib olla veebiserver. nginx ĂŒhes tagurpidi-proksi reĆŸiimis. Tagurpidi-proksi paigaldatakse kliendi ja rakenduse vahele. See vĂ”tab vastu pĂ€ringud klientidelt ja suunab need rakendusse ning rakenduse vastused suunatakse klientidele.

Rakenduse ja tagurpidi-proksi saab Dockeris siduda docker network. Nii ei pea isegi rakenduse konteinerile porti host-sĂŒsteemis suunama, see vĂ”imaldab maksimaalselt isoleerida rakendust vĂ€liste ohtude eest.

Kui tagurpidi-proksi asub teise hosti peal, tuleb loobuda docker network’ist ja siduda rakendus tagurpidi-proksiga hosti vĂ”rgu kaudu, suunates porta. rakendused parameeter --publish, nagu esmakordsel kĂ€ivitamisel ja tagurpidi-proksiga.

Reversproksi kĂ€ivitame pordil 80, kuna see on see, mida tuleks vĂ€lisse ĂŒhendustelt kuulata. Kui 80. port on Teie testkeskkonnas hĂ”ivatud, muutke parameetrit --publish 80:80 jĂ€rgnevaga --publish ANY_FREE_PORT:80.

Huvitavad tehnikad

Prindikommando

$ docker network create web-gateway
5dba128fb3b255b02ac012ded1906b7b4970b728fb7db3dbbeccc9a77a5dd7bd

$ docker run --detach --rm --name uptimer --network web-gateway uptimer
a1105f1b583dead9415e99864718cc807cc1db1c763870f40ea38bc026e2d67f

$ docker run --rm --network web-gateway alpine wget -qO- http://uptimer:8080
<h2>Uptimer v1.0 töötab juba 11,5 sekundit.</h2>

$ docker run --detach --publish 80:80 --network web-gateway --name reverse-proxy nginx:alpine
80695a822c19051260c66bf60605dcb4ea66802c754037704968bc42527bf120

$ docker ps
KONTROLLERI ID        PILDID               KÄSK                   LOODUD              STATUSE              PORTID                NIMED
80695a822c19        nginx:alpine        "/docker-entrypoint.…"   27 sekundit tagasi       Töötab 25 sekundit       0.0.0.0:80-&gt;80/tcp   reverse-proxy
a1105f1b583d        uptimer             "python -u ./app.py"     Umbes minut tagasi   Töötab Umbes minut   8080/tcp             uptimer

$ cat << EOF > uptimer.conf
server {
    listen 80;
    location / {
        proxy_pass http://uptimer:8080;
    }
}
EOF

$ docker cp ./uptimer.conf reverse-proxy:/etc/nginx/conf.d/default.conf

$ docker exec reverse-proxy nginx -s reload
2020/06/23 20:51:03 [notice] 31#31: signaaliprotsess käivitatud

$ wget -qSO- http://localhost
  HTTP/1.1 200 OK
  Server: nginx/1.19.0
  Kuupäev: Laupäev, 22 Aug 2020 19:56:24 GMT
  Sisu tüüp: text/html
  Ülekande kodeering: chunked
  Ühendus: keep-alive
<h2>Uptimer v1.0 töötab juba 104,1 sekundit.</h2>

Seamless deployment

Saame uue versiooni rakendusest (kahekordse kÀivituse jÔudluse kasvu) ja proovime seda sujuvalt juurutada.

Huvitavad tehnikad

  • echo 'my text' | docker exec -i my-container sh -c 'cat > /my-file.txt' — Kirjutada tekst my text faili /my-file.txt konteineri sees my-container.
  • cat > /my-file.txt — Kirjutada faili standardse sisendi sisu /dev/stdin.

Prindikommando

$ sed -i "s/app_version = 1/app_version = 2/" uptimer.py

$ docker build --tag uptimer .
Sending build context to Docker daemon  39.94kB
Step 1/4 : FROM python:alpine
 ---&gt; 8ecf5a48c789
Step 2/4 : EXPOSE 8080
 ---&gt; Using cache
 ---&gt; cf92d174c9d3
Step 3/4 : COPY uptimer.py app.py
 ---&gt; 3eca6a51cb2d
Step 4/4 : CMD [ "python", "-u", "./app.py" ]
 ---&gt; Running in 8f13c6d3d9e7
Removing intermediate container 8f13c6d3d9e7
 ---&gt; 1d56897841ec
Successfully built 1d56897841ec
Successfully tagged uptimer:latest

$ docker run --detach --rm --name uptimer_BLUE --network web-gateway uptimer
96932d4ca97a25b1b42d1b5f0ede993b43f95fac3c064262c5c527e16c119e02

$ docker logs uptimer_BLUE
Uptimer v2.0 (laeb 5 sek.) algas.

$ docker run --rm --network web-gateway alpine wget -qO- http://uptimer_BLUE:8080
<h2>Uptimer v2.0 töötab 23.9 sekundit.</h2>

$ sed s/uptimer/uptimer_BLUE/ uptimer.conf | docker exec --interactive reverse-proxy sh -c 'cat &gt; /etc/nginx/conf.d/default.conf'

$ docker exec reverse-proxy cat /etc/nginx/conf.d/default.conf
server {
    listen 80;
    location / {
        proxy_pass http://uptimer_BLUE:8080;
    }
}

$ docker exec reverse-proxy nginx -s reload
2020/06/25 21:22:23 [notice] 68#68: signaal protsess käivitati

$ wget -qO- http://localhost
<h2>Uptimer v2.0 töötab 63.4 sekundit.</h2>

$ docker rm -f uptimer
uptimer

$ wget -qO- http://localhost
<h2>Uptimer v2.0 töötab 84.8 sekundit.</h2>

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                NAMES
96932d4ca97a        uptimer             "python -u ./app.py"     Umbes minut tagasi   Toimib Umbes minut   8080/tcp             uptimer_BLUE
80695a822c19        nginx:alpine        "/docker-entrypoint.…"   8 minutit tagasi    Toimib 8 minutit    0.0.0.0:80-&gt;80/tcp   reverse-proxy

Praegu ehitatakse pilt otse serveris, mis nĂ”uab seal rakenduse allika olemasolu ja koormab serverit lisategevusega. JĂ€rgmine samm on pildi ehitamine eraldi masinas (nĂ€iteks CI-sĂŒsteemis) ja selle edastamine serverisse.

Piltide edastamine

Kahjuks ei ole mÔtet edastada pilte localhostilt localhostile, seega saab seda jaotist uurida ainult kahe Dockeriga hostiga. Minimaalsetes tingimustes nÀeb see vÀlja umbes nii:

$ ssh production-server docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

$ docker image save uptimer | ssh production-server 'docker image load'
Loaded image: uptimer:latest

$ ssh production-server docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
uptimer             latest              1d56897841ec        5 minutes ago       78.9MB

Meeskond docker save salvestab pildi andmed .tar arhiivi, st see kaalub umbes 1.5 korda rohkem, kui see vÔiks kaaluda tihendatud kujul. Nii et pigistame selle kokku ajas ja liikluses kokkuhoiu nimel:

$ docker image save uptimer | gzip | ssh production-server 'zcat | docker image load'
Loaded image: uptimer:latest

Ja veel, saab jÀlgida edastamisprotsessi (kuigi selleks on vajalik kolmas osapool):

$ docker image save uptimer | gzip | pv | ssh production-server 'zcat | docker image load'
25,7MiB 0:01:01 [ 425KiB/s] [                   <=    ]
Loaded image: uptimer:latest

NĂ”uanne: Kui vajate SSH serveriga ĂŒhendamiseks hulgaliselt parameetreid, ei pruugi te kasutada faili ~/.ssh/config.

Pildi edastamine lĂ€bi docker image save/load — see on kĂ”ige minimalistlikum meetod, kuid mitte ainus. On ka teisi:

  1. Container Registry (tööstuse standard).
  2. Ühenda docker daemon serveriga teisest hostist:
    1. Keskkonnamuutuja DOCKER_HOST.
    2. KÀskluse parameeter -H vÔi --host tööriistast docker-compose.
    3. docker kontekst

Teine viis (kolme rakendamisvariandiga) on hĂ€sti kirja pandud artiklis Kuidas juurutada eemal asuvatel Docker hostidel docker-compose’iga.

deploy.sh

Kogume nĂŒĂŒd kĂ”ik, mida me kĂ€sitsi tegime, kokku ĂŒhte skripti. Alustame peafunktsioonist ja seejĂ€rel vaatame teisi funktsioone, mida selles kasutatakse.

Huvitavad tehnikad

  • ${parameter?err_msg} — ĂŒks bash-maagiast (aka parameetri asendamine). Kui parameeter pole mÀÀratud, kuvada err_msg ja vĂ€ljutada koodiga 1.
  • docker --log-driver journald — vaikesena on dockeri logimise draiveriks tekstifail ilma rotatsioonita. Tootmis keskkonna jaoks on vajalik vahetada draiver nutikamaks, et vĂ€ltida logide kiiret kettaruumi tĂ€itmist.

Juurdusskript

deploy() {
    local usage_msg="Kasutamine: ${FUNCNAME[0]} pildi_nimi"
    local image_name=${1?$usage_msg}

    ensure-reverse-proxy || return 2
    if get-active-slot $image_name
    then
        local OLD=${image_name}_BLUE
        local new_slot=GREEN
    else
        local OLD=${image_name}_GREEN
        local new_slot=BLUE
    fi
    local NEW=${image_name}_${new_slot}
    echo "KĂ€ivitame '$NEW' asemele '$OLD'..."
    docker run 
        --detach 
        --restart always 
        --log-driver journald 
        --name $NEW 
        --network web-gateway 
        $image_name || return 3
    echo "Konteiner kÀivitatud. Kontrollime tervist..."
    for i in {1..20}
    do
        sleep 1
        if get-service-status $image_name $new_slot
        then
            echo "Uus '$NEW' teenus tundub korras. Vahetame pead..."
            sleep 2  # Veenduge, et teenus on valmis
            set-active-slot $image_name $new_slot || return 4
            echo "'$NEW' teenus on aktiivne!"
            sleep 2  # Veenduge, et kÔik pÀringud on töödeldud
            echo "Tapan '$OLD'..."
            docker rm -f $OLD
            docker image prune -f
            echo "Deployimine Ônnestus!"
            return 0
        fi
        echo "Uus '$NEW' teenus ei ole veel valmis. Ootan ($i)..."
    done
    echo "Uus '$NEW' teenus ei tÔusnud, tapame selle. Deployimine ebaÔnnestus T_T"
    docker rm -f $NEW
    return 5
}

Kasutatud funktsioonid:

  • ensure-reverse-proxy — Veendub, et pöördproksi teenus töötab (kasulik esimese deploy'i jaoks)
  • get-active-slot teenus_nimi — MÀÀrab, milline slot on aktiivne antud teenusele (BLUE vĂ”i GREEN)
  • get-service-status teenus_nimi deploy_slot — MÀÀrab, kas teenus on valmis sisendpĂ€ringute töötlemiseks
  • set-active-slot teenus_nimi deploy_slot — Muudab nginx konfiguratsiooni pöördproksi konteineris

JĂ€rjekorras:

ensure-reverse-proxy() {
    is-container-up reverse-proxy && return 0
    echo "Tagastamine reverse-proxy..."
    docker network create web-gateway
    docker run 
        --detach 
        --restart always 
        --log-driver journald 
        --name reverse-proxy 
        --network web-gateway 
        --publish 80:80 
        nginx:alpine || return 1
    docker exec --interactive reverse-proxy sh -c "> /etc/nginx/conf.d/default.conf"
    docker exec reverse-proxy nginx -s reload
}

is-container-up() {
    local container=${1?"Kasutus: ${FUNCNAME[0]} konteineri_nimi"}

    [ -n "$(docker ps -f name=${container} -q)" ]
    return $?
}

get-active-slot() {
    local service=${1?"Kasutus: ${FUNCNAME[0]} teenuse_nimi"}

    if is-container-up ${service}_BLUE && is-container-up ${service}_GREEN; then
        echo "Kollision tuvastatud! Peatamine ${service}_GREEN..."
        docker rm -f ${service}_GREEN
        return 0  # BLUE
    fi
    if is-container-up ${service}_BLUE && ! is-container-up ${service}_GREEN; then
        return 0  # BLUE
    fi
    if ! is-container-up ${service}_BLUE; then
        return 1  # GREEN
    fi
}

get-service-status() {
    local usage_msg="Kasutus: ${FUNCNAME[0]} teenuse_nimi juurutus_slot"
    local service=${1?usage_msg}
    local slot=${2?$usage_msg}

    case $service in
        # Lisa siia teie teenuste jaoks konkreetsed tervisekontrolli teed
        *) local health_check_port_path=":8080/" ;;
    esac
    local health_check_address="http://${service}_${slot}${health_check_port_path}"
    echo "Taotlemine '$health_check_address' 'web-gateway' docker vÔrgus:"
    docker run --rm --network web-gateway alpine 
        wget --timeout=1 --quiet --server-response $health_check_address
    return $?
}

set-active-slot() {
    local usage_msg="Kasutus: ${FUNCNAME[0]} teenuse_nimi juurutus_slot"
    local service=${1?$usage_msg}
    local slot=${2?$usage_msg}
    [ "$slot" == BLUE ] || [ "$slot" == GREEN ] || return 1

    get-nginx-config $service $slot | docker exec --interactive reverse-proxy sh -c "cat > /etc/nginx/conf.d/$service.conf"
    docker exec reverse-proxy nginx -t || return 2
    docker exec reverse-proxy nginx -s reload
}

Function get-active-slot vajab vÀikest selgitust:

Miks see tagastab numbri, mitte ei prindi vÀlja stringi?

Igal juhul kontrollime me vÀlja kutsuva funktsiooni puhul selle töö tulemust, ja kontrollida vÀljumiskoodi bash'i vahenditega on oluliselt lihtsam kui stringi. Lisaks sellele, on selle stringi saamine vÀga lihtne:
get-active-slot service && echo BLUE || echo GREEN.

Kas kolme tingimust on piisavalt, et eristada kÔiki olukordi?

Blue-Green Deployment pÔhimÔtetest

Isegi kahest piisaks, viimane on lihtsalt tÀielikkuse nimel, et mitte kirjutada muud.

Alles on mÀÀratlemata ainult funktsioon, mis tagastab nginx'i konfiguratsioonid: get-nginx-config service_name deployment_slot. Sarnaselt tervisekontrolliga, saab siia mÀÀrata mis tahes konfiguratsiooni mis tahes teenuse jaoks. Huvi pakkuda — ainult cat <<- EOF, mis vĂ”imaldab eemaldada kĂ”ik tabulatsioonid alguses. TĂ”si, vÀÀrika vormindamise hind on segatud tabulatsioonid ja tĂŒhikud, mis tĂ€nasel pĂ€eval loetakse vĂ€ga halba tooniks. Kuid bash surub tabulatsioonide kasutamise, ja nginx'i konfiguratsioonis oleks ka hea omada normaalset vormindamist. ÜhesĂ”naga, selline tabulatsioonide ja tĂŒhikute segu tundub tĂ”eliselt halvimast valikust parim lahendus. Kuid allpool olevas koodilĂ”igus te seda ei nĂ€e, kuna habr „teeb hĂ€sti”, muutes kĂ”ik tabulatsioonid 4 tĂŒhikuks ja tehes EOF mitte kehtivaks. Siin on selgelt nĂ€ha.

Et mitte kahte korda rÀÀkida, rÀÀgin kohe cat << 'EOF', mis tuleb edaspidi veel juttu. Kui kirjutada lihtsalt cat << EOF, siis heredoc sees toimub stringi interpoleerimine (muutujad ($foo), kĂ€su vĂ€ljakutsed ($(bar)) jne.), aga kui dokumenti lĂ”ppeva mĂ€rgi paneb ĂŒhte tĂŒĂŒpi jutumĂ€rgid, siis interpoleerimine keelatakse ja mĂ€rk $ vĂ€ljastatakse nii nagu on. Just see, mida vajate skripti sisestamiseks teise skripti sisse.

get-nginx-config() {
    local usage_msg="Kasutamine: ${FUNCNAME[0]} teenuse_nimi juurutuse_slot"
    local service=${1?$usage_msg}
    local slot=${2?$usage_msg}
    [ "$slot" == BLUE ] || [ "$slot" == GREEN ] || return 1

    local container_name=${service}_${slot}
    case $service in
        # Lisa oma teenuste jaoks siia spetsiifilised nginx seaded
        *) nginx-config-simple-service $container_name:8080 ;;
    esac
}

nginx-config-simple-service() {
    local usage_msg="Kasutamine: ${FUNCNAME[0]} proxy_pass"
    local proxy_pass=${1?$usage_msg}

cat << EOF
server {
    listen 80;
    location / {
        proxy_pass http://$proxy_pass;
    }
}
EOF
}

See ongi kogu skript. Ja siin on gisti see skript allalaadimiseks wget vÔi curl abil.

Parameetritega skriptide kÀitamine kauges serveris

On aeg sihtserveriga ĂŒhendust vĂ”tta. Seekord localhost sobib tĂ€iesti:

$ ssh-copy-id localhost
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
himura@localhost's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'localhost'"
and check to make sure that only the key(s) you wanted were added.

Oleme kirjutanud juurutusskripti, mis edastab eelnevalt loodud pildi sihtserverisse ja vahetab sujuvalt teenuse konteineri, kuid kuidas seda eemal oleval masinal kĂ€ivitada? Skriptil on argumendid, kuna see on universaalne ja suudab kohe mitu teenust ĂŒhe pöördpöitetoru alla juurutada (nginx'i seadistustega saab lahendada, millise URL-i all mis teenus on). Skripti ei saa serveris hoida, kuna siis ei saa me seda automaatselt uuendada (vigade parandamise ja uute teenuste lisamise eesmĂ€rgil), ja ĂŒldiselt, staatilisus = kurjus.

Lahendus 1: Hoida skripti siiski serveris, kuid kopeerida seda iga kord lĂ€bi scp. SeejĂ€rel ĂŒhendada lĂ€bi ssh ja kĂ€ivitada skript vajalike argumentidega.

Miinused:

  • Kaks tegevust ĂŒhe asemel
  • Koht, kuhu kopeerid, vĂ”ib olla olematu vĂ”i puudub sellele ligipÀÀs, vĂ”i skripti vĂ”ib kĂ€itada hetkel, kui toimub asendamine.
  • Soovitav on oma jĂ€lgedest koristada (skript eemaldada).
  • Juba kolm tegevust.

Lahendus 2:

  • Skriptis hoida ainult funktsioonide mÀÀratlusi ja mitte midagi kĂ€ivitada
  • KĂ€esoleva abil sed lisa funktsiooni kĂ”ne lĂ”ppu
  • Saada kĂ”ik ĆĄh kaudu pĂŒsikontakti (|)

Plussid:

  • TĂ”eliselt staateless
  • Ilma boilerplate'ita
  • Tunne end lahedalt

Teeme seda ainult ilma Ansible'ita. Jah, kÔik on juba vÀlja mÔeldud. Jah, rattas. Vaadake, kui lihtne, elegantne ja minimalistlik on see ratas:

$ cat < deploy.sh
#!/bin/bash

usage_msg="Usage: $0 ssh_address local_image_tag"
ssh_address=${1?$usage_msg}
image_name=${2?$usage_msg}

echo "Connecting to '$ssh_address' via ssh to seamlessly deploy '$image_name'..."
( sed "$a deploy $image_name" | ssh -T $ssh_address ) << 'END_OF_SCRIPT'
deploy() {
    echo "Yay! The '${FUNCNAME[0]}' function is executing on '$(hostname)' with argument '$1'"
}
END_OF_SCRIPT
EOF

$ chmod +x deploy.sh

$ ./deploy.sh localhost magic-porridge-pot
Ühendamine localhostiga...
VÀga hea! Funktsioon 'deploy' kÀivitub 'hut' peal argumendiga 'magic-porridge-pot'

Kuid me ei saa olla kindlad, et eemaloleval hostil on sobiv bash, seega lisame algusesse vÀikese kontrolli (see asenduseks shellbang):

if [ "$SHELL" != "/bin/bash" ]
then
    echo "Shell '$SHELL' ei ole 'deploy.sh' poolt toetatud. MÀÀrake '$USER@$HOSTNAME' jaoks '/bin/bash' shell."
    exit 1
fi

Ja nĂŒĂŒd on kĂ”ik pĂ€riselt:

$ docker exec reverse-proxy rm /etc/nginx/conf.d/default.conf

$ wget -qO deploy.sh https://git.io/JUURc

$ chmod +x deploy.sh

$ ./deploy.sh localhost uptimer
Saates gzipped pildi 'uptimer' 'localhost' kaudu ssh...
Laaditud pilt: uptimer:latest
Ühendumine 'localhost' kaudu ssh, et sujuvalt saada 'uptimer'...
Deploying 'uptimer_GREEN' asendamisel 'uptimer_BLUE'...
06f5bc70e9c4f930e7b1f826ae2ca2f536023cc01e82c2b97b2c84d68048b18a
Konteiner kÀivitatud. Tervise kontroll...
Pöördumine 'http://uptimer_GREEN:8080/' 'web-gateway' docker vÔrgus:
  HTTP/1.0 503 Teenus ei ole saadaval
wget: server tagastas vea: HTTP/1.0 503 Teenus ei ole saadaval
Uus 'uptimer_GREEN' teenus ei ole veel valmis. Ootame (1)...
Pöördumine 'http://uptimer_GREEN:8080/' 'web-gateway' docker vÔrgus:
  HTTP/1.0 503 Teenus ei ole saadaval
wget: server tagastas vea: HTTP/1.0 503 Teenus ei ole saadaval
Uus 'uptimer_GREEN' teenus ei ole veel valmis. Ootame (2)...
Pöördumine 'http://uptimer_GREEN:8080/' 'web-gateway' docker vÔrgus:
  HTTP/1.0 200 OK
  Server: BaseHTTP/0.6 Python/3.8.3
  Date: Sat, 22 Aug 2020 20:15:50 GMT
  Content-Type: text/html

Uus 'uptimer_GREEN' teenus tundub OK. Pea vahetamine...
nginx: konfiguratsiooni fail /etc/nginx/nginx.conf sĂŒntaks on ok
nginx: konfiguratsiooni fail /etc/nginx/nginx.conf test on edukas
2020/08/22 20:15:54 [notice] 97#97: signaaliprotsess kÀivitati
'Uptimer_GREEN' teenus on aktiivne!
'uptimer_BLUE' tapmine...
uptimer_BLUE
Kokku pÀÀstetud ruum: 0B
KÀivitamine Ônnestus!

NĂŒĂŒd saab avada http://localhost/ brauseris, kĂ€ivitada deploy' jĂ€lle ja veenduda, et see toimub sujuvalt lehte vĂ€rskendades jooksvalt.

Ärme unusta koristada pĂ€rast tööd :3

$ docker rm -f uptimer_GREEN reverse-proxy 
uptimer_GREEN
reverse-proxy

$ docker network rm web-gateway 
web-gateway

$ cd ..

$ rm -r blue-green-deployment

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster