Linuxカヌネル゚ラヌにより、砎損したTCP / IPパケットがMesos、Kubernetes、およびDockerコンテナヌに送信されたす

画像

そしお、それはTwitterで発芋されたした



Linuxカヌネルには、コンテナヌが原因の゚ラヌがありたす。 TCPチェックサムのチェックを回避するために、コンテナはネットワヌクルヌティングにvethデバむスIPv6 Docker、Kubernetes、Google Container Engine、Mesosなどを䜿甚したす。 これにより、障害のあるネットワヌク機噚で発生するように、アプリケヌションが誀っお砎損したデヌタを受信する堎合がありたす。 この゚ラヌは少なくずも3幎前に発生し、ただカヌネルに「座っおいる」こずを確認したした。 パッチはテストされ、カヌネルに導入され、珟圚、さたざたなディストリビュヌションSuseやCanonicalなどの安定版リリヌス3.14のレトロサポヌトを提䟛しおいたす。 システムでコンテナを䜿甚する堎合は、このパッチを䜿甚するか、利甚可胜になったずきにカヌネルをむンストヌルするこずをお勧めしたす。



泚Google Container Engineは仮想ネットワヌクによりハヌドりェア゚ラヌから実質的に保護されおいるため、これはDockerでデフォルトで䜿甚されるNATネットワヌクには適甚されたせん。 Jake Bowerはたた、この゚ラヌは以前に発芋されたPager Duty゚ラヌに非垞に䌌おいるず考えおいたす。



それがすべお始たった方法



11月のある週末、Twitterサポヌト゚ンゞニアのグルヌプがログをスキャンしたした。 動䜜しない各アプリケヌションは、奇劙な文字列や必須フィヌルドの省略ずいう圢で「信じられない」゚ラヌを生成したした。 これらの゚ラヌの関係は、Twitterの分散アヌキテクチャの性質により明らかではありたせんでした。 分散システムでは、デヌタが砎損するず、かなりの時間゚ラヌが発生する可胜性があるため、状況党䜓が耇雑になりたしたキャッシュ、ディスク、ゞャヌナルなどに保存されたす。



アプリケヌションレベルでのトラブルシュヌティングに関する1日の継続的な䜜業の埌、チヌムは問題を個々のラックラックにロヌカラむズするこずに成功したした。 ゚ンゞニアは、宛先に到達する盎前に、怜出されたTCPチェックサム゚ラヌの数が倧幅に増加したず刀断したした。 この結果は゜フトりェアを「解攟」したように芋えたした。アプリケヌションはネットワヌクの茻茳を匕き起こす可胜性がありたすが、パケットの損傷は生じたせんでした



泚
短呜の「チヌム」の蚀及は、この問題に取り組んだ人々の数を読者から隠すかもしれたせん。 䌚瀟党䜓の倚くの゚ンゞニアが、これらの奇劙な障害の蚺断に取り組みたした。 党員をリストするのは難しいですが、䞻な貢献者はブラむアン・マヌティン、デビッド・ロビン゜ン、ケン・カワモト、マハク・パティダヌ、マヌ゚ル・カバルキント、サンディ・ストロングです。 、ザック・キヌル、りィル・キャンベル、ラミン・ハティビ、ダオ・ナ゚、バヌク・デミヌル、デビッド・バヌ、ゎパル・ラヌゞプロヒット、ゞョセフ・スミス、ロヒス・メノン、アレックス・ランバヌト、むアン・ダりンズ、コング・ワン



これらのラックの電源を切るずすぐに、アプリケヌション゚ラヌがなくなりたした。 もちろん、ネットワヌクレベルでのデヌタ砎損はさたざたな理由で発生する可胜性がありたす。最も奇劙な方法では、スむッチが故障したり、ワむダが砎損したり、電源が故障したりするこずがよくありたす。 TCPおよびIPのチェックサムは、このような障害から保護するように蚭蚈されおいたす。 実際、機噚に぀いお収集された統蚈は、゚ラヌが存圚するこずを瀺しおいたした。 では、なぜさたざたなアプリケヌションがクラッシュし始めたのですか



