Cybozu Inside Out | サイボウズエンジニアのブログ

 

開発文化を育て広げる愉しみ

どうも!アプリケーション基盤チームの@yokotaso です。

先日のCybozuTechConference 2017で、「開発文化を育て広げる愉しみ」という内容で登壇させていただきました。 発表内容のカンペを公開します。

かわゆいまとめをしていただいたので、お忙しい方はこちらをどうぞ!

f:id:cybozuinsideout:20171205122410j:plain

文章にはなってしまいますが、どうぞ!

f:id:cybozuinsideout:20171205123010j:plain

「開発文化を育て広げる楽しみ」という話をさせていただきます。今日は宜しくお願いします。

2011年にサイボウズ新卒入社の横田と申します。Webアプリケーションエンジニアとして主に働いております。

本題の前に

f:id:cybozuinsideout:20171205123016j:plain

本題に入る前にすこしお話しさせてください。

まずはチーム開発開発体制について。 ユーザー管理などの管理機能の開発を行なっています。 日本で開発と上海で試験の2拠点体制です。

開発のScrum化の波に乗りまして、我々もScrumを採用しています。 Scrum 開始当初は、1 Sprint内で開発から試験設計までを完了がDoneの定義になっていました。 最近はすべてのタスクというわけではないですが、 1 Sprintで開発から試験完了まで1個流しができるようになってきています。

f:id:cybozuinsideout:20171205123018j:plain

なぜKanbanを採用したのかですが、マルチプロジェクト担当メンバーが多い問題がありました。 影の仕事の存在があったり、誰が何をやっているのかわからない問題がありました。

加えて、開発から試験完了までの仕事はどんどん高速化していきたいので、 上海と日本で多拠点でKanbanをやってみようということになりました。

開発文化の歴史

f:id:cybozuinsideout:20171205123021j:plain

次に、開発文化の歴史についてお話させて下さい

f:id:cybozuinsideout:20171205123024j:plain

サイボウズはもともとオンプレミス・ビジネス中心でした。年単位で開発・試験スケジュールが組まれていました。

ユニットテストがないプロダクトや開発Fixが近くなると動き出す名ばかりのデイリービルドなど悪しき慣習がありました。

開発文化らしいものはなかったんじゃないかと思っています

f:id:cybozuinsideout:20171205123027j:plain

そこからクラウド・ビジネスに挑戦しはじめるわけですが、 前のスライドから開発効率が悪いというのはお察しいただけると思います。

あっという間に緊急リリースが乱発しまして、 品質の不安定化と開発工数の爆発に悩まされることになります。

こういった実務的な問題を解決するために、継続的インテグレーション・継続的デリバリーを利用するようになります。 今まではプロダクト開発をメインに投資を行ってきましたが、開発効率向上のために積極投資をするようになります。

f:id:cybozuinsideout:20171205123029j:plain

ビジネスの主軸がオンプレミスからクラウドの移ろいと時を同じくして開発文化も変化していきます。

クラウド創世記の開発文化をベースに改善を続けてきました。 その結果、開発効率が向上したので開発のボトルネックが少なくなってきました。

そこで、開発から少し視点をあげてリリースまでのプロセス全体の改善したい欲がでてきました。 開発から試験工程までを含めて全体最適化をしていくために、Scrum/Kanban型の開発スタイルへ移行していきます。

開発効率向上のための仕組みから、価値を素早く届けるための開発文化に進化してきます。

f:id:cybozuinsideout:20171205123032j:plain

開発文化は、サイボウズのビジネスを支える重要なファクターに位置付けられるようになってきています。

疑問

f:id:cybozuinsideout:20171205123034j:plain

開発文化の歴史を話してきましたが、社会人経験がある人は、疑問を持ってるかもしれません。

f:id:cybozuinsideout:20171205123038j:plain

クールにみえる開発文化がなんでうちには馴染まないんだろう?とか

f:id:cybozuinsideout:20171205123040j:plain

開発のベストプラクティスと呼ばれるものを導入したけど、廃れちゃったとか

f:id:cybozuinsideout:20171205123043j:plain

そんなのサイボウズだからうまくいくんだろうとか

f:id:cybozuinsideout:20171205123046j:plain

ただ、これってサイボウズでもよくある話なんです。

失敗から改善したり、少しづつですが前に進み続けて今の開発文化があります。

f:id:cybozuinsideout:20171205152223j:plain

開発文化を定着させるためのコツがあるっぽいので、

日本と上海のKanban導入と過去の失敗をネタに

開発文化を育てるためのプラクティス

f:id:cybozuinsideout:20171205123048j:plain

開発文化を育てるためのプラクティスについてお話ししようと思います。

ボトルネックは文化の母

f:id:cybozuinsideout:20171205123108j:plain

さて、一つめですが、ボトルネックは文化の母です。

f:id:cybozuinsideout:20171205123111j:plain

開発プラクティスは開発プロセスのボトルネックを解消するでしょうか? 無理に作ったり導入した開発文化というのはうまくいきません。 導入したら、どうボトルネックが解消されるのか?を考えましょう。

逆にボトルネックが解消されない文化は廃れがちです。 コードやチームの状況を見極めた上で、必要な開発文化を作っていく必要があります。

f:id:cybozuinsideout:20171205123114j:plain

過去の失敗例です。UnitTestを広めようとして失敗したことがあります。 UnitTestが当たり前の開発体制にしたかったんですが、見事に失敗しました。 今思い返すと、当時はまだチームの開発文化として取り組むのは早かったと反省しています。

UnitTestのあるなしは大きなボトルネックではなかったのです。他にもっと大きなボトルネックがあったのでした。

f:id:cybozuinsideout:20171205123117j:plain

その大きなボトルネックは、クラウドとオンプレミスのアーカイブが同時にビルドされないことから生じる問題でした。 そこで、オンプレ・クラウドのデイリービルドを自動化しました。

