いますぐ実践! Linuxシステム管理

いますぐ実践! Linux システム管理 / Vol.278 / 読者数:2821名

こんばんは、うすだです。

先日、うだるような暑さの中、 天井に屋根だけある電気自動車にカメラとLiDARを取り付け、 人間が運転したときのデータを収集してきました。

ちなみに、LiDARとは、こういうものです。

今更聞けないライダー(Lidar)入門 | TechCrunch Japan
https://jp.techcrunch.com/2017/02/13/20170212wtf-is-lidar/

なお、LiDARのデータを見ているだけでも、半日くらいは飽きずに過ごすことができます。 楽しいです。
(どう楽しいかは、上記ページの動画をご覧いただければわかります。)

それはさておき、収集した後、データを確認してみたら、 カメラの画像がすべて真っ白になっていました。

社内の詳しい人に聞いてみたところ、それなりに高性能なカメラのチップは熱に弱く、 熱対策をしないと誤動作してしまうそうです。

確かに、データ収集しているとき、カメラに触るとかなり熱かったため、 途中からタオルをかぶせるなどしていたのですが、40度を越える猛暑の中では、 焼け石に水、もしくは水にもなっていなかったようです。

というわけで、炎天下の下、 クーラーもドアもない車でカメラによる撮影を今後行わなければならなくなった暁には、 熱対策をめいいっぱい存分に行うようにしていただきたいと存じます。

夏の間に、もう一回データを取りに行ってこい! と言われないことを切に願いつつ、 今回もはりきってまいりたいと思います。

今回のお題 - flannelを動かしてみる (レベル:中級)

Kubernetes では、複数のノードでそれぞれコンテナを動かしていた場合でも、 コンテナ間で通信できるようになっています。

それには、「flannel」という仮想ネットワークが使われています。
(他にも選択肢があるようですが、flannelが多いです。)

Flannel - CoreOS
https://coreos.com/flannel/

別に、Kubernetesからでないと利用できない、ということはありません。
そこで、今回は、flannel を単体かつ手動で動かしてみたいと思います。

なお、例によって例のごとく、Ubuntu16.04でのみ確認しております。
ご容赦いただけますと、たいへん幸いです。

構成

今回は、2台のPC(Ubuntu16.04で、下記のsrv1とsrv2)を用意しています。

それぞれのネットワークインタフェース(eth0)にはIPアドレスが設定済であり、 同じサブネット(192.168.1.0/24)に属しています。

        <eth0>
  [srv1]-------------------------------------------------+
        192.168.1.1                                      |
                                         (192.168.1.0/24)|
        <eth0>                                           |
  [srv2]-------------------------------------------------+
        192.168.1.2

各PCにはDockerが動作する環境が整っており、コンテナ間 (container1 と container2 の間)で通信できるようすることが、今回の目標です。

                     <veth0>            <eth0>
  [[container1]------------------[srv1]]-----------------+
               10.0.X.2  10.0.X.1       192.168.1.1      |
                  (10.0.X.0/24)                          |
                                         (192.168.1.0/24)|
                                                         |
                     <veth0>            <eth0>           |
  [[container2]------------------[srv2]]-----------------+
               10.0.Y.2  10.0.Y.1       192.168.1.2
                  (10.0.Y.0/24)
つまり、10.0.X.2 と 10.0.Y.2 の間で通信できるようにします。
(10.0.0.0/16 をまるっとDockerで使用します。)

まずは etcd を動かす

Flannel では、設定情報を etcd で共有するようになっています。
そこで、まずは、srv1 と srv2 のそれぞれで etcd を動かします。

その手順は、前回と同じです。

Vol.277 - etcdを動かしてみる
http://www.usupi.org/sysad/277.html

…が、念のため、インストールしてからの手順をもう一度示します。
1台目(srv1)では、以下のように実行します。

  srv1$ ./etcd --name srv1 --listen-peer-urls http://192.168.1.1:2380 \
    --initial-advertise-peer-urls http://192.168.1.1:2380 \
    --initial-cluster srv1=http://192.168.1.1:2380,srv2=http://192.168.1.2:2380

2台目(srv2)では、以下のように実行します。

  srv2$ ./etcd --name srv2 --listen-peer-urls http://192.168.1.2:2380 \
    --initial-advertise-peer-urls http://192.168.1.2:2380 \
    --initial-cluster srv1=http://192.168.1.1:2380,srv2=http://192.168.1.2:2380

