Innleiðing docker pull og docker push skipanir án þess að docker biðlari noti HTTP beiðnir

Við vorum með 2 poka af grasi, 75 meskalín spjaldtölvur unix umhverfi, docker geymsla og það verkefni að útfæra docker pull og docker push skipanir án docker biðlara.

Innleiðing docker pull og docker push skipanir án þess að docker biðlari noti HTTP beiðnir

UPP:
Spurning: Til hvers er þetta allt?
Svar: Hleðsluprófun á vörunni (EKKI með bash, forskriftirnar eru veittar í fræðsluskyni). Ákveðið var að nota ekki Docker biðlarann ​​til að minnka viðbótarlög (innan skynsamlegra marka) og líkja því eftir hærra álagi. Fyrir vikið voru allar kerfistafir Docker biðlarans fjarlægðar. Við fengum tiltölulega hreint álag beint á vöruna.
Greinin notaði GNU útgáfur af verkfærum.

Fyrst skulum við reikna út hvað þessar skipanir gera.

Svo til hvers er docker pull notað? Samkvæmt skjöl:

„Taktu mynd eða geymslu úr skrásetningu“.

Þar finnum við líka hlekk á skilja myndir, ílát og geymslurekla.

Innleiðing docker pull og docker push skipanir án þess að docker biðlari noti HTTP beiðnir

Héðan getum við skilið að docker mynd er sett af ákveðnum lögum sem innihalda upplýsingar um nýjustu breytingarnar á myndinni, sem er augljóslega það sem við þurfum. Næst skoðum við registry API.

Þar segir eftirfarandi:

""Mynd" er sambland af JSON upplýsingaskrá og einstökum lagaskrám. Ferlið við að draga > mynd miðast við að sækja þessa tvo þætti."

Þannig að fyrsta skrefið samkvæmt skjölunum er "Að draga myndbirtingu".

Auðvitað munum við ekki skjóta það, en við þurfum gögnin frá því. Eftirfarandi er dæmi um beiðni: GET /v2/{name}/manifests/{reference}

"Nafnið og tilvísunarfæribreytan auðkenna myndina og eru nauðsynlegar. Tilvísunin getur innihaldið merki eða samantekt."

Docker geymslan okkar er sett upp á staðnum, við skulum reyna að framkvæma beiðnina:

curl -s -X GET "http://localhost:8081/link/to/docker/registry/v2/centos-11-10/manifests/1.1.1" -H "header_if_needed"

Innleiðing docker pull og docker push skipanir án þess að docker biðlari noti HTTP beiðnir

Til að bregðast við fáum við json frá sem við höfum sem stendur aðeins áhuga á líflínunum, eða öllu heldur kjötkássa þeirra. Eftir að hafa fengið þær, getum við farið í gegnum hvern og einn og framkvæmt eftirfarandi beiðni: "GET /v2/{name}/blobs/{digest}"

„Aðgangur að lagi verður lokaður með nafni geymslunnar en er auðkenndur einstaklega í skránni með samdrætti.

samantekt í þessu tilfelli er kjötkássa sem við fengum.

Reynir

curl -s -X GET "http://localhost:8081/link/to/docker/registry/v2/centos-11-10/blobs/sha256:f972d139738dfcd1519fd2461815651336ee25a8b54c358834c50af094bb262f" -H "header_if_needed" --output firstLayer

Innleiðing docker pull og docker push skipanir án þess að docker biðlari noti HTTP beiðnir

Við skulum sjá hvers konar skrá við fengum loksins sem fyrsta björgunarlínuna.

file firstLayer

Innleiðing docker pull og docker push skipanir án þess að docker biðlari noti HTTP beiðnir

þeim. teinar eru tjöruskjalasafn, við að pakka þeim upp í viðeigandi röð munum við fá innihald myndarinnar.

Við skulum skrifa lítið bash forskrift svo hægt sé að gera þetta allt sjálfvirkt

#!/bin/bash -eu

downloadDir=$1
# url as http://localhost:8081/link/to/docker/registry
url=$2
imageName=$3
tag=$4

# array of layers
layers=($(curl -s -X GET "$url/v2/$imageName/manifests/$tag" | grep -oP '(?<=blobSum" : ").+(?=")'))

# download each layer from array
for layer in "${layers[@]}"; do
    echo "Downloading ${layer}"
    curl -v -X GET "$url/v2/$imageName/blobs/$layer" --output "$downloadDir/$layer.tar"
done

# find all layers, untar them and remove source .tar files
cd "$downloadDir" && find . -name "sha256:*" -exec tar xvf {} ;
rm sha256:*.tar
exit 0

