メインコンテンツまでスキップ

「Docker Swarm」タグの記事が3件件あります

全てのタグを見る

snake

DockerのSwarm modeには、ルーティングメッシュと呼ばれる機能があります。この機能により、外部からのアクセスをロードバランシングすることができます。ルーティングメッシュにより、接続先のノード自身がタスクを実行していなくても、タスクが利用可能なノード上へリクエストを転送してくれるようになります。 Use swarm mode routing mesh

この機能は便利であり、Swarmを冗長構成にするのであれば、必要不可欠な機能の一つです。ただし、ルーティングメッシュが有効になっている場合、アクセス元のIPアドレスを取得できない可能性がある問題が存在しています。正確には取得できますが、接続元のIPアドレスではなく、アクセスを受け付けたノードのIPアドレスが取得されます。

最初に提示した画像を元に説明を行います。

仮に203.0.113.10から Node-03(192.168.10.102:8080)へアクセスがあったとします。Node-03上に利用可能なタスクがないため、全てのリクエストは利用可能なタスクの存在する異なるノードへ転送されます。そのためNode-01もしくはNode-02のnginx.1がアクセスを受けます。この時、アクセスを受けたnginx.1でアクセスログを確認すると、接続元のIPアドレスはNode-03のIPアドレスである192.168.10.102が記録されています。

という訳で、ルーティングメッシュによりリクエストが転送された場合、転送元のノードのIPアドレスが記録されてしまいます。

一般的に元のIPアドレスを取得場合、httpではX-Forwarded-Forと呼ばれるプロキシを通した際に元のIPアドレスを保持する仕組みを利用し、L4ではProxy Protocolと呼ばれるロードバランサを通した際に元のIPアドレスを保持する仕組みを利用します。

しかしながら、ルーティングメッシュによって転送されたリクエストは、X-Forwarded-ForやProxy Protocolが対応してないんですね。類する代替手段が用意されている訳でもないため、Docker Swarmのみで元のIPを取得することは不可能です。

この問題はすでに把握されており、issueは立ち上げられています。しかし、2016年から開かれ続けており、すぐに解決される問題ではない気がします。

Unable to retrieve user’s IP address in docker swarm mode · Issue #25526 · moby/moby

Proxy Protocolのサポートも同様にissueは立ち上がっているものの、すぐに解決される問題ではなさそうです。

Proxy Protocol support in Swarm ingress · Issue #39465 · moby/moby

対処法1

この問題に対する対処法として、ルーティングメッシュの無効化があります。しかし、Overlay Networkの利点を失うことになる点は注意してください。

Docker-composeの場合、long syntaxでポートを以下のように指定することでルーティングメッシュを無効化することができます。

  • target: 80 published: 80 protocol: tcp mode: host
  • target: 53 published: 53 protocol: udp mode: host

modeを省略した場合、もしくは、ingressを設定した場合はルーティングメッシュが有効になります。

Docker Swarmを使う意味がよく分からなくなりますが、クラスタの外側にHAProxyのようなロードバランサを設置してあげることで、ルーティングメッシュみたいなことはできるようになります。

対処法2

docker-ingress-routing-daemonなるものを利用することで、元のIPアドレスを取得できるようになるらしいですが、使ったことがないので詳しいことはよく分かりません。少なくとも、私は複雑になり過ぎるので使おうと思いませんでした。

GitHub - newsnowlabs/docker-ingress-routing-daemon: Docker swarm daemon that modifies ingress mesh routing to expose true client IPs to service containers

snake

lucaslorentz/caddy-docker-proxy で発生するエラー「Service is not in same network as caddy」に対する解決策です。

前提

Docker Swarmでlucaslorentz/caddy-docker-proxy をデプロイし、各種コンテナへのリバースプロキシ用のラベルを適切に設定されている状態。

特に他にエラーが見られず設定に問題がないのにも関わらずエラーが発生する場合。

エラー内容

エラーは以下の通りです。

"msg":"Failed to get ingress networks" "error":"Cannot find container id in cgroups" "msg":"Service is not in same network as caddy"

修正方法

環境変数の CADDY_INGRESS_NETWORKS に属するネットワークを設定する。

例えば、externalの public ネットワークに参加しており、 public に属するコンテナへプロキシを行う場合は、 CADDY_INGRESS_NETWORKS=public と環境変数を設定する必要がある。

docker-compose.yml 例

version: "3.7" services: caddy: image: lucaslorentz/caddy-docker-proxy:ci-alpine ports:

  • 80:80
  • 443:443 environment:
  • CADDY_INGRESS_NETWORKS=public networks:
  • public volumes:
  • /var/run/docker.sock:/var/run/docker.sock
  • caddy_data:/data restart: unless-stopped

networks: public: external: true

volumes: caddy_data:

snake

Docker Engineが標準的に提供するオーケストラレーションツールであるDocker Swarmについて、マネージャーノードはいくつが良いのかが分からなかったので、簡単に調べました。それについてちょっとだけまとめておきます。基本的に語っていることは公式のドキュメントと大差ありませんので、より詳細で正確な情報を知りたい場合は、公式ドキュメントをご確認ください。

Docker Documentation

※この投稿で言う「Docker Swarm」は、Docker Engineに標準的に組み込まれているSwarm modeを指しています。

Docker SwarmのマネージャーノードはRaftコンセンサスアルゴリズム(分散合意アルゴリズム)によって状態管理が行われます。通常、このアルゴリズムについて詳しく理解する必要はありませんが、概要を理解することでマネージャーノードの数を決定する役に立ちます。

