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

 

#osc20do でサイボウズ開発本部各チームの文化とコミュニティについてお話ししました

登壇者 4 名が談笑している様子
「ぼく、サイボウズで優勝したよ!」で優勝している 4 人の様子

西原(@tomio2480)です.5/1(金) に入社して以降,ここに記事を書くのははじめてです.地方ITコミュニティのことを 10 年くらいやっていて,お仕事でもそこをやっていくことになりました.
 
さっそくですが,イベントの登壇報告をいたします.6/27(土) Open Source Conference 2020 Online/Hokkaido に参加してきました.タイトルにもある osc20do は本イベントで用いられたハッシュタグです.イベント名が長いので,これ以降は便宜的に osc20do と表記します.
https://event.ospn.jp/osc2020-online-do/event.ospn.jp

Open Source Conference は一般に OSC と呼ばれていて,一年とおして各地で開催されています.北海道地区オフライン開催の代替としてオンライン開催となったのが今回のイベントです.サイボウズからはセッション枠とミーティング枠の 2 枠をいただいてお話ししてきました.また,一般社団法人 LOCAL が担当する枠にも自分含めサイボウズ社員が 2 名登壇しました.
 

 
いずれも手応えを感じるいい時間になったと聞いています.特に低レイヤ相談室は延長戦に次ぐ延長戦で合計 3 時間ちかくの濃い時間を過ごすことができたとようです.私は裏でコミュニティ関連の話にちょっと出ていたり,スタッフ業だったりでまともに参加できなかったのですが,話を聞く限りでは sat さん (@satoru_takeuchi) と内田さん (@uchan_nos) の知識/経験量をなくして成り立たないコンテンツだったということでした.北海道出身として北海道関連のイベントで盛り上げていただいてありがたい限りです.
 
さて,今回はこの盛りだくさんのコンテンツから,西原が登壇したものに絞りレポートします.今回触れないコンテンツについても公開可能な物に限り,主催である OSPN の YouTube で視聴することができます.
https://www.youtube.com/channel/UCEPkrGMghsXnoG1LffgjMJg  

ぼく、サイボウズで優勝したよ!──地元ゆかりの社員が本音でサイボウズを語る

登壇の様子を Twitter 上に残しましたが,自分で撮ったのに謎の表情がスクショにおさまってしまいました.
 
今回は北海道に縁のある 3 名とサイボウズ歴の長い 1 名,合計 4 名でお話しをさせていただきました.
 

  • 今野遼太 @rkonno / 開発本部 モバイルチーム
  • 笠間保鷹 @b4h0-c4t / 開発本部 フロントエンドエキスパートチーム
  • 上岡真也 @ueokande / 開発本部 コネクト支援チーム
  • 西原翔太 @tomio2480 / 開発本部 コネクト支援チーム
  • (配信担当) 風穴江 @windhole / 開発本部 コネクト支援チーム

 
よく試された道民であればわかると思いますが,今回のタイトルは道民に愛されしフレーズを RESPECT したものになっています.実はスライドの中にもいくつかそんなフレーズを盛り込んでおきました.
 
セッションの内容は「サイボウズに入社したきっかけ」「入社前の印象と入社後のギャップ」「サイボウズ社員として北海道でやりたいこと」という 3 点の質問を基軸に「サイボウズと自分」を座談会形式でお話しさせていただきました.
 
今回のねらいは「サイボウズで働く人々を通じてサイボウズを知ってもらう」ことです.そのためにも北海道民がたくさん参加するであろう osc20do では道民の感覚を持った人たちの登壇が不可欠でした.特に北海道の OSC は学生が多いこともあって,そもそも働いている人の生態を知る機会として使って欲しい!という思いも込めておりました.
 
座談会形式でお話しすることでそれぞれの所属チームの違いや,サイボウズとの出会いの違い,出身地や住んでいた地方地域の違いを比べながら,様々な視点からの経験を伝えられたかなと感じています.ざっくり言うと「会社に入るまでの動きと共感」「チームごとに異なる仕事の発生の仕方」「専門性の生かされ方」「北海道に対する思い」この辺りが話の中心だったかな,というところです.
 
詳しくは YouTube で動画をご覧ください! www.youtube.com  