オンプレミスとクラウドのアーカイブを毎日好きな時間に作れるように刷新しました。 オンプレ・クラウドの同時試験が可能になりました。 試験が同時にできないのが実は大きなボトルネックだったのです。 こういうボトルネックが解消されて初めてオンプレミス・クラウドの環境を意識した開発を行うことができるようになるのです。

f:id:cybozuinsideout:20171205123120j:plain

これだけだと開発文化も何もないんですが、これが新しい開発文化のベースになったりしていくわけです。 開発プロセスのボトルネックから導入する開発プラクティスを見極めていきましょう。

仲間を増やそう

f:id:cybozuinsideout:20171205123124j:plain

次は「仲間を増やそう」です。

f:id:cybozuinsideout:20171205123127j:plain

サイボウズで開発文化として定着したものを振り返ると全員参加型の勉強会を開いていることがとても多いです。

目的は、

  • 知識のベースラインを揃える。
  • 共通の語彙と知識をつける。
  • 問題意識の共有をする。

です。

勉強会のコツですが、シンプルな原理・原則を理解を理解してもらうことが大事です。 そして、全員参加しやすい勉強会にしていきましょう。勉強会の目標をシンプルにして、妥協できるところは妥協していきましょう。

f:id:cybozuinsideout:20171205123130j:plain

Kanbanを導入した時の話ですが、日本・上海で合同の勉強会を開きました。

カンバンの理解としては、WIP(Work In Progress/進行中の仕事)や仕事の流量制限がなぜ大事か?仕事の可視化について、重点的に勉強しました。

f:id:cybozuinsideout:20171205123133j:plain

輪読に利用したカンバン仕事術は、日本語版と中国語版が出版されているので、こちらを利用しました。 言葉は、本質的ではないので使えるものは使いました。

f:id:cybozuinsideout:20171205123135j:plain

また、カンバン仕事術特有ではあるのですが付録にゲームが付いているので、毎回の勉強会の最後にゲームを実施しました。 ゲームを通して、Kanbanの原理原則を体感してもらいました。

なぜ、重要なのか?を共有するのは、開発文化を作っていく上で、重要です。

f:id:cybozuinsideout:20171205123138j:plain

逆に失敗してしまった例ですが、有識者で勉強会を開いてしまったことです。 開発文化にしていきたかったのに、特定メンバーのみで勉強会を開いてしまったことです。

メンバー全員と問題意識の共有ができないだけでなく、メンバー間で知識差ができてしまう原因にもなりました。

小さく始めよう

f:id:cybozuinsideout:20171205123141j:plain

次はSmall Start、読んで字のごとく「小さく始める」という話です。

f:id:cybozuinsideout:20171205123143j:plain

とにかく小さく、早く始めていきましょう。

1週間、1つみんなで決めた簡単なプラクティスに取り組んでみるくらいから始めてみましょう。 無理をしてすべてを取り入れる必要はありません。

f:id:cybozuinsideout:20171205123146j:plain

うまくいったパターンでは、すぐにKanbanを始めました。 できるだけシンプル、簡単なKanbanを作ってみました。上海拠点も自分たちのカンバンを作ってもらいました。 自分たちのKanbanを作りながら勉強会を進めることで、勉強会のネタに合わせてKanbanを改造したり試行錯誤できるわけです。

やっていくうちに、改善アイデアを思いついたりや新たな気づきなどもあります。 改造することを前提に簡単に始めるのがおすすめです

f:id:cybozuinsideout:20171205123149j:plain

失敗例として、知識を一通り身につけてから実践しよう としたことがあります。 ひとまず一通り知識を身につけてから開発プロセスに組み込もうとしました。

ベストプラクティスを謳っているにもかかわらず開発プロセスにそのまま組み込めないものは多いです。 その現実に疲れてしまって、本質的な開発プロセスの改善に時間を使えず、失敗しました。

開発プロセスや組織の状態を考慮して、プラクティスの改造、取捨選択が必要なのです。

効果的な振り返りをしよう

f:id:cybozuinsideout:20171205123153j:plain

小さくはじめたら、いいタイミングで振り返りをしましょう。

f:id:cybozuinsideout:20171205123156j:plain

開発文化を定着させてるために効果的な振り返りをしましょう。開発プラクティスの原理・原則を意識して、振り返ります。

振り返り内容に、開発プラクティスの原理原則を意識した内容がでてくればメンバーに知識が定着しているだけでなく、 日々それを意識して仕事にあたってくれているのがよくわかります。

例を見てみましょう

f:id:cybozuinsideout:20171205123159j:plain

これは、我々のチームででてきた実際の振り返りの内容です。 原理・原則を意識してチームの問題を解決することができた例です。

褒めるポイントが明確で、どう解決したのか?の考え方がよくわかりますね。 チーム全体の処理中の仕事の量を意識して仕事ができるようになっているのがわかります。

f:id:cybozuinsideout:20171205123204j:plain

今度はProblemを見てみましょう。

根拠が明確になり、kanban導入以前では見えていなかった開発プロセスの問題が出てきているのが分かると思います。

普通に開発していたら、WIPが多いとか気にしないですよね。 チームメンバーにKanbanの知識が定着して、それを使って考えることができている証拠ですね。

f:id:cybozuinsideout:20171205123206j:plain

よくないパターンですが、ふんわりした振り返りをしてしまう。

根拠が明確でない・瑣末なProblemをとりあげて、複雑な回避策を採用していませんか? 開発プロセスのボトルネックを解消できるProblemの発見、調査、解決に注力しましょう

KAIZENと守破離

f:id:cybozuinsideout:20171205123211j:plain

振り返りを終えたらKAIZENです。

f:id:cybozuinsideout:20171205123214j:plain

一般的なプラクティスをただ適用するのではなく、 それぞれのカルチャーに合わせて取捨選択して改造してきましょう。