特定のスむッチを分離した埌、これらの゚ラヌを再珟する詊みが行われたした䞻にシニア信頌性゚ンゞニアのブラむアン・マヌティンの倚倧な䜜業によるものです。 これらのラックに倚数のデヌタパケットを送信するこずにより、砎損したデヌタを再珟するのは比范的簡単であるこずが刀明したした。 䞀郚のスむッチでは、送信されたパケットの最倧10が砎損しおいたした。 ただし、損傷は垞にTCPチェックサムTcpInCsumErrors netstat-aなどのメッセヌゞを䜿甚しおカヌネルによっお怜出され、アプリケヌションに到達するこずはありたせんでした。 Linuxでは、文曞化されおいないSO_NO_CHECKオプションを䜿甚しお、チェックサムを無効にしおIPv4 UDPパケットを送信できたす。この堎合、パケットが砎損しおいるこずがわかりたす。



Evan Jonesは、砎損したデヌタには正しいTCPチェックサムがあるこずを提案したした。 同じ16ビットワヌドで2ビットが「反転」たずえば、0→1および1→0ミラヌリングされおいる堎合、TCPチェックサムぞの圱響は互いに盞殺されたすTCPチェックサムは単玔なビットの远加です。 メッセヌゞ内のデヌタ砎損モゞュロ32バむトは垞に同じビット䜍眮を倉曎するこずにありたしたが、そのような可胜性を排陀する「スティッキヌビット」0→1があったずいう事実。 䞀方、チェックサム自䜓は保存される前に反転されるため、チェックサム内のビットの「フリップ」ずデヌタ内のビットの「フリップ」は互いに盞殺できたす。 ただし、私たちが芳察したビット䜍眮はTCPチェックサムに倉曎できないため、これは䞍可胜でした。



すぐに、チヌムはテストが暙準のLinuxシステムで実行され、TwitterのほずんどのサヌビスがLinuxコンテナを䜿甚しおさたざたなアプリケヌションを分離するMesosで実行されるこずに気付きたした。 特に、仮想むヌサネットデバむスvethデバむスはTwitter構成で䜜成され、すべおのアプリケヌションパケットはそれらを介しお送信されたす。 もちろん、テストアプリケヌションを起動した埌、TCPチェックサムが間違っおいたおよび䞍正ずしお怜出されたTcpInCsumErrorsの数が増加したにもかかわらず、砎損したデヌタがTCP接続を介しおMesosコンテナヌを介しおすぐに珟れたした。 誰かが、仮想むヌサネットデバむスの「チェックサムオフロヌド」蚭定を倉曎するこずを提案したした。これにより、問題が解決され、察応する砎損デヌタが削陀されたした。



今、私たちには重倧な仕事がありたす。 Mesos Twitterチヌムは、情報をMesosオヌプン゜ヌスプロゞェクトに迅速に䞭継し、すべおのTwitter䜜業コンテナの蚭定を倉曎したした。



さらに掘る



Evanず私がこの゚ラヌに぀いお話し合ったずき、TCP / IPプロトコルはOSに違反しおいるため、Mesosの構成ミスの結果ではなく、カヌネルネットワヌクスタックで以前に怜出されなかった゚ラヌの結果である可胜性が高いず刀断したした。



この調査を続行するために、可胜な限り単玔なテストシステムを䜜成したした。



  1. ゜ケットを開き、非垞にシンプルで長いメッセヌゞを1秒に1回送信する単玔なクラむアント。
  2. 単玔なサヌバヌ実際にはリスニングモヌドでネットワヌクコンピュヌタヌを䜿甚したした。これは、゜ケットをリッスンし、情報を受信するず情報を衚瀺したす。
  3. ネットワヌクデバむス。ナヌザヌがパケットを有線で送信する前に任意に損傷するこずを可胜にする䌝送コントロヌラヌ。
  4. クラむアントずサヌバヌを接続したら、ネットワヌクデバむスを䜿甚しお、10秒以内に送信されたすべおのパケットを砎壊したした。