[北海道企画]北海道出身のエンジニアが学生の質問に答えます!

こちらの企画は一般社団法人 LOCAL が担当するイベントで,北海道の IT 系を学ぶ学生たちが所属する LOCAL 学生部の部員に向けたセッションでした.実は登壇者 5 名はいずれも LOCAL 学生部を卒業したエンジニア他で構成されています.サイボウズからは 2 名登壇しました. (ちなみに,竹内さんは LOCAL 学生部の元部長です.)
 

  • 竹内健人(けんつ) @lrf141 / 開発本部 Shash/CyDE-Cチーム
  • 西原翔太 @tomio2480 / 開発本部 コネクト支援チーム
  • 他 LOCAL 学生部 OB 3 人

 
セッションでは,LOCAL 学生部の現役メンバーから出た質問に対してそれぞれの立場から答えていきました.登壇者全員が北海道で生まれ育ち,コミュニティ運営活動の経験もあり,いずれも工業大学を出ているなど共通点は多かったのですが,回答にはそれぞれの色がでました.当然社会に出てからやってきた仕事はそれぞれ別々で,その違いが大きく出たコメントになったなぁという印象です.
 
学生からは研究と仕事の関係や,学ぶ分野を広げるべきかどうかといった学習や就職に関係する質問もあれば,北海道と関東関西の暮らし的な違いや北海道ならではの勉強会文化など北海道と本州の比較についての質問もあり,未来を想像する上でのヒントを得たい!という思いが伝わってくる質問が多かったと感じています.
 
そろそろ一回り違う子達が後輩にあたる頃合いです.彼らとは育った時代背景が違うし,疑問に感じることも違うだろうから,質問への回答も困るかもしれないと想像していました.しかし,いざ蓋を開けてみれば,自分も感じていたような疑問や悩みが出てきました.同じ北海道で生まれ育った人たちだと,時代を超えて抱く疑問も似通うのかもしれません.
 
しかし,ひとつここで思ったのは,自分たちがぶつかった課題を解決しないままに置いてきたから,同じ課題にぶつかっているのかもしれないということです.誰もが通る道とよく言いますが,それは今まで通ってきた人の怠慢でつらいままのこともあるのではないかということです.自分にできることはどんどんやっていかなきゃな,と考えさせられるセッションでした.
 
こちらもやはり詳細は動画をご覧いただければわかりやすいです.
www.youtube.com

持っている知見は惜しみなく発信しよう

以上,自分の登壇したセッションについてのレポートでした.
 
今回パネルディスカッションというか座談会というかを 2 つやってみて,登壇者同士が事前にどれだけ交流を取れるかが鍵だと感じました.サイボウズのセッションは社内向けにプレ開催をやっていて,ここでいろいろ登壇者同士で意見交換ができたのがデカかったと思います.こういった取り組みによって阿吽の呼吸感を生み出せれば,いい回答をお互いに引き出していくことができるのかなと思いました.(LOCAL のセッションも事前の顔合わせをしています.こっちは内輪感が出過ぎないように注意するぞ!という決起集会でしたが)
 
もちろん,聞き手側が何を求めているかということを知っていないと,独りよがりになってしまいます.しかし,座談会だと登壇者半分,視聴者半分で参加できるので「興味深く聞けることを引き出す視聴者」としての役割を担えます.ここを意識すると,当日も面白い流れを生むことができそうです.
 
サイボウズセッションを道産子勢で固めたのは正解でした.はじめての顔合わせでも,わかりあうための前提がある程度整っていて,視聴者とも同じ視点をわざわざ作る必要がありませんでした.これからの OSC でも各地の出身者を集めて座談会ができると,その地方の参加者に喜んでもらえる情報発信ができるのではないかと,今回の登壇を通じてより強く感じました.
 
どれだけの効果があったかは分かりませんが,こうしてサイボウズ社員の魅力を伝えられる場を設定できたこと,各地方の人とわかりあえるきっかけの場を作れたことはサイボウズに所属する一員として願ったり叶ったりです.これからもこういった視点の取り組みを続け,地方の IT エンジニアや IT エンジニアを目指す人たちに役立つ活動を展開していきたいと考えています.どうぞよろしくお願いいたします!


