Day One という日記書きソフト、愛用しているのだけど今週頭に障害が発生して日本時間で 2018/05/11 の明け方まで同期ができない状態になってた。

Sync Status | Day One Help

ユーザーとして不便だったけど復旧にかなり時間がかかったのがソフトウェア開発者の一人として興味深かった。何が原因で復旧が遅れたのか推測した。

Day One のバックエンドは AWS に構築してあるようで、負荷でサーバーがダウンしたのなら EC2 インスタンスを追加してサーバー再起動すれば良いはずなのですぐ復旧できるはずと思ったが、一向に復旧しない。復旧作業の状況報告ページにしきりに “server rebalance” というフレーズが出てきており、アプリケーションサーバーで “rebalance” なんてことはやらないから、どうもデータベースがクラッシュしたようだった。

Day One のバックエンドエンジニアの採用情報見たら技術スタックが書いてあって、開発言語は Scala で DB は Couchbase を使ってるとのことだった。で、 Couchbase では Shared Cluster の rebalance という作業が必要らしい。

Couchbase は CAP 定理のうち一貫性と分断耐性を保証していて、その代わりに可用性が犠牲になっている(Couchbase Server - Wikipedia)。 Day One では複数のクライアントからほぼ同時に同一ドキュメントに対して更新が走ることが多いし、 iOS からは不安定なモバイル回線経由で接続される。かつては Dropbox や iCloud も同期のバックエンドとしてサポートしていたが、コンフリクトしたり意図せぬデータ欠落などがあったと思われ、自前のバックエンドシステムに移行したのだろう。一貫性と分断耐性に特化した Couchbase はユースケースとして最適に思えるが、障害が起こるとリバランスに手間取り復旧の難易度が上がるようだった。

自分は大規模分散データベースみたいなやつは受託の会社に勤めてた下っ端の頃にしか使ったことがなく、自分でがっつり運用・構築したことがないので大規模データベースに対する知識が足りていないと思う。大した考察は出来ていないが、今後もバックエンド API おじさんとして余生を過ごしていく上で参考になる出来事だった。そのうち詳細な post-mortem が Day One のエンジニアによって公開されるようなのでこちらもあとで読んでおきたい。

あまりに復旧が遅かったのでこのままサービス終了するのではないかと心配になったが、何とか復旧出来たようである。 Day One のバックエンドの皆さんおつさまでした 🍵

三井住友 VISA カードで払うと 12 回まで分割手数料が無料だったのでそれで買った。税込み 25 万くらい。 SSD だけ 256GB から 512GB に変えた。あとはキーボードを Magic Keyboard の US 配列にした。マウスは Magic Mouse 2 を選んだけど正直使いづらい。 Magic Trackpad 2 にすればよかった。キーボードを売って Magic Trackpad を買おうか検討中。 MacBook Pro 2009 の方はデータを抜き取ったらメルカリに出そうと思う。 2 〜 3 万くらいでは売れそう。

MacBook Pro の Touch Bar なしのやつとどっちにするか迷ったけど、最近はアイフォ〜ンが進化してて帰省や旅行に Mac を持って行かなくなった(雑な日記書きやインターネット閲覧などはアイフォ〜ンで事足りる)。ほとんど家で使ってるだけ。仕事で必要なときは会社から借りてる MacBook Pro を使うので私物は据え置き型で良いなという結論に至った。同じくらいの値段ででかい 5K ディスプレイが手に入るなら iMac の方が良い。

CPU を Core i7 にしなかったのはミスったかなと思ったけど全く問題無く快適に動く。普通にコードを書いて写真を整理する程度であれば Core i5 で問題無いと思う。ディスプレイでかくて解像度高いのがなによりすばらしい。 MacBook Pro + 外部ディスプレイを使うのよりも省スペースになり机を広々と使えるのもよい。ディスプレイが一枚なので首を左右に動かす負担もなくなる。

メモリを増やしておこうと思って、いまはちょっと値段が高いが 16GB のやつを 2 枚 Amazon で注文した。これでまた 8 年くらいは粘りたい。

会社でプロジェクトのふりかえりをしていて自分でエモ発言をしてしまって結構いい話だと思ったのでブログに書いておきます。