どちらか一方で以下を実行し、2台構成になっていることを確認します。

 $ ./etcdctl member list
  27470ba4b88bce9e: name=srv1 peerURLs=http://192.168.1.1:2380 \
  clientURLs=http://localhost:2379 isLeader=true
  f19e707aed49b299: name=srv2 peerURLs=http://192.168.1.2:2380 \
  clientURLs=http://localhost:2379 isLeader=false

そうしましたら、以下を実行して、flannel の設定情報を登録します。

  srv1$ ./etcdctl set /coreos.com/network/config \
    '{ "Network":"10.0.0.0/16", "Backend":{"Type":"vxlan"}}'

Flannel は、「/coreos.com/network/config」 に書かれたJSON形式の設定をもとに動作します。
「Network」で指定されたアドレスを使用します。割り当て単位はクラスC毎です (サブネットマスクが24)。割当単位を変更したければ、 サブネットマスクの長さを「SubnetLen」で指定します。

「vxlan」は、仮想的なネットワークインタフェースで、 UDPのデータ部にEthernetフレームを放り込んでカプセル化することで、 遠く離れたネットワークをつなぐことができます。これを使って仮想的につなぎます。

flannelを動かしてみる

では、flannel を動かしてみましょう。

Ubuntu のパッケージにはないため、githubから入手します。
それぞれのマシンで以下を実行します。

  $ curl -LO \
  https://github.com/coreos/flannel/releases/download/v0.10.0/flannel-v0.10.0-linux-amd64.tar.gz
  $ mkdir flannel-v0.10.0 && cd flannel-v0.10.0/
  $ tar xfz ../flannel-v0.10.0-linux-amd64.tar.gz
  $ ls
  README.md  flanneld*  mk-docker-opts.sh*

バイナリがどーんとあるので、 「-iface」とネットワークインタフェースを引数に指定して実行します。 (srv1, srv2 の双方で実行します。)

  $ sudo ./flanneld -iface eth0

すると、「flannel.1」というネットワークインタフェースが、 それぞれのマシンに作成されます。

  srv1$ ip link show flannel.1 
  5: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc \
  noqueue state UNKNOWN mode DEFAULT group default 
      link/ether 01:23:45:67:89:ab brd ff:ff:ff:ff:ff:ff

そして、10.0.0.0/16 に含まれるクラスCのネットワークが、 それぞれに割り当てられます。確認するには、「/coreos.com/network/subnets」 にあるキーを参照します。

  $ etcdctl ls /coreos.com/network/subnets
  /coreos.com/network/subnets/10.0.80.0-24
  /coreos.com/network/subnets/10.0.47.0-24

それぞれのキーの値を参照することで、詳細を確認できます。

  $ etcdctl get /coreos.com/network/subnets/10.0.80.0-24
  {"PublicIP":"192.168.1.1","BackendType":"vxlan","BackendData":\
    {"VtepMAC":"01:23:45:67:89:ab"}}
  $ etcdctl get /coreos.com/network/subnets/10.0.47.0-24
  {"PublicIP":"192.168.1.2","BackendType":"vxlan","BackendData":\
    {"VtepMAC":"fe:dc:ba:98:76:54"}}

srv1には「10.0.80.0/24」が、srv2には「10.0.47.0/24」 が割り振られたことがわかります。
実際、flannel.1 には、 「10.0.80.0」と「10.0.47.0」というアドレスがそれぞれ設定されています。

  srv1$ ip addr show flannel.1
  5: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc \
  noqueue state UNKNOWN group default 
      link/ether 01:23:45:67:89:ab brd ff:ff:ff:ff:ff:ff
      inet 10.0.80.0/32 scope global flannel.1
         valid_lft forever preferred_lft forever

  srv2$ ip addr show flannel.1
  5: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc \
  noqueue state UNKNOWN group default 
      link/ether fe:dc:ba:98:76:54 brd ff:ff:ff:ff:ff:ff
      inet 10.0.47.0/32 scope global flannel.1
         valid_lft forever preferred_lft forever

