こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。
この記事ではDocker Swarm環境にデフォルトで作成されるingressにserviceをデプロイ。コンテナ間通信を可能にし、更に負荷分散をしているところを確認してみます。
ingressとは
ザックリ行ってしまうと、
- ホスト間のオーバレイネットワークを構築するもの
- これがあるとホストを跨ったコンテナ間の通信が出来る
- 良い感じにロードバランシングしてくれる
って感じだと思っています。(間違っていたらすみません)
コンテナオーケストレーションツールとしてkubernetesが有名ですが、そちらでもingressはありますね。恐らくニュアンス的にはSwarmもkuberenetesも変わらないと思っています。
※関係ないですがオーバレイネットワークって響きが最高にかっこいいですよね。厨二病を刺激されます。
ingressを指定してserviceをデプロイする
デフォルトのingressを指定してserviceをデプロイする為にはdocker service createに--publishオプションを指定してあげると良い様子。
以下の場合、コンテナの数が常に3つになるように、ホストの8080ポートに接続があった場合httpdコンテナの80ポートに転送するようにしています。
root@docker:~# docker service create --replicas=3 --name httpd --publish publish
ed=8080,target=80 httpd:latest
x57l3av545tbxvqffbowlwgjw
overall progress: 3 out of 3 tasks
1/3: running
2/3: running
3/3: running
verify: Service converged
root@docker:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c03147d2f83c httpd:latest "httpd-foreground" 3 minutes ago Up 3 minutes 80/tcp httpd.1.t5zt9glbr4tlgjofhcozjz7bi
521b69dd00e9 nginx:latest "/docker-entrypoint.…" 31 hours ago Up 31 hours 80/tcp my-nginx.3.hux0zd2goc6974s25n4vvafcj
8240d0af95a3 portainer/portainer-ce "/portainer" 7 days ago Up 31 hours 0.0.0.0:8000->8000/tcp, :::8000->8000/tcp, 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp, 9443/tcp portainer
root@docker:~# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
x57l3av545tb httpd replicated 3/3 httpd:latest *:8080->80/tcp
g4inx6fpvjzb my-nginx replicated 5/5 nginx:latest *:80->80/tcp
root@docker:~# docker service ps httpd
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
t5zt9glbr4tl httpd.1 httpd:latest docker Running Running 9 minutes ago
l9y0iwo3ig2d httpd.2 httpd:latest swarm-worker01 Running Running 9 minutes ago
rbra2u5gg8s9 httpd.3 httpd:latest swarm-worker02 Running Running 9 minutes ago
各コンテナのIPアドレスを見てみましょう。
Leader
root@docker:~# docker inspect httpd.1.t5zt9glbr4tlgjofhcozjz7bi | grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "",
"IPAddress": "10.0.0.16",
worker01
root@swarm-worker01:~# docker inspect httpd.2.l9y0iwo3ig2dib0du7wh16wpf | grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "",
"IPAddress": "10.0.0.17",
worker02
root@swarm-worker02:~# docker inspect httpd.3.rbra2u5gg8s9bpps6ijvv7g19 | grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "",
"IPAddress": "10.0.0.18",
ingressのネットワークを見てみます。
コンテナと同じネットワークにいるということと、Containersの部分でhttpd.1を認識していることから、httpdコンテナはこれに繋がっていると思って間違いないでしょう。
root@docker:~# docker network inspect ingress
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "10.0.0.0/24",
"Gateway": "10.0.0.1"
}
]
},
中略
"Containers": {
"521b69dd00e926866e1cf341b369a65e00288c8e982a8bdae7b5d7631c1eb7fc": {
"Name": "my-nginx.3.hux0zd2goc6974s25n4vvafcj",
"EndpointID": "2c9e925936cec8c030a031693c3f834123f0a3afe3bab3c24b9486739dec4d57",
"MacAddress": "02:42:0a:00:00:0a",
"IPv4Address": "10.0.0.10/24",
"IPv6Address": ""
},
"c03147d2f83cc0f90706913ac78f56f85e3ed16afe7b3e0b771bb9447603d4a6": {
"Name": "httpd.1.t5zt9glbr4tlgjofhcozjz7bi",
"EndpointID": "6c6403c4ff692e275004245921571befc4701e816b560fd079f6d741bb530afd",
"MacAddress": "02:42:0a:00:00:10",
"IPv4Address": "10.0.0.16/24",
"IPv6Address": ""
},
"ingress-sbox": {
"Name": "ingress-endpoint",
"EndpointID": "1f85e65c9f18ca7aded3222893dc2ae63dfcaa37609a0e6c39ae1a072027495c",
"MacAddress": "02:42:0a:00:00:02",
"IPv4Address": "10.0.0.2/24",
"IPv6Address": ""
}
},
ingressに繋がっているコンテナ同士で疎通が取れるか確認する
httpd.1からhttpd.2と3に対してping疎通を確認します。
以下のログから疎通が取れていることが分かると思います。
root@c03147d2f83c:/usr/local/apache2# ping 10.0.0.17
PING 10.0.0.17 (10.0.0.17): 56 data bytes
64 bytes from 10.0.0.17: icmp_seq=0 ttl=64 time=4.238 ms
64 bytes from 10.0.0.17: icmp_seq=1 ttl=64 time=0.802 ms
64 bytes from 10.0.0.17: icmp_seq=2 ttl=64 time=0.784 ms
64 bytes from 10.0.0.17: icmp_seq=3 ttl=64 time=0.707 ms
64 bytes from 10.0.0.17: icmp_seq=4 ttl=64 time=0.874 ms
^C--- 10.0.0.17 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.707/1.481/4.238/1.380 ms
root@c03147d2f83c:/usr/local/apache2# ping 10.0.0.18
PING 10.0.0.18 (10.0.0.18): 56 data bytes
64 bytes from 10.0.0.18: icmp_seq=0 ttl=64 time=5.083 ms
64 bytes from 10.0.0.18: icmp_seq=1 ttl=64 time=0.745 ms
64 bytes from 10.0.0.18: icmp_seq=2 ttl=64 time=0.639 ms
64 bytes from 10.0.0.18: icmp_seq=3 ttl=64 time=0.703 ms
64 bytes from 10.0.0.18: icmp_seq=4 ttl=64 time=0.966 ms
^C--- 10.0.0.18 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.639/1.627/5.083/1.731 ms
ingressが負荷分散をしていることを確認する
確認の仕方として、それぞれのhttpdコンテナのindex.htmlをそれぞれ固有のものに変更。
ホストに対してhttp接続を何度かしてみて出力される内容が定期的に変わる(ingressからロードバランシングして、表面上Webブラウザから接続しているホストは同じだけど、実際にアクセスしているコンテナは別になっている)ことを確認してみたいと思います。
現状、それぞれのホストにWebブラウザで8080ポートを指定してアクセスすると以下の様な出力結果となります。
このままではどのhttpdコンテナに接続しているのかわかりません。
仕込みを入れていきたいと思います。
apache2のindex.htmlを書き換えていきます。apache2のindex.htmlは/usr/local/apache2/htdocsにあるみたいです。
コンテナにviコマンドは無いのでインストールし、index.htmlを編集します。
編集後、apacheに設定反映を行うためrestartを実施します。
※エラーっぽいのが出てますが、設定反映されていることは確認できたため、今回はスルー。
Leader
root@docker:~# docker ps
doCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c03147d2f83c httpd:latest "httpd-foreground" 12 minutes ago Up 12 minutes 80/tcp httpd.1.t5zt9glbr4tlgjofhcozjz7bi
521b69dd00e9 nginx:latest "/docker-entrypoint.…" 31 hours ago Up 31 hours 80/tcp my-nginx.3.hux0zd2goc6974s25n4vvafcj
8240d0af95a3 portainer/portainer-ce "/portainer" 7 days ago Up 31 hours 0.0.0.0:8000->8000/tcp, :::8000->8000/tcp, 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp, 9443/tcp portainer
root@docker:~# docker exec -it httpd.1.t5zt9glbr4tlgjofhcozjz7bi /bin/bash
root@c03147d2f83c:/usr/local/apache2# cd /usr/local/apache2/htdocs
root@c03147d2f83c:/usr/local/apache2/htdocs# ls -ltr
total 4
-rw-r--r-- 1 501 staff 45 Jun 11 2007 index.html
root@c03147d2f83c:/usr/local/apache2/htdocs# cat index.html
<html><body><h1>It works!</h1></body></html>
root@c03147d2f83c:/usr/local/apache2/htdocs# apt update
root@c03147d2f83c:/usr/local/apache2/htdocs# apt upgrade
root@c03147d2f83c:/usr/local/apache2/htdocs# apt-get install vim
root@c03147d2f83c:/usr/local/apache2/htdocs# vi index.html
root@c03147d2f83c:/usr/local/apache2/htdocs# cat index.html
<html><body><h1>It works on node:192.168.2.177!</h1></body></html>
root@c03147d2f83c:/usr/local/apache2/htdocs# /usr/local/apache2/bin/apachectl restart
AH00557: httpd: apr_sockaddr_info_get() failed for c03147d2f83c
AH00558: httpd: Could not reliably determine the server's fully qualified domainerName' directive globally to suppress this message
worker01
root@swarm-worker01:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7f81733ca153 httpd:latest "httpd-foreground" 21 minutes ago Up 21 minutes 80/tcp httpd.2.l9y0iwo3ig2dib0du7wh16wpf
1f9410c4ecb2 nginx:latest "/docker-entrypoint.…" 31 hours ago Up 31 hours 80/tcp my-nginx.5.9nm6wov2o74y9uzfetpbv4b6d
ff92cb76fad6 nginx:latest "/docker-entrypoint.…" 31 hours ago Up 31 hours 80/tcp my-nginx.2.1r2rq8q5a5uiy0ywybgin8pjb
root@swarm-worker01:~# docker exec -it httpd.2.l9y0iwo3ig2dib0du7wh16wpf /bin/bash
root@7f81733ca153:/usr/local/apache2# cd /usr/local/apache2/htdocs
root@7f81733ca153:/usr/local/apache2/htdocs# ls -ltr
total 4
-rw-r--r-- 1 501 staff 45 Jun 11 2007 index.html
root@7f81733ca153:/usr/local/apache2/htdocs# cat index.html
<html><body><h1>It works!</h1></body></html>
root@7f81733ca153:/usr/local/apache2/htdocs# apt update
root@7f81733ca153:/usr/local/apache2/htdocs# apt upgrade
root@7f81733ca153:/usr/local/apache2/htdocs# apt-get install vim
root@7f81733ca153:/usr/local/apache2/htdocs# vi index.html
root@7f81733ca153:/usr/local/apache2/htdocs# cat index.html
<html><body><h1>It works on node:192.168.2.188!</h1></body></html>
root@7f81733ca153:/usr/local/apache2/htdocs# /usr/local/apache2/bin/apachectl restart
AH00557: httpd: apr_sockaddr_info_get() failed for 7f81733ca153
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName' directive globally to suppress this message
worker02
root@swarm-worker02:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
41f566a7b21e httpd:latest "httpd-foreground" 31 minutes ago Up 31 minutes 80/tcp httpd.3.rbra2u5gg8s9bpps6ijvv7g19
0507bb89e81b nginx:latest "/docker-entrypoint.…" 31 hours ago Up 31 hours 80/tcp my-nginx.4.zprs5gbh2krbrakov75trn2e2
8b531cf804d8 nginx:latest "/docker-entrypoint.…" 31 hours ago Up 31 hours 80/tcp my-nginx.1.mk4z1xgsd04kc5hb8uiwk593w
root@swarm-worker02:~# docker exec -it httpd.3.rbra2u5gg8s9bpps6ijvv7g19 /bin/bash
root@41f566a7b21e:/usr/local/apache2# cd /usr/local/apache2/htdocs
root@41f566a7b21e:/usr/local/apache2/htdocs# ls -ltr
total 4
-rw-r--r-- 1 501 staff 45 Jun 11 2007 index.html
root@41f566a7b21e:/usr/local/apache2/htdocs# cat index.html
<html><body><h1>It works!</h1></body></html>
root@41f566a7b21e:/usr/local/apache2/htdocs# apt update
root@41f566a7b21e:/usr/local/apache2/htdocs# apt upgrade
root@41f566a7b21e:/usr/local/apache2/htdocs# apt-get install vim
root@41f566a7b21e:/usr/local/apache2/htdocs# vi index.html
root@41f566a7b21e:/usr/local/apache2/htdocs# cat index.html
<html><body><h1>It works on node:192.168.2.199!</h1></body></html>
root@41f566a7b21e:/usr/local/apache2/htdocs# /usr/local/apache2/bin/apachectl restart
AH00557: httpd: apr_sockaddr_info_get() failed for 41f566a7b21e
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName' directive globally to suppress this message
仕込みが完了したらWebブラウザでコンテナが稼働しているホストに何度か接続してみます。
今回はそれぞれ3回ずつ接続をしてみました。
接続するたびに出力されている内容が変わっていることが分かると思います。
ingressがロードバランシングを行い、接続しているコンテナが変わっていることが分かると思います。
ホスト192.168.2.177のみ着目した通信の流れですが、イメージとして以下の様になります。
赤くしたところが通信の可能性のある経路となります。