helen's blog

ずっとおもしろいことしてたいな。

Mackerelアンバサダーになりました

わーい😁

f:id:heleeen:20190213002523p:plain

この見栄えのためにOrganizationのアイコンを設定しました😅

Mackerelアンバサダーとは

mackerel.io

要するに

  • 個人では試しづらかったMackerelの有償機能も無料で使わせていただける🎉
  • ノベルティがもらえる🙌
  • ブログなどでアウトプットしてMackerelにより貢献できる💪
  • ※ アンバサダーになったことの公開はOKだそうです

Win-Winですね😊

わたしのMackerel Organization

いつの日かハムスターと温度と湿度を見守ってくれていたラズパイは
今は別の用途で使われていますが、Mackerelエージェントは動かしています

Mackerelアンバサダーになった今日、突然アラートがあがりました

f:id:heleeen:20190213011426p:plain

以前からいつの間にかsshできなくなっていることがあったので
今度は何が起こったんだ..と思いながら再起動しちゃいました
繋げれるやつ持ってないんです😢

github.com

これと同じ現象だったので同じ対応を入れて数日様子を見ることにしました

Mackerelエージェントをアップデートする

最初にMackerelエージェントを入れてからそのままであり
いい機会なのでエージェントをアップデートします

現状

$ /usr/local/bin/mackerel-agent version
mackerel-agent version 0.47.3 (rev 4334e86) [linux arm go1.9.2]

Raspberry Pi なので Releases · mackerelio/mackerel-agent · GitHub から
mackerel-agent_linux_arm.tar.gz をwgetして再配置して再起動

f:id:heleeen:20190213023105p:plain

バイナリなので簡単ですね

0.47.3 から 0.59.0 へ

アップデートを放置していた間にいろいろ変わりました

Memory使用率の算出方法が変わる

mackerel.io

f:id:heleeen:20190213024404p:plain

グラフはこんな感じになりました

インストールに際して

貧弱なディスクしかないので一応気にしてる

圧縮ファイル

1.3Mほど大きくなっています

2.4M Nov 28  2017 0_47_mackerel-agent_linux_arm.tar.gz
3.7M Jan 10 07:00 0_59_mackerel-agent_linux_arm.tar.gz

エージェント

エージェント自体のファイルサイズ0.5M増、
あといろんなファイルが増えていました

# 0.59.0
total 6.8M
19K Jan 10 06:52 CHANGELOG.md
10K Jan 10 06:52 LICENSE
13K Jan 10 06:52 LICENSE.rtf
2.2K Jan 10 06:52 README.md
6.8M Jan 10 06:57 mackerel-agent
3.6K Jan 10 06:55 mackerel-agent.conf

# 0.47.3
total 6.3M
2.2K Nov 28  2017 README.md
6.2M Nov 28  2017 mackerel-agent
3.6K Nov 28  2017 mackerel-agent.conf

ラズパイの掃除しないとDiskが危ういなぁ...

