Quantcast
Channel: Cybozu Inside Out | サイボウズエンジニアのブログ
Viewing all 681 articles
Browse latest View live

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

$
0
0

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

今回は、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を以下にまとめてみました。参考までに。

ではまた。


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

$
0
0

はじめに

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

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では16.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の開発者達と協議して決める予定です。

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

$
0
0

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

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

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

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

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

インターンの概要

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

東京

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

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

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

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

大阪

大阪でインターンに参加した学生には、東京と同じくkitoneの新機能のプロトタイプ開発をしてもらいました。
大阪ならではという点として、普段の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日間という短い期間でしたが、それぞれのインターン生がしっかりユーザストーリーを考え、納得感のあるプロトタイプを作ることができました。
また、単に課題をこなすだけではなく、サイボウズ自体の文化や雰囲気にも触れてもらうことができたと思います。
学生の皆さんの今後の活躍を期待しています!

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

$
0
0

こんにちは、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



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

$
0
0

どうも!アプリケーション基盤チームの@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:plainf: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

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

Cybozu Tech Conference 2017 開催報告

$
0
0

こんにちは。コネクト支援チームの成田です。

12/2(土)に、サイボウズが主催するイベント「Cybozu Tech Conference 2017」を開催しました。

f:id:cybozuinsideout:20171213111916p:plain

Cybozu Tech Conference について

「Cybozu Tech Conference」は、サイボウズが主催する、techな人向けのカンファレンスです。 サイボウズが、チームのためのクラウドサービス「cybozu.com」を開発、運用する中で、日々蓄積された学びを多くの方々と共有し、そのフィードバックから私たちも学びたいという思いで、昨年からスタートしました。

昨年は様々な技術トピックを紹介してきたのですが、今年は、エンジニアを取り巻く環境に焦点を当てたテーマのパネルディスカッションや発表が行われました。

発表

パネルディスカッション以外の発表資料はすべて公開しておりますのでぜひご覧ください。


開発文化を育て、広げる愉しみ - 海外拠点Kanban導入記 -

当日の Twitter のつぶやきは、togetter でまとめています。
https://togetter.com/li/1178341

懇親会

ピザやお寿司、スイーツなどをいただきつつ、サイボウズ社員と参加者で親睦を深めることができました。懇親会中に開催したLT大会では、サイボウズの社員だけでなく社外の方々にも発表していただき盛り上がりました。 LTで発表していただいた皆さま、ありがとうございました!!

f:id:cybozuinsideout:20171213113608p:plain

おわりに

去年からテーマを大きく変えたこともあり、どれだけの方に興味を持っていただけるか不安もあったのですが、 結果、去年より多くの人にご来場いただけました。懇親会やLTでも盛り上がることができよかったです。

これからもサイボウズの技術情報や働き方など、技術発信のためにイベントを開催していきたいと思っています。 興味ある方は、connpassグループ「Cybozu Inside Out」をチェックしてください!

ご参加頂いた皆さま、ありがとうございました。今後ともよろしくお願いします!

スプリングインターンシップ2018を開催します!

$
0
0

こんにちは!品質保証部の中園です。

2018年2月、サイボウズでは初のエンジニア&デザイナー向けスプリングインターンシップを開催することになりました!

f:id:cybozuinsideout:20171221101122p:plain

今回は4つのコースをご用意しました。

スプリングインターンを通して、サイボウズのことをより知っていただけると嬉しいです。

(2月ですが、)サイボウズで熱い熱い5日間を過ごしましょう!

皆さんのエントリーをお待ちしています!

募集要項

日時

2018年2月19日(月)~23日(金)

場所

東京オフィス

就業時間

9:00~18:00

※ 初日は10時集合、最終日は懇親会を実施するため20時~21時頃解散となります

対象

2019年4月の入社が可能な学生

募集人数

各コース1回につき3名程度

選考

書類選考、面接(Webも可)1回

待遇

日給8,000円

※ 遠方からご参加いただく方には、交通費・宿泊費を支給します

エントリー方法

こちらよりエントリーしてください

お問い合わせ

  • 人事部: 本林 明子
  • メールアドレス: recruit_contact@cybozu.co.jp
  • 電話番号: 03-4306-0870

Webサービス開発コース

Webサービス開発コース

概要

サイボウズが提供するkintoneの機能のプロトタイプを作成します。

テーマは実際のユーザーや社内での要望を元に、仕様検討や実装、テストの自動化にチャレンジしてもらいます。

インターン期間中はkintoneを開発する社員がメンターとして指導やコードレビューを担当し、大規模なWebサービス開発の現場を体験することができます。

必要な経験/スキル

  • Webサービス開発の経験
  • JavaもしくはJavaScriptの知識

あると望ましい経験/スキル

  • Git/GitHubの使用経験

モバイルアプリ開発コース

モバイルアプリ開発コース

概要

サイボウズのモバイル製品に簡単な機能を実装していただきます。

製品のソースコードに触れたり、テスト・コードレビューを通じて実際の開発現場を体験することができます。

必要な経験/スキル

  • iOS(Swift) の開発経験

あると望ましい経験/スキル

  • Git/GitHubの使用経験

UX/UIデザイナーコース

UX/UIデザイナーコース

概要

サイボウズのデザイングループメンバーとともに、製品・サービスのデザイン業務に取り組んでいただきます。

自由な発想を活かして新しいデザインを提案してください。

必要な経験/スキル

  • PCやスマホ向けのデザイン経験
  • ポートフォリオ

あると望ましい経験/スキル

  • ユーザーリサーチの興味、経験
  • プロトタイピングスキル
  • チャレンジ精神

品質保証コース

品質保証コース

概要

サイボウズ製品のテスト業務を通して、サイボウズ製品の品質がどのように担保されているのか、品質とは何なのかを体験していただきます。

実施内容としては、以下を予定しています。

  • サイボウズ製品のテスト設計、テスト実施
  • Seleniumを使った簡単な自動テストの作成

現役の品質保証部のメンバーがメンターとなり、手厚くサポートをしますので、テスト自動化やテスト未経験の方でも大歓迎です。

必要な経験/スキル

  • ITに関する基本的な知識がある
  • Webサービスのテストについて興味がある
  • 「品質保証」という概念を説明できる
  • 地道な作業をコツコツとすることが好きである

あると望ましい経験/スキル

  • Webサービスのテスト経験
  • プログラミング経験(言語問わない)

2017年サマーインターンの開催記事

「生産性向上」してますか?──「Cybozu Meetup #3」開催レポート

$
0
0

こんにちは、コネクト支援チームの風穴(かざあな)です。先日開催した「Cybozu Meetup #3 生産性向上」についてレポートします。

f:id:cybozuinsideout:20170511165859j:plain

サイボウズのミートアップ

「Cybozu Meetup」は、サイボウズのエンジニアとカジュアルに交流する場として企画、開催しているイベントシリーズです。いま流行の企業ミートアップのサイボウズ版ですね。会場はサイボウズのオフィスなので、社内の雰囲気を実際に肌で感じて頂ける機会でもあります。

開催頻度は東京オフィスで月1回、大阪オフィスで数カ月に1回程度の予定です。毎回テーマを決めていて、これまでに「フロントエンド」、「SRE」(Site Reliability Engineering)というネタで開催しました。

サイボウズの生産性向上

通算3回目となるCybozu Meetupのテーマは「生産性向上」。

2015年8月に生産性向上チームを立ち上げた宮田(@miyajan)が「すべてを自動化せよ! 〜生産性向上チームの挑戦〜」と題してトークセッションを行いました。

f:id:cybozuinsideout:20170511170013j:plain

質問&交流タイム

f:id:cybozuinsideout:20170511171011j:plain

トークセッションの後の交流タイムでは、別チームのエンジニアや一般社員も参加し、生産性向上に関する技術の話や、エンジニアの働き方の話などでも盛り上がりました。

f:id:cybozuinsideout:20170511171212j:plain

f:id:cybozuinsideout:20170511171250j:plain

サイボウズの生産性向上チームでは、一緒に生産性向上に取り組んでくれるエンジニアを絶賛、募集中です。詳しくは、以下のサイトをご覧ください。

生産性向上エンジニア──CIや自動化などの開発基盤を整備する大事なお仕事 - サイボウズ株式会社のWeb エンジニア中途の求人 - Wantedly

次回は「スクラム/アジャイル」

次回のCybozu Meetupは「スクラム/アジャイル」をテーマに開催します。開催の様子は、こちらのブログでレポートしますので、お楽しみに。

また6月には、大阪オフィスでの開催も予定しています。ご興味ある方は、connpassグループ「Cybozu Inside Out」をフォローしてくださいませ。

ではまた。


サイボウズ Live アクセス障害の裏で起こっていたこと

$
0
0

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

2017/11/13 にサイボウズLiveの長時間にわたる障害が発生しご迷惑をおかけしました。

技術的な調査が一段落し、対応を進めております。

障害にいたった原因と対応のお話をさせていただきます。

簡単なまとめ

  • Java8u152以降で、CPU負荷が高まる現象
  • Java標準のデシリアライズとSecurity Managerの相性が悪くなった
  • 解決策は現時点では存在しない。サイボウズLiveでは、Java標準のデシリアライズをやめる準備段階

障害発生時の状況

障害発生の数時間前に、運用マシンのメンテナンスを行っておりました。

  • Javaのマイナーアップデート
  • カーネルのアップデート
  • その他、設定ファイルなどの更新

障害発生時には次のような現象が見られました。

  • JavaプロセスがCPU高負荷状態
  • MySQLに大量のロック及びエラーが発生

監視システムが警告した時にはこのような状態になっており、問題の切り分けが難しい状態でした。

時系列の対応はブログの最後に書いておきますので、興味のある方はどうぞ。

最終的にJDKをダウングレードし、障害が収束しました。

原因の特定

メトリクスやChange logから考えられる原因は無数に存在しました。

  • Full GCでThreadがHungした説
  • MySQLの大量ロックが発生していたので、JDBCドライバとJDKの相性が悪い説
  • 機材故障説
  • DoS攻撃説

などが考えられましたが、どれも根拠に乏しく断定ができませんでした。

調査の結果、slow.logから数万件のオブジェクトをWebサーバーで生成していることがわかりました。 同様の現象が発生するデータで検証したところ、5~8倍程度のパフォーマンスの劣化が判明しました。

検証環境で perf コマンドを利用した結果です。

プロファイル例: perf record -a -p <PID> sleep 20

Java8u152

$ sudo perf report
# (省略)
# Overhead  Command  Shared Object       Symbol 
# ........  .......  ..................  .....
#
    15.64%  java     libjvm.so           [.] JVM_GetStackAccessControlContext    
     7.70%  java     libjvm.so           [.] Method::validate_bci_from_bcx  
     7.57%  java     libjvm.so           [.] vframeStreamCommon::next  
     6.71%  java     libjvm.so           [.] java_lang_Class::protection_domain