この時点で、10.0.80.0 と 10.0.47.0 同士の通信が可能です。

  srv1$ ping -c 3 10.0.47.0
  PING 10.0.47.0 (10.0.47.0) 56(84) bytes of data.
  64 bytes from 10.0.47.0: icmp_seq=1 ttl=64 time=3.90 ms
  64 bytes from 10.0.47.0: icmp_seq=2 ttl=64 time=3.87 ms
  64 bytes from 10.0.47.0: icmp_seq=3 ttl=64 time=4.49 ms

  --- 10.0.47.0 ping statistics ---
  3 packets transmitted, 3 received, 0% packet loss, time 2003ms
  rtt min/avg/max/mdev = 3.873/4.090/4.496/0.296 ms

ルーティングテーブルを確認すると、相手のネットワーク(10.0.47.0/24)へは flannel.1 を介して到達できる、という経路情報ができています。

  srv1$ ip route show
  default via 192.168.1.254 dev eth0  proto static  metric 600 
  10.0.47.0/24 via 10.0.47.0 dev flannel.1 onlink 
  192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.1...
  ...後略...

コンテナから使えるようにする

Dockerで使えるようにしてみましょう。

まず、dockerサービス(docker.service)の設定ファイルに手を加えます。
双方の「/lib/systemd/system/docker.service」の、

ExecStart=/usr/bin/dockerd -H fd://

となっている行を、

ExecStart=/usr/bin/dockerd -H fd:// --bip 10.0.80.1/24 --mtu 1450

に変更します。(上記は srv1 の場合です。srv2 では、 「--bip」の後のアドレスを「10.0.47.1/24」にしてください。)

そして、systemdに変更した旨を伝え、dockerサービスを再起動します。

  $ sudo systemctl daemon-reload
  $ sudo systemctl restart docker

すると、Dockerのネットワークインタフェース「docker0」に、 指定したアドレスが設定されます。

  srv1$ ip addr show docker0 
  4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc \
  noqueue state DOWN group default 
      link/ether 00:22:44:66:88:aa brd ff:ff:ff:ff:ff:ff
      inet 10.0.80.1/24 scope global docker0
         valid_lft forever preferred_lft forever
  ...後略...

ルーティングテーブルにも、「10.0.80.0/24」の経路情報が追加されて、 「docker0」を介して中継されることが分かります。

  srv1$ ip route show
  default via 192.168.1.254 dev wlp5s0  proto static  metric 600 
  10.0.47.0/24 via 10.0.47.0 dev flannel.1 onlink 
  10.0.80.0/24 dev docker0  proto kernel  scope link  src 10.0.80.1
  ...後略...

コンテナを起動してみましょう。
イメージ名を「ubuntu:latest」としていますが、 コマンドが同等に動作するものであれば、何でも構いません。

  srv1$ docker run -it ubuntu:latest /bin/sh
  # 

eth0(veth0)には、ちゃんとアドレスが設定されています。

  # ip addr show eth0
  8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc \
  noqueue state UP group default 
      link/ether 11:33:55:77:99:bb brd ff:ff:ff:ff:ff:ff
      inet 10.0.80.2/24 scope global eth0
         valid_lft forever preferred_lft forever

pingも通ります。(厳密には相手がコンテナではありませんが…。)

  # ping -c 3 10.0.47.0
  PING 10.0.47.0 (10.0.47.0) 56(84) bytes of data.
  64 bytes from 10.0.47.0: icmp_seq=1 ttl=63 time=4.01 ms
  64 bytes from 10.0.47.0: icmp_seq=2 ttl=63 time=4.18 ms
  64 bytes from 10.0.47.0: icmp_seq=3 ttl=63 time=3.97 ms

  --- 10.0.47.0 ping statistics ---
  3 packets transmitted, 3 received, 0% packet loss, time 2001ms
  rtt min/avg/max/mdev = 3.971/4.056/4.183/0.105 ms

確認し終えたら、コンテナをきれいに消しておきましょう。
(コンテナを1つしか起動していなければ、TABで補完できます。)

  # exit
  srv1$ docker rm コンテナ名

おわりに

以上、flannel の動かし方をさらっとご紹介しました。

最初の図に、実際に割り当てられたアドレスを記入すると、 うまく書けていない気もしますが、こういう感じでしょうか。

               <veth0>    <docker0>      <flannel.1>  <eth0>
  [[container1]--------------------[srv1]------------]------------+
               10.0.80.2  10.0.80.1      10.0.80.0    192.168.1.1 |
                 (10.0.80.0/24)                                   |
                                                  (192.168.1.0/24)|
                                                                  |
               <veth0>    <docker0>      <flannel.1>  <eth0>       |
  [[container2]--------------------[srv2]------------]------------+
               10.0.47.2  10.0.47.1      10.0.47.0    192.168.1.2
                 (10.0.47.0/24)