なぜ、改造や取捨選択が大切なのかはあとでお話しします

f:id:cybozuinsideout:20171205123217j:plain

たとえば、こういう Problemがあって、Kanbanを観察した結果、KAIZENするべき内容をきめたとします。 ちょっとわかりにくいと思うので、簡単なKanbanの図で説明します

f:id:cybozuinsideout:20171205123219j:plain

f:id:cybozuinsideout:20171205123222j:plain

f:id:cybozuinsideout:20171205123225j:plain f:id:cybozuinsideout:20171205123229j:plain

プロジェクト開始直後はDoingのタスクはすくないですが、 レビューのフェーズに入ると途端にWIPが高まるのが分かると思います。

f:id:cybozuinsideout:20171205123232j:plain

WIPが高い状態はKanbanでは避けるべき状態です。

f:id:cybozuinsideout:20171205123235j:plain

f:id:cybozuinsideout:20171205123238j:plain

これを改善するためにまず、アバターを導入しました。 そして、Review列を新設して、Reviewには関係者全員を配置します。

f:id:cybozuinsideout:20171205123242j:plain

この改善のおかげでDoingに仕事が持ち込まれないだけでなく、 Reviewはアバターを2人で消費してしまうので、できるだけ早く終わらせたいプレッシャーになるのがお分かりいただけますか?

我々のチームのKanbanを改善例でした。

f:id:cybozuinsideout:20171205123245j:plain

自分たちの状況、カルチャー、問題に合わせてプラクティスを取捨選択・改造して、組織にフィットする開発文化にしていきましょう。 プラクティスを単純に当てはめるのではなく、チームで開発文化を育てていきましょう。

f:id:cybozuinsideout:20171205123248j:plain

海外拠点はどうしたのか?ですが、上海のKanbanも上海のカルチャーを尊重して管理はしていません。

我々とは別のカルチャーや問題を上海も抱えていてそれを解決すべくKanbanを使っています。仕事をしながら日々Kaizenをしてくれています。

私がやったことといえば、最初のKanbanを作るのをお手伝いしたことと、相談や注意喚起くらいです。 勉強会でやることをやった後は、あとは支援するだけです。 ことわざで言うところの魚を与えるのではなく、魚の釣り方を教えるのと同じです。

f:id:cybozuinsideout:20171205123251j:plain

とはいうものの、最終的には日本、上海間で仕事を開発から試験完了まで行いたい目的もあります。

kintoneでタスク処理の基本的なところをやりつつ、各拠点の仕事の流れは各拠点のkanbanで管理しています。

仕事終わりに拠点ごとのKanbanの写真をアップロードしてもらっています。これで多拠点のタスク待ちや他拠点への仕事の依頼のしすぎに気づけるようになっています。

複利と再投資

f:id:cybozuinsideout:20171205123254j:plain

さて、複利と再投資というお話。

f:id:cybozuinsideout:20171205123259j:plain

開発文化として定着したら開発工数が減っていると嬉しいですね。その余剰時間を開発文化に再投資していきましょう。

開発文化を進化させていくのです。新しい挑戦をしていくために開発文化をKAIZENしていきましょう。

f:id:cybozuinsideout:20171205123302j:plain

たとえば、テストエンジニアになるための勉強や今まで煩雑だった試験手順を半自動化するなどに投資できる時間がでてくるわけです。

f:id:cybozuinsideout:20171205123305j:plain

サイボウズは改修後、即リリースというのはまだできていないのですが、実現のためにはさらなる開発文化の進化が必要だと思っています。

f:id:cybozuinsideout:20171205123309j:plain

まだまだやることは盛りだくさんですが、自分たちで開発文化を作り変えてきたことが財産であり、組織と開発体制の基礎体力なのです。

アジャイルな開発プラクティスは実践しなくてもよいが、アジャイルな組織、開発文化を目指していきたいと思っています。

f:id:cybozuinsideout:20171205123312j:plain

必ず何かの問題はあるので、また変わっていきたいと思っております。

まとめ

f:id:cybozuinsideout:20171205123315j:plain

最後は、そして、夢の外へ。

f:id:cybozuinsideout:20171205123319j:plain

サイボウズには拠点・組織をこえて開発文化を育てる取り組みをしてきました。 僭越ながら、開発文化を育て広げるコツをお話ししました。

100組織あったら、100通りの開発文化があって良いと思っています。 なので、自分たちの開発文化がよく知られた開発プラクティスでなくても良いのです。 ベスト・プラクティスと違っててもいいのです。 それよりはボトルネックを解消するための開発文化であってほしいと思います

f:id:cybozuinsideout:20171205123322j:plain

オンプレミス時代から振り返ると隔世の感に驚くばかりなのですが、僕が入社した頃は開発文化がある組織を憧れていました。

頭の中の夢から開発文化のある組織が実現しつつあります。

そして、夢の外へこれからも開発文化を育てていく取り組みを続けたいと思っています。

f:id:cybozuinsideout:20171205123326j:plain

このカンファレンスの大きなテーマに戻ってくるのですが、開発文化を育てることを愉しみたいエンジニアに 少しでも参考にしていただいただければ、幸いです。

f:id:cybozuinsideout:20171205123337j:plain

「開発文化を育て広げる愉しみ」でした。ありがとうございました。

 

「サイボウズ バグハン合宿2017」 開催報告

こんにちは、Cy-PSIRT の大塚です。 

サイボウズでは、3年ぶり2度目となるバグハン合宿を開催 (2017/11/3,4) しました。合宿の様子と結果についてご報告いたします。

バグハン合宿とは?

「サイボウズ バグハンター合宿」、略して「バグハン合宿」。普段オンラインで脆弱性探索をしているハンターの皆様を集めて、寝食を共にしながら脆弱性発見コンテストをやろう!というものです。今回は、15名の方にご参加いただきました。