おまけ情報

7/18(土) 14:00 - LOCAL Developer Day Online ’20 /Security にて「地方ITコミュニティとの関わりに何を求めていたのか」というタイトルで西原が登壇します.オンライン全盛になりつつある今,地方ITコミュニティとはそもそもどんな役割を果たしていたのか,ということについて考える時間にします. local.connpass.com

 

AWS移行が完了したUS版kintoneと、これからの挑戦

こんにちは、@ueokandeです。 先日6月21日に、日本のデータセンターで運用していたUS版kintone (kintone.com) が、ついにAWSに完全移行しました。 このAWS移行プロジェクトは2018年にスタートし、2019年秋の新規顧客向けリリースを経て、この6月に全US顧客のAWS移行が完了しました。 本日はUS版kintoneのAWS移行と、これからのチャレンジについてお話します。

モノリスシステムからの独立

AWS移行プロジェクトには、2つの背景があります。

1つはUSを含めたグローバル市場の拡大です。 現地のUSリージョンで運用することで、ユーザーからのレイテンシを小さく抑えることができ、より安定したサービスを提供できます。 またこれを機に販売管理システムもUS市場向けに新規開発し、現地に合わせた販売戦略を計画できるようになりました。

2つめの背景として、クラウドネイティブ時代の、開発、運用フローの確立です。 国内に提供しているcybozu.comは、インフラシステムのモノリス化により、開発、運用面で新しいチャレンジがしにくいという課題があります (国内インフラに関してはNeco/Manekiチームによるインフラ刷新が進んでいます)。 AWS移行プロジェクトでは、国内のcybozu.comから独立して開発がスタートしました。 国内インフラの運用経験を活かして、高速なリリースフローや、コンテナアプリケーションの運用などに取り組んできました (具体的な取り組みは過去の記事を御覧ください)。

US版kintoneのこれから

移行プロジェクトが無事終了し、チームは6月いっぱいで解散しました。 しかしチームがなくなっても、サービスが終了するわけではありません。 解散後は元チームメンバーの数名がkintone開発チームに参加し、今後はkintone開発チーム全体でUS版kintoneをメンテナンスします。

開発者と運用者が同じチームに属することで、機能開発から、リリース、運用までの一連のフローが、同じチーム内で完結します。 チーム内で意思決定がしやすく、メトリクスの追加やパフォーマンスチューニングなど、新しいチャレンジへのハードルが下がります (従来のプロダクトでは、運用チームと開発チームが明確に分かれています)。

これまでkintoneの機能開発をしていたメンバーが運用に携わることで、真のサイトリライアビリティに向けた取り組みがスタートできます。 AWS移行プロジェクトではできなかった、今後の取り組みについては、以下のようなものがあります。

  • アプリケーションやユーザー視点でのSLI/SLOの検討
  • Microservicesなどの脱モノリス
  • 分散トレーシングなどのクラウドネイティブな監視の仕組み

US版kintoneの開発、運用体制は、技術的だけでなく組織的にも、社内のカナリアリリースに当たります。 そして溜まった知見は、将来のNeco/Maneki移行に活かす予定です。

もっとAWS移行について知りたい人は

7月14日(火)にMeetupを開催します! 当時のプロジェクトメンバーから、US版kintoneのアーキテクチャや、移行の裏側についてお話します。 YouTube Liveによるオンライン配信予定なので、興味のある人はぜひご視聴ください!

cybozu.connpass.com

 

サイボウズには「社内コネクト」を支援するチームがいます

社内イベントの様子
2019年開催のハッカソンでの1枚
こんにちは!プロ野球がついに始まりましたね! 開発本部社内コネクトチームのhokatomoです。

今日は私が所属している「社内コネクトチーム"WASABI"」の紹介です。 このチームは「社内開発イベントを通じて、製品の垣根を超えた輪を広げていく」をミッションにし、活動をしています。

具体的な活動

  • 社内(主に、開発本部・運用本部)の繋がりを作る・深めるためのイベントの企画運営
  • 多拠点に開発・運用のメンバーがいるので、自チーム以外でもそれぞれのことを知り興味を持つきっかけを作る
  • よりよいチームワークに繋げる

