Fire Engine

化学の修士号→消防士→ITエンジニア(2016年11月〜)

Site Reliability Engineering – 10章 時系列データからの実践的なアラート

こんにちは、つるべーです。
先日、福岡のインフラ界隈のエンジニアの方々がやっているSRE本の輪読会に参加し、発表をさせていただいたので、その時の内容をまとめます。
私は、10章の「時系列データからの実践的なアラート」を担当させてもらいました。

はじめに

なぜ「時系列データからの実践的なアラート」が必要かを考えてみた。
Webサービスの大規模化や複雑化に伴い、サーバ台数の増加やシステム構成の複雑化が進んだことで、サーバのメトリクス等の情報を高解像度かつ長期間保持したいという要望が高まっている。また、サーバのメトリクスをより統計的に解析し、アラーティングの精度を向上させたいといったシーンも増え、時系列データベースに溜め込んだデータを用いた柔軟なアラーティングの需要が高まっているのではないだろうか。

概要

  • 10章ではBorgmonと呼ばれるGoogleの内部システムについての話が中心だが、「アラートを発するためのデータソースとして時系列データを扱う」という発想は、汎用性が高く、最近ではPrometheus、Riemann、Heka、BosunといったOSSのツールを通じて広く受け入れられている。
  • 大規模なシステムにおいて如何にメンテナンスコストを抑えながら、適切なモニタリングを行うかが重要である。
  • 大量の時系列データを継続的に収集することで、アラーティングの精度・柔軟性を高めることができる。

まとめノート

大規模システムのモニタリングが難しい理由

  • 単にモニタリング対象となるコンポーネントの数が多すぎる。
  • システムに対する責任を負うエンジニアのメンテナンスの負荷を低く保つ必要がある。

大規模システムの場合、1台のマシンが不具合を起こしているくらいでアラートを発するのはノイジー過ぎる。(きちんと冗長化されている場合の話だが)
大規模システムでは、個々のコンポーネントの管理を求めるのではなく、データを適切な粒度で集約して、異常値のみを拾い上げるべきである。
また、必要に応じて個々のコンポーネントの調査もできる粒度に情報を保っておいてくれるようなモニタリングシステムが求められる。

10.1 Borgmonの誕生

  • 大量の収集を行うためにメトリックスのフォーマットは標準化されている必要がある。
  • 単一のターゲットに対する全てのメトリクスの収集を1回のHTTPのフェッチで行えるように定められている。 /varzエンドポイントを叩くとメトリクスが取得できる。
$ curl http://webserver:80/varz
http_requests 37
errors_total 12

10.2 アプリケーションのインスツルメンテーション

  • 全てのエクスポートされた変数をkey/value式のプレーンテキストで返す
  • スキーマレスなテキストベースのインタフェースは、新しいメトリクスを追加するのが簡単である
  • ひとつの変数に対して複数のラベルをつけて出力できるようになった。 例えば、HTTP200のレスポンスが25件、500のレスポンスが12件の場合、下のように出力される。
http_responses map:code 200:25 404:0 500:12

10.3 エクスポートされたデータの収集

  • Borgmonでは、サービスディスカバリを利用してモニタリング対象のリストを動的に生成するため、リストのメンテナンスコストが下がり、モニタリングのスケーラビリティを高めることができている。
    サービスディスカバリを有する点はPrometheusも同じ。PrometheusにはAWS、Azure、GCP、OpenStack、Kubernetesなど多種多様なプラットフォームのメタデータを元にサービスディスカバリすることができるし、Consulとの連携もできる。
  • Borgmonは一定間隔ごとにターゲットのエンドポイント(/varz)を叩いて、結果をメモリに貯める。(Pull型の監視)
  • データの収集をHTTP経由で行っているのは、HTTPのオーバーヘッドが問題になるケースはほとんどないことや、そもそもメトリクスが取れないことそのものを シグナルとして利用することができるからである。

10.4 時系列のアリーナにおけるストレージ

  • データポイントは(timestamp, value)という形式を持ち、 時系列データ と呼ばれる時間順のリストとして保存される。
  • それぞれの時系列データはname=valueという形式で、ユニークなラベルが付与される。 時系列データの概念は、時間と共に進んでいく数値からなる1次元の行列(列ベクトル)であり、変数に対して複数のラベルの組み合わせを追加すると、多次元の行列になる。
  • Borgmonは全てのデータをインメモリデータベースに保存し、定期的にチェックポイントを実行して、時系列データベース(Time-Series Database: TSDB)にアーカイブされる。 Borgmonでは、TSDBに対してもクエリを実行できる。TSDBはインメモリデータベースより低速だが、低コストで大容量である。

時系列データとは(補足)

時系列データとは、時間の推移ととともに観測されるデータのこと。世の中の実務の現場に貯まっていく多くのデータは時系列のデータである。
ITインフラの現場においても、サーバのメトリクス、ネットワークトラフィックなどといった時系列データが時々刻々と蓄積されている。
データ分析において、隣り合う時刻の観測値同士には明らかに相関関係がある(時間依存性を持つ)時系列データの取り扱いは、他のデータ(クロスセクションデータなどと言われる)に比べて、理論的にも実銭的にも難しいとされている。

時系列データベースとは(補足)

時系列データの保存・処理に特化したデータベースである。
Webサービスの大規模化に伴うサーバ台数の増加や、複雑化により、高い解像度の様々なメトリクスを長期間保持したいという要望や、サーバのメトリクスをより統計的に解析し、アラーティングの精度を向上させたいという要望などがあり、時系列データベースの需要が高まっている背景がある。

もちろん、時系列データを格納するためにバックエンドとして、MySQLのようなRDBMSを使用することもできるし、RRD(ラウンドロビンデータベース)のような時系列データに特化したデータベースもある。しかし、最近の時系列データベースでは共通して、時系列データの符号化方式や、メモリもしくはストレージの使用法などのアーキテクチャに工夫がなされており、 ストレージ容量の節約や、解析時に使用するメモリ量の削減などの効果を上げることができる。 また、ほとんどの時系列データベースにおいて、SQL等をベースにしたデータ解析の方法が用意されているという特色もある。

【参考】

階層型のデータストアアーキテクチャについて(補足)

データの保持期間に応じた階層型のデータストアアーキテクチャは、時系列データの保存においてはいくつか事例も見受けられる。

【参考】

10.4.1 ラベルとベクタ

  • 時系列データの名前はラベルセットである。ひとつの時系列データをユニークに探すためには、最低でも次のラベルが必須である。
var    :変数名
job    :モニタリング対象のサーバー の種類
service:サービスを提供するジョブの集合
zone   :データを収集したBorgmonのデータセンタ

これらをまとめて、以下のように変数式として表現できる。

{var=http_requests,job=webserver,instance=host0:80,service=web,zone=us-west}
  • 時系列データに対するクエリでは、これらのラベルセットに対して検索を行うと、マッチする全ての時系列データが返される。

10.5 ルールの評価

  • Borgmonルールと呼ばれるBorgmonのプログラムコードは時系列データから別の時系列データを算出する。
  • ルールの書き方自体は特に重要でない。 ポイントは、「10分間におけるHTTPエラーの比率」といったように、適度な幅で集計をしている点である。(さらにその幅は自由に調整できる)これは時系列にデータを溜め込んでいるからできる。

10.6 アラート

  • 「10分間のエラー率が1%以上で、1秒に1回以上のエラーが 2分以上出るときにアラートをあげる」といったことができるのも時系列データを溜めているからできる。

10.7 モニタリングのトポロジーのシャーディング

  • Borgmonは他のBorgmonから時系列データをインポートできる。そのため、データセンターごとにBorgmonで監視対象の時系列データを取得して、グローバルなBorgmonが各データセンターのBorgmonから時系列データを取得するといったシステム構成が組める。

