Docker Üzerine Genel Bakış — Docker Swarm Kullanımı

Serkan Bingöl
AWS Certified User Group Turkey
10 min readJan 1, 2019

Merhabalar önceki yazımızda docker containerların “docker compose” kullanarak tek komut ile çalıştırılıp kullanıma alındığı ve kalıcı verinin nasıl uygulandığı ile ilgili genel bilgileri vermiştik. Bu yazı ile birlikte ise birçok containerdan oluşan, yönetebilir ve yük altında scale edilebilir bir container ağı ( cluster ) yapısını ele almak istiyorum. Tam burada “Docker Swarm” yapısı bizler için devreye giriyor.

Docker Swarm Nedir ?

Swarm, yönetici (master) ve yönetilen (worker) adı verilen makinelerin oluşturduğu bir ağdır (cluster). Yada diğer bir değiş ile multiple hostlar üzerinde birden fazla instance koşturarak single point of failure problemlerini çözümlemek üzerine Docker ile birlikte bizlere sunulan bir servistir. Docker Swarm ile birlikte entegre cluster yönetimi (Container Orchestrating), ölçekleme (Scaling), periyodik güncellemeler (Reduce Downtime Cost), güvenlik (TLS Connection), yük dağıtımı (Load Balancing), dahili DNS sunucusu (Service Discovery), containerlar arası durum yönetimi ( Desired State Reconciliation) , bileşen gruplandırma ( Declarative Service Model)” gibi kavramlara çözümler sunulmaktadır.

Cluster yapısı ile ilgili genel bilgi kazanmak adına aşağıdaki resimde mimariyi inceleyebiliriz. Manager node’lar kendi aralarında consensus(fikir birliği) sağlamak için RAFT algoritmasını kullanmaktadır. Manager’ların kendi aralarında ve worker’larla konuştuğunu göreceğiz. Worker’lar kendi aralarında iletişim kurmazlar.

RAFT Algoritması (N — 1) / 2 : Cluster ortamınızda 3 adet manager node var ise (3–1)/2 = 1, yani 1 manager node down olsa bile cluster mimariniz bundan etkilenmeyecektir.

Öncelikli olarak makinemizde docker üzerinde swarm mode’ un aktif olup olmadığını docker info komutu ile kontrol ediyoruz.

$ docker info

Swarm “inactive” olarak gözüktüğü için docker swarm init komutu ile swarm modu aktif duruma getirerek artık swarm mod’ un bizlere sunduğu özelliklerini kullanmaya başlayabiliriz.

$ docker swarm init

docker node ls komutu ile swarm mode üzerinde 1 adet yönetici rolünde node ayağa kaldırıldığını inceleyebiliriz. Ayrıca docker network ls komutu ile birlikte docker networkler arasında swarm için özel bir overlay network’un kurulduğunu görmekteyiz. Bu oluşan overlay network aynı swarm cluster’ına dahil tüm containerların iletişim kurması için oluşturulan default bir networktür. docker service create [imaj_ismi] komutu cluster yapımızın içinde kullandığımız containerları ayaklandırmak için kullanılır. Service kelimesi bizim için içinde bulunan containera ait bir adet iş parçacığını (task) simgelemektedir. Burada biz alpine dağıtımından oluşan bir container içinde devamlı google ‘ a ping atma işlemini gerçekleştiriyoruz.

$ docker nodel ls , $ docker network ls , $ docker service create [imaj_ismi]

Oluşturmuş olduğumuz servisleri görüntülemek için docker service ls komutu ile işlem yaparak “suspicious_lederberg” random ismi ile oluşturulan servisi listeliyoruz. docker service ps [servis_ismi] yani burada docker service ps suspicious_lederberg ile bu servis içindeki bir task olan alpine containerımızı inceleyebiliriz. servis isimlerini ps komutu ile kullanarak oluşan servisin kaç adet worker (node) üzerinde instance alındığını ve bunlara ne isimler verildiğini anlayabiliyoruz.