(省略)

Java8u144

$ sudo perf report 
# (省略)
# Overhead  Command  Shared Object       Symbol 
# ........  .......  ..................  .....
#
     3.11%  java     libjvm.so           [.] InstanceKlass::oop_oop_iterate_nv   
     2.90%  java     perf-8026.map       [.] 0x00007f953268275b   
     2.06%  java     perf-8026.map       [.] 0x00007f9532678c5d
(省略)         

0x...で始まるものはJITコンパイルされたコードです。

JVM_GetStackAccessControlContextはSecurityManager関連のメソッドです。SecurityManagerが怪しい。

この結果を元に障害発生時の ThreadDumpを読んでいきます。次の部分で停止しているThreadが大量にありました。

"http-bio-8080-exec-24" #64 daemon prio=5 os_prio=0 tid=0x00007fe984007000 nid=0x3352 runnable [0x00007fe9d9283000]
   java.lang.Thread.State: RUNNABLE
 at java.security.AccessController.getStackAccessControlContext(Native Method)
 at java.security.AccessController.getContext(AccessController.java:820)
 at java.io.ObjectStreamClass.newInstance(ObjectStreamClass.java:1093)
 at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2048)
 at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1568)
 at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2282)
 at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2206)
 at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2064)
 at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1568)
 at java.io.ObjectInputStream.readObject(ObjectInputStream.java:428)
 at java.util.ArrayList.readObject(ArrayList.java:797)
 at sun.reflect.GeneratedMethodAccessor107.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1158)
 at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2173)
 at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2064)
 at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1568)
 at java.io.ObjectInputStream.readObject(ObjectInputStream.java:428)
 ....(以下プロダクトコードが続く)

この検証からJava8u152でSecurity ManagerをOFFにしたところ、パフォーマンス劣化現象が発生しなくなったため、Security Managerが原因の可能性が高いと判断しました。

Java Security Manager でセキュアなサービスを構築しようでも言及されているように SecurityManagerはパフォーマンス対策が行われていました。原因の可能性が低いと判断していたため、初期の段階で原因として排除してしまいました。

JDKの原因

OpenJDKの改修は次のとおりです。 http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/58243fea3fe2#l1.152

調査の結果、次のようなことがわかりました。

  • Java標準のクラス以外をデシリアライズするときに、 java.security.AccessController.getStackAccessControlContextが実行される
  • java.util.Listをデシリアライズすると、Listのサイズと同じ回数のjava.security.AccessController.getStackAccessControlContextが実行される
  • java.security.AccessController.getStackAccessControlContextは計算コストが高い

サイボウズLiveでの原因

サイボウズLiveではクエリの結果をキャッシュする機構で、シリアライズ/デシリアライズ用いてオブジェクトのディープコピーを行っていました。 キャッシュするクエリの結果が大きいときに、今回の現象が発生していました。

障害のシナリオは次のように考えています。

  1. 大量のキャッシュ生成が発生するリクエストが実行される
  2. (1)のトランザクション内でテーブルロックするクエリが実行される
  3. (1)のトランザクションが終わらない
  4. 滞留したリクエストが原因で最終的にMySQL側でロックが報告される

データ量や実行されたリクエストに依存して発生する現象だったため、発見に時間がかかってしまいました。

java.security.AccessController.getStackAccessControlContextが数万回実行されてしまうケースがあったと思われます。

アプリケーションサーバーが非常に高負荷だった状況とも整合性がとれます。

サイボウズLiveでの対策

前述ですが、Security Managerのパフォーマンスを改善するために独自のSecurityManagerクラスを実装しています。 これによって、計算コストが高いメソッドがコールされることを回避しています。

JDKの改修では計算コストが高いメソッドがハードコードされているので、 Security Manager を利用するのであれば解決策は、Java標準のシリアライズ/デシリアライズをやめることです。

サイボウズLiveとしては、次のような対策をとる予定です。

  1. データベースの結果キャッシュは、シリアライズ/デシリアライズの処理をkryoライブラリに置き換える
  2. (1)をリリースして問題ないことを確認した後 JDKを再度アップデート

参考: github.com/EsotericSoftware/kryo

JDKの脆弱性に該当しないのか?

サイボウズLiveのJDKのアップデート直後に、CPU負荷が高まりアクセスしにくい状況になりました。 JDKのアップデートの結果、今まで処理できていたリクエストがDoS攻撃になってしまいました。

このことからJDKの脆弱性の可能性もあるとして、Oracleに脆弱性報告させていただきました。 Oracleからは脆弱性には当たらないと回答を得られました。その回答をもって、ブログで公開しています。

CPU負荷が増加傾向にある方は一度ご確認ください!

他のプロダクトの影響は?

Security Manager、Javaの標準のデシリアライズ 機能 を利用していると発生する可能性があるということで、他のプロダクトへの影響も調査しました。

kintoneでは、デシリアライズ を使っていましたが、Javaの標準クラスのみでした。

f:id:cybozuinsideout:20171212181034p:plain

Javaの標準クラス以外がデシリアライズされる可能性を調査したところ、3行の型変換のおかげで障害を回避していたことがわかりました。 はるか昔にコミットされた3行に圧倒的...感謝…!

教訓

うまくいったこと

  • 原因の切り分けが難しいときは、断片的な情報からしらみつぶしで原因究明にあたること
  • バイアスにとらわれている可能性も頭の片隅に入れること
  • 障害発生時のメトリクス情報から、プロファイリングツールを適切に使いこなす大切さ

うまくいかなかったこと

  • サイボウズLiveには運用環境をプロファイリングできていない。問題の切り分けに時間がかかった
  • リリース前の性能評価がうまくできていない
  • 夜間など稼働率が低い時間帯のアップデートは問題の早期発見を難しくさせると学んだ
  • カナリア・リリースが我々には必要

参考: カナリアのおかげで命拾い : CRE が現場で学んだこと

最後に

サイボウズLiveを安全にご利用いただくためのアップデートが、障害を起こしてしまい大変ご迷惑をおかけしました。

2017/12/19 の障害は今回の障害を踏まえたJDKアップデートの布石のための修正が原因でした。度々のアクセス障害、大変申し訳なく思っております。 決して手を抜いているわけではないです。そこだけはどうか、ご理解いただけると幸いです。

2019年に終了してしまうプロダクトではありますが、出来る限り安全にご利用いただけるよう手を尽くしていきますので、よろしくお願いしたします。

2016年の懺悔に引き続き2017も懺悔したので、来年は良い年になりますように。

来年も引き続き、技術ブログをお楽しみいただければと思います。では、良いお年を!

障害の時系列対応

時間対応
08:06 JST モニタリングシステムより通常警告を受信。JVM threads 数に上昇傾向があることを視認。
08:22 JST モニタリングシステムより緊急警告を受信。詳細な調査を開始。
08:35 JST ログイン画面は表示されるがログインができない状態。アクセスログを調査しても正常時と比べて大きな変化は確認できない状況。
09:22 JST 切り分けのため、Javaアプリケーションサーバの再起動を実施。
09:38 JST Javaアプリケーションサーバの再起動後、ログインはできたが非常にアクセスが重い状態。
10:16 JST データベースサーバの不具合を疑いスレッドダンプを取得し調査。応答待ちが多い状況を確認。
11:31 JST 特定のUPDATE クエリが顕著に遅いことを確認。クエリに問題は見受けられないなため、物理機材を疑い HDD や SSD の状態を調査。
11:41 JST データベースサーバの SSD に不具合の傾向を確認。当該 SDD の切り離しを実施。
11:48 JST await は改善したが、未だサイボウズ Live のアクセス状況は改善せず。
12:03 JST クライアントコネクションに起因する問題を疑い、1つのデータベースサーバにて全 MySQL コネクションの kill を実施。結果、効果が認められず。データベースサーバ自体の問題を疑い、スイッチオーバーを試行。
12:06 JST スイッチオーバーの実施後もアクセス状況に改善は見られず。
12:09 JST 再度、Javaアプリケーションサーバの再起動を実施するが、JVM threads 数が即上昇。
12:17 JST ~ 14:42 JST スイッチオーバーを実施した際に Master, Slave 間で一部データ不整合が発生したため、この対応を実施し、復旧を確認。
改めて障害の切り分け対応を議論し同時アクセス数を絞って原因箇所を探ることを決断
16:15 JST 社外からの同時アクセス数を 10 に制限。改善見られず。
16:43 JST 社外からの同時アクセス数を 1 に制限。改善を確認。
16:53 JST 社外からの同時アクセス数を 2 に変更。少し遅くなることを確認。
16:59 JST 社外からの同時アクセス数を 4 に変更。明らかに遅くなる状況。次の試行策として、11/12(日)にアップグレードした JDK のダウングレードを決断。
17:42 JST JDK のダウングレードおよび仮想アプリケーションサーバの再起動を実施。改善を確認。
17:47 JST 社外からの同時アクセス数を 10 に変更。
17:53 JST 社外からの同時アクセス数を 20 に変更。
17:58 JST 社外からの同時アクセス数を 40 に変更。
18:01 JST 社外からの同時アクセス数を 80 に変更。
18:08 JST 社外からの同時アクセス数を初期設定に戻す。ここで全体のアクセス状況の復旧を確認。
18:24 JST スタックダンプを取得し、その他関連する仮想サーバの再起動を実施し完全復旧を確認。

サマーインターンサイトのアクセシビリティ対応の裏話

$
0
0

こんにちは、デザイングループ所属の小林です。サイボウズのサービスや製品に関するアクセシビリティ対応をしています。

先日、サイボウズはサマーインターンのWebサイトを公開しました。 このサイト、実はWebアクセシビリティについて、さまざまな配慮をしながらデザインやマークアップを行なっています。今回はその制作裏話をしようと思います。

サイボウズサマーインターンWebサイトの表紙

なぜアクセシビリティ対応?

サイボウズでは、アクセシビリティを「ユーザがチームにアクセスできる能力」と定義してアクセシビリティの取り組みを進めています。

理想的には、サイボウズが制作しているすべてのWebサイトや製品、サービスについてアクセシビリティの配慮が行われることが望ましいですが、いきなり規模の大きい既存のWebサイトのアクセシビリティを改善するのは大きなコストがかかります。また、デザイナーやエンジニアのアクセシビリティに関するスキルも、一朝一夕に身につくものではありません。

そこで、まずは規模が小さく新規に作成するページについて、少しずつアクセシビリティに考慮することで、今後のサイトの改善のヒントを得ながら、一人ひとりのスキルを高めていこうということになりました。サマーインターンサイトは、1ページのみ、かつ新規につくるページだったので、目的に合致していました。

制作体制