f:id:cybozuinsideout:20171109143533p:plain

タイムスケジュール

1日目 もくもく 時々 わいわい

決戦の場所は、三浦海岸。遠方の方は前泊して会場入りされていたり、受付時に配ったTシャツをその場で着て臨むという方もいて、スタート前からハンターの皆様の気合いを随所に感じました。途中、チームごとの成果発表やご飯などを挟み、約24時間(1日目 11:00 ~ 2日目 11:00)の戦いがスタートです。 

f:id:cybozuinsideout:20171109171521p:plain

真剣な表情のハンター

今回は、初のチーム戦でした。初めて顔を合わせる方もいましたが、いざ開始すると何かある度に人の輪が出来るチーム、担当製品を分けてもくもくと攻撃するチーム、とそれぞれ特色が出て非常に興味深かったです。チーム戦にしたことで横の繋がりが出来て行くのを肌で感じました。

また、今回は各チームに一人弊社開発者を配置し、ハンターの方々と一緒に脆弱性を探してもらいました。自分たちが作っている製品に対して、攻撃者の視点や手法を屈指し脆弱性を報告される実例を見ることは、今後の開発にとてもプラスとなったようです。

夕食 そして負けられない戦い

宴会場での夕食タイムです。ハンターの皆様もしばし休息の時間...お酒を飲みながらワイワイかなと思いきや、ほとんどの方がウーロン茶を飲んでいました。(翌朝、運営側はその理由を知ることに...。)

f:id:cybozuinsideout:20171109171728p:plain

夕食

そして、夕食もそこそこに始まった「ストリームス(※)」。ゲームの結果もチーム戦ポイントに加算されるというルールでしたので、各チーム負けていられません!!

1日目に得点が低かったチームは一層気合が入ります。運営メンバーも各チームに1人ずつ入り一緒に戦いました。単純なゲームなのですが、運と確率論を駆使した戦いとなります。ゲームの特性上、トイレも我慢でしたがw 全員が本気でゲームをやるという貴重な時間となりました。 

※ 運営メンバーが息抜きの一つとして用意したボードゲームです。  

sgrk.blog53.fc2.com

1日目の夜 ハンターの気配を感じ続けた

夕食後は、部屋に戻り各自ご自由に~というスケジュールでした。チームごとの部屋割りになっているのもあり、ほとんど寝ずにバグハントされていたようで、翌朝までに多くの脆弱性が報告されておりました。朝PCを開いた時の衝撃は言葉に表せません。(この時初めて、ハンターの皆様がウーロン茶を飲まれていたことに納得しました)

日常を忘れてとことん出来た!!という声も多くいただき、夜中もワイワイとバグハンできるのは、合宿形式のメリットだと感じました。

2日目 ラストスパート

「合宿の得点として加算されるのは、11時までに報告されたもの」というルールでしたので、どのチームも最終日の追い上げは凄まじいものがありました。夜中に報告された分の評価が終わらないうちに、「新しい脆弱性が登録されたよ!」という通知が止まらない止まらない。。

f:id:cybozuinsideout:20171109172013p:plain

評価について議論する運営

評価チームが殺気立ちはじめ、2名体制から4名体制に変更し、ガシガシ評価していきました。それでも時間が足りず、重複チェックなどが甘かった点は大変申し訳なかったです。

最終成果発表

各チーム、スライドやデモを用いて、2日間で見つけた脆弱性について発表していただきました。そんな方法が...という内容も多く、おーー!といった感嘆の声があがっておりました。発見した脆弱性の情報、検出手法、悪用の手口などを共有していただくことで、運営側としても非常に勉強になりました。

f:id:cybozuinsideout:20171110162257j:plain

発見した脆弱性を発表する参加者

結果発表 

優勝賞品は、複数種類ご用意しました!それぞれにキャッチコピーがある点も運営のこだわりです。優勝チーム内で高得点を獲得した人から順に選んでね方式です。

1.Google Home「最高のバグハンターに、最高の室内環境を!」
2.Fitbit AltaHR  「適度な運動!元気なハンター!最高のパフォーマンス!」
3.AirPods         「生活をよりスマートに!浮いた時間でバグハント!」

そして、栄えある優勝は・・・Dチーム!!!!

1人少ないというハンデもあったのですが、チーム全員が報告しており、また、Masato Kinugawa さんの他を寄せ付けないパワーもあり見事優勝となりました!!

何かあると誰かの端末に集まって議論していたり、仕様に対するメンバーからの疑問にについて弊社開発者の横田も素早く回答していたりと、チームワークも素晴らしく納得の優勝でした。 

f:id:cybozuinsideout:20171109145500j:plain

Masato Kinugawaさん、raynoldさん、れっくすさん、横田智哉(Cy開発)

本部長 賞 (Google Home)

グローバル開発本部長 佐藤鉄平 が全ての報告を確認し、選出しました。「堅い堅いと言われていた kintoneの脆弱性を唯一報告した」という点が高く評価され、 llamakko さん に送られました!!

f:id:cybozuinsideout:20171114141538j:plain

報告された脆弱性を確認する グローバル開発本部長 佐藤鉄平

PSIRT 賞 (Apple TV)

一番影響度の高い脆弱性(CVSS v3 に基づいた評価値の最高得点)を報告した ゆったん さん に送られました!!

f:id:cybozuinsideout:20171109164426j:plain

バグハン合宿 を通して感じたこと

一同に集まることのメリットを感じた2日間でした。チーム戦にしたことで複数人での議論が生まれ、更に問題点を深堀りすることで報告件数の増加に繋がったと思います。開催目的の一つでもあった、バグハンター ⇔ バグハンター の交流バグハンター ⇔ サイボウズ社員 との交流も達成できたと感じております。

何より、24時間で48件の報告(内30件を超える認定数)をいただいたことに、ただただ驚きました。ハンターの皆様のお力に大変感謝しております。

