Docker ネットワークの基礎 |仮想ネットワークデバイスペア(Veth)の原理

Docker ネットワークの基礎 |仮想ネットワークデバイスペア(Veth)の原理

[[402397]]

この記事はWeChatの公開アカウント「Linux Kernel Things」から転載したもので、著者はsongsong001です。この記事を転載する場合は、Linux Kernel Matters パブリック アカウントにご連絡ください。

コンテナ化が普及しつつある今日、Docker はコンテナ界の寵児と言えるでしょう。かさばる仮想マシンと比較すると、Docker はツバメのように軽量です。もちろん、この記事では仮想マシンと Docker の長所と短所を紹介するのではなく、Docker ネットワークの重要なコンポーネントの 1 つを紹介します。

仮想ネットワークデバイスペア: veth

veth を紹介する前に、まずネットワーク名前空間を紹介しましょう。

ネットワーク名前空間

ネットワーク名前空間は、Linux カーネルによって、異なるコンテナ間のネットワーク リソースを分離するために使用されます (各 Docker コンテナには独立したネットワーク名前空間があります)。ネットワーク名前空間は主に次のリソースを分離します。

  • iptables ルールテーブル
  • ルーティングルールテーブル
  • ネットワークデバイスリスト

次の図に示すように、システム内に 3 つのネットワーク名前空間がある場合:

異なるネットワーク名前空間は互いに分離されているため、直接通信することはできません。たとえば、IP アドレスが 172.17.42.1 のデバイスはネットワーク名前空間 A に設定されていますが、次の図に示すように、ネットワーク名前空間 B ではアクセスできません。

2 台のコンピューターの場合と同様に、ネットワーク ケーブルで接続されていないと、コンピューター同士は通信できません。そのため、Linux カーネルは、異なるネットワーク名前空間間の通信を解決するために、仮想ネットワーク デバイス ペア (veth) 機能を提供します。

仮想ネットワークデバイスペア (veth)

仮想ネットワーク デバイス ペアは、異なるネットワーク名前空間間の通信を解決するために使用され、ネットワーク ケーブルで接続された 2 つのネットワーク カードとして表示できます。次の図に示すように、ネットワーク カードの 1 つがネットワーク名前空間 A に配置され、もう 1 つのネットワーク カードがネットワーク名前空間 B に配置されている限り、2 つの異なるネットワーク名前空間は通信できます。

上図に示すように、veth0 と veth1 は仮想ネットワーク デバイス ペアを形成します。仮想ネットワーク デバイス ペアはパイプのようなものです。データが一方の端に送信されれば、もう一方の端からデータを受信できます。

Docker は仮想ネットワーク デバイスを使用して、異なるコンテナー間の通信を実装します。原則は次のとおりです。

上の図からわかるように、各コンテナは仮想ネットワークデバイスペアを介して直接接続されていません。代わりに、ホスト上に docker0 という名前のブリッジが作成され、各コンテナは仮想ネットワーク デバイス ペアを介してブリッジに接続されます。ブリッジは、実際のスイッチと同様に、複数のネットワーク デバイスを接続する機能を備えています。

もちろん、この記事のテーマは veth の実装であり、ブリッジの実態ではないので、ブリッジの紹介はここで終わります。ご興味がございましたら、「Linux Bridge の動作原理と実装」の記事を参照してください。

仮想ネットワークデバイスペアの実装

Linux カーネルでは、ネットワーク デバイスは net_device オブジェクトによって表されます。 veth は双方向通信を提供するため、これを実装するには 2 つの net_device オブジェクトが必要です。 net_device オブジェクトは非常に大きいため、この記事に関連するフィールドのみをここにリストします。

  1. 構造体net_device
  2. {
  3. 文字 名前[IFNAMSIZ];
  4. ...
  5. 定数構造体net_device_ops *netdev_ops;
  6. ...
  7. }

これら 2 つのフィールドの機能について次に説明します。

  • name: eth0 などのデバイス名を保存するために使用されます。
  • netdev_ops: デバイスを初期化するためのインターフェース、デバイスをシャットダウンするためのインターフェース、データを送信するためのインターフェースなど、デバイス関連の操作インターフェースのリスト。

veth は 2 つの net_device オブジェクトで構成されているため、これら 2 つの net_device オブジェクトは互いへのポインターを持つ必要があります。しかし、コードを調べても、お互いを指すポインターは見つかりませんでした。カーネルは veth をどのように実装するのでしょうか?

Linux カーネルは、net_device オブジェクトを使用してネットワーク デバイスを表しますが、異なるメーカーのネットワーク デバイスは互いに異なる場合があります。 Linux カーネルをさまざまなネットワーク デバイスに適応させるために、さまざまなネットワーク デバイスにプライベート データ用のストレージ スペースが提供されます。