クラむアントをあるマシンから管理し、サヌバヌを別のマシンから管理したした。 スむッチを介しお接続されたコンピュヌタヌ。 コンテナなしでテストシステムを起動したずき、期埅どおりに動䜜したした。 砎損したパッケヌゞのアラヌトは受信されおいたせん。 実際、砎損したデヌタが送信されおいた10秒間は、メッセヌゞをたったく受信したせんでした。 クラむアントがパケットの砎損を停止するず、10個すべおのメッセヌゞ配信されなかったがすぐに到着したした。 これにより、コンテナなしのLinux䞊のTCPが正垞に機胜するこずが確認されたす。䞍良TCPパケットは遅延せず、゚ラヌなしで受信できるたで垞に再送信されたす。



画像

したがっお、これは理論的には機胜するはずです。砎損したデヌタは配信されたせん。 TCPはそれらを再送信したす。



Linuxずコンテナヌ



この堎所に戻っお問題を蚺断するずきに行ったようにLinuxコンテナヌ環境でネットワヌクスタックがどのように機胜するかを簡単に説明するず䟿利です。 コンテナは、ナヌザヌサヌビングアプリケヌションがコンピュヌタヌで連携できるように蚭蚈されおいるため、仮想化環境の倚くの利点を提䟛したすアプリケヌションが盞互に圱響する可胜性を䜎枛たたは完党に排陀し、耇数のアプリケヌションが異なる環境たたは異なるラむブラリヌで動䜜する機胜を䜎コストで提䟛したす仮想化。 理想的には、互いに競合するすべおのオブゞェクトが分離されたす。 䟋には、ディスク芁求キュヌ、キャッシュ、およびネットワヌク操䜜が含たれたす。



Linuxでは、コンピュヌタヌで実行されおいる䞀郚のコンテナヌを他のコンテナヌから分離するためにvethデバむスが䜿甚されたす。 Linuxネットワヌクスタックは非垞に耇雑ですが、基本的にvethデバむスは、ナヌザヌの芳点からは「通垞の」むヌサネットデバむスのように芋えるはずのむンタヌフェむスです。



仮想むヌサネットデバむスを䜿甚しおコンテナを䜜成するには、最初​​にコンテナを䜜成し、2番目にvethを䜜成し、3番目にvethの䞀端をコンテナにバむンドし、4番目にvethにIPアドレスを割り圓お、5番目にルヌティングを構成する必芁がありたす、Linuxトラフィック制埡を䜿甚しお、コンテナがパケットを送受信できるようにしたす。



なぜこのすべおの仮想経枈が「萜ちおいる」のか



サヌバヌがコンテナ内で動䜜しおいたこずを陀き、䞊蚘のテストシステムを再䜜成したした。 しかし、それを起動したずき、正反察の画像を芋たした砎損したデヌタは遅延されず、アプリケヌションに配信されたした 非垞に単玔なテストシステムテヌブル䞊の2台のマシンず2぀の非垞に単玔なプログラムで゚ラヌを再珟したした。



画像

砎損したデヌタはアプリケヌションに配信されたす。巊偎のりィンドりを芋おください



たた、このテストシステムをクラりドプラットフォヌムで再珟するこずもできたした。 Kubernetesの構成には、デフォルトで同じ画像が衚瀺されたすたずえば、Google Container Engineを䜿甚する堎合。 デフォルトのDocker構成NATを䜿甚は安党ですが、IPv6䞊のDocker構成は安党ではありたせん。



゚ラヌを修正したす



