Blue-Green Deployment lihtsustatud vormis

Selles artiklis korraldame bash, ssh, docker ja nginx katkematu veebirakenduse maailmakeerimise. Blue-green deployment on tehnika, mis vĂ”imaldab rakendust kiiresti uuendada, katkestamata ĂŒhtegi pĂ€ringut. See on ĂŒks zero downtime deployment strateegiatest ja sobib kĂ”ige paremini ĂŒhte instantsi kasutavatele rakendustele, kuid vĂ”imaldades samas kĂ”rval valmis teise instantsi kĂ€ivitamist.

Oletame, et teil on veebirakendus, millega töötab aktiivselt palju kliente, ning seda ei saa hetkekski peatada. Aga teil on hĂ€dasti vaja vĂ€lja anda raamatukogu uuendus, viga parandada vĂ”i uus ja lahe funktsioon aktiveerida. Tavalistes olukordades tuleb rakendust peatada, asendada see ja uuesti kĂ€ivitada. Docker'i puhul saab esmalt asendada ja seejĂ€rel kĂ€ivitada uuesti, kuid siiski toimub aeg, mille jooksul rakenduse pĂ€ringud ei jĂ”ua kohale, kuna tavaliselt kulub rakendusele algseks laadimiseks aega. Ja mis siis, kui see kĂ€ivitatakse, kuid osutub mittenĂ€htavaks? Niisiis, lahendame selle ĂŒlesande minimaalselt ja maksimaalselt elegantiselt.

DISCLAIMER: Suur osa artiklist on esitatud katsetuslikus vormingus — konsoolisessiooni salvestusena. Loodan, et see pole liiga raske mĂ”ista ja see kood dokumenteerib ennast piisavalt. AtmosfÀÀri loomiseks kujutage ette, et need ei ole lihtsalt koodilĂ”igud, vaid paber "raudtelegraafist".

Blue-Green Deployment lihtsustatud vormis

Huvitavaid tehnikaid, mida on keeruline lihtsalt koodi lugedes leida, kirjeldatakse iga jaotise alguses. Kui midagi jÀÀb arusaamatuks — googeldage ja kontrollige explainshell (Ă”nneks töötab see taas, seoses Telegrami blokeeringuga vabastamisega). Kui midagi ei googeldi — kĂŒsige kommentaarides. TĂ€iendame hea meelega vastavat jaotist "Huvitavad tehnikad".

Hakkame pihta.

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

Teenuseid

Loome katserakenduse ja paigutame selle konteinerisse.

Huvitavad tehnikaid

  • cat < file-name (Here Document + I/O Redirection) — viis luua mitmerealine fail ĂŒhe kĂ€suga. KĂ”ik, mida bash loeb /dev/stdin selle rea ja rea vahel EOF salvestatakse file-name.
  • wget -qO- URL (explainshell) — kuvab veebidokumendi HTTP kaudu /dev/stdout (analoog curl URL).

Prinditav

Ma lĂ”hestan teadlikult snippi, et sisaldada Pythonile esiletĂ”stmist. LĂ”pus on veel ĂŒks selline tĂŒkk. Pidage silmas, et nendes kohtades on paber lĂ”igatud, et see edastada esiletĂ”stmise osakonda (kus kood maaliti kĂ€sitsi esiletĂ”stmismarkeritega), ja seejĂ€rel need tĂŒkid liimiti tagasi.