Nú getum við keyrt það með viðeigandi breytum og fengið innihald nauðsynlegrar myndar

./script.sh dirName “http://localhost:8081/link/to/docker/registry” myAwesomeImage 1.0

Part 2 - Docker push

Þetta verður aðeins flóknara.

Byrjum aftur með skjöl. Svo við þurfum að hlaða niður hverjum leiðtoga, safna samsvarandi upplýsingaskrá og hlaða því niður líka. Það virðist einfalt.

Eftir að hafa kynnt okkur skjölin getum við skipt niðurhalsferlinu í nokkur skref:

  • Frumstilling ferli - "POST /v2/{repoName}/blobs/uploads/"
  • Að hlaða upp björgunarlínu (við munum nota einhlíta upphleðslu, þ.e. við sendum hverja björgunarlínu í heild sinni) - "PUT /v2/{repoName}/blobs/uploads/{uuid}?digest={digest}
    Efnislengd: {stærð lags}
    Efnistegund: forrit/oktett-straumur
    Lag tvöfaldur gögn".
  • Hleður upplýsingaskránni - "PUT /v2/{repoName}/manifests/{reference}".

En skjölin missa af einu skrefi, án þess mun ekkert virka. Fyrir einhleypta hleðslu, sem og fyrir hluta (klumpa), áður en járnbrautin er hlaðin, verður þú að framkvæma PATCH beiðni:

"PATCH /v2/{repoName}/blobs/uploads/{uuid}
Innihaldslengd: {stærð klumpur}
Efnistegund: forrit/oktett-straumur
{Layer Chunk Binary Data}".

Annars muntu ekki geta farið lengra en fyrsta stigið, vegna þess að... Í stað væntanlegs svarkóða 202 færðu 4xx.

Nú lítur reikniritið svona út:

  • Frumstilling
  • Patch rail
  • Að hlaða handrið
  • Hleður upplýsingaskrá
    Liðir 2 og 3, í sömu röð, verða endurteknir eins oft og þarf að hlaða fjölda lína.

Í fyrsta lagi þurfum við hvaða mynd sem er. Ég mun nota archlinux:nýjasta

docker pull archlinux

Innleiðing docker pull og docker push skipanir án þess að docker biðlari noti HTTP beiðnir

Nú skulum við vista það á staðnum til frekari greiningar

docker save c24fe13d37b9 -o savedArch

Innleiðing docker pull og docker push skipanir án þess að docker biðlari noti HTTP beiðnir

Pakkaðu skjalasafninu sem myndast í núverandi möppu

tar xvf savedArch

Innleiðing docker pull og docker push skipanir án þess að docker biðlari noti HTTP beiðnir

Eins og þú sérð er hver líflína í sérstakri möppu. Nú skulum við líta á uppbyggingu upplýsingaskrárinnar sem við fengum

cat manifest.json | json_pp

Innleiðing docker pull og docker push skipanir án þess að docker biðlari noti HTTP beiðnir

Ekki mikið. Við skulum sjá hvaða farmskrá þarf til að hlaða, skv skjöl.

Innleiðing docker pull og docker push skipanir án þess að docker biðlari noti HTTP beiðnir

Augljóslega hentar núverandi stefnuskrá okkur ekki, svo við munum búa til okkar eigin með blackjack og kurteisi, líflínum og stillingum.

Við munum alltaf hafa að minnsta kosti eina stillingarskrá og fjölda líflína. Scheme útgáfa 2 (núverandi þegar þetta er skrifað), mediaType verður óbreytt:

echo ‘{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
   "config": {
      "mediaType": "application/vnd.docker.container.image.v1+json",
      "size": config_size,
      "digest": "config_hash"
   },
   "layers": [
      ’ > manifest.json

Eftir að grunnskráin hefur verið búin til þarftu að fylla hana með gildum gögnum. Til að gera þetta notum við json sniðmát járnbrautarhlutarins:

{
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "size": ${layersSizes[$i]},
         "digest": "sha256:${layersNames[$i]}"
      },

Við munum bæta því við upplýsingaskrána fyrir hverja braut.

Næst þurfum við að finna út stærð stillingaskrárinnar og skipta út stubbunum í upplýsingaskránni fyrir raunveruleg gögn

sed -i "s/config_size/$configSize/g; s/config_hash/$configName/g" $manifestFile

Nú geturðu hafið niðurhalsferlið og vistað þér uuid, sem ætti að fylgja öllum síðari beiðnum.

Allt handritið lítur einhvern veginn svona út:

#!/bin/bash -eux

imageDir=$1
# url as http://localhost:8081/link/to/docker/registry
url=$2
repoName=$3
tag=$4
manifestFile=$(readlink -f ${imageDir}/manifestCopy)
configFile=$(readlink -f $(find $imageDir -name "*.json" ! -name "manifest.json"))

# calc layers sha 256 sum, rename them accordingly, and add info about each to manifest file
function prepareLayersForUpload() {
  info_file=$imageDir/info
  # lets calculate layers sha256 and use it as layers names further
  layersNames=($(find $imageDir -name "layer.tar" -exec shasum -a 256 {} ; | cut -d" " -f1))

  # rename layers according to shasums. !!!Set required amount of fields for cut command!!!
  # this part definitely can be done easier but i didn't found another way, sry
  find $imageDir -name "layer.tar" -exec bash -c 'mv {} "$(echo {} | cut -d"/" -f1,2)/$(shasum -a 256 {} | cut -d" " -f1)"' ;

  layersSizes=($(find $imageDir -name "*.tar" -exec ls -l {} ; | awk '{print $5}'))

  for i in "${!layersNames[@]}"; do
    echo "{
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "size": ${layersSizes[$i]},
         "digest": "sha256:${layersNames[$i]}"
      }," >> $manifestFile
  done
  # remove last ','
  truncate -s-2 $manifestFile
  # add closing brakets to keep json consistent
  printf "nt]n}" >> $manifestFile
}

# calc config sha 256 sum and add info about it to manifest
function setConfigProps() {
  configSize=$(ls -l $configFile | awk '{print $5}')
  configName=$(basename $configFile | cut -d"." -f1)

  sed -i "s/config_size/$configSize/g; s/config_hash/$configName/g" $manifestFile
}

#prepare manifest file
prepareLayersForUpload
setConfigProps
cat $manifestFile

# initiate upload and get uuid
uuid=$(curl -s -X POST -I "$url/v2/$repoName/blobs/uploads/" | grep -oP "(?<=Docker-Upload-Uuid: ).+")

# patch layers
# in data-binary we're getting absolute path to layer file
for l in "${!layersNames[@]}"; do
  pathToLayer=$(find $imageDir -name ${layersNames[$l]} -exec readlink -f {} ;)
    curl -v -X PATCH "$url/v2/$repoName/blobs/uploads/$uuid" 
  -H "Content-Length: ${layersSizes[$i]}" 
  -H "Content-Type: application/octet-stream" 
  --data-binary "@$pathToLayer"

# put layer
  curl -v -X PUT "$url/v2/$repoName/blobs/uploads/$uuid?digest=sha256:${layersNames[$i]}" 
  -H 'Content-Type: application/octet-stream' 
  -H "Content-Length: ${layersSizes[$i]}" 
  --data-binary "@$pathToLayer"
done

# patch and put config after all layers
curl -v -X PATCH "$url/v2/$repoName/blobs/uploads/$uuid" 
  -H "Content-Length: $configSize" 
  -H "Content-Type: application/octet-stream" 
  --data-binary "@$configFile"

  curl -v -X PUT "$url/v2/$repoName/blobs/uploads/$uuid?digest=sha256:$configName" 
  -H 'Content-Type: application/octet-stream' 
  -H "Content-Length: $configSize" 
  --data-binary "@$configFile"

# put manifest
curl -v -X PUT "$url/v2/$repoName/manifests/$tag" 
  -H 'Content-Type: application/vnd.docker.distribution.manifest.v2+json' 
  --data-binary "@$manifestFile"

exit 0

við getum notað tilbúið handrit:

./uploadImage.sh "~/path/to/saved/image" "http://localhost:8081/link/to/docker/registry" myRepoName 1.0

UPP:
Hvað fengum við í kjölfarið?
Í fyrsta lagi raunveruleg gögn til greiningar, þar sem prófin eru keyrð í blazemeter og gögnin um beiðnir um tengilið viðskiptavina eru ekki mjög upplýsandi, ólíkt hreinum HTTP beiðnum.

Í öðru lagi, umskiptin leyfðu okkur að fjölga sýndarnotendum fyrir upphleðslu bryggju um 150% og fá meðalsvarstíma 20-25% hraðar. Fyrir docker niðurhal tókst okkur að fjölga notendum um 500%, en meðalviðbragðstími minnkaði um um 60%.

Þakka þér fyrir athygli þína.

Heimild: www.habr.com

Bæta við athugasemd