新しいプロジェクトを始めるとき、誰しもナウでモダンなフレームワークや技術を使いたいと思うだろう。しかし、 Qiita でみんながその技術についての記事を書いてるから、他の会社の友だちがそのフレームワークを使っているから、という理由で技術選択をしてはいけないと思う。新しいものを使うな、という話をしているのではない。社内によく知ってる人がいない技術を自分の意思で取り入れるからには「覚悟」が必要だという話。わからない挙動に遭遇したときにフレームワークのソースコードを読んで問題を解決したり、バグを踏んだときに修正する Pull Request を送ったりする気概があるか、という意味だ。自分以外の人がそのコードを触るときのためにユニットテストのカバレッジを高く保つということも「覚悟」に含まれるだろう。

その話をしていたらジョジョの奇妙な冒険に有名な台詞があるということだったので、 Slack で覚悟と入力したらその画像が表示されるようにしておいた。

スクリーンショット 2018-04-26 18.43.39.png

「覚悟」とは!!
暗闇の荒野に!!
進みべき道を切り開くことだッ!

前書いてた記事の続き。

🏭 Docker を Production 投入するメリットを考える

🏭 Docker を Production 投入するメリットを考える

仕事で開発中のシステムで、 master ブランチに Pull Request が Merge されると自動的に AWS ECS に構築した社内向けの確認環境にデプロイが行われるような仕組みを導入した。自動テスト、コンテナイメージのビルド、デプロイには CircleCI を...

portalshit.net

Kaizen Platform 時代は Naoya Ito さんの以下の記事にあるような感じで deploy してた。 Slack 上で hubot に話しかけると deploy 用の Pull Request が作られていい感じに deploy フローが始まる。

GitHub 時代のデプロイ戦略 - naoyaのはてなダイアリー

GitHub 時代のデプロイ戦略 - naoyaのはてなダイアリー

少し前までアプリケーションのデプロイと言えば capistrano などをコマンドラインから叩いてデプロイ、み..

d.hatena.ne.jp

これがめっちゃ良くて、現職場でも導入したいと思ってたので今週ちょっとやってみたところ deploy できるようになった。

実際のデプロイフロー

まず Slack で hubot ( 山の会社なので tengu という名前にしてる)に話しかける。すると hubot で GitHub の API を叩いて deploy 対象の Pull Request を取得し、それぞれの Pull Request ごとに commit をグルーピングして、 deploy 対象の Pull Request の Author にメンションするかたちで master ブランチから deployment/production ブランチへの Pull Request が作成される。

tengu deploy 1

最近 Slack の GitHub Integration がアップデートされて、 Webhook の通知がいい感じに飛んでくるようになったので Slack 上でどんな内容が deploy されるのかが一目瞭然となる。

実際に作成される Pull Request は以下のような感じ。この Pull Request を Merge することで CircleCI 上で deploy 用のビルドが走る。その辺は Naoya さんの記事で書いてあるのと同じ。

tengu deploy 2

いま作ってるやつは AWS ECS で運用しようとしてるので、 cap deploy ではなく手製のシェルスクリプトで以下のことをやっている。

  1. deploy 用のコンテナイメージをビルド
  2. AWS ECR にコンテナイメージをプッシュ
  3. プッシュしたイメージを利用する Task Definition を追加し、 ECS のサービスを更新 ecs-deploy というシェルスクリプトでやる

以前の記事にも書いたが「 CircleCI が落ちてたら deploy できないじゃん?」というツッコミが入ったため CircleCI が落ちていても deploy できるようにシェルスクリプト化してあるので、手元からおもむろに bin/deploy production とかやっても deploy できる。

ちなみにこのフローを実現する .circleci/config.yml は以下のような感じ。

jobs:
  deploy:
    docker:
      - image: docker:17.05.0-ce-git
    steps:
      - checkout
      - setup_remote_docker:
          docker_layer_caching: true
      - run:
          name: Install dependencies
          command: |
            apk add --no-cache py-pip=9.0.0-r1 jq curl curl-dev bash
            pip install docker-compose==1.18.0 awscli==1.14.38
            curl -s https://raw.githubusercontent.com/silinternational/ecs-deploy/ac2b53cb358814ff2cdf753365cc0ea383d7b77c/ecs-deploy | tee -a /usr/bin/ecs-deploy && chmod +x /usr/bin/ecs-deploy
      - run:
          name: Execute deployment (Docker image build, push to ECR, create new Task and replace container)
          command: |
            case ${CIRCLE_BRANCH} in
              "deployment/dev" | "master" )
                DEPLOY_ENV="dev" ;;
              "deployment/production" )
                DEPLOY_ENV="production" ;;
            esac
            bin/deploy ${DEPLOY_ENV}