を意識し、社内イベントの企画開催運営を行っています。

なんで「WASABI」なの?

もともとの名前は「社内開発イベントPJ」だったのですが、

  • 「社内開発イベントPJ」が呼びづらい
  • (WASABIのきっかけとなったイベント)フリージャンルのLTやりたい→みんなに話してもらうイベントに→寿司食べながら聞きたい→話しながら寿司を食べる(※)→話す+寿司🍣→話スシ(!)→寿司といえばワサビ→WASABIチーム誕生!

などの経緯や事情があり「WASABI」という名前になりました!

※2020年6月現在フルリモート開催なので寿司は出ていません。

WASABIチームは現在国内の3拠点、4人💪

それぞれ別のチームを兼務し、

  • モバイルエンジニア(東京)
  • フロントエンドエンジニア(松山)
  • QAエンジニア(大阪)
  • 技術広報(東京)

といったメンバー構成です。 リアルで全員集合したことは多分まだないです。

どんな社内イベントを開催しているかと言うと👀

社内LTからPodcast、成果発表会からハッカソンまで!さまざまなイベントを開催しています。

  • LTイベント(技術メイン、趣味、自己紹介等テーマはさまざま)
  • 社内座談会
  • 社内Podcast
  • 合宿
  • ハッカソン

など、普段業務で関わらないようなチームや本部、メンバーとコミュニケーションが取れるイベントを企画したり それぞれの取り組みや人となりを知れるイベントを開催しています。(今年は合宿の開催は見送りました)

開催したイベントの関連記事

blog.cybozu.io blog.cybozu.io blog.cybozu.io

2020年前半は合計13回開催👏👏

2月以降はすべてフルリモート・オンライン開催で、以下のイベントの企画・運営、一部運営のみなどをやりました。

  • 自己紹介系LTイベント…3回
  • 技術系LTイベント…4回
  • 趣味系LTイベント…1回
  • 社内Podcast…2回
  • その他、各チームの成果発表報告会等…3回

月2回以上は何かしらのイベントを開催していますね! 詳細な参加人数は取れていないのですが、だいたい1回につき30人〜80人はリモート参加しています。

「オンラインならでは」の社内イベント事情

情勢を考えて、2020年2月からどこにも集まらず、運営も参加者も全員オンラインで開催です。 オンラインだと拠点の格差(多く集まっている拠点だけが盛り上がってしまう)がなく、 それぞれが思い思いに盛り上がれるのがオンラインの良さだと感じました。

社内イベントの待機画面
イベント開始までの待機画面を改善したり、イベントが少しでも楽しくなるような工夫も

ただ、フルリモート・オンライン開催だと「リアクションが分かりにくい」という問題が顕著なため効果音をつけたり、他にも社内オンラインイベントの体験を少しでも改善できるよう、イベント開始前にちょっとした案内を出したり、細かな改善なども模索しています。 (効果音の付け方は下記の記事を参考にさせていただきました)

参考記事

note.com

サイボウズならでは?!の社内イベント文化

実況スレッドでイベントの感想をやりとりしている様子
社内オンラインイベントで、おすすめの本が紹介された時の実況スレの様子

自社プロダクトの「kintone」に「実況スレ」を立てて、文字通りイベントを実況したり 疑問に思ったこと、感じたことなどをそれぞれ自由に書いています。 そこから意外な話に発展したり、嬉しいリアクションをもらえたり、他本部のメンバーが興味を持ってくれたり……。

社内イベントで実況スレをやってみるの、とってもおすすめです!

終わりに

リアルイベントに限りなく近づけるのは難しいので、現在は「オンラインならでは」の良さを楽しんで運営しています。

雑談やちょっとした会話が難しい今だからこそ、 社内のこうした取り組みがオンライン上でコメントをするきっかけになったり リアルで会ったときのコミュニケーションの種になると信じて、引き続き取り組んでいきます!

 

styled-componentsの採用と既存資産を捨てた理由

こんにちは。フロントエンドエキスパートチームの@nakajmgです。

私が所属しているフロントエンドエキスパートチームでは、現在 kintone の脱レガシーの一環として React + TypeScript 化に取り組んでいます。この取組の中で Scss で定義されている既存のスタイルを styled-components で書き直していくという決定をしました。

