tech」カテゴリーアーカイブ

CentOS7でDockerでコンテナから外部通信できなくてハマった

仕事でCentOS7でDockerを使うことがあってハマった。具体的にはコンテナから外部通信ができない。

$ # docker run --rm  --network bridge  -it centos:latest  /bin/bash
[root@15b96c6afbda /]# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
...

なんでだろうと思って、手癖でtcpdumpを打つと。

$ tcpdump -i docker0 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:25:09.820768 IP 192.168.0.2 > 8.8.8.8: ICMP echo request, id 16, seq 1, length 64
17:25:09.821863 ARP, Request who-has 192.168.0.2 tell 192.168.0.1, length 28
17:25:09.821874 ARP, Reply 192.168.0.2 is-at 02:42:c0:a8:00:02, length 28
17:25:09.821877 IP 8.8.8.8 > 192.168.0.2: ICMP echo reply, id 16, seq 1, length 64

経験からプロミスキャストモードのときだけパケットが転送されることを瞬時に理解したので、まず1ツイート

ifconfig docker0 promiscas とか打てば、それはそれで通信できるんだけど、本来はこんなことやらなくてもいいはずなので、色々探していると、大体大事なことはsyslogに書いてあるんですね。

dockerd: time="2020-07-30T17:10:53.075020306+09:00" level=warning msg="Running modprobe bridge br_netfilter failed with message: modprobe: WARNING: Module br_netfilter not found.\ninsmod /lib/modules/3.10.0-327.el7.x86_64/kernel/net/llc/llc.ko \ninsmod /lib/modules/3.10.0-327.el7.x86_64/kernel/net/802/stp.ko \ninsmod /lib/modules/3.10.0-327.el7.x86_64/kernel/net/bridge/bridge.ko \n, error: exit status 1" 

br_netfilterについては こちら のページが詳しいです。さて、このbr_netfilterなんでないのだと思って、調べると。

$ lsmod |grep br_netfilter
$

ないでおじゃる。

このあたり の情報を見る限り古いkernelには含まれていなさそう。

ELRepo から新しめのカーネルを持ってきて、万事解決。

今回の教訓としては CentOSでDocker使うのやめましょう いかなるときも思い込みであれこれやらないようにしましょうでした。

カテゴリー: tech

クラウドネイティブなLinuxユーザー管理ミドルウェアのSTNSのクライアントソフトウェアlibnss-stns-v2 2.6.0をリリースしました(マジタイトル長くてウケる

先日のブログ で紹介したcache-stnsdとの連携に加えて、libcrypto.soの競合で起こるSEGV への対応として、OpenSSLとCurlをstaticリンクしました。

cache-stnsdとの連携

先日ブログを書いたところ、 @fujiwara さんから即フィードバックをもらえたので、cache-stnsdはインストールは必須としたものの、利用するかどうかは運用者で決定できるようにしました。

具体的には/etc/stns/client/stns.confuse_cached = true と書いた場合のみ、cachedを利用するようにします。またこれはv3のリリースでデフォルト値となります。

また先日Twitterにも書きましたが、開発者としても運用者としても使ってくださる皆様の要望に合理性の範囲内でなるべく答えたいと思っているので、TwitterなりGithub issueなりでどんどんご意見頂けると嬉しいです。

関連ライブラリのStaticリンクについて

ペパボで利用しているNginxとChefで問題がおきていたので、CurlとOpenSSLをsoにStaticリンクするようにしました。具体的にはNginxでOpenSSLをStaticリンクしている場合や、ChefがEnbeded Rubyを利用する関係でOpenSSL系のメソッドで競合が発生し、SEGVする事象がありました。

それらに対する根本的な対応として、Staticリンクすることで、より多くの環境で安定動作する方向に意思決定しました。

テスト実行に加えて、Ubuntu 16/18、CentOS7については手元で動かして動作検証を取ってありますが、その他のOSについては基本的にはビルドが通れば動くものではあると思っているので万が一何かあれば雑にご連絡ください。

カテゴリー: tech

libnss-stns-v2とohaiを組み合わせたときにSEGVする

いずれ調べるかって思ってたやつちゃんと調べた。

エラーメッセージ的にはこんな感じ。

g /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/ohai-14.4.2/lib/ohai/plugins/passwd.rb:19: [BUG] Segmentation fault at 0x00007f521bce3e20
g ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
g 
g -- Control frame information -----------------------------------------------
g c:0026 p:---- s:0135 e:000134 CFUNC  :passwd
g c:0025 p:0073 s:0131 e:000130 BLOCK  /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/ohai-14.4.2/lib/ohai/plugins/passwd.rb:19 [FINISH]
g c:0024 p:---- s:0128 e:000127 CFUNC  :instance_eval
g c:0023 p:0058 s:0124 e:000123 METHOD /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/ohai-14.4.2/lib/ohai/dsl/plugin/versionvii.rb:128
g c:0022 p:0058 s:0118 e:000117 METHOD /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/ohai-14.4.2/lib/ohai/dsl/plugin.rb:104
g c:0021 p:0004 s:0114 e:000113 METHOD /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/ohai-14.4.2/lib/ohai/dsl/plugin.rb:187
g c:0020 p:0174 s:0109 e:000108 METHOD /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/ohai-14.4.2/lib/ohai/runner.rb:87
g c:0019 p:0070 s:0101 e:000100 BLOCK  /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/ohai-14.4.2/lib/ohai/runner.rb:48
g c:0018 p:0039 s:0097 e:000096 METHOD /opt/chef/embedded/lib/ruby/2.5.0/benchmark.rb:293
g c:0017 p:0011 s:0088 e:000087 METHOD /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/ohai-14.4.2/lib/ohai/runner.rb:41
g c:0016 p:0009 s:0082 e:000081 BLOCK  /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/ohai-14.4.2/lib/ohai/system.rb:93 [FINISH]
g c:0015 p:---- s:0078 e:000077 CFUNC  :each
g c:0014 p:0019 s:0074 e:000073 METHOD /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/ohai-14.4.2/lib/ohai/system.rb:92
g c:0013 p:0021 s:0065 e:000064 METHOD /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/ohai-14.4.2/lib/ohai/system.rb:83
g c:0012 p:0048 s:0060 e:000059 METHOD /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/chef-14.4.56/lib/chef/client.rb:608
g c:0011 p:0204 s:0054 e:000053 METHOD /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/chef-14.4.56/lib/chef/client.rb:260
g c:0010 p:0014 s:0042 E:000950 METHOD /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/chef-14.4.56/lib/chef/application.rb:303
g c:0009 p:0091 s:0038 e:000037 BLOCK  /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/chef-14.4.56/lib/chef/application.rb:279
g c:0008 p:0007 s:0034 e:000033 METHOD /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/chef-14.4.56/lib/chef/local_mode.rb:44
g c:0007 p:0040 s:0030 e:000029 METHOD /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/chef-14.4.56/lib/chef/application.rb:261
g c:0006 p:0099 s:0025 e:000024 METHOD /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/chef-14.4.56/lib/chef/application/client.rb:440
g c:0005 p:0019 s:0020 e:000019 METHOD /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/chef-14.4.56/lib/chef/application.rb:66
g c:0004 p:0063 s:0016 e:000015 TOP    /opt/chef/embedded/lib/ruby/gems/2.5.0/gems/chef-14.4.56/bin/chef-client:25 [FINISH]
g c:0003 p:---- s:0013 e:000012 CFUNC  :load
g c:0002 p:0585 s:0008 E:0006f0 EVAL   /usr/bin/chef-client:75 [FINISH]
g c:0001 p:0000 s:0003 E:000d60 (none) [FINISH]

ワークアラウンドとしては、chef打つ前にssh打って、getent passwd/group とか実行してキャッシュを作っておいて、stnsにhttpリクエストさせなければ普通に動く。

本題としては、libcrypto.soがembededなohaiとシステムのものを利用するstnsで異なることから、どちらのsoのファンクションを利用するか衝突しているようだった。

7f521b591000-7f521b82c000 r-xp 00000000 fc:01 2967                       /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1
7f521b82c000-7f521ba2b000 ---p 0029b000 fc:01 2967                       /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1
7f521ba2b000-7f521ba57000 r--p 0029a000 fc:01 2967                       /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1
7f521ba57000-7f521ba59000 rw-p 002c6000 fc:01 2967                       /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1
7f5220b97000-7f5220da7000 r-xp 00000000 fc:01 537824                     /opt/chef/embedded/lib/libcrypto.so.1.0.0
7f5220da7000-7f5220fa7000 ---p 00210000 fc:01 537824                     /opt/chef/embedded/lib/libcrypto.so.1.0.0
7f5220fa7000-7f5220fc2000 r--p 00210000 fc:01 537824                     /opt/chef/embedded/lib/libcrypto.so.1.0.0
7f5220fc2000-7f5220fce000 rw-p 0022b000 fc:01 537824                     /opt/chef/embedded/lib/libcrypto.so.1.0.0

基本的にnssモジュールはプロセスにリンクされるので、プロセスから名前解決のメソッドが呼ばれると、その先でstnsはcurlを打つので、そこでopensslもリンクされて、ぶつかるみたいな事象に見える。

対応としてはどうすっかなぁ。opensslをstaticリンクするか、はたまた何かしらの仕組みを入れてchefとか特定のプロセスのときはhttpを利用した名前解決しないようにするか。。。ちょい考える。

カテゴリー: tech

LDAPに変わるLinuxユーザー管理ソフトウェアのSTNSにキャッシュプロセスを追加した

僕が個人で開発を続けているSTNSのクライアントのマイナーバージョンアップをしました。

STNSについてはこちらが詳しいです。

今回の変更点としては、クライアントサイドにキャッシュプロセスをおきました。

これによって解決される課題は下記です。

  1. systemdによってlogin処理時にNetwork通信は原則許可されていないため、設定変更を行う必要があったがそれが不要になる
  2. libnss-stns-v2においてはファイルキャッシュを採用していたので、従業員がキャッシュファイルを書き換えると権限以上のアクセス権を得ようと思えば得られた

実装

cache-stnsdについてはlibnss-stnsとunix socketで通信させる実装にしました。すべての外部とのhttp通信やキャッシュ処理をcache-stnsdに移譲したのでCで実装されたlibnss-stnsの実装がかなり薄くなっています。

今後libnss-stns-v2をインストールする際はDependsにcache-stnsdが入っているので、普通に意識せずに利用できると思います。

インストール

debian系の例ですが下記で導入できます。

$ curl -fsSL https://repo.stns.jp/scripts/apt-repo.sh | sh
$ apt install libnss-stns-v2 cache-stnsd
$ service cache-stnsd start 

まだSTNSを触ったことがない方は、以前僕がSTNS as a Service を作っているので、こちらで試してみるのも楽しいかもしれません。

現状、手元の環境でしばらくエージングしてからリリースするつもりなので、今週中くらいにはyum/aptリポジトリに入っていくと思います。

なにか問題などあればissueなど起票頂けると嬉しいです。

あと余談なのですがclient、serverともに対応OSを増やして、debian8/9とCentOS8にも対応しました。

追記

リリースに際し、運用上の懸念などがあればこちらにコメントを下さい!

カテゴリー: tech

Apache KafkaのトピックをTailするIsakaをリリースした

動機

ペパボではKubernetsの環境やプライベートクラウド環境を中心にすべてのログをApache Kafkaを経由し、S3にバックアップしたり、Graylogで取り込んで検索可能にしています。また筆者がそれらの基盤の開発、メンテナンスをやっているのですが、なにか障害があったときにGraylogで検索をかけてそれをダウンロードして、grepしたりawkしたりするのは非常に手間に感じていました。またリアルタイムに tail -f のようなことをやりたくても、なかなかやりづらい状況がありました。

kinessisについては @fujiwara さんが似たようなものかつ、lambdaで検索までできるようなものを実装されているのですが、kafkaはちょっと探しきれなかったので実装しました。

使い方

インストールはhomebrewでインストールできるようにしています。

$ brew install pyama86/homebrew-isaka/isaka

今のところはzookeeperから諸々情報を取得するようにしています。kafka本体がzookeeperをやめると言う方針を出しているので、いずれ移行するかもしれません。zookeeperについてはだいたい同じものを見ると思うので環境変数で指定したほうが便利です。

$ ISAKA_ZOOKEEPERHOST=zookeeper.example.com ISAKA_CLUSTERNAME=example isaka topic-list

上記のようにclusterのtopic-listをシュッと取得することができます。

そいて取得したtopic listの中から、tailしたいtopicを選び、tailするだけです

$ ISAKA_ZOOKEEPERHOST=zookeeper.example.com ISAKA_CLUSTERNAME=example isaka --topic example tail
# ログがずらーーーっとでる

もちろん本家のように -f(follow) も対応しています。ペパボはhashicorpのVaultを利用して、kafkaの通信をTLSクライアント認証しているので、TLS周りも指定できるようにしました。詳細は tail コマンドのヘルプを見てもらえればわかると思います。また、zookeeperにアクセスしたくないケースを想定して、kafka brokerもISAKA_KAFKABROKERS とかで指定可能にしています。

名前の由来

kafkaの由来がフランツ・カフカが好きだったからという理由っぽかったので、最初は海辺のカフカにちなんでharukiとしようと思ったのですが、僕は一番好きなのは金城一紀だけど、最近作品をあまり書かなくなってしまったので、殺し屋シリーズが好きな伊坂幸太郎から取りました。

今後は使ってみて、需要に応じてあれこれ機能追加していきたいと思います。

カテゴリー: tech

ポモドーロテクニック開始とともにSlackのディスプレイネームを変えたい

モチベーション

割と僕は集中が失われているとき、SlackとTwitterをひたすら往復している。そういうときはちょっとやるぞ!!と思ってもなんかSlackで同僚困ってないかな?とかさっきコメントしたIssueにレスポンス来てるかなとか気になってみてしまう。正直僕のレスポンスが多少遅くてもどうでもいいんだけど、性格上なんかすぐ処理しないと気がすまないところもあったりしてついついみてしまう。

そう、Slack便利なんだけど、時に言い訳になりえてしまっていて、それを解決するためにしばらくポモドーロやるかと思い立ったのだけど、一方でポモドーロやるときは邪魔されたくないし、相手にも僕がその間、反応遅いことを伝えたいのだ。なので下記を実装した。

  1. cliでpomodoro.shを実行する
  2. SlackのディスプレイネームをN時N分までポモドーロ中と書き換える
  3. 25分たったらMacのNotificationで通知する

たったこれだけです。ちなみに似たようなことができるSlackアプリはあったりするのですがSlackアプリ正直どこまで信用できるかわからんみたいなところがあって、秘匿情報つまりまくりの会社のSlackに入れるのなかなか厳しいのですよね。なので、SlackAPIトークンさえあれば手元で動かせる仕組みを準備しました。あとメッセージとかちょっとカスタマイズしたいわーみたいなのあると思うのであえてBashで書いた。

在宅でちょい気が散っちゃうわーーーみたいなときにどうだろうか。

カテゴリー: tech

shawkを動かしてみた

このブログは僕が yuuk1/shawk を動かしてみただけのブログで、技術的に得られる情報は少ないです。もしなにかを求められてきた方は、こちらの動画でなにかを得てください。

ということでやっていきましょう。上記のソフトウェアは下記の資料の実装体です。

僕のモチベーションとしてはペパボのサーバ間ネットワークをゼロトラストネットワークを前提として再構築する際に、既存のサーバ間がどのように通信しているのかを洗い出すためであったり、不正な通信の検知をできないかというちょっともとの研究とはそれた使い方かもしれません。

自分で使うとなると、僕の背景からはeBPFを利用するにはカーネルのバージョンアップを途方も無い台数実行必要が生まれるため、そのときはカーネルモジュールでの実装やauditdでの実装をコントリビュートする必要があるだろうなと思ったりもした。

そして、どうせブログ書くからrpm/debパッケージ作ったり、docker-compose.ymlでも書くかと思ってたいのですが、それもすでにあったので動かすだけでした。

まずはバイナリ作っていきましょう。

% make all

ほいで、docker-composeあるんで使っていきます。

% docker-compose up
shawk_db_1 is up-to-date
Starting shawk_agent_1 ... error

ERROR: for shawk_agent_1  Cannot start service agent: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"/go/bin/shawk\": stat /go/bin/shawk: no such file or directory": unknown

ERROR: for agent  Cannot start service agent: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"/go/bin/shawk\": stat /go/bin/shawk: no such file or directory": unknown
ERROR: Encountered errors while bringing up the project.

あー、これdocker-composeは別途buildしろってことか。

% docker-compose build
db uses an image, skipping
Building agent
Step 1/3 : FROM golang:1.14.2
 ---> 2421885b04da
Step 2/3 : ENV PKG github.com/yuuki/shawk
 ---> Using cache
 ---> eff5000775c7
Step 3/3 : WORKDIR /go/src/$PKG
 ---> Using cache
 ---> 141e5f1d2e8f

Successfully built 141e5f1d2e8f
Successfully tagged shawk_agent:latest
% docker-compose up
shawk_db_1 is up-to-date
Starting shawk_agent_1 ... error

ERROR: for shawk_agent_1  Cannot start service agent: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"/go/bin/shawk\": stat /go/bin/shawk: no such file or directory": unknown

ERROR: for agent  Cannot start service agent: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"/go/bin/shawk\": stat /go/bin/shawk: no such file or directory": unknown
ERROR: Encountered errors while bringing up the project.

あかんな。これbuildしたバイナリもっていかないかん。

    volumes:
      - ./shawk:/go/bin/shawk

雑に追加。

% docker-compose up
shawk_db_1 is up-to-date
Recreating shawk_agent_1 ... done
Attaching to shawk_db_1, shawk_agent_1
db_1     | Error: Database is uninitialized and superuser password is not specified.
db_1     |        You must specify POSTGRES_PASSWORD to a non-empty value for the
db_1     |        superuser. For example, "-e POSTGRES_PASSWORD=password" on "docker run".
db_1     |
db_1     |        You may also use "POSTGRES_HOST_AUTH_METHOD=trust" to allow all
db_1     |        connections without a password. This is *not* recommended.
db_1     |
db_1     |        See PostgreSQL documentation about "trust":
db_1     |        https://www.postgresql.org/docs/current/auth-trust.html
d

fmfm.ということで、dbのパスワード追加したり、環境変数入れたり。

services:
  agent:
    build: .
    depends_on:
      - db
    entrypoint: /go/bin/shawk probe
    command: ["--dbhost", "db"]
    volumes:
      - ./shawk:/go/bin/shawk
    environment:
      - SHAWK_CMDB_URL=postgres://shawk:shawk@db:5432/shawk?sslmode=disable
  db:
    image: postgres:11.7
    ports:
      - 5432
    environment:
      - POSTGRES_USER=shawk
      - POSTGRES_DB=shawk
      - POSTGRES_PASSWORD=shawk
    restart: always
    user: postgres
    volumes:
      - ./postgres/init:/docker-entrypoint-initdb.d
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ttracer"]
      interval: 3s
      timeout: 3s
      retries: 5
      start_period: 3s

そうすると、

agent_1  | flag provided but not defined: -dbhost
agent_1  |
agent_1  | Usage: shawk probe [options]
agent_1  |
agent_1  | start agent for collecting flows and processes.
agent_1  |
agent_1  | Options:
agent_1  |   --env
agent_1  |   --once                    run once only if --mode='polling'
agent_1  | flag provided but not defined: -dbhost
shawk_agent_1 exited with code 11

引き数変わったっぽいのでdbhostを削ってと。。

(⎈ |nks-production:drone)[13:52:25] ~/src/github.com/yuuki/shawk (not-exist-task) <U>
% docker-compose up
Starting shawk_db_1 ... done
Starting shawk_agent_1 ... done
Attaching to shawk_db_1, shawk_agent_1
db_1     | 
db_1     | PostgreSQL Database directory appears to contain a database; Skipping initialization
db_1     | 
db_1     | 2020-05-09 04:52:37.680 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
db_1     | 2020-05-09 04:52:37.680 UTC [1] LOG:  listening on IPv6 address "::", port 5432
db_1     | 2020-05-09 04:52:37.689 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db_1     | 2020-05-09 04:52:37.726 UTC [12] LOG:  database system was interrupted; last known up at 2020-05-09 04:50:50 UTC
db_1     | 2020-05-09 04:52:38.001 UTC [12] LOG:  database system was not properly shut down; automatic recovery in progress
db_1     | 2020-05-09 04:52:38.005 UTC [12] LOG:  redo starts at 0/16517C0
db_1     | 2020-05-09 04:52:38.005 UTC [12] LOG:  invalid record length at 0/16517F8: wanted 24, got 0
db_1     | 2020-05-09 04:52:38.005 UTC [12] LOG:  redo done at 0/16517C0
db_1     | 2020-05-09 04:52:38.033 UTC [1] LOG:  database system is ready to accept connections
agent_1  | 2020/05/09 04:52:38 INFO <command> --> Connecting postgres ...
agent_1  | 2020/05/09 04:52:38 INFO <command> Connected postgres
db_1     | 2020-05-09 04:52:40.725 UTC [26] FATAL:  role "ttracer" does not exist
db_1     | 2020-05-09 04:52:43.874 UTC [33] FATAL:  role "ttracer" does not exist

[kkkdb_1     | 2020-05-09 04:52:47.025 UTC [41] FATAL:  role "ttracer" does not exist
db_1     | 2020-05-09 04:52:50.187 UTC [48] FATAL:  role "ttracer" does not exist
db_1     | 2020-05-09 04:52:53.331 UTC [55] FATAL:  role "ttracer" does not exist

ああ、上がったけどdbのヘルスチェックが前の名前のままだったから、shawkに変える。

ここまでで1PRなげた。

db_1     |
db_1     | PostgreSQL Database directory appears to contain a database; Skipping initialization
db_1     |
db_1     | 2020-05-09 04:53:37.694 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
db_1     | 2020-05-09 04:53:37.695 UTC [1] LOG:  listening on IPv6 address "::", port 5432
db_1     | 2020-05-09 04:53:37.699 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db_1     | 2020-05-09 04:53:37.746 UTC [12] LOG:  database system was shut down at 2020-05-09 04:53:32 UTC
db_1     | 2020-05-09 04:53:37.760 UTC [1] LOG:  database system is ready to accept connections
agent_1  | 2020/05/09 04:53:38 INFO <command> --> Connecting postgres ...
agent_1  | 2020/05/09 04:53:38 INFO <command> Connected postgres

db_1     | 2020-05-09 04:54:08.426 UTC [19] ERROR:  relation "processes" does not exist at character 16
db_1     | 2020-05-09 04:54:08.426 UTC [19] STATEMENT:
db_1     |                      INSERT INTO processes (ipv4, pgid, pname, updated)
db_1     |                      VALUES ($1, $2, $3, CURRENT_TIMESTAMP)
db_1     |                      ON CONFLICT (ipv4, pgid, pname)
db_1     |                      DO UPDATE SET updated=CURRENT_TIMESTAMP
db_1     |                      RETURNING process_id
db_1     |
agent_1  | 2020/05/09 04:54:08 ERROR <agent/polling> query error:
agent_1  |     github.com/yuuki/shawk/db.(*DB).InsertOrUpdateHostFlows
agent_1  |         /go/src/github.com/yuuki/shawk/db/db.go:189

なるほどなぁ、スキーマが初期化されてなさそう。

多分このあたりを実行しないといけない。

    command: bash -c "/go/bin/shawk create-scheme && /go/bin/shawk probe"

ソフトウェアの性質上、docker-composeはシュッと試したいときに使うものだから雑にbashでやっつけた。

ホイで起動したから雑に試すためにdocker exec bin/bashしてnetcatいれちゃうぞ〜。

$ apt install netcat
$ nc -l -p 11111     # listenしておいて
$ nc localhost 11111 # 接続する
$ /go/bin/shawk look

ここで、接続情報出るんかなぁと思ってたけどそんなことなかった。

なんでやねーーんと思ってたら、

agent_1  | 2020/05/09 05:14:57 ERROR <agent/polling> readlink /proc/58/fd/0:
agent_1  |     github.com/yuuki/shawk/probe/netlink/netutil.BuildUserEntries
agent_1  |         /go/src/github.com/yuuki/shawk/probe/netlink/netutil/netutil_linux.go:349
agent_1  |   - readlink /proc/58/fd/0: permission denied

なるほどね。でもこれコンテナのprocだから特権いらなさそうだけどな。fd0だから標準入力見ようとしてんのかな。

あらためて、lookをip指定で見たらみれた。

root@615b76a8b754:/go/src/github.com/yuuki/shawk# /go/bin/shawk look  --ipv4 172.19.0.3
172.19.0.3:55562 ('', pgid=0)
└<-- 172.19.0.3:many ('nc', pgid=505)
172.19.0.3 ('', pgid=0)
└--> 172.19.0.2:5432 ('', pgid=0)
172.19.0.3 ('nc', pgid=505)
└--> 172.19.0.3:55562 ('', pgid=0)
root@615b76a8b754:/go/src/github.com/yuuki/shawk# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 05:12 ?        00:00:05 /go/bin/shawk probe
root        22     0  0 05:14 pts/0    00:00:00 /bin/bash
root        47     0  0 05:14 pts/1    00:00:00 /bin/bash
root       381     0  0 05:16 pts/2    00:00:00 /bin/bash
root       505    47  0 05:24 pts/1    00:00:00 nc -l -p 11111
root       507   381  0 05:24 pts/2    00:00:00 nc 172.19.0.3 11111
root       560    22  0 05:26 pts/0    00:00:00 ps -ef
root@615b76a8b754:/go/src/github.com/yuuki/shawk#

これ11111ポートの情報はでないんかな。情報の出し方的には 172.19.0.3:many の場所が 172.19.0.3:11111 で良さそうだけどなんでやろか。

root@615b76a8b754:/go/src/github.com/yuuki/shawk# /go/bin/shawk look  --ipv4 172.19.0.3
172.19.0.3:55562 ('', pgid=0)
└<-- 172.19.0.3:many ('nc', pgid=505)
172.19.0.3 ('', pgid=0)
└--> 172.19.0.2:5432 ('', pgid=0)
172.19.0.3 ('nc', pgid=507)
└--> 172.19.0.3:11111 ('', pgid=0)
root@615b76a8b754:/go/src/github.com/yuuki/shawk# /go/bin/shawk look  --ipv4 172.19.0.3
172.19.0.3:55562 ('', pgid=0)
└<-- 172.19.0.3:many ('nc', pgid=505)
172.19.0.3 ('', pgid=0)
└--> 172.19.0.2:5432 ('', pgid=0)
172.19.0.3 ('nc', pgid=505)
└--> 172.19.0.3:55562 ('', pgid=0)

コネクション自体は繋ぎっぱなしで、何回か実行してると結果が変わるっぽい。これはなんかポーリング間隔によって得られる情報が違うからなんだろう。openしか取ってないとするとあり得るから、ストリーミングモードでやると多分ちゃんと取れそう。

最後に

一通り動かしてみて、PRもさっきマージされてました。yuukiくんも書いてるようにパフォーマンスとのトレードオフになる部分はあれど、僕が思ってる用途や他の用途にも使えそうだった。それこそグラフ図にするとホスト間の依存を図示することもできるだろうし、CMDBがあるから基本ソフトウェアとして使い手のアイディア次第で可能性のあるソフトウェアだと思った。

カテゴリー: tech

embulkでOutputPlugin ‘bigquery’ is not found. が発生した

先日開発したembulk-input-prometheusを利用して、BigQueryに情報をロードしようとしたところ下記のエラーが発生した。

org.embulk.config.ConfigException: OutputPlugin 'bigquery' is not found.
org.jruby.proxy.org.embulk.config.ConfigException$Proxy1: Unknown output plugin 'bigquery'. embulk/output/bigquery.rb is not installed. Run 'embulk gem search -rd embulk-output' command to find plugins.
        at org.embulk.plugin.PluginManager.buildPluginNotFoundException(PluginManager.java:75)
        at org.embulk.plugin.PluginManager.newPluginWithoutWrapper(PluginManager.java:61)
        at org.embulk.plugin.PluginManager.newPlugin(PluginManager.java:28)
        at org.embulk.spi.ExecSession.newPlugin(ExecSession.java:162)
        at org.embulk.spi.Exec.newPlugin(Exec.java:67)
        at org.embulk.exec.BulkLoader$ProcessPluginSet.<init>(BulkLoader.java:428)
 

該当箇所のjavaのソースコード読んでもcatchされててあまり深い情報がそのままでは取れなかったので、embulkのgem版を準備して実行したところ、

Gem::ConflictError: Unable to activate signet-0.11.0, because faraday-1.0.1 conflicts with faraday (~> 0.9)
              raise_if_conflicts at /root/.rbenv/versions/jruby-9.1.17.0/lib/ruby/stdlib/rubygems/specification.rb:2291
                        activate at /root/.rbenv/versions/jruby-9.1.17.0/lib/ruby/stdlib/rubygems/specification.rb:1411
  block in activate_dependencies at /root/.rbenv/versions/jruby-9.1.17.0/lib/ruby/stdlib/rubygems/specification.rb:1445
                            each at org/jruby/RubyArray.java:1735
           activate_dependencies at /root/.rbenv/versions/jruby-9.1.17.0/lib/ruby/stdlib/rubygems/specification.rb:1431
                        activate at /root/.rbenv/versions/jruby-9.1.17.0/lib/ruby/stdlib/rubygems/specification.rb:1413
                    try_activate at /root/.rbenv/versions/jruby-9.1.17.0/lib/ruby/stdlib/rubygems.rb:220
                         require at /root/.rbenv/versions/jruby-9.1.17.0/lib/ruby/stdlib/rubygems/core_ext/kernel_require.rb:126

faradayのバージョンが signetembulk-input-prometheus で利用している prometheus apiで衝突しているらしかったので、バージョン依存の記述を合わせて解決した。

これ、embulkでgemのconflictが起きたときにnot foundになるのちょい追えなくて不便だからどこかでおかわり案件かなぁ。

カテゴリー: tech

Prometheusの時系列データをBigQueryにエクスポートするembulk-input-pluginを書いた

現在ペパボでホスティング事業におけるデータ駆動での意思決定やあれこれができる基盤を構築しており、ホスティングにおいては顧客の契約情報だけではなく、やはりホスティングしているサーバのメトリクスとユーザーの動向の因果関係なども見たい。それらを分析するにあたって一箇所で統計を取ったりMLを適用したい。

そのためにあらゆる情報を今BigQueryに集めていて、Prometheusからサーバのリソース情報を連携するのにembulkを採用して、データをエクスポートするプラグインを書いた。

実装的にはPromQLを投げてその情報を整形して出しているだけなので難しいことはなにもしていない。

ペパボではAPIをmTLS運用をしているので認証はトークンだけじゃなくてTLS認証も対応している。

embulk plugin初めて書いたけど、インターフェースもシンプルだし、実質数時間でかけてしまった。またTwitterで雑にツイートしたら必要な情報をシュッといただけてマジ感謝。

この一連の仕事がアウトプットでたらもろもろまとめてどこかでお話できるといいな。

カテゴリー: tech

SlackからSecurityGroupをコントロールする関門海峡を書いた

こんにちは、皆さんはゼロトラストですか?残念ながら僕はまだゼロトラストではありません。

一方で、ゼロトラストになるまでの過程は技術的に楽しみながら豊かに過ごしたいと思っています。

先日書いたポストでは、踏み台サーバをGoogleoAuthを利用して堅牢にするという実装を紹介しました。一方でペパボは多くの商材がありその全てが一気にこれらの認証方式に移行できるかというとそうではありません。つまり、これまで通りFromIPでのデバイス認証が必要な箇所がおおくあります。

それらを解決するために同僚の @buty4629 が開発した kanmon を利用して、CLIからOpenStackのSGを開閉していました。

これはサーバ名を指定したり、操作するSGを設定ファイルとして持たせることで、自宅のIPから特定のサーバにアクセスできるようにするソフトウェアです。とても便利なのですがOpenStackのAPIを実行する必要があるので、非エンジニアによる操作が少々困難であったり、OpenStackのアカウントの整備諸々が必要でした。

それらを解決すために開発したのが関門海峡です。

これは先に紹介したkanmonをSlack経由で実行するものなのですが、下記のような動きになります。

まずはボットにアクセスを許可したいServerIDを指定して話しかけると、URLが払い出されます。

リンクをクリックするとGoogleoAuthの画面が出てきます。

認証が無事パスされると、このときブラウザからアクセスしたFromIPをSecurityGroupにPermitで登録します。

本来Slack経由で何かしらを利用してAPI叩くとき非常に監査がしづらくなるのですが、このようにoAuthと上手に組み合わせることで監査も可能にしつつ、認証、認可をコントロールすることができます。

今回開発にあたって、botの部分は社内で@hibomaがしっかりとした実装を残してくれていたのでそれを大いに参考にしました。

CLIで運用しているものをちょっと工夫して、平易にすることで利活用できる場面は今の時代とても多いと思うで、運用でのちょっとした気づきをChatOpsしてみてはどうでしょうか。

カテゴリー: tech