workflows:
  version: 2
  production-deploy:
    jobs:
      - deploy:
          filters:
            branches:
              only:
                - deployment/production

Chat deploy のよさ

deploy フロー・ deploy 状況が可視化され、民主化されることがよい。昔ながらのローカルからの capistrano による deploy の問題点は deploy の特権化を招いてしまうことだと思う。 ○×さんしか deploy 用の踏み台サーバーに ssh できないので一々○×さんに deploy をお願いしないといけない、というような状況はよく分からない遠慮や序列を招きがち。 deploy フローが自動化されていることでチームに入ったばかりの人でもさくっと deploy が行えるというメリットもある。

deploy の履歴が Slack 上と CircleCI 上、また GitHub 上に Pull Request として残るのもよい。ひとくちに deploy といっても schema 変更が伴う場合は作業ログの共有やコミュニケーションをどこかで行う必要があり、その場所として GitHub の Pull Request が使えるのがとてもよい。 YAMAP で作った deploy スクリプトではそこまでやってないが、 Kaizen Platform の deploy スクリプトには deploy 用の Pull Request 本文に動作確認用のチェックボックスを作って、チェックボックスにチェックが入れられるまで cronbot が二時間おきに deploy 対象の commit author に Slack 上で動作確認を促す、というような仕組みまであった。

今後 YAMAP でもどんどん deploy フローを改善していって Merge ボタンを押したあと寿司を食ってれば良いような状態1にしていきたい。


ちなみに上記の chat deploy を実現するためには GitHub App を作っていろいろやる必要があって、その辺は Kaizen Platform で同僚だった t32k さんの以下の記事が参考になった。

チャットデプロイしたい2018 - MOL

チャットデプロイしたい2018 - MOL

タイトルの通り、チャットデプロイしたい。

t32k.me

書いてあるフローはほとんど Kaizen Platform のやつと同じでちょっとウケた。いやでもそのくらい完成されてる仕組みだと思う。この割とイケてる deploy フローを体験してみたい人は僕が勤めてる YAMAP の Wantedly をご覧下さい。資金調達しており割と積極的に採用中です。


  1. Terraform + GitHub + CircleCI + Atlasを利用してAWSの操作を自動化した - Glide Note http://blog.glidenote.com/blog/2015/02/18/terraform-github-circleci-atlas-aws/ 

はてなブックマーク - リモートワークのストレス | POSTD

リモートワーク別に寂しくないし楽勝、みたいなコメント多いけど違和感あった。リモート楽勝という人はフリーランスとか受託の会社の人なのではないかと思う。自分のブックマークコメントは以下。

激しく同意。雑談したい、家族から家事を頼まれる、オフィスにいる連中から事業理解が低いと責められる、毎日服を着替える能力や通勤電車に乗る能力が失われる、などなど — http://b.hatena.ne.jp/morygonzalez/20180309#bookmark-359971190

「こいつはわかってない」問題

自分の場合は事業会社に所属した上でのリモートワークだった。事業会社(大抵のスタートアップもこれに含まれるはず)の場合はソフトウェアエンジニアにも事業やプロダクトへの理解が求められるので、リモートだとなかなか厳しい部分がある。事業理解は日々の MTG の他、オフィスで何気なく交わす雑談や昼飯の時なんかに醸成されるものだと思うので、リモートだと MTG での情報伝達密度が下がるし雑談や昼飯に至ってはそもそも不可能なので自分自身の事業理解も深まらない。仮にこちらに事業に対する理解があったとしても、それをオフィスにいる連中に伝えることが難しいので結局「こいつはわかってない」という烙印を押されることになる。リモートワークやってて同僚のエンジニアの皆さんとは友好関係を築けたと思うけど、 PM や上司とはなかなか良い関係になれなかった。