つまり、ネットワーク デバイスには、net_device 部分に加えてプライベート データ部分があります。ネットワーク デバイスごとにプライベート データ部分が異なり、ネットワーク デバイスのプライベート データ部分は通常、次の図に示すように、net_device オブジェクトの最後に保存されます。

上図は、PCMCIA ネットワーク カードと RTL-8139 ネットワーク カードに対応するプライベート データ部分の保存場所を示しています。 PCMCIA ネットワーク カードのプライベート データ部分は pcnet_dev_t 構造体に対応し、RTL-8139 ネットワーク カードのプライベート データ部分は rtl8139_private 構造体に対応します。

話題に戻ると、仮想ネットワーク デバイス ペアのプライベート データ部分は、次のように定義される veth_priv 構造体によって表されます。

  1. 構造体veth_priv{
  2. 構造体net_device *ピア;
  3. 構造体 veth_net_stats *統計;
  4. ...
  5. };

veth_priv 構造体の各フィールドの機能について次に説明します。

  • peer: 仮想ネットワーク デバイス ペアはネットワーク デバイスのペアで構成されるため、このフィールドはペア内のもう一方のデバイスを指すために使用されます。
  • 統計: 統計情報を保存するために使用されます。

veth_priv 構造から、次の図に示すように、仮想ネットワーク デバイス ペアに属する 2 つのデバイス オブジェクトが peer フィールドによって関連付けられていることがわかります。

1. 仮想ネットワークデバイスペアを作成する

ip コマンドを使用して仮想ネットワーク デバイスのペアを作成すると、作成を完了するために veth_newlink 関数が呼び出されます。実装は次のとおりです。

  1. 静的 整数 
  2. veth_newlink(構造体net_device *dev、構造体nlattr *tb[]、構造体nlattr *data[])
  3. {
  4. 整数エラー;
  5. 構造体net_device *ピア;
  6. 構造体 veth_priv *priv;
  7. char ifname[IFNAMSIZ];
  8. ...
  9.  
  10. // 仮想ネットワークデバイスペアは2つのネットワークデバイスで構成されているため、
  11. // dev は仮想ネットワークデバイスペアのネットワークデバイスの 1 つです。
  12. // したがって、rtnl_create_link() を呼び出して別のネットワーク デバイスを作成し、それをピア変数に保存する必要があります。
  13. ピア = rtnl_create_link(dev_net(dev), ifname, &veth_link_ops, tbp);
  14. ...
  15.  
  16. priv = netdev_priv(dev); // devのプライベートデータ部分を取得する
  17. priv->peer = ピア; // ピアフィールドをピアにポイントする
  18.  
  19. priv = netdev_priv(ピア); // ピアのプライベートデータ部分を取得する
  20. priv->peer = dev; // ピアフィールドをdevに向ける
  21.  
  22. 0を返します
  23. }

上記のコードは合理化された後もメインロジックを保持するため、veth_newlink は主に次のタスクを実行します。

  • 仮想ネットワーク デバイス ペアは 2 つのネットワーク デバイスで構成されており、dev は仮想ネットワーク デバイス ペアのネットワーク デバイスの 1 つであるため、rtnl_create_link 関数を呼び出して別のネットワーク デバイスを作成し、それを peer 変数に保存する必要があります。
  • dev デバイス オブジェクトの peer フィールドをピア デバイス オブジェクトにポイントします。
  • ピア デバイス オブジェクトの peer フィールドを dev デバイス オブジェクトにポイントします。

このようにして、仮想ネットワークデバイスのペアの作成が完了します。

2. 仮想ネットワークデバイスペアを初期化する

もちろん、仮想ネットワークデバイスペアを作成する場合は、初期化も必要です。初期化プロセスは、次のように実装される veth_setup 関数によって完了します。

  1. 静的定数構造体net_device_ops veth_netdev_ops = {
  2. ...
  3. .ndo_start_xmit = veth_xmit、
  4. ...
  5. };
  6.  
  7. 静的void veth_setup(構造体 net_device *dev)
  8. {
  9. ...
  10. dev->netdev_ops = &veth_netdev_ops;
  11. ...
  12. }

仮想ネットワークデバイスペアを初期化する際に最も重要なことは、その操作機能セットを設定することです。 net_device_ops 構造体は、ネットワーク デバイスの操作機能セット構造体です。デバイスにデータが送信されると、デバイス操作機能セットの ndo_start_xmit メソッドがトリガーされます。

veth_setup 関数はこのメソッドを veth_xmit に設定します。つまり、仮想ネットワーク デバイス ペアの一方の端にデータを送信するときに、veth_xmit 関数が呼び出されてデータが送信されます。

3. 仮想ネットワークデバイスペアにデータを送信する