サマーインターンサイトは、数名のデザイナーが人事やメンターと一緒に制作しました。制作中の成果物に対して、自分がアクセシビリティの観点から数回レビューを行い、各デザイナーに問題点や改善方法をフィードバックしました。

アクセシビリティレビュー

今回、アクセシビリティについては、以下のような観点を考慮して、チェックや改善を行いました。

色のコントラスト比

ロービジョンのユーザや、屋外で日光があたる環境などでは、コントラスト比の低い色同士を区別することが難しい場合があります。アクセシビリティの国際基準であるWeb Content Accessibility Guideline 2.0(WCAG 2.0)には、文字色と背景色のコントラスト比を一定値以上にせよ、という基準があります。

もともと「エントリー」ボタンについては、WCAG2.0の基準を満たしていませんでした。また、ボタンにマウスホバーをしたときには、コントラスト比がさらに低くなるデザインになっていました。デザイナーに相談し、マウスホバーする前後どちらでも、コントラスト比の基準を満たすように色を修正しました。

以下の画像は、修正前のエントリーボタンです:

修正前のエントリーボタン

以下の画像は、修正後のエントリーボタンです: 修正後のエントリーボタン

キーボードによる操作

マウスを使うことが難しいユーザにとっては、代替手段として、キーボードでマウスと同等の操作ができることが重要です。

当初のデザインでは、キーボード操作したときのインジケータがCSSで消されており、 キーボードでどこを操作したのかがわからない状態だったので、インジケータを復活させました。

以下の画像は、Chromeでページ内のテキストリンクにキーボードフォーカスしたときの様子です。 ここにはブラウザデフォルトのインジケータが表示されるデザインにしています。Chromeでは水色のインジケータが表示されます: Chromeでテキストリンクにキーボードフォーカスした様子

また、「募集要項」のボタンをクリックした時に表示されるダイアログは、当初LeanModalというライブラリを使って実装していましたが、 LeanModalはキーボード操作の対応が不十分で、ダイアログの裏側の要素にフォーカスすることができてしまっていました。 これではマウスで操作できない部分をキーボードで操作できてしまいます。

キーボード操作に対応しているライブラリを探したところ、BootstrapのModalが対応できていたので、 ライブラリを変更し、ダイアログを開いているときには、ダイアログの裏側にフォーカスがあたらないようにしました。

ダイアログのマークアップ

BootstrapのModalに関する文書には、アクセシビリティに関するポイントがまとめられています。 この文書には、ダイアログのマークアップについて、以下のように記載されています:

  • role=“dialog"をつける
  • aria-labelledby=“…"に、ダイアログのタイトル部分のIDを指定する
  • aria-describedby=“…"に、ダイアログのボディ部分のIDを指定する

これらの属性をつけることで、ダイアログを開いた時に、スクリーンリーダーが、ダイアログのタイトルやボディを読み上げます。デザイナーにマークアップの意味を説明し、各属性を追加しました。

画像の代替テキスト

当初、メンターの画像にはalt属性を使った代替テキストとしてメンターの名前がついていました。この指定方法でも大きな問題はありませんが、スクリーンリーダーなどで読み上げた際には、メンターの名前が二重で読み上げられることになります。今回は読み上げの冗長さを解消するため、画像のalt属性には空文字を指定するようにしました。

メンターの紹介のスクリーンショット。メンターの画像の下にメンターの名前、所属、FacebookとTwitterのリンクが書かれている。

アイコンフォント

「メンター」セクションのFacebookとTwitterのアイコンには、Font Awesomeが使われています。これらのアイコンは当初、以下のようにマークアップされていました。

<a href="..." target="_blank">
  <i class="fa fa-facebook-official fa-lg" aria-hidden="true"></i>
</a>

この実装では、アイコンにラベルがついていないため、 スクリーンリーダーなどでアイコンを読み上げようとしても、読み上げが行われません。

Font AwesomeのAccessibilityに関するページには、aria-labelを使ってラベルをつけるように指示されています。 これをデザイナーに伝え、アイコンフォントにはラベルをつけるようにしました。

<a href="..." target="_blank" aria-label="facebook">
  <i class="fa fa-facebook-official fa-lg" aria-hidden="true"></i>
</a>

レビューの効果

自動チェックツールによるエラーが0個に!

今回は、aXeというアクセシビリティ自動チェックツール(Chrome拡張)を導入し、 上記に挙げた以外にも、様々なデザインやマークアップの修正を行いました。 最終的に、aXeによるアクセシビリティエラーや警告の検出数を0個にすることができました。

aXeの自動テストでエラーが0個になった状態をChromeの開発コンソールで確認する様子。

デザイナーのスキルアップ

デザイナーのスキルも向上しました。例えば、「概要」の会社の「場所」につけられた地図アイコンは、 Font Awesomeで実装しましたが、デザイナー自ら、aria-labelをつけてくれるようになりました。

<a href="https://cybozu.co.jp/company/access/#tokyo" target="_blank" aria-label="地図">
  <i class="fa fa-map-marker fa-lg" aria-hidden="true"></i>
</a>

デザイナーに修正をお願いするときのポイント

できるだけ公式情報を参照する

デザイナーに修正をお願いするときは、個人のブログやTipの紹介等のページを参照することはできるだけ避けました。 個人のブログなどで紹介されている技術情報の中には、アクセシビリティに配慮されていないものがあったり、一部の障がいや環境のみを取り上げて解説している場合があるためです。 また、場当たり的な内容を伝えているという印象を与えかねないことも懸念のひとつでした。

代わりに、W3Cの提供しているページや、Font Awesome、Bootstrapの公式サイトを参照するようにし、標準的な対応であることを強調しました。 この方法は、スキルアップを望んでいるデザイナーからも好評でした。

デザイナーとのやりとり。デザイナー「小林大輔さんのアクセシビリティの話はホント勉強になるなぁ。今まで作ったサイトも見直そーっと」と書かれている。

スクリーンリーダーで効果を説明する

マークアップの修正の中には、ビジュアルブラウザのみでは、効果が確認しづらい内容もありました。 スクリーンリーダーを使って実際にサイトを読み上げながらマークアップの違いをデザイナーに伝えることで 修正がどのような影響をもたらすのか、理解の手助けになりました。

サマーインターンでアクセシビリティの講義を受けませんか?

サイボウズでは、サマーインターンの参加者を募集しています。 サマーインターン期間中には、アクセシビリティの講義を開催する予定です。 より詳しくアクセシビリティの話をきいてみたい、アクセシビリティに関してスキルアップしたいという方は是非エントリーしてみてください。

エントリーをお待ちしています!

運用本部長を退任して Neco プロジェクトに専念します

$
0
0

前運用本部長の ymmtです。 1 月 1 日付けで運用本部長を退任して、cybozu.com のアーキテクチャ刷新プロジェクト Necoに専念することにしました。

blog.cybozu.io

この記事では運用本部を設立して 4 年間でやってきたことをまとめつつ、Neco プロジェクトについてお伝えします。思いを込めたら少し長めの記事になってしまいましたが、Neco で取り組んでいる Kubernetes を中心にした取り組みを末尾で紹介しています。

運用本部とは

自社の情報システムと顧客向けクラウドサービス cybozu.comの運用をミッションとする本部です。 4 年前に私が初代本部長となって設立したのですが、それ以前は開発本部所属のエンジニアが運用業務をしていました。

開発本部のミッションには運用業務が明示されていなかったこともあり、例えば情報システム部は存在していませんでした。 そのため数名のインフラ系エンジニアで 500 名近い社員の PC を、サービス運用の傍ら面倒を見ていました。

この体制のままでは人員やサービス運用の規模拡大に対応できないと考え、システムの運用と継続的な改善をミッションとして運用本部を設立したのです。

4 年間の歩み

運用本部は社内の情報システムを管轄する情報システム部と、自社クラウドサービスを管轄するサービス運用部で構成されます。 発足当初の所属社員数は 14 名でしたが、この 4 年で 37 名まで陣容を拡大しました。全体の社員数は 458名から 730 名に増加しています。

本部長として力を入れてきたことは様々ありますが、時間を要したという点では以下が挙げられます。

  • セキュリティ対策
  • 情報システム全体の見直し
  • サービス運用体制の強化

それぞれ少し詳しく解説していきますが、実現したのは本部内外の社員の方々ですのでそこはお間違いなく。

セキュリティ対策

cybozu.com は企業向けクラウドサービスですので、顧客データの保護は最優先課題です。サービス自体はもちろん、 それを扱う社内の情報システムのセキュリティも万全でなくてはなりません。

一方で、完璧なセキュリティというのもまたありえません。未知の脆弱性を突くゼロデイ攻撃がきたり、 ソーシャル・エンジニアリングで従業員が騙されてしまったり、最悪の場合内部犯行という可能性だってあります。

備えよ常にとセキュリティの原則と方針を示して、年々着実に対策を積み上げてきました。 結果として大きな事故なく運用してこれたことは素直に嬉しい点です。 下記資料は 2 年前のものですが、当社のセキュリティ対策の一部を解説したものです。

情報システム全体の見直し

情報システム部がなかったので、当初 2 年間は部長を兼務して部内の体制の整備と、社内システムの刷新を指揮してきました。

変わらなかったものはほとんどないというくらい、ネットワーク構成も PC やスマホの端末管理も電話等のコミュニケーションシステムも軒並み刷新したのですが、その背景にはサイボウズが目指す「100人いたら100通りの働き方」ができる会社を実現する必要があったことが挙げられます。

cybozu.co.jp

例として、当社は規模の割に拠点数が多いです。日本国内の主なオフィスで 4 箇所、海外にも 3 拠点ほどあります。それぞれの拠点の増床や引っ越しも頻繁で、常にどこかしら工事をしています。業務都合もありますが、働きたい場所で働けるというのを重視した側面もあります。なんにせよ、そのような頻繁な引っ越しや拠点の追加に情報システムが耐えられるよう、主要システムはデータセンターに集約し、各拠点は IT システムとしては端末化させました。

また、いつでも在宅勤務できる制度を支えるために、Cisco のビデオ会議システムを導入して、在宅・拠点間でいつでも会議ができるシステムを整備しました。 在宅勤務を支援するため、自宅作業用の PC やスマホを希望する全社員に支給する制度を導入したりもしています。

www.cisco.com

エンジニアの働く環境も、元(?)エンジニアの視点で必要十分になるよう整備しました。

cybozushiki.cybozu.co.jp

サービス運用体制の強化

cybozu.com を運用する人員の拡充に努めると同時に、当番制度の導入や待機手当などでサービス運用を支える社員に過剰な負担がかからないよう仕組みを整えました。 また、SRE チームとしてソフトウェアエンジニアが継続的にシステムの運用を改善できるよう取り組んでいるところです。詳しいことは以下の資料をご覧いただくとして、例えば緊急警告に対応する当番は、終日在宅勤務で OK で、いつ寝ていても良いです。

