Perbarui wadah layanan di Amazon ECS

32

Pendekatan apa yang disarankan untuk memperbarui wadah layanan yang berjalan di Amazon ECS?

The dokumentasi AWS mengatakan: "Jika Anda telah memperbarui Docker gambar aplikasi Anda, Anda dapat membuat definisi tugas baru dengan gambar itu dan menyebarkan ke layanan Anda, salah satu tugas pada satu waktu." Ini adalah hampir semua yang saat ini tersedia dalam dokumentasi saat ini (13 April 2015).

Apakah saya mengerti dengan benar, bahwa satu-satunya cara untuk memperbarui wadah aplikasi saya di Amazon ECS adalah membuat tugas baru, lalu menghentikan tugas lama dan memulai tugas baru?

Saya telah berhasil menggunakan tag "terbaru" dengan Core OS & Fleetctl. Ini bermanfaat karena tidak perlu mengubah tag gambar Docker untuk pembaruan baru, karena memuat ulang layanan akan melihat perubahan baru dan memperbarui wadah (menggunakan tag yang sama "terbaru").

Pendekatan apa yang telah Anda gunakan untuk memperbarui layanan Anda dengan gambar buruh pelabuhan yang diperbarui di Amazon ECS?

Petrus Repo
sumber
Juga mencoba untuk mencari tahu ini, karena kami berharap dapat menggunakan ECS untuk mengerahkan berbagai daemon yang perlu dijalankan secara terus-menerus dalam produksi.
parent5446
1
Hanya untuk mengonfirmasi, Anda mengatakan bahwa me-restart layanan ecs akan menurunkan versi terbaru dari suatu gambar? Saya telah mencari dokumentasi tentang ini dan tidak dapat menemukannya di mana pun.
mmilleruva
1
Adakah konfirmasi untuk yang ini?
Lior Ohana
@LiorOhana Sedihnya itu benar. Lihat jawaban saya untuk detailnya.
hamx0r
Saya memposting jawaban terperinci yang baru di bawah, tetapi untuk memperjelas di sini: Layanan Anda akan selalu berusaha untuk menarik salinan baru wadah Anda dari repo, berdasarkan tag yang telah Anda tetapkan. Jika sebuah tugas terbunuh, ketika layanan menyebarkannya lagi, ia tidak memiliki ingatan tentang apa yang ada di repo, hanya apa yang ada di repo.
MrDuk

Jawaban:

18

Tidak yakin apakah ini dianggap sebagai pertanyaan yang diabaikan - menemukan ini saat memecahkan masalah saya dan sekarang menambahkan solusi saya sekarang setelah diselesaikan.

Untuk memperbarui layanan dengan wadah baru, Anda perlu:

  1. unggah wadah baru ke repositori;
  2. memicu pembaruan definisi tugas;
  3. memicu pembaruan wadah;
  4. Penting: pastikan aturan layanan memungkinkan peluncuran versi tugas baru.

Jika tugas layanan tidak diperbarui ke versi terbaru, periksa tab "peristiwa" untuk kesalahan. Misalnya, mungkin ECS tidak dapat memulai versi baru dari layanan Anda: Anda hanya memiliki satu contoh EC2 di kluster dan port aplikasi sudah digunakan pada host. Dalam hal ini, setel batasan "min health / max health" ke "0%, 100%" - dengan cara ini, ECS akan memilih untuk membunuh kontainer lama sebelum menggunakan yang baru. Ini juga terjadi selama beberapa menit - jangan terburu-buru jika Anda tidak melihat umpan balik segera.

Di bawah ini adalah contoh skrip penyebaran untuk memperbarui wadah dalam klaster dan layanan yang telah dikonfigurasi sebelumnya. Perhatikan tidak perlu menentukan versi jika Anda hanya bermaksud "menggunakan terbaru dari keluarga".

awsRegion=us-east-1
containerName=..
containerRepository=..
taskDefinitionFile=...
taskDefinitionName=...
serviceName=...


echo 'build docker image...'
docker build -t $containerName .

echo 'upload docker image...'
docker tag $containerName:latest $containerRepository:$containerName
docker push $containerRepository:$containerName

echo 'update task definition...'
aws ecs register-task-definition --cli-input-json file://$taskDefinitionFile --region $awsRegion > /dev/null

