Co nowego (i złego) w docker 1.12

Za nami wielkie wydarzenie DevOpsowe – DockerCon2016, z tego co oglądałem i słuchałem większość sesji kręciła się wokół nowej wersji – 1.12. Wersja na pewno rewolucyjna ale wprowadzone zmiany wyglądają jakby były nieuzgadniane z resztą firmy. Odnoszę też wrażenie że nową wersję wprowadzono nieco na siłę z deadlinem takim aby na tę konferencję za wszelką cenę zdążyć. Nieco szerszy komentarz (+ co o tym wszystkim sądzę) jest na końcu artykułu, a więc jeśli kogoś nie interesują technikalia można przewinąć na dół.

Ogólnie do tej pory postawienie swarma nie było trywialne, zwłaszcza gdy korzystało się z overlay-networks i zewnętrznego KVS (np consula).  W przypadku użycia TLS/SSL do komunikacji między węzłami (i z KVS’em) sytuacja robiła się już mocno skomplikowana i trzeba było sporo dupogodzin żeby postawić architekturę. W wersji 1.12 dockera swarm uległ drastycznemu uproszczeniu, obecnie postawienie farmy dockerowej to 3 polecenia.

Na początek dwie ważne uwagi wycięte z dokumentacji:

  1. When you run Docker Engine outside of swarm mode, you execute container commands. When you run the Engine in swarm mode, you orchestrate services.
  2. Worker nodes receive and execute tasks dispatched from manager nodes. By default manager nodes are also worker nodes, but you can configure managers to be manager-only nodes.

Pierwsza mówi że docker to kontenery a swarm to serwisy. Druga podkreśla że jak sterować to z managerów a nie z workerów. I faktycznie tego się trzymają.