Aşağıdaki resimden biraz daha detaylı olarak anlatmak gerekir ise suspicious_lederberg isimli servis bizim için 1 adet instance üzerinde koşturacak çünkü servisimizi oluştururken yada daha sonrasında kaç adet replikası olacağını belirtmedik dolayısı ile bu servisi 1 adet olarak oluşturdu.Bunu docker service ps suspicious_lederberg ile incelediğimizde alpine dağıtımı bir imaj üzerinden oluşturduğumuz containera suspicious_lederberg.1 isimli bir taskı vererek işleme aldığını görmekteyiz. docker container ls komutunu kullanarak ilgili container’ımızı daha detaylı inceleyebiliriz.

$ docker service ls , $ docker service ps [servis_ismi] , $ docker container ls

Bu servisin içindeki alpine containeri için çalışan taskın yani bu containerın durması (down) durumunda aslında yapmakta olduğumuz iş kesintiye uğrayacaktır. Swarm’ın ölçeklendirme ve yük dağıtımı özelliklerini kullanarak daha yönetilebilir bir cluster yapısına ulaşmak için bu taskı birden fazla container üzerinde çalıştırmak gerekmektedir. docker service update [servis_ID] — replicas 4 komutu ile bu task için 3 adet daha çalışan replikasyon üretiyoruz.

$ docker service update [servis_ID] — replicas 4

Sonrasında docker servise ls suspicious_lederberg komutunu çalıştırdığımızda 4 adet taskımızın oluştuğunu ve docker container ls komutu ile ise bu 4 adet taskın 4 ayrı container instance’ ında işleme alındığını görebilmekteyiz.

Oluşturmuş olduğumuz 4 adet containerdan, ID si 7c8b ile başlayan 3. containerını cluster yapısından docker container rm -f [container_ID] yani docker container rm -f 7c8b komutunu kullanarak yok ediyoruz. Hemen ardından docker service ls ile 4 adet container içinde 3 adet containerımızın çalıştığını ve docker container ls ile bunların hangileri olduğunu kontrol ediyoruz. Çok kısa bir süre sonrasında docker container ls komutunu tekrar çalıştırır isek tekrardan 4. container’ın ayağa kalktığını inceleyebiliriz.

$ docker container rm -f [container_ID]

Swarm yapısını kendi makinemizde test ettikten sonra daha gerçekçi bir yapıyı test etmek adına 3 platformu (Play With Docker , Digital Ocean Droplet with Docker ve Windows Server 2019 Core with Containers) kısaca sizlere tanıtarak bunlardan Digital Ocean platformu üzerinde bir test senaryosunu ayağa kaldırmayı planlıyorum.Diğer platformlar üzerinde aynı kurguyu yapacağım için sizlerde istediğiniz platformu seçerek aynı işlemleri tekrar edebilirsiniz.

Play With Docker

Docker ile ilgili denemelerinizi yapabileceğiniz ilk platform olarak http://play-with-docker.com/ adresinden faydalanabilirsiniz. Play with docker , linux alpine dağıtımını browser da kullanarak aslında docker containerlar içinde docker kullanmanızı sağlayan bir platform.

Saniyeler içinde docker containerları ayaklandırmanıza yada birkaç farklı node kullanarak bir docker swarm cluster yapısını kurgulamamıza olanak tanımaktadır. 4 saatlik kullanım süresi içinde tüm docker komutlarını kullanarak bir sistem oluşturabiliriz. 4 saatin sonunda oluşturduğumuz tüm nodelar sistemden silinecektir.

Windows Server 2019 Core with Containers