10.8 ブラックボックスモニタリング

  • Borgmonはホワイトボックスモニタリングであり、調べるのはターゲットのサービス内部の状態のみである。したがって、ブラックボックスモニタリングも組み合わせないと、ユーザーにインパクトのある障害に気づけなくなる場合がある。

10.9 設定のメンテナンス

  • Borgmonではルールの定義をモニタリングの対象となるターゲットから分離しているため、同じルールセットを多くのターゲットに対して一斉に適用できる。これによりモニタリングのメンテナンスコストが大幅に削減できる。

10.10 10年が経過して

  • Borgmonは「アラートの診断のための大量の変数の収集と時系列データに対する集中化されたルールの評価」というモデルである。
  • メンテナンスコストがサービスのサイズに比例しないようにすることがモニタリングをメンテナンス可能にするための鍵である。

最後に…インフラ監視 × データサイエンス

  • Prometheusなどの時系列データベースや次世代監視ツールの発展と人工知能などデータサイエンス分野の発展が相まって、
    サーバの異常状態を予測して自動で制御するような時代が来るかもしれないなどと考えている。
    そのためにも、まずデータを高解像度・長期間溜め込むことは重要だ。さらに、溜め込んだデータを単なる閾値ベースの判定だけでなく、統計学機械学習を駆使したより高度なデータ分析を適用することで、アラーティングの柔軟性を高め、必要なアラートだけを発するようにする。自動制御はその先の世界…

参考

SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム

SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム

インフラエンジニアになって覚えたLinuxコマンド その2(ネットワーク系コマンド編)

こんにちは、つるべーです。
今回の記事は以前の続きで、インフラ業務の中で覚えたLinuxコマンドについてです。

www.hirotsuru.com

今回はネットワーク系のコマンドに絞ってまとめていきます。

環境

目次

ping

ICMPを使ってネットワーク上のホストの接続を確認する

$ ping www.example.com
PING www.example.com (93.184.216.34) 56(84) bytes of data.
64 bytes from 93.184.216.34 (93.184.216.34): icmp_seq=1 ttl=63 time=123 ms
64 bytes from 93.184.216.34 (93.184.216.34): icmp_seq=2 ttl=63 time=123 ms
64 bytes from 93.184.216.34 (93.184.216.34): icmp_seq=3 ttl=63 time=123 ms
^C
--- www.example.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2005ms
rtt min/avg/max/mdev = 123.096/123.361/123.551/0.345 ms

dig

DNSサーバに問い合わせてドメイン名(またはIPアドレス)を調べる。

dig [@DNSサーバ] ドメイン [検索タイプ]

DNSサーバは指定しない場合は、/etc/resolv.confに記述されたDNSサーバを使用する。
検索タイプはデフォルトではAレコード
-x AAA.BBB.CCC.DDDで逆引き問い合わせもできる。

$ dig google.com

; <<>> DiG 9.10.6 <<>> google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50236
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;google.com.            IN  A

;; ANSWER SECTION:
google.com.     279 IN  A   216.58.197.174

;; Query time: 28 msec
;; SERVER: 192.168.11.1#53(192.168.11.1)
;; WHEN: Fri May 04 23:08:38 JST 2018
;; MSG SIZE  rcvd: 55

+shortオプションをつけると目的の情報だけを表示する

$ dig +short -x 216.58.197.174
nrt12s02-in-f174.1e100.net.
nrt12s02-in-f14.1e100.net.

whois

whoisを利用してドメイン情報を取得する

$ whois gihyo.jp
% IANA WHOIS server
% for more information on IANA, visit http://www.iana.org
% This query returned 1 object

refer:        whois.jprs.jp

domain:       JP

organisation: Japan Registry Services Co., Ltd.
address:      Chiyoda First Bldg. East 13F,
address:      3-8-1 Nishi-Kanda
address:      Chiyoda-ku Tokyo 101-0065
address:      Japan

(省略)

tcpdump

ネットワークインターフェイスを通過するパケットを観察する。
tcpdumpと打つだけでもパケットが流れる様子が観察できるが、大量に流れてくるため通常は以下のように条件を絞って観察する。

tcpdump -i [interface name] port [port number]

実際の実行例は下のような感じ。

$ tcpdump -i eth1 port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
02:09:24.936395 IP 192.168.10.1.50796 > nginx.http: Flags [F.], seq 2273804563, ack 848006729, win 4117, options [nop,nop,TS val 715484926 ecr 28938], length 0
02:09:24.936422 IP 192.168.10.1.50797 > nginx.http: Flags [F.], seq 1504651190, ack 642584441, win 4117, options [nop,nop,TS val 715484926 ecr 28938], length 0
02:09:24.936425 IP 192.168.10.1.50798 > nginx.http: Flags [F.], seq 2028803151, ack 3632381970, win 4117, options [nop,nop,TS val 715484926 ecr 28938], length 0
02:09:24.936428 IP 192.168.10.1.50799 > nginx.http: Flags [SEW], seq 3820785142, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 715484926 ecr 0,sackOK,eol], length 0
02:09:24.936447 IP nginx.http > 192.168.10.1.50799: Flags [S.E], seq 2665692678, ack 3820785143, win 28960, options [mss 1460,sackOK,TS val 43425 ecr 715484926,nop,wscale 6], length 0

(省略)

これを見るだけでもパケット届いてるなーとかまではわかるが、出力結果をちゃんと見るには下の記事がすごく参考になった。

qiita.com

-w ファイル名でファイル出力もでき、出力したファイルをWiresharkで見ると良さそう。

ip

ipコマンドは様々なネットワーク関連の設定を確認/変更できるコマンドである。
CentOS7では、ifconfig、route、netstatなどといったコマンドが入っているnet-toolsパッケージが廃止予定であり、iproute2パッケージに含まれる「ip」「ss」などのコマンドを使用することが推奨されているようです。これについては以下の記事に非常にわかりやすくまとめられています。

enakai00.hatenablog.com

ネットワークデバイスの設定を確認

$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 52:54:00:5f:94:78 brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic eth0
       valid_lft 83407sec preferred_lft 83407sec
    inet6 fe80::5054:ff:fe5f:9478/64 scope link
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:2e:38:d9 brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.11/24 brd 192.168.10.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe2e:38d9/64 scope link
       valid_lft forever preferred_lft forever

aaddrの略。ifconfigコマンドに相当するコマンド。