さいごに

今年の報奨金制度は、12/20 で終了となります。制度の見直し、施策の準備期間を経て、来年度は4月頃の開始を予定しております。12/20を過ぎた脆弱性のご報告は翌年度の報奨金制度の対象となります。合宿を実施するかは未定ですが、ハンターの皆様にとって魅力的な施策を考えていきたいと思っております。

 

バグハン合宿にご参加くださったハンターの皆様、本当にありがとうございました!!現在、粛々と再評価作業を進めております。評価確定までもうしばらくお時間いただけますと幸いです。またいつかお会いできることを、運営一同願っております。:)

引き続き、サイボウズ報奨金制度をどうぞよろしくお願いいたします。

f:id:cybozuinsideout:20171109170945j:plain



 

サイボウズサマーインターン2017 報告その4〜Webサービス開発コース

こんにちは kintone開発チームの小林です。

サイボウズでは、8月から9月にかけて、5日間のサマーインターンを3回開催しました。サマーインターンは以下の5つのコースに分かれて行いました:

  • Webサービス開発
  • モバイルアプリ開発
  • UX/UIデザイナー
  • 品質保証/セキュリティ
  • Site Reliability Engineering

今回は、Webサービス開発コースについてお伝えします。

サマーインターンメンバーの集合写真

インターンの概要

Webアプリケーション開発コースは、東京、大阪、松山の3拠点で行いました。

東京

東京では、サイボウズが提供しているクラウドサービス「kintone」に対して、お客様から寄せられた要望などをもとに新機能のプロトタイプを作ってもらいました。
このプロトタイプは今後の製品への反映を目的にしています。去年のインターンでは、インターン生が実装したプロトタイプのうちの1つが実際に製品に取り込まれました。

プロトタイプの開発にあたっては、ただ機能を実装するだけではなく、

  • ユーザーストーリーやシナリオを想定して仕様を検討する
  • メンターと一緒にペア・プログラミングやコードレビューを行なう
  • 単体テストやブラウザテストを実装する

など、実際のkintoneの開発でも行われている一連のプロセスを体験してもらいました。

大阪

大阪でインターンに参加した学生には、東京と同じくkintoneの新機能のプロトタイプ開発をしてもらいました。
大阪ならではという点として、普段のkintone開発チームのリモート開発を体験していただく形になりました。
メンターが在宅勤務の日もあったり、東京とは様子が異なり大変だったこともあったとは思いますが、最終的には問題なく課題のプロトタイプを実装してくれました。
リモートで開発するのに必要なオンライン上のコミュニケーションを積極的に取ってくれたり、TV会議越しのミーティングに参加したり、実は一番サイボウズの開発らしさを感じたかもしれません。

松山

松山では、ネット連携サービスの路線検索を題材に、不具合改修と新機能のプロトタイプの作成を行いました。
不具合改修については対応したものを、レビュー、QAによる試験を通過させて本番環境に適用するところまでできました。
新機能のプロトタイプについては東京と同様、要望から仕様検討、実装、ブラウザテストまで実装してくれました。
今回の課題は実装の難易度が高めのものでしたが、5日間という短い期間のなかで素晴らしい実装をしていただきました。
実装だけでなく、この期間中に様々な社員とのコミュニケーションを取る機会があったので、その中でいろいろな学びを得たようでした。

プロトタイプ

インターン生がつくったプロトタイプをいくつか紹介します。

アプリ一覧の、アプリを名前順に並び替えて表示する機能

kintoneのポータル画面には、アプリの一覧が作成した順で表示されています。この並び順をユーザが変更することはできず、指定した順序でアプリを並び替えたいという要望を実現するのは難しい状態でした。
このプロトタイプでは、アプリの並び順を、作成順・名前順の2つから選択できるパーツを用意しました。
これによって、アプリ名に通し番号をつけるといった工夫することで、アプリの並び替えができるようにしました。

アプリを名前順に並び替えて表示する機能のスクリーンショット

書きかけのスペース本文の内容を自動保存する機能

kintoneでは、参加者を選んで「スペース」を作り、参加者同士で議論したり、情報を共有したりすることができます。
スペースには本文を設定することができますが、自動保存されることはないので、マシントラブルやブラウザの強制終了などで、編集中の本文の内容が失われてしまう可能性がありました。
このプロトタイプでは、数秒ごとに、スペース本文の内容を自動保存するようにし、不測の事態が起きても、編集中の本文の内容が復活するようにしました。

書きかけのスペース本文の内容を自動保存する機能のスクリーンショット

カレンダビューで、登録者によってレコードの色を変える機能

kintoneには、アプリに登録されたレコードをカレンダー形式で表示する「カレンダービュー」と呼ばれる機能があります。
このプロトタイプでは、研究室で予定を共有する方法として、各メンバーがアプリにレコードを登録してカレンダビューに表示することを想定し、研究室の教授など、特定の人物の予定だけ、色を指定して目立たせることができるようにしました。

カレンダビューで登録者によってレコードの色を変える機能のスクリーンショット

スケジュール

1日目

1日目は、インターンの概要についてオリエンテーションを行ったあと、サイボウズで用意していた課題のリストから課題を選ぶ作業と、kintoneを開発する上で必要な知識を身につける練習問題を解いてもらいました。

2日目

2日目は、選んだ課題に対して、ユーザストーリーや利用シナリオを検討して、仕様書にまとめる作業を行いました。

3日目〜4日目

3日目〜4日目は、実装を行いました。インターン期間中は、メンターがインターン生のとなりに座り、相談を受けたり、ペア・プログラミングやコードレビューを行いました。

5日目

5日目は、成果発表会を行いました。ひとりひとり、実装したプロトタイプの紹介やデモ、インターンを通じて学んだことなどを紹介してもらいました。

インターン生の感想

インターンに参加した方の感想をいくつか掲載します:

企業での大規模なシステム開発に携わるのは初めてで、沢山苦労することもありましたが、メンターの方々に丁寧に説明して頂き課題を終えることができました。
システム開発の知識だけではなく、サイボウズさんの社風や実務のこなし方を学ぶ事ができとても良い経験になりました。
社員の方々のチームワークも素晴らしく、実際にkintoneのアプリで連絡のやり取りを行っている点に驚きました。
サイボウズさんのサマーインターンに参加する事ができて本当に良かったです!


とても楽しくあっという間の5日間でした.
インターンの内容も,実際の業務をこなす内容だったのでCybozuで働いた際のイメージをしやすかったです.
業務もわからないことがあれば,メンターの方に教えていただけて不安なく業務をこなすことができました.
自分で調べる癖をなくすことはいけないことですが,調べても分らないことを聞くのにすごく聞きやすい雰囲気でした. 自分が聞かれた際に,ちゃんと回答できるようにこれからも勉強に励みたいです.
また,インターン中にも自分の課題を見つけることができたので,課題克服に向けて頑張りたいです.


今回のインターンでは、チーム開発のプロセスや製品テストなど普段体験出来ないようなことを沢山勉強することが出来ました。
今回使用したJavaScriptに関しては、基本的な部分を触った程度で、実務開発の経験はありませんでした。
実装課題に取り組んでみると、頻繁に躓くことが多々ありましたが、メンターの方が丁寧に説明して下さり、なんとか無事に課題をこなすことができました。
また、技術面だけではなく、ランチやイベントを通してサイボウズの社風・雰囲気を知ることができたり、社員の方がやさしく接してくれたりと充実した5日間を過ごすことができました。

まとめ

5日間という短い期間でしたが、それぞれのインターン生がしっかりユーザストーリーを考え、納得感のあるプロトタイプを作ることができました。
また、単に課題をこなすだけではなく、サイボウズ自体の文化や雰囲気にも触れてもらうことができたと思います。
学生の皆さんの今後の活躍を期待しています!

 

mdadmの検証中に発見したバグと今後の取り組み

はじめに

こんにちは、技術顧問の武内です。

Linuxにはmultiple devices(以下md)と呼ばれるソフトウェアRAID機能があります。この機能はmdadmというツールを使って管理します。サイボウズのSREチームは、Ubuntu16.04のmdadmを検証をした際に次のような2つのバグを発見しました。

  • mdのresync*1時に使うwrite intent bitmap*2(以後bitmapと表記)のサイズが所定量を超える場合、mdを構成するストレージデバイスに不良セクタを検出した際にbitmapを破壊する
  • mdのサイズ拡張時にbitmapの付与に失敗する

これに関して、本エントリでは、次のようなことをお伝えしたいと思います。

  • これらのバグが具体的にどういうものなのか
  • サイボウズはこのよう場合に、自分たちが使うものだけを修正するのではなくupstreamのOSSを修正するという方針
  • どういう思考プロセスに基づいてどのような流れで調査したのか

検出したバグ

バグ1: mdのresync時に使うbitmapのサイズが所定量を超える場合、mdを構成するデバイスに不良セクタを検出した際にbitmapを破壊する

影響

resync(正確にはmdから一度取り外したデバイスを再度追加する際のresync)をすると、resyncが正常終了するものの、実際には不正な状態になります。

原因

Ubuntu 16.04 から追加されたbad block list(以下bblと記載)というデータの配置位置の誤りによって発生しました。

bblはmdを構成する各デバイスに対して存在し、それぞれのデバイスに対するI/O時に見つかった不良セクタの一覧です。bitmap領域はデバイス先頭から8KB地点に配置されます。その一方、 bblはbitmap領域の後に配置されます。ただし、bitmap領域のサイズによらず、必ず同じ位置(デバイス先頭から40KB地点)に配置されます。このため、bitmap領域のサイズが32KBを超えると、bblへの書き込みが発生した際にbitmapを破壊します。

bitmapのサイズは次のようにして求められます。

256(bitmap領域のヘッダサイズ) + mdのサイズ/((bitmap内の1bitに対応する領域のサイズ(bitmap chunk size)。デフォルトは64MB)*8)

回避方法

以下のいずれかの方法を使います。

  • bitmapを使わない
  • bblを使わない
  • mdを構成するすべてのデバイスについて、次のような手順によってbblを再作成する
# mdadm /dev/md0 --fail /dev/sdc --remove /dev/sdc --re-add /dev/sdc --update=bbl

修正状況

upstreamにおいて修正済(commit 1b7eb672f7792313cc1517feaae8267575fc496b)です。Ubuntuでは17.10において修正済です。

今後の取り組み

Ubuntu 16.04に対してupstreamの修正をバックポートします。

バグ2: mdのサイズ拡張時にbitmapの付与に失敗する

影響

bitmap領域を使うことによるresyncのI/O量削減ができない。

原因

mdのサイズ拡張に伴ってbitmapのサイズを拡張する際に、bitmapのために使える予約領域(以後bitmap予約領域と記載)が少ないことが原因です。

bitmap予約領域のサイズはmdadm -Eコマンドによって求められます。以下20TBのmdを構成するデバイスの一つ、/dev/sdbについての値を計算する例です。

# mdadm -E /dev/sdb
...
Internal Bitmap : 8 sectors from superblock                      # (1)
... 
  Bad Block Log : 512 entries available at offset 96 sectors     # (2)
...

(2)の行の96から(1)の行の8を引いた88がbitmap予約領域のセクタ単位のサイズです。セクタの大きさは512バイトなので、バイト単位に直すと44KBです。bitmap chunk sizeを64MBとすると

64*1024**2*44*1024*8 = 24189255811072 [バイト]

約22TBほどまでしか拡張の余地が無いことがわかります。

修正状況

upstreamにおいても未修正です。Ubuntu 16.10以降にも同じバグが存在します。

