سه‌شنبه نهم شهریور در اولین همایش داکر درباره docker swarm ارائه‌ای داشتم، چون قرار بود برای آن دمویی داشته باشیم و RAM سیستم پایین بود (۴ گیگ) ریسک نکردم و از ارائه فیلم نگرفتم، برای همین در این پست سعی می‌کنم مراحل دموی ارائه شده که ایجاد یک کلاستر با swarm بود رو به صورت کامل بنویسم.

اول از همه اگر با داکر آشنا نیستید، می‌توانید در دوره‌ی آشنایی با داکر وب سایت فرانش 😎 ثبت‌نام کنید.

اسلاید ارائه را هم می‌توانید در گوگل اسلاید ببینید.

پروژه‌ی داکر swarm از سال گذشته روی این مخزن توسعه‌داده شد، شرکت داکر برای سرویس‌ها ابری خودش از آن استفاده می‌کرد، همچنین با stable شدن آن شرکت‌های دیگری نیز از آن در دنیای واقعی استفاده کردند، در طی این یک سال بهبود‌هایی در زمنیه شبکه، امنیت، service discovery در داکر swarm انجام شد، همچنین شرکت‌ داکر برای ترقیب کاربران به استفاده از آن، به کل swarm را به docker منتقل کرد به گونه‌ای که در ورژن 1.12 شما در سه سوت می‌توانید یک کلاستر swarm راه‌اندازی کنید. نکته‌ای که باید بهش اشاره کرده این هست که توسعه swarm در مخزن اصلی آن همچنان ادامه دارد ! در اینجا بحث اصلی استفاده از راهکار ارائه شده در docker ورژن 1.12 است.

اول از همه یک http سرور خیلی خیلی ساده با زبان گو داریم که ازش به عنوان برنامه‌ اجرایی در این دمو استفاده می‌کنیم 👇

package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
)

func hello(res http.ResponseWriter, req *http.Request) {
	hostName, err := os.Hostname()
	if err != nil {
		log.Fatalln(err)
	}
	// io.WriteString(res, fmt.Sprintf("Hello world from 👉 %v 👈  ", hostName))
	io.WriteString(res, fmt.Sprintf("Hello world from 👉 %v 👈 containerID 🐋 ", hostName))
}

func main() {
	http.HandleFunc("/", hello)
	http.ListenAndServe(":80", nil)
}

خوبی زبان گو این هست که شما می‌توانید از برنامه‌ی خود یک باینری مناسب برای کانتینر ایجاد کنید و بعد در سه خط Dockerfile یک ایمیج خیلی رژیم گرفته ایجاد کنید، مثلاً ایمیج این برنامه شد 5.63MB 👌

برای تولید باینری مناسب کانتینر دستور go build را با این سوییچ‌ها و envها به صورت زیر اجرا کنید:

CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o hello-world

حال که باینری فایل مورد نظر hello-world را داریم، کافیه یک Dockerfile سه خطی بنوسید و بعد هم ایمیج رو بسازید!

FROM scratch
ADD hello-world /
# default port for hello-world is 80
CMD ["/hello-world"]

دقت کنید چون برنامه در قالب یک باینری فایل هست، شما دیگر از base ایمیج خاصی استفاده نمی‌کنید و همانند ایمیج‌هایی مثل debian از scratch ساخته می‌شود. 💪

واسه ایجاد کلاستر یه ubuntu server به صورت مجازی نصب می‌کنیم و بعد فقط کافیه داکر را روی آن نصب کنیم، همچنین واسه راحتی کار SSH را روی آن اوکی می‌کنیم تا از طریق SHELL خود هاست به آن وصل بشویم.

برای راحتی ۲ سرور مجازی دیگر از روی‌ آن clone می‌کنیم 😁 الان هر سه نود مورد احتیاج برای این دمو را داریم، یکی از نودها رو به عنوان swarm manager انتخاب می‌کنیم و روی آن دستور زیر را اجرا می‌کنیم

docker swarm init

حالا به شما می‌گوید که می‌توانید برای اضافه‌کردن نودهای دیگر به عنوان worker دستور زیر را در نودهای دیگر وارد نمایید، روی دو نود دیگر این دستور رو اجرا می‌کنیم.

docker swarm join \
    --token SWMTKN-1-2t7lf1rv07ht8j5sbt7q4yssbqiaqgeop8yplaaelywyqh6bcm-6k0a07wq8ey7xf85td9cfgwlj \
    192.168.0.59:2377

برای نمایش وضعیت نودها و کانتینرهایی که در آن اجرا می‌شود از یک ویژولایزر استفاده می‌کنیم، برای اجرای آن ایمیج داکر آن را اجرا می‌کنیم:

docker run -it -d -p 8080:8080 -e HOST=[YOURHOST] -v /var/run/docker.sock:/var/run/docker.sock manomarks/visualizer

دقت کنید که به جای YOURHOST باید IP و یا یک DNS A Record وارد کنید که IP نود ۱ را resolve کند، واسه این کار به راحتی می‌توانید در فایل etc/hosts/ یک hostname ای برای نود ۱ در نظر بگیرید.

نکته‌ی مهمی که باید توجه کنید این هست که ایمیج برنامه‌ای که می‌خواهید روی کلاستر scale شود، باید در تمامی نودها وجود داشته باشد، پس باید با scp ایمیج برنامه را به نودها انتقال دهید، البته می‌توانید به راحتی یک داکر رجیستری خصوصی راه‌اندازی کرده و ایمیج برنامه را به آن PUSH کنید و هنگام اجرای دستور docker service create با سوییچ with-registry-auth اطلاعات کاربری رجیستری را پاس بدهید، که در این حالت تمامی نودهای کلاستر ایمیج مربوطه را از آن رجیستری می‌گیرند.

حال برای اجرای یک سرویس جدید روی کلاستر، دستور زیر را روی نود اصلی swarm manager اجرا می‌کنیم:

docker service create -p 80:80 --name our_app golang-hello-world:1.0

برای اطلاع از سرویس‌های در حال اجرا روی کلاستر 👇

docker service ls

برای scale سرویس در کلاستر از دستور docker service scale our_app=6 استفاده می‌کنیم.

همچنین شما می‌توانید با دستور docker service update تغییراتی در کانتینرهای در حال اجرا بدهید، در مثال زیر تمامی کانتیرها به صورت ۲ به ۲ با فاصله زمانی ۱۰ ثانیه ایمیج جدید دریافت می‌کنند.( در حقیقت اول stop & remove می‌شوند و بعد با ایمیج جدید start می‌شوند)

docker service update --image golang-hello-world:1.1 --update-parallelism 2 --update-delay 10s our_app

✋ 👈 در همایش هم گفتم به عنوان تست با swarm کار کرده‌ام، پس تجربه‌های لازم در محیط production رو ندارم. فعالین این حوزه آینده خوبی برای swarm تصور می‌کنند که در یک سال آینده بتواند همانند Kubernetes حرفی برای گفتن داشته باشد.