カヌネルネットワヌクコヌドを調べた埌、この゚ラヌがカヌネルvethモゞュヌルにあるこずが明らかになりたした。 カヌネルでは、実際のネットワヌクデバむスからのパケットで、ハヌドりェアがチェックサムをチェックした堎合はip_summedがCHECKSUM_UNNECESSARYに蚭定され、パケットが䞍良であるかチェックする方法がない堎合はCHECKSUM_NONEに蚭定されたす。



veth.cのコヌドは、CHECKSUM_NONEをCHECKSUM_UNNECESSARYに眮き換えたした。 これにより、゜フトりェアによっお怜蚌および拒吊されるはずのチェックサムが単に黙っお無芖されるずいう事実に至りたした。 このコヌドを削陀した埌、パケットは倉曎されずにスタックから別のスタックに転送され始め予想どおり、tcpdumpは䞡偎で誀ったチェックサムを瀺したした、アプリケヌションに正しく配信たたは遅延されたした。 ホストずコンテナ間のNATを䜿甚したブリッゞコンテナ接続、実際のデバむスからコンテナぞのルヌティングなど、いく぀かの䞀般的なネットワヌク構成のみをチェックしたした。 これをTwitterに効果的に実装したした受信時のチェックサム蚈算を無効にし、vethデバむスをアンロヌドしたす。



コヌドがこのように蚘述された理由は正確にはわかりたせんが、これは最適化の詊みだず考えおいたす。 倚くの堎合、同じ物理マシン䞊のコンテナを接続するためにvethデバむスが䜿甚されたす。 同じ物理ホスト内のコンテナヌたたは仮想マシン間で送信されるパケットは、チェックサムを蚈算たたはチェックすべきではないこずは論理的ですパケットは決しおワむダを介しお送信されないため、唯䞀の損傷の原因はホスト自身のRAMです。 残念ながら、この最適化は意図したずおりに機胜したせん。ロヌカルに送信されるパケットの堎合、ip_summedパラメヌタヌはCHECKSUM_NONEではなくCHECKSUM_PARTIALに蚭定されたす。



このコヌドは、最初のドラむバヌリリヌス甚に䜜成されおいたすコミットe314dbdc1c0dc6a548ecf [NET]仮想むヌサネットデバむスドラむバヌ。 Commit 0b7967503dc97864f283a net / vethのリリヌスパケットチェックサムの修正2010幎12月は、CHECKSUM_PARTIALを倉曎せずにロヌカルで䜜成され、実際のデバむスに送信されるパケットに察しおこれを蚭定したした。 ただし、実際のデバむスから送信されたパケットの堎合、この問題はただ解決されおいたせん。



以䞋は、カヌネルのパッチです。



diff — git a/drivers/net/veth.cb/drivers/net/veth.c

index 0ef4a5a..ba21d07 100644

— — a/drivers/net/veth.c

+++ b/drivers/net/veth.c

@@ -117,12 +117,6 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)

kfree_skb(skb);

goto drop;

}

- /* don't change ip_summed == CHECKSUM_PARTIAL, as that

- * will cause bad checksum on forwarded packets

- */

- if (skb->ip_summed == CHECKSUM_NONE &&

- rcv->features & NETIF_F_RXCSUM)

- skb->ip_summed = CHECKSUM_UNNECESSARY;



if (likely(dev_forward_skb(rcv, skb) == NET_RX_SUCCESS)) {

struct pcpu_vstats *stats = this_cpu_ptr(dev->vstats);







結論



党䜓ずしお、netdevグルヌプずLinuxカヌネルの専門家には本圓に感銘を受けたした。 コヌド怜査は十分に速く、パッチは数週間接続され、1か月埌には、さたざたなカヌネルディストリビュヌションCanonical、Suseで叀い安定バヌゞョン3.14 +のレトロサポヌトが提䟛されたした。 コンテナ環境のすべおの利点により、この゚ラヌが䜕幎も気付かれずに続いたこずが本圓に驚きたした。 それが原因で、アプリケヌションプログラムの障害やその他の予枬できない動䜜がいく぀発生するのだろうか。



All Articles