まあ、マシンが壊れることはほぼありませんので、試していただければと思います。

なお、/coreos.com/network/configの設定項目や、flanneldのオプションに関する情報は、 以下にあります。

flannel/configuration.md at master・coreos/flannel・github
https://github.com/coreos/flannel/blob/master/Documentation/configuration.md

宿題の答え

前回の宿題は、

  Minikubeで動作しているetcdにアクセスしてみましょう。

でした。

アクセスしてみた、と書くと、YouTubeの動画のタイトルっぽいですが、 それに似て、以下では実行してみた内容を淡々と示していくだけになっております。 ご容赦くださいませ。

まずは、Minikubeを起動し、起動したゲストOSにログインします。

  host$ minikube start
  host$ minikube ssh

etcdが動いていそうなコンテナを探します。

  $ docker ps | awk '/etcd/ {print $1, $3}'
  b97d7be7305b "etcd
  50a10cb37065 "/pause"

それっぽいものがありました。そのコンテナでshを起動してみましょう。
そして、etcdctlを実行してみます。

  $ docker exec -it b97d7be7305b sh
  # etcdctl member list
  client: etcd cluster is unavailable or misconfigured; error #0: \
  dial tcp 127.0.0.1:4001: getsockopt: connection refused
  ; error #1: malformed HTTP response "\x15\x03\x01\x00\x02\x02"

なんだか叱られてしまいました。
psコマンドを実行して、etcdが動いているかどうかなど確認してみます。

  # ps auxww | grep etcd | grep -v grep
     1 root      0:14 etcd --advertise-client-urls=https://127.0.0.1:2379 \
   --peer-client-cert-auth=true \
   --key-file=/var/lib/localkube/certs/etcd/server.key \
   --trusted-ca-file=/var/lib/localkube/certs/etcd/ca.crt \
   --peer-key-file=/var/lib/localkube/certs/etcd/peer.key \
   --listen-client-urls=https://127.0.0.1:2379 --client-cert-auth=true \
   --data-dir=/data --cert-file=/var/lib/localkube/certs/etcd/server.crt \
   --peer-cert-file=/var/lib/localkube/certs/etcd/peer.crt \
   --peer-trusted-ca-file=/var/lib/localkube/certs/etcd/ca.crt

SSL/TLSを使っているため、etcdとやりとりするには、 各種証明書の情報が必要なようです。
また、応答がJSONではなさそうなことから、 新しいバージョンで動作しているようです。
いきなりで恐縮ですが、下記のように実行すると話が通じました。

  # ETCDCTL_API=3 etcdctl --cacert=/var/lib/localkube/certs/etcd/ca.crt \
    --cert=/var/lib/localkube/certs/etcd/peer.crt \
    --key=/var/lib/localkube/certs/etcd/peer.key member list
  2018-07-29 11:37:20.827085 I | warning: ignoring ServerName for \
  user-provided CA for backwards compatibility is deprecated
  8e9e05c52164694d, started, default, http://localhost:2380, \
  https://127.0.0.1:2379

あるいは、環境変数を設定して実行すれば、同様の結果が得られます。

  # export ETCDCTL_API=3
  # export ETCDCTL_CACERT=/var/lib/localkube/certs/etcd/ca.crt
  # export ETCDCTL_CERT=/var/lib/localkube/certs/etcd/peer.crt
  # export ETCDCTL_KEY=/var/lib/localkube/certs/etcd/peer.key
  # etcdctl member list
  ...中略...
  8e9e05c52164694d, started, default, http://localhost:2380, \
  https://127.0.0.1:2379

以降では、環境変数が設定されているという前提で、実行例を示します。

で、バージョンが上がったからなのでしょうか、ls がありません。
(ヘルプをみても、ls というコマンドがありませんでした。)

  # etcdctl ls 
  Error: unknown command "ls" for "etcdctl"
  Run 'etcdctl --help' for usage.
  Error:  unknown command "ls" for "etcdctl"

以下のように実行すると、キーの一覧を得ることはできます。

  # etcdctl get / --prefix --keys-only
  /registry/apiregistration.k8s.io/apiservices/v1.

  /registry/apiregistration.k8s.io/apiservices/v1.apps

  /registry/apiregistration.k8s.io/apiservices/v1.authentication.k8s.io
  ...後略...