今回は styled-components の採用を決定するまでの過程や、既存の Scss ファイルの扱いについて検討した内容などを紹介します。

スタイル定義方法の検討

kintone にはユーザーが JavaScript でカスタマイズできる機能があり、ユーザーが行っているカスタマイズの中には、DOM 構造や CSS のクラス名に依存しているものもあります。このようなカスタマイズはサポートの対象外ではありますが、ユーザーにできるだけ不利益を出したくないという考えから、かなり慎重な方法も検討しました。

  • React コンポーネントで DOM 構造とクラス名を再現して既存のスタイル(Scss)をそのまま使う
  • Scss ファイルからコンポーネントで使うスタイルを抜き出して、コンポーネントと対になる Scss ファイルを新規で作成する
  • 既存の Scss を使わず新たにスタイルを定義し直す

これらは検討した案の一部です。プロダクトがすでにリリースされて多くの人に使われているという状況と、どういった形でリリースしていくかを考えて、これ以外にも様々なパターンが挙げられました。

既存の Scss ファイルを捨てる

さまざまなパターンを検討した結果、スタイルについては再利用せずに書き直そうという決定になりました。

これは既存の Scss が@mixin@extendを多用していて、かなり複雑な状態になっていたこと、それが課題として認識されてたのが大きな要因です。課題を解決するより新しく書くほうがコストが低いと考えてこのタイミングで捨てることを決断しました。

また、DOM 構造についても既存のものを踏襲せずに、よりよいマークアップで作り変えていこうとなりました。

スタイルを何で定義するか

既存の Scss ファイルを使わないことが決まったので、次は React コンポーネントでスタイルを定義する方法です。

React コンポーネントのスタイルの定義方法については、次の3つの候補が挙げられました。

  • Scss ファイルで新規作成
  • Scss + CSS Modules
  • CSS in JS

Scss ファイルで新規作成

既存メンバーが慣れ親しんだ方法で行い、コンポーネントごとのスタイルを@extendなどを使わずに、現状より独立した形で捨てやすい単位で定義し直すという選択肢です。

この方法は React 化が完了していない部分のスタイルと相互に干渉しあう可能性があること、コンポーネント化の恩恵を受けづらいことを理由に採用しませんでした。既存の Scss の課題をどうにかしたいと思っていたのもあり、メンバーからは新たな課題を生み出すだけではという懸念が出ました。

CSS Modules ( with Scss )

Scss で挙げたような懸念を一部解消できる選択肢として CSS Modules(css-loader による利用) も候補に挙がりました。.scssをコンポーネントからimportして使うことで scoped なスタイルとして使えること、メンバーが持っている知識で運用できるという点では悪くない選択肢のように思いました。

しかしながら、現在 CSS Modules はメンテナンスオンリーな状態にあり、将来 deprecateとされる可能性が高く、採用するにはリスクが高いと判断しました。

また、.scss ファイルを ES Modules の構文で import するのは、ビルドツールの選定において CSS Modules をサポートしていることが必要条件となってしまうので、将来的に身動きがとりづらい状況になってしまう可能性があります。

CSS in JS

CSS in JS はその名のとおり JavaScript の中で CSS を書くものです。CSS in JS を実現するためのツールは多くありますが、代表的なものとして styled-components や emotion があります。

今回 styled-components を採用することにしましたが、次のような懸念点も挙げられました。

  • JavaScript(TypeScript)の中でスタイル書いていくのつらそう
  • styled なラッパーコンポーネントとかがいっぱい作られていろいろつらそう
  • JSX に styled なコンポーネントと React コンポーネントが混ざって視認性が悪くなりそう
  • デザイナーが参加しにくくなりそう
  • 負債になりそう

検討を重ねた結果これらの懸念点のほとんどは styled-components の使い方にルールを設けることで払拭できそうだと考えました。

styled-components の使用ルールを定める

styled-components を使う上で定めたのは次のようなルールです。

  • styledはコンポーネントを引数に取ってスタイルをあてる以外の使い方をしない
  • styledは同一ファイル内で使用してファイルを分割しない

具体的には次のような書き方になります。

