読者です 読者をやめる 読者になる 読者になる

Macのターミナルの起動が遅すぎてつらかったので対処した

個人で使用しているMacも会社で使用しているMacもターミナルの起動に10秒くらいかかって、わりとストレスがたまる感じだったので対処方法を調べました。

標準のTerminalもiTermも同様に重たく、 zsh が起動に時間が掛かっているのを疑ったのですが、 oh-my-zsh などは使っていませんし、プロファイルを取ってみても一瞬で起動しているようでした。

起動時のターミナルのタイトルバーをよく見ると、 zsh の呼び出し元になっている login コマンドで時間が掛かっていました。

対処方法

あたりをつけて調べた所、すぐに同様の事象で困ってる人の記事を見つけました。

totem3.hatenablog.jp

asl というのは Apple System Log の略らしく、このログから最終ログイン日時を検索したりしているようなのですが、これが重いと読み込みに時間が掛かるようです。 この記事を参考に、

$ sudo rm -rf /var/log/asl/*.asl
$ sudo rm -rf /private/var/log/asl/*.asl

したあとに再起動すると、一瞬で起動するようになりました。

めでたしめでたし👏

Ansibleで牛が表示されるのをやめたい

きっかけ

久しぶりにAnsibleでサーバを構築していたのですが、なんかいつもと表示が違う…

f:id:kuro_m88:20160415203825p:plain

動物っぽいような…牛ですね。 そして、なんとなくこの出力、見覚えがあります。 cowsay コマンドだ!

$ cowsay "hello world"

_____________
< hello world >
 -------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

調べてみた

誰かのいたずらかと思ってplaybookを見てみたのですが、playbookを見ても特に異常はなく、なんなんだと悩んで調べてみると…

support.ansible.com

If cowsay is installed, Ansible takes it upon itself to make your day happier when running playbooks. If you decide that you would like to work in a professional cow-free environment, you can either uninstall cowsay, or set an environment variable

cowsay コマンドがインストールされている場合は幸せになれる出力をしてくれるらしいです()

プロフェッショナルな cow-free な環境な場合は cowsay をアンインストールするか、 export ANSIBLE_NOCOWS=1 して環境変数cowsay を使わない事を宣言する必要があるようです。

対処

なんで手元の環境に cowsay コマンドが入っていたのかは分かりませんが、僕はプロフェッショナルな cow-free な環境なので

f:id:kuro_m88:20160415204057p:plain

ANSIBLE_NOCOWS=1 という環境変数を設定して実行することでいつもの出力に戻すことができました。

LXDで作ったコンテナをcloud-initで初期化してみる

LXD2.0がもうすぐリリースされますね!

LXDでコンテナが簡単に作れるようになったらコンテナ生成時にsshログインするための公開鍵を設定したり、任意のスクリプトを走らせたりしたくなりますよね。

調べてみたところ、LXDはcloud-initに対応していたようなので、試してみます。

実験環境

Ubuntu 15.10とLXD 2.0.0.rc8 です。

ubuntu@dev01:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=15.10
DISTRIB_CODENAME=wily
DISTRIB_DESCRIPTION="Ubuntu 15.10"

ubuntu@dev01:~$ lxd --version
2.0.0.rc8

cloud-initの設定ファイルを作る

ドキュメントを見ながらcloud-initの設定ファイルを作ってみました。

Cloud config examples — Cloud-Init 0.7.7 documentation

#cloud-config

hostname: cloud-container

users:
  - name: user01
    shell: /bin/bash
    ssh-authorized-keys:
      - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDRqP+9+b3ZHoXYyXo+V3g1K8AR+dBgYPUVdTieTtnLh2FPfKp9lGe9sLQcTDiWCiBvU9iUvx3m42gvzHeYht/SPjzske4ushSwS7wbz761dMyM9HL3jjmH8iIj/gyrARkBOUQj5e9TVvPtX8xfJOegHcxR/MssQsTlWcDdBsR0rV+DJAglMM11Rei5H46ZebYX8HCfg5BrYZlQtXJkHFNaMW59XlwL3Pk7i48MkHvApo8+2MHWU7gPSoo4guFl4G9M5BrRTpxiZbpnPkjxW+YX8u7UVZLR1OE0KgZeNUJK84dXq1cOAMWfM/6n5gPlGSUhGCoOGTinv3OCLGExvbrV ubuntu@dev01
    sudo: ALL=(ALL) NOPASSWD:ALL
  - user02
  - user03

runcmd:
  - [sh, -c, "echo 'hello world!' > /tmp/hello.txt"]

ホームディレクトリに cloud-init-config.yml という名前で保存しました。

設定項目としては、上から順に

  • ホスト名を cloud-container に設定する
  • ユーザ user01, user02, user03 を作成する
    • user01 は、シェルを bash に設定し、sshログイン用の 公開鍵 を設定、sudo 権限も付与する
  • /tmp/hello.txt を作成し、hello world! と書き込む

コンテナを作成する

作るだけで、まだ起動はしません。

ubuntu@dev01:~$ lxc init ubuntu:14.04 container
Creating container

ubuntu@dev01:~$ lxc list
+-----------+---------+-------------------+------+------------+-----------+
|   NAME    |  STATE  |       IPV4        | IPV6 |    TYPE    | SNAPSHOTS |
+-----------+---------+-------------------+------+------------+-----------+
| container | STOPPED |                   |      | PERSISTENT | 0         |
+-----------+---------+-------------------+------+------------+-----------+

コンテナにcloud-initの設定をする

作成した設定ファイルの内容を流し込みます。

ubuntu@dev01:~$ ls
cloud-init-config.yml

ubuntu@dev01:~$ lxc config set container user.user-data - < cloud-init-config.yml

コンテナを起動する

ubuntu@dev01:~$ lxc start container

ubuntu@dev01:~$ lxc list
+-----------+---------+-------------------+------+------------+-----------+
|   NAME    |  STATE  |       IPV4        | IPV6 |    TYPE    | SNAPSHOTS |
+-----------+---------+-------------------+------+------------+-----------+
| container | RUNNING | 10.0.3.251 (eth0) |      | PERSISTENT | 0         |
+-----------+---------+-------------------+------+------------+-----------+

確認

user01 を作成し、公開鍵を設定したので、sshができるようになっているはずです。

ubuntu@dev01:~$ lxc list
+-----------+---------+-------------------+------+------------+-----------+
|   NAME    |  STATE  |       IPV4        | IPV6 |    TYPE    | SNAPSHOTS |
+-----------+---------+-------------------+------+------------+-----------+
| container | RUNNING | 10.0.3.251 (eth0) |      | PERSISTENT | 0         |
+-----------+---------+-------------------+------+------------+-----------+

ubuntu@dev01:~$ ssh user01@10.0.3.251

The authenticity of host '10.0.3.251 (10.0.3.251)' can't be established.
ECDSA key fingerprint is SHA256:hrredNI9D1T5QX12WC6McqxBGwl4+b1neq7g7KP5wCE.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.0.3.251' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 14.04.4 LTS (GNU/Linux 4.2.0-34-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

  System information as of Tue Apr  5 11:52:16 UTC 2016

  System load:    0.0       Memory usage: 0%   Users logged in: 0
  Usage of /home: unknown   Swap usage:   0%

  => There were exceptions while processing one or more plugins. See
     /var/log/landscape/sysinfo.log for more information.

  Graph this data and manage this system at:
    https://landscape.canonical.com/

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

0 packages can be updated.
0 updates are security updates.



The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

user01@cloud-container:~$
user01@cloud-container:~$ sudo su
sudo: unable to resolve host cloud-container
root@cloud-container:/home/user01#

ログインでき、sudoも成功しました。ホスト名も設定できていますね。

ユーザ一 user02, user03 も作成できたか確認します。

user01@cloud-container:~$ cat /etc/passwd | grep user
user03:x:1000:1000::/home/user03:
user02:x:1001:1001::/home/user02:
user01:x:1002:1002::/home/user01:/bin/bash

最後に、hello.txt が作成できたか確認します。

user01@cloud-container:~$ cat /tmp/hello.txt
hello world!

完璧ですね!

まとめ

LXDが標準でcloud-initに対応してくれているおかげでとっても簡単にコンテナの初期化ができました!

LXD最高!

参考

askubuntu.com

AWSのAvailability Zoneとロケーションの関係

シンプルなんだけど面白かったのでまとめました。

AZ(アベイラビリティーゾーン)とは

ご存知の方も多いと思いますが、AWS(EC2)のロケーションは、リージョンとアベイラビリティーゾーンという概念があります。

リージョンというのは、 東京バージニアサンパウロ などです。最近だと ソウル も追加されました。

アベイラビリティーゾーンというのは、同一リージョン内の独立したロケーションの単位(データセンターを想定するとだいたいあってる)で、 アベイラビリティーゾーン間の距離は「近距離」(数キロ〜数十キロらしい)にあるそうです。

参考: http://www.atmarkit.co.jp/ait/articles/1411/20/news106.html

AWSのドキュメントの図を引用するとこんな感じ。 f:id:kuro_m88:20160113123004p:plain http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-regions-availability-zones.html

素朴な疑問

たとえば、東京リージョンであれば、 ap-northeast-1a , ap-northeast-1b , ap-northeast-1c 3つのAZがあります。
ここで疑問に思うのが「(冗長化構成を取らない場合) とりあえず ap-northeast-1aインスタンス立てそうだし、 ap-northeast-1a ばっかり選択されてAZごとのリソースの使用状況が偏るんじゃないか」ってことです。
僕だったらとりあえず1台立てるなら 1a を使ってますし、同じことを考えてる人が何百万人と居ると大変です。

シンプルな解決方法

ドキュメントをよく読んでみました。 http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-regions-availability-zones.html

リソースがリージョンの複数アベイラビリティーゾーンに分散されるようにするため、アベイラビリティーゾーンは各アカウントの識別子に個別にマップされます。たとえば、あるアカウントのアベイラビリティーゾーンは別のアカウントのus-east-1aアベイラビリティーゾーンと同じ場所にはない可能性がありますus-east-1a。

実はAZの識別子と実際のAZのロケーションの対応関係はAWSアカウントによって違う可能性があるようです。

この事を知っていると、以下のような疑問にも納得が行きます。

Tokyoリージョンにて、Regional data transferが計上されない現象について

異なるAZの間(ap-northeast-1aとap-northeast-1b)でプライベートIPアドレスを用いたTCP通信を行い、5GBのデータを送信しましたが、送信側アカウントにも受信側アカウントにもregional data transferの課金が生じません。これは正常な動作となりますでしょうか? https://forums.aws.amazon.com/thread.jspa?messageID=273850

単純ですが一番効果的な解決方法ですね!

松屋アドベントカレンダー 15日目

この記事は、松屋 Advent Calendar 2015 15日目の記事です。

@kuro_m88 です。
4月から社会人デビューをして、シブヤーで一人前のエンジニアになるために修行しています。

シブヤーはIT系企業が多く、道玄坂界隈には特に密集しているという噂も。
忙しい時や、集中し過ぎた時、気づけばお昼を食べる時間が少ない!みたいな事もあるかもしれない。
そんな時のあなたの食卓が松屋渋谷道玄坂上店である。忙しくなくても行くけど。

ということで、松屋で特に普通に昼食をとるとどれくらいの時間がかかるのか気になったので調べてみました。
特に急いだりとかせず、いつもどおりな感じで。

f:id:kuro_m88:20151215193959p:plain

数字は各フェーズごとに掛かった時間です。

00:00 入店

自動ドアの目の前に食券機がある。

00:27 食券機に並ぶ

前に1人食券を買っている人が居た。
食券機は2台あるけど、Suicaで決済できるのは1台しかないので並ぶ。 オートチャージ最強。

00:15 食券を買う

この日はプレミアム牛丼のミニとサラダでした。
メニューが決まってて、操作に慣れてたら15秒くらいで食券が買える。

00:10 着席

回転率が良いので、今まで着席まで待たされた事はない。
着席と同時に食券を店員さんに受け取ってもらう。
忘れずに「ねぎだく、つゆ抜きでお願いします」と言う。

01:47 待ち

店員さんがキビキビ動いているのを眺めつつ、すごいなーと関心していたらあっという間だった。

09:25 昼食

スマホいじりながら食べている人もそこそこいるけれど、自分は器用じゃないので食べるのに集中する。
なんとなく仕事の事を考えてる事が多いかも。
プレミアム牛丼のねぎだくつゆ抜きにカルビソースを少しだけかけて食べるのが最強。

00:15 退店

ごちそうさまでした。

合計: 12:19

思ったより早かった。20分あれば行って食べて帰ってこれそう。

以上、松屋渋谷道玄坂上店での日常でした。

busybusyboxというDocker imageを作った

busybusybox

簡単な負荷試験や、CPUの使用率制限の実験とかするのに、CPUを使いまくってくれるコンテナが欲しいなと思って作ってみました。

中では、opensslのベンチマークを無限ループさせてるだけです。

github.com

名前ですが、 busybox だと紛らわしいし、 busybox に失礼かなと思い、busybusybox にしてみました(笑)

使い方

Dockerhubに上げたので、

$ docker run -it kurochan/busybusybox

とするだけで、CPUを全部使い切ろうとしてくれるはず。

そういえば

stressコマンドの方が良かったかな…

Dockerでダイナミックルーティング!

前回、Dockerでルータが動くようにできたので、今度はルータを使ってダイナミックルーティングをしようと思います。

kurochan-note.hatenablog.jp

使うもの

  • ubuntu 15.04
  • vyOSのコンテナ
  • open vSwitch

作るネットワーク

以下の図のようなルータ3台のシンプルなネットワーク構成にしました。

RouterAとRouterB、RouterBとRouterCは直接接続されていて、RouterAとRouterCは直接接続されていないので、RouterBにルーティングをしてもらわないと通信ができません。 OSPFで経路情報を交換して、RouterAとRouterC間の疎通が取れるようにする事をゴールにしてみようと思います。 f:id:kuro_m88:20151011095239p:plain

それぞれのRouterがコンテナで動いていて、コンテナ間の接続にopen vSwitchを使います。 イメージとしてはこんな感じです。 f:id:kuro_m88:20151011095316p:plain

環境構築

Ubuntu15.04とdockerとopen vSwitchがあればOKです。

$ sudo aptitude install docker.io openvswitch-common openvswitch-switch
$ sudo service docker start

ovs-docker

dockerのインターフェイスを簡単にopen vSwitchに接続ためのシェルスクリプトです。 今回インストールしたopenvswitch-commonには入っていなかったので、Githubリポジトリからダウンロードしてきます。

ovs/ovs-docker at master · openvswitch/ovs · GitHub

$ wget https://raw.githubusercontent.com/openvswitch/ovs/master/utilities/ovs-docker
$ chmod +x ovs-docker

ネットワークを作る

ルータを作る

ルータを3台用意します。

Ubuntuカーネルモジュールを使用するため、特権コンテナにして、 /lib/modulesをマウントしてあげます。 NICは後で追加するので、 --net=none で起動します。

$ sudo docker run -d --name RouterA --net=none --privileged -v /lib/modules:/lib/modules kurochan/vyos:1.1.6 /sbin/init
$ sudo docker run -d --name RouterB --net=none --privileged -v /lib/modules:/lib/modules kurochan/vyos:1.1.6 /sbin/init
$ sudo docker run -d --name RouterC --net=none --privileged -v /lib/modules:/lib/modules kurochan/vyos:1.1.6 /sbin/init

スイッチを作る

vSwitchを1つ作ります。

$ sudo ovs-vsctl add-br vswitch0

スイッチとルータを接続する

ovs-docker を使ってコンテナのNICの作成、IPアドレスサブネットマスクの設定、スイッチへの接続をします。

RouterBだけNICを2つ作成します。

$ sudo ./ovs-docker add-port vswitch0 eth0 RouterA --ipaddress=192.168.100.1/24
$ sudo ./ovs-docker add-port vswitch0 eth0 RouterB --ipaddress=192.168.100.2/24
$ sudo ./ovs-docker add-port vswitch0 eth1 RouterB --ipaddress=192.168.200.2/24
$ sudo ./ovs-docker add-port vswitch0 eth0 RouterC --ipaddress=192.168.200.1/24

ポートVLANを設定する

ルータの全ポートが同じスイッチに繋がっている状態なので、VLANを使ってネットワークを分割します。ポートとVLANの対応は以下の表のようになります。

Router port vlan
RouterA eth0 100
RouterB eth0 100
RouterB eth1 200
RouterC eth0 200
$ sudo ./ovs-docker set-vlan vswitch0 eth0 RouterA 100
$ sudo ./ovs-docker set-vlan vswitch0 eth0 RouterB 100
$ sudo ./ovs-docker set-vlan vswitch0 eth1 RouterB 200
$ sudo ./ovs-docker set-vlan vswitch0 eth0 RouterC 200

ここまでの確認

ここまでの疎通確認をしてみます。

まだルーティングの設定をしていないので、状態は以下の表のようになるはずです。

Router Router ping
RouterA RouterB
RouterB RouterC
RouterA RouterC

RouterAからRouterB

$ sudo docker exec -it RouterA ping -c 1 192.168.100.2
PING 192.168.100.2 (192.168.100.2) 56(84) bytes of data.
64 bytes from 192.168.100.2: icmp_req=1 ttl=64 time=0.309 ms

--- 192.168.100.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.309/0.309/0.309/0.000 ms

RouterBからRouterC

$ sudo docker exec -it RouterB ping -c 1 192.168.200.1
PING 192.168.200.1 (192.168.200.1) 56(84) bytes of data.
64 bytes from 192.168.200.1: icmp_req=1 ttl=64 time=0.998 ms

--- 192.168.200.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.998/0.998/0.998/0.000 ms

RouterAからRouterC

$ sudo docker exec -it RouterA ping -c 1 192.168.200.1
connect: Network is unreachable

ルータの設定をする

各ルータにOSPFの設定をして、経路情報を交換してルーティングできるようにします。

RouterA

$ sudo docker exec -it RouterA /bin/vbash
vbash-4.1# su - vyos
vyos@vyos:~$ configure
vyos@vyos# set interfaces loopback lo address 1.1.1.1/32
vyos@vyos# set protocols ospf area 0 network 192.168.0.0/16
vyos@vyos# set protocols ospf parameters router-id 1.1.1.1
vyos@vyos# commit
vyos@vyos# exit
vyos@vyos:~$ exit
vbash-4.1# exit

RouterB

$ sudo docker exec -it RouterB /bin/vbash
vbash-4.1# su - vyos
vyos@vyos:~$ configure
vyos@vyos# set interfaces loopback lo address 2.2.2.2/32
vyos@vyos# set protocols ospf area 0 network 192.168.0.0/16
vyos@vyos# set protocols ospf parameters router-id 2.2.2.2
vyos@vyos# commit
vyos@vyos# exit
vyos@vyos:~$ exit
vbash-4.1# exit

RouterC

$ sudo docker exec -it RouterC /bin/vbash
vbash-4.1# su - vyos
vyos@vyos:~$ configure
vyos@vyos# set interfaces loopback lo address 3.3.3.3/32
vyos@vyos# set protocols ospf area 0 network 192.168.0.0/16
vyos@vyos# set protocols ospf parameters router-id 3.3.3.3
vyos@vyos# commit
vyos@vyos# exit
vyos@vyos:~$ exit
vbash-4.1# exit

再び確認

再び疎通確認をしてみます。

OSPFできちんと経路交換をしてルーティングされていれば、状態は以下の表のようになるはずです。

Router Router ping
RouterA RouterB
RouterB RouterC
RouterA RouterC

RouterAからRouterB

$ sudo docker exec -it RouterA ping -c 1 192.168.100.2
PING 192.168.100.2 (192.168.100.2) 56(84) bytes of data.
64 bytes from 192.168.100.2: icmp_req=1 ttl=64 time=0.215 ms

--- 192.168.100.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.215/0.215/0.215/0.000 ms

RouterBからRouterC

$ sudo docker exec -it RouterB ping -c 1 192.168.200.1
PING 192.168.200.1 (192.168.200.1) 56(84) bytes of data.
64 bytes from 192.168.200.1: icmp_req=1 ttl=64 time=0.238 ms

--- 192.168.200.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.238/0.238/0.238/0.000 ms

RouterAからRouterC

$ sudo docker exec -it RouterA ping -c 1 192.168.200.1
PING 192.168.200.1 (192.168.200.1) 56(84) bytes of data.
64 bytes from 192.168.200.1: icmp_req=1 ttl=63 time=0.280 ms

--- 192.168.200.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.280/0.280/0.280/0.000 ms

RouterAからRouterCの通信ができるようになりましたね!

せっかくなのでルーティングテーブルも確認

RouterAのルーティングテーブルを確認してみます。

$ sudo docker exec -it RouterA /bin/vbash
vbash-4.1# su - vyos
vyos@vyos:~$ show ip route
WARNING: terminal is not fully functional
Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF,
       I - ISIS, B - BGP, > - selected route, * - FIB route

C>* 1.1.1.1/32 is directly connected, lo
C>* 127.0.0.0/8 is directly connected, lo
O   192.168.100.0/24 [110/10] is directly connected, eth0, 00:10:38
C>* 192.168.100.0/24 is directly connected, eth0
O>* 192.168.200.0/24 [110/20] via 192.168.100.2, eth0, 00:05:33

さいごに

ルータをコンテナで動かして、実際にルーティングするところまでやってみました。

コンテナで動いているため、ノートPC1台あればルータを10台くらい立てたりできると思うので、ネットワークの勉強をするための環境にはよいかもしれません。

今更ですが、ポートVLANを使わなくてもvSwitchをもう一つ作った方が分かりやすかった気がしてきました(笑)