アンバサダープログラム使い倒すぞ٩(๑`^´๑)۶

AWSのAuto ScalingでTarget Tracking Scaling PolicyのALBRequestCountPerTargetを本番試用した

自分が初めて使った Amazon EC2 Auto Scaling についてのログと感想を残します

Auto Scaling

Auto ScalingはEC2やRDSなどのサービスに対し、正常なインスタンス数を保ったり
スケジュール・負荷に合わせてスケーリングしてくれるAWSの便利サービスです
もちろん手動でのインスタンス増減も対応していて、
ヘルスチェック、Warming time、Instance Drawningを利用して安全に増減させてくれます

Amazon EC2 Auto Scaling の動的スケーリングとして現在3つのスケーリングポリシーがあります

Target tracking scaling: 
  特定のメトリクスのターゲット値に基づいて、グループの現在の容量を増減させます。
  これはサーモスタットで家の温度を管理する方法と似ています(温度を選択すれば、後はサーモスタットがすべてを実行する)。
Step scaling:
  アラーム超過のサイズに応じて変動する一連のスケーリング調整値(ステップ調整値)に基づいて、
  グループの現在の容量を増減させます。
Simple scaling: 
  1つのスケーリング調整値に基づいて、グループの現在の容量を増減させます。 
https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/as-scale-based-on-demand.html

そして続けてこんな記載があります

If you are scaling based on a utilization metric 
that increases or decreases proportionally to the number of instances in an Auto Scaling group,
we recommend that you use target tracking scaling policies. 
Otherwise, we recommend that you use step scaling policies.

インスタンスの使用率に基づく場合はTarget Tracking Policy、
そうでなければStep Scaling Policyがおすすめだそうです

今回はインスタンスのキャパシティがわかっていたため Target Tracking Policyを選択してみたくなりました

Simple Scale, Step Scale

Target Tracking Policyは2017/7/12にリリースされました
Introducing Target Tracking Scaling Policies for Auto Scaling

それまでに追加されていたポリシーはSimple Scale Policyとして扱われます

スケーリングアクティビティまたはヘルスチェック交換の最中でも、
アラームを継続的に評価し、グループをロックしない

という点から、Simple Scale PolicyよりStep Scaling, Target Tracking Scalingが推奨されています

Step Scaling, Target Tracking Scalingは

Auto Scaling グループ内のインスタンス数に比例して増減するメトリクスに基づいてスケールする場合は、
代わりにターゲット追跡スケーリングポリシーを使用することをお勧めします

という基準があります
ちなみにAWSコンソールからEC2 Auto Scale Policyを追加するとデフォルトはTarget Tracking Policyになっています
日本語では"ターゲット追跡スケーリングポリシー"などと表記されます

docs.aws.amazon.com

Target Tracking Scale

Target Tracking Scaleの特徴は下記です

ターゲットの追跡スケーリングポリシーは、メトリクスをターゲット値近くに維持することに加えて、
負荷パターンの変動によるメトリクスの変動に合わせて調整し、
Auto Scaling グループの容量の急速な変動を最小化します。
https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/as-scaling-target-tracking.html

このドキュメントでの "事前定義されたメトリクス" は現在4つあります

ASGAverageCPUUtilization: 
  average CPU utilization of the Auto Scaling group
ASGAverageNetworkIn: 
  average number of bytes received on all network interfaces by the Auto Scaling group
ASGAverageNetworkOut: 
  average number of bytes sent out on all network interfaces by the Auto Scaling group
ALBRequestCountPerTarget: 
  number of requests completed per target in an Application Load Balancer target group
https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/APIReference/API_PredefinedMetricSpecification.html

事前定義されたメトリクスを使用する場合、CloudWatchAlarmの作成も自動で行われます
Alarmを定義しなくて済むのはすごく便利でした

今回はRequest数に基づいてスケールさせたかったので(本当は私のTryしてみたい思いが99.8%です)ALBRequestCountPerTargetを選択したのですが自分の理想通りになかなかいきませんでした

Terraformする

Target Tracking PolicyをTerraformするとこうなります
なお、今回のTarget Value閾値)は4200と仮定します

resource "aws_autoscaling_policy" "scale_out_policy" {
  name                      = "scale-out-policy"
  autoscaling_group_name    = "<Auto Scaling Group Name>"
  policy_type               = "TargetTrackingScaling"
  estimated_instance_warmup = "180"

  target_tracking_configuration {
    predefined_metric_specification {
      predefined_metric_type = "ALBRequestCountPerTarget"
      resource_label = "<ALB ARN Suffix>/<TargetGroup ARN Suffix>"
    }
    target_value = 4200 # ↓で使う仮のTargetValue
    disable_scale_in = true # チキンなのでScale inはDisable
  }
}

Simple Policy, Step Policyでは閾値を超えたときにインスタンスのを追加するなどの指定がありますが、
Target Tracking Policyでは閾値を超えたときの挙動をALBとターゲットグループ以外指定しません
Target Tracking Policyの場合、閾値を上回らないようにAuto Scaleしてくれるので指定する必要がありません

ALBRequestCountPerTarget

ポリシーを作成すると、CloudWatchAlarmが作成されます
ALBRequestCountPerTarget(Scaling Policy作成画面ではApplication Load Balancer Request Count Per Targetと表記されます)を選択したときに作成されるAlarmの一部をピックアップします

Title Description Value
State Details アラームの状態(OK, ALARM or INSUFFICIENT_DATA)とその理由 OK. 理由: 3データポイントがthresholdを超えていませんでした
Threshold ALARMになる条件 RequestCountPerTargetが3分間の3データポイントでthresholdを超えたとき
Statistic メトリクスの統計方法 Sum
Period データポイントの粒度 1 minute

Thresholdは

RequestCountPerTarget > 4200 for 3 datapoints within 3 minutes

などが表示されていて、
詳細モニタリングが有効になっていて1分に1回メトリクスが投稿されているとすると、
3分間に3つのデータポイントがあり、TargetValue(4200)を超えると閾値をオーバーしたとみなします

RequestCountPerTargetはCloudWatch MetricsのApplicationELB > TargetGroup内にあり、

RequestCountPerTarget
Statistics: The only valid statistic is Sum. Note that this represents the average not the sum.
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html

StatisticのSumはSumという名の平均値になります

Alarm状態を眺める

ALARM状態になったときのState Reasonの例は下記です

Threshold Crossed: 3 datapoints [5200, 5300, 4250] were greater than the threshold (4200.0).

この[5200, 5300, 4250]はRequestCountPerTargetの値で、
ApplicationELBのRequestCountをTargetGroup内で稼働しているインスタンス数で割った数におよそ一致するはずです
[5200, 5300, 4250]のように3datapointsがthe threshold(4200)を超えるとALARMとなります

Target Valueを考える

(1秒間に捌けるリクエスト数) * 60(秒) * 係数(という気持ち)

チューニングすれば1秒間に捌けるリクエスト数が増えるし、
係数はモニタリングしながら調整かなぁとやりながら思いました
同様に総リクエスト数を考慮してAuto ScaleのMax, Minを指定します

仮に秒間100Requestsをギリギリ捌けるインスタンスをTargetとした場合、
100 * 60(1minute) = 6000のRequestCountPerTargetはギリギリ捌けることになり、
インスタンスが2台ある場合、1分間に12000リクエストをさばくことができると想定されます
そこでScale PolicyのTarget Valueを4200くらい(6000さばけるけど余裕見て0.7掛け)にしておくと、
1分間に8400Request(4200*2)を超えた状態が3分続くとスケールアウトされる計算になります

この計算が全然わからなくて苦労しました
クッ...Sumに惑わされた...

おまけ

実際にインスタンスを増減させる際にはこんな挙動も起こります

ターゲット値と実際のメトリクスデータポイント間にギャップが発生する場合があります。
これは、追加または削除するインスタンス数を決定するときに、
その数を切り上げまたは切り捨てて常に控えめに動作するためです。
これにより、不十分な数のインスタンスを追加したり、インスタンスを過剰に削除したりすることがなくなります。
https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/as-scaling-target-tracking.html

結局、リクエストが瞬間的に増加するが継続時間は2,3分程度で、
スケールアウトする頃にはリクエストが落ち着いているというよくある状態になってしまいました

感想

構築時は1秒間に捌けるリクエスト数がわかっていてCPU使用率が高騰していてもさばけるときに
ALBRequestCountPerTargetを使うといいのかなぁと考えていたのですが
リクエストがバーストしてもインスタンスの各使用率が高騰せず済んでしまうほどチューニングが優秀過ぎて
余裕でアクセスをさばくインスタンス郡が増設されるだけになってしまいました😂
一度バーストするとしばらく継続される状況でAuto Scale Inもさせるなら良さそうでした

瞬間にバーストしてすぐ落ち着くサービスは難しいなぁ🤔
台数用意して耐えきるほうが現実的なのかなぁ🤔

mackerel-plugin-varnishのグラフを読めるようになりたい

Varnishをやっていて悩むことがよくあって
mackerel-plugin-varnishを使ってみようと思い立ってすぐ入れたけど
あまりリファレンスややってみた記事がヒットしなかったのでざっくりまとめました😁

キャッシュサーバやVarnishを自分で構築するのも監視するのも初めてなので
お手柔らかにお願いします...🙏

今回使った環境

  • CentOS7.5
  • mackerel-agent 0.56.0
  • Varnish 6.0
  • プロキシ先は同ホストに立てたPHPのWebアプリケーション
    • 今回はあまり重要ではないので詳細は割愛します

Varnishとは?

Varnish HTTP Cache — Varnish HTTP Cache

キャッシュするHTTPリバースプロキシ(直訳)で
6.0.0は2018年3月にリリースされたものです
語り始めると長いのでVarnishについては気が向いたら別で書きます

mackerel-plugin-varnish

github.com

VarnishにはvarnishstatというVarnishのパフォーマンスを見れる便利ツールがあり
mackerel-plugin-varnishはvarnishstatの出力した結果をMackerelへ投稿してくれます
varnishstatはVarnishをインストールすると一緒にインストールされます

varnishstatを実行するとこのような画面になります
引数に-1で今の瞬間のデータ表示、つけない場合は最新のものが常に表示されます
※長いので関係する箇所だけ抜粋しました

# varnishstat -1
MAIN.client_req           103036        10.97 Good client requests received
MAIN.backend_req              10         0.00 Backend requests made
MAIN.backend_conn              4         0.00 Backend conn. success
MAIN.backend_unhealthy         0         0.00 Backend conn. not attempted
MAIN.backend_busy              0         0.00 Backend conn. too many
MAIN.backend_fail              0         0.00 Backend conn. failures
MAIN.backend_reuse             6         0.00 Backend conn. reuses
MAIN.backend_recycle          10         0.00 Backend conn. recycles
MAIN.backend_retry             0         0.00 Backend conn. retry
MAIN.client_req           103036        10.97 Good client requests received
MAIN.cache_hit            103025        10.97 Cache hits
MAIN.cache_hit_grace           0         0.00 Cache grace hits
MAIN.cache_hitpass             0         0.00 Cache hits for pass.
MAIN.cache_hitmiss             0         0.00 Cache hits for miss.
MAIN.n_object                  3          .   object structs made
MAIN.n_objectcore            153          .   objectcore structs made
MAIN.n_objecthead            153          .   objecthead structs made
MAIN.n_expired                 7          .   Number of expired objects
SMA.s0.c_req                  30         0.00 Allocator requests
SMA.s0.c_fail                  0         0.00 Allocator failures
SMA.s0.c_bytes            368834        39.28 Bytes allocated
SMA.s0.c_freed            196382        20.92 Bytes freed
SMA.s0.g_alloc                15          .   Allocations outstanding
SMA.s0.g_bytes            172452          .   Bytes outstanding
SMA.s0.g_space         268263004          .   Bytes available

これを目で追うのが大変だけど、
Mackerelを使うとデータを蓄積して
見やすく表示して監視してくれるのが本当にありがたいです

プラグインを実行すると上記の出力がこうなります

# mackerel-plugin-varnish
[SMA.s0.g_alloc s0 g_alloc]
varnish.requests.requests	13020.000000	1534141634
varnish.requests.cache_hits	13020.000000	1534141634
varnish.backend.backend_req	0.000000	1534141634
varnish.backend.backend_conn	0.000000	1534141634
varnish.backend.backend_fail	0.000000	1534141634
varnish.objects.n_object	1.000000	1534141634
varnish.objects.n_objectcore	151.000000	1534141634
varnish.objects.n_objecthead	151.000000	1534141634
varnish.objects_expire.n_expired	0.000000	1534141634
varnish.busy_requests.busy_sleep	0.000000	1534141634
varnish.busy_requests.busy_wakeup	0.000000	1534141634
varnish.sma.g_alloc.s0.g_alloc	5.000000	1534141634
varnish.sma.memory.s0.allocated	57231.000000	1534141634
varnish.sma.memory.s0.available	268378225.000000	1534141634

カスタムメトリック

pluginを読み込ませるだけで7個のグラフが生成されます
対象のvarnishstatのフィールド名と合わせて表にしました

Varnish Backend

BackendはVarnishがリクエストを受け取ったあとの転送先です
今回用意した環境で言うと「PHPのWebアプリケーション」がそれにあたります

Metrics 説明 varnishstatのフィールド名
Conn fail Backendとのコネクション失敗数 MAIN.backend_fail
Conn Success Backendとのコネクション成功数 MAIN.backend_conn
Requests Backendへのリクエスト数 MAIN.backend_req

このRequestsはアクセス数ではなくBackendへのアクセス数なので
サイトのアクセス数とは一致しません
クライアントのリクエスト数はMAIN.client_reqです
MAIN.backend_failが上がってくるようだと、
BackendのアプリケーションかVarnishとアプリケーションの疎通に問題がある可能性が高いです

f:id:heleeen:20180813190455p:plain

これはキャッシュをオフにしたときのグラフです
キャッシュをオフにするとRequestが増え、Conn Successがすこしだけ増えます

Varnish Busy Requests
Metrics 説明 varnishstatのフィールド名
wakeup sleep listから取り除かれたリクエスト数 MAIN.busy_wakeup
sleep Busy状態のオブジェクトがあるのでsleepさせたリクエスト数 MAIN.busy_sleep

Varnishでは、リクエストがバックエンドに到達するとbusyオブジェクトが生成されます
この処理中に新しいリクエストが同じページに来たときに
Varnishがbusyオブジェクトがある(同じページへのアクセスが処理中)と判断すると
そのリクエストを一度Waitingリストへ登録します
そして、最初のリクエストが処理されたときに
Waitingリストに登録されていたリクエストたちにもレスポンスします

つまり、Varnishは同じページへのリクエストがあるときは
最初の1つをBackendへ流し他は待機させておいて、
最初のリクエストが処理された後に、そのキャッシュを待機させていたリクエストに返すという動作をしています

その監視をしているのがBusyとWakeupです

Varnish Client Requests
Metrics 説明 varnishstatのフィールド名
Hit キャッシュヒット数 MAIN.cache_hit
Requests リクエスト数 結果 MAIN.cache_hit ?

HitがRequestsに近ければ
Varnishがキャッシュをユーザに返してくれていて
そのリクエストは裏のアプリケーションに到達していないことになります

f:id:heleeen:20180814152356p:plain

キャッシュをオフにした状態のグラフです
オフにしてもデフォルトのキャッシュである程度Hitはします
Hit率が低い場合、キャッシュ条件を見直すと高速化する可能性があります

f:id:heleeen:20180813160621p:plain

キャッシュ設定してこれくらいでした
特定ページへのabなのでHitsとRequestsが一致しちゃっておもしろくないですが
Hit率が高いので調子は良さそうですね😅
cache_hitpass(キャッシュしないキャッシュ)も見れるとうれしいけど
Mackerelのメトリックとしてないってことは見なくていいのかな?🤔

Varnish Objects
Metrics 説明 varnishstatのフィールド名
objecthead キャッシュ内でハッシュが異なるものの数 MAIN.n_objecthead
objectcore キャッシュ内のメタデータの数 MAIN.n_objectcore
object キャッシュしたオブジェクト数 MAIN.n_object

hashはここではキャッシュのKeyです
Varnishで"オブジェクト"というといろんな種類があり
その中のobjectcore, objectheadがモニタリングされています

f:id:heleeen:20180814153621p:plain

キャッシュをオフにした状態でのグラフです

Varnish Objects Expire
Metrics 説明 varnishstatのフィールド名
expire 期限切れしたオブジェクト数 MAIN.n_expired

f:id:heleeen:20180813190140p:plain

これはキャッシュをオフにして30秒おきにアクセスしたグラフです
キャッシュを作ってもすぐexpiredになっていまうので上がって下がってを繰り返します

MAIN.n_lru_nuked(新しいキャッシュのために強制削除されたキャッシュ)が
カスタムメトリックにはないのはなぜなのかが気になった
n_lru_nukedが起こるということはキャッシュ用メモリサイズがあっていないのかも?っていう監視は不要なものなのかな

Varnish SMA Allocations

SMAとはキャッシュのために確保したメモリ(MAlloc Stevedore counters)のことです

SMFやSMUなどがあるのですが
ここではMackerelが収集対象としているSMAのみにフォーカスします
端的にいうとキャッシュを何に保存しているか?です

Varnishの起動時に指定します
今回は検証なので

VARNISH_STORAGE="malloc,256M"

RAM使用の256MiBとしました
256MのMはmebibytesです
またオブジェクトごとに1 KiBを内部構造用に使用します

指定はMiBなのにvarnishstat -1したときはByteで表示される罠があります😂

Metrics 説明 varnishstatのフィールド名
num 未処理のストレージ割り当て数 SMA.s0.g_alloc

f:id:heleeen:20180814164411p:plain

キャッシュをオンにしてアクセスして放置すると
このように増えたり減ったりしてました

Varnish SMA Memory
Metrics 説明 varnishstatのフィールド名
Available ストレージの残りバイト数 SMA.s0.g_space
Allocated 割り当て済みバイト数 SMA.s0.g_bytes

使われれば使われるほどAvailableが減っていって
Allocatedが上限になります

グラフはByte表示されます

f:id:heleeen:20180814164656p:plain

キャッシュ対象が少ないため全然使われてないですが
きっとこれからAvailableとAllocatedが戦いを繰り広げてくれるでしょう!

参考サイト

Varnishと戦い始めての感想は、6系は特に実践記事は少なく、
数年前の記事にVarnishは対応していないので・・って書いてあっても
実はもうその機能実装されてたりするので、ひたすらリファレンス見てTryErrorしてます
その合間もMackerelが見ててくれるのはモチベーションにもなりますね💪

はてなブログ映えのために何度かabコマンド叩いてるけど怒られないといいなぁ😅

vagrant vbguestはもう打ちたくなかったんだ

Versions

vagrantでsynced_folderしたくてvbguestを入れたはずなのに
reloadするとまた

# 抜粋
Failed to mount folders in Linux guest. This is usually because
the "vboxsf" file system is not available. Please verify that
the guest additions are properly installed in the guest and
can work properly. The command attempted was:

mount -t vboxsf -o uid=`id -u vagrant`,gid=`getent group vagrant | cut -d: -f3` vagrant /vagrant
mount -t vboxsf -o uid=`id -u vagrant`,gid=`id -g vagrant` vagrant /vagrant

The error output from the last command was:

mount: unknown filesystem type 'vboxsf'

が出るを何度も繰り返して発狂しそうでした

起動ログを見るとguest additionsが入ってないって言われている

# 抜粋
==> boxName: Machine booted and ready!
==> boxName: Checking for guest additions in VM...
    boxName: No guest additions were detected on the base box for this VM! Guest
    boxName: additions are required for forwarded ports, shared folders, host only
    boxName: networking, and more. If SSH fails on this machine, please install
    boxName: the guest additions and repackage the box to continue.
    boxName:
    boxName: This is not an error message; everything may continue to work properly,
    boxName: in which case you may ignore this message.

どうやらcentos/7はデフォルトでGuestAdditionsが入っていないようだ
なんでだろう🤔

普段vagrantコマンドでしか操作しなくてGUIに戸惑ったのでログ残します

GuestAdditionインストール

対象のisoイメージを探す

Index of http://download.virtualbox.org/virtualbox から自分のバージョンのものを探して
GuestAddition.isoをダウンロード

対象のBoxにボリュームを追加してドライブとして選択

f:id:heleeen:20180713183810p:plain

GUIからVMを起動して諸々のバージョンを合わせる

合ってないとのちのち悲しい気持ちになります

$ sudo su -
# yum update -y
# reboot

## login

# yum install gcc kernel-devel kernel-header

# reboot

## ここで↓2つのバージョンが一致することを確認しておく
# uname -r
# yum list installed | grep kernel

あとはイメージをマウントしてrunして
できたイメージをpackageしてaddしちゃえばもう困ることはないね!

Appendix

but compiler support broken.
arch/x86/Makef i le:96: stack-protector enabled but compiler support broken arch/x86/Makef ile : 166: *** CONFIG RETPOLINE=y, but not supported by the compiler . Compiler update recommended.. Stop. make: *** [vboxguest] 
Error 2 Creating user for the Guest Additions, Creating udev rule for the Guest Additions kernel module.

gccをインストールする

unable to find the sources of Linux kernel.
Creating user for the Guest Additions. 
Creating udev rule for the Guest Additions kernel module. 
tmp/vbox.O/Makefile.include .header:97: *** 
Error: unable to find the sources of your current Linux kernel. 
Specify KERN_DIR=<directory> and run Make again.

kernelのライブラリとカーネルのバージョンが一致してなかった

めも

ちなみにvbguestしたときのログでも若干怪しいことは言われてました

$ vagrant vbguest

...

Complete!
Copy iso file /Applications/VirtualBox.app/Contents/MacOS/VBoxGuestAdditions.iso into the box /tmp/VBoxGuestAdditions.iso
Mounting Virtualbox Guest Additions ISO to: /mnt
mount: /dev/loop0 is write-protected, mounting read-only
Installing Virtualbox Guest Additions 4.3.40 - guest version is unknown
Verifying archive integrity... All good.
Uncompressing VirtualBox 4.3.40 Guest Additions for Linux............
VirtualBox Guest Additions installer
Copying additional installer modules ...
Installing additional modules ...
Removing existing VirtualBox non-DKMS kernel modules[  OK  ]
Building the VirtualBox Guest Additions kernel modules

調べるととりあえずvbguestすればいいって出てくるけど根本解決にはならないみたい

nwdiagでただサンプルを動かすまでが長かった

nwdiagというMarkdownでネットワーク図を書ける素敵ツールを見つけたので
さくっと書こうと思ったらなぜか半日かかった苦しみを残します
だからpipは苦手なんだ...

nwdiag

Markdownを書けばネットーワーク図、パケットヘッダなどGenerateできる優れもの

http://blockdiag.com/en/nwdiag/index.html

インストール方法
pip install nwdiag

http://blockdiag.com/en/nwdiag/introduction.html

実行
nwdiag simple.diag

http://blockdiag.com/en/nwdiag/nwdiag-examples.html

みたいなのがさくっとできる

Symbol not found: _clock_gettime
nwdiag simple.diag
Traceback (most recent call last):
  File "/usr/local/bin/nwdiag", line 7, in <module>
    from nwdiag.command import main
  File "/usr/local/lib/python2.7/site-packages/nwdiag/command.py", line 18, in <module>
    import nwdiag.builder
  File "/usr/local/lib/python2.7/site-packages/nwdiag/builder.py", line 18, in <module>
    from nwdiag.elements import (Diagram, DiagramNode, DiagramEdge,
  File "/usr/local/lib/python2.7/site-packages/nwdiag/elements.py", line 17, in <module>
    import blockdiag.elements
  File "/usr/local/lib/python2.7/site-packages/blockdiag/elements.py", line 19, in <module>
    from blockdiag.utils import images, unquote, urlutil, uuid, XY
  File "/usr/local/lib/python2.7/site-packages/blockdiag/utils/images.py", line 20, in <module>
    from PIL import Image
  File "/usr/local/lib/python2.7/site-packages/PIL/Image.py", line 60, in <module>
    from . import _imaging as core
ImportError: dlopen(/usr/local/lib/python2.7/site-packages/PIL/_imaging.so, 2): Symbol not found: _clock_gettime
  Referenced from: /usr/local/lib/python2.7/site-packages/PIL/.dylibs/liblzma.5.dylib (which was built for Mac OS X 10.12)
  Expected in: /usr/lib/libSystem.B.dylib
 in /usr/local/lib/python2.7/site-packages/PIL/.dylibs/liblzma.5.dylib

pipでインストールするときって
うまくいくと大喜びするくらいうまくいかない..

エラーメッセージがおっしゃる通り、使ってるMacは10.11.6で
10.12で入る何かが足りないらしい

github.com

同じようなissueは見つかるけど
OSアップデートするのは嫌だし
brew update や brew upgrade, prune試しても変わらなかった

ライブラリのバージョンを下げる

github.com

$ pip list
Package         Version
--------------- --------
Pillow          5.1.0 # アウツ

$ pip install 'pillow!=5.1.0'

$ pip list
Package         Version
--------------- --------
Pillow          5.0.0 # 下げた

$ nwdiag simple.diag # Success!

pipでハマると普通に半日吹き飛んでつらいなぁ😥