Šajā rakstā mēs ar , , un organizēsim bezšuvju tīmekļa lietojumprogrammas izvietošanu. ir tehnika, kas ļauj nekavējoties atjaunināt lietojumprogrammu, nepārtraucot nevienu pieprasījumu. Tā ir viena no zero downtime deployment stratēģijām un vislabāk piemērota lietojumprogrammām ar vienu instanci, taču ar iespēju blakus augšupielādēt otro, gatavu instanci.
Pieņemsim, ka jums ir tīmekļa lietojumprogramma, ar kuru aktīvi strādā daudzi klienti, un tai nekādā gadījumā nevar atļauties, lai uz dažām sekundēm tas apstājas. Un jums ļoti nepieciešams izlaist bibliotēkas atjauninājumu, labot kļūdu vai pievienot jaunu foršu funkciju. Parastā situācijā būs nepieciešams apturēt lietojumprogrammu, aizvietot to un pēc tam atkārtoti palaist. Ja izmantojat Docker, varat vispirms aizstāt, pēc tam restartēt, taču tomēr būs periods, kad pieprasījumi uz lietojumprogrammu netiks apstrādāti, jo parasti lietojumprogrammai ir nepieciešams laiks, lai sākotnēji ielādētu. Un, ja tā tiek palaista, bet izrādās, ka tā nedarbojas? Šāda uzdevuma risināšana ir jāveic minimāliem līdzekļiem un maksimāli eleganti.
ATKLĀJUMS: Lielākā daļa raksta ir ietverta eksperimentālā formātā - kā konsoles sesijas ieraksts. Ceru, ka to būs viegli uztvert, un šis kods pietiekami dokumentē sevi. Lai radītu gaisotni, iedomājieties, ka tas nav tikai kods, bet papīrs no "dzelzs" telegrāfa.
Interesantas tehnikas, kuras ir grūti atrast, vienkārši lasot kodu, ir aprakstītas katra nodaļas sākumā. Ja kaut kas nav skaidrs - meklējiet un pārbaudiet (laimīgā kārtā tas atkal darbojas sakarā ar Telegrama atbloķēšanu). Ko nevar atrast - uzdodiet jautājumus komentāros. Ar prieku papildināšu attiecīgo sadaļu "Interesantas tehnikas".
Sāksim.
$ mkdir blue-green-deployment && cd $_Serviss
Izveidosim eksperimentālo servisu un ievietosim to konteinerā.
Interesantas tehnikas
cat < file-name( + ) - veids, kā izveidot daudzrindu failu ar vienu komandu. Viss, ko bash izlasīs no/dev/stdinpēc šīs rindiņas un līdz rindaiEOFtiks ierakstītsfile-name.wget -qO- URL() - izvadīt saņemto HTTP dokumentu uz/dev/stdout(analogscurl URL).
Izvadīt
Es īpaši pārtraucu snippetu, lai iekļautu izcelšanu Python. Beigās būs vēl viens šāds fragments. Uztveriet, ka šajās vietās papīrs tika sagriezts, lai to nodotu krāsotāju nodaļai (kur kods tika krāsots ar roku ar augstspiediena marķieriem), un pēc tam šie gabali tika atkārtoti ielīmēti.
$ cat < uptimer.pyimportēt http.server kā BaseHTTPRequestHandler, HTTPServer
importēt laiku kā monotonic
lietojumprogrammas_versija = 1
lietojumprogrammas_nosaukums = f'Uptimer v{lietojumprogrammas_versija}.0'
lādēšanās_sekundes = 15 - lietojumprogrammas_versija * 5
klase Handler(BaseHTTPRequestHandler):
def do_GET(self):
ja self.path == '\/':
mēģināt:
t = monotonic() - server_start
ja t < lādēšanās_sekundes:
self.send_error(503)
cita:
self.send_response(200)
self.send_header('Content-Type', 'text\/html')
self.end_headers()
atbilde = f'<h2>{lietojumprogrammas_nosaukums} darbojas {t:3.1f} sekundes.</h2>n'
self.wfile.write(atbilde.encode('utf-8'))
except Exception:
self.send_error(500)
cita:
self.send_error(404)
httpd = HTTPServer(('', 8080), Handler)
server_start = monotonic()
print(f'{lietojumprogrammas_nosaukums} (ielādējas {lādēšanās_sekundes} sek.) uzsākta.')
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
---> 8ecf5a48c789
Step 2\/4 : EXPOSE 8080
---> Using cache
---> cf92d174c9d3
Step 3\/4 : COPY uptimer.py app.py
---> a7fbb33d6b7e
Step 4\/4 : CMD [ "python", "-u", ".\/app.py" ]
---> Running in 1906b4bd9fdf
Removing intermediate container 1906b4bd9fdf
---> 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->8080\/tcp uptimer
$ docker logs uptimer
Uptimer v1.0 (loads in 10 sec.) started.
$ wget -qSO- http://localhost:8080
HTTP\/1.0 503 Service Unavailable
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 darbojas jau 15.4 sekundes.</h2>
$ docker rm --force uptimer
uptimerTiesas proxy
Lai mūsu lietotne varētu nemanāmi mainīties, ir nepieciešams, lai priekšā tai būtu vēl kāda entītija, kas slēpj tās nomaiņu. Tas var būt tīmekļa serveris par . Reversā proxy tiek novietots starp klientu un lietotni. Tas pieņem pieprasījumus no klientiem un pārsūta tos uz lietotni, savukārt lietotnes atbildes nosūta klientiem.
Lietotni un reverso proxy var savienot iekš Docker, izmantojot . Tādējādi lietotnes konteineram pat nav jāpārsūta ports viesējsistēmā, tas ļauj maksimāli izolēt lietotni no ārējiem draudiem.
Ja reversais proxy dzivos citā viesējsistēmā, būs jāatsakās no docker tīkla un jāsaista lietotni ar reverso proxy caur viesējsistēmas tīklu, pārsūtot portu lietojumprogrammas parametru --publish, kā pirmajā palaišanā un kā luksoforam.
Reverso proxy darbosies uz 80. porta, jo tā ir tā entītija, kurai jāuzklausa ārpuse. Ja 80. ports jūsu testēšanas viesējsistēmā ir aizņemts, mainiet parametru --publish 80:80 uz --publish ANY_FREE_PORT:80.
Interesantas tehnikas
- «Docker tīklos, kurus izveidojis lietotājs, ar konteineriem var sazināties ne tikai pēc IP adreses. Konteineru nosaukums arī tiek izšķirts kā tā IP adrese» (, punkts 5 Docker ētikas kodeksā).
Izvadīt
$ 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 darbojas jau 11.5 sekundes.</h2>
$ docker run --detach --publish 80:80 --network web-gateway --name reverse-proxy nginx:alpine
80695a822c19051260c66bf60605dcb4ea66802c754037704968bc42527bf120
$ docker ps
KONTEINERA ID ATTĒLS KOMANDA RADĪTS STATUSS PORTI NOSAUKUMI
80695a822c19 nginx:alpine "\/docker-entrypoint.…" 27 sekundes atpakaļ Darbojās 25 sekundes 0.0.0.0:80->80\/tcp reverse-proxy
a1105f1b583d uptimer "python -u .\/app.py" Apmēram pirms minūtes Darbojās Apmēram minūti 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: signal process started
$ wget -qSO- http://localhost
HTTP\/1.1 200 OK
Server: nginx\/1.19.0
Date: Sat, 22 Aug 2020 19:56:24 GMT
Content-Type: text\/html
Transfer-Encoding: chunked
Connection: keep-alive
<h2>Uptimer v1.0 darbojas jau 104.1 sekundes.</h2>Bezsavienojuma izvietošana
Mēs izlaidīsim jauno lietotnes versiju (ar divkāršu palielinājumu starta veiktspējā) un mēģināsim to bezsasaistē izvietot.
Interesantas tehnikas
echo 'my text' | docker exec -i my-container sh -c 'cat > /my-file.txt'— Ierakstīt tekstumy textfailā/my-file.txtkonteinera iekšienēmy-container.cat > /my-file.txt— Ierakstīt failā standartā ievadi/dev/stdin.
Izvadīt
$ sed -i "s/app_version = 1/app_version = 2/" uptimer.py
$ docker build --tag uptimer .
Sūtot būvniecības kontekstu Docker demonam 39.94kB
Solījums 1/4 : NO python:alpine
---> 8ecf5a48c789
Solījums 2/4 : EXPOSE 8080
---> Izmantojot starpkontu
---> cf92d174c9d3
Solījums 3/4 : COPY uptimer.py app.py
---> 3eca6a51cb2d
Solījums 4/4 : CMD [ "python", "-u", ".\/app.py" ]
---> Darbojas 8f13c6d3d9e7
Noņemot starpkonteineru 8f13c6d3d9e7
---> 1d56897841ec
Veiksmīgi izveidots 1d56897841ec
Veiksmīgi apzīmēts uptimer:latest
$ docker run --detach --rm --name uptimer_BLUE --network web-gateway uptimer
96932d4ca97a25b1b42d1b5f0ede993b43f95fac3c064262c5c527e16c119e02
$ docker logs uptimer_BLUE
Uptimer v2.0 (ielāde 5 sek.) uzsāka.
$ docker run --rm --network web-gateway alpine wget -qO- http://uptimer_BLUE:8080
<h2>Uptimer v2.0 darbojas 23.9 sekundes.</h2>
$ sed s/uptimer/uptimer_BLUE/ uptimer.conf | docker exec --interactive reverse-proxy sh -c 'cat > /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: signālu process uzsākts
$ wget -qO- http://localhost
<h2>Uptimer v2.0 darbojas 63.4 sekundes.</h2>
$ docker rm -f uptimer
uptimer
$ wget -qO- http://localhost
<h2>Uptimer v2.0 darbojas 84.8 sekundes.</h2>
$ docker ps
KONTEINERA ID ATTĒLS KOMANDA IZVEIDOTS STATUSS PORTI NOSAUMI
96932d4ca97a uptimer "python -u .\/app.py" Pirms aptuveni minūtes Aktīvs aptuveni minūti 8080/tcp uptimer_BLUE
80695a822c19 nginx:alpine "\/docker-entrypoint.…" 8 minūtes ago Aktīvs 8 minūtes 0.0.0.0:80->80/tcp reverse-proxyŠajā posmā attēls tiek veidots tieši serverī, kas prasa lietotnes avotu klātbūtni tur, kā arī papildus noslogo serveri ar lieku darbu. Nākamais solis būs izveidot attēla veidošanu uz atsevišķas mašīnas (piemēram, CI sistēmā) ar turpmāku tā nodošanu serverim.
Attēlu pārsūtīšana
Diemžēl nav jēgas pārsūtīt attēlus no localhost uz localhost, tādēļ šo sadaļu var izmēģināt tikai, ja jums ir divi hosti ar docker. Minimālajā variantā tas izskatās apmēram šādi:
$ 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.9MBKomanda docker save saglabā attēla datus .tar arhīvā, tas nozīmē, ka tam ir aptuveni 1,5 reizes lielāks apjoms nekā tam būtu kompresētā veidā. Tātad piespiežam to saspiest laika un datu ietaupīšanas labad:
$ docker image save uptimer | gzip | ssh production-server 'zcat | docker image load'
Loaded image: uptimer:latestTurklāt var novērot pārsūtīšanas procesu (gan tam ir nepieciešama trešā puse utilīta):
$ docker image save uptimer | gzip | pv | ssh production-server 'zcat | docker image load'
25,7MiB 0:01:01 [ 425KiB/s] [ ]
Loaded image: uptimer:latestPadoms: Ja jums SSH savienojumam ar serveri nepieciešami daudz parametru, iespējams, jūs neizmantojat failu
~/.ssh/config.
Attēla pārsūtīšana caur docker image save/load ir visminimalistiskākais veids, bet ne vienīgais. Ir arī citi:
- Container Registry (nozares standarts).
- Pieslēgties docker daemon serverim no cita hosta:
- Videss maiņu
DOCKER_HOST. - Komandrindas parametrs
-Hvai--hostinstrumentadocker-compose. docker context
- Videss maiņu
Otrais veids (ar trim tā īstenošanas variantiem) ir labi aprakstīts rakstā .
deploy.sh
Tagad savāksim visu, ko mēs darījām manuāli, vienā skriptā. Sāksim ar augstāko līmeņa funkciju, tad aplūkosim pārējās, kas tajā tiek izmantotas.
Interesantas tehnikas
${parameter?err_msg}ir viens no bash burvju burtiem (aka ). Japarameternav norādīts, jāizvadaerr_msgun jāiznāk ar 1. kodu.docker --log-driver journaldpēc noklusējuma docker žurnālu draiveris ir tekstu fails bez jebkādas rotācijas. Šādā veidā žurnāli ātri aizpilda visu disku, tāpēc produkcijas vidē ir jānomaina draiveris uz gudrāku.
Dēplojuma skripts
deploy() {
local usage_msg="Usage: ${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 "Deploying '$NEW' in place of '$OLD'..."
docker run
--detach
--restart always
--log-driver journald
--name $NEW
--network web-gateway
$image_name || return 3
echo "Container started. Checking health..."
for i in {1..20}
do
sleep 1
if get-service-status $image_name $new_slot
then
echo "New '$NEW' service seems OK. Switching heads..."
sleep 2 # Ensure service is ready
set-active-slot $image_name $new_slot || return 4
echo "'$NEW' service is live!"
sleep 2 # Ensure all requests were processed
echo "Killing '$OLD'..."
docker rm -f $OLD
docker image prune -f
echo "Deployment successful!"
return 0
fi
echo "New '$NEW' service is not ready yet. Waiting ($i)..."
done
echo "New '$NEW' service did not raise, killing it. Failed to deploy T_T"
docker rm -f $NEW
return 5
}Izmantotās funkcijas:
ensure-reverse-proxy— Pārliecinās, ka apgrieztā proxy darbojas (noderīgi pirmajā izvietošanā)get-active-slot service_name— Nosaka, kurš slots šobrīd ir aktīvs norādītajam servisam (BLUEvaiGREEN)get-service-status service_name deployment_slot— Nosaka, vai serviss ir gatavs apstrādāt ienākošos pieprasījumusset-active-slot service_name deployment_slot— Maina nginx konfigurāciju apgrieztā proxy konteinerā
Secībā:
ensure-reverse-proxy() {
is-container-up reverse-proxy && return 0
echo "Izvietojam 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?"Izmantošana: ${FUNCNAME[0]} container_name"}
[ -n "$(docker ps -f name=${container} -q)" ]
return $?
}
get-active-slot() {
local service=${1?"Izmantošana: ${FUNCNAME[0]} service_name"}
if is-container-up ${service}_BLUE && is-container-up ${service}_GREEN; then
echo "Kollizija atklāta! Apstādinām ${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="Izmantošana: ${FUNCNAME[0]} service_name deployment_slot"
local service=${1?usage_msg}
local slot=${2?$usage_msg}
case $service in
# Pievienojiet konkrētas veselības pārbaudes ceļus jūsu pakalpojumiem šeit
*) local health_check_port_path=":8080/" ;;
esac
local health_check_address="http://${service}_${slot}${health_check_port_path}"
echo "Pieprasām '$health_check_address' 'web-gateway' docker tīklā:"
docker run --rm --network web-gateway alpine
wget --timeout=1 --quiet --server-response $health_check_address
return $?
}
set-active-slot() {
local usage_msg="Izmantošana: ${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
}Funkcija get-active-slot prasa nelielus paskaidrojumus:
Kāpēc tā atgriež skaitli, nevis izvada virkni?
Tomēr izsaukšanas funkcijā mēs pārbaudām tās izpildes rezultātu, un pārbaudīt exit kodu ar bash līdzekļiem ir daudz vienkāršāk nekā virkni. Turklāt, iegūt no tās virkni ir ļoti vienkārši:
get-active-slot service && echo BLUE || echo GREEN.
Vai trīs nosacījumu nepietiek, lai atšķirtu visus stāvokļus?
Pat divu pietiek, pēdējais šeit ir vienkārši pilnīgam, lai neuzrakstītu else.
Joprojām ir nenoteikta tikai funkcija, kas atgriež nginx konfigurācijas: get-nginx-config service_name deployment_slot. Līdzīgi kā ar veselības pārbaudi, šeit var noteikt jebkuru konfigurāciju jebkuram pakalpojumam. No interesantā — tikai cat <<- EOF, kas ļauj noņemt visus tabulācijas simbolus sākumā. Patiesība ir tāda, ka kārtīga formatējuma cena ir sajauktie tabuli un atstarpes, kas šodien tiek uzskatīta par ļoti sliktu toni. Bet bash piespiež tabulācijas simbolus, un arī nginx konfigurācijā nebūtu slikti iegūt normālu formatējumu. Tātad sajaukums starp tabulācijām un atstarpēm šeit šķiet patiešām labākais risinājums no sliktākajiem. Tomēr zemāk esošajā snippētā jūs to neredzēsiet, jo habr .
Lai divas reizes neizsēdētos, uzreiz pastāstīšu par
cat << 'EOF', kas vēlāk parādīsies. Ja rakstīt vienkāršicat << EOF, tad iekšā heredoc notiek virknes interpolācija (tiek atvērtas mainīgās ($foo), komandu izsaukumi ($(bar)) utt.), bet, ja beigu dokumenta zīmi ieliek vienkāršajos pēdiņās, interpolācija tiek izslēgta, un simbols$tiek izvadīts tāds, kāds tas ir. Tas ir tieši tas, kas nepieciešams, lai ievietotu skriptu cita skripta iekšpusē.
get-nginx-config() {
local usage_msg="Izmantošana: ${FUNCNAME[0]} pakalpojuma_nosaukums dislokācijas_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
# Šeit pievienojiet specifiskas nginx konfigurācijas jūsu pakalpojumiem
*) nginx-config-simple-service $container_name:8080 ;;
esac
}
nginx-config-simple-service() {
local usage_msg="Izmantošana: ${FUNCNAME[0]} proxy_pass"
local proxy_pass=${1?$usage_msg}
cat << EOF
server {
listen 80;
location / {
proxy_pass http://$proxy_pass;
}
}
EOF
}Un tas ir viss skripts. Un šeit lejupielādei caur wget vai curl.
Parametrizētu skriptu izpilde attālinātajā serverī
Ir pienācis laiks piekļūt mērķa serverim. Šoreiz localhost piemēroti būs:
$ ssh-copy-id localhost
/usr/bin/ssh-copy-id: INFO: cenšas pierakstīties ar jaunajiem atslēgas(-ēm), lai filtrētu ārā tās, kas jau ir instalētas
/usr/bin/ssh-copy-id: INFO: 1 atslēga(s) paliek instalēšanai -- ja jums tagad tiek prasīts, tad tas ir jauno atslēgu instalēšanai
himura@localhost's parole:
Pievienoto atslēgu skaits: 1
Tagad mēģiniet pierakstīties mašīnā, ar: "ssh 'localhost'"
un pārbaudiet, vai tika pievienotas tikai tās atslēgas, kuras jums bija jāpieprasa.Mēs uzrakstījām izvietošanas skriptu, kas pārkopē iepriekš sagatavoto attēlu uz mērķa serveri un nevainojami aizstāj pakalpojuma konteineru, bet kā to izpildīt attālinātajā mašīnā? Skriptam ir argumenti, jo tas ir universāls un var izvietot vairākus pakalpojumus zem viena reversā prokšija (ar nginx konfigurācijām var sakārtot, kāds pakalpojums būs pieejams, izmantojot kādu URL). Skriptu nevajadzētu glabāt serverī, jo šādā gadījumā mēs nevarēsim to automātiski atjaunināt (lai novērstu kļūdas un pievienotu jaunus pakalpojumus), un vispār — saglabāt stāvokli = slikti.
Risinājums 1: Tomēr glabāt skriptu serverī, bet katru reizi to kopēt caur scp. Pēc tam pievienoties caur ssh un izpildīt skriptu ar nepieciešamajiem argumentiem.
Mīnusi:
- Divas darbības, nevis viena.
- Vietas, uz kurām jūs kopējat, var nebūt, vai arī nepieejamība var būt, vai skripts var izpildīties aizvietošanas brīdī.
- Vēlams, lai viss būtu sakārtots (izdzēst skriptu).
- Jau trīs darbības.
Risinājums 2:
- Skriptā glabāt tikai funkciju definīcijas un vispār neko neizpildīt.
- Izmantojot
sedpievienot funkcijas izsaukumu beigās. - Nosūtīt visu tieši uz shh caur cauruļvadu (
|)
Priekšrocības:
- Patiesi bezstāvoklis.
- Bez boilerplate entītēm.
- Jūtos forši.
Labi, bet tikai bez Ansible. Jā, viss jau ir izgudrots. Jā, velosipēds. Skatieties, kāds vienkāršs, elegants un minimālistisks velosipēds:
$ 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_SCRIPTEOF
$ chmod +x deploy.sh
$ ./deploy.sh localhost magic-porridge-pot
Izveidoju savienojumu ar localhost...
Jā! 'deploy' funkcija izpildās uz 'hut' ar argumentu 'magic-porridge-pot'.Tomēr mēs nevaram būt droši, ka attālinātajā hostā ir adekvāts bash, tādēļ pievienosim nelielu pārbaudi sākumā (tas vietā ):
if [ "$SHELL" != "/bin/bash" ]
then
echo "'$SHELL' shells nav atbalstīts ar 'deploy.sh'. Iestatiet 'bash' shell '$USER@$HOSTNAME'."
exit 1
fiUn tagad viss patiesi:
$ 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
Sūtot gzipēto attēlu 'uptimer' uz 'localhost' pa ssh...
Ielādētais attēls: uptimer:latest
Savienojamies ar 'localhost' pa ssh, lai bezšuvju uzstādītu 'uptimer'...
Uzstādam 'uptimer_GREEN' vietā 'uptimer_BLUE'...
06f5bc70e9c4f930e7b1f826ae2ca2f536023cc01e82c2b97b2c84d68048b18a
Konteiners uzsākts. Pārbaudām veselību...
Pieprasām 'http://uptimer_GREEN:8080/' iekš 'web-gateway' docker tīkla:
HTTP/1.0 503 Pakalpojums nav pieejams
wget: serveris atgrieza kļūdu: HTTP/1.0 503 Pakalpojums nav pieejams
Jaunais 'uptimer_GREEN' pakalpojums vēl nav gatavs. Gaidām (1)...
Pieprasām 'http://uptimer_GREEN:8080/' iekš 'web-gateway' docker tīkla:
HTTP/1.0 503 Pakalpojums nav pieejams
wget: serveris atgrieza kļūdu: HTTP/1.0 503 Pakalpojums nav pieejams
Jaunais 'uptimer_GREEN' pakalpojums vēl nav gatavs. Gaidām (2)...
Pieprasām 'http://uptimer_GREEN:8080/' iekš 'web-gateway' docker tīkla:
HTTP/1.0 200 OK
Serveris: BaseHTTP/0.6 Python/3.8.3
Datums: Sāt, 22 Aug 2020 20:15:50 GMT
Saturs-Tips: text/html
Jaunais 'uptimer_GREEN' pakalpojums izskatās labi. Pārejam uz jauno versiju...
nginx: konfigurācijas fails /etc/nginx/nginx.conf sintakse ir pareiza
nginx: konfigurācijas fails /etc/nginx/nginx.conf tests ir veiksmīgs
2020/08/22 20:15:54 [paziņojums] 97#97: signāls procesam uzsākts
'uptimer_GREEN' pakalpojums ir aktīvs!
Nobeidzam 'uptimer_BLUE'...
uptimer_BLUE
Kopējā atbrīvotā telpa: 0B
Uzstādīšana veiksmīga!Tagad varat atvērt pārlūkprogrammā, vēlreiz palaist uzstādīšanu un pārliecināties, ka tā notiek bezšuvju veidā, atsvaidzinot lapu ar F5 laikā, kad notiek uzstādīšana.
Neaizmirstiet sakopt pēc darba :3
$ docker rm -f uptimer_GREEN reverse-proxy
uptimer_GREEN
reverse-proxy
$ docker network rm web-gateway
web-gateway
$ cd ..
$ rm -r blue-green-deploymentAvots: habr.com