Eğer deneme sürümü yada paralı sürüm bir Microsoft Azure hesabına sahipseniz ve docker üzerinde bazı işlemleri gerçekleştirebilecek bir cluster yapısı planlıyorsanız “Windows Server 2019 Datacenter Server Core with Containers” sanal makineleri sizin için ideal olacaktır. Bu makinelerde Windows server için gerekli olan minimum bileşenler bir GUI desteği olmadan gelmektedir. Üzerinde docker engine yapılandırılmış şekilde kullanıma açılmaktadır. Daha detaylı bilgiyi Halil İbrahim Mollaoğlu hocam belki ilerideki bir yazısında ele alarak bu konuda bizi biraz daha fazla aydınlatır diye düşünüyorum. (Kusura bakma hocam sanki zorla yazdırır gibi olduk :D)

Buradaki sistem için 1 adet manager ve 2 ader workerdan oluşan bir cluster yapısı için toplamda 3 adet Core Server 2019 (VM-SWARMNODE1, VM-SWARMNODE2, VM-SWARMNODE3 ) makinesi açıyorum.

3 makine de kurulduktan sonra docker info komutu ile dockerın tüm makinelerde çalışır konumda olduğunu test ediyoruz.

$ docker info

Bu makinelerde bir cluster yapısı kurgularken gerekli olan portları tek tek açmak yerine makineler arası port iletişimi için windows firewall’ u Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled false komutunu kullanarak kapalı konuma getiriyorum. Bu makinelerde sadece terminal çalıştığı için powershell komutu ile bu işlemi gerçekleştirebiliyoruz.

Önemli Not :Devam eden kısımda Digital Ocean platformunda port ayarlamalarını yapacağım için aynı portları isterseniz burada da kullanabilirsiniz.

Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled false

Sonra docker swarm’ı aktif hale getirebilmek adına ve bir cluster yapısı kurguladığımız için (bir kaç node birbiri ile iletişim halinde olacağından dolayı) docker swarm init komutu yerine docker swarm init — advertise-adr [Public yada Private IP] — listen-addr [Public yada Private IP:PORT] komutunu çalıştırıyoruz. Sonrasında docker node ls ile 1. makinede açılan node’un Leader-manager status yani yönetici rolü ile kurulduğunu anlıyoruz.

Ayrıca SWARMNODE2 ve SWARMNODE3 nodelarının bu cluster yapısına dahil edilmesi ve SWARMNODE1 tarafından kontrol edilmesi için her 2 nodu docker swarm join — token [created_ID] [LeaderNode_IP:LeaderNode_PORT] komutu ile ( bizim senaryomuzda docker swarm join — token SWMTKN-1–3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2 10.0.0.5:2377 ) bu swarm yapısına worker olarak ekliyoruz.

docker swarm init — advertise-adr [Public yada Private IP] — listen-addr [Public yada Private IP:PORT]

Aşağıdaki adımda ise SWARMNODE1 nodu üzerinden docker node update — role manager [NODE_İSMİ] komutunu kullanarak SWARMNODE2 ve SWARMNODE3 makinelerinide manager rolü ile güncelleyerek tüm kontrolleri gerçekleştirmiş oluyoruz.

docker node update — role manager [NODE_İSMİ]

Digital Ocean Docker Swarm Cluster Kurulumu

DigitalOcean, bulut tabanlı altyapı sağlayıcısı olarak kendini konumlandıran, geliştirme, sürüm kontrolü ve test ortamları gibi bir çok ihtiyaca cevap veren dünyanın en büyük bulut sunucu sağlayıcılarından birisidir.

Droplet adı altında ifade edilen bulut sunucularını , Image ya da app tercihi yaparak ,donanım kapasitesi ve sunucu bölge konumlandırması seçiminden birkaç saniye sonra kullanıma hazır bir şekilde tüketebiliriz.

2017 Verilerine Göre Bulut Sunucu Hizmeti sağlayıcıları Payı

Biz oluşturmak istediğimiz cluster yapısı için digital ocean platformundan “One-click Apps” sekmesi ile Linux Ubuntu dağıtımına ait 18.04 sürümü üzerinde Docker kullanımına hazır bir imaj seçiyoruz.