家庭内で仕事が軽んじられる

家族がいる人の場合は家族が「こいつ家にいてあんまり忙しくなさそうだから家事を頼もう」ということになりがち。自分の場合は子どもの幼稚園の送り迎え(バス乗り場まで)、幼稚園から帰ってきたあとの子守、洗濯物干し・取り込み、などを頼まれることが多かった。配偶者も仕事をしていて家事を分担する、ということなら当然やるけど、我が家の場合は嫁さんが習い事やヨガで忙しいので家事をやらなければならない、という感じで、自分の仕事は嫁さんの習い事よりも優先度が低いものなのだろうかと悶々とした。

社会適応能力の低下

毎日身支度をする能力、出かけていく能力も確実にむしばまれていく。転職してリモートワークからオフィスワークに切り替えて、朝の混んでる時間の電車に乗る通勤生活を再開してからの数ヶ月間は肉体的にも精神的にも非常につらかった。また家で仕事してると出歩かないので当然に運動不足になる。自分で意識してジョギングしたり体を動かしたりしないと確実に健康を損なう

自分がリモートワークに対して否定的な見解を持っているのは以上のような背景があるのであった。

良い面もある

もちろんリモートワークには良い面もある。

ワークライフバランス

子育てのための一時期や家族の看病が必要な時期には非常にありがたい制度だと思う。ワークライフバランスは非常に良好になる。

集中維持

コード書きに集中したいときにもリモートワークは便利だった。リリース前など、移動の時間も惜しんでコードを書きたいときには朝 10:00 から夜の 24:00 頃まで風呂とトイレと飯の時間以外はずっと仕事してたこともあった。それでも 10 時間は時間が空くので十分睡眠をとることはできる。これも前にブログで書いたような気がするが、いつでもオフィスに仕事しに行ける環境で、自分の裁量で週に数日リモートで仕事をするのが一番満足度の高い働き方になると思う。

地方都市に暮らしながらデラウェア法人で働ける

あとそもそも福岡では前職のような数十億円規模の資金を調達してがつんと成長しようとしているスタートアップの仕事にありつくことなんかは不可能なので、田舎に住んでいても都会のイケてる手法で仕事できてたのはリモートワークならではだったと言える(これも元記事に書いてある)。いまの職場でやってることは前職で身につけた1もの(スタートアップで働くエンジニアのディシプリン的なもの、あるいは技術顧問おじさんの素養)を土台にしているので、これは非常にありがたかった。

まとめ

ひとくちにリモートワークといってもいろいろな形態、状況があるので、↑の記事のブコメのように「リモートとか楽勝じゃね?」というコメントを読んでうかつにリモートワークを始めようとしている人がいたとしたらちょっと踏みとどまってもらいたいし、自分に向いているか、勤務先のビジネス領域・ビジネスモデルなども加味した上で決めてもらいたいと思う。

あとリモートワークだとコードレビューが甘くなりがちではないか、という問題もあるけどそれはまた別の話かもしれない。

References


  1. 当時は自分は全然成長してないと思ってた。こういうのを身につけたんだということはあとから気がついた 

※絵といっても絵画のことではないてす。 UML とかのことです。

夜中まで訳の分からない仕様書・設計書を書かせられてたブラック企業時代の体験が辛すぎて UML 的なやつを見ると嫌な思い出がフラッシュバックしてたけど、最近は絵を描くのが好きになってきて、結構いいものだと思うようになってきた。

当時はアホにみたいにドキュメント書かせられてた。フローチャート、ユースケース図、シーケンス図、 ER 図、画面詳細設計書などなど。もちろん方眼の Excel で( Visio は下っ端には使わせてもらえなかった)。オープンソースのショッピングカート( Magento )のガワだけ変えて EC サイト構築する場合でもユースケース図描けとか言われて、 OSS のコードの処理の流れを図化するとかギャグだろと思ってた。要するに単なる工数稼ぎで客から金を詐取するための汚いやり口だったのだ。

そもそも実際に絵に描いた通りにシステムを作れることなんてなかった。複数社で引き継がれてきたコ〜ルドフュ〜ジョンのコピペコードの塊の前では UML とか描いても意味なかったし、自分たちのコーディングスキルも低かった。今でも事前に絵に描いた通りにシステムを作るのは難しいと思う。