$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.2.15  netmask 255.255.255.0  broadcast 10.0.2.255
        inet6 fe80::5054:ff:fe5f:9478  prefixlen 64  scopeid 0x20<link>
        ether 52:54:00:5f:94:78  txqueuelen 1000  (Ethernet)
        RX packets 32746  bytes 17741551 (16.9 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 22008  bytes 2394181 (2.2 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.10.11  netmask 255.255.255.0  broadcast 192.168.10.255
        inet6 fe80::a00:27ff:fe2e:38d9  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:2e:38:d9  txqueuelen 1000  (Ethernet)
        RX packets 161  bytes 26250 (25.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 27  bytes 3146 (3.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ルーティングの確認

$ ip r
default via 10.0.2.2 dev eth0 proto static metric 100
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15 metric 100
192.168.10.0/24 dev eth1 proto kernel scope link src 192.168.10.11 metric 100

rrouteの略。routeコマンドに相当するコマンド。

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.2.2        0.0.0.0         UG    100    0        0 eth0
10.0.2.0        0.0.0.0         255.255.255.0   U     100    0        0 eth0
192.168.10.0    0.0.0.0         255.255.255.0   U     100    0        0 eth1

-nオプション:ホストの名前解決をせずにIPアドレスを表示

上で表示したネットワークデバイスやルーティングの設定は、adddelなどを使って設定情報を追加、削除できる。

ss

ソケットの状態を表示する。

$ ss -tan
State      Recv-Q Send-Q                                            Local Address:Port                                                           Peer Address:Port
LISTEN     0      128                                                           *:111                                                                       *:*
LISTEN     0      128                                                           *:80                                                                        *:*
LISTEN     0      128                                                           *:22                                                                        *:*
LISTEN     0      100                                                   127.0.0.1:25                                                                        *:*
ESTAB      0      0                                                     10.0.2.15:22                                                                 10.0.2.2:50759
LISTEN     0      128                                                          :::111                                                                      :::*
LISTEN     0      128                                                          :::22                                                                       :::*
LISTEN     0      100                                                         ::1:25                                                                       :::*

-tオプション:TCPソケットを表示
-aオプション:接続待ち(LISTEN)も含めて表示
-nオプション:ポート番号を表示(デフォルトではサービス名)
ssコマンドはnetstatコマンドに相当するコマンド。

$ netstat -tan
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN
tcp        0      0 10.0.2.15:22            10.0.2.2:50759          ESTABLISHED
tcp6       0      0 :::111                  :::*                    LISTEN
tcp6       0      0 :::22                   :::*                    LISTEN
tcp6       0      0 ::1:25                  :::*                    LISTEN

参考

[改訂第3版]Linuxコマンドポケットリファレンス

[改訂第3版]Linuxコマンドポケットリファレンス

インフラエンジニアになって覚えたLinuxコマンド その1

こんにちは、つるべーです。
会社のインフラ研修も終わり、4月の2週目から正式にインフラチームにJoinしました。
今回は私が初めてインフラ業務をやっていく中で覚えたLinuxコマンドを備忘録的に書いていきます。まだまだインフラ運用に必要なコマンドはあると思うので、定期的にまとめて書いていこうと思っています。
細かいオプションの使い方等は解説しませんが、どういうときに使えるコマンドであるかと、実行例を書いていきたいと思います。

環境

目次

df

ファイルシステムの使用状況を確認する

$ df -Th
Filesystem                      Type      Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00 xfs        38G  929M   37G   3% /
devtmpfs                        devtmpfs  236M     0  236M   0% /dev
tmpfs                           tmpfs     245M     0  245M   0% /dev/shm
tmpfs                           tmpfs     245M  4.4M  240M   2% /run
tmpfs                           tmpfs     245M     0  245M   0% /sys/fs/cgroup
/dev/sda2                       xfs      1014M   63M  952M   7% /boot
tmpfs                           tmpfs      49M     0   49M   0% /run/user/1000

-Tファイルシステムの種別(Type)を表示
-h:読みやすいように単位をつけて表示

du

ファイルのディスク使用量を確認する

$ du -hs *
0   bin
30M boot
0   dev
31M etc
19M home
0   lib

(省略)

-h:読みやすいように単位をつけて表示
-s:引数で指定したファイル/ディレクトリの合計容量のみ表示
上の例ではカレントディレクトリの全てのファイルおよびディレクトリの合計容量を表示している。

free

メモリの使用量・空き容量を表示

$ free -h
              total        used        free      shared  buff/cache   available
Mem:           488M         82M         78M        4.4M        328M        373M
Swap:          1.5G          0B        1.5G

-h:読みやすいように単位をつけて表示

ln

ファイルへのリンクを作成

<ハードリンク>
1つのファイルに複数の名前を持たせる
rmコマンドで削除すると指定したファイル名だけが取り除かれファイルの実体は残る。リンクされた最後のファイルが削除されたタイミングでディスク上から削除される。

$ ln file1 file-hl

シンボリックリンク
Windowsのショートカットと同様に、あるファイルを別のファイル名で参照させる。
シンボリックリンクを削除しても元のファイルは削除されない。

$ ln -s file file-sl

$ ls -la
total 0
drwxr-xr-x  2 root    root     33 Apr 29 13:55 .
drwx------. 6 vagrant vagrant 234 Apr 29 13:31 ..
-rw-r--r--  1 root    root      0 Apr 29 13:50 file
lrwxrwxrwx  1 root    root      4 Apr 29 13:55 file-sl -> file

-sシンボリックリンクを作成

lsof

プロセスが開いているファイルを表示する
<ファイル名指定>
ファイルを開いているプロセスを特定

$ lsof /usr/local/nginx/logs/access.log
COMMAND  PID   USER   FD   TYPE DEVICE SIZE/OFF  NODE NAME
nginx   3202   root    3w   REG  253,0   416000 74101 /usr/local/nginx/logs/access.log
nginx   3629 nobody    3w   REG  253,0   416000 74101 /usr/local/nginx/logs/access.log

<ポート番号指定>
-iで指定したポートを開いているプロセスを特定

$ lsof -i:80
COMMAND  PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nginx   3202   root    7u  IPv4  24069      0t0  TCP *:http (LISTEN)
nginx   3629 nobody    7u  IPv4  24069      0t0  TCP *:http (LISTEN)

w

現在サーバにログインしているユーザを確認する

$ w
 12:15:40 up  8:48,  1 user,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
vagrant  pts/0    10.0.2.2         03:37    4.00s  0.16s  0.00s sshd: vagrant [priv]

tar

アーカイブを作成/展開する
tarは複数のファイルやディレクトリをまとめるだけであり、通常gzipなどの圧縮処理と組み合わせて利用される

<作成>

$ tar czvf dir1.tar.gz dir1
dir1/
dir1/file1.txt
dir1/file2.txt
dir1/file3.txt
dir1/file4.txt

※ オプションにハイフン「-」をつけなくてよい
cアーカイブを作成(Create)
zgzip形式を利用
v:処理したファイル一覧を表示
f:ファイルを指定

<展開>

$ tar xzvf dir1.tar.gz dir1
dir1/
dir1/file1.txt
dir1/file2.txt
dir1/file3.txt
dir1/file4.txt

xアーカイブの展開(eXtract:抽出)

xargs

入力を引数としてコマンドを実行する

$ ls test*
test_1.txt  test_2.txt  test_3.txt

$ ls test* | xargs rm

空白もしくは改行で区切られて文字列を1つずつコマンドに引数として渡して実行する。

tee

標準入力を標準出力とファイルに書き出す

$ ls -la | tee ls.txt
total 116
drwxr-xr-x. 13 root root   169 Apr 29 12:31 .
dr-xr-xr-x. 18 root root   273 Apr 29 12:29 ..
dr-xr-xr-x.  2 root root 20480 Mar 11 08:43 bin
drwxr-xr-x.  2 root root     6 Nov  5  2016 etc
drwxr-xr-x.  2 root root     6 Nov  5  2016 games
drwxr-xr-x. 34 root root  8192 Mar  5 14:56 include
dr-xr-xr-x. 27 root root  4096 Mar  5 14:56 lib

上の標準出力に加えてファイルにも書き出されている

# cat ls.txt
total 116
drwxr-xr-x. 13 root root   169 Apr 29 12:31 .
dr-xr-xr-x. 18 root root   273 Apr 29 12:29 ..
dr-xr-xr-x.  2 root root 20480 Mar 11 08:43 bin
drwxr-xr-x.  2 root root     6 Nov  5  2016 etc
drwxr-xr-x.  2 root root     6 Nov  5  2016 games
drwxr-xr-x. 34 root root  8192 Mar  5 14:56 include
dr-xr-xr-x. 27 root root  4096 Mar  5 14:56 lib

find

ディレクトリツリーからファイルを検索する

$ find . -type f -name "*.txt"
./test.txt
./member.txt
./dev/dev.txt
./dev/test/file.txt

-type:ファイルの種類を指定(f:ファイル、d:ディレクトリ、l:シンボリックリンク
-name:ファイル名を指定(-inameとすると大文字小文字を区別しない)
上の例ではカレントディレクトリ配下の.txtファイルを検索して表示している。

参考

[改訂第3版]Linuxコマンドポケットリファレンス

[改訂第3版]Linuxコマンドポケットリファレンス

ペパカレのインフラ研修を修了した

どうもつるべーです。
私は2018年3月1日から、GMOペパボ本社にてペパボカレッジ(通称ペパカレ)のインフラ研修を受けており、4月6日に無事修了することができました!
今回は研修で学んだことやこれからやりたいことなどを書いていきます。
以前ペパボへの転職エントリーも書いたので、よければ読んでください!

www.hirotsuru.com

ペパカレって?

ペパカレとは第二新卒エンジニア向け研修のことで、中途で入ってもみっちり研修を受けられます。
私はペパカレ6期生で、これまでWebアプリケーションエンジニアとモバイルアプリケーションエンジニアの採用があったみたいですが、インフラエンジニアのペパカレは今回が初めてだったようです。 ペパボカレッジについては詳しく知りたい方は下の記事を見てください!

www.wantedly.com

やったこと

作業環境ハンズオン

  • zshの導入
  • tmuxの導入
  • ghqとpecoを使ったGit環境の整備(参考

(一言)
ターミナルやエディタ周りはエンジニアにとって最も重要な仕事道具であるため、こだわりを持ってハックすることが大事

Linuxオペレーション基礎

  • Linuxコマンド100本ノック
    • awkコマンドを使ったログの集計
    • grepコマンドによる文字列検索など

(一言)
実際は30本ノックくらいだったかな?一つの処理をするコマンドをパイプで繋いでいき複雑な処理を行っていくところにUNIX哲学を感じた。

オンコール対応

  • 障害原因の調査(ログ・プロセス監視など)
  • サービスの復旧
  • ポストモーテム
作成

(一言)
サンプルのサービス上で意図的に障害を起こしてもらいオンコール対応の疑似体験をした。
障害発生時には「データ(パケット)が流れる順番に沿って調査する」ことが重要だ。

Infrastructure as Code入門

(一言)
いろんな技術に触れまくって超楽しかった。一気に使えるツールが増えた。
Infrastructure as Codeは奥が深いからIaC本を隅々まで読んで復習をしよう。

コマンドラインツール開発

(一言)
初めてコマンドラインツールを作った。Rubyを書くのが楽しくなった。

スクラム研修

  • レゴスクラムを通したチーム開発手法の研修

(一言)
チームでレゴを使って街を作った。大人になってレゴ初めてやったけど普通に楽しい。
チームで作業をするときは、みんなでコミュニーケーションを取り、作りたいものの認識を合わせることが重要だ。

振り返り会

  • KPTを使った週次の振り返り

(一言)
振り返りってこれまでちゃんとやったことがなかったし、その重要性がわかってなかったけど、振り返りの文化はチームでも個人でも超大事だと思った。
何が大事かっていっぱい理由はあるけど「俺たちは前に進んでるんだ」って実感が得られるのが大きいんじゃないかな。

その他(仕事の進め方など)

  • GitHubを使ったPRベースの仕事の進め方
  • Slackの活用方法(スレッドの活用など)
  • コミュニケーション方法
    • 誰かに何かをお願いするときは、いつまでにやってほしいかを明確にする
    • 自分側にあって、相手側にない情報を的確に伝える
    • 遠慮はしない
  • 勉強していて疑問に思ったことはガンガン共有する
  • 何かを習得するときに自分の言葉で説明できるようになる(言語化できること)が重要

(一言)
技術的なところ以外にもいっぱい学びがあるのがペパカレ。

気持ちが変わったこと

自分は成長する存在だと信じられるようになった

これまでエンジニアになって1年間ちょっとの間、自分が成長していると思えなくて悩んでいた時期もあったが、ペパカレでは凄まじいスピードでいろんな技術を習得させてもらったことや、それら学んだ技術を毎週振り返り会で書き出して実感することで、自分の成長を実感できた。
そもそも「自分の成長を信じれないなら、頑張る意味なんてないんだ」と思うようにもなった。

ペパボが大好きだ

  • どんなに小さなことでも褒めてくれる
  • ネガティブな発言はしない
  • みんなと仲良く、でも遠慮はしない
  • 困っているときにいろんな人が手を差し伸べてくれる。
    そんなペパボが大好きになった。

全体を通しての感想

今回のペパカレでのインフラ研修を一言で表現をすると 最高 という言葉しか思い浮かばない。
教えてくださる講師の方々も 最高 、一緒に学ぶ同期も 最高 、会社の雰囲気も 最高 、窓から見える渋谷の街も 最高チリチリネパリコ最高 、最寄りのジムのトレーニング器具も 最高 だった。
ペパカレは本当に頑張る人を支援する仕組みだから、自分と同じようにITとは全く関係のない仕事をしていて、でもITめっちゃやりたいという人にもぜひチャレンジしてほしい。

今後やっていきたいこと

今後は福岡に帰り、インフラ業務をやらせてもらうが、研修でいっぱい学んだとはいえ、広大なインフラの中ではほんの一部であり、まだまだ足りない知識や技術もたくさんあるだろうと思っている。なので、まずはインフラエンジニアとして必要な知識や技術をいち早く習得し、日常的なインフラの業務をこなせるようになることが最優先でやりたいことだ。
その中で、現場の様々な課題に自分自身が直面し、コードを書いて問題解決できるようになりたい。そしてゆくゆくは、自分の得意な領域でかつ誰にも負けない領域を築き上げて、自分にしか作れないものを作ることが夢だ。
あと引き続きベンチプレス150kgを目標に体も鍛え続けたい。

f:id:hirotsuru314:20180408231615j:plain

k近傍法による異常検知のライブラリをmrubyで作ってみた

こんにちは!インフラエンジニア見習いつるべーです。
今回は、mrubyという組込ソフトウェア向けの軽量なRuby言語を使って、k近傍法による異常検知を行うスクリプトを書いてみたので、そちらの紹介です!

目次

なぜ作ったのか

今回は、「何かの問題を解決したい」というよりは、「Rubyの勉強がてらに何か作ってみよう」という動機で作りました。
ただ、一般的なRuby(CRuby)ではなくmrubyを選択したのには理由があります。
私が勤めているGMOペパボでは、mrubyを利用してミドルウェアの振る舞いを設定・制御する仕組み(これを"Middleware Configuration as Code"と呼んでいる)を積極的に導入しており、そこに非常に興味を持ったからです。
下の二つのスライドには、"Middleware Configuration as Code"の概要や事例がまとめられています。

Middleware Configuration as Code // Speaker Deck

Middleware as Code with mruby

作ったもの

ソースコード

github.com

k近傍法に基づく異常検知の理論は最後に書いておくので興味のある方はぜひ!

使い方

mrubyで自分が書いたコードを動かすには、mrubyのコンパイル時に書いたコードを組み込んでコンパイルする必要があります。
したがって、まずはmrubyをコンパイルする環境を用意する必要があります。QiitaにCentOS7上でmrubyをコンパイルして動かすまでの手順を書きましたので、ご参考までに。

qiita.com

mrubyをビルドする前にbuild_config.rbに以下の記述を追加してやると、mruby-knn-detectorを組み込んだmrubyができます。

MRuby::Build.new do |conf|

    # ... (snip) ...

    conf.gem :github => 'tsurubee/mruby-knn-detector'
end

それでは、mirbというCRubyにおけるirbに相当する対話型インタープリタを使って動かしてみます。
※ mruby-knn-detectorは一次元の時系列データの異常検知を行うもので、入力データは一次元配列になります。

$ mruby/bin/mirb
mirb - Embeddable Interactive Ruby Shell

> knn = KNN.new(2, 1)  #(Window size, Number of neighbors)
 => #<KNN:0xdc0fa0 @k=1, @w=2>
> data = [1, 2, 10, 2, 1]
 => [1, 2, 10, 2, 1]
> knn.score(data)
 => [0, 1.4142135623731, 8.0622577482985, 8.0622577482985, 1.4142135623731]

KNNクラスの引数にはスライド窓の幅と近傍数を渡してやり、一次元配列をscore関数に投げ込むと、投げ込んだ配列と同サイズの異常度配列が返ってきます。
(スライド窓や近傍数については最後に解説しています)
返ってきたら異常度配列のうち要素の値が大きいものほど異常度が高いと判断できます。

mrubyに入門するには

mrubyを書き始めるのはCRubyやPythonなどを始めるより少しハードルが高く感じました。それはなぜかというと、コンパイルということに馴染みがなかったからです。私自身ほぼPythonしか書いたことがなかったため、今回初めて自分の書いたコードをコンパイルしました。
それでは、私と同じように「mrubyってちょっと取っつきづらいよ」と感じる方がどうやってmrubyに入門すると良いかということについてですが、私の場合、最初に「WEB+DB PRESS Vol.101」の中で@pyama86さんが執筆された「mrubyを活用したインフラ運用の最前線」を読みました。mrubyの部分は本の中の7ページだけですが、実際にmrubyを利用して開発を行うときに必要な手順がわかりやすく解説されていました。
具体的には、@matsumotoryさんが開発しているmruby-mrbgem-templateを用いたmrbgem開発の基本的な流れが書かれていました。 mruby-mrbgem-templateを用いると、たった数コマンドでmrbgemのひな形が生成されるため、大変便利でした。
mruby-mrbgem-templateの使い方は下の記事に解説がありました。

qiita.com

mrbgemのひな形までできると、あとは普通にRubyを書いていくだけでした。
やりたいことによっては、Linuxシステムコールを利用するような処理をC言語で実装し、C言語のメソッドをRubyから呼び出したりできるようです。
今回私は50行くらいのRubyを書いただけです。

Changefinderとの比較から見るKNNの特徴

mrubyによる異常検知の実装には@matsumotoryさんのmruby-changefinderがあります。今回これとKNNの比較をしてみたいと思います。
用いるデータは、あんちぽさんがmruby-changefinderを使った異常検知例を以前のブログに書いていたので、それを真似てみようと思います。
データの元ネタは「異常検知でGo!」のデータを使っています。
ハイパーパラメータは以下のような値を用いました。(ハイパーパラメータとは人が決定しなければならないパラメータのこと)

# ChangeFinder
cf = ChangeFinder.new(5, 0.01, 10, 0.01, 5)

# KNN
knn = KNN.new(5, 5)

異常検知の結果が以下のグラフになります。比較しやすくするために縦軸は調整しています。

f:id:hirotsuru314:20180401183834p:plain

KNNもなかなかいい形してますね!
ここで両者の違いをいくつか議論します。(アルゴリズム的にどちらが優れているとかいう話ではない)
まず、ハイパーパラメータについてですが、ChangeFinderが5つに対して、KNNは2つしかありません。したがって、ChangeFinderの方が柔軟な設定が可能であり、確率分布がバチっとハマった時は強そうですが、ハイパーパラメータのチューニングが大変だとも言えます。
明示的に確率分布を仮定しない、KNNや特異スペクトル変換などのアルゴリズムは、ハイパーパラメータも少ないですし、様々なデータに頑強な印象です。
ChangeFinderのメリットの一つは逐次的な学習アルゴリズムであるため、初期学習をしておけば、新しい観測点に対して、一つの異常度を返します。そのため、計算も比較的軽量ですし、異常度のデータを受け取る側の実装もシンプルに組めそうです。
一方、KNNは、今の実装だとデータ配列を受け取って、それと同じサイズの異常度配列を返すので、オンラインで異常検知してやるには実装側でインプットのデータ配列をいい感じにずらしながらデータを投げ込んでやる必要があるし、計算もそこそこ重いです。

今後やりたいこと

Ruby・mruby周りで今後やりたいこと。

  • テストを書く
    今回はなるべく早く動かしたかったのでテストの実装をサボりました。Travis CIで自動テストするとこまではちゃんとやりたい。

  • 言語仕様を学ぶ
    下の本をちら見したらmrb_stateとかmrb_valueとか知らないことがいっぱい解説してあったので、ちゃんと読むと言語仕様を学ぶのに良さげな感じ。

eb.store.nikkei.com

オマケ:k近傍法(K-Nearest Neighbor :KNN)に基づく異常検知の理論

k近傍法とは一般的には多クラス分類のアルゴリズムですが、ちょっとした工夫で時系列データの異常検知にも応用することができます。
k近傍法を言葉で簡単に説明すると、「各点から最も近いデータへの距離を計算することで異常度を算出する手法」です。
もう少し詳しく解説していきます。
まず、1次元の時系列データを時間的に隣接したまとまりとして取り出します。これはスライド窓とも呼ばれ、下のようなイメージです。

f:id:hirotsuru314:20180401181356p:plain

この長さwの窓を左から右にずらしていくことで、1次元の時系列データをスライド窓の幅の次元数の列ベクトルの集合に変換することができます。
ここで列ベクトルとは空間上の点のようなものだとイメージして下さい。(正確には、ユークリッド空間の原点から空間内のどこか一点を結ぶ有向線分)列ベクトル同士には近い/遠い、すなわち距離の概念を考えることができます。k近傍法では、ある列ベクトルから距離が近いベクトルをk個取り出して、その距離の大きさをもとに異常度を算出します。
ここで、ベクトル間の「距離」の求め方と、「異常度」の算出方法には任意性があります。
今回の実装では、距離は典型的にはユークリッド距離を用いています。(マハラノビス距離などを使うこともできる)
異常度の計算には、k個の近傍距離の平均を用いました。

Terraformでインスタンスの停止ができない理由を考えたらInfrastructure as Codeへの理解が深まった話

こんにちは、筋肉系インフラエンジニア見習いのつるべーです。
私は今、GMOペパボ株式会社でペパボカレッジという第二新卒エンジニア向け研修を受けている真っ最中です!
今回のエントリーは、私が研修中に感じた素朴な疑問を会社のコミュニケーションツールに書いたら、そこから議論が広まって、最終的にはInfrastructure as Codeという重要な概念への理解を深めることができたよ、という話です。

Infrastructure as Codeって?

Infrastructure as Codeを一言で表すと「コードによりインフラの管理をすること」です。
コードで管理することのメリットとしては、

  • コードのバージョン管理ができる
  • 設定変更の適用前にプルリクエストベースで確認が行える
  • 設定の共有・再利用が容易である
  • オペレーションミスが防げる
  • インフラ構築の属人化が防げる

などが挙げられます。
現在、Infrastructure as Codeを実現するためのツールは、Terraform、Puppet、Ansibleなど数多く存在し、それぞれがコード管理をしたい対象のレイヤーが異なっていたりして、非常に複雑なため、その点については下記のブログが大変参考になります。

インフラ系技術の流れ - Gosuke Miyashita

サーバのプロビジョニングを「Orchestration・Configuration・Bootstrapping」という3つのレイヤーで分けて説明されている点がとても参考になりました。

問題提起

今回はタイトルにもあるようにTerraformというツールについての話です。(ツールに固執した話ではなく単に考えるきっかけがTerraformだった)
TerraformはHashiCorpが開発している「インフラの構築・変更を効率的に行うためのオーケストレーションツール」です。AWSにおけるCloudFormationのような存在です。

www.terraform.io

Terraform独自のテンプレートにインフラ構築に必要な各種リソース(インスタンスやネットワークなど)を定義し、適用のコマンドを実行すると、定義したインフラの「あるべき姿」を再現してくれます。私は、Terraformを使って実際のWebサービスを想定したインフラを構築する研修を受けていました。
Terraformでは、定義ファイルを書いてterraform applyとコマンドを叩くと定義した全インスタンスが立ち上がって、terraform destroyとコマンドを叩くと立ち上げた全インスタンスが削除されます。
ここで一つ疑問が湧きました。インスタンスの起動・削除はできるけど、インスタンスの停止は??
terraformコマンドのオプションを見てみると、(一部省略)

$ terraform --help
Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

stopやpauseがないんですね。起動や削除はできるのに停止ができないのはなんでやねん!!ってなったわけです。
そこで社内のコミュニケーションツールで質問してみました。

つる「TerraformのCLIからインスタンスの停止ってできないんですか?」

すると・・・ペパボのハイパーエキセントリックボウイな先輩方が

「Terraformの役割をちゃんと説明できますか?」

インスタンスを停止したい理由がなぜかを考えてみては?」

「サーバのライフサイクルの観点から考えてみては?」

オライリーの『Infrastructure as Code』を読んだ方が・・」

「上のようなことがわかるとなぜTerraformで「インスタンスを停止する」操作をしないかが自分の言葉で言えるようになるかも」

などとありがたいコメントをいっぱいくれたわけです。これをきっかけに、私なりに色々考えた結果が今日のメインの話です。(素朴な疑問にこれだけ反応してくれる環境って最高ですよね?)

注意点

  • Terraform以外の他のツールがインスタンスの停止ができるのか?というところは知りません。したがって、議論のきっかけは汎用性に欠けるかもしれませんが、そこから得られる議論や考察には一定の汎用性があると思っています。

  • 後述の話はあくまで私の考察です。実際にTerraformが何かしらの信念をもって敢えて「インスタンスの停止を実装していない」のか、そこまで深い意味がないのかどうかは知りません。ただ、色々考えると、停止って別になくてもいいよねってなりました。(インスタンス停止が絶対ダメ!という話ではない)

  • 今回のサーバとインスタンスはほぼ同じ意味で使っています。

自分なりの考え

解釈が間違っていたり、他にも考えをお持ちの方はビシバシ指摘してください!

Terraformの役割は何か?

Terraformはインフラストラクチャの定義をコードで管理するオーケストレーションツールです。ここでいうインフラストラクチャは通常、相互に関連し合う様々なスタックから構成され、Terraformはこれらの複数のスタック構成を「ある状態」に収束させるためのツールであるともいえます。
つまり、Terraformの役割は、単体のサーバの管理ではなく、サーバーの集合体(クラスタ)を管理する役割です。これは「オーケストレーション」という言葉のそもそもの意味からも言えそうです。

オーケストレーションとは複雑なコンピュータシステム/ミドルウェア/サービスの配備/設定/管理の自動化を指す用語。(Wikipediaより)

とあるように「複雑な」システムの管理等が目的であるため、単体のリソースに着目するものではないと言えます。
このことから、Terraformでは「ひとつだけのサーバを停止する」ような操作を用意していないのかもしれません。じゃあ全台一気に停止するようなコマンドはあってもいいのでは?

サーバを停止したいのはなぜか?

「サーバを停止したいのはなぜか?」を考えると、それは「サーバの構成/設定を変更したいから」です。
Infrastructure as Codeの意義はインフラストラクチャの定義をコードで管理することで、「統一的な」管理ができる点にあります。そこに対して、サーバを停止して手作業で設定変更を行うなどといった管理されていない変更を許すと、統一的な管理が失われ、構成ドリフトやスノーフレークを招く恐れがあります。そのため、オートメーションの外からサーバに変更を加えることを認めてはなりません。これがTerraformからインスタンスの停止ができない理由の一つだと考えます。

サーバの変更管理モデルについて

ただし、インスタンスの停止ができないからといってオートメーションの外からの管理されていない変更を完全に排除することにはなりません。ここで、サーバの変更管理モデルにまで話を深めていくと、「Immutable Infrastructure」という考え方があります。これは、サーバの構成/設定を変更する際に、既に動いているサーバに対して変更を加えるのではなく、変更が加えられた全く新しいサーバを構築する手法です。これにより、オートメーションの外から加えられた変更を打ち消すことができ、構成ドリフトなどを防ぐことに非常に有効です。
このように昨今のインフラ、特に仮想化技術やクラウド技術が使われたインフラにおいては、「サーバのライフサイクルを短く保つこと」が求められています。こういった背景も、Terraformでインスタンスdestroyはできるがstopができない理由の一つかもしれないと考えました。

さいごに

今回のことを考えているうちにInfrastructure as Codeって本当におもしろいなーって思いました!ここに昨今のコンテナ化技術の議論が入っているとさらに奥が深くなりおもしろそうですね。私は今回の一連の議論からInfrastructure as Codeに非常に興味を持ったので、これからも勉強していきたいと思います。
あと、Twitterにも書いたのですが、

こんな成長できる環境に身を置けることが心から幸せです。以上、最後まで読んでいただきありがとうございました!

参考

Infrastructure as Code ―クラウドにおけるサーバ管理の原則とプラクティス

Infrastructure as Code ―クラウドにおけるサーバ管理の原則とプラクティス

「3分間ネットワーク基礎講座」を読んだ

ネットワークの勉強をするため「3分間ネットワーク基礎講座」という本を読みました。
私は2月からインフラエンジニアに転職しました。業務の中でネットワークのことを知らなすぎて危機感を感じたため、有名なマスタリングTCP/IP 入門編 第5版を読もうと試みたのですが、私にとっては難しすぎました。そこでもっと初心者寄りの本を探してこの本に行き着きました。

[改訂新版] 3分間ネットワーク基礎講座

[改訂新版] 3分間ネットワーク基礎講座

本の紹介と感想

本書を読んだ率直な感想は、「めっちゃくちゃわかりやすかった」です。ネットワークについてちゃんと学んだことがない人が最初に読む一冊としてはかなり良い選択だと思います。
本書は「3分間Networking」というWebサイトを元に書籍化したみたいです。
本書の特徴は、

  • 対話形式で読みやすい

  • OSI参照モデルを中心に広範囲のネットワークについてカバーしている

といった点が挙げられるかと思います。
対話形式である点は、正直好き嫌いがあるかと思うのですが、私は読みやすく感じました。もともとネットワークには堅苦しいイメージがあり、抵抗感があったのですが、難しいこともカジュアルにポイントを押さえて書いてあったので、頭に入りやすかったです。
内容としては、最初にネットワークの基礎について書いてあり、OSI参照モデルの話が出て、そこからOSI参照モデルの各レイヤーを下から順に丁寧に解説していく感じです。特にレイヤー1〜4に大部分のページが割かれており、レイヤー5以上は最後にちょろっと触れてあるだけでした。 本書を読むと、OSI参照モデルの全体像と各レイヤーの役割・要素技術の知識が得られます。 私はTCPとかIPアドレスとかふんわりとしか理解してなかったので、頭の中が整理されてちょうどよかったです。 これでマスタリングTCP/IP 入門編 第5版と戦えるようになっているはずだと信じて読み進めていきたいと思います!

読書ノート

私がポイントだと思ったことだけをまとめた読書ノートです。

1章 ネットワークの基礎知識

回線交換とパケット交換
  • データ通信には回線交換とパケット交換がある。コンピュータネットワークはパケット交換方式。
    データをパケットに分割して送るため回線を占有する時間が短く、回線を複数のコンピュータで共有できる。
ネットワークの構造
  • パケット交換機なしでケーブルの分岐でつながっている範囲のことをセグメントと呼ぶ。分岐させるためにハブという機器を使う。
    セグメントの範囲内にあるコンピュータはパケット交換機なしで直接データのやりとりができる。このようなネットワークの構造をマルチアクセスネットワークと呼ぶ。

  • 一方、専用線を用いて固定した相手としかデータのやりとりができないネットワークをポイントツーポイントネットワークと呼ぶ。

LANとWAN
  • LAN(Local Area Network)は地域的に狭い範囲で自身の責任で構築するネットワーク。

  • WAN(Wide Area Network)は離れた地域にあるLAN同士を電気通信事業者(NTTやKDDIなど)の通信ケーブルを借りてつないだネットワーク。
    世界規模で最大のWANがインターネット。

  • インターネット接続サービスを行うプロバイダはISP(Internet Service Provider)と呼ばれる。

OSI参照モデル
  • OSI参照モデル(Open Systems Interconnection Reference Model)はデータ通信の標準化を行うために作られたデータ通信全体の「段階と手順の設計図」。 OSI参照モデルではデータ通信を7つの段階に分けている。この段階のことを層(レイヤー)と呼ぶ。

  • レイヤーはそれぞれ独立している。すなわち、基本的にはレイヤーのプロトコル変更は他のレイヤーに影響しない。

  • 下のレイヤーは上のレイヤーのために働き、上のレイヤーは下のレイヤーのことに関知しない。

カプセル化
  • データとデータを送るために必要なものがまとまった状態をプロトコルデータユニット(PDU)と呼ぶ。 それぞれのレイヤーごとにPDUがあり、それらが順々にくっついて実際に送信するPDUができるイメージ。
    このようにデータに制御情報をくっつけてPDUを作り上げることをカプセル化と呼ぶ。

  • カプセル化で追加される制御情報は、データの前につくときはヘッダー、うしろにつくときはトレーラーと呼ぶ。

プロトコル
  • OSI参照モデルのレイヤーごとに、それぞれのレイヤーの役割のプロトコルが必要。

  • 上下のプロトコルをインターフェースでつなぐことでレイヤー7からレイヤー1までを一つのつながったプロトコル群と捉えることができる。基本的にはどのプロトコル群を使うかによって各レイヤーで使用するプロトコルが決まる。
    現在最も使われているのがインターネットで使われているTCP/IPプロトコル群である。

  • プロトコルは「データの中身を決める」「ヘッダーを決める」「やりとりの手順を決める」

TCP/IP モデル
  • TCP/IPIETF(the Internet Engineering Task Force)が制定している。
    IETFが制定する文章はRFC(Request For Comment)と呼ばれる。

2章 信号の伝送と衝突

レイヤー1の役割と概要
  • レイヤー1の役割は、ケーブルがつながっている機器への信号の伝達。

  • 信号が流れるパイプとなる通信媒体には有線と無線があり、優先には電気信号を使う銅線のUTP(Unshielded Twist Pari Code)と光信号を使う光ファイバーがある。

  • コンピュータとケーブルの仲介役であるインターフェースは、コンピュータが送りたいデータをケーブルに合った信号に変換してケーブルに流し、ケーブルから流れてきた信号をコンピュータで使うデータに変換する。

  • コンピュータで使われるインターフェースとして、LAN用のケーブルに接続するためのNIC(Network Interface Card)が一般的。

  • WANの場合の信号変換器をDCE(Data Circuit terminating Equipment:回線終端装置)と呼ぶ。

信号と衝突
  • インターフェースはビットを信号に、信号をビットに変換する機器である。信号にはアナログ信号とデジタル信号がある。

  • ビットは「0」か「1」、デジタル信号は「ON」か「OFF」であるため、デジタル信号はビットを表現しやすい。

  • 信号には減衰、ノイズ・干渉、衝突などの問題が発生する。

ハブ
  • ハブの機能1:複数の機器をつなげてネットワークを構築する機能。ハブにケーブルでつながっている機器は、同一のケーブルにつながっているのと同じ扱いになり、ハブにつながっている機器同士で信号のやりとりが可能になる。

  • ハブの機能2:ハブは減衰によって崩れた信号を元の形に増幅・成形する。増幅だけを行う機械としてリピーターというものがある。

  • ハブとハブをつなぐ接続をカスケード接続と呼ぶ。ハブをカスケード接続していけば大きなネットワークを作ることができる。

  • ハブは受信したポート以外のすべてのポートに受信した信号を送信する。これをフラッディング(Flooding)と呼ぶ。

  • 信号を送信すると衝突が起きるかもしれない範囲のことを衝突ドメインと呼ぶ。同じハブにつながっているコンピュータ同士は同時に信号を送信すると衝突が発生する可能性があるため、ハブでつながっている範囲は衝突ドメインにあることになる。(違うハブにつながっていてもハブ同士をカスケード接続していると衝突ドメインになる)「たまたま同じタイミング」で信号を送信する可能性を減らすためには衝突ドメインは小さくしなければならない。

レイヤー2の役割と概要
レイヤー2アドレスとイーサネット
  • アドレスはデータの送りかたによってユニキャスト、ブロードキャスト、マルチキャストの3種類存在する。
    ユニキャストは「1対1」の通信、ブロードキャストは「1対全」の全員宛の通信、マルチキャストは「1対多」の複数機器宛の通信。

  • それぞれの機器は最低1つ以上のユニキャストアドレスを持つ。ルーターのように複数のインターフェースを持つ機器は、インターフェースごとにユニキャストアドレスを持つ。

  • ユニキャストアドレスはユニークでなければならない。一方マルチキャストアドレスは「グループ番号」といった扱いであるため、同じアドレスを持つ機器が複数あってもよい。

  • イーサネットで使われるアドレスはMACアドレス(Media Access Control Address)と呼ばれるアドレスで、このアドレスはインターフェースにつけられた固定のアドレスである。

イーサネット
スイッチ
  • CSMA/CDは衝突を起こりにくくする仕組みであるため、衝突ドメインのコンピュータの台数が多い場合、衝突が起きて効率が悪くなる。これを防ぐために「信号が通る道を分ける」ための機器であるスイッチ(スイッチングハブ、L2スイッチなどとも呼ばれる)をハブの代わりに使用する。

  • 現在LANで使われているUTPや光ファイバーのケーブルは送信と受信の信号の通り道は分かれている。そのため衝突はケーブル上では発生せず、ハブで発生する。スイッチは「MACアドレスフィルタリング」と「バッファリング」で衝突を防ぐ。

  • スイッチはフレームを受信した際、送信元MACアドレスと受信したポートの対応をアドレステーブルという対応表の形で記憶する。これにより宛先MACアドレスに対応したポートからのみフレームを送信するのがMACアドレスフィルタリングである。
    MACアドレスフィルタリングにより別の宛先のフレームが同時にスイッチに届いても衝突が発生しなくなる。

3章 IPアドレッシング

レイヤー3の役割と概要
  • レイヤー3ではセグメント間でのデータのやりとりを行う。

  • ルーターはブロードキャストを中継しないので、ルーターを超えてブロードキャストは流れない。

インターネットプロトコル
  • レイヤー2のイーサネットではアドレスとしてMACアドレスを使ったが、MACアドレスに含まれているのはベンダーコードとベンダーがつけた番号だけで、「場所を特定できない」アドレスである。

  • レイヤー2で使用するアドレスは「物理アドレス」と呼ばれ、レイヤー3で使用するアドレスは「論理アドレス」と呼ばれる。違いはアドレスに位置情報が含まれているかいないか。

  • 「アドレッシング」と「ルーティング」によりインターネットワークを行うためのプロトコルとして、TCP/IPプロトコル群で使われるのがIP(Internet Protocol)

  • IPにはIP version4(IPv4)とIP version6(IPv6)があり、この二つに互換性はない。

  • データにIPヘッダーがついた状態のレイヤー3PDUはIPデータグラムと呼ばれる。

IPアドレス その1
  • IPアドレスネットワーク管理者がコンピュータに割り当てる。インタフェースが故障した場合、物理アドレスは変わるが論理アドレスは変わらない。
    MACアドレスはインターフェースに付属しているため、コンピュータどこにいても同じアドレスであるのに対して、論理アドレスはコンピュータの場所を変えるとアドレスも変わる。

  • IPアドレスにもユニキャスト・マルチキャスト・ブロードキャストの3種類のアドレスがある。

  • IPv4では32ビットで「ネットワークの番号」の「コンピュータの番号」を表す。8ビット毎の区切り(オクテット)を10進数にして表記される。

IPアドレス その2
  • 「ネットワークの番号」は接続されているすべてのネットワークでユニークである必要がある。これはICANN(The Internet Corporation for Assigned Name and Number)という組織が割り当てている。ICANNIPアドレスを実際に使うプロバイダーや企業に貸し出しているイメージ。

  • どのオクテットまでがネットワーク番号かでクラスに分けられる。ネットワーク番号の部分のビット数が少ないとそれだけ多くのコンピュータを所有する大きなネットワークになれる。

  • ICANNによりネットワーク番号が割り振られれば、コンピュータ番号(これをホスト番号と呼ぶ)はそのネットワーク管理者が決められる。

  • ホスト番号のビットがすべて0のアドレスはネットワークアドレスで、ネットワークそのものを示すアドレス。
    ホスト番号のビットがすべて1のアドレスはブロードキャストアドレスで、ネットワークに所属するすべてのホストを示す。

サブネッティング
  • IPアドレスは階層型のアドレスであり、大きなネットワークを小さなネットワークに分割できる。このように分割された小さなネットワークのことをサブネットワーク、またはサブネットと呼ぶ。

  • ホスト番号のビットを、サブネット番号とホスト番号に分割する。
    サブネットを使用する場合、IPアドレスはネットワーク番号、サブネット番号、ホスト番号で構成される。

  • サブネットを使用する場合はサブネットマスクと呼ばれるビット列をIPアドレスと一緒に表記する。ネットワーク番号・サブネット番号のビットをすべて1、ホスト番号を0にしたもの。サブネットを使用していなければクラスによってどこまでがネットワーク番号かわかる。

クラスレスアドレッシング
  • クラスフルアドレッシングは3つのクラスに分けるため、組織が使用するIPアドレスの個数がクラスにぴったりと当てはまらないと無駄が多くなる。そこで登場したのがクラスレスアドレッシング。

  • クラスレスアドレッシングでは必要なIPアドレスの個数からネットワーク番号を決める。例えばクラスCのネットワーク(192.168.32.0〜192.168.39.0など)をまとめて1つのネットワークとして運用する。

  • サブネットマスクと同様にネットワーク番号のビット数を表す値としてプレフィックス長がある。IPアドレスのうしろにスラッシュを書いてネットワーク番号のビット数を書く(例:192.168.32.0/21)。プレフィックス長はCIDR(Classless Inter-Domain Routing)表記とも呼ぶ。

DHCP
ARP
  • ARP(Address Resolution Protocol)は宛先IPアドレスに対応したMACアドレスを調べる。そのためにはIPアドレスMACアドレスの対応表であるARPテーブルを参照する。

  • ARPテーブルに宛先IPとMACアドレスの対応がない場合、ブロードキャストでネットワーク内の全コンピュータにARP要求が送信される。ARP要求を受け取ったコンピュータのうち、指定されたIPアドレスを持つコンピュータだけがARP応答を返す。ARP応答を受け取ったコンピュータはARPの結果をARPテーブルに載せる。

  • ARPテーブルの情報は一定時間で消去される。

DNS

4章 ルーティング

アドレスと経路
  • 宛先IPアドレスは最終的なデータの届け先を示すのに対し、宛先MACアドレスは同じネットワーク内での宛先(次の届け先)を特定する。宛先IPアドレスは最後まで変わらないが、宛先MACアドレスは変わる。

  • ルーターは宛先までの経路を示しているのではなく、次にどこへ送ればよいかだけ決定している。

  • ルーターがなければ別のネットワークへデータグラムを送ることはできない。
    コンピュータは「宛先が別のネットワークにある場合はルーターへ送信する」「宛先が同じネットワークにある場合は直接宛先へ送信する」というルールで動いている。

  • コンピューターが指定するルーターのことをデフォルトゲートウェイと呼ぶ。

ルーター
  • ルーターはネットワークの境界上にあり、複数のネットワーク同士をつなぎ、ルーティングにより次のルーターを指定して経路を作る。

  • ルーターは複数のインターフェースを持ち、それぞれ異なるIPアドレスを持つ。(複数のネットワークに所属している)

  • ルーティングとはデータグラムの宛先IPアドレスを元に、次に送信するルーターを決定すること。

  • ルーターはルーティングテーブルを持っている。

デフォルトゲートウェイ
ルーティング
  • ルーターは最適な経路を見つけるために他のネットワークへの経路をすべて知る必要がある。
    経路を知る方法としてルーターが自動で情報を交換し合い経路を知る動的ルーティングという方法がある。

  • 動的ルーティングのメリットは障害があった場合に、自動で新たな最適経路にルーティングテーブルを書き換えること。

  • 動的ルーティングのデメリットはルーター同士が情報を交換し合うため、その分の回線の転送を圧迫すること。さらに、最適な経路を計算するための処理能力も必要。

ルーティングプロトコル
  • ルーティングプロトコルとは、動的ルーティングにおいて、近接ルーターとの間でネットワークの情報を交換し合うためのルール。交換した情報を元にルーティングテーブルを変更する。
ICMP
  • IP以外のレイヤー3のプロトコルとしてICMP(Internet Control Message Protocol)がある。ネットワークの制御や管理に使用される。

  • 通常IPデータグラムのペイロードにはTCPセグメントかUDPセグメントが入るが、これらの代わりにICMPメッセージを入れて送る。

  • ICMPにはQueryメッセージとErrorメッセージがある。Queryは状態を調査するために使用されるメッセージで、Errorはエラーを通知するためのメッセージ。

  • pingやtracerouteはICMPを利用したコマンドである。

5章 コネクションとポート番号

レイヤー4の役割と概要
  • レイヤー4の役割のにはエラーで届かなかった場合にデータを送り直すエラー回復や、処理しきれないデータが溢れ出てしまうのを防ぐフロー制御などがある。

  • ポート番号を使って、どのアプリケーションにデータを届けるかを判別する。IPアドレスMACアドレスだけではアプリケーションを識別できない。

  • レイヤー4で用いられるプロトコルにはTCP(Transmission Control Protocol)とUDP(User Datagram Protocol)がある。主な役割は「エラー回復」「フロー制御」「アプリケーションの識別」

コネクションとセグメント
  • TCPではアプリケーション間のデータのやりとりを行う。このアプリケーション間のやりとりを行うデータの道のことをコネクションという。

  • TCPで作られる通信路は仮想的な通信路と呼ばれる。この仮想的な通信路を作り出すことをコネクションの確立という。

  • 大きいデータはMSS(Max Segment Size)に分割し、その先頭番号をシーケンス番号とする。

ポート番号
  • ポートとアプリケーションを接続する機能をソケットという。
ネットワークアドレス変換
NAPT
  • NAPT(Network Address Port Translation)の最大の特徴は、1つのグローバルIPアドレスで複数台が接続可能であること。NAPTではIPアドレスだけでなくポート番号も変換することによって複数台を識別可能にしている。

  • NAPTではNATテーブルにない変換はされないためセキュリティ面のメリットもある。一方、LAN内部に外部に公開したいサーバがある場合は、手動で変換を入力しておく(静的NAPT)

レイヤー5~7
  • レイヤー5~7はTCP/IPモデルではまとめて1つのプロトコルとして実装されていることが多い。