仮想ネットワーク デバイス ペアの一方の端にデータを送信する場合、送信プロセスを完了するために veth_xmit 関数が呼び出されます。これは次のように実装されます。

  1. 静的netdev_tx_t veth_xmit(構造体 sk_buff *skb、構造体 net_device *dev)
  2. {
  3. 構造体net_device *rcv = NULL ;
  4. 構造体 veth_priv *priv、*rcv_priv;
  5. ...
  6.  
  7. // データを送信するデバイスのピアデバイスを取得します
  8. priv = netdev_priv(dev);
  9. rcv = priv->peer;
  10. ...
  11.  
  12. skb->tstamp.tv64 = 0;
  13. skb->pkt_type = PACKET_HOST;
  14. // データパケットの受信デバイスをピアデバイスに設定する
  15. skb->プロトコル = eth_type_trans(skb, rcv);
  16. ...
  17.  
  18. // データパケットをカーネルプロトコルスタックに送信する
  19. netif_rx(skb);
  20.  
  21. NETDEV_TX_OK を返します
  22. }

まず、veth_xmit 関数の各パラメータの意味を紹介します。

  • skb: 送信するパケット オブジェクト。
  • dev: データを送信するデバイス。

veth_xmit 関数の実装は比較的単純で、主に次のタスクを実行します。

  • データを送信するデバイスのピア デバイスを取得します。
  • データ パケットの受信デバイスをピア デバイスに設定します。
  • データ パケットをカーネル プロトコル スタックに送信します。

データ送信のプロセスを示すために次の図を使用します。

上図に示すように、仮想ネットワーク デバイス ペアの一方の端からデータ パケットが送信されると、もう一方の端で受信され、カーネル プロトコル スタックに送信されて処理されます。

要約する

仮想ネットワーク デバイス ペアの出現により、コンテナー間の通信の問題が解決されます。この記事では、主に仮想ネットワーク デバイス ペアの実装原理を分析しますが、一部の詳細については詳細に分析されていません。ご質問がある場合は、WeChat で私を追加して話し合うことができます。

<<:  アリ・ジア・ヤンチン:ビッグデータとAI機能を通じて企業にアップグレードの力を提供する

>>:  5種類のサーバー仮想化を理解する

推薦する

5つのオープンソース仮想化ツールで仮想マシンを管理する

仮想化ツール (Virt Tools) を使用すると、仮想マシンの使用がより便利になります。今日は ...

cloudcone: 超大容量ハードディスク VPS 再入荷、ロサンゼルス KVM、最大 500G ハードディスク、PayPal/Alipay

cloudcone は、電子メール マーケティング用の大容量ハード ドライブ VPS (ストレージ ...

【ハードウェア仮想化】カーネルの理想郷からは程遠い

導入このストーリーでは、ハードウェア仮想化 (HVM) を使用して、独自のフック コードの一部をカー...

検索エンジンの3つの主要な問題

1. ユーザーの真のニーズは何ですか?検索エンジンのユーザーが入力するクエリは非常に短く、平均クエリ...

## ニュース Linode: カナダのトロントに 10 番目のデータセンターを開設

今日のニュース: Linode は、10 番目のデータ センターがカナダのトロントにあることを正式に...

現在の「安価な SEO」の終焉

昨日、筆者はSEO業界の大物と雑談して、彼のビジネスについて話しましたが、もちろんSEOの安さの問題...

SUSE NeuVectorは、サイバーセキュリティエクセレンス検証センターと中国電信技術研究所によって認定されています。

最近、中国情報通信研究院は「第6期先進サイバーセキュリティ能力検証評価プログラム - クラウド(ネイ...

G ポートのアップグレード: budgetvm-$4.99/Xen/2IP/1g メモリ/50g ハードディスク/3T トラフィック/Alipay

ご存知のとおり、budgetvm の以前の VPS はすべて 100M ポートでしたが、現在はすべて...

weloveservers-1G メモリ/年間 19.99 ドル/3 つのデータセンター

weloveservers、1Gメモリ特別版の説明:サーバーはIntel Xeon Quad-Cor...

完全ネットワークマーケティングによる商品チャネルプロモーション!

今日では、製品のマーケティングやプロモーションにはさまざまな方法があります。それらはすべて理にかなっ...

servermania-1G メモリ/月額 7 USD/XEN ONAPP ベース

Servermania は 2002 年に設立されたインターネット企業です。主な事業は、サーバーのレ...

音楽ダウンロード料金は継続:レコード会社はウェブサイトを統一せず、目立たないようにしている

音楽のダウンロードにお金を払うのは難しいです。イラスト:北京ニュースの趙斌レコード会社は統一されてお...

SEO担当者の理解:SEOはオンラインマーケティングの唯一の手段ではない

SEO トレーニング コースの人気が高まり、SEO 担当者の数も増加しているため、一般のウェブマスタ...

ブランドマーケティング革新の方法論!

Heytea、Sandunban、Nayukiなど、最近人気が出ている新しい消費者ブランドを数えてみ...