空行が余計ですので、省きましょう。

  # etcdctl get / --prefix --keys-only | grep /
  /registry/apiregistration.k8s.io/apiservices/v1.
  /registry/apiregistration.k8s.io/apiservices/v1.apps
  /registry/apiregistration.k8s.io/apiservices/v1.authentication.k8s.io
  /registry/apiregistration.k8s.io/apiservices/v1.authorization.k8s.io
  /registry/apiregistration.k8s.io/apiservices/v1.autoscaling
  /registry/apiregistration.k8s.io/apiservices/v1.batch
  /registry/apiregistration.k8s.io/apiservices/v1.networking.k8s.io
  ...後略...

試しに、/registry/namespaces/default というキーの値を見てみると…

  # etcdctl get /registry/namespaces/default --hex --print-value-only
  \x6b\x38\x73\x00\x0a\x0f\x0a\x02\x76\x31\x12\x09\x4e\x61\x6d\x65\
  \x73\x70\x61\x63\x65\x12\x5f\x0a\x45\x0a\x07\x64\x65\x66\x61\x75\
  ...後略...

中身がバイナリの、よくわからないものが得られました。

よくはわかりませんが、 このような形でetcdが使われているということがおぼろげにわかりました。

さらっと確認し終えて Minikube が不要になったら、 コンテナやゲストOSから exit して、Minikube を終了しておきましょう。

  # exit
  $ exit
  host$ minikube stop

今回の宿題

今回の宿題は、

  コンテナ間を行き来するパケットを眺めてみましょう。

です。

どのようにカプセル化されたり取り出されたりしているのか、 パケットを実際に見て確認してみたいと思います。

ちなみに、vxlanが使用するUDPポートは、以下に書かれています。

flannel/backends.md at master・coreos/flannel・github
https://github.com/coreos/flannel/blob/master/Documentation/backends.md

あとがき

最近、スパムメールが減って、メールの確認が楽になったと思っていたのですが、 ちょっと嫌な感じの怪しいメールを受け取ってしまいました。

まず、題名に、普段あまり使っていないメールアドレスと、かつて使っていた (今も使っているかもしれない)パスワードが書かれていました。

本文には、(わたしが)アダルトビデオを見たときにマルウェアを仕込み、 パスワードなどを知ったこと、 ビデオを見ている際の画面とカメラの映像を記録していること、などが書かれています。

で、ばらされたくなければビットコインで1000ドル払え、とあります。
(なお、ビットコインのアドレスが書かれていましたが、 いまのところは まだ取引に使われていないようです。)

とはいえ、普段使っているPCのOSはUbuntuですし、アダルトビデオをみることは、 まったく…とは言いませんが、ほっとんどありません。

また、そのマルウェアでは、MessengerやFacebook、RDP、 Outlookなども対象と書かれていました。こちらのOSがUbuntuにも関わらず RDPやOutlookと書いていること、ご指摘のパスワードは普段使用していないことから、 不特定多数に出しているように思われます。

おそらく、どこかでユーザ登録した情報が漏洩しているのではないか… と思われるのですが、 そのメールアドレスとパスワードの組み合わせで登録したサイトで怪しいところは… 結構あって特定が難しいです。(-ε-;;;
(サービスを終了しているサイトもそれなりにありますし…。)

普段 Windows を使わないため、 セキュリティに関してちょっと油断していたかもしれません。とりあえず、 怪しいサイトへのアクセスは控えて、普段使っていないPCもしくはブラウザで、 各所のパスワードを変更しようと思います。

まったくやましいことがないと言いきれないため、対策範囲を狭めたり、 無視したりできないのが悲しいところです。今後は、 もう少し清く正しく生きていきたいと思います。

 

今回も、ここまで読んでいただき、誠にありがとうございました。
次回は、9月2日の発行を目指します。(依然として歯切れが悪いですがー)

 

「いますぐ実践! Linux システム管理」はこちらです。
メルマガの解除、バックナンバーなども、以下からどうぞ。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

その他、作者に関するページは、概ね以下にございます。
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)
http://twitter.com/kuriking/ (twitter)
http://facebook.com/kuriking3 (facebook)
https://jp.pinterest.com/kuriking/ (pinterest) https://www.instagram.com/kuri_king_/ (instagram)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本