Na potrzeby LAB`a kreuję 3 maszyny:

master: node01 , węzły liczące: node02, node03 
node01: 192.168.43.240
node02: 192.168.43.164
node03:192.168.43.203

Docker zwraca uwagę że należy udrożnić komunikację sieciową:

port 2377 for cluster management communications
port 7946 (tcp+udp) for communication among nodes
port 4789 (tcp+udp) for overlay network traffic

Tak kreujemy swarma:

root@node01:~# docker swarm init 
Swarm initialized: current node (066btqaw69byww15yfos2b8h6) is now a manager.

A potem dodajemy 2 węzły liczące:

root@node02:~# docker swarm join  192.168.43.240:2377
root@node03:~# docker swarm join  192.168.43.240:2377

I to by było na tyle, koniec artykułu, idziemy do domu 🙂 Ale oczywiście żeby nie było różowo – join może zawisnąć w stanie:

Error response from daemon: This node is processing an existing join request that has not succeeded yet.

Oprócz tego (pracuję na 1.12-dev) błędami wali co chwilę, czasem nie chce się podłączyć, czasem odłączyć itd itp. Jak już wszystko pójdzie poprawnie to należy zauważyć że na hostach kompletnie nic się nie uruchomiło:

root@node01:~# docker ps -a
CONTAINER  ID  IMAGE   COMMAND     CREATED   STATUS    PORTS     NAMES
root@node01:~# 
root@node02:~# docker ps -a
CONTAINER ID   IMAGE   COMMAND     CREATED   STATUS    PORTS     NAMES
root@node02:~#

Żegnajcie zatem czasy kiedy mieliśmy kontenery swarm mamange, swarm join i consule, tutaj jakoś tak jakby wszystko wbudowali w engine, oczywiście gdzie i co – nie wiadomo. Stan klastra sprawdzamy poprzez:

root@node01:~# docker node ls

ID  HOSTNAME  MEMBERSHIP           STATUS AVAILABILITY  MANAGER STATUS
066btqaw69byww15yfos2b8h6 * node01 Accepted Ready   Active  Leader
3vg00uxz3q6fr7qevhj8lpywj   node02 Accepted Ready   Active       9ldzxwy20s3zz7k4k279q8dza   node03 Accepted Ready   Active

Przy okazji – nodes ls da się zrobić tylko na węźle master. Oczywiście na workerze nie da się powołać kolejnego swarma (chyba że zastosujemy “leave”)

root@node02:~# docker swarm init 
Error response from daemon: This node is already part of a Swarm cluster. Use "docker swarm leave" to leave this cluster and join another one.

A teraz uruchomienie nowości – czyli tzw. “service” :

root@node01:~# docker service create --replicas 1 --name helloworld alpine ping docker.com
16bcj47n3x5wnlplntgztyuk1

Service to zbiór N-kontenerów serwujących usługę z tego samego obrazu – pełna analogia do serwisów z ranchera. Listing serwisów:

root@node01:~# docker service ls
ID            NAME        REPLICAS  IMAGE   COMMAND
16bcj47n3x5w  helloworld  1/1       alpine  ping docker.com

A tak objawia się to w klasycznym świecie kontenerów:

root@node01:~# docker p
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
459608c58f65        alpine:latest       "ping docker.com"   20 seconds ago      Up 19 seconds                           helloworld.1.cluooqdbu5yv1r7fv56alhbqa

Inspekcja serwisu podaje całkiem obszerne info:

root@node01:~# docker service inspect --pretty helloworld
ID: 16bcj47n3x5wnlplntgztyuk1
Name: helloworld

Mode: Replicated
Replicas: 1
Placement:
Strategy: Spread
UpdateConfig:
Parallelism: 0
ContainerSpec:
Image: alpine
Args: ping docker.com
Resources:
Reservations:
Limits:

Aby obejrzeć kontenery świadczące usługi dla serwisu używamy polecenia “service tasks”:

root@node01:~# docker service tasks helloworld

ID                         NAME          SERVICE     IMAGE   LAST STATE         DESIRED STATE  NODE

cluooqdbu5yv1r7fv56alhbqa  helloworld.1  helloworld  alpine  Running 2 minutes  Running        node01

A teraz kolejna nowość – skalowanie serwisu:

root@node01:~# docker service ls

ID            NAME        REPLICAS  IMAGE   COMMAND

16bcj47n3x5w  helloworld  1/1       alpine  ping docker.com
root@node01:~# docker service scale helloworld=10

helloworld scaled to 10
root@node01:~# docker service ls

ID            NAME        REPLICAS  IMAGE   COM

16bcj47n3x5w  helloworld  1/10      alpine  ping docker.com

Jak widać z 1 zrobiło się 10.  “Service tasks” zapewne pokaże 10 kontenerów – oczywiście swarm sam je już po swojemu porozrzuca po hostach:

root@node01:~# docker service tasks helloworld
ID                         NAME           SERVICE     IMAGE   LAST STATE         DESIRED STATE  NODE
cluooqdbu5yv1r7fv56alhbqa  helloworld.1   helloworld  alpine  Running 4 minutes  Running        node01
2v4d01lri5cw0p7l4jlfywjo5  helloworld.2   helloworld  alpine  Running 9 seconds  Running        node01
b9ndfph7ul2p24tpxrb22jt5x  helloworld.3   helloworld  alpine  Running 9 seconds  Running        node03
c020yz8gjl87s39wpnltpruy8  helloworld.4   helloworld  alpine  Running 9 seconds  Running        node03
7od718x3pw52cepgypn59nu8n  helloworld.5   helloworld  alpine  Running 9 seconds  Running        node02
78fs3ub4oe9hozvemcqtosi9k  helloworld.6   helloworld  alpine  Running 9 seconds  Running        node01
6856clu0ll6mkuhxwgaxuu60b  helloworld.7   helloworld  alpine  Running 9 seconds  Running        node03
8z4loz59f15ihvzc4m3r0d26e  helloworld.8   helloworld  alpine  Running 9 seconds  Running        node01
1sb5lrn1o309lkkzai8tz637d  helloworld.9   helloworld  alpine  Running 9 seconds  Running        node02
2itiyshm17v26i16ehd0se0ze  helloworld.10  helloworld  alpine  Running 9 seconds  Running        node02

Na koniec usunięcie serwisu:

root@node01:~# docker service rm helloworld

A teraz nowy fajny ficzer – service upgrade. Na każdym węźle tworzymy 2 nowe obrazy – oto ich Dockerfile:

FROM alpine

CMD while [ 1 ] ; do echo usluga w wersji 1 ; sleep 1 ; done

Budujemy:

docker build -t app_image_01 .

I drugi:

FROM alpine

CMD while [ 1 ] ; do echo usluga w wersji 2 ; sleep 1 ; done

Budujemy

docker build -t app_image_02 .

Startujemy service:

root@node01:/tmp# docker service create --replicas 6 --name application_service  app_image_01

157v06ckhnkc7zfxi0ms52d5w

Jak widać się odpalił:

root@node01:/tmp# docker service ls

ID            NAME                 REPLICAS  IMAGE         COMMAND

157v06ckhnkc  application_service  6/6       app_image_01

6 replik to oczywiście 6 kontenerów, a zatem :

root@node01:/tmp# docker service tasks application_service

ID                         NAME                   SERVICE              IMAGE         LAST STATE          DESIRED STATE  NODE

alzx5dn7rekq5b201t952iu1e  application_service.1  application_service  app_image_01  Running 12 seconds  Running        node01

2qzt2o4pgjq3c15wbpzsgj4hc  application_service.2  application_service  app_image_01  Running 12 seconds  Running        node03

ddbookvceol8w3f1drjbojy0m  application_service.3  application_service  app_image_01  Running 12 seconds  Running        node02

cv3n3ma0vlvxi0e7ecf0ir2hu  application_service.4  application_service  app_image_01  Running 12 seconds  Running        node02

ekqns979muf40u8u92mn7oxbg  application_service.5  application_service  app_image_01  Running 12 seconds  Running        node01

ehs2wp6q6pbxb5b4bvp68kntw  application_service.6  application_service  app_image_01  Running 12 seconds  Running        node03

Robimy update service’u o nowy obraz:

root@node01:/tmp# docker service update --image app_image_02 application_service 

application_service

O ile service jest update’owany nowym obrazem (nową f-cjonalnością) to niestety usługi padają:

root@node01:/tmp# docker service tasks application_servic

ID  NAME  SERVICE  IMAGE  LAST STATE  DESIRED STATE  NODE

Dopiero po chwili wszystko wstaje na nowym obrazie, no ale downtime niestety był:

root@node01:/tmp# docker service tasks application_service

ID                         NAME                   SERVICE              IMAGE         LAST STATE          DESIRED STATE  NODE

5jrhulg9exy5lfg4pgvp84uzq  application_service.1  application_service  app_image_02  Running 29 seconds  Running        node01

3ufr19iq9xqvzkd5ne20z59jp  application_service.2  application_service  app_image_02  Running 29 seconds  Running        node02

cn6pq0n5sj28ug9m88pcue3bk  application_service.3  application_service  app_image_02  Running 29 seconds  Running        node01

3h7r42m0w5j1bptjzjvksvg1r  application_service.4  application_service  app_image_02  Running 29 seconds  Running        node03

8phc3d3b0j1xq0wje012dmj6y  application_service.5  application_service  app_image_02  Running 29 seconds  Running        node03

4xfpcfdpbyxcsqe2bl6f8lm8k  application_service.6  application_service  app_image_02  Running 29 seconds  Running        node02

Rozwiązaniem jest powołanie service z kolejnymi nowościami – update-delay i parallelism:

root@node01:/tmp# docker service create --replicas 6 --name application_service_2 --update-delay 10s --update-parallelism 1  app_image_01

amy9mt2pyyvphaxkqpuatika4

6 kontenerów (tak jak wcześniej):

root@node01:/tmp# docker service tasks application_service_2

ID                         NAME                     SERVICE                IMAGE         LAST STATE         DESIRED STATE  NODE

2hs8iz0pvjfd1si0habzpc1fz  application_service_2.1  application_service_2  app_image_01  Running 9 seconds  Running        node02

530ofzox2n0faqxjo0ifsqhj8  application_service_2.2  application_service_2  app_image_01  Running 9 seconds  Running        node01

e8gq5yr9qpxvi3r6umceyb1p5  application_service_2.3  application_service_2  app_image_01  Running 9 seconds  Running        node01

b58ygfhau1hp2b5z8ooaxfykc  application_service_2.4  application_service_2  app_image_01  Running 9 seconds  Running        node03

ce3kkyumlv450ggmjretwrjgl  application_service_2.5  application_service_2  app_image_01  Running 9 seconds  Running        node03

evk966pxj7v1iv0nv84963sk7  application_service_2.6  application_service_2  app_image_01  Running 9 seconds  Running        node02

Update serice’u o nowy obraz:

root@node01:/tmp# docker service update --image app_image_02 application_service_2 

application_service_2

Tym razem swarm robi update po jednym kontenerze i w dodatku ze sporym odstępem :

root@node01:/tmp# docker service tasks application_service_2ID                         NAME                     SERVICE                IMAGE         LAST STATE          DESIRED STATE  NODE

5e5q3g5g8fgfq5fkf4fjjzx8z  application_service_2.1  application_service_2  app_image_02  Ready 11 seconds    Running        node02

530ofzox2n0faqxjo0ifsqhj8  application_service_2.2  application_service_2  app_image_01  Running 28 seconds  Running        node01

e8gq5yr9qpxvi3r6umceyb1p5  application_service_2.3  application_service_2  app_image_01  Running 28 seconds  Running        node01

b58ygfhau1hp2b5z8ooaxfykc  application_service_2.4  application_service_2  app_image_01  Running 28 seconds  Running        node03

ce3kkyumlv450ggmjretwrjgl  application_service_2.5  application_service_2  app_image_01  Running 28 seconds  Running        node03

evk966pxj7v1iv0nv84963sk7  application_service_2.6  application_service_2  app_image_01  Running 28 seconds  Running        node02

root@node01:/tmp# docker service tasks application_service_2

[...]

Kawa 🙂

[...]
root@node01:/tmp# docker service tasks application_service_2

ID                         NAME                     SERVICE                IMAGE         LAST STATE              DESIRED STATE  NODE

5e5q3g5g8fgfq5fkf4fjjzx8z  application_service_2.1  application_service_2  app_image_02  Running About a minute  Running        node02

20buphd7vdh8v1nehbz14hupn  application_service_2.2  application_service_2  app_image_02  Running About a minute  Running        node01

2hq79718i6rd1835zqq6psdk5  application_service_2.4  application_service_2  app_image_02  Running 49 seconds      Running        node02

841pi9ty7rqstg05znuusx4c5  application_service_2.5  application_service_2  app_image_02  Running 28 seconds      Running        node03

evk966pxj7v1iv0nv84963sk7  application_service_2.6  application_service_2  app_image_01  Running About a minute  Running        node02

Taki prawie blue-green deployment 🙂

Wprowadzono też DRAIN węzła (a la vmware maintenance mode – zresztą działa tak samo):

root@node01:/tmp# docker node update --availability drain node02

node02

root@node01:/tmp# docker node ls

ID                           HOSTNAME  MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS

066btqaw69byww15yfos2b8h6 *  node01    Accepted    Ready   Active        Leader

3vg00uxz3q6fr7qevhj8lpywj    node02    Accepted    Ready   Drain         

9ldzxwy20s3zz7k4k279q8dza    node03    Accepted    Ready   Active

Swarm przerzucił usługi na zdrowe węzły:

root@node01:/tmp# docker service tasks application_service_2

ID                         NAME                     SERVICE                IMAGE         LAST STATE            DESIRED STATE  NODE

dhhg2n4437i450byb0yr9qmyi  application_service_2.1  application_service_2  app_image_02  Preparing 14 seconds  Running        node01

20buphd7vdh8v1nehbz14hupn  application_service_2.2  application_service_2  app_image_02  Running 21 minutes    Running        node01

13ymp8zgrv0lrcckaxeqjq7rr  application_service_2.3  application_service_2  app_image_02  Running 20 minutes    Running        node03

2t1luej8908mnbjsg5f8kck3z  application_service_2.4  application_service_2  app_image_02  Preparing 14 seconds  Running        node03

841pi9ty7rqstg05znuusx4c5  application_service_2.5  application_service_2  app_image_02  Running 20 minutes    Running        node03

2z2440h71yc752lcbhg4pxgc1  application_service_2.6  application_service_2  app_image_02  Running 19 minutes    Running        node01

Przestawiamy zatem kolejny węzeł w stan DRAIN:

root@node01:/tmp# docker node update --availability drain node03

node03

Natychmiastowo swarm odpala taski na jedynym pozostałym przy życiu węźle:

root@node01:/tmp# docker service tasks application_service_2ID                         NAME                     SERVICE                IMAGE         LAST STATE                   DESIRED STATE  NODE

dhhg2n4437i450byb0yr9qmyi  application_service_2.1  application_service_2  app_image_02  Running 3 minutes            Running        node01

20buphd7vdh8v1nehbz14hupn  application_service_2.2  application_service_2  app_image_02  Running 24 minutes           Running        node01

0ul9zj9qaqqn2gcpcbiubjlak  application_service_2.3  application_service_2  app_image_02  Accepted Less than a second  Accepted       node01

dbbfmtwm54o4hrgxb3jovrnb0  application_service_2.4  application_service_2  app_image_02  Accepted Less than a second  Accepted       node01

cghq1augfo1mgnrbqdn4p8idk  application_service_2.5  application_service_2  app_image_02  Accepted Less than a second  Accepted       node01

2z2440h71yc752lcbhg4pxgc1  application_service_2.6  application_service_2  app_image_02  Running 23 minutes           Running        node01

Naprawiamy sytuację (a właściwie wracamy do stanu wyjściowego):

root@node01:/tmp# docker node update --availability active node03

node03

root@node01:/tmp# docker node update --availability active node02

node02

A teraz symulacja awarii (via service docker stop lub wręcz kill -9 na procesach dockera):

root@node01:/tmp# docker service tasks application_service_2

ID                         NAME                     SERVICE                IMAGE         LAST STATE          DESIRED STATE  NODE

7czubtzmdqtawo128x0axcsod  application_service_2.1  application_service_2  app_image_02  Running 34 seconds  Running        node02

1euzmm02djjnavg42wj359en6  application_service_2.2  application_service_2  app_image_02  Running 34 seconds  Running        node03

0ul9zj9qaqqn2gcpcbiubjlak  application_service_2.3  application_service_2  app_image_02  Running 3 minutes   Running        node01

euye2zuszub1it839obco7oti  application_service_2.4  application_service_2  app_image_02  Running 34 seconds  Running        node03

73vq1v246ypzl1xe0h4cymc0a  application_service_2.5  application_service_2  app_image_02  Running 34 seconds  Running        node03

5gcm7dmbyssq013x98t2uxii5  application_service_2.6  application_service_2  app_image_02  Running 34 seconds  Running        node02

[kill lub inne wyciągnięcie wtyczek z maszyny node03]

root@node01:/tmp# docker service tasks application_service_2

ID                         NAME                     SERVICE                IMAGE         LAST STATE                   DESIRED STATE  NODE

7czubtzmdqtawo128x0axcsod  application_service_2.1  application_service_2  app_image_02  Running 41 seconds           Running        node02

ebx1oj6e61tdjhj44ulvyb607  application_service_2.2  application_service_2  app_image_02  Accepted Less than a second  Accepted       node02
0ul9zj9qaqqn2gcpcbiubjlak  application_service_2.3  application_service_2  app_image_02  Running 3 minutes            Running        node01
eqpts6u91ax088qfj1eb713qc  application_service_2.4  application_service_2  app_image_02  Accepted Less than a second  Accepted       node02

8uc6h3ntw1rxvv7zwqry2809p  application_service_2.5  application_service_2  app_image_02  Accepted Less than a second  Accepted       node02

5gcm7dmbyssq013x98t2uxii5  application_service_2.6  application_service_2  app_image_02  Running 41 seconds           Running        node02

Jak widać swarm przełączył taski na nody które żyją , działa toto właściwie jak swarm reschedule , tyle że tam mieliśmy kontrolę nad tym co ma być przepinane a co nie – tutaj jest samograj 🙂

A teraz będzie o LoadBalancerach jaki ma nowy swarm mode – to już jest naprawdę super i jednocześnie naprawdę straszne… Tworzymy na każdym z 3 węzłów obraz serwujący hostname na porcie 80:

cat  /tmp/Dockerfile

FROM ubuntu:14.04

RUN apt-get -y update && apt-get -y install apache2

CMD apachectl start && hostname > /var/www/html/index.html && /bin/bash

Budujemy:

root@node02:~# docker build -t www_server .

Tworzymy service:

root@node02:/tmp# docker service create --replicas 6 --name www-service www_server 

root@node02:/tmp# docker service ls

ID            NAME         REPLICAS  IMAGE       COMMAND

9at6xt9i6nmk  www-service  0/6       www_server

Mamy 6 kontenerów:

root@node02:/tmp# docker service tasks www-service

ID                         NAME           SERVICE      IMAGE       LAST STATE                   DESIRED STATE  NODE

02f7uwos7q3xr5vgqd130s7z6  www-service.1  www-service  www_server  Preparing 5 seconds          Running        node01

dch7ngh98mryvbvxh49j8y8wj  www-service.2  www-service  www_server  Preparing 6 seconds          Running        node02

bvg7077u3ma7fwgooy1rzet7c  www-service.3  www-service  www_server  Preparing 6 seconds          Running        node02

7q1sz7pfwpcmn1df2gbxxjvke  www-service.4  www-service  www_server  Preparing 5 seconds          Running        node01

939b1wr9b624621vesj07izf2  www-service.5  www-service  www_server  Accepted Less than a second  Accepted       node03

1xuzqd0sgr2judis6cw470d39  www-service.6  www-service  www_server  Accepted Less than a second  Accepted       node03

I tu wychodzi kolejny problem – usługa się w kółko restartuje, powodem jest konieczność podania jakiegoś polecenia (CMD) podczas uruchamiania service – i niestety nie wystarczy że CMD jest w Dockerfile lub że jako CMD podano polecenie “bash”, na chwilę zastąpiłem to pingiem i zaczęło działać. Trochę mi to przypomina problemy z pluginem Jenkinsowym do Dockera, tam jest ten sam problem.

Niestety nawet standardowy obraz ubuntu nie działa jako service (przez ten nieszczęsny bash w CMD).

Skoro sprawy aż tak się komplikuję sprawdźmy zatem przykład podawany w dokumentacji na docs.docker.com czyli:

 docker service create --name redis redis:3.0.6

Oto jego sekcja CMD z dockerfile:

CMD [ "redis-server" ]

Po utworzeniu servicu jednak tu problemu nie ma – kontenery działają stabilnie, żaden się nie wyłącza a service nie ulega restartom , warto to gdzieś zapisać/zapamiętać, podejrzewam że może to być sporym źródłem problemów przy deploymentach. Wróćmy jednak do LoadBalancera , tworzymy nowy IMG i na jego bazie service z dodatkową opcją publish:

Dockerfile:

FROM ubuntu:14.04

EXPOSE 80

RUN apt-get -y update && apt-get -y install apache2

CMD apachectl start && hostname > /var/www/html/index.html && ping wp.pl

Tworzymy service (www3333 bo będzie na porcie 3333) z 2 replikami:

# docker service create --replicas 2 --name www3333 --publish 3333:80/tcp www_server

exgidsn8rstlwhneaap8ufihf

Jak widać swarm umieścił obydwie kopie na 1 węźle (node01)

# docker service tasks www3333

ID                         NAME       SERVICE  IMAGE       LAST STATE          DESIRED STATE  NODE

euvsyo4gid7elaqss3o2eyynf  www3333.1  www3333  www_server  Running 21 seconds  Running        node01

a3tge5v9b3tyju97pzgxjtjvb  www3333.2  www3333  www_server  Running 21 seconds  Running        node01

Mimo to jednak każdy z hostów otworzył port 3333:

root@node02:~# netstat -an | grep LISTEN | grep 3333

tcp6       0      0 :::3333                 :::*                    LISTEN     

root@node02:~# 

root@node01:~# netstat -an | grep LISTEN | grep 3333

tcp6       0      0 :::3333                 :::*                    LISTEN     

root@node01:~# 

root@node03:~# netstat -an | grep LISTEN | grep 3333

tcp6       0      0 :::3333                 :::*                    LISTEN     

root@node03:~#

Możemy teraz odpytywać curlem dowolny węzeł swarma – nawet ten na którym nie ma żadnego kontenera (np node03):

root@node03:~# docker ps

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES

root@node03:~# curl 127.0.0.1:3333

3b6d766298df

root@node03:~# curl 127.0.0.1:3333

57f4109eebb2

root@node03:~# curl 127.0.0.1:3333

3b6d766298df

root@node03:~# curl 127.0.0.1:3333

57f4109eebb2

Jak widać LB zwraca raz jeden raz drugi kontener. Ten sam test zróbmy na drugim węźle – również takim który nie ma kontenerów (node02):

root@node02:~# docker ps

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES

root@node02:~# curl 127.0.0.1:3333

3b6d766298df

root@node02:~# curl 127.0.0.1:3333

57f4109eebb2

root@node02:~# curl 127.0.0.1:3333

3b6d766298df

root@node02:~# curl 127.0.0.1:3333

57f4109eebb2

Mechanizm bardzo sympatyczny – żegnajcie jwilderry i inne reverse-proxy nasłuchujące na docker events , teraz swarm buduje sieć (typu ingress) i routuje wszystko w środku, oczywiście mechanizm pełen bugów (sporo wątków na githubie) i jednocześnie mało jasny i nie wiadomo jak konfigurowalny. No ale jest 🙂

Podsumowanie

Reasumując na zakończenie – w zamyśle swarm mode i cała reszta z 1.12 jest świetna, szkoda tylko że weszła dopiero teraz. Mnóstwo użytkowników na świecie (w tym i ja u siebie w swojej infrastrukturze) zbudowało już farmy w oparciu o dotychczasowe wersje, nie widzę jakoś synergii i prostej metody połączenia starego i nowego swarma. Oczywiście ten nowy jest w zamyśle lepszy i bardziej prosty ale z drugiej strony nieco pozbawia nas kontroli i możliwości podmiany poszczególnych komponentów farmy (lub ja na razie nie wiem jak to zrobić). Stary może i był skomplikowany ale po przejściu trudów instalacji pozwalał na pełną kontrolę i zarządzanie każdym z komponentów.

Nie jestem jedyną osobą która widzi minusy, podczas sesji Q&A po poszczególnych wystąpieniach na DockerCon inni userzy również zadawali pytania:

  • co z dotychczasowym mechanizmami swarm’a,
  • co z możliwością podmiany i konfiguracji load-balancerów,
  • jak działają te load-balancery,
  • czy będzie możliwość wprowadzenia własnego CA,
  • czy da się obracać kluczami inaczej niż w defaulcie,
  • itd. itp.

Zwróćmy uwagę że dotychczasowy swarm udawał API dockera więc można było do niego zapiąć np. shipyarda czy inny orkiestrator który nawet nie wiedział że zarządza klastrem. Teraz swoim ruchem docker spowodował ciężkie mandaysy developerów z firm około kontenerowych które muszą szybko wprowadzić nowe wersje wyposażone w komendę “service”.

Jednym słowem – IMHO 1.12 wyprodukowana aby zdążyć na DockerCon – udać im się udało ale wylali przy okazji z kąpielą mnóstwo dzieci i pracę wielu osób przy sklejaniu obecnych wersji do kupy. Nie kupuję tego. Czekam aż zrobią migration roadmap albo jakiś handbook o parametryzacji swarm mode. Bez tego zostaję na 1.11.