import React from "react";
import styled from "styled-components";

const Component = ({ className }) => (
  <div className={className}>
    <div className={`${className}__child`}>コンポーネント</div>
  </div>
);

const StyledComponent = styled(Component)`
  background-color: #fff;
  color: #000;
  &__child {
    border: 1px solid #000;
  }
`;

export const MyComponent = StyledComponent;

JavaScript の中でスタイルが書くのがつらそうという懸念については、IDE やエディタにプラグインを入れることで軽減できます。また、この形式であれば styled なコンポーネントと React コンポーネントがごちゃ混ぜになることはありません。React コンポーネント自体もピュアな React コンポーネントの状態を保つことができます。

デザイナーがスタイルの修正などに参加しにくくなりそうという点も、スタイルが記述されている場所が限定されることで、これまでの .scss ファイルと同じように変更を加えられるようになっています。

そして将来的に負債になりそうという懸念ですが、これはどんなツールやライブラリを選んだとしても、早かれ遅かれ、多かれ少なかれ負債になるものだと考えています。その負債を小さくするために考えるべきは、スタイルを小さい範囲で書いて捨てやすい状況にすること、そして変更に耐えれる設計にできるかどうかです。この観点からすると、styled-components でも前述したルールで運用すれば大丈夫であろうと判断しました。

Scss の資産と向き合う

styled-components でやっていくにあたり、既存の Scss に定義してある変数をどうするかについて検討しました。

最終的な決定としてはこの機会に Scss の資産をすべて放棄して、styled-components に適したやり方で色などを管理していこうとなりました。styld-componets はテーマによってスタイルを変更する機能を持っているので、テーマとして扱っていくことにしました。

検討の途中で Scss の変数を抽出して JavaScript から扱えるように変換する方法を試してみました。このプロジェクトでは使わないことにしましたが、移行の途中段階などで使える状況もあるかと思いますので、方法を紹介します。

Scss の変数を JavaScript に変換する

次のようなディレクトリ構成をもとに変換方法を紹介します。

.
├── package-lock.json
├── package.json
└── src
    └── scss
        ├── _components.scss
        ├── _variables.scss
        └── entry.scss

変換には次のパッケージを使います。

npm からインストールしてください。

npm i -D sass-extract sass-extract-js rgb-hex

変換スクリプトの作成

次の内容を extractScssVariables.js としてプロジェクトのルートに作成します。

const fs = require("fs");
const path = require("path");
const sassExtract = require("sass-extract");
const rgbHex = require("rgb-hex");
const { writeFile } = fs.promises;

const extract = () => {
  const rendered = sassExtract.renderSync(
    {
      file: path.resolve(__dirname, "./src/scss/entry.scss"),
    },
    {
      plugins: [
        {
          plugin: "sass-extract-js",
          options: { camelCase: false },
        },
        {
          plugin: {
            run: () => ({
              postExtract: (vars) =>
                Object.keys(vars).reduce((ret, key) => {
                  ret[`${key}`] = `#${rgbHex(vars[key])}`;
                  return ret;
                }, {}),
            }),
          },
        },
      ],
    }
  );
  console.log(rendered.vars);
  writeFile(
    path.resolve(__dirname, "./src/variables.js"),
    `
    export const scssVariables = ${JSON.stringify(rendered.vars, null, 2)}
  `.trim()
  );
};

extract();

Scss の中身

今回サンプルとして使うのは次のような Scss です。

// src/scss/_variables.scss
$color-text: #333;
$color-text-hover: #666;
$color-active: #3498db;
$color-border-focus: $color-active;
$bg-button: #f7f9fa;
$bg-button-hover: $color-active;
// src/scss/_components.scss
@import "./variables";
.button {
  color: $color-text;
  background-color: $bg-button;
  &:hover {
    color: $color-text-hover;
    background-color: $bg-button-hover;
  }
  &:focus {
    border-color: $color-border-focus;
  }
}
// src/scss/entry.scss
@import "./components";

これらの Scss をもとに変換します。

変換してみる

次のコマンドをプロジェクトのルートディレクトリで実行します。

node ./extractScssVariables.js

変換結果

実行が終わると、次のようなファイルが生成されます。