また Linux やオープンソース開発に関して著名な開発者である小崎資広氏、武内覚氏を技術顧問に招請しました。

blog.cybozu.io

さらに、サービスの成長に耐えられなくなることが予想されたシステムのアーキテクチャを見直して刷新するべく Neco プロジェクトを立ち上げた・・・のですが、こちらは残念ながらログ基盤の刷新を除き進捗が芳しくありません。理由ははっきりしていて、専従できる社員をあまり割り当てられなかったためです。

www.slideshare.net

これからの Neco プロジェクト

前置きが長くなってすみません。ここからが本題となります。

ここまで cybozu.com のアーキテクチャ見直しプロジェクト Neco は開発本部・運用本部合同のプロジェクトとして進めてきました。 しかし昨年、海外向けブランドである kintone.com を海外の IaaS に移し、海外現地のデータセンターで運用することを決め、発表しました。

topics.cybozu.co.jp

これに伴い Neco プロジェクトの一方の責任者である開発本部長 佐藤鉄平が、kintone.com の IaaS 化プロジェクトの責任者となりました。 IaaS 化プロジェクトは別の記事で今後紹介を予定しています。

専従者が少なく、責任者も抜けるということで Neco プロジェクト体制の見直しが必須となったわけです。一方良い状況として、昨年来エンジニア採用をエンジニア自身が力を入れて取り組むようにしてきた結果、ここのところ採用が絶好調です。お陰で Neco プロジェクトを専従体制で進める目途が立ちました。

そこで、私も思い切って運用本部長を退任し、Neco プロジェクト責任者として専従する体制とすることにしました。 後任の本部長を任せられる逸材に恵まれてのことではあります。

そういったわけで今年 1 月の頭からプロジェクトのゴールやスコープも整理しなおし、心機一転取り組んでいます。 全面 IaaS 化は先に紹介した kintone.com のプロジェクトが担うことになりましたので、Neco ではそこまでは踏み込まず、 自社データセンター環境の改善に集中します。

まずはハードウェアプロビジョニングの容易化とアプリケーションのコンテナ化をテーマに、以下の調査を進めています。

いずれも調査段階で採用を決めたというわけではないのですが、Kubernetes と Calico は採用するつもりで調査しています。 これらの成果をベースに、来年再来年で各種ミドルウェアのスケーラビリティや運用性を向上させ、現 cybozu.com からシステムを移動させていくつもりです。

最後に

というわけで、進捗が芳しくなかった Neco プロジェクトですが、本部長を退任してがっつり取り組んでいくことにしました。 cybozu.com は今や売り上げの 7 割近くを占める主要サービスで、今後も長く成長し続けることを見込んでいます。 Neco プロジェクトを完遂して、今後の成長を支えられるよう不退転の覚悟で取り組んでいきます。

この取り組みについて興味があるとか、協力したいという方はぜひご連絡ください。まだまだ人員募集中です! 以下は SRE 枠の募集ですが、Neco に興味ある旨お伝えいただければ問題ありません。

www.wantedly.com

毎月ミートアップイベントも開催していますので、そちらもお気軽にどうぞ。

福岡・広島に開発拠点を設立します

$
0
0

こんにちは、西日本開発部長の岡田(@y_okady)です。2018年1月1日付で大阪開発部と松山開発部を統合し、西日本開発部を設立しました。そして、福岡と広島の開発拠点設立を進めていくことになりました。

f:id:cybozuinsideout:20180124181057j:plain

私が2014年に大阪にUターンしてから3年半が経ち、住みたい場所で働けることによるQoLの向上を日々実感しています。大阪最高やでホンマ。

サイボウズでは「100人100通りの働き方」を理想に掲げており、みんな住みたい場所で働けばええやんという考え方が根付いています。一方で、住みたい場所にオフィスがないと「仕事を諦めて移住する」か「移住を諦めて仕事を続ける」かの選択を迫られるのが現実です。私は幸運にも大阪開発拠点設立のタイミングで移住が叶いましたが、より多くの人が住みたい場所で働けるように、西日本開発部の設立、そして福岡と広島に開発拠点を設立することを決めました。

働く場所の自由化

サイボウズでは「働く場所の自由化」を実現するために、チームメンバーが異なる拠点や在宅など離れた場所で開発するリモート開発を推し進めてきました。「働く場所の自由化」は企業にとっては災害対策や人材確保の面で避けられない問題ですが、一方でエンジニア個人にとってもQoL向上や生産性向上などプラスの効果が見込めます。現代の日本において、非常に重要な取り組みになるのではないかと思っています。

www.slideshare.net

なぜ福岡と広島?

福岡・広島ともに人口が多く、サイボウズにも多くの出身者が在籍しています。将来、社内のエンジニアがUターンを希望する可能性の高い地域だと考えています。実際、昨年まで松山開発部長を務めて現在西日本開発部副部長の水戸将弥が、2019年1月に地元広島へ移住することが決まっています。福岡についても、数年後の移住をぼんやり考えていると公言しているエンジニアがいます。

従業員が増えれば増えるほどそういった要望も増え、多様化していきます。また、社内に限らず、家庭環境の変化などで移住を考えている人は世の中にたくさんいると思います。福岡と広島に拠点を作ってもみんなの希望を叶えられるわけではありませんが、少しずつやれるところからやっていこうと考え、まずは福岡と広島から始めることにしました。

福岡と広島以外は?

そうは言っても、全国に拠点を作るまでみんなの希望を叶えられないようでは「働く場所の自由化」なんて夢物語でしょう。拠点を作るにはそれなりのコストもかかりますし、全国に拠点を作るのは非現実的です。

サイボウズには、無理すれば出社できなくはないけど天候や家庭の事情でリモートワークをする人がたくさんいます。オフィスにいても家にいても、たとえチームメンバーが全員バラバラの場所で働いていても、効率よく開発できる環境がここ数年でだいぶ整ってきました。そろそろ、オフィスへの出社が難しい場所でリモート中心で働くエンジニアが増えても良い頃かなと感じています。それが当たり前になれば、より多くの人の希望を叶えられそうです。

現在のところ、週2出社・週3在宅1ヶ月間限定の週5在宅が最大のリモートワーク活用事例で、これぐらいなら何の問題もないことが実感できました。これ以上になっても業務に支障はないと思いますが、たまにはチームメンバーと直接顔を合わせたいと思える職場環境にしたいですね。

We are Hiring!

西日本開発部設立に当たって、福岡・広島・リモートで働きたい開発エンジニアの募集を開始しました。「チームワークあふれる社会を創る」という理念に共感してくれる仲間を募集中です。住みたい場所に住んで、いろんな場所で働く仲間と力を合わせて、世界中のチームを支えるサービスを一緒に開発しませんか?ご興味ある方はWantedlyで「話を聞きに行きたい」ボタンを押していただけると嬉しいです。

また、今年は東京や大阪でのUターンMeetup開催や、福岡や広島でのMeetup開催・イベント出展を計画しています。サイボウズで働くことに興味を持ってくださったみなさんとお会いできる日を楽しみにしています!

www.wantedly.com

www.wantedly.com

www.wantedly.com

JMX で快適モニタリング環境を作ろう

$
0
0

こんにちは、アプリケーション基盤チームの青木(@a_o_k_i_n_g)です。

今回は Java アプリケーションのモニタリング等で活躍する JMX について記します。JMX を用いれば、きめ細やかでかつ手軽にモニタリングすることができます。もちろんサイボウズが提供するクラウドサービス cybozu.comでも JMX を活用して日々モニタリングを行っています。

モニタリングの重要性については今さら言うまでもありません。一方で現実のモニタリングは何かと手間がかかったり属人化してしまったりすることがありがちです。JMX は銀の弾丸ではありませんが、少なくともメトリクスの収集・提供部分に関しては利便性を提供してくれます。JMX ユーザーが少しでも増えるよう、この記事で紹介させていただきます。

JMX とは

JMX とは Java Management Extensions の略称で、Java アプリケーションを管理するための仕様です。この JMX を用いることで Java アプリケーションの任意の項目を外部から取得したり設定できたりします。

特別な設定をしなくとも JMX を用いてヒープや GC の情報は取得できますし、また、既存の数多くのアプリケーションが JMX に対応しています。例えば Jetty や Tomcat、 Solr、 Elasticsearch、 Hadoop、 Cassandra 等々、それぞれがアプリケーションに応じた細やかなメトリクスを収集できるようになってます。同様に多くのモニタリングツールやサービスが JMX に対応しており、 Zabbix や Prometheus、 Datadog や Mackerel 等を使えばスムーズに JMX によるメトリクス収集を行えます。

今回は、任意のメトリクスを外部から取得するケース、つまり一般的なモニタリング用途での使い方について紹介します。例として、サーバーにやってきたリクエストの数を取得する JMX の例を作ってみます。

手順は下記の通りで、小さなコードでモニタリング出来ることを示したいと思います。

  1. 取得したいメトリクスに沿った MBean インターフェースを作る
  2. MBean を実装したクラスを作る
  3. 2. のクラスを MBeanServer に登録する
  4. メトリクスを取得可能な場所で値を設定する
  5. モニタリングシステムでモニタリング項目を取得する

MBean インターフェースを作ろう

まず始めに、MBeanというインターフェースを作る必要があります。MBean(Management Bean)とは管理された Bean を意味し、ここではモニタリングに用いるオブジェクトということを表します。外部からアプリケーションの情報を取得する際はこの MBeanを介します。

作成したインターフェース名のサフィックスの MBeanは省略できないので注意してください。今回は RequestMonitorMBeanという名前でインターフェースを作ります。インターフェースには、JMX で取得したい項目を記述します。

publicinterface RequestMonitorMBean {
    long getRequestCount(); // リクエスト数を取得する
}

MBean を実装したクラスを作ろう

では RequestMonitorMBeanを実装したクラスを作りましょう。サーバーのリクエストは並列に来るものなので、内部カウンタは AtomicLongを利用します。

publicclass RequestMonitor implements RequestMonitorMBean {

    // リクエスト数を保持するカウンタprivatefinal AtomicLong requestCount = new AtomicLong();

    @Overridepubliclong getRequestCount() {
        return requestCount.get();
    }

    // リクエスト数をインクリメントするpublicvoid incrementRequestCount() {
        requestCount.incrementAndGet();
    }
}

MBeanServer に登録しよう

RequestMonitorクラスを作成したら、そのインスタンスを MBeanServerという MBeanを管理するためのクラスに登録する必要があります。オブジェクト登録時にオブジェクト名を任意に決められるので、わかりやすい名前を付与しましょう。オブジェクト名には様々な属性値を付与することができますが今回は省略します。下記コードはモニタリングを行う前の部分(通常はアプリケーション起動時)で処理されるようにします。