echo 'update our service with that last task..'
aws ecs update-service --service $serviceName --task-definition $taskDefinitionName --region $awsRegion  > /dev/null
uiron
sumber
2
Ini memaksa saya untuk memiliki definisi tugas sebagai file secara lokal, dan jika saya mengerti dengan benar, itu adalah satu-satunya tempat di mana saya dapat mendefinisikan variabel lingkungan. Apakah ada cara untuk melakukan ini tanpa memiliki variabel lingkungan secara lokal? Idealnya saya ingin mengeluarkan perintah untuk menunjuk ke tag gambar buruh pelabuhan baru tanpa mengirim informasi lain tentang tugas / layanan / wadah / dll.
rmac
1
Komentar di atas set "min health/max health" limits to "0%, 100%"adalah emas. Terima kasih banyak!
sivabudh
1
Kata hati-hati di sini, jika Anda menetapkan minuntuk 0%, ketika Anda mengubah definisi tugas yang digunakan layanan Anda, Anda pada dasarnya memberikan otoritas penuh untuk menjatuhkan semua tugas pada saat yang sama untuk penyebaran itu.
MrDuk
1

Saya menggunakan beberapa bagian dari script ecs-deploy dengan peningkatan saya (mengambil gambar dari setiap deskripsi wadah, dan mengganti bagian tag-nya dengan $ TAG_PURE): https://gist.github.com/Forever-Young/e939d9cc41bc7a105cdcf8cd7ab9d714

# based on ecs-deploy script
TASK_DEFINITION_NAME=$(aws ecs describe-services --services $SERVICE --cluster $CLUSTER | jq -r .services[0].taskDefinition)
TASK_DEFINITION=$(aws ecs describe-task-definition --task-def "$TASK_DEFINITION_NAME" | jq '.taskDefinition')
NEW_CONTAINER_DEFINITIONS=$(echo "$TASK_DEFINITION" | jq --arg NEW_TAG $TAG_PURE 'def replace_tag: if . | test("[a-zA-Z0-9.]+/[a-zA-Z0-9]+:[a-zA-Z0-9]+") then sub("(?<s>[a-zA-Z0-9.]+/[a-zA-Z0-9]+:)[a-zA-Z0-9]+"; "\(.s)" + $NEW_TAG) else . end ; .containerDefinitions | [.[] | .+{image: .image | replace_tag}]')
TASK_DEFINITION=$(echo "$TASK_DEFINITION" | jq ".+{containerDefinitions: $NEW_CONTAINER_DEFINITIONS}")
# Default JQ filter for new task definition
NEW_DEF_JQ_FILTER="family: .family, volumes: .volumes, containerDefinitions: .containerDefinitions"
# Some options in task definition should only be included in new definition if present in
# current definition. If found in current definition, append to JQ filter.
CONDITIONAL_OPTIONS=(networkMode taskRoleArn)
for i in "${CONDITIONAL_OPTIONS[@]}"; do
  re=".*${i}.*"
  if [[ "$TASK_DEFINITION" =~ $re ]]; then
    NEW_DEF_JQ_FILTER="${NEW_DEF_JQ_FILTER}, ${i}: .${i}"
  fi
done

# Build new DEF with jq filter
NEW_DEF=$(echo $TASK_DEFINITION | jq "{${NEW_DEF_JQ_FILTER}}")
NEW_TASKDEF=`aws ecs register-task-definition --cli-input-json "$NEW_DEF" | jq -r .taskDefinition.taskDefinitionArn`

echo "New task definition registered, $NEW_TASKDEF"

aws ecs update-service --cluster $CLUSTER --service $SERVICE --task-definition "$NEW_TASKDEF" > /dev/null

echo "Service updated"
Selamanya muda
sumber
Disarankan untuk memberikan informasi yang berguna dari tautan dalam jawaban Anda, untuk memberikan tautan-busuk. Bisakah Anda melakukannya?
BE77Y
1
Diperbarui jawaban saya
SelamanyaYoung
1

Setelah mengunggah gambar Docker baru, meskipun memiliki tag yang sama dengan yang digunakan oleh Tugas, seseorang harus menyalin tugas terbaru, dan kemudian mengonfigurasi Layanan untuk menggunakan Tugas baru itu. Secara opsional, seseorang dapat dengan mudah memiliki 2 tugas duplikat dan mengonfigurasi Layanan untuk bertukar di antara mereka setiap kali Gambar Docker diperbarui.

Pada dasarnya, untuk menyebabkan Docker Container baru dibuat oleh ECS, pembaruan ke Layanan harus memicunya, dan satu-satunya cara untuk membuat pemicu Layanan adalah dengan memperbaruinya dalam beberapa cara - seperti dengan mengatakannya untuk menggunakan nomor tugas yang berbeda.

Perhatikan bahwa Kontainer yang sedang berjalan mungkin tidak berhenti secara otomatis hanya karena Layanan telah diperbarui - Anda mungkin perlu melihat daftar Tugas Anda dan menghentikannya secara manual.