マネージャーノードの数とパフォーマンス

Docker Swarmでクラスターに追加できるマネージャーノード数には、制限がなく、追加しようと思えばいくらでも追加することができます。基本的な考え方として、マネージャーノードの数が多ければ多いほど、障害耐性が強くなります。しかし、ほとんどの場合でマネージャーノードの増加はパフォーマンスの悪化を引き起こします。これは単純にノードの追加・削除といった処理を多数のノードで行う必要があるためです。数が増えればその分パフォーマンスが悪化します。

マネージャーノードとquorum

Docker Swarmでマネージャーノードが何らかのタスクを実行する際には、quorumと呼ばれるものが必要です。quorumは分散システムでよく利用されるものであり、処理の整合性を保つために使われます。Docker Swarmでは、このquorumが全マネージャーノードの半数を超過する必要があります。これは単純な議決のように考えることができ、参加者の半数を超過した数が賛同しなければ、実行することができません。

注意点:quorumは全マネージャーノードの半数を超過している必要があります。6ノード存在する場合、半数の3の超過、つまり4以上のquorumが必要です。

では、以上を踏まえてquorumが常に半数以上確保できる環境を考えてみます。

マネージャーノードが1つである場合、1つのマネージャーノードが必要です。もしマネージャーノードが1つダウンした場合、クラスターではタスクが実行できなくなります。この場合、必要なquorumが1となる為、1つでもダウンすると必要quorumに達しません。

マネージャーノードが2つである場合、2つのマネージャーノードが必要です。もしマネージャーノードが1つダウンした場合、クラスターではタスクが実行できなくなります。この場合、必要なquorumが2となる為、1つでもダウンすると必要quorumに達しません。

マネージャーノードが3つである場合、3つのマネージャーノードが必要です。もしマネージャーノードが1つダウンした場合、クラスターでのタスクが実行可能です。この場合、必要なquorumが2となる為、1つのダウンまでは許容されます。2つダウンした場合は、必要quorumに達しません。

マネージャーノードが4つである場合、4つのマネージャーノードが必要です。もしマネージャーノードが1つダウンした場合、クラスターでのタスクが実行可能です。この場合、必要なquorumが3となる為、1つのダウンまでは許容されます。2つダウンした場合は、必要quorumに達しません。

同様の考え方でそれ以上の数の場合でも考えていくことができます。

quorumについて、以下に簡単にまとめます。

Docker Swarmでは:

  • 最大 (N-1)/2 までの障害が許容されます。
  • クラスターでのタスク実行には (N/2)+1 ノードのquorumが必要です。

マネージャーノードの耐障害性

これまでの内容を踏まえ、マネージャーノードの耐障害性について考えていきます。

以下はマネージャーノード数が1~9の場合に必要なquorumと、ダウンが許容されるノード数を表にまとめたものです。表は、「Administer and maintain a swarm of Docker Engines | Docker Documentation」から引用しています。 マネージャーノード数quorum許容値110220321431532642743853954 マネージャーノード数が偶数(2, 4, 6, 8~)である場合、耐障害性に対するメリットはありません。例えば、マネージャーノード数が 4 である場合 2ノード 以上がダウンすると、quorumが足らなくなります。しかし、マネージャーノード数が 3 である場合も同様に 2ノード 以上のダウンでquorumが足らなくなります。マネージャーノード数が 3 もしくは 4 の場合のどちらであっても、ダウンが許容されるノード数は 1 です。

そのためマネージャーノード数は奇数(1, 3, 5, 7, 9)であることが、望ましいです。

適切なマネージャーノード数

最後に適切なマネージャーノード数について考えます。とはいえども、ここまで流れで読んできていれば、何となく分かっているかもしれません。

クラスターの耐障害性を確保するために、マネージャーノードが複数であることは必要です。Docker Swarmでは、マネージャーノードがなければクラスターでタスクの実行が不可能になるためです。

  • 通常、クラスターを構築する場合、マネージャーノード数 3 は目指すべき最低限のラインです。
  • クラスターが中規模である場合は、マネージャーノード数 5 を目指すべきです。
  • クラスターが大規模である場合は、マネージャーノード数 7 を目指すべきです。

中規模は数百のノードである場合を指し、大規模は数千のノードである場合を指します。この規模感のノード数は、殆どの場合エンタープライズなので、個人で検証することは難しいです。そのため明確な根拠を出すことができません。

では、上記よりも更にクラスターの規模が大規模であり、マネージャーノードが不足していると感じている場合は、マネージャーノード数を 9 にするべきでしょうか。この場合は、増やすべきではないという答えになります。

Dockerの公式ドキュメントでは、次のように言及されています。

Docker recommends a maximum of seven manager nodes for a swarm.

Important Note: Adding more managers does NOT mean increased scalability or higher performance. In general, the opposite is true.

How nodes work | Docker Documentation 雑に翻訳すると以下のようになります。

Dockerでは、Swarmに対して最大7のマネージャーノードが推奨されています。 注意:マネージャーノードを追加しても、スケーラビリティーの向上やパフォーマンスの向上には繋がりません。通常、その逆が起こります。

一切の効果がないと断言することは私にはできませんが、少なくとも公式ドキュメントで非推奨である旨が明示されています。

参考

Administer and maintain a swarm of Docker Engines

How nodes work

Pros and Cons of running all Docker Swarm nodes as Managers?

How to handle when leader node goes down in docker swarm