RequestMonitor monitor = new RequestMonitor(); // MBean オブジェクトの生成
String name = "com.cybozu.server:type=RequestMonitor"; // MBean 名
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); // MBeanServer を取得
mBeanServer.registerMBean(monitor, new ObjectName(name)); // 登録

メトリクスを収集しよう

ここまで準備が整ったら、あとは RequestMonitorクラスのインスタンスに、適切な箇所でリクエスト数をインクリメントしていくだけです。イメージ的には下記のようなリクエストを受け付ける部分にコードを差しこめば OK です。

一つ注意点があります。ここで使う monitorMBeanServerに登録したオブジェクトと同じオブジェクトを使うようにしましょう。このオブジェクトの受け渡しが手間になることもしばしばあるので、RequestMonitorのようなクラスはシングルトンにするという手もあります。

publicvoid doGet(Request req, Response res) {
    monitor.incrementRequestCount(); // リクエストが来たらカウンタをインクリメント...
}

モニタリングしよう

いよいよモニタリング出来る状態になりました。ここで、正しく外部からメトリクスを取得出来るか試してみます。JMX に対応していればツールは何でも良いのですが、手元で気軽に試すには jconsole が簡単です。jconsole は JDK に同梱されているのでターミナルで jconsole と打てば起動するはずです。

jconsole 起動

自身で起動したアプリケーションを選択して [Connect] を選択、その後 [MBeans] タブを開くと左ペインに MBeanオブジェクトがあるはずなので、そのオブジェクトのツリーを展開すると今回のメトリクスが表示されていることが確認できるかと思います。今回は実験でサーバーに 5 回アクセスしたので、[Attribute value] に RequestCount が 5 と表示されています。

メトリクス表示

実際に運用環境でモニタリングする際は RMI を用いてリモートから値を取得できるようにしましょう。RMI (Remote Method Invocation) とはその名の通りリモート環境の Java のメソッド呼び出しを行える仕組みです。起動オプションでプロパティを指定すれば RMI が有効になり、リモートで JMX メトリクスを収集できるようになります。簡単に動かすための例を示します。

  • -Dcom.sun.management.jmxremote
  • -Dcom.sun.management.jmxremote.port=18686
  • -Dcom.sun.management.jmxremote.rmi.port=18686
  • -Dcom.sun.management.jmxremote.authenticate=false
  • -Dcom.sun.management.jmxremote.ssl=false

ポート番号は適当な空いているポートを使いましょう。RMI は外部から接続できるとは言えインターネット経由で誰でも接続できる状態にしてしまうとセキュリティホールになるので注意してください。RMI を呼び出す際に認証することもできるので、環境に応じてセキュリティ設定をしましょう。仕様はこの辺りにあります。

ポートを開けたり、MBean周りのメソッドの実行などは Java Security Managerの権限を必要とします。必要に応じて権限も修正しましょう。

以上で、無事 JMX を用いてモニタリングを行えるようになりました。

サイボウズの JMX 活用例

サイボウズでの JMX の活用例を紹介します。

まずひとつ目は定番である JVM メモリ量です。単にプロセスの使用メモリ量を表示するのではなく、コードキャッシュ容量や OLD 領域、EDEN 領域などに区分けして可視化しています。メモリ状況はモニタリング用の特別なコードを書かずとも取得できるので、このようなグラフを作るのは非常に簡単です。

Datadog-Memory

こちらはとある Java プログラムの内部キャッシュ状況です。キャッシュのサイズや、キャッシュにエントリを挿入した回数、ルックアップ回数、ヒット率などを表示しています。

Datadog-Cache

最後に、ある非同期ジョブ実行サービスの各種ジョブの実行状況のグラフです。ジョブ実行キューが滞留してしまった際などはこのようなグラフを見ると異常な形をしていることが多く、ひと目で状況が理解できます。

Datadog-JobCount

プロセスの使用メモリ量などは JMX を使わずとも取得できますが、内部キャッシュのルックアップ回数のような細やかな値も取得できるのは JMX の面目躍如といったところだと思います。

終わりに

モニタリングはシステムの中でも無限に追求できてしまう部分です。アラートのしきい値をどれくらいにすれば良いのか、どのメトリクスを収集すれば良いのか、どうやって収集するか、モニタリングシステムのスケーラビリティ問題、等々追求しようとする限り終わりがありません。

個人的には、モニタリング環境がどれだけ整っているか、という指標はわりとシステムの成熟度を表しているのではないかと思います。アプリケーションがダウンした際に即座に対応できたり、負荷状況を確認できたりすることはアプリケーションをより良い方向に進化させるきっかけとなるからです。アプリケーション開発とモニタリング、この両輪が揃うことでシステムが成熟する方向に進むことができ、結果、開発者やユーザーの幸福度を増大してくれるものだと信じています。きっと、 JMX はその一端を担ってくれることでしょう。

それでは、良いモニタリングライフを!

参考

スレッド名にデバッグ情報を埋め込むと激しく捗る件

$
0
0

こんにちは、アプリケーション基盤チームの青木(@a_o_k_i_n_g)です。

今回、Java のちょっとしたデバッグテクニックを紹介したいと思います。Java で運用中何かトラブルが発生した場合、スレッドダンプを取得することはしばしばあると思いますが、スレッドダンプだけだとちょっと情報が足りないことがあります。今回はスレッドダンプから得られる情報を増やして、素早く障害対応したりデバッグに役立てる方法を紹介します。

まずはじめに: スレッドダンプの取り方

基本ですが、改めてスレッドダンプの取得の仕方を紹介しておきます。スレッドダンプを取得する対象のプロセス ID を仮に 12345 として、下記のように jstackコマンドを実行すればスレッドダンプが取得できます(※Linux上で操作する想定)。

$ jstack 12345

対象のプロセス ID は ps aux | grep javaや、jps -lコマンドで調べましょう。

一つ注意点があります。jstackを実行するユーザーは Java プロセス実行ユーザーと同じユーザーでなければなりません。仮にログインユーザーが aoking で、対象プロセスの実行ユーザーが cybozu なら下記のようにしましょう。

$ sudo -u cybozu jstack 12345

さて jstack を発行するとこんなスレッドダンプが取得できます(一部抜粋)。

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f31fc09c000 nid=0x57d4 in Object.wait() [0x00007f31ccd17000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000005cab10ff8> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
    - locked <0x00000005cab10ff8> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"main" #1 prio=5 os_prio=0 tid=0x00007f31fc01a000 nid=0x57c4 runnable [0x00007f3204b90000]
   java.lang.Thread.State: RUNNABLE
    at java.util.regex.Pattern.<init>(Pattern.java:1351)
    at java.util.regex.Pattern.compile(Pattern.java:1028)
    at com.cybozu.common.Sample.main(Sample.java:8)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

これはスレッドごとにスレッド名や優先度、スレッド ID、スタックトレース等を出力したものです。例えば例では mainスレッドと Finalizerスレッドがあり、mainスレッドでは java.util.regex.Patternクラスのインスタンス初期化をしている最中だということがわかります。

スレッド名に情報を埋め込もう

さて前述の例のスレッド名は mainFinalizerだったので一目瞭然でしたが、一般的なスレッド名は pool-472-thread-6392qtp278934944-22などで、実質意味を成さないものがよくあります。ここに任意の名前を埋め込んで、デバッグ効率を高めましょう。

早速例を見てみます。

long customerId = ...
String requestId = ...

Thread current = Thread.currentThread();
String originalName = current.getName();

String name = String.format("blob-add-%d-%s", customerId, requestId);
current.setName(name); // スレッド名をセットtry {
    addFile(...);
} finally {
    current.setName(originalName); // スレッド名を元に戻す
}

こちらは cybozu.com内で利用しているファイルサーバーの実装を元にした例です。このファイルサーバーに対してファイル追加を行うリクエストが来た時を想定しています。ここでは、ファイル追加処理であるという目印(blob-add の部分)と、顧客 ID、それからリクエスト ID というものをスレッド名に載せています。リクエスト ID とは cybozu.com へのアクセスごとに割り当てられる ID のことで、このリクエスト ID があればどのサーバーに何時にアクセスしたのかということがわかるようになっています。

この処理を入れておくと、スレッドダンプを出した際のスレッド名が blob-add-52153-1bd6bb9a88cc4adのようになり、スレッドダンプを眺める時に「ファイル追加処理が怪しい。顧客 ID 52153 のユーザーに影響が出ていそうだ、リクエスト ID を元に他のログを見よう」ということができるようになります。

これはあくまで例であり、アプリケーションによって必要な情報は大きく異なります。過去の障害調査の経緯などを参考にしてスレッド名に埋め込む情報を決めると良いでしょう。

処理が終わったらスレッド名を元の名前に戻しておくと良いです。理由はふたつほどあります。ひとつ目は、スレッドは処理が終わったらスレッドプール内で寝ているので、その寝ている時のスレッドと処理中のスレッドを見分けるため、という理由が一つ。もうひとつは、スレッドが再利用された時、スレッド名を適切な名前に設定していなかったらリクエストとスレッドの情報に乖離が生じることになってしまう、という理由です。

スレッドプールの名前を任意の名前にしよう

前章では Web アプリケーションをイメージしており、リクエストごとにスレッド名を指定する作りでした。しかしアプリケーションの種類によっては、スレッド個々についてではなくスレッドプール単位で情報が分かれば良い、というケースもあります。

Java でスレッドプールといえば ExecutorServiceが便利なので良く使われますが、こちらはデフォルトだと pool-7-thread-5のような味気ないスレッド名が使われます。ExecutorServiceを使う場合でもスレッド名を自由に設定することができるので、今回の例では新規にスレッドが生成される度にスレッドに番号を埋め込む方法を紹介します。

通常、ExecutorServiceの生成は Executors.newCachedThreadPool()あたりが良く使われます。このメソッドには java.util.concurrent.ThreadFactoryを渡すことができ、ThreadFactoryではスレッド生成時の処理を書けるので、そこで任意の名前を設定することができます。

コード例です。

publicclass CybozuExecutors {
    publicstatic ExecutorService newCachedThreadPool(String poolName) {
        // ここのスレッド名の %d にスレッド番号が自動的に割り当てられる
        ThreadFactory factory = new CybozuThreadFactory(poolName + "-thread-%d");
        return Executors.newCachedThreadPool(factory);
    }

    privatestaticclass CybozuThreadFactory implements ThreadFactory {
        privatefinal AtomicInteger counter = new AtomicInteger();
        privatefinal String threadNameFormat;

        private CybozuThreadFactory(String threadNameFormat) {
            this.threadNameFormat = threadNameFormat;
        }

        @Overridepublic Thread newThread(Runnable r) {
            // ここでスレッド名をフォーマットする
            String name = String.format(threadNameFormat, counter.incrementAndGet());
            returnnew Thread(null, r, name);
        }
    }
}