回避方法

後述するbad block listを無効にすれば、bitmap予約領域は最大128KBまで増やせます。

今後の取り組み

upstreamのmdadmに対して修正を作成して、取り込んでもらう予定です。

サイボウズはOSSにフリーライドするのではなく、このような場合は積極的にupstream版を修正するという方針があります。過去にもMySQLやNginxを修正したという実績があります。

調査の流れ

注意: やったことを事細かに書くのではなく、重要な点に絞って、思考プロセスに重きを置いて説明します。

検証環境

  • ソフトウェアのバージョン

    • Ubuntu: 16.04
    • mdadm: 3.3
  • ストレージの構成

    • 2つのiSCSIデバイス(以下/dev/sd[bc]と記載)上に構築したRAID1のmd(以下/dev/md0と記載)
    • /dev/sd[bc]のサイズはそれぞれ20TB

バグ1の検出

/dev/md0を作成した後にbitmap領域のサイズとbbl領域の位置を確認すると、辻褄が合わないことがわかりました。

# ./mdadm --create /dev/md0 --level=raid1 --bitmap=internal --size=$((20*1024))G --raid-devices 2 /dev/sdb /dev/sdc
...
# mdadm -E /dev/sdc
...
Internal Bitmap : 8 sectors from superblock                          # bitmap領域の位置
...
  Bad Block Log : 512 entries available at offset 72 sectors  # bblの位置
       Checksum : d2f4290b - correct
...

mdを構成する全てのデバイスには、先頭から4KBの時点に、サイズ4KBのsuperblockというデータが仕様上存在します。bitmap領域、およびbbl領域のsuperblock先頭からの相対的な位置はsuperblock内の所定の場所に記録されています。それによると、bitmap領域のために使えるのは72-8=64セクタ、つまり32KBだということがわかります。

しかし、bitmapの実際のサイズを前述の式によって計算してみると、32KBを超えていることがわかりました。

$ ruby -e "puts 256 + 20*1024**4/(64*1024**2*8)"
41216                                          # 約40KB。81セクタを占める

これは、/dev/sdcに対するI/Oにおいてbblにデータが書き込まれると、bitmapの32KB以降のデータが破壊されることがわかります。

バグ1の修正状況確認

問題があることはわかったので、次はupstreamのmdadmにおいて問題が修正されているかどうかを確認することにしました。

$ git clone git://git.kernel.org/pub/scm/utils/mdadm/mdadm.git
...
$ cd mdadm
$ make -j16 >/dev/null
...
$ sudo
# ./mdadm --create /dev/md0 --level=raid1 --bitmap=internal --size=$((20*1024))G --raid-devices 2 /dev/sdb /dev/sdc
# mdadm -E /dev/ram1
...
Internal Bitmap : 8 sectors from superblock
...
  Bad Block Log : 512 entries available at offset 96 sectors
...
# 

今度はbitmap領域とbbl領域が重なっていませんでした。

次に、具体的にどのような修正なのかを確認しました。Ubuntu 16.04のmdadmはバージョン3.3にいくつかパッチを当てたものなので、mdadmの当該バージョンからHEADまでの間に修正が存在するかどうかを見ました。すべてのcommitを調査するのは大変なので、commit logのフィルタリングによって一次調査するcommitを絞り込みます。

$ git log --oneline mdadm-3.3.. | grep -i "bad.*block.*log"
e4467bc imsm: 4kn support for bad block log
c07a5a4 imsm: clear bad block from bad block log
6f50473 imsm: record new bad block in bad block log
bbab094 imsm: write bad block log on metadata sync
8d67477 imsm: parse bad block log in metadata on startup
1b7eb67 super1: fix setting bad block log offset in write_init_super1()                                                                                                                      86a406c super1: Do not create bad block log for clustered devices.                                                                                                                           968d2a3 md.4: replace "bad block log" with "bad block list"
$ 

怪しそうなcommit(1b7eb67 super1: fix setting bad block log offset in write_init_super1())を見つけたので、詳細調査することにしました。