// src/variables.js
export const scssVariables = {
  "$color-text": "#333333",
  "$color-text-hover": "#666666",
  "$color-active": "#3498db",
  "$color-border-focus": "#3498db",
  "$bg-button": "#f7f9fa",
  "$bg-button-hover": "#3498db",
};

TypeScript で補完を効かせたい場合には次のように as const を足してください。

writeFile(
  path.resolve(__dirname, "./src/variables.js"),
  `
  export const scssVariables = ${JSON.stringify(
    rendered.vars,
    null,
    2
  )} as const
`.trim()
);

これで Scss の変数が JavaScript から扱える形になりました。直接importrequireをして使ったり、styled-components のthemeで注入して使うといったことが可能になります。

今回変換対象として用意した Scss ファイルはシンプルなものでしたが、このスクリプトはエントリーとなる Scss から辿れる全ての変数を抽出してくれます。

今回紹介したスクリプトのサンプルが次のリポジトリに置いてありますので、ぜひお手元の Scss ファイルで試してみてください。

https://github.com/nakajmg/sample-scss-variables-to-js

おわりに

styled-components の採用を決めた経緯と、既存の Scss をどう扱っていくかについて紹介しました。

負債はコツコツと返済していければ良いですが、対象やタイミングによっては難しいこともあるので、思い切って捨ててしまう(作り直す)という選択も有効です。

プロジェクトの状況やチームが達成したい目標によってレガシーとの向き合い方はさまざまですが、先を見据えてじっくりと検討を重ねて、一歩づつ進んでいければと思います。

 

マージボタン1つで本番適用するための仕組み

こんにちは、Yakumoチーム兼コネクト支援チームの@ueokandeです。

本日はYakumoチームで構築した、デプロイパイプラインとその工夫について紹介します。 Yakumoプロジェクトはグローバル市場向けに、kintone.comをAWSから提供することを目指すプロジェクトです。 これまで日本のデータセンターから提供していたkintone.comを、現在AWS上に移行しています。 プロジェクトのもう1つのゴールとして、開発・運用体制を見直してクラウドネイティブなリリースプロセスを確立するというのがあります。

このプロジェクトは、国内向けのcybozu.comと完全に切り離されて開発がスタートしました。 ゼロからリリースフローを作るということで、これまでのインフラの経験や反省点を活かしつつ、チームの理想的なデプロイパイプラインの構築を目指しました。 そして最終的には、マージボタン1つで本番適用できるデプロイパイプラインを構築しました。 この記事ではYakumoチームのデプロイパイプラインと、それに至るまでの経緯を紹介します。

kintone.comのインフラ構成

kintone.comは異なる責務を持ったいくつかのサービスから構成されます。 たとえば、マルチテナントを実現するサービスや、非同期ジョブを処理するサービスなどです。 各サービスはKubernetes (Amazon EKS) を使ってデプロイされます。 それぞれのサービスが利用するデータベースやストレージは、AWSのマネージドサービスを利用します。

kintone.comのインフラ構成
kintone.com on AWSのインフラ構成

理想のデプロイパイプライン

インフラ構成の更新や本番オペレーションでは、運用するチームにとって負担が少ないことが理想です。 これまでの国内インフラの運用経験で、オペレーションを自動化するだけでは管理者の負担が減らないというのがわかっていました。 Yakumoプロジェクトでは、KubernetesやTerraformで採用された宣言的モデルという考えに基づいて、デプロイパイプラインを構築しました。

ソースコードは構築したいインフラの構成を表し、常に本番環境の設定はソースコードを見ればよいという状態を維持します。 そしてインフラの構成やアラートの閾値調整も、ソースコードを変更してマージするというフローにして、本番オペレーションを最小限に抑えました。

kintone.comのデプロイパイプラインの図
kintone.comのデプロイパイプライン
宣言的モデルをインフラに適用するのに必要なのが、差分検知と差分を埋めるオペレーションです。

差分検知とオペレーション

宣言的モデルでは、管理者が定義した状態を元に、実際のインフラを定義された状態に収束させます。 システムは、実際のインフラの状態と定義された状態との差分を検知し、その差分を埋めるオペレーションを実行します。