使う側ではこのようにして呼び出して ExecutorServiceを生成します。

ExecutorService executor = CybozuExecutors.newCachedThreadPool("mail-processor-" + customerId);

するとこの executorを使ったタスクのスレッド名は mail-processor-52153-thread-3mail-processor-52153-thread-27のようなスレッド名になり、顧客 ID 52153 のメール関連の処理を担当するスレッドということがスレッドダンプから一目瞭然になります。

注意点。CybozuThreadFactoryはあくまでサンプル用に書いたコードです。実際に使う場合は Guava の ThreadFactoryBuilder等を使うと安全でシンプルに ThreadFactoryを生成できるのでおすすめです。

最後に

スレッド名にデバッグ情報を埋め込むのは大変便利ですが、当たり前すぎるのかあまり紹介されないテクニックなので今回紹介させていただきました。適切な情報をスレッド名に指定しておくと原因や影響範囲が特定しやすくなり、結果的にユーザーへのサービス品質が高めることができると思います。

特にマルチスレッドなプログラムはデバッグに大変時間がかかることが多いです。スレッド名の改善だけで解決できるようになるわけではありませんが、解決困難な現象に立ち向かう時のひとつの手がかりとしては有用なので、ぜひ参考にしてみてください。

それでは、良いデバッグライフを!

React.js meetup #5 を開催しました

$
0
0

フロントエンドエキスパートチームの小林(@koba04)です。

2/1にReact.js meetup #5をサイボウズで開催しました。 当日は雪が降っていましたが、会場がいっぱいになるほどたくさんの人に集まって頂きましてありがとうございました。

https://reactjs-meetup.connpass.com/event/76375/

Contributing React! @koba04

最初に、まず私から「Contributing to React!」というタイトルで、Reactにコントリビュートする方法を紹介しました。

Reactにコントリビュートしようと思っても、コードが複雑でどうしていいのかわからないということもあると思います。 そのため、コントリビュートするための第一歩に必要な情報について紹介しました。

Reactでは、good first issueというラベル以外にも、タスクの難易度に対するDifficulty: mediumのようなラベルもあったり、誰かが取り組んでいるgood first issuegood first issue(taken)に変わったりと、コントリビュートしやすくするための取り組みが行われています。

また、コードに対するPull Requestを送る以外にも、ドキュメントに対する修正もコントリビュートの1つです。 英語で書く必要はありますが、足りないと感じたドキュメントをPull Requestすることもできます。

他にも、ドキュメントの翻訳を行うという形でのコントリビュートも可能です。 Reactのサイトでは、YarnやJestと同様にCrowdinを使った翻訳の仕組みがあることを紹介しました。

コードに対してコントリビュートしたいと思っても、Reactの複雑なコードベースをすぐに把握するのは難しいと思います。 Reactのサイトには、コントリビュートする人に対するドキュメントがあります。

これらのドキュメントを読んで、まずはgood first issueをやってみたり、不親切な警告メッセージがあればそれを修正したり、新しく警告を追加することはコードにコントリビュートする第一歩になります。

また別のトピックとして、v17で廃止されるライフサイクルメソッドと新しいContext APIについても、大きな変更であるため簡単に紹介しました。

f:id:cybozuinsideout:20180202175726j:plain

Static sites with create-react-app and Junctions @james_k_nelson

React ArmonyというReactを学ぶためのサイトを作っていたり、Junctionsというルーティングライブラリを作成されている@james_k_nelsonさんの発表は、 create-react-appから作成したアプリをJunctionsを使い、15分でブログにする内容でした。 ライブコーディング中心の内容で、個人的にライブコーディング見るのが好きなのでとても楽しめました。

Panel Discussion

というメンバーでパネルディスカッションしました。 多くの人がReactを使うときに悩む、サードパーティライブラリの選定やアニメーション、CSSについて、Redux、ルーティングについて話しました。 他にも、Reactを教えるときに難しいところやドメインロジックの置き場についても触れました。

実際にプロダクトを開発するときに、どのように考えてどうしているのかという話がたくさん聞けて、とても勉強になりました。

f:id:cybozuinsideout:20180202175741j:plain

LT

10 min ReactDOM Codebase Overview @malloc007

Reactのコードを読んでみたという内容のLTでした。 まぁ複雑ですよね...。

Redux のディレクトリ構成を考える @sottar_

Reduxを使ったアプリケーションのディレクトリ構造についてのLTでした。 Container ComponentとPresentational Componentの使いわけや、Action CreatorやReducerなどをどのように配置するのかというパターンについてのお話でした。 actionsとかreducersのような単位で分けることをRails-styleっていうんですね。

中大規模開発をReactで行う現場から伝えたいこと @mki_skt

規模の大きなフロントエンド開発の難しいところやそれをどのように解決していくのかというLTでした。 テストの必要性や共通Componentの管理方法、ライブラリのバージョン更新についてなど、放置しておくと破綻してしまう部分についての話で、Twitterでもツライという声で溢れていました。

まとめ

今回は天候を考慮して懇親会を事前に中止したのもあって、参加者同士で話す機会が取れませんでしたが、その分パネルディスカッションを長めにしたので参考になることが少しでもあれば嬉しいです。 次回に開催する際の参考のためにも、感想などあれば共有してもらえると嬉しいです。

サイボウズでは、フロントエンドに専門的に取り組みたいエンジニアも募集しています。 ご興味のある方は是非ご連絡ください。

また、関東以外でも積極的に採用を行っていますのでよろしくお願いします!


社内で「TE Cafe」を開催しました

$
0
0

こんにちは!品質保証部の中園です。

私が所属するテストエンジニアリング(以下、TE)チームでは、年に数回、社内メンバー向けにTEの活動報告や取り組みを紹介する「TE Cafe」を開催しています。

f:id:cybozuinsideout:20180205162755p:plain:w200

TEについてはこちらの記事をご覧ください。 blog.cybozu.io

2018年最初のTE Cafeは東京オフィスで開催され、ベトナム・上海・松山拠点に中継、さらに海外拠点では同時通訳をしながら開催しました!

今回は、TE Cafeでの発表内容をいくつかご紹介します。

2017年の振り返りと2018年の目標

TEチームは「枠組みを超えて品質/生産性の向上に貢献する」をミッションとして活動しています。

2016年は、各プロダクトにヒアリングをし、抱えている問題点を洗い出しました。

2017年は、問題を解決するためのツールの開発、導入支援を行いました。

テストを自動化するフレームワークやツールの開発は進んだものの、導入できたプロダクトはごく一部に留まりました。

反省点として、これらのツールや、自動化の導入事例を社内にアウトプットする機会が少なく、社内でのTEの活動の認知度がまだまだ低いということが挙げられます。

そこで、2018年は2017年に引き続き、「アウトプットを増やす」という目標を掲げます。

f:id:cybozuinsideout:20180205160344p:plain

TEの活動を積極的に発信することで、TEが開発したツールをプロダクトで使ってもらい、品質や生産性向上の助けとなることを目指します。

また、社内に留まらず、このCybozu Inside Out のブログ等で、社外への情報発信も積極的に行うことにしました。

自動テスト共通基盤について

TEでは、自動テスト共通基盤(Test Common Base、以下TCB)という、サイボウズ製品に合った自動テストのフレームワーク・ツールを開発しています。

TCBを使うことで、プロダクト毎に異なる手法で行われているテスト自動化を共通化して、導入/教育コストの削減や、ナレッジの横展開ができることを目標としています。

TCBには様々な種類のツールがあり、これらについて紹介しました。

以下に書いているものはその一部です。

  • eslint-config-tcb: サイボウズのESLint共通ルールを自動テストのテストコードに適用できるツール。

  • tcb-cli: TCBを使ったテストのサンプルファイルとフォルダを作成できるコマンドラインツール。

f:id:cybozuinsideout:20180205161727p:plain

  • tcb-api-rest: REST APIをテストする時に利用するツール。APIの実行から、結果の判定までできる。

  • tcb-hook: 自動テストの結果をkintoneのアプリやスレッドに投稿することができるツール。テストが失敗した時のスクリーンショットを投稿することも可能。

  • tcb-lerning: TCBを使った自動テストのコーディング方法を学習することができるツール。

f:id:cybozuinsideout:20180205161744p:plain

スクラム開発に対応した継続的性能検証(Garoon編)

最近、サイボウズでは多くのプロダクトがスクラム開発を採用し始めました。Garoonチームもその一つです。

スクラム開発では、2~3週間のサイクルで、出荷可能な製品の機能を作る必要があります。出荷可能な機能とそのテストだけでなく、性能要件も重要となってきます。

今までは、複数スプリント経過後~リリース前に性能検証を実施していました。

原因の特定に時間を要するような性能劣化が発見された場合、リリース遅延のリスクがありました。

そこで、日々性能検証を実行できるように、継続的な性能検証の自動化に取り組みました。

f:id:cybozuinsideout:20180205162158p:plain

テスト環境の構築、テストデータの挿入、テストの実行はJenkinsとScaleBenchを使い、テスト結果の確認はGrafanaを使っています。

今後はGaroonだけでなく、他のプロダクトへの普及も視野に入れています。

さいごに

上記に書いたことは、2017年のTEの活動のごく一部となります。

ベトナムTE、上海TEと良いチームワークを発揮し、少しずつですがサイボウズにテスト自動化の文化を浸透させています。

今年は、昨年の活動の実績を糧に、社内外へのアウトプットを積極的に行い、プロダクトの品質向上/生産性向上という使命を果たしていきたいと思います。

We are hiring!

TEでは一緒に働いてくれる仲間を大募集中です!

2016年 脆弱性報奨金制度を振り返って

$
0
0

こんにちは。Cy-PSIRT の山西です。

本エントリでは 2016 年に実施した脆弱性報奨金制度の結果、ご参加いただいた方向けのアンケートでいただいた質問への回答、2017年後半戦の取り組みについてまとめました。

ご報告くださった方、アンケートへ回答くださった方、ありがとうございました!

2016年の振り返り

定量情報

2016年のご報告数、報奨金のお支払金額は以下のようになりました。 f:id:cybozuinsideout:20170623135014p:plain

※ 数値の見方  外部からお寄せいただいた脆弱性情報は、受付 > 検証(再現確認)のプロセスを経て、脆弱性の認定手続きに進みます。  詳しくは過去の総括記事をご覧ください。

blog.cybozu.io

2016年報奨金額獲得ランキング

2016年にご報告いただいた脆弱性によって、獲得した報奨金額が最も多かったのは東内裕二(@yousukezan) 様でした。おめでとうございます。

f:id:cybozuinsideout:20170626092635p:plain

高額な脆弱性をご報告いただいた方ランキング

ご報告いただいた脆弱性が高額だった方ランキングも、全体のランキングに続き、東内裕二(@yousukezan) 様が 1 位でした。こちらもおめでとうございます。