$ git show 1b7eb67
commit 1b7eb672f7792313cc1517feaae8267575fc496b
Author: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Date:   Thu Nov 10 11:50:54 2016 +0100

    super1: fix setting bad block log offset in write_init_super1()

    Commit f79bbf4f6904 ("super1: don't put the bblog at the end of the free
    space.") changed the location of the bad block log to be after the
    write-intent bitmap, but a fixed offset was used and it can make bbl
    overlap with the bitmap, especially when using a small bitmap chunk.
    This patch changes it to use the actual offset and size of the bitmap.
    It also joins the cases for v1.1 and v1.2 superblock because the code
    was very similar.

何やらそれらしい修正です。この後具体的にソース調査をした結果、このパッチで間違いないことを確認しました。このバグについてはupstreamに存在するpatchをバックポートすれば解決しそうだということがわかりました。

バグ2の検出

バグ1の修正パッチをバックポートしたものを適用したmdadmを使って次のようなmdのリサイズ処理の検証をしました。

  1. bitmap(後述)を無効化: mdadm --grow /dev/md0 --bitmap=none
  2. iSCSIデバイスの容量を拡張: 今回の場合は4TB拡張
  3. mdのリサイズ: mdadm --grow /dev/md0 --size=max
  4. bitmapの再有効化: mdadm --grow /dev/md0 --bitmap=internal

すると、処理4において次のようなエラーメッセージを出して異常終了しました。

failed to create internal bitmap - chunksize problem.

ソース調査

このメッセージでソースを検索すると、Grow.c内のGrow_addbitmap()という関数内で失敗していることがわかりました。

...
                                        if (st->ss->add_internal_bitmap(
                                                    st,
                                                    &s->bitmap_chunk, c->delay, s->write_behind,
                                                    bitmapsize, offset_setable,
                                                    major)
                                                )                                              # この関数が失敗した
                                                st->ss->write_bitmap(st, fd2);
                                        else {
                                                pr_err("failed to create internal bitmap"
                                                       " - chunksize problem.\n");             # このメッセージが出た
                                                close(fd2);
                                                return 1;
                                        }
...

さらに調査したところ、st->ss->add_internal_bitmap()というのはsuper1.c内のadd_internal_bitmap1()という関数だということ、およびその中で呼ばれるbitmap予約領域の最大サイズは128KBに制限されていることがわかりました。

static int
add_internal_bitmap1(struct supertype *st,
                     int *chunkp, int delay, int write_behind,
                     unsigned long long size,
                     int may_change, int major)
{
...
                if (creating) {
                        offset = 4*2;
                        room = choose_bm_space(__le64_to_cpu(sb->size));      # ここでbitmap予約領域を計算
                        bbl_size = 8;
...
...
static unsigned long choose_bm_space(unsigned long devsize)
{                                                                                                                                                                                                    
        /* if the device is bigger than 8Gig, save 64k for bitmap usage,
         * if bigger than 200Gig, save 128k
         * NOTE: result must be multiple of 4K else bad things happen
         * on 4K-sector devices.
         */                                                                                                                                                                                          
        if (devsize < 64*2) return 0;
        if (devsize - 64*2 >= 200*1024*1024*2)
                return 128*2;
        if (devsize - 4*2 > 8*1024*1024*2)
                return 64*2;
        return 4*2;
}
...

さらにbblはbitmap予約領域の後に配置されるのではなく、上記add_internal_bitmap1()の後に呼ばれるwrite_init_super1()において、現在のbitmap領域の直後に配置されることがわかりました。

static int write_init_super1(struct supertype *st)
{ 
        ...
                /* work out how much space we left for a bitmap */
                if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {        # ここは真
                        bitmap_super_t *bms = (bitmap_super_t *)
                                        (((char *)sb) + MAX_SB_SIZE);
                        bm_space = calc_bitmap_size(bms, 4096) >> 9;                    # bm_spaceは現在のbitmapのサイズ
                        bm_offset = (long)__le32_to_cpu(sb->bitmap_offset);
                } else {
                        bm_space = choose_bm_space(array_size);
                        bm_offset = 8;
                }
        ...
                               sb_offset = st->minor_version == 2 ? 8 : 0;
                        sb->super_offset = __cpu_to_le64(sb_offset);
                        if (data_offset == INVALID_SECTORS)
                                data_offset = sb_offset + 16;

                        sb->data_offset = __cpu_to_le64(data_offset);
                        sb->data_size = __cpu_to_le64(dsize - data_offset);
                        if (data_offset >= sb_offset+bm_offset+bm_space+8) {            # ここは真
                                sb->bblog_size = __cpu_to_le16(8);
                                sb->bblog_offset = __cpu_to_le32(bm_offset +
                                                                 bm_space);             # bitmap予約領域ではなく現在のbitmapのサイズをもとにbblのオフセットを計算している

          ...
}

upstreamにおける修正確認

upstreamのmdadmにおいて実機確認をしたところ、Ubuntu16.04と同じ結果になりました。このため、このバグは未修正であることがわかりました。

修正案の検討

仕様(RAID superblock formats - Linux Raid Wiki)の確認によって、bblはどこに配置してもいいことがわかりました。この仕様の話と、これまでの調査の結果から、bblがbitmap領域の直後ではなく、bitmap予約領域の後に配置されるようにするという改善案が考えられます。詳細については今後upstreamのmdadmの開発者達と協議して決める予定です。

 

Cy-PSIRTの紹介と脆弱性報奨金制度の近況──「Cybozu Meetup #7 セキュリティ」開催報告

こんにちは。 コネクト支援チームの風穴(かざあな)です。

今回は、8月22日に開催した「Cybozu Meetup #7 セキュリティ」についてレポートします。

f:id:cybozuinsideout:20171015150653j:plain

Cybozu Meetupとは?

「Cybozu Meetup」は、サイボウズのエンジニアらと気軽に交流する場として企画している、ミートアップイベントシリーズです。会場はサイボウズのオフィス(今のところ東京と大阪)なので、会社の雰囲気や社員の様子を、実際に肌で感じて頂ける機会でもあります。

東京オフィスは毎月1回、大阪オフィスは3カ月に1回程度のペースで開催していて、これまでに以下のようなテーマで計6回開催してきました。

これまで開催されたCybozu Meetupのレポートは、「カテゴリ:Meetup」で一覧することもできます。

セキュリティ

今回のテーマは、Cybozu Meetup初登場の「セキュリティ」。

最初に、品質保証部の山西 生恵(@MtIkutea)が、Cy-PSIRT(Cybozu Inc. Product Security Incident Response Team=サイボウズ製品のセキュリティ品質向上のために活動しているチーム)の活動内容を紹介しました。

f:id:cybozuinsideout:20171015150810j:plain

続いて、急遽お休みをいただいた大塚に代わって再び山西が、サイボウズが2014年から実施している「脆弱性報奨金制度」の近況を報告しました。

f:id:cybozuinsideout:20171015150905j:plain

トークセッションの後は、立食形式の懇親会へ。今回は、著名なバグハンターの方々が参加してくださったこともあって、とても熱量の高い懇親会となりました。

f:id:cybozuinsideout:20171015150934j:plain

f:id:cybozuinsideout:20171015150950j:plain

f:id:cybozuinsideout:20171015151005j:plain

今後も、東京オフィスでは、毎月開催を予定しています。ご興味ある方は、connpassグループ「Cybozu Inside Out」をフォローしてくださいませ。

「こんな話を聞いてみたい!」というご要望も、随時、受け付けています。お気軽にお寄せください。

f:id:cybozuinsideout:20171015151027j:plain

この日のtweetを以下にまとめてみました。参考までに。

ではまた。