hamx0r
sumber
Ini sebenarnya tidak benar - Anda selalu dapat membunuh tugas secara manual alih-alih mengandalkan layanan Anda untuk melakukannya. Ketika layanan mendeteksi itu telah dibunuh, ia akan berusaha untuk mengangkatnya lagi, memaksa menarik kembali hal yang samatag
MrDuk
1

Pendekatan yang bekerja untuk saya mirip dengan yang di atas. Setelah membuat layanan dan tugas Anda, dan memulai segalanya, edit Grup Penskalaan Otomatis dan pastikan min , maks , dan yang diinginkan diatur ke 1 .

Grup mungkin adalah grup default; jika Anda tidak yakin maka Anda bisa mencapainya dengan memilih tab ECS Instances di cluster Anda, lalu dari drop-down Actions pilih Cluster Resources dan klik tautan di dekat bagian bawah kotak dialog yang terbuka.

Ketika itu semua di tempat, setiap kali Anda ingin menyebarkan update gambar wadah pergi ke Task area cluster dan Berhenti tugas . Anda akan mendapatkan peringatan, tetapi asalkan penskalaan otomatis diatur, layanan akan memulainya lagi dengan dorongan terbaru.

Tidak perlu membuat versi baru dari layanan atau tugas.

Perhatikan bahwa layanan / tugas memperbarui diri dari mana saja secara instan menjadi sekitar satu menit atau lebih. Jika Anda menunggu dengan putus asa, Anda bisa Menjalankan Tugas Baru secara manual. Layanan tidak akan memilikinya, jadi itu tidak ideal, tetapi masih akan berputar yang baru jika mati.

K Cartlidge
sumber
1

Saya tahu ini adalah utas lama, tetapi solusinya jauh lebih mudah daripada sebagian besar jawaban di sini.

Cara memperbarui wadah yang sedang berjalan dalam dua langkah:

Di bawah ini mengasumsikan Anda memiliki layanan yang menjalankan tugas yang mereferensikan penandaan kontainer latest(atau penandaan statis lainnya yang tidak mengubah pembaruan lintas penampung).

  1. Unggah wadah baru Anda ke repositori
  2. Secara manual bunuh tugas Anda

Jika tujuannya adalah agar kita mendapatkan bangunan baru di alam bebas, kita tidak benar-benar perlu bergantung pada layanan kita untuk itu (dan saya berpendapat, kita tidak seharusnya bergantung pada itu). Jika Anda mematikan tugas Anda, layanan akan mengenalinya tidak memiliki Desired Counttugas yang sedang berjalan, dan hanya memutar yang baru. Ini akan memicu penarikan kembali wadah Anda, berdasarkan tag yang sama.

Layanan ECS adalah jaring keamanan HA, bukan pengganti untuk pipa CD / CI Anda.


Bonus: Jika tujuannya adalah agar layanan mengenali wadah baru telah didorong (terlepas dari tag), kami perlu mempertimbangkan implikasinya. Apakah kita benar-benar menginginkan layanan dasar yang mengendalikan pipa penempatan kita? Mungkin tidak. Idealnya, Anda akan mendorong wadah Anda dengan tag yang berbeda (berdasarkan versi rilis atau sesuatu). Dalam hal ini, penghalang untuk penyebaran adalah bahwa layanan harus diberi tahu tentang sesuatu yang baru - sekali lagi, ini merupakan jaring pengaman untuk layanan tersebut, dan tidak lebih.


Cara menyebarkan tag baru dalam tiga langkah:

  1. Unggah yang baru container:tagke repositori
  2. Buat definisi tugas baru dengan merujuk yang baru tag
  3. Perbarui layanan Anda untuk referensi definisi tugas baru
    • Hati-hati di sini! Jika Anda telah minimum healthymengatur untuk 0%beberapa jawaban lain menyarankan, Anda memberi AWS wewenang penuh untuk membunuh seluruh layanan Anda untuk menyebarkan definisi tugas baru. Jika Anda lebih suka penyebaran bergulir / bertahap, atur minimum Anda menjadi sesuatu >0%.
    • Atau, atur minimum healthyke 100%dan maximum healthyke sesuatu >100%untuk memungkinkan layanan Anda menyebarkan tugas baru sebelum mematikan yang lama (meminimalkan dampaknya bagi pengguna Anda).

Dari titik ini, layanan Anda akan secara otomatis mengenali bahwa Anda telah menentukan tugas baru, dan bekerja menyebarkannya berdasarkan minimum/ maximumambang batas sehat yang telah Anda konfigurasi.

MrDuk
sumber
bagus, terima kasih, lebih baik daripada jawaban lain
Olegzandr Denman