はじめに
DockerやKubernetesを使ってマイクロサービスなどを構築する時には、必ずネットワーキングが必要になります。そのために必要な基礎知識をまとめておきました。 テーマは、
です。 その1では、「ネットワーク機器の種類」までをまとめています。
※DockerやKubernetesの話は出てきません。
- ネットワークの階層構造
- プロトコルの詳細と通信の流れ
- L4とTCP
- L3とIP
- L2とEthernet
- フローのまとめ(HTTP/TCP/IP/Ethernet)
- MACアドレスとIPアドレス
- IPアドレス
- ネットワーク機器の種類
- おわりに
ネットワークの階層構造
プロセスとプロセスが通信するときには情報やデータを相手先に送り届ける必要があります。この送り届ける仕組み=ネットワークの仕組みをプロトコルとして統一したルールを定めることで、様々な離れたサーバやPC同士が通信できるようになっています。
通信を実現するためにはいくつかの機能が必要であり、その種類ごとに階層に分けてプロトコルが用意されています。
7つの階層に分かれたOSI参照モデルと4つの階層に分かれたTCP/IP階層モデルが有名です。
OSI参照モデル
OpenSystemsInterconnectionという通信規格で使われていた通信の階層構造です。今はもうOSI自体は使われなくなったようですが、その考え方は残っているため、「参照」モデルと呼ばれています。
階層 | レイヤー | 説明 | プロトコル |
---|---|---|---|
L7 | アプリケーション層 | 稼働しているアプリケーションやサービスのやりとりを規定 | HTTP, SMTP, FTP |
L6 | プレゼンテーション層 | データの表現方法を規定 | (同上) |
L5 | セッション層 | 通信の開始と終了のやり方を規定 | (同上) |
L4 | トランスポート層 | ポートをもとに通信を制御する方法を規定 | TCP, UDP |
L3 | インターネット層 | 実際にデータ信号が流れる通信経路を制御するための層、IPアドレスをもとに制御する方法を規定 | IP, ICMP, ARP |
L2 | リンク層 | 実際の機器同士のやりとり、MACアドレスをもとに制御する方法を規定 | Ethernet, Wi-Fi, PPP |
L1 | 物理層 | 機器の電気的な接続方法を規定 |
TCP/IP階層モデル
OSIよりも階層を減らしてシンプルにしたモデルです。ただし、階層番号はL2スイッチ、L3スイッチのように習慣的にOSI参照モデルの名称で呼ばれています。
階層 | レイヤー | 説明 | プロトコル |
---|---|---|---|
L7 | アプリケーション層 | OSI参照モデルのL5〜L7を1つにした規定 | HTTP, SMTP, FTP |
L4 | トランスポート層 | OSI参照モデルのL4と同じく、ポートをもとに通信を制御する方法を規定 | TCP, UDP |
L3 | インターネット層 | OSI参照モデルのL3と同じく、実際にデータ信号が流れる通信経路を制御するための層、IPアドレスをもとに制御する方法を規定 | IP, ICMP, ARP |
L2 | リンク層 | OSI参照モデルのL1〜L2を1つにした規定 | Ethernet, Wi-Fi, PPP |
通信の流れは
HTTP → TCP → IP → Ethernet
という順で大元のデータにヘッダがくっつき(カプセル化していき)、最終的にはEthernetフレームが作られます。このEthernetフレームがNICに転送され、ケーブルを通じて、通信先のノードまで届きます。
プロトコルの詳細と通信の流れ
L7とHTTP
HTTP
HTTPはブラウザでインターネットを使う時によく利用されるプロトコルです。URLを指定することで、Webサーバにリクエストが転送されます。そのレスポンスとしてWebサーバからHTMLファイルが届き、ブラウザがそのファイルを解析することでWebページが表示される仕組みとなっています。
リクエストの種類とデータの中身
リクエストの種類は、GET(情報の取得をリクエストする)とPOST(情報を渡し処理をリクエストする)が主に使われます。そのほかPUTやDELETEなども存在し、詳しくは下記のページにまとまっています。
リクエストをする時には、GETの場合は欲しい情報、POSTの場合はこちらの情報をデータとして渡します。HTTPはこのデータにヘッダという情報を付与して、アプリのデータとして次の階層に渡します。このヘッダ部分には、Content-Type(ファイルの種別)やUser-Agent(ブラウザの識別情報)、Cookie(セッション識別子)といった付加情報が格納されており、通信を制御するために利用されます。
通信経路の確保
HTTPがリクエストを投げた後の、通信経路の確保は、L4以下のカーネルプロセスによって実行されます。HTTP自身は、システムコールを使ってカーネルに対し、「TCP/IPで宛先Aのhttpdアプリと通信をしたいので、経路を開けて欲しい」とリクエストするだけになっています。そのためアプリが知っておくべきは、宛先AのIPアドレスと、httpdプロセスのTCPポート番号のみになります。
システムコールを受けたカーネルは、TCPを使って、IPアドレスとポート番号を元に、ソケットを作成し、宛先とコネクションを張ります。これで宛先Aとの通信路が確保される、という仕組みになっていますが、ソケット作成の詳細は後述します。
L4とTCP
TCP
TCPは、アプリから渡されたデータを、確実に宛先に届けるためのコントロールをするプロトコルです。IPアドレスを見て宛先まで送り届けるプロセス自体は一つ下のIP層の責任範囲ですが、TCPはその送り届けた結果のチェックや、ポート番号を使ってその先のアプリまで届ける責任を担っています。
主な機能は下記です。
- ソケット(コネクション)の生成
- データ保証と再送制御
- フロー制御(輻輳制御)
ソケットの生成
ソケットの生成の前に、まず通信を受けるサーバ側で、あらかじめポート番号が利用できる状態(ポートをLISTENしている状態)になっている必要があります。LISTEN状態になっていることで、そのポート番号に通信が来ないか常に確認し続けることになります。
LISTEN状態になっていたらソケットを生成できます。ソケットの生成には3way handshakeと呼ばれる方法が使われています。3way handshakeとは、クライアントがサーバに依頼をして(1回目)、サーバ側は問題ないと返し(2回目)、クライアント側も始めるよという合図を送る(3回目)というやりとりです。3回の通信をしてようやくソケットが生成されるため3wayと呼ばれています。
ただしTCPとしては、宛先のポート番号とのソケット生成をIPに依頼しているだけです。そのため、一度ソケットが生成されてしまえば、物理的にケーブルが切れても、通信先のサーバが突然落ちても、TCPが気づくことはありません。TCPで張ったソケットは、アプリやカーネルからの依頼で明示的に切断するか、通信先サーバからエラーが返ってくることで切断されます。
なお、ソケットが生成された後は、ソケットごとに専用のメモリ領域(ソケットバッファ)が用意され、L4以降は同じソケットバッファを使ってデータを転送することになります。
データ保証と再送制御
ポイントは2点「問題なくサーバに渡ったか」と「順番通りデータが送られているか」です。
- 問題なくデータがサーバに渡ったか
サーバはデータを受け取ったら、ACKという返事をクライアントに返すことで、データが問題なく届いたことをクライアントに伝えるようになっています。クライアントはACKが返って来ない限り、送信用のソケットバッファにTCPセグメントを残しておき、いつでも再送できるようにしています。再送は、いつまでもACKが返って来なかったり、逆にいつまでも同じACKが返ってき続けた場合に実行されます。
- 順番通りデータが送られているか
また、TCPセグメントのヘッダには、シーケンス番号がついており、送信データのバイト数を表しています。サーバ側は次に欲しいデータの頭のバイト数をACKに記載して送り返します。例えば、クライアントがシーケンス番号として1461として1460ByteのTCPセグメントを送ったら、ACK番号が2921のACKが返ってくるということになります。
フロー制御(流量制御)
効率的に転送するために、ある程度のデータサイズ内であれば、非同期に(=ACKを待たず)データを送れるようになっています。このデータサイズをウィンドウサイズと呼びます。このウィンドウサイズを変化させることで流量制御を実現しています。
例えば、複数のクライアントから非同期にどんどんデータが転送されてきたら、サーバ側の負荷が高まり、ソケットバッファが溢れそうになってしまいます。こういった時には、ウィンドウサイズを小さくし非同期送信できるデータ量を制限することで、サーバ側への負荷を調整できます。
L3とIP
IP
IPは、TCP層から渡されたTCPセグメントにIPパケットを付与し、L2レイヤーに渡す処理を担っています。IPパケットには宛先のIPアドレスや格納データの長さ、プロトコルの種類(TCPやUDP)、TTL(Time To Live)などが記録されています。
TTL(Time To Live)
ルーティングの間違いなどでパケットが延々とネットワーク内を行き来してしまった時に、あらかじめ経由するルータ数をTTLとして設定しておくことで、TTL=0になった時にパケットを捨てられるようになっています。これによってパケットがネットワーク内を永遠に彷徨うことを防ぐことができます。(この捨てられたパケットの再送はTCPにて実施されますが、ルーティングが直らなければ結局は同じことの繰り返しになります…)
L2とEthernet
Ethernet
Ethernetはリンク層の代表的なプロトコルであり、有線LANで使われます。MACアドレスによって宛先機器を判断し、同じネットワーク内の機器までデータを届ける処理を担っています。
「同じネットワーク内の機器」とはつまり他のマシンもしくはL2スイッチやデフォルトゲートウェイ(ルータやL3スイッチ)といったネットワーク機器までが転送責任範囲になります。ネットワーク機器に届けた場合は、そこから先はスイッチやルータなどのコントロールに任せることになります。
- L2スイッチでの動き
L2スイッチでは、受け取ったEthernetフレームのMACアドレスを見て、自身のアドレステーブルと突き合わせ、宛先が含まれているL2スイッチまでフレームを転送します。受け取ったL2スイッチでも同様にアドレステーブルを見て、自身とつながっているマシンまでフレームを送り届けます。
- デフォルトゲートウェイ(ルータやL3スイッチ)での動き
L2スイッチはEthernetフレームのMACアドレスのみを使って転送処理をしますが、デフォルトゲートウェイとなっているルータやL3スイッチでは、IPアドレスまで確認して、宛先を判断します。そして異なるEthernetフレームに付け替えて、次のルータやL3スイッチまで転送するようになっています。
またルータには、プライベートIPアドレスをグローバルIPアドレスに変換するNAT機能を持っているものもあり、その場合は、EthernetフレームだけではなくIPパケットの宛先IPアドレスや送信元IPアドレスも変換して、転送することになります。変換処理自体はルータで持っているNATテーブルを参照して実行されています。
フローのまとめ(HTTP/TCP/IP/Ethernet)
ここまでの通信フローをまとめます。
- アプリプロセスが宛先をURL(IPアドレスとポート番号)で指定したHTTPリクエストをシステムコールでカーネルに渡す
- カーネルプロセスがTCPの3way handshakeによってソケットを生成(この時点で一旦IP/Ethernetも通って宛先サーバまで通信が届いている)
- TCPのヘッダ(シーケンス番号などの制御情報)をHTTPリクエストに付与し、TCPセグメントとしてIPに渡す
- IPのヘッダ(IPアドレスなど)をTCPセグメントに付与し、IPパケットとしてEthernetに渡す
- Ethernetのヘッダ(MACアドレスなど)をIPセグメントに付与し、Ethernetフレームとして次の機器に転送する
- 次の機器とは、同一ネットワーク内に宛先があるならその機器であり、同一ネットワークにないのであればデフォルトゲートウェイであるスイッチやルータである
- EthernetフレームはIPアドレスやMACアドレスの情報が変更されながら、スイッチとルータを経由して、宛先サーバに転送される
- 宛先MACアドレスを持った機器にEthernetフレームが届いた後は、各レイヤーでヘッダが取り外され、httpdにリクエストボディが届く
6、7での詳細は、次項目の「MACアドレスとIPアドレス」で扱います。
より細かいネットワークフローの話は下記の本にとても丁寧に書かれています。今後ネットワークに関わっていくのであれば、読んでおいて損はない一冊です。
MACアドレスとIPアドレス
MACアドレス
MACアドレスの使われ方
MACアドレスはL2スイッチでのルーティングで使われます。
L2スイッチには、物理ポート番号とその先に存在するネットワーク機器のMACアドレスを保存したMACアドレステーブルを持っており、このテーブルを使って、ルーティングしています。
MACアドレスによるルーティングの仕組み
最初はMACアドレステーブルは空の状態になっています。初めてEthernetフレームがきた時には、通信元のホストAとそのMACアドレスをテーブルに記録します。そして、通信元以外の全ての接続先にEthernetフレームを転送します。これを「フラッディング」と呼びます。
Ehternetフレームに記載されているMACアドレスのホストCがその通信を受け取ると、そこからだけレスポンスが返ってきます。そうするとスイッチは今度はホストCとそのMACアドレスをテーブルに記録します。そしてホストAにレスポンスを返します。
一度、MACアドレステーブルに書かれたホストへの通信が再度発生すると、今度はフラッディングせずに、そのホストにのみパケットを転送するようになり、効率的に通信ができるようになっています。
MACアドレスは世界で唯一のアドレスか?
MACアドレスは世界で唯一と言われていますが、実際には重複しています。しかし、そもそもなぜ重複させたくないかというと同じネットワーク内で宛先が複数ある矛盾が生じるためです。つまり、物理的に機器が繋がっている同一ネットワーク内だけで重複していなければ問題ないということになります。
IPアドレス
IPアドレスの形式
IPアドレスはL3スイッチやルーターの通信で利用されます。IPアドレスはネットワーク部とホスト部に分かれており、サブネットマスク(/24や/28)で分割表現されます。ネットワーク部でどのネットワークに属するか(いずれかのデフォルトゲートウェイもしくは同一ネットワーク)を特定し、ホスト部はそのネットワーク内のどのホストかを特定できるようになっています。
ARP
1つのホストが複数のIPアドレスを持つことがあるため、まずは、送りたいIPアドレスを持っているホストのMACアドレスを見つける必要があります。その時に利用されるのが、ARP(Address Resolution Protocol)というIPアドレスに対応するMACアドレスを返してくれるプロトコルです。
リクエストを送信すると、同一ネットワークの全ノードに対してARPリクエストがブロードキャストされ、そのIPアドレスを持つホストのみがMACアドレスを返してくれる、という仕組みです。これによりL3スイッチやルーターは送り先であるMACアドレスにパケットを転送できるようになっています。
なお、各マシンはMACアドレステーブルと同様にARPテーブルを持っており、そこに情報をキャッシュしていくので、毎回ブロードキャストで問い合わせるということは発生しません。
ネットワーク機器の種類
昔は、それぞれの役割があって、明確に定義を分けられていたようですが、最近はネットワークの仮想化技術が発展し、また機器自体も高性能になってきているため、明確に分けにくくなっています。 そのため、機器の違いに関しては参考程度に抑えておき、実際に何をしているかの機能面にフォーカスして覚えておけば良いと思います。
ブリッジ
複数のマシンを接続し、それぞれで通信できるようにする機器やソフトウェアのことです。MACアドレステーブルを持っており、都度確認して、行き先を振り分けます。ソフトウェアでデータ転送するので、ハードウェアで制御するスイッチよりも速度が遅いというデメリットがあります。
L2スイッチ
基本的な機能はブリッジと同じですが、ポート数が多い点、ASICと呼ばれる専用の回路によるハードウェアにて処理する点が異なります。ハードウェアでの処理ということで、OSなどのソフトウェアを介さず電気信号のまま送信できるため、素早いデータ転送が実現できます。
L3スイッチとルータ
ルータは、異なるネットワーク、WANと社内LANをつなげる機器として主に利用されます。L3スイッチは主にネットワークの拡張や分離の用途として利用されます。下記のサイトにコンパクトに分かりやすくまとまっています。
また、下記のサイトも参考になります。リピータ/ブリッジ/スイッチ/ルータのそれぞれについて違いとともに解説されており、分かりやすいです。
おわりに
その1では、ネットワークのプロトコルと通信フローを中心にまとめました。
その2では、Docker/Kubernetesでよく使われている、VLAN、iptables、network namespace についてまとめます。