f:id:cybozuinsideout:20170626092558p:plain

2016年のトレンド

前年以上に認定の可否を議論する機会が増えました。 2016年に社内で議論を重ねた報告については Cybozu Tech Conference 2016 で紹介した際の資料を公開しているので、よろしければこちらもご覧いただけると嬉しいです。

www.slideshare.net

それと同時に 2016年は、XSS の脆弱性がご報告数 1 位に返り咲きました。XSS単体では、前年より 10 件ほど多くご報告いただきました。

f:id:cybozuinsideout:20170623160617p:plain

新しい機能も追加されており、まだまだ「こんな脆弱性あるの?」と思ってしまうような脆弱性も眠っているかもしれません。 社内としてもそんな脆弱性達を撲滅するために新たな企画を考えておりますので、是非バグハンターの方々にもご協力賜りたいです。

アンケートでいただいた質問への回答

アンケートにご協力いただいた皆さま、貴重なフィードバックをありがとうございました。 いただいたご意見は今後の運営に生かすと共に、出来る限り要望にもお応えしていきたいと考えております。

報奨金のお支払い方法の検討

現在、報奨金のお支払いは口座振り込みでのみ行っております。口座振り込み以外で受け取りたいといった方もいらっしゃいましたので、その他のお渡し方法についても検討してまいります。

「脆弱性情報のご報告フォーム」で投稿したら自動返信をしてほしい

HPのご報告フォームに、自動返信の機能を早速設定いたしました。

認定までの期間を改善してほしい

現在は可能な限り 10 営業日以内に評価完了までご連絡できるように努めておりますが、報告が集中したり、報告いただいた内容が複雑だったりした場合には通常よりお時間をいただくケースもございます。ご了承ください。

修正の遅さを改善してほしい

申し訳ございません。セキュリティ品質の向上には日々努めておりますが、改修による影響範囲や脆弱性の与える深刻度によっては、改修が遅れる場合がございます。 また、クラウドサービスに比較してパッケージ製品はリリース間隔が長いため改修に時間がかかる傾向があります。 現在、そのような状況を解決するために開発プロセスの高速化に取り組んでおります。

修正までの期間が短い脆弱性の報奨金を上乗せしてほしい

CVSS の評価では、攻撃の容易度についても評価として考慮しておりますのでご要望にはお応え出来かねます。 また、前項で記載しておりますように、製品によってはリリースの間隔が異なり、改修期間で報奨金の上乗せをするのは難しい状況です。

2017年の取り組み

最大 5倍キャンペーン

最後のご案内になりましたが本日より報奨金の増額キャンペーンを実施いたします。

f:id:cybozuinsideout:20170623135407p:plain

詳細についてはキャンペーンページをご覧ください。

最大5倍キャンペーン

本制度の中では前例にない取り組みとなりますが、弊社の脆弱性に対する発見価値も高まってきており増額に踏み切りました。 対象製品は、Garoon、Office、メールワイズ がそれぞれ倍額。 kintone および、クラウド環境の共通管理画面(ログイン機能を含む)については、通常金額の 5 倍の額といたします。

報奨金獲得者のリアルタイムランキング

ご要望を多くいただいたため、リアルタイムランキングの実施を検討してまいります。 毎日の更新には対応できませんが、週 1 程度でランキングを公式 Twitter アカウント(@CybozuBugBounty)にてご案内いたします。 よろしければフォローをお願いします。最大 5倍キャンペーンで報奨金を獲得された方につきましても、こちらの公式アカウントにてつぶやいていく予定です。

バグハンター合宿

ご要望を多くいただいておりますので、今年の秋頃の開催を目指し検討を進めております。詳細は未定となっておりますが今しばらくお待ち下さい。

今後の活動について

今年の 1 月から Cy-PSIRT は、プロダクトセキュリティを担当するチームと社内のセキュリティ対策を行うチームを編成しました。よりセキュアに、そしてフットワーク軽く活動することを目標にしています。引き続きたくさんの脆弱性報告をお寄せいただけると幸いです。 報奨金制度に限らず「サイボウズにこんな企画してほしい」という要望がございましたら、 productsecurity@cybozu.co.jp までお気軽にご連絡ください。

よろしくお願いします。

脆弱性報奨金制度 | サイボウズ株式会社

スレッド名にデバッグ情報を埋め込むと激しく捗る件

$
0
0

こんにちは、アプリケーション基盤チームの青木(@a_o_k_i_n_g)です。

今回、Java のちょっとしたデバッグテクニックを紹介したいと思います。Java で運用中何かトラブルが発生した場合、スレッドダンプを取得することはしばしばあると思いますが、スレッドダンプだけだとちょっと情報が足りないことがあります。今回はスレッドダンプから得られる情報を増やして、素早く障害対応したりデバッグに役立てる方法を紹介します。

まずはじめに: スレッドダンプの取り方

基本ですが、改めてスレッドダンプの取得の仕方を紹介しておきます。スレッドダンプを取得する対象のプロセス ID を仮に 12345 として、下記のように jstackコマンドを実行すればスレッドダンプが取得できます(※Linux上で操作する想定)。

$ jstack 12345

対象のプロセス ID は ps aux | grep javaや、jps -lコマンドで調べましょう。

一つ注意点があります。jstackを実行するユーザーは Java プロセス実行ユーザーと同じユーザーでなければなりません。仮にログインユーザーが aoking で、対象プロセスの実行ユーザーが cybozu なら下記のようにしましょう。

$ sudo -u cybozu jstack 12345

さて jstack を発行するとこんなスレッドダンプが取得できます(一部抜粋)。

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f31fc09c000 nid=0x57d4 in Object.wait() [0x00007f31ccd17000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000005cab10ff8> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
    - locked <0x00000005cab10ff8> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"main" #1 prio=5 os_prio=0 tid=0x00007f31fc01a000 nid=0x57c4 runnable [0x00007f3204b90000]
   java.lang.Thread.State: RUNNABLE
    at java.util.regex.Pattern.<init>(Pattern.java:1351)
    at java.util.regex.Pattern.compile(Pattern.java:1028)
    at com.cybozu.common.Sample.main(Sample.java:8)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

これはスレッドごとにスレッド名や優先度、スレッド ID、スタックトレース等を出力したものです。例えば例では mainスレッドと Finalizerスレッドがあり、mainスレッドでは java.util.regex.Patternクラスのインスタンス初期化をしている最中だということがわかります。

スレッド名に情報を埋め込もう

さて前述の例のスレッド名は mainFinalizerだったので一目瞭然でしたが、一般的なスレッド名は pool-472-thread-6392qtp278934944-22などで、実質意味を成さないものがよくあります。ここに任意の名前を埋め込んで、デバッグ効率を高めましょう。

早速例を見てみます。

long customerId = ...
String requestId = ...

Thread current = Thread.currentThread();
String originalName = current.getName();

String name = String.format("blob-add-%d-%s", customerId, requestId);
current.setName(name); // スレッド名をセットtry {
    addFile(...);
} finally {
    current.setName(originalName); // スレッド名を元に戻す
}

こちらは cybozu.com内で利用しているファイルサーバーの実装を元にした例です。このファイルサーバーに対してファイル追加を行うリクエストが来た時を想定しています。ここでは、ファイル追加処理であるという目印(blob-add の部分)と、顧客 ID、それからリクエスト ID というものをスレッド名に載せています。リクエスト ID とは cybozu.com へのアクセスごとに割り当てられる ID のことで、このリクエスト ID があればどのサーバーに何時にアクセスしたのかということがわかるようになっています。

この処理を入れておくと、スレッドダンプを出した際のスレッド名が blob-add-52153-1bd6bb9a88cc4adのようになり、スレッドダンプを眺める時に「ファイル追加処理が怪しい。顧客 ID 52153 のユーザーに影響が出ていそうだ、リクエスト ID を元に他のログを見よう」ということができるようになります。

これはあくまで例であり、アプリケーションによって必要な情報は大きく異なります。過去の障害調査の経緯などを参考にしてスレッド名に埋め込む情報を決めると良いでしょう。

処理が終わったらスレッド名を元の名前に戻しておくと良いです。理由はふたつほどあります。ひとつ目は、スレッドは処理が終わったらスレッドプール内で寝ているので、その寝ている時のスレッドと処理中のスレッドを見分けるため、という理由が一つ。もうひとつは、スレッドが再利用された時、スレッド名を適切な名前に設定していなかったらリクエストとスレッドの情報に乖離が生じることになってしまう、という理由です。

スレッドプールの名前を任意の名前にしよう

前章では Web アプリケーションをイメージしており、リクエストごとにスレッド名を指定する作りでした。しかしアプリケーションの種類によっては、スレッド個々についてではなくスレッドプール単位で情報が分かれば良い、というケースもあります。

Java でスレッドプールといえば ExecutorServiceが便利なので良く使われますが、こちらはデフォルトだと pool-7-thread-5のような味気ないスレッド名が使われます。ExecutorServiceを使う場合でもスレッド名を自由に設定することができるので、今回の例では新規にスレッドが生成される度にスレッドに番号を埋め込む方法を紹介します。

通常、ExecutorServiceの生成は Executors.newCachedThreadPool()あたりが良く使われます。このメソッドには java.util.concurrent.ThreadFactoryを渡すことができ、ThreadFactoryではスレッド生成時の処理を書けるので、そこで任意の名前を設定することができます。

コード例です。

publicclass CybozuExecutors {
    publicstatic ExecutorService newCachedThreadPool(String poolName) {
        // ここのスレッド名の %d にスレッド番号が自動的に割り当てられる
        ThreadFactory factory = new CybozuThreadFactory(poolName + "-thread-%d");
        return Executors.newCachedThreadPool(factory);
    }

    privatestaticclass CybozuThreadFactory implements ThreadFactory {
        privatefinal AtomicInteger counter = new AtomicInteger();
        privatefinal String threadNameFormat;

        private CybozuThreadFactory(String threadNameFormat) {
            this.threadNameFormat = threadNameFormat;
        }

        @Overridepublic Thread newThread(Runnable r) {
            // ここでスレッド名をフォーマットする
            String name = String.format(threadNameFormat, counter.incrementAndGet());
            returnnew Thread(null, r, name);
        }
    }
}

使う側ではこのようにして呼び出して ExecutorServiceを生成します。

ExecutorService executor = CybozuExecutors.newCachedThreadPool("mail-processor-" + customerId);

するとこの executorを使ったタスクのスレッド名は mail-processor-52153-thread-3mail-processor-52153-thread-27のようなスレッド名になり、顧客 ID 52153 のメール関連の処理を担当するスレッドということがスレッドダンプから一目瞭然になります。

注意点。CybozuThreadFactoryはあくまでサンプル用に書いたコードです。実際に使う場合は Guava の ThreadFactoryBuilder等を使うと安全でシンプルに ThreadFactoryを生成できるのでおすすめです。