しかし自社で製品を作ってる会社で働くようになって、自分たちのために描くシーケンス図やらフローチャートはとても役に立つなと思うようになった。実装前にドキュメント作るよりも、実装してて詰まったときや最初にガーっと作ったやつをリファクタリングしてるとき、開発終盤のコードが安定してきたときに作るととてもよい。

最近気に入ってるのはシーケンス図で、 Microservice 化されたウェブアプリケーションのデータの流れを理解するのにとても役に立つ。社内のドキュメントツールを Kibela にしたおかげで PlantUML が使えるのが快適極まりない。 Markdown なので変更があったときに絵をサクッと編集しやすい。これがドローツールをいちいち起動して編集したあと画像を書き出さないといけないとかだったらなかなか更新する気にならない。

とはいえ PlantUML が苦手なやつもあって、フローチャートはダメダメだった。フローチャート、プログラムの処理の流れが描いてあるだけでは不十分で、見た目の整い具合も重要だと思う。そもそも絵や図は言葉で書かれているものだと理解しづらいものを視覚化して理解しやすくするものなので見た目はとても重要になる。 PlantUML ではなかなか条件分岐や処理の塊の位置が揃わず、綺麗にグリッドに配置される OmniGraffle の方が圧倒的に描きやすかった。 OmniGraffle は値段が高いのが玉に瑕だけどとても良いものだと思う。


ブラック企業時代は絵を描くことが金儲けのためだから辛かったのだと思う。自分たちが後から困らないようにするために書くドキュメントは全然つらくない。当事者意識を持てるか持てないかの違いなのだと思う。 ATI を高めていけば Excel 方眼シートも辛くないのかも知れない。知らないけど。

Hush-up houndci-bot by morygonzalez · Pull Request #232 · lokka/lokka

Hush-up houndci-bot by morygonzalez · Pull Request #232 · lokka/lokka

Let @houndci-bot shut his big mouse up What I did Add Rubocop and HAML-Lint to Gemfile in order to check link locally. Add rules for Rub...

github.com

lokka/lokka 、 Pull Request を出す度に Hound CI のチェックが走って bot にコードレビューでぼこぼこにされるので、この bot を黙らせるべくガチャガチャやってた。 Hound CI のチェックルールは Rubocop に準拠しているようで、 2011 年からある Rack アプリを Rubocop のチェックにかけるのは面白かった。

Lokka 、意外と Hacky なコードが多く、条件式内での代入とか、ヨーダ記法とか、後置の until とか、スコープが広い一文字変数とか、めっちゃ長いメソッドとか、 if 文のネスト、代入したものの使われてない変数なんかを修正した。 method_missing はカスタムフィールドを定義できるという Lokka の仕様上根絶できなかったけど、 .rubocop.yml に最低限の除外ルールを追加して Rubocop のチェックはパスするようにできた。

Lokka 、 ORM が ActiveRecord じゃないことが問題だと思ってたけど、真の問題は lib/lokka/helpers/{helers,render_helper}.rb にビジネスロジックが詰め込まれてることだと思った。しかもこのあたりのコードの可読性がよくなく、触るのが怖い感じの複雑なやつが多い。この辺のコードをもうちょいクラス化して分割し、ユニットテストも手厚くしていかないと ORM を変えても F/E を今風にしてもウェブアプリケーションとして生存していくことは厳しいと思う。

前に進んでいくためにも Rubocop のチェックを入れる&パスさせるのはプラスになると思う。 頑張ってメンテしていくぞ。

追記

この辺のコードをもうちょいクラス化して分割し

と書いたけど、 Rails と違って手軽にサクッと作れるのが Sinatra の良い所なわけではあって、仕事で作る Rails アプリのノリでクラスやファイルを分割したりするのは違うのかもしれないと思った。 Rails で作られたオープソースの CMS やブログツールに長生きし続けるものがないのも、 Rails の場合、個人が偶発的に始めてメンテ出来るようなものになりにくいからかも知れない。

とはいえヘルパーがビジネスロジックを所持しているのはテスタビリティやメンテナビリティが良くないので Lokka と心中する覚悟でやっていくぞ!!!、!