AWS CloudFormationやKubernetesは、この仕組を備えています。 ユーザーが定義したマニフェストファイルをCloudFormationやKubernetesに与えると、その定義ファイルに基づいたインフラの構築やコンテナをデプロイします。 またマニフェストファイルで何らかのパラメータを変更すると、対象リソースや関連するリソースに新しい設定を反映します。

一方でインフラレイヤーだけでなく、Yakumoチームが開発しているサービス群のデプロイもあります。 こちらもソースコードと本番環境の状態を常に一致させたいです。 サービスのソースコードを更新すると、新しいバージョンのイメージをKubernetes上にデプロイしたいです。 サービスの更新を検知するために、コンテナのイメージタグにソースコードのハッシュ値を採用しました。

ソースコードからイメージタグを生成

それぞれのサービスのイメージタグは、バージョン番号vX.Y.Zなどではなく、ソースコードから計算したハッシュ値を使います。 このソースコードには、サービス本体のコードだけでなく、コンテナに同梱するスクリプトやDockerfileも含みます。 ソースコードやDockerfileが更新されると、新しいイメージタグでコンテナレジストリに登録されます。

Kubernetesに適用するマニフェストは、レポジトリに含まれるソースコードからハッシュ値を計算して、イメージタグを埋め込みます。 ソースコードに更新があったサービスは新しいイメージタグが割り当てられ、 Kubernetesマニフェストの適用 (kubectl apply) でサービスのコンテナが更新されます。 開発者は、現在サービスのどのバージョンがデプロイされているかを考える必要がなくなり、本番環境は常にレポジトリにあるソースコードがデプロイされる事になります。

spec:
  containers:
    - name: my-service-a
      # 575C70E78FE448BC973EB46A46F4AE8Bなどのイメージタグが適用される
      image: quay.io/cybozu/my-service-a:{{ tag "my-service-a" }}

ケーススタディ: コンテナのベースイメージ更新

このしくみにより本番適用の自動化が容易になり、マージボタン1つで本番適用できるしくみができました。 ここで1つ例として、コンテナのベースイメージの更新を考えます。

例えばJVM用にビルドされたサービスの、Javaのバージョンの更新を考えます。 Yakumoチームでは管理の容易化のために、JVMサービスでは同じベースイメージを利用します。 セキュリティパッチなどで新しいJavaのバージョンがリリースされると、そのたびに本番環境のサービスを更新する必要があります。

一般的なベースイメージの更新作業は以下のとおりです。

  1. べースイメージのDockerfileを更新
  2. ベースイメージのリビルド (docker build)
  3. ベースイメージをコンテナレジストリに登録 (docker push)
  4. 各種サービスをリビルド (docker build)
  5. 各種サービスをコンテナレジストリに登録 (docker push)
  6. 各種サービスを本番環境に適用 (kubectl apply)

Yakumoチームのリリースフローでは、手順1.のDockerfileを更新してマージするだけです。

ベースイメージもまた、ハッシュ値のイメージタグを持ちます。 各サービスはベースイメージのタグを参照するため、ベースイメージが更新されると、それを利用するサービスも更新されます。 そして新しいイメージタグを持つサービスが本番環境に適用され、作業は完了です。

コンテナのベースイメージの更新と本番適用
コンテナのベースイメージの更新と本番適用

まとめ

以上がYakumoプロジェクトで取り組んだ、リリースフローとデプロイパイプラインの紹介でした。 宣言的モデルにより、「インフラやサービスの状態を確認し、影響範囲を考慮しながら、適用手順を作成する」という難しいフローも発生しません。 このリリースフローを確立したことで、本番環境への適用オペレーションというのがほぼなくなりました。 masterマージと本番適用が同義となり、切り戻しもgit revertするだけ、というフローです。

この理想のデプロイパイプラインも、一朝一夕で構築できたわけではありません。 これまでのcybozu.comの知見や、チーム内で積み重ねてきた改善活動によって現在の形に至りました。 このリリースフローで退屈な適用オペレーションを省けるだけでなく、製品の価値をより早くユーザーに届けることにも繋がります。

みなさんも、同じオペレーションを繰り返してるなと感じた時は、理想のリリースフローを探求してみてはいかがでしょうか?