Toplamda 3 adet node oluşturup gerekli işlemlerimize başlayabiliriz.Oluşturmuş olduğumuz sunuculara ulaşmak için kayıt olur iken vermiş olduğumuz mail adresine gelen bilgiler ile droplet sunucularına ssh bağlantısı yapıyoruz.

İlk önce nodelar arasında iletişimi sağlamak adına UFW (Uncomplicated Firewall) üzerinden sudo ufw allow [PORT] komutu ile 2377,7946 ve 4789 portlarını aktif hale getiriyoruz.

$ sudo ufw allow [PORT]

Node 1 üzerinde docker swarm’ı aktif hale getirmek için docker swarm init — advertise-addr [PUBLIC_IP] komutunu kullanarak node2 ve node 3 üzerinde docker swarm join — token [created_ID [LeaderNode_IP:LeaderNode_PORT] komutunu kullanarak swarm’a birer worker olarak eklenme işlemini gerçekleştiriyoruz. Node1 üzerinde docker node ls komutunu bir kez daha çalıştırarak node2 ve node3 ‘ünde artık cluster içinde olduklarını listelemiş oluyoruz.

Node1 üzerinde docker node update — role manager [NODE_İSMİ] komutu ile node2 ve node 3 için gerekli manager atama işlemlerini yaptıktan sonra docker node ls ile tüm nodelar üzerinde node listelemeyi yaparak işlemi başarı ile gerçekleştirdiğimizi görmekteyiz.

$ docker node update — role manager [NODE_İSMİ]

Artık cluster yapımız içinde tüm nodeların birbiri arasında iletişimini sağladıktan sonra bir test senaryosunu kurgulayabiliriz. 1 adet postgre database servisi ve 1 adet drupal yönetim sitesi servisi ayaklandırarak gerekli servisler arasındaki iletişimi bir overlay network üzerinden sağlayacağız. Bunun için docker network create — driver overlay [Network_İsmi] komutu ile Drupal_Net adında bir overlay networku olusturup bunu docker network ls ile görüntülüyoruz.

$ docker network create — driver overlay [Network_İsmi]

Sonrasında swarm içerisinde leader statüsünde bulunan node1 üzerinde docker service create — name postgre — network Drupal_Net postgres komutu ile bir postgre database containerı ve docker service create — name drupal — network Drupal_Net -p 8080:80 drupal komutu ile bir drupal yönetim sitesi container’ı ayaklandırarak bunların Drupal_Net overlay networkü üzerinden iletişim halinde olduğunu belirtiyoruz.

$ docker service create — name postgre — network Drupal_Net postgres ve $ docker service create — name drupal — network Drupal_Net -p 8080:80 drupal

Node1 sunucusuna ait public IP üzerinden browser da gerekli kurulum işlemlerine başlıyoruz.

Aynı zamanda node 1 üzerinde docker service ps [Servis_İsmi] komutu ile hem drupal için hem postgre servisi için hangi nodelar üzerinde hangi state anında olduğunu inceliyoruz. Burada drupal servisindeki containerdan 1 adet instance node1 üzerinde, postgre servisindeki containerdan 1 adet instance node2 üzerinde ayaklanmış olarak gözüküyor.

Gerekli kurulum işlemlerini tamamlarken veritabanı sunucusu olarak postgre olarak belirlediğimiz servis adını yazmamı yeterli olmaktadır. Service discovery sayesinde iki uygulama birbiri arasında iletişim halinde olduğunu anlamaktadır.

Veri tabanı bağlantısını başarılı bir şekilde geçerek kurulum işlemlerine devam etmekteyiz.

Kurulum tamamlandıktan sonra artık tüm nodeların public-ip leri üzerinden 8080 portuna bir ulaşım sağladığımızda aslında node1 üzerinde çalışan drupal servisindeki container’a tüm nodelar üzerinden ulaşabildiğimizi görmekteyiz. Aşağıdaki resimden bunu inceleyebilirsiniz.

Fakat node1 üzerinde bulunan containerdaki drupal uygulamamıza diğer nodelardan nasıl ulaşılabiliyor ? Burada “Routing Mesh” kavramına bir değinmemiz gerekmektedir.

Mesh network, network’e dahil bütün cihazların birbirlerine tek tek bağlı olduğu bir topolojidir. Hepsi birbirine doğrudan bağlı olduğu için aynı zamanda bütün cihazlar dağıtıcı görevi de görür. Bir cihaz gittiğinde (down olma durumu ) gelen istek, ayakta olan farklı bir cihaza otomatikman yönlendirilir. Burada swarm için oluşturulan Virtual IP bizim için load balancer görevi görmektedir. Bizim sistemimizdeki topolojiyi görmek için aşağıdaki resmi inceleyebilirsiniz.

Routing Mesh ile ilgili daha detaylı bilgiyi bu linkteki dökümanlardan takip edebilirsiniz.

Drupal servisinde bulunan containerımız için toplamda 4 adet instance oluşturmak üzere docker service update — replicas 4 drupal komutunu kullanarak tüm nodeları kullanacak şekilde 4 adet containerımızı oluşturuyoruz.

$ docker service update — replicas 4 drupal

Bütün işlemlerimizi tamamladıktan sonra docker service ps drupal komutunu kullanarak 2'si node2 de ve 1'er tanesi node1 ve node3 üzerinde olmak üzere 4 containerlarımızın da farklı nodelarda oluşturulduğunu görebilmekteyiz. İlgili örneğimizin sonucunu aşağıdaki resimden takip edebilirsiniz.

$ docker service ps drupal

Burada routing mesh’in , tasklar üzerinde bir load balancer görevi gördüğünü kısa bir örnekle daha açıklamak istiyorum. Node1 üzerinde bir adet elasticsearch containerı instance alarak bundan 3 adet replica üreteceğim. 9200 portunu dinleyen elasticsearch uygulaması, 3 node üzerinde de birer task olarak işlem yapmak için ayağa kalkmış olacak.

$ docker service create — name search — replicas 3 -p 9200:9200 elasticsearch:2

Node1 üzerinde curl localhost:9200 ile elasticsearch uygulamasına istekte bulunarak virtual IP nin her seferinde başka bir node da bulunan containera gelen isteği yönlendirdiğini oluşan json response çıktısı üzerinden görebiliriz. Burada bir round robin kullanımı söz konusu olmaktadır.

$ curl localhost:9200

İstek yapmaya devam ettikçe sıra tekrardan başa dönmektedir.Aşağıdaki resimden 4. ve 5. isteklerin cevaplarının aslında 1 ve 2. istekle aynı olduğunu görebilmekteyiz.

Swarm için 3 Node Cluster Senaryosu aşamaları :https://1drv.ms/b/s!AskWoAU3NqUug_hW2uRbkcAMpTJ-zQ

2018 yılının bittiği 2019' un başladığı bu ilk günde docker swarm üzerinden ölçeklendirilebilir ve yönetilebilir bir cluster yapısını özetleyip, örneklendirdiğimiz bir yazımızın sonuna daha geldik.

2019 yılında daha çevik , daha yönetilebilir projelerde bulunup, daha sağlam alt yapılı, ölçeklendirilebilir ve düşük maliyetli yazılımlar yapmanız dileği ile.

2019 yılının DevOps kültürünün daha uygulanabilir olduğu bir yıl olması dileği ile. DevOps ‘lu günler sizinle olsun.

--

--

Serkan Bingöl
AWS Certified User Group Turkey

Muzur bir oğlan babası, hayvan sever, Harry Potter hayranı, bazen maceracı düz yazılımcı.