$ cat < uptimer.py
import http.serverist 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} (laadimiseks {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 (loadib 10 sek.) started.

$ 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 juba 15.4 sekundit.</h2>

$ docker rm --force uptimer
uptimer

Tagasi-proksi

Kuna meie rakendus peab olema vĂ”imeline mĂ€rkamatult vahetuma, peab selle ees olema mingi muu entiteet, mis peidab selle vahetuse. See vĂ”ib olla veebiserver. nginx ja tagasi-proksi reĆŸiimis. Tagasi-proksi paigaldatakse kliendi ja rakenduse vahele. Ta vĂ”tab vastu pĂ€ringud klientidelt ja suunab need rakendusse ning rakenduse vastused suunatakse klientidele.

Rakendust ja tagasi-proksi saab siduda Dockeris, kasutades docker network. Nii saab rakenduse konteinerile isegi pordi edastamisest host-sĂŒsteemis loobuda, mis vĂ”imaldab rakendust maksimaalselt eraldada vĂ€listest ohtudest.

Kui tagasi-proksi elab teises hostis, tuleb loobuda docker network'ist ja siduda rakendus tagasi-proksiga hosti vÔrgus, edastades pordi. rakenduse parameetriga --publish, nagu esimesel kÀivitamisel ja nagu tagasi-proksiga.

Tagasi-proksi kÀivitame pordil 80, kuna just see entiteet peaks kuulama vÀliskeskkonda. Kui 80. port on teie test-hostis kinni, muutke parameetrit. --publish 80:80 . Tundub, et --publish ANY_FREE_PORT:80.

Huvitavad tehnikaid

Prinditav

$ 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 on käivitatud 11,5 sekundit.</h2>

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

$ docker ps
KONTO ID        PILDID               KÄSK                     LOOMINE           OLEK               PORTID               NIMED
80695a822c19        nginx:alpine        "\/docker-entrypoint.…"   27 sekundit tagasi        Üles 25 sekundit        0.0.0.0:80-&gt;80\/tcp   reverse-proxy
a1105f1b583d        uptimer             "python -u .\/app.py"      Umbes minut tagasi    Üles 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 [teade] 31#31: signaaliprotsess algas

$ wget -qSO- http://localhost
  HTTP/1.1 200 OK
  Server: nginx/1.19.0
  Kuupäev: Laup, 22 Aug 2020 19:56:24 GMT
  Sisu Tüüp: text/html
  Ülekanne: chunked
  Ühendus: püsiv
<h2>Uptimer v1.0 on käivitatud 104,1 sekundit.</h2>

Sujuv juurutamine

VÀlja lasta uus rakenduse versioon (kaks korda suurema kÀivitustÔhususega) ja proovida see sujuvalt juurutada.

Huvitavad tehnikaid

  • echo 'my text' | docker exec -i my-container sh -c 'cat > /my-file.txt' — Salvestada tekst my text faili /my-file.txt konteineris my-container.
  • cat > /my-file.txt — Salvestada faili sisu standardse sisenemise kaudu /dev/stdin.

Prinditav

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

$ docker build --tag uptimer .
Saadan ehituskonteksti Docker daemonile  39.94kB
Samm 1/4 : FROM python:alpine
 ---&gt; 8ecf5a48c789
Samm 2/4 : EXPOSE 8080
 ---&gt; Kasutades vahemälu
 ---&gt; cf92d174c9d3
Samm 3/4 : COPY uptimer.py app.py
 ---&gt; 3eca6a51cb2d
Samm 4/4 : CMD [ "python", "-u", "./app.py" ]
 ---&gt; Käitamine 8f13c6d3d9e7
Eemaldades vahepealse konteineri 8f13c6d3d9e7
 ---&gt; 1d56897841ec
Edukalt ehitatud 1d56897841ec
Edukalt märgistatud uptimer:latest

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

$ docker logs uptimer_BLUE
Uptimer v2.0 (laadib 5 sekundi jooksul) käivitatud.

$ 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: signaalprotsess käivitatud

$ 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
KONTEINERI ID        PILT               KOMANDI                  LOODUD              OLEK              PORTID                NIMED
96932d4ca97a        uptimer             "python -u ./app.py"     Umbes minut tagasi   Töös Umbes minut   8080/tcp             uptimer_BLUE
80695a822c19        nginx:alpine        "docker-entrypoint.…"   8 minutit tagasi        Töös 8 minutit        0.0.0.0:80-&gt;80/tcp   reverse-proxy

Sellel etapil ehitatakse pilt otse serveris, mis nĂ”uab seal rakenduse algkoodide olemasolu ning koormab serverit liigse tööga. JĂ€rgmine samm on eraldada pildi ehitamine eraldi masinasse (nĂ€iteks CI-sĂŒsteemi) ja seejĂ€rel edasi saata see serverisse.

Piltide edastamine

Kahjuks ei ole mÔtet kopeerida pilte localhost'ist localhost'i, seega saab seda jaotist testida ainult kahe Dockeriga hostiga. Minimaalselt 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, seega kaalub see umbes 1,5 korda rohkem, kui ta vÔiks kaaluda kompressitud kujul. Pigem tihendame selle ajakulu ja liikluse sÀÀstmiseks:

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

Ja veel, saate jÀlgida edastusprotsessi (kuid selleks on vajalik kolmanda osapoole utiliit):

$ 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 teile on SSH serveriga ĂŒhenduse loomiseks vajalik palju parameetreid, siis vĂ”ib-olla ei kasuta te faili ~/ .ssh / config.

Pildi edastamine lÀbi docker image save/load on kÔige minimalistlikum meetod, kuid mitte ainus. On ka teisi:

  1. Container Registry (tööstusstandard).
  2. Ühendage Docker daemon'i serveriga teisest hostist:
    1. Keskkonnamuutuja DOCKER_HOST.
    2. KÀskluse parameeter -H vÔi --host tööriista version: '1' services: simplesample-sonar: image: sonarqube:lts ports: - 9001:9000 - 9092:9092 network_mode: bridge.
    3. docker context

Teine meetod (kolme erineva variandi rakendamiseks) on hÀsti kirjeldatud artiklis Kuidas kasutada docker-compose'i kaug-Docker hostides.

deploy.sh

NĂŒĂŒd kogume kĂ”ik, mida oleme kĂ€sitsi teinud, ĂŒheks skriptiks. Alustame peafunktsioonist ja seejĂ€rel vaatame teisi, mida seal kasutatakse.

Huvitavad tehnikaid

  • ${parameter?err_msg} on ĂŒks bash-maagia nĂ”idustest (aka parameter substitution). Kui parameter ei ole mÀÀratletud, vĂ€ljastage err_msg ja vĂ€ljuge koodiga 1.
  • docker --log-driver journald on vaikimisi dockeri logide kĂ€itaja tekstifail ilma igasuguse ridade vahetamiseta. Sellise lĂ€henemisega tĂ€idetakse logid kiiresti kogu ketas, seega tuleb tootmiskeskkonnas vahetada kĂ€itaja intelligentsema vastu.

Skripti juurutamine

deploy() {
    local usage_msg="Kasutus: ${FUNCNAME[0]} image_name"
    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Ă€ivitamine '$NEW' '$OLD' asemele..."
    docker run 
        --detach 
        --restart always 
        --log-driver journald 
        --name $NEW 
        --network web-gateway 
        $image_name || return 3
    echo "Konteiner kÀivitatud. Kontrollin tervist..."
    for i in {1..20}
    do
        sleep 1
        if get-service-status $image_name $new_slot
        then
            echo "Uus '$NEW' teenus nÀib töötavat. Pea vahetus..."
            sleep 2  # Veendu, et teenus on valmis
            set-active-slot $image_name $new_slot || return 4
            echo "'$NEW' teenus on aktiivne!"
            sleep 2  # Veendu, et kÔik pÀringud on töödeldud
            echo "Tapan '$OLD'..."
            docker rm -f $OLD
            docker image prune -f
            echo "Paigaldamine Ônnestus!"
            return 0
        fi
        echo "Uus '$NEW' teenus ei ole veel valmis. Ootan ($i)..."
    done
    echo "Uus '$NEW' teenus ei kÀivitunud, tapame selle. Paigaldamine ebaÔnnestus T_T"
    docker rm -f $NEW
    return 5
}

Kasutatud funktsioonid:

  • ensure-reverse-proxy — Veendub, et pöördproksi teenus töötab (kasulik esmakordsel paigaldamisel)
  • get-active-slot service_name — MÀÀrab, milline slot on praegu aktiivne antud teenuse jaoks (BLUE vĂ”i GREEN)
  • get-service-status service_name deployment_slot — MÀÀrab, kas teenus on sissetulevate pĂ€ringute töötlemiseks valmis
  • set-active-slot service_name deployment_slot — Vahetab nginx-i seadistuse pöördproksi konteineris

JĂ€rjekorras:

ensure-reverse-proxy() {
    is-container-up reverse-proxy && return 0
    echo "Deploying 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?"Usage: ${FUNCNAME[0]} container_name"}

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

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

    if is-container-up ${service}_BLUE && is-container-up ${service}_GREEN; then
        echo "Collision detected! Stopping ${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="Usage: ${FUNCNAME[0]} service_name deployment_slot"
    local service=${1?usage_msg}
    local slot=${2?$usage_msg}

    case $service in
        # Add specific healthcheck paths for your services here
        *) local health_check_port_path=":8080/" ;;
    esac
    local health_check_address="http://${service}_${slot}${health_check_port_path}"
    echo "Requesting '$health_check_address' within the 'web-gateway' docker network:"
    docker run --rm --network web-gateway alpine 
        wget --timeout=1 --quiet --server-response $health_check_address
    return $?
}

set-active-slot() {
    local usage_msg="Usage: ${FUNCNAME[0]} service_name deployment_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
}

Funktsioon get-active-slot vaja vÀikeste selgitustega:

Miks ta tagastab numbri, mitte vÀljundab stringi?

Oleme ikka kutsuva funktsiooni poolt tulemuse kontrollitav, ja eksituskoode bash'is on palju lihtsam kontrollida kui stringi. Lisaks, saada string ilmselt on vÀga lihtne:
get-active-slot service && echo BLUE || echo GREEN.

Kas tÔesti on kolme tingimuse jaoks piisav, et eristada kÔiki olekuid?

Blue-Green Deployment lihtsustatud vormis

Kahega piisab, viimane on siin lihtsalt selleks, et mitte kirjutada muul juhul.

Pole veel mÀÀratud funktsioon, mis tagastab nginx konfiguratsioonid: get-nginx-config service_name deployment_slot. Sarnaselt tervise kontrollile vĂ”ib siin mÀÀrata igasuguseid konfigureerimise igale teenusele. Huvi pakkudes — ainult cat <<- EOF, mis aitab eemaldada kĂ”ik tabulaatorid alguses. TĂ”si, viisakusformaatimise hind on segatud tabulaatorid ja tĂŒhikud, mis tĂ€napĂ€eval loetakse vĂ€ga halbadeks kombedeks. Kuid bash sunnib tabulaatoreid, ja nginx-i konfiguratsioonis oleks ka soovitav omada korrektset vormindust. LĂŒhidalt, siin tundub segamine tabulaatorite ja tĂŒhikutega tĂ”esti parima halva lahendusena. Siiski, allolevas snippes Te seda ei nĂ€e, kuna habr "teeb hĂ€sti", muutes kĂ”ik tabulaatorid neljaks tĂŒhikuks ja tehes EOF-i mitte kehtivaks. Aga siin on selgelt nĂ€ha.

Et mitte kaks korda ei rÀÀkida, rÀÀgin kohe cat << 'EOF', mis tuleb veel juttu. Kui kirjutada lihtsalt cat << EOF, siis heredoc-is toimub rea intervallimine (muutujad avatakse ($foo), kĂ€skude kutsumised ($(bar)) jne., ja kui panna dokumendi lĂ”pu mĂ€rk ĂŒhtegi tsiteerimisnurka, siis intervallimine aktiveeritakse ja sĂŒmbol $ vĂ€ljastatakse nagu on. See ongi vajalik skripti sisestamiseks teise skripti sisse.

get-nginx-config() {
    local usage_msg="Kasutamine: ${FUNCNAME[0]} teenuse_nimi juurutus_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 spetsiifilised nginx konfiguratsioonid siia
        *) 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 on kogu skript. Ja siin gisti selle skripti allalaadimiseks wget vÔi curl kaudu.

Parameetriseeritud skriptide tÀitmine kaugserveris

On aeg sihtserverisse siseneda. Seekord localhost sobib hÀsti:

$ ssh-copy-id localhost
/usr/bin/ssh-copy-id: INFO: ĂŒritatakse sisse logida uute vĂ”tmete kaudu, et eemaldada kĂ”ik, mis on juba installitud
/usr/bin/ssh-copy-id: INFO: 1 vĂ”tme(ite) jÀÀb paigaldada -- kui Te nĂŒĂŒd ette seatakse, on see uute vĂ”tmete installimiseks
himura@localhost'i parool: 

VÔtmeid on lisatud: 1

NĂŒĂŒd proovige masinasse siseneda, kasutades: "ssh 'localhost'"
ja kontrollige, et ainult need vÔtmed, mida soovisite, on lisatud.

Me oleme kirjutanud rakenduskava, mis edastab eelnevalt loodud pildi sihtserverisse ja sujuvalt asendab teenuse konteineri, aga kuidas seda teostada kaugmasinal? Skriptil on argumendid, kuna see on universaalne ja vĂ”ib samaaegselt paigutada mitu teenust ĂŒhele pöördproksile (nginx konfiguratsiooni saab lahendada, millise URL-i kaudu teenust kĂ€ituda). Skripti ei saa serverisse salvestada, kuna siis me ei saa seda automaatselt uuendada (veaparanduste ja uute teenuste lisamise eesmĂ€rgil) ja ĂŒldiselt: olek = kurjus.

Lahendus 1: Hoidke skripti serveris, kuid kopeerige seda iga kord lĂ€bi scp. Siis ĂŒhendage kaudu ssh ja kĂ€itage skripti koos vajalike argumentidega.

Miinused:

  • Kaks toimingut ĂŒhe asemel
  • Koht, kuhu te kopeerite, ei pruugi olemas olla, vĂ”i sellele ei pruugi ligi pÀÀseda, vĂ”i skript vĂ”ib kĂ€ivituda asendamise hetkel.
  • Soovitav on jĂ€tta endale puhtaks (kustutada skript).
  • Kokku on juba kolm toimingut.

Lahendus 2:

  • Hoida skriptis ainult funktsioonide mÀÀratlemised ja tegelikult mitte midagi kĂ€ivitada
  • EL-i abil sed lisada lĂ”ppu funktsiooni kutse
  • Saata kĂ”ik see otse shh kaudu pipe'i kaudu (|)

Plussid:

  • TĂ”eliselt olekuta
  • Ei mingeid mallide elemente
  • Tunneb end Ă€gedalt

Aga tehkem seda ilma Ansible'ita. Jah, kÔik on juba vÀlja mÔeldud. Jah, jalgratas. Vaadake, kui lihtne, elegantne ja minimalistlik jalgratas:

$ 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...
Jei! 'deploy' funktsioon kÀivitub 'hut' peal argumendiga 'magic-porridge-pot'

Kuid me ei saa olla kindlad, et eemal oleval hostil on adekvaatne bash, nii et lisame algusesse vÀikese kontrolli (see asendab shellbang):

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

Ja nĂŒĂŒd on kĂ”ik tĂ”eliselt:

$ 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 gzip'd pildi 'uptimer' 'localhost' kaudu ssh...
Laetud pilt: uptimer:latest
Ühendamine 'localhost' kaudu ssh, et sujuvalt seadistada 'uptimer'...
Seadistamine 'uptimer_GREEN' 'uptimer_BLUE' asemele...
06f5bc70e9c4f930e7b1f826ae2ca2f536023cc01e82c2b97b2c84d68048b18a
Konteiner kÀivitatud. Tervise kontrollimine...
Taotlemine '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. Ootamine (1)...
Taotlemine '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. Ootamine (2)...
Taotlemine 'http://uptimer_GREEN:8080/' 'web-gateway' docker vÔrgus:
  HTTP/1.0 200 OK
  Server: BaseHTTP/0.6 Python/3.8.3
  KuupÀev: la, 22 Aug 2020 20:15:50 GMT
  Sisu tĂŒĂŒp: text/html

Uus 'uptimer_GREEN' teenus nÀib olevat OK. Pead vahetama...
nginx: konfiguratsioonifail /etc/nginx/nginx.conf sĂŒntaks on ok
nginx: konfiguratsioonifaili /etc/nginx/nginx.conf test on edukas
2020/08/22 20:15:54 [teade] 97#97: signaaliprotsess kÀivitatud
'Uptimer_GREEN' teenus on aktiivne!
Tappes 'uptimer_BLUE'...
uptimer_BLUE
Kokku taastatud ruum: 0B
Seadistamine edukas!

NĂŒĂŒd saab avada http://localhost/ brauseris, kĂ€ivitada seadistamine uuesti ja veenduda, et see lĂ€heb sujuvalt, vĂ€rskendades lehte klaviatuuri otseteeni ajal seadistamist.

Ärge unustage pĂ€rast tööd koristada :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 hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster