an odd fellow

仕事のメモ

locustのNUM_CLIENTSとHATCH_RATEについて

背景

GAEで作ったAPIサーバーを本番反映するに当たり必要なリクエスト数さばけるのかを確認する必要があった。先輩社員がlocustを使っていたので自分もlocustを使ったが、NUM_CLIENTSとHATCH_RATEの挙動が分からな過ぎた。NUM_CLIENTSとHATCH_RATEの関係が分からなかったし、locustを動かしているとAll locusts hatchedというログを残して計測した情報が一旦リセットされる理由もわからなかった。

結論

NUM_CLIENTSは同時接続数でサーバーでさばきたい接続数でOK。

問題はHATCH_RATEでこいつはクライアントを毎秒いくつ作るかを指定する。そしてNUM_CLIENTSで指定した数までクライアントを作ったら統計情報がリセットされる。

つまり最初クライアントは0で、HATCH_RATEで指定した数だけクライアントが作られていくことで、接続数が徐々に増えていく状況をシミュレート出来る。これによりオートスケールの設定が正しく動いているかが確認できる。また、本当に計測したいのは"オートスケールした後のピークリクエスト時に正しくリクエストを捌けるか"なので統計情報がリセットされる。

docker multi stage buildを試す

背景

reviewdogのDockerfileについて先輩社員にレビューもらうと、dockerのmulti stage build使うと幸せになれるよと教えてもらった。

レビューをもらったDockerfileは以下。pythonのdockerイメージにgoをインストールしてからgo getでreviewdogを入れている。これをまずgoのイメージでreviewdogをgo getしてきて、pythonのイメージにコピーしてくればいいんじゃないの?という意図で言ったのだと思う。

FROM python:3.6

USER root
ENV HOME /root

# install Golang
ARG GO_VERSION=1.8.3
RUN mkdir /tmp/go && \
    cd /tmp/go && \
    curl -O -sS -L https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz && \
    tar zxf go${GO_VERSION}.linux-amd64.tar.gz && \
    mkdir /usr/local/go && \
    mv go/* /usr/local/go && \
    rm -rf /tmp/go
ENV GOPATH=${HOME}/go
ENV PATH=${PATH}:/usr/local/go/bin:${GOPATH}/bin

# install reviewdog
RUN go get github.com/haya14busa/reviewdog/cmd/reviewdog
ENV GITHUB_API="https://ghe.misosiru.io/api/v3/"
ARG GITHUB_API_TOKEN=""
ENV REVIEWDOG_GITHUB_API_TOKEN=${GITHUB_API_TOKEN}

# リポジトリをコンテナにマウント
ARG WORK_DIR
WORKDIR ${WORK_DIR}
ENV APP_ROOT ${WORK_DIR}
COPY . ${APP_ROOT}

# install flake8
RUN pip install flake8 flake8-import-order flake8-double-quotes flake8-print pep8_naming

結論

やってみた。こんな感じになった。goはバイナリに出来るので、ランタイムが不要になるのでこういうことが出来るのか。素晴らしい。golangのインストールとかGOPATHの設定がなくなっていい感じになりました。

FROM golang:latest as reviewdog
# install reviewdog
RUN go get github.com/haya14busa/reviewdog/cmd/reviewdog

# ------------------------------------------------------

FROM python:3.6

USER root
ENV HOME /root

# reviewdogの設定
COPY --from=reviewdog /go/bin/reviewdog /usr/local/bin/reviewdog
ENV GITHUB_API="https://ghe.misosiru.io/api/v3/"
ARG GITHUB_API_TOKEN=""
ENV REVIEWDOG_GITHUB_API_TOKEN=${GITHUB_API_TOKEN}

# install flake8
RUN pip install flake8 flake8-import-order flake8-double-quotes flake8-print pep8_naming

# リポジトリをコンテナにマウント
ARG WORK_DIR
WORKDIR ${WORK_DIR}
ENV APP_ROOT ${WORK_DIR}
COPY . ${APP_ROOT}

# 自前のflake8 pluginのインストール
RUN pip install flake8_ml_batch/

IntelliJでproject painとかをショートカットでリサイズする

背景

IntelliJと書いたがPyCharmもRubyMineでも同様。

Command+1でプロジェクトペインが開けるが、windowをガチャガチャリサイズしたあとだとプロジェクトペインのサイズが以上にデカかったり小さかったりする。マウスでサイズ調整してたが、キーバインド割り当てられてないのか?と思って調べた。

f:id:roronya:20180115134012p:plain

結論

Resize (tool) windows with keyboard | IntelliJ IDEA Blog

リサイズしたいペインにフォーカスを当てて、Shift+Command+カーソルキーでリサイズできた。

docker runでローカルのgoファイルを実行する

背景

RealWorldHTTPを読み始めた。goでサンプルのHTTPサーバを立ててcurlで色々オプションを付けてリクエストを試しながら挙動を確認していくようだった。

それで、サンプルのHTTPサーバーを書いたんだけど、dockerで実行したくて以下のようにした。

$ docker run golang go run server.go

が、当然docker runに渡すコマンドはコンテナ内で実行されるので、server.goはコンテナ内には無いのでこうなる。

stat server.go: no such file or directory

結論

まずdockerコンテナのワーキングディレクトリを調べる。

$ docker run golang pwd
/go

/goらしい

そしたらローカルのカレントディレクトリを/goにボリュームしながらrunする。

$ docker run -v $PWD:/go golang go run server.go

docker run -vに渡すパスは絶対パスでないとならないので.(ドット)で渡すとdockerに怒られるため$PWDとするしかない。

あとはdocker-composeのvolumesを使う方法もあるけど、そのためだけにdocker-compose.ymlを書くのも馬鹿らしいので上でやることにした。

drone.ioでdocker run -vしてハマった

背景

drone.ioでreviewdogを使いたくてこんな感じで書いた。

Dockerfile.reviewdog

FROM python:3.6

USER root
ENV HOME /root
ARG WORK_DIR
WORKDIR ${WORK_DIR}
ENV APP_ROOT ${WORK_DIR}

# install Golang
ARG GO_VERSION=1.8.3
RUN mkdir /tmp/go && \
    cd /tmp/go && \
    curl -O -sS -L https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz && \
    tar zxf go${GO_VERSION}.linux-amd64.tar.gz && \
    mkdir /usr/local/go && \
    mv go/* /usr/local/go && \
    rm -rf /tmp/go
ENV GOPATH=$HOME/go
ENV PATH=$PATH:/usr/local/go/bin:$GOPATH/bin

# install reviewdog
RUN go get github.com/haya14busa/reviewdog/cmd/reviewdog
ENV GITHUB_API="https://ghe.misosiru.io/api/v3/"
ARG GITHUB_API_TOKEN=""
# build時にGITHUB_API_TOKENを渡す
ENV REVIEWDOG_GITHUB_API_TOKEN=$GITHUB_API_TOKEN

# install flake8
RUN pip install flake8 flake8-import-order flake8-double-quotes flake8-print pep8_naming

.drone.yml

pipeline:
  reviewdog:
    image: drone-build:latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WORK_DIR=/usr/src/app
    commands:
      - export GITHUB_API_TOKEN="GITHUB_API_TOKEN"
      - docker build --build-arg WORK_DIR=$WORK_DIR --build-arg GITHUB_API_TOKEN=$GITHUB_API_TOKEN -t reviewdog:latest -f Dockerfile.reviewdog .
      - docker run -v $PWD:$WORK_DIR reviewdog:latest /bin/bash -c "flake8 . | reviewdog -ci=droneio -f=pep8"
    when:
      event: pull_request

だが、reviewdogがreviewをしてくれない。(flake8が文句を言うコードはリポジトリに含まれている)

docker run -v $PWD:$WORK_DIR reviewdog:latest /bin/bash -c "flake8 ."

としてもflake8も何も出力してくれなかった。

仮設

docker run -v $PWD:$WORK_DIR reviewdog:latest ls

としたが、droneのログに出力されなかったので、docker run -vが何らかの理由で効いておらずマウントされていないのでないかと考えた。

結論

https://stackoverflow.com/questions/31381322/docker-in-docker-cannot-mount-volume

A Docker container in a Docker container uses the parent HOST's Docker daemon and hence, any volumes that are mounted in the "docker-in-docker" case is still referenced from the HOST, and not from the Container.

Dockerコンテナの中で動かすDockerデーモンはHOSTのものらしい。なので、docker run -v で渡すファイルパスはHOSTのものになってしまっているとのこと。

なので、droneではdocker in dockerは使わないで予めDockerfile.reviewdogの中でCOPYをしてから、prepareでdocker buildするようにしました。

Dockerfile.reviewdog

FROM python:3.6

USER root
ENV HOME /root
ARG WORK_DIR
WORKDIR ${WORK_DIR}
ENV APP_ROOT ${WORK_DIR}

# install Golang
ARG GO_VERSION=1.8.3
RUN mkdir /tmp/go && \
    cd /tmp/go && \
    curl -O -sS -L https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz && \
    tar zxf go${GO_VERSION}.linux-amd64.tar.gz && \
    mkdir /usr/local/go && \
    mv go/* /usr/local/go && \
    rm -rf /tmp/go
ENV GOPATH=$HOME/go
ENV PATH=$PATH:/usr/local/go/bin:$GOPATH/bin

# install reviewdog
RUN go get github.com/haya14busa/reviewdog/cmd/reviewdog
ENV GITHUB_API="https://ghe.misosiru.io/api/v3/"
ARG GITHUB_API_TOKEN=""
# build時にGITHUB_API_TOKENを渡す
ENV REVIEWDOG_GITHUB_API_TOKEN=$GITHUB_API_TOKEN

# install flake8
RUN pip install flake8 flake8-import-order flake8-double-quotes flake8-print pep8_naming

COPY . $APP_ROOT  # ここを追加

.drone.yml

pipeline:
  prepare:  #prepareでdocker buildをしてしまう
    image: drone-build:lates
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WORK_DIR=/usr/src/app
    commands:
      - export GITHUB_API_TOKEN="GITHUB_API_TOKEN"
      - docker build --build-arg WORK_DIR=$WORK_DIR --build-arg GITHUB_API_TOKEN=$GITHUB_API_TOKEN -t reviewdog:latest -f Dockerfile.reviewdog .

  reviewdog:
    image: reviewdog:latest
    environment:
      - flake8 . | reviewdog -ci=droneio -f=pep8
    when:
      event: pull_request

GCPでprojectをまたいだ権限の設定方法

背景

読み飛ばしてOK。自分用メモ。

AppEngineからBigTableを読み込みたかったが、BigTableはprdにあり、AppEngineはdev,stg,prdに立ち上げる予定で、devのAppEngineからprdのBigTableを読み込むとい うprojectを跨いでアクセスする必要があったが、やり方がわからず権限周りに詳しいひとに聞いたので、メモ。

結論

devのAppEngineのサービスアカウントproject-dev@appspot.gserviceaccount.comをprdのIAMから追加しBigTable読み込みの権限を付ける。

サービスアカウントについて

https://cloud.google.com/iam/docs/service-accounts?hl=ja

サービスアカウントについて理解している必要があったので読んだ。

サービスアカウントが良くわからなかったんだけど、公式のマニュアルを読んで理解した。

サービス アカウントは、個々のエンドユーザーではなく、アプリケーションや仮想マシンVM)に属している特別な Google アカウントです。アプリケーションはサ ービス アカウントを使用して、ユーザーの関与を必要とせずに Google のサービス API を呼び出すことができます。

なので、VMを作るとそのVMに対してサービスアカウントが作られて、そのサービスアカウントに設定されている権限の範囲でVMは動作するということだった。

今回の場合はAppEngineのサービスアカウントに対して、BigTableの読み込み権限を付けることで、AppEngineはBigTableを読み込むことができるようになる。

今年読んだ本

2014年 →2014年消費したおはなしたちまとめ - an odd fellow

2015年 → 今年読んだ本 - an odd fellow

2016年 → 今年読んだ本 - an odd fellow

毎年書いてるので今年も書く。

ろにゃさんの読んだ本 - 読書メーター

今年読書メーターに登録した冊数は20冊ぴったり。今年は就職したのもあってビジネス書の類を眺めるようになった。小説だけだと13冊。ノルマの1月1小説は今年も達成できた。良かった。

新作できちんと追っていたのは竹宮ゆゆこ先生。"応えろ生きてる星"と"おまえのすべてが燃え上がる"が最高に面白かった。ラノベの様な軽さで疾走感があるのに、ぐっと身の詰まった感じが最高。毎回物語の導入が不安になるくらいぶっ飛んでいるのに、物事の処理に当たる登場人物たちは結構地に足の着いた思考をしていたりして、だけどやっぱり軽さはあって、現代人的な気がする。youtuberのように、軽い生き方に見える人たちが、実はものすごい努力の上に成り立っているのに似ている。今年何が面白かったか?と聞かれたらこの2冊を推したい。

"おまえのすべてが燃え上がる"は記事も書いた。

おまえのすべてが燃え上がる - an odd fellow

おまえのすべてが燃え上がる (新潮文庫nex)

おまえのすべてが燃え上がる (新潮文庫nex)

去年に引き続き三浦綾子も読んだ。"続・氷点"、良かったなあ。原罪という観点だと、陽子は重大な罪を抱えていたかも知れないけど、彼女は本当に注意深く潔癖に生きていて、周りの人間の方がよっぽど罪深い感情を持っていて、その対比からキリスト教の原罪に対する赦しという概念を導いているように思った。まあキリスト教とかわからんのですケド。潔癖過ぎる少女に対して、周囲の人々の精神が不潔過ぎるし、それによってもたらされる不幸も度肝を抜いてくるし、それを経ても潔癖であるので、勇気づけられる?というか、私も本当はこうありたいぜという気持ちになります。

"道ありき"は三浦綾子の自叙伝的小説なんだけれど、三浦小説を読むと、「この人はキリスト教信者のくせに人の悪意に詳しすぎる」という感情が湧きます。それで、三浦綾子本体を詳しく知りたくなってくるので読むと納得する。"氷点"の陽子のような綺麗な人なのかも、と思って読むとその実態は夏枝寄りの人間だった。

自叙伝は3部作あるので、またゆっくり読みたい。

道ありき―青春編 (新潮文庫)

道ありき―青春編 (新潮文庫)

今年は森博嗣も読んだ。2年ぶりに読んだかな。理系の気持ちを忘れたときは森博嗣を読んで、僕の考えるかっこよさはコレだと再確認する。大学院を出て研究というのを真面目にやってみた後に改めて森博嗣を読むとエモい。犀川創平の考える"綺麗さ"に近い概念を自分も獲得していることに気付いて嬉しくなった。犀川創平の考える"不潔さ"は、もしかしたら三浦綾子の"綺麗"とかぶるかもなあとか思う。まあよくわかりませんケド。

詩的私的ジャック JACK THE POETICAL PRIVATE S&M (講談社文庫)

詩的私的ジャック JACK THE POETICAL PRIVATE S&M (講談社文庫)

封印再度 WHO INSIDE S&M (講談社文庫)

封印再度 WHO INSIDE S&M (講談社文庫)

アラカルト的に読んだのは"いちご同盟"と"池袋ウエストゲートパーク"。池袋に住んでいるし、ウエストゲートパークは読んどかないとなと思った。思ったより悪くは無かったが、治安悪い話は好きじゃないな。いちご同盟は"四月は君の嘘"のオマージュ元だというのは知っていて、いつか読まなければと思っていたのを忘れかけた頃たまたま本屋で平積みされていて思い出した。

いちご同盟 (集英社文庫)

いちご同盟 (集英社文庫)

池袋ウエストゲートパーク (文春文庫)

池袋ウエストゲートパーク (文春文庫)

古臭い本を読み過ぎか?最近読んでいるのは"マリみて"。池井戸潤は興味がある。さっき妹が陸王の最終回の録画をリビングで見ていて、一緒に見たら面白かった。やるやんけ池井戸潤…。

今年はシリーズものを読み切りたいなあ。飽きっぽくてフラフラと色々読んでしまうんだよなあ。