2

私は現在 CoreOS をいじくり回しており、それに基づいてクラスターを作成しています。これまでのところ、単一ホストでの CoreOS のエクスペリエンスは非常にスムーズです。しかし、サービス ディスカバリに関しては、少し曖昧になります。どういうわけか全体的なアイデアが得られないため、ここで助けを求めています。

私がやりたいことは、最初のコンテナーが 2 番目のコンテナーに依存する 2 つの Docker コンテナーを実行することです。純粋な Docker について話している場合は、リンクされたコンテナーを使用してこれを解決できます。ここまでは順調ですね。

ただし、Docker は複数のホスト間でコンテナーをリンクできないため、このアプローチはマシンの境界を越えては機能しません。だから私はこれを行う方法を考えています。

私がこれまでに理解したのは、これに対処する方法に関するCoreOSのアイデアは、etcd基本的にポートを介して各ホストでローカルにアクセスできる分散キー値ストアであるサービスを使用することであるという4001ことです。したがって、対処する必要はありません( の消費者としてetcd) ネットワークの詳細: アクセスするだけlocalhost:4001で問題ありません。

したがって、私の頭の中では、サービスを提供する Docker がスピンアップすると、自分自身 (つまり、その IP アドレスとそのポート) を local に登録し、Dockeretcd全体etcdに情報を配布することを意味するという考えが浮かびました。通信網。このようにして、たとえば次のようなキーと値のペアを取得します。

RedisService => 192.168.3.132:49236

現在、別の Docker コンテナが にアクセスする必要がある場合、少なくともネットワーク全体に情報が配布された後は、RedisService独自のローカル から IP アドレスとポートを取得します。etcdここまでは順調ですね。

しかし今、私には答えられない質問があり、それはすでに数日間私を困惑させています: サービスがダウンするとどうなりますか? 内のデータをクリーンアップするのは誰etcdですか? クリーンアップされていない場合、すべてのクライアントが存在しないサービスにアクセスしようとします。

現時点で私が考えることができる唯一の (信頼できる) 解決策はetcd、データに の TTL 機能を利用することですが、これにはトレードオフがあります: 数秒ごとにハートビートを送信する必要があるため、ネットワーク トラフィックが非常に多い、または古いデータと一緒に暮らす必要があります。どちらもいいじゃない。

私が考えることができるもう 1 つの「解決策」は、サービスがダウンしたときにサービス自体を登録解除することですが、これは計画的なシャットダウンに対してのみ機能し、クラッシュや停電などに対しては機能しません …</p>

それで、あなたはこれをどのように解決しますか?

4

1 に答える 1

8

これを解決するには、いくつかの異なる方法があります:ExecStopPost失敗時に使用および削除するサイドキック メソッド。CoreOSetcd、およびsystemdのトリオを想定していますが、これらの概念は他の場所にも適用できます。

相棒の方法

これには、メイン アプリケーションの隣で別のプロセスを実行し、ハートビートをetcd. 単純な面では、これは永久に実行される単なる for ループです。systemd の BindsTo を使用して、メイン ユニットが停止したときに、このサービス登録ユニットも停止するようにすることができます。ExecStop では、設定しているキーを明示的に削除できます。また、不正な停止に対処するために、TTL を 60 秒に設定しています。

[Unit]
Description=Announce nginx1.service
# Binds this unit and nginx1 together. When nginx1 is stopped, this unit will be stopped too.
BindsTo=nginx1.service

[Service]
ExecStart=/bin/sh -c "while true; do etcdctl set /services/website/nginx1 '{ \"host\": \"10.10.10.2\", \"port\": 8080, \"version\": \"52c7248a14\" }' --ttl 60;sleep 45;done"
ExecStop=/usr/bin/etcdctl delete /services/website/nginx1

[Install]
WantedBy=local.target

/health複雑な面として、これは、データを に送信する前にヘルス チェックを実行するためにアプリが提供するエンドポイントを起動してヒットするコンテナである可能性がありますetcd

ExecStopPost

メイン アプリ以外で何かを実行したくない場合はetcdctl、メイン ユニット内にコマンドを配置して、開始時と停止時に実行することができます。あなたが述べたように、これはすべての失敗をキャッチするわけではないことに注意してください。

[Unit]
Description=MyWebApp
After=docker.service
Require=docker.service
After=etcd.service
Require=etcd.service

[Service]
ExecStart=/usr/bin/docker run -rm -name myapp1 -p 8084:80 username/myapp command
ExecStop=/usr/bin/etcdctl set /services/myapp/%H:8084 '{ \"host\": \"%H\", \"port\": 8084, \"version\": \"52c7248a14\" }'
ExecStopPost=/usr/bin/etcdctl rm /services/myapp/%H:8084

[Install]
WantedBy=local.target

%H は、マシンのホスト名を置き換える systemd 変数です。より多くの変数の使用に興味がある場合は、CoreOS Getting Started with systemdガイドを確認してください。

失敗時の削除

クライアント側では、接続に X 回以上失敗したインスタンスを削除できます。から 500 またはタイムアウトが発生した/services/myapp/instance1場合は、実行して失敗回数を増やし続けてから、/services/myapp/ディレクトリ内の他のホストへの接続を試みることができます。

etcdctl set /services/myapp/instance1 '{ \"host\": \"%H\", \"port\": 8084, \"version\": \"52c7248a14\", \"failures\": 1 }'

希望のしきい値に達したら、 でキーを取り外しますetcdctl

ハートビートが引き起こすネットワーク トラフィックに関しては、ほとんどの場合、プロバイダーが実行するローカル プライベート ネットワークを介してこのトラフィックを送信する必要があるため、無料で非常に高速である必要があります。etcdとにかく、ピアと常にハートビートしているため、これはトラフィックのわずかな増加にすぎません。

他に質問がある場合は、Freenode の #coreos にアクセスしてください。

于 2014-02-06T18:32:43.920 に答える