最後に

スレッド名にデバッグ情報を埋め込むのは大変便利ですが、当たり前すぎるのかあまり紹介されないテクニックなので今回紹介させていただきました。適切な情報をスレッド名に指定しておくと原因や影響範囲が特定しやすくなり、結果的にユーザーへのサービス品質が高めることができると思います。

特にマルチスレッドなプログラムはデバッグに大変時間がかかることが多いです。スレッド名の改善だけで解決できるようになるわけではありませんが、解決困難な現象に立ち向かう時のひとつの手がかりとしては有用なので、ぜひ参考にしてみてください。

それでは、良いデバッグライフを!

大阪で「SRE」「生産性向上」「スクラム/アジャイル」を肴にミートアップ!

$
0
0

こんにちは。隙あらばコネクトしようと考えている風穴(かざあな、@windhole)です。

6月17日(土)に、サイボウズ大阪オフィスにて「Cybozu Meetup Osaka #2 SRE、生産性向上、スクラム/アジャイル」を開催しましたので、レポートします。

f:id:cybozuinsideout:20170713123730j:plain

サイボウズのミートアップ

2017年2月からスタートした「Cybozu Meetup」は、サイボウズのエンジニアとカジュアルに交流する場として企画、開催しているイベントシリーズです。会場はサイボウズのオフィスなので、社内の雰囲気や社員の様子を、実際に肌で感じて頂ける機会でもあります。

第1回は、東京と大阪をTV会議システムで接続して同時開催しましたが、運営上、やや難しい面があることが分かり、それ以降は別々に開催することになりました。その後も東京は月1回のペースで開催していますが、大阪は今回が2回目ということになります。

久しぶりの大阪開催ということで、東京の3回分のコンテンツ(SRE、生産性向上、スクラム/アジャイル)をまとめてお送りする「豪華版」(自称)として企画しました。

開催時間も、東京は毎回平日夜ですが、今回の大阪開催は、土曜日の午後として、3つのトークをゆっくり聞いていただく趣向に。

SRE

f:id:cybozuinsideout:20170713123939j:plain

運用本部長の山本 泰宇(@ymmt2005)は、サイボウズのSRE(Site Reliability Engineering)チームについて紹介。オフレコなトピックも交えつつ、話はアーキテクチャ刷新プロジェクト「Neco」にまで及びました。

生産性向上

f:id:cybozuinsideout:20170713124008j:plain

生産性向上チームの宮田 淳平(@miyajan)は、自身が2015年8月に立ち上げた同チームについて、具体的な例を交えて紹介。会場からは「生産性向上のための新しいツールを導入する際に、抵抗勢力が出てきたらどうしてますか?」といった、生々しい(?)質問が出ました。実はこれ、東京開催のときも同様の質問が出ていました。サイボウズの生産性向上チームは、各開発チームからの相談や要望を受けて活動しているので、今のところ、そういう課題は出ていないのでした。「人は、他の人から言われたことをやらされるのは楽しくないですよね。なので、当人たちがやりたいと思うところから改善していくのが良いのでは」(宮田談)。

スクラム/アジャイル

f:id:cybozuinsideout:20170713124026j:plain

自身が旗振り役となって、サイボウズの開発チームへのスクラム導入を進めてきた天野 祐介(@ama_ch)は、その経験を紹介しました。会場からは、改善スプリントについての悩みや、KPTのやり方、トレーニングへの取り組み方などについて質問が出ました。スクラムは、悩みが尽きないですね……。

交流タイム

トークセッションの後は、ドリンク片手におやつをつまみつつの交流タイム。今回は、3つの異なるテーマを詰め込んだため、テーマごとに参加者が分断されるかも……とも思ったのですが、蓋を開けてみると、複数のトピックに関心がある方がほとんどで、参加者同士でも大いに話が盛り上がっていました。

f:id:cybozuinsideout:20170713124050j:plain

次回は9月?

次の大阪開催は未定ですが、3カ月に1回は……ということで、9月に開催できたらと考えています。ご興味ある方は、connpassグループ「Cybozu Inside Out」をチェックして頂ければ。

また、「こんなテーマを聞いてみたい!」とか「今度は松山で開催してほしい!」といったご要望があれば検討いたしますので、遠慮なくお知らせください。

おまけ:
開催前夜は、チームワークを高めるべく「たこ焼き」に挑戦しました。 f:id:cybozuinsideout:20170710070117j:plain

ではまた。

x86/x64最適化勉強会8 レポート

$
0
0

サイボウズ・ラボの光成です。

今回は2月17日に開催された「x86/x64最適化勉強会8」の模様についてお伝えします。 第7回からなんと約3年振りです。

今回の発表内容はAVX-512周りの話が2件、命令の正確なレイテンシの話、年明けから世間を騒がせているMeltdownとSpectreの話が2件でした。

以下、それぞれの発表内容について簡単に解説します。

AVX-512関係

私の発表は「AVX-512(フォーマット)詳解」でした。 AVX-512はまだSkylake-Xなどの一部のCPUにしか搭載されていませんが、今後徐々に採用が増えるでしょう。

(注意)21ページの「3値論理」は「3項論理」の方が適切です。

AVX-512のレジスタ構成や基本的な命令セットを説明した後、AVX2までにはなかったマスクレジスタ、静的丸めモード、ブロードキャストなどの解説をしました。 マスクレジスタは便利に使えそうです。 AVX-512のエンコーディングはxbyakを開発するときにいろいろ調べたものを紹介しました。

資料をほぼ作り終えたところで、そういえば昔@tanakmuraさんが解説されていたようなと探したらAVX-512 Advent Calendar 2014が見つかりました。 ほとんど内容がかぶってたのですがまあすいません。disp8*Nの話はあまり見たことがないのでよしとしてください。

@kaityo256さんの発表は「AVX2/AVX-512を用いたLennard-Jones系 ポテンシャルの力計算のSIMD化」でした。

分子動力学法を用いて泡のシミュレーションなどをするそうです。その際に必要なポテンシャルの計算をメモリ律速になりがちな部分をSIMDを用いていかにうまく最適化するかという話でした。 キャッシュラインを意識しつつ何度もデータレイアウトを変更したり、gather/scatterをうまく使って高速化した経過を紹介しました。 どうやったのかという工夫の話はとても参考になります。 AVX-512はコンパイラの自動最適化に任せられる部分が増えてきて楽できそうとのことです。

@slankdevさんは残念ながら体調不良でお休みでした。またの機会にお願いしたいです。

命令速度の計測

@tanakmuraさんの発表は「命令単体の性能を計測する」でした。 高速化に必要な基本的な情報として各種命令のスループットやレイテンシがあります。 公式ドキュメント、Agnerさんのドキュメントなどの情報には一長一短があって自分で計測ツールを作ったとのことです。

vmovdquの境界をまたいだときのロード時間の違いの一覧表は珍しいです。依存関係を加味したパズルチックな命令配列は面白いです。 rdtscはTurbo boostなどの影響を受けるので__NR_perf_event_openのsyscallをして測定すると楽とのことです。

Meltdown & Spectre

MeltdownとSpectreは今年初めに話題になった(対策が現在進行中の)近年の多くのプロセッサに潜在的に存在する脆弱性です。 攻撃対象のメモリの情報を、キャッシュに載ったか否かというサイドチャネル攻撃によって推測する手法です。 お二人には連続講義という形でお願いしました。

f:id:cybozuinsideout:20180219165042j:plain

@satoru_takeuchiさんは「図解でわかるSpectreとMeltdown」、 @mhiramatさんは「SpectreBustersあるいはLinuxにおけるSpectre対策」でした。

基本的に投機実行や分岐予測といったCPUの高速化機構に対する攻撃なので、その対策は速度が落ちる方法になるのが悲しいところです。 ただ速度低下は複雑な要因が絡むため各自のシステムで評価しないと分からないことも多く、マイクロベンチマークで一喜一憂しないように、とのことです。 これから登場するであろう対策されたCPUに期待です。

Bounds Check Bypass対策のArray_index_nospecや、Branch Target Injection対策のRetpolineの詳細な解説は勉強になりました。 特に後者はROP(return oriented programming)という攻撃手法を脆弱性対策に使うという逆向きなアイデアは面白いです。

FILL_RETURN_BUFFERについては、Skylakeがそこまで頑張って高速化しようとしているのになんて無慈悲なという感想です。

「完全対応はできないけどどうしましょう」という質問に対して「バッファオーバーフローと同じでプログラマが原理を理解して一つずつ対応していくしかない」という答えになるほどと思いました。

LT

@yottuiさんは「AVX512自動ベクトル化」の話でした。gccやclangは結構頑張ってベクトル化してくれるけどVisual Studioはあんまりしてくれません。ただsin関数はVSの方がベクトル化してたのこと。Intelコンパイラも超越関数のSIMD版を持っています。

@makoto_katoさんはARMv8 Cryptography Extension & Performanceの発表でした。 ARMv8には暗号用専用命令が搭載されていて、それを利用するとSHA2ではCorex-A53(1.2GHz)がCore i7-7700のソフトウェア実装より速いので是非みなさん使いましょうとのことです。 SHA2用命令はIntelならGoldmontに搭載されています。

@shinhさんはTensorFlow XLAの話でした。 TensorFlowは機会学習フレームワークでPythonでコードを書くと依存グラフを生成し、XLAでコンパイルして並列実行するという仕組みです。 ただ計算時間の大半をmatmul(行列演算)が占めるので今のところ効果は小さいかなという発表でした。

@ksmakotoさんは、@xoreaxeaxeaxさんが作ったmovfuscatorというCプログラムをmov命令のみにコンパイルするツールを紹介しました。Stephen Dolanさんがmov命令がチューリング完全だよという論文(mov is Turing-complete)を出したところ、それをまじめに?実装してみたというものです。 少し前に話題になったのですがDOOMというゲームを1フレーム描画するのに7時間かかるそうでいろいろ「頭おかしい」です。

動画と懇親会

今回の勉強会はProject92@makotokogaさんがビデオ中継と配信をしてくださいました。 youtubeでごらんいただけます。

会場の隅から斜めに撮られたスクリーン画像をリアルタイムで台形補正したり、発表者とプレゼン資料が同時に表示されたりといった機能に驚きました。配信中も細かく調整されていて素晴らしかったです。

懇親会はさくらインターネット社がフードスポンサーになってくださいました。

どうもありがとうございました。

f:id:cybozuinsideout:20180219165051j:plain

まとめ

今回はMeltdownとSpectreという旬の話題を扱ったせいもあるのか80人を超える参加者で大盛況でした。 活発な討論もよかったです。もちろん発表者の方々にも感謝です。 今度はそんなに空けずに開催したいものですね。

Viewing all 681 articles
Browse latest View live