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

Hardening II Collective 参加報告

$
0
0

こんにちは、QAの上池です。
Hardening というセキュリティ堅牢化の競技会に参加して、優勝しました!! f:id:cybozuinsideout:20180821181030j:plain

大変良い経験だったので、イベントの様子を報告します。

Hardening とは

Hardening とは、チームでECサイトを運営し、サイトの収益を上げつつインシデントレスポンスを実施して、その技術力や対応力を競うイベントです。

https://wasforum.jp/hardening-project/

今回の大会から、1チーム内でサービスプラットフォーム・営業統括・経営企画のビジネスユニットに分かれて競技を行うことになりました。

やったこと

私は経営企画を担当しました。
CSIRT を設立して JPCERT/CC とやり取りしたり、プライバシーポリシーを掲載したり、データを抜かれて個人情報が漏洩してしまった(笑)ので、その報告をまとめて関係各所に連絡したりしました。

プライバシーポリシーは、GDPR 対応したものとその英訳版を事前に用意しておいたので、必要になった時にスムーズに掲載することができました。
他のメンバーも、あらかじめ必要となりそうなコマンドや手順を準備していて、競技中に活用していました。
やりたいこと全てをやりきれたわけではありませんが、メンバー間でうまくコミュニケーションを取ってそれぞれがベストを尽くせたので、優勝することができたのだと思います。

学びと感想

円滑なコミュニケーションの必要性

インシデントレスポンスは、以下の状況の中で実施していく必要があると実感しました。

  • 部署をまたいだ意思決定が必要で、全社最適な優先順位で対応する
  • 現場の人が実際に手を動かす時は結論の背景をちゃんと理解しておく

そのために、組織間コミュニケーションを円滑にしたり、経営層のやり取りが現場に伝わっていることの必要性を感じました。
今回は Slack を使うことで、このあたりをうまく実現できました。メールでのやり取りが必要だったり、オフラインで招集しないといけないような企業だと辛すぎると思いました。
普段の業務では kintone上でやり取りをしていて理想に近い状態ではありますが、まだまだ改善の余地はありそうです。

レスポンスのフローを用意しておく

インシデントが起きたらその具体的な対処や意思決定に追われるので、「これが起きたらどこに何をどのような手順で対応するか」をまとめたり、報告書のフォーマットを用意しておくだけで、レスポンスが圧倒的に速くなります。
お客様対応やサービスの運用のためにも、レスポンスのスピードは重要だと感じました。

みんな一回はヤバい事象を体験しておくべき

今回の Hardening への参戦で、セキュリティインシデント発生時に、どう情報をまとめて共有するか、どこに報告しないといけないかといったことを学びました。
それ以外にも、職種によってそれぞれ学びがあると思います。実業務でヤバみを体験していない中堅社員には参加を推したいです。

  • 開発・運用:データ保全や稼働率維持を目的とした作業の優先順位付け、スムーズな実施
  • 営業・サポート:お客様とのやり取り
  • 広報・IR:HP掲載、メディア対応
  • 法務::法的整理、関係省庁へのインシデント報告

もう1つの Hardening

今回の開催場所は宮古島で、開催期間中は快晴でした。 f:id:cybozuinsideout:20180821152613j:plainが、開催前日の7/5は50年に1度の大雨が降り、大型台風が至近に到達しているという状況でした。
Hardening Project 公式からも台風ネタが投下される有様……。

私はイベント後に宮古島に2泊する予定だったのですが、飛行機が飛ばなくなって宮古島から出られなくなるということだったので、急遽予定を繰り上げて沖縄本島に移動するというインシデントレスポンスを発動しました。
みなさま、宮古島にお出かけの際は、大雨・台風にお気をつけください!


Go言語向けFailure Injectionツール: gofail

$
0
0

こんにちは、Necoチームの池添(@zoetro)です。

gofailは、etcdの開発チームがつくったFailure Injectionのためのツールです。 Go言語で書かれたプログラム中に故意にエラーを発生させるポイント(failpoint)を埋め込み、任意のタイミングでプログラムの挙動を変えることができます。 公式ドキュメントに記載されていない項目が多々あるので、詳しい使い方を紹介したいと思います。

なお、本記事は2018年8月時点のソースコードを対象に解説しています。

gofailのインストール

gofail をインストールします。

$ go get -u github.com/etcd-io/gofail/...

failpointの埋め込み

プログラム中にfailpointを埋め込むためには、Go言語のプログラム中に gofailというキーワードから始まるコメントを記述します。 なお、ブロックコメントの場合はfailpointとして認識されないため、必ず行コメントで記述する必要があります。

コメントの1行目にはトリガーとなる変数定義を記述し、2行目以降にはfailpointを有効化した時に実行されるコードを記述することができます。 複数行の処理を埋め込みたい場合は、空行をあけずにコメントを記述します。

例えば任意の値を返すようなfailpointを埋め込みたい場合は、下記のように1行目に返す値となる変数宣言、2行目にreturnを記述します。

func someFunc() string {
    // gofail: var SomeFuncString string// return SomeFuncStringreturn"default"
}

なお、failpointとなる変数の型は bool, int, string, struct{}のみになります。

fail発生後に任意の処理を実行する必要がない場合(panicを発生させる場合など)は、以下のように struct {}型の変数宣言のみを記述します。

func ExampleOneLineFunc() string {
    // gofail: var ExampleOneLine struct{}return"abc"
}

failpointを有効化した時にgotoやラベル付きcontinue文を実行したい場合は、下記のように gofail の後ろにラベル名を記述することもできます。

func ExampleRetry() {
    // gofail: RETRY:for i := 0; ; i++ {
        fmt.Println(i)
        time.Sleep(time.Second)
        // gofail: var RetryLabel struct{}// goto RETRY
    }
}

failpointを埋め込んでビルド

failpointを埋め込んでビルドするには、まず下記のコマンドを実行します。

$ gofail enable

するとgofailから始まるコメントを記述した箇所が書き換えられ、*.fail.goというファイルが生成されます。 あとは生成されたコードを含めて通常通りにビルドします。

書き換えられたコードをもとに戻すには、以下のコマンドを実行します。

$ gofail disable

failpointの有効化

埋め込まれたfailpointは初期状態ではoffになっているので、実際にfailさせるためにはfailpointの有効化をおこなう必要があります。 failpointを有効化させる手段としては、プログラムの起動時に環境変数で指定するかHTTP APIで有効化するか2通りの方法がありますが、ここではHTTP APIを利用した方法を紹介します。

まずgofailのエンドポイントを環境変数で指定してプログラムを起動します。

GOFAIL_HTTP="127.0.0.1:1234" ./cmd

下記のAPIを叩くと、failpointの一覧を取得することができます。

$ curl http://127.0.0.1:1234/
my/package/path/SomeFuncString=
my/package/path/ExampleOneLine=
my/package/path/ExampleLabels=

failpointを有効化するためには下記のAPIを実行します。 ここでは、SomeFuncStringhelloという文字列を返すように設定しています。

$ curl http://127.0.0.1:1234/my/package/path/SomeFuncString -XPUT -d'return("hello")'

再度下記のAPIを実行すると、failpointが設定されていることが確認できます。

$ curl http://127.0.0.1:1234/
my/package/path/SomeFuncString=return("hello")
my/package/path/ExampleOneLine=
my/package/path/ExampleLabels=

この状態でsomeFunc()関数が実行されると、helloという文字列が返ってくるようになります。

failpointを無効化するには下記のAPIを実行します。

$ curl http://127.0.0.1:1234/my/package/path/SomeFuncString -XDELETE

failpointで実行可能なアクション

failpointには、下記のアクションを指定することができます。

  • off: failpointの無効化
  • return: 任意の値を返す(返すことのできる型は bool, int, string, struct{} のみ)
  • sleep: 一定時間待つ(待ち時間はDurationフォーマットで指定可能。intで指定した場合はミリ秒になる)
  • panic: panicを発生させる
  • break: デバッガによるbreakを発生させる
  • print: 標準出力に文字列を出力する

また、failを発生させる回数や確率を指定することもできます。

下記の例では、failpointが呼び出された最初の3回はhelloという文字列を返し、その後は通常の状態に戻ります。

$ curl http://127.0.0.1:1234/my/package/path/SomeFuncString -XPUT -d'3*return("hello")'

下記の例では、50%の確率でhelloを返すようになります。

$ curl http://127.0.0.1:1234/my/package/path/SomeFuncString -XPUT -d'50.0%return("hello")'

おわりに

gofailを利用すると任意のタイミングでソフトウェアの挙動を変えることができ、Failure Injection Testをおこなう際にはとても便利なので、ぜひ使ってみてください。

我々はgofailを利用した耐障害性試験を実施し、信頼性の高いインフラ基盤の構築を進めています。次回の記事ではそのあたりを詳しく紹介したいと思います。

分散システムの耐障害性テストの取り組み

$
0
0

こんにちは、Necoチームの池添(@zoetro)です。

サイボウズが提供するクラウドサービスcybozu.comでは、アーキテクチャを刷新すべく「Neco」というプロジェクトを実施しています。 そのプロジェクトでは、サーバのライフサイクルを管理するsabakanや、Kubernetesクラスタを構築するためのCKE(Cybozu Kubernetes Engine)などの分散システムを開発しています。 安定してサービスを提供するためには、このようなインフラを支える分散システムの耐障害性が重要になってきます。

本記事では、我々のチームが分散システムに対してどのような耐障害性テストを実施しているのかを紹介します。

耐障害性を高めるために

機材故障

サイボウズの管理するデータセンターでは1,000台規模のサーバを扱っており、日常的にハードウェアの故障が発生します。 例えば、以下のような機材故障が発生する可能性があります。(参考: 本当は恐ろしい分散システムの話)

  • 電源やサーバが故障して、サーバが利用できなくなる
  • ストレージが故障して、アクセスできなくなったり遅延が発生したりする
  • NICが故障して、通信障害や遅延やパケットロスが発生する
  • スイッチが故障して、通信障害や遅延やパケットロスが発生する
  • ラックが故障して、ラック内のサーバが利用できなくなる

f:id:cybozuinsideout:20180830140950p:plain
ハードウェア故障

このような故障はどれだけ信頼性の高いハードウェアを使ったとしても回避することができないため、ハードウェアの冗長化とソフトウェアでの対応の両面から対策をおこなう必要があります。

故障への対策

機材故障に対してどのような対策をおこなうべきかを、サービスレベル目標(SLO: Service Level Objective)から考えていきます。 例えば、下記のようなSLOを設定しているとしましょう。

  • 機材に単一の障害が発生した場合、サービスの停止が一分以内に復旧すること
  • 機材に単一または二重の障害が発生した場合でもデータを紛失しないこと

このSLOを達成するために、機材故障に対する対策をいくつかのレイヤーに分けて考えてみます。

まずはハードウェアの冗長化による対策となります。ラックの電源は二系統用意し、NICはサーバごとに二枚、ToR(Top of Rack)スイッチやSpineスイッチも二重化します。

次にネットワークレイヤーでの対策を考えます。Necoプロジェクトのアーキテクチャでは、ECMP(Equal-Cost Multi-Path routing)による冗長経路とBFD(Bidirectional Forwarding Detection)による障害検知により、ネットワーク障害が発生しても即座に経路収束するような構成となっています。 障害発生時にネットワークの経路が収束する様子については、Necoのネットワーク - アーキテクチャと設計編で紹介しています。

上記の対策により、電源故障やネットワーク障害などをある程度防ぐことができるでしょう。 しかし、サーバの故障やネットワークの遅延、ラックがまるごと故障するケースは防ぐことができません。 このような状況ではソフトウェアレイヤーで対策をおこなう必要があります。

例えば我々の開発しているCKE(Cybozu Kubernetes Engine)では、以下のような対策をおこなっています(具体的な実装方法は今回は割愛します)。

  • 3つ以上のプロセスを異なるラック上のサーバに分散配置してクラスタを構築する
  • クラスタ内のいずれかのプロセスからリーダーを選出し処理を進める
  • リーダーにアクセスできなくなったり不正終了した場合、別のプロセスがリーダーを引き継いで処理を続行する
  • データは分散KVSに格納する

耐障害性テスト

どのようなテストをすべきか

耐障害性テストでは、上述したような対策をおこなうことでSLOを達成することができるかどうかを確認することになります。

ここで機材の故障をやみくもに発生させても効果的なテストをおこなうことはできません。 どういう故障が発生した時に分散システムに問題が起きるのかを考えます。 例えば以下のような状況が考えられます。

  • ネットワークの障害により、リーダープロセスにアクセスできなくなる
  • サーバの故障などにより実行中のリーダープロセスが突然終了する
  • ネットワーク障害によりクラスタが複数に分断されてしまう
  • ストレージ故障により、データの複製の一部が失われる

f:id:cybozuinsideout:20180830140955p:plain
クラスタ故障

これらの障害が発生した時に下記の項目を確認するテストを用意することになります。

  • リーダープロセスにアクセスできなくなっても一分以内に復旧すること
  • リーダープロセスが途中終了した処理が、別のリーダーに引き継がれて実行されること
  • クラスタ分断によりスプリットブレイン問題が発生しないこと
  • データを紛失したり、データの不整合を発生させたりしないこと

サーバやネットワーク障害のエミュレート

耐障害性テストを実施するためには、サーバやネットワークに故意に障害を発生させる必要がありますが、実機上で実施することは簡単ではありません。 そこで我々は placematというツールを開発し、VMやコンテナやnetns, iptablesなどを駆使して、データセンター環境の仮想化を実施しています。

このplacematにより、サーバの故障、NICの故障、スイッチの故障などを仮想環境上で再現することができるようになっています。 スイッチはBIRDやdnsmasqを利用してソフトウェア的に再現しているので、本物の機材と若干の挙動の差異が発生する場合もありますが、多くのケースは再現できています。

なお、placematでデータセンター環境を再現するためには大量のVMを立ち上げる必要があります。 そのようなテストをCircleCI上でそのまま実行することは難しいため、GCP上にテスト用の大きめのインスタンスを用意し、CircleCIからテストをキックする仕組みを構築しています。

Failure Injection Test

分散システムでは、特定の処理をおこなっているタイミングで障害が発生した場合に問題が起きる可能性が高いです。

例えばCKEはetcdクラスタを自動構築する機能を持っているのですが、etcdクラスタにメンバを追加する際に以下のような処理をおこなっています。

  1. etcdのコンテナイメージを取得する
  2. etcd用のデータボリュームを作成する
  3. etcdのMember Add APIを利用してetcdクラスタにメンバの追加を要求する
  4. Member Add APIの結果を利用してetcdコンテナを起動する

ここで手順3と4の間で何か障害が発生しプロセスが終了してしまった場合、etcdクラスタにはメンバ追加のリクエストを受けているのに、実際にはetcdのメンバプロセスが起動していないという中途半端な状態になってしまいます。 CKEではこのような状況が発生した場合、別のCKEプロセスがリーダーとなって処理を続行し、etcdクラスタを正しく構築します。

さて、このような挙動をテストしたい場合、手順3と4の間というとても短いタイミングでサーバやネットワークの障害を発生させる必要があり、狙っておこなうことは困難でしょう。

そこで、システム内に意図的にエラーを発生させるコードを埋め込んでテストするFailure Injection Testingという手法を使います。 Go言語であればgofailというツールが利用できます。gofailの利用方法は別記事にまとめたのでそちらをご覧ください。

blog.cybozu.io

Failure Injection Testの例を紹介したいと思います。可読性をあげるため一部処理を簡略化しています。 なおテストコードの記述にはGinkgoというBDDテストフレームワークを利用しています。

var _ = Describe("etcd cluster deployment", func() {
    It("should change the leader and continue to deploy etcd cluster", func() {
        // 現在のリーダーを確認
        firstLeader := ckecli("leader")
        Expect(firstLeader).To(Or(Equal("host1"), Equal("host2")))

        // etcdにmember addした直後に障害を発生させるように、firstLeaderにfailure pointを設定
        injectFailure(firstLeader, "etcdAfterMemberAdd")

        // etcdクラスタにメンバを追加するようにCKEを設定する
        ckecliClusterSet(cluster)

        // etcdクラスタが構築されたことを確認
        Eventually(func() bool {
            return checkEtcdClusterStatus()
        }).Should(BeTrue())

        // リーダーが切り替わっていることを確認
        newLeader := ckecli("leader")
        Expect(newLeader).To(Or(Equal("host1"), Equal("host2")))
        Expect(newLeader).NotTo(Equal(firstLeader))
    }
})

injectFailure()が、故意にエラーを発生させるコードを埋め込むための関数になっています。 gofailを利用するとREST API経由でエラーコードの埋め込みをおこなうことができます。

ここでは、現在のリーダープロセスがetcdクラスタにmember addした直後にpanicを起こすコードを埋め込んでいます。 その後に別のプロセスがリーダーを引き継ぎetcdクラスタを正しく構築していることを確認しています。

おわりに

近年ではサービスを提供するためのインフラとしてAWSなどのパブリッククラウド環境を利用することが当たり前になってきています。 サイボウズでもUS市場向けクラウドサービスのAWS移行プロジェクトを実施しています。 AWSを利用すれば容易に信頼性・可用性の高いインフラを手に入れることができます。

一方で我々は、サーバスペックの自由度の高さ、顧客のセキュリティ要件への対応、コストメリットなどを考慮して、自社データセンターで運用しています。 自社データセンター上のインフラで高い信頼性を実現するためには、今回紹介したような耐障害性試験の取り組みが重要になります。 今後はより安定したサービスを提供できるよう耐障害性テストを強化し、Chaos Engineering的な取り組みにも挑戦していきたいと考えています。

なお本プロジェクトは人員募集中です。信頼性の高いインフラづくりに関わってみたい方はぜひお声掛けください!

ASTを活用してコードの自動修正に挑戦してみよう

$
0
0

どうも!アプリケーション基盤チームの@yokotasoです。 単純だけど、大量のソースコードの修正が必要な場合、みなさんはどうやって修正していますか?

Junit4からJunit5の移行調査をしていたときに、例外を検証する@TestexpectedがJunit5では消えていることがわかりました。 社内のコードを調べたところ、修正が必要な箇所が1000箇所くらいということがわかったので、ASTを活用した自動修正ツールを作ってみました。 今回は自動修正ツールを使った大量修正の話を紹介します。

ASTとはなにか?

ASTとはプログラミング言語のソースコードの構造をツリーとして表現したもです。

今回はJavaの話なので、javaparserを使って話していきます。

例えば次のようなテストコードがあったとします。

@Test(expected = IllegalArgumentException.class)
publicvoid testNullInput() {
    // setup
    Dog sut = new Dog();
    sut.sit();

    // exercise & verify
    sut.eat(null);
}

このプログラムをASTに分解すると次のような構造になります(簡略化しています)。

f:id:cybozuinsideout:20180904175225p:plain

今回はこのテストコードを次のように変換します。

@Testpublicvoid testNullInput() {
    // setup
    Dog sut = new Dog();
    sut.sit();

    // exercise & verify
    assertThatThrownBy(() -> sut.eat(null)).isInstanceOf(IllegalArgumentException.class);
}

ASTを活用して自動修正ツールを作ってみよう

社内のコード変換につかったコードはjunit-exception-test-replacerにおいてありますので、もしよかったらご利用ください。

修正したい箇所をVisitorパターンを実装して探す

メソッドに対して@Test(expected=...class)となっているところを探します。

publicclass ExceptionTestVisitor extends VoidVisitorAdapter<ExceptionTest> {

    privatevoid collectMethodDeclaration(final MethodDeclaration n, final ExceptionTest arg, final Optional<AnnotationExpr> testAnnotation) {
        // 後述
    }

    @Overridepublicvoid visit(final MethodDeclaration n, final ExceptionTest arg) {
        super.visit(n, arg);
        Optional<AnnotationExpr> testAnnotation = n.getAnnotationByClass(Test.class);
        if (!testAnnotation.isPresent()) {
            return;
        }
        // メソッド定義の位置情報を収集する
        collectMethodDeclaration(n, arg, testAnnotation);
    }
}

修正したい場所の位置情報や必要な情報を収集する

ソースコードからASTを構築するとソースコード上の行や列の位置情報を取得することができます。ソースコードの修正対象箇所を収集していきましょう。

このメソッドの中では、次の情報を収集しています。

  • 修正が必要な @Testがプログラムファイルの中のどこに存在しているのか
  • @Test(expected = ...class)で指定されているクラス名
  • テストメソッドの中の最後のステートメント
privatevoid collectMethodDeclaration(final MethodDeclaration n, final ExceptionTest arg, final Optional<AnnotationExpr> testAnnotation) {
        testAnnotation.ifPresent((annotationExpr) -> {
            for (Node node : annotationExpr.getChildNodes()) {
                if (!(node instanceof MemberValuePair)) {
                    continue;
                }
                
                MemberValuePair memberValuePair = (MemberValuePair) node;
                if (memberValuePair.getName().asString().equals("expected")) {
                    Range range = annotationExpr.getRange().orElseThrow(IllegalStateException::new);
                    // @Test(expcected=...class) の 例外クラスの情報を取り出す
                    ClassExpr expected = (ClassExpr) memberValuePair.getValue();
                    arg.testAnnotationPositions.put(range, expected);
                    
                    // テストメソッドの最後のステートメントの位置情報を記録する
                    List<Statement> statements = n.getBody().orElseThrow(IllegalStateException::new).getStatements();
                    range = statements.get(statements.size() - 1).getRange().orElseThrow(IllegalAccessError::new);
                    arg.lastStatementPositions.put(range, expected);
                }
            }
        });
}

ASTで解析した情報を使ってパッチを自動生成する

ASTを使ってソースコードを解析した結果、修正が必要なソースコードの位置情報や修正に必要な情報がわかりました。 この情報を使ってパッチを自動生成していきましょう。パッチにはJavaのOSSライブラリのDiff Utilsを使っています。

ASTのデータ構造を直接書き換える方法もありますが、その場合、空白行やImport文が微妙に変わるなど難しいことが実装してわかったのでパッチを生成する方法をとっています。

@Testに修正するパッチを生成

patch = new Patch<>();
Pair<Range, ClassExpr> rangeAndClassExpr = ...;
Range range = rangeAndClassExpr.getOne();
int beginLine = range.begin.line - 1;
int beginColumn = range.begin.column - 1;
String oldSource = sourceCode.get(beginLine);
String indent = oldSource.substring(0, beginColumn);

// @Test(expected = Throwable.class) を次のように置き換えるパッチを生成// @Test
Chunk<String> oldChunk = new Chunk<>(beginLine, Lists.newArrayList(oldSource));
Chunk<String> newChunk = new Chunk<>(beginLine, Lists.newArrayList(indent + "@Test"));
patch.addDelta(new ChangeDelta<>(oldChunk, newChunk));

例外が発生することを検査するようにコードを修正する

テストメソッドの最後のステートメントで例外が発生する仮定で、テストコードを修正するパッチを生成していきます。 テストメソッドの最後のステートメントを assertjassertThatThrownByを使って変換します。

assertThatThrownBy(() =>/* テストメソッドの最後のステートメント */)
    .isInstanceOf(/* @Test(expecred=) で指定されていたクラス */)

上のようなコードを頭にイメージしながら、パッチを生成していきます。

Pair<Range, ClassExpr> rangeAndClassExpr = ...;
Range range = rangeAndClassExpr.getOne();
int beginLine = range.begin.line - 1;
int beginColumn = range.begin.column - 1;
String indent = sourceCode.get(beginLine).substring(0, beginColumn);

StringBuilder newSource = new StringBuilder(indent).append("assertThatThrownBy(() -> ");
newSource.append(sourceCode.get(beginLine).substring(beginColumn, range.end.column - 1));
newSource.append(").isInstanceOf(").append(getExpectedClass(rangeAndClassExpr.getTwo())).append(");");

Chunk<String> oldChunk = new Chunk<>(beginLine, Collections.singletonList(sourceCode.get(beginLine)));
Chunk<String> newChunk = new Chunk<>(beginLine, Collections.singletonList(newSource.toString()));
patch.addDelta(new ChangeDelta<>(oldChunk, newChunk));

自動修正したい部分のパッチはこれで自動生成できるようになるので、Diff Utilのドキュメントの通りにパッチを適用して、 修正対象のソースコードを上書きしていけば完成です。

目視とテストで変換に失敗しているところを探す

自動変換が失敗するケースや自動修正に加えて再度修正が必要になるケースもあるので、修正すればすべての修正は完了です。

AST活用できる場面はたくさんありそう

ASTの知識を使うと、自動化できる対象が増えそうです。楽しいことができそうで夢が広がりますね。 ソースコードを解析したり解析した情報をもとにプログラムを自動生成できる一歩手前ですね。

ASTを使って大量の修正を自動修正してみた話を紹介してみました。 アプリケーション開発をしているとASTを活用する機会はあまりないので、息抜きに楽しいコーディングタイムとなりました。

サイボウズもコード量が増殖しつづけているので、自動化できるところはできるだけ自動化して人間らしい仕事に集中していきたいですね!

サイボウズのオープンソースソフトウェアポリシーを紹介します

$
0
0

OSS準備室長を務めていた ymmt (@ymmt2005) です。 過去形なのは、OSS準備室は 7 月末で解散したためです。

OSS準備室では、サイボウズ社員がオープンソースソフトウェアに関する活動を行いやすくすることを主な目的として、会社の基本方針を「OSSポリシー」という文書にまとめる作業を行いました。

完成したOSSポリシーはCC0 (いかなる権利も保有しない、いわゆるパブリックドメイン)で広く他の企業の方々にも活用いただけるよう以下で公開しました。本記事ではその内容と、サイボウズにおけるオープンソース活動のこれまでとこれからを紹介いたします。

オープンソースについて

オープンソースソフトウェア(Open Source Software, OSS)とは、オープンソースの定義に基くライセンスで利用可能なソフトウェアのことです。オープンソースの定義(The Open Source Definition, OSD)は http://www.opensource.jp/osd/osd-japanese.htmlにて和訳が公開されています。短いものですのでぜひ一度目を通していただければと思います。

OSSの利用に際して大事なことは、問題が発生しても作者が解決してくれる保証はないということです。不具合や脆弱性は、基本的に利用者自身が解決する必要があります。有償でのサポートを提供している会社もあります。

OSSポリシー策定前の状況

昨今のソフトウェア開発でOSSを利用しないことはほとんどないと思います。当社ももちろん例外ではなく、kintone や cybozu.com のインフラでは数えきれないほどのOSSを活用しています。

利用に際して当然不具合をみつけたり自前で修正するということも良くあるのですが、会社としてこうしましょうという方針はなかったため、たとえば開発元に報告するといったことは各自の判断でされたりされなかったりしていました。

具体的に、当時のOSSに関する社内規程は以下二つしかありませんでした。

  • OSSの利用前にライセンスを確認する(そしてライセンス条件に従う)
  • 自社製のOSSを公開する際は所属部署の部長の許可を得る

そんななかでも、多くはありませんが以下のような活動をしていました。

OSS準備室について

OSSがここまで発展してきたのは、多くの人が様々な形でその開発に貢献してきたからに他なりません。 私達も多くのOSSを利用するにとどまらず、OSSの発展により寄与する存在でありたいと思います。

そこで社員のオープンソース活動を支援し、また貢献を促すようなOSSポリシーの策定を目的として、昨年12月に「OSS準備室」を設立しました。法務を含め、OSSに関係する各部門の代表者からなる部署横断の組織です。当時運用本部長だった私が起案し、責任者を務めました。

以下の成果をあげたのちに、後継組織である「OSS推進室(英語名称:Open Source Program Office, OSPO)」に業務を引き継いで 2018 年 7 月末を持って解散しました。

  • OSSポリシーを策定し、全社規程として起案(承認済み)
  • OSSポリシーを補完する細則にあたる「OSSガイドライン」の整備
  • 職務著作となる条件を大幅に制限(あとで解説します)
  • 他社の貢献者ライセンス同意書(CLA)の調査
  • 経営陣並びに社員向けにOSSポリシーとガイドラインの説明会を実施
  • OSSに関する専門組織「OSS推進室」を後継組織として起案

OSSポリシーの策定にあたっては、以下を参考にさせていただきました。

OSSポリシーの内容解説

公開しているOSSポリシーは、全社規程であるため取り扱う範囲を著作権、特許、商標のライセンスに限定しています。OSSに関する業務はライセンス関係以外に多々ありますが、それらは細則にあたる「OSSガイドライン」で取り扱っています。

前文

ポリシーを定める背景と目的を書いています。短いのでそのまま転記してしまいます。

本規程の第一の目的は、当社ならびに当社従業員が OSS 関連活動を過大な負担なく行えるよう支援することである。 そのために、当社、当社従業員または他者の著作権、特許権および商標権に関する事項を定める。

本規程の第二の目的は、当社がオープンソースコミュニティにおける良き一員であるために必要な規定を定めることである。 そのために、ライセンス違反への対応方針ならびに社員が発見した他者 OSS の不具合を報告する努力義務を定める。

注目いただきたいのは「社員が発見した他者 OSS の不具合を報告する努力義務」です。 サイボウズで働く社員は、利用しているOSSの不具合を発見したら開発元に報告するよう努めねばなりません。

著作権の帰属

会社の業務で作成した著作物は会社が著作者になります。正確には著作権法の職務著作の要件に該当する場合に限られますが、当社では入社時に以下のような誓約書に同意してもらっていました。

私がサイボウズでの業務遂行上、著作物を作成したときは、サイボウズの法人著作となる場合を除き、その著作権(著作権法第27条、第28条に規定する権利を含む)を別段の意思表示を要することなく、創作時にサイボウズに帰属させます。また、著作者人格権をサイボウズならびにいかなる第三者に対しても行使いたしません。

この規程そのままですと、例えば業務中に編集した .emacs.vimrcが会社のものということになってしまいます。また当社は働く時間も場所も非常に柔軟ですので一日のうちいつ業務をしているかが人によりばらばらで判断しづらい事情があります。

そこでOSS準備室で議論し、誓約書の内容を無効化し、会社に帰属する職務著作に該当する条件を以下のように絞りこむこととしました。

2.1. 当社の著作物 以下のいずれかに該当するものについては、その著作権が当社に帰属するものとする。

当社の極秘情報を含むもの
上長の明示的な指示または承認のもと作成されたもの

この規程により、「業務時間中であっても指示なく自発的に作ったソフトウェアは個人のもの」となります。 先述の .emacsはもちろん、自発的に書いたOSSのパッチも個人の著作物となるので、会社のルールに縛られません。

次に 2.2.2 の規程:

従業員が自己の所有する OSS プロダクトに対して自己が業務で作成した著作物を取り込む場合は、前項に定める手続きをしなくとも、当社から当該従業員に対し著作権が譲渡されたものとみなす。

これは個人で開発したOSSを業務で利用していて、業務中に必要な機能を追加することを想定した規程です。

指示された業務中に開発しているので会社の著作物が個人のOSSに混ざることになるわけですが、OSSであれば会社の著作物にしなくても誰でも利用できるわけですから、手続き不要で従業員に譲渡をしてしまおうというわけです。

従業員個人の著作物のオープンソース化および当社商標の使用

社員が自発的に当社製品に関する OSS を開発することがあります。

その際「kintone」や「サイボウズ」といった当社の商標を利用することが想定されるため、無用なトラブルを招かないよう注意する点を定めています。

当社著作物のオープンソース化

当社が管理する場所(github.com/cybozu等)であれば、自由に作ったOSSを公開していいルールとしました。従来は所属部長の許可が必要だったのですが、まだ一行もコードを書く前に形式的に申請をするケースが多かったので、社員の良識を信じて承認不要としました。

利用しているOSSにパッチを送る場合、最近は貢献者ライセンス同意書(CLA)への署名を求めるところが多くあります。CLAは多くの場合英語の法律文書ですので、主要な CLA をあらかじめ法務にて分析し、「署名可能 CLA 一覧」を作成することにしました。

署名可能 CLA 一覧にある CLA であれば、従業員は自分の判断で署名が可能です。多くの場合上長の同意も求められるのですが、個々の開発者が自分の判断で上長欄に署名して良いのです。

他者 OSS の利用

他者の OSS を利用する場合、ライセンスを確認して使用条件に従うことを書いてあります。

また前文で触れたように、利用している OSS の不具合を発見した場合は開発元に報告する努力義務を定めています。

当社 OSS への他者著作物の取り込み

当社が所有する OSS に他者の著作物を取り込むルールを記載しています。

6.1 は当社の CLA への同意としていますが、まだ CLA は準備中であるため運用していない規程です。

6.2 ではパッチをいただいた開発者への謝意をこめて、CONTRIBUTORS等のドキュメントに明記することを定めています。

ライセンス違反への対応

当社のOSSのライセンスに違反する利用を発見しても、60日以内なら訴えませんよとしています。

逆に当社内で違反があった場合、速やかに報告・是正することとしています。

OSSガイドラインの内容

OSSポリシーは全社規程ですので、具体的なことは書かれていません。 そのままでは社員が困ってしまいますので、詳細は「OSSガイドライン」にまとめています。

以下のような内容で構成されています。

  • 著作権や特許の基本
  • OSSライセンスの種類と使い分け
  • OSSにおける英語の使いかた
  • 署名可能 CLA 一覧
  • GitHub のリポジトリ管理

社内の事情が書かれているためすぐに公開はできないのですが、広く有用な部分はいずれ公開できると良いなと考えています。

OSS推進室(OSPO)について

OSS準備室の後継組織として常設の「OSS推進室 (OSPO)」を設置しました。 Open Source Program Office は Google や Microsoft も設置している、OSS活動に関する専門機関です。

詳しい説明は opensource.com の解説記事Linux Foundation の記事にあります。Google の OSPOは先述のように OSS 活動全般の方針をドキュメントで公開してくれています。Microsoft は github.com の管理などに利用できる、OSPO のためのツールを公開しています。

サイボウズの OSPO ではポリシーとガイドラインのメンテナンスに加え、社外のOSS組織への支援などに取り組んでいく予定です。

まとめと謝辞

OSSポリシーの策定にあたっては相当な期間と手間が必要でした。 当社と同じく、これからOSSポリシーを定めていかれる方が参考にしていただけるように、策定したOSSポリシーの全文を CC0ライセンスで公開しています。ご活用いただければ幸いです。

また、ご覧いただきました通り当社は社員のオープンソース活動を公私にわたり支援しています。 OSSに理解のある企業をお探しの技術者の方は、是非当社も候補に入れていただければと思います。

末尾となりますが、OSSポリシーの策定にあたっては、奥一穂氏(@kazuho)ならびに当社技術顧問の小崎資広氏(@kosaki55tea)にご協力をいただきました。ここに感謝の意を表します。

業務利用しているOSSの休日個人開発は業務か?

$
0
0

こんにちは、OSS推進室長の岡田(@y_okady)です。 先日公開したOSSポリシーについて、たくさんのご意見をいただきました。ありがとうございます!

その中の一つに、労務管理上の懸念についてのご指摘がありました。上長からの指示がなくても、業務利用しているOSSの休日個人開発は業務にあたるのではないか、というものです。

これについて、社員のオープンソース活動を支援する役割を担う「OSS推進室(OSPO)」で話し合って見解をまとめたのでご紹介したいと思います。

技術系イベントへの参加は業務か?

OSSの休日個人開発の話をする前に、技術系イベントへの参加について考えてみます。

サイボウズでは、業務に役立つ技術系イベントへの業務としての参加を推奨しています。イベントの規模は問わず、小規模な勉強会でも大規模なカンファレンスでも業務として参加可能です。業務として参加する場合、交通費や参加費を支給します。休日に参加する場合は休日出勤になります。もちろん、業務外で参加したいということであれば業務としての参加を強制することはありません。

この方針を明確に打ち出したのは3年前ですが、それ以前も業務としての参加を禁止していたわけではありません。しかし、業務として参加したいと申し出る人はほとんどいませんでした。参加を指示されたわけではない、自分が参加したいだけのイベントに業務で参加してもいいなんて誰も思わなかったのでしょう。

社員の自主的な取り組みを会社としてサポートすることで、社員はスキルアップや学びの機会を増やすことができ、結果的に会社への貢献に繋がると考えてこのような方針を取っています。

技術書は経費で購入可能か?技術書を読むのは業務か?

技術書の購入もこの方針に基づいて、業務に役立つ技術書を(福利厚生費ではない)経費で購入することができます。たとえばRustの勉強をしたいエンジニアがいたとして、担当業務でRustを使っていなかったとしてもRust本を購入可能です。

経費で購入した物でも私物でも、業務に役立つ技術書は業務時間中に読むことができます。休日に読む場合は休日出勤になります。一方で、業務に役立つとしても技術書を読むのは業務ではない、なんの強制もなくカフェでコーヒーでも飲みながらのんびり読みたいんだ、と考える人もいます。技術系イベントへの参加と同様に、業務外でのんびりと読んでもらって構いません。

OSSの休日個人開発は業務か?

ようやく本題です。上長からの指示がなくても、業務利用している(業務に役立つ)OSSの休日個人開発は業務にあたります。ただし、技術系イベントへの参加や技術書の読書と同様に、業務としての開発を強制することはありません。

自分の好きなOSSを自分のペースで楽しく開発したいのであれば、業務外で開発する方がきっと幸せだと思います。

おわりに

サイボウズでは、社員の自主的な取り組みを会社としてサポートすることが、社員のスキルアップや学習に繋がると考えています。また、サポートは強制するものではなく、社員が望めばいつでも利用できるものでありたいと思っています。社員には、上長からの指示ではない自主的な取り組みであっても業務になり得ることを理解してもらった上で、業務とするかどうかを自身で判断できることを期待しています。

それでは、引き続きサイボウズのOSSポリシーへのご意見をお待ちしております!

QAに配属されて1ヶ月経った話

$
0
0

はじめまして、8月に品質保証部に配属された新人の大塚と田村です! 本記事では、配属されたばかりの私たちがこの1カ月を振り返ってディスカッションをしてみました。

品質保証部の新人2人

自己紹介

田村 ななみ

Slash QAに配属。趣味は観劇。
Slash:cybozu.com共通管理(ユーザ管理やセキュリティ設定の機能)を開発しているチーム

大塚 純平

PSIRTに配属。好きな攻撃はパスワードスプレー攻撃
PSIRT:サイボウズ製品のセキュリティ品質向上のために活動しているチーム

品質保証部がどのような役割を担っているのかについては、こちらの記事が参考になると思います。 blog.cybozu.io

最初の1カ月で何をやった?

大塚:
配属されて1カ月が経ちましたが、これまでに何をやりましたか?

田村:
私はチームで必要な知識を身に着けているところです。 メンターさんに用意していただいた研修タスクアプリに沿って進めています。 具体的には今後使うツールの使い方を学んだり、製品の機能に慣れるための課題をやったりしてます。

大塚:
製品には慣れましたか?

田村:
少しずつですね。 私はcybozu.com共通管理の画面を今まであまり触ったことがなかったので、初めはどのような機能があるのか知りませんでした。 マニュアルに沿って一通り操作をしてみて、その機能をまとめるという課題に取り組んで、製品への理解を深めることができてきたと感じています。 その中でいろいろな方にお世話になりました。

大塚:
チームメンバーの印象はどうですか?

田村:
とっても優しいです。 分からないことがあったとき、質問すると素早く対応してくれます。 先輩社員さんとコミュニケーションの時間がたくさんあるので安心感があります。 毎日朝と夕方のミーティングの時間に気軽に質問することもできますし、 メンターさんがいらっしゃらないときは質問箱のアプリに登録することもあります。 Slackを使って海外拠点のメンバーに質問もします。

大塚:
海外拠点の方ともやり取りがあるんですね。

田村:
そうなんです。週に一度テレビ会議システムを使って海外拠点の方とリモートで打ち合わせをしています。

大塚:
打ち合わせへの参加もしているんですね。

田村:
しています。でも参加しても内容が追えないこともありますね……。

大塚:
それは僕も同じです。何の話をしているのかわからないことありますよね。

田村:
そうですよね。初めは知らない単語ばっかりだったので、打ち合わせの後に毎回質問していました。 メンターさんは基本的なことでも丁寧に説明してくれますし、難しい内容を含む打ち合わせに参加するときは事前に説明を受けることもあります。

大塚:
実業務への参加はしていますか?

田村:
少しずつ参加しています。今後リリースするバージョンの試験を一部担当しているので、今取り組んでいるところです。

大塚:
やっていて何か苦労などはありますか?

田村:
製品知識がまだ少ないので手順がわからず困ることがあります。 初めてのことばかりなので慣れるまでは簡単なことにも時間がかかったり作業が止まったりしてしまいます。 ただ、そういうとき周りの方が快く助けてくれるので、不安はあまりないです。

大塚君はPSIRTでこれまで何をやりましたか?

大塚:
製品理解を深めるために、パッケージ版の製品をインストールしたり、クラウド版のkintone, Garoon, メールワイズの簡易試験をしたりしました。 また、メンターの方から1日1~2時間くらい業務内容の説明を受けています。

田村:
例えばどんなことを教わっているんですか?

大塚:
PSIRTの業務内容についての説明です。 PSIRTは意外とたくさん業務があって、そのやり方を説明してもらっています。 聞いているだけだとわからないので、メンターの方と一緒に実際に業務をしながら学んでいます。

田村:
今後はどのようなことをするんですか?

大塚:
僕は9月からkintoneの担当として少しずつ業務に取り組んでいく予定です。

インターンに参加してどうだった?

cybozu.co.jp

大塚:
研修の一環として、8月のサマーインターンにインターン生として参加しましたね、どうでしたか?

田村:
もともとQAを体験したことのない人を対象にしているので、とても説明が丁寧でした。 今までの研修で自分がやってきたことが自己流であったことや、インターン生の成果物を見て人それぞれ違うことに気づくことができました。

大塚:
もし、学生時代に戻ったらインターンに参加したいですか?

田村:
そうですね、余力があれば参加したいです。大塚君は、学生時代もサイボウズのインターンに参加してたんですよね?

大塚:
僕は2年前のインターンに参加していました。

田村:
今回も参加しようと思ったのはなぜですか?

大塚:
僕が参加したときから内容が変わっていると聞いていたので、どう変わっているのか知りたかったからです。

田村:
実際に参加してみてどうでした?

大塚:
内容もやり方も変わっていて、年々進化していますね。今回は、インターンのメンター側が準備をしているのも見ていましたが、インターン生に楽しんでもらおうと工夫されているなと感じました。

田村:
次回のインターンではメンターをやるようですね。

大塚:
そうなんです。準備段階からやっています。今回参加してくれているインターン生が2年後には一緒に働いているかもしれないんですよね。実際に、配属されてからは、2年前に参加したインターンでメンターをしてくださった方の隣で仕事をしています。そう考えると当時のことを思い出して感慨深いものがありますね。

ミネルヴァの勉強会はどう?

blog.cybozu.io

大塚:
配属されたチームでの研修とは別に、ミネルヴァチームが主催している品質保証部としての新人研修もありますよね。 テスト技法や不具合管理の方法の講義などを受けました。 ミネルヴァの勉強会に参加した感想はありますか?

田村:
研修が整っているなと感じました。 研修内容がすごく考えられていると感じています。

大塚:
どういうとき、そう感じましたか?

田村:
品質保証部の様々なチームに所属している社員さんが講師としてそれぞれ専門の分野について教えてくれて、とても勉強になります。 今まで話したことがなかった社員さんと話す機会にもなるのが私は嬉しいです。 この分野はこの方に聞けばいいんだということを知ることができます。

大塚:
確かに。勉強会を機に今まで話したことない先輩社員とも関わりを持てるっていうのはとても貴重ですね。 今後仕事をしていく上でも活きてくると思います。

田村:
わからないところをkintoneの分報スレッド(作業内容や思っていることを自由につぶやく場所)に書き込むと、それを見た先輩社員の方が教えてくれるなどフォローが手厚くてありがたいです。

大塚:
途中で僕たちの困っていることとか、やりたいことを拾ってくれて、その先の研修に反映させてくれるのもありがたいですね。

田村:
本当に新人に対する教育体制が整っているなと思います。 

大塚:
新人以外も対象にしている勉強会もたくさん開催されていて、品質保証部全体の教育体制が整っているんですね。

配属された感想は?

大塚:
QAに配属されてどうでしたか?

田村:
配属されて良かったといつも思っています。 私はもともとITの知識も少なく、QAとしての経験も全くなかったですが、周りの人が親切なので安心して働くことができています。 毎日が楽しくて充実しています。 もともと、楽しく働ける社会人になりたかったので、理想の社会人生活が送れている気がして嬉しいです。

大塚君はPSIRTに配属されてどうですか?

大塚:
配属されてよかったなと思っています。 実は、配属先の希望をPSIRTかセキュリティ室のどちらに出すか悩みました。 配属面談の前に各部署の人に話を聞いて、最終的にPSIRTを選びました。

田村:
なぜPSIRTを選んだんですか?

大塚:
セキュリティ室の業務内容は大学で学んできた内容に近いですが、サイボウズに入ったからにはサイボウズの製品に関わりたいという思いが強かったからです。

田村:
その選択は正解だったと思いますか?

大塚:
配属前に戻ったとしてもPSIRTを希望します。 僕は学生の頃からセキュリティをやりたいと思っていたので、今こうして実際にやりたいことをできていることが感慨深いです。 特に僕の場合は人との巡り合わせと運がよかったんだと思います。 多くの方と関わって今ここでやりたいことができていることに、感謝です 。

今後の目標は?

田村:
私は今はまだまだですが、QAとして戦力になりたいと思っています。 自分の意見をちゃんと言えるようになりたいです。 業務を改善していくところにも興味があります。

大塚:
サイボウズはいろいろなことに挑戦ができる環境なので、どんどん挑戦していきたいです。 やったことがないことなのに逃げてやらないとかはしたくないと思っています。 今年は海外のカンファレンスにも参加しますし、それ以外でも自分が挑戦する機会があれば積極的に取り組みたいです!

田村:
1年目から海外出張にいくんですね。楽しみですか?

大塚:
やっぱり新しいことに挑戦するのは楽しみですね!頑張ります!

まとめ

  • 配属されたチームでの研修、ミネルヴァの研修がどちらも手厚くて安心
  • インターンに参加するという経験もできる
  • いろいろな挑戦ができる環境がある
  • 品質保証部に配属されてよかった!

最後に

このように品質保証部は新人も安心して成長でき、やりたいことに挑戦できる環境があります。
本記事を通じてサイボウズの品質保証部に興味を持った方は是非こちらをチェックしてみてください!

www.wantedly.com

モブ英作文と、異文化間コミュニケーション改善活動の話

$
0
0

こんにちは。東京品質保証部の臼井です。

日本国外にも上海(中国)とホーチミン市(ベトナム)に開発拠点を持つサイボウズ。エンジニアの日々の業務にも英語が必須…とまではいきませんが、英語が使えたほうが便利な場面に遭遇することは多々あります。今回は、そんなサイボウズ エンジニアの英語学習を支援する「モブ英作文」の取り組みと、異文化間コミュニケーションの改善を目指すコミュニケーションエンジニアリングチームの活動をご紹介します。

モブ英作文とは

名前から想像がつくかと思いますが、モブプログラミングに倣ってみんなでわいわいしながら英語の文章を書いていくという取り組みです。モブ英作文では最初に書き手がお題(書きたい内容)を口頭で他の参加者に説明してから、画面をモニター上に投影して書いていきます。他の人たちは書かれた文を見て、修正したい点を提案します。

作文するためのツールはふつうのテキストエディタでも何でもかまわないのですが、サイボウズでは自社製品であるkintoneのアプリをよく使っています。

f:id:cybozuinsideout:20180914114005p:plain

適当なところで一度保存してはまた加筆修正して、参加者全員が「もう直すところないよね」と合意できるまで繰り返します(上の例では、画面上から下へ①~④の順で修正が進んだ状態になっています)。このようにするのは、作成途中の状態を残すことで思考の過程を追えるようにするためです。

サイボウズではモブ英作文が学習目的で行われることが多いためにこのようになっていますが、業務で使う文章を書くなど、最終的に作文ができあがればそれでいい(お勉強はいらない)という場合はわざわざこのようにする必要はないでしょう。

効果

通常は参加者の間で英語力に多少なりともばらつきがあり、知っている(思い出せる)語彙や文法事項にも違いがあるので、各自が得意分野や知識を生かして他の人の苦手を補うことができます。疑問や質問があれば周りの人にすぐに相談しやすい雰囲気になっているのも利点の一つです。

一方で、人を集めて話し合いながら進めるという特性上、一人で書くよりも時間がかかる傾向があります。一人だと辞書を引いたり考え込んだりする時間が長い、という人なら、それほどデメリットにはならないでしょう。

進め方や注意点など

モブ英作文を進めるにあたって気をつけている点の一部を以下に説明します。このあたりは、作文の目的(業務で使うのか、練習としてやるのか)や参加者のスキルなどに応じて変わってくることもあります。

1. 日本語で下書きしない

これは翻訳になってしまうことを防ぐためです。一般に、翻訳には作文よりも高度な英語力が要求されます。慣れていない人がやろうとすると、翻訳元の日本語に振り回されて不自然な英語を書いてしまうことが多いです。

他にも、日本語で文章を書いてから英訳しようとすると

  • 概念的に英語にしにくい表現や、日本文化に深く結びついた語が入り込んでくる
    • 例: 「せっかくなので」「お盆休み」
  • 遠回しになる
    • 例: 「できないこともない」「ちょっとどうかと」「誤りという理解で正しいでしょうか」
  • 行間を読ませる書き方になる

といった現象が生じやすく、補足を追加したり、意訳したりする羽目になることもしばしば。

日本語を書くにしても、あとで英語に訳すなら訳しやすさを考慮しないといけないというわけですね。また、エンジニアの業務では日本語版と英語版の両方が必要になるのではなく、英語だけあればよいというケースのほうが多いので、日本語で文章を書いてもたいていはすぐに捨てる(だったら最初から英語で書けばいい!)という結果になります。

業務で日常的に翻訳をしているような英語力の高い人たちばかりが集まるなら「モブ翻訳」もよいかもしれません。

2. すぐにわからないところは置いておく

上掲のスクリーンショットにもあるように、すぐに単語が思い浮かばない箇所には日本語の単語を仮置きして後回しにします。内容が複雑な場合、下のように単語よりももっと大きい句や節といった単位にABCなどの記号を当てはめておくこともあります。

f:id:cybozuinsideout:20180913145433p:plain

英語が苦手な人ほど細かい部分を気にしすぎて「木を見て森を見ず」になってしまいがちなので、まずは文章全体の構成を設計することに意識を向けられるように、こういった方法をとっています。

文章構成としては "PREP"を推奨しています。PREPとは

  • Point (要点)
  • Reason (理由)
  • Example (例示)
  • Point (要点)

の順番で書く技法のことで、その構成要素の頭文字をとってこう呼ばれます。日本語話者が作文すると、どうしても背景情報を先、要点を最後にしてしまいがちですが、そういった癖を直す意味でもこの技法は役に立ちます。

3. 完璧を目指さない

サイボウズのモブ英作文で扱うのはお客様にお出しする文書ではありませんし、書き手も読み手も非ネイティブなので、多少おかしなところが残っていても仕方がないと割り切ります。一人で書く場合よりも読みやすくなっているな、と思えれば十分でしょう。

この点はプログラムの試験とも似ていまして、問題の検出と修正を繰り返せば繰り返すほど、新しい問題が見つかる確率は小さくなっていきます。費やすコストに対して得られるメリットが次第に減っていくので、やりすぎにならないよう合理的な範囲で実施する必要があるというわけです。

コミュニケーションエンジニアリングチームとは?

今回紹介したモブ英作文をはじめとして、サイボウズの各国拠点間の言葉の壁・文化の壁を乗り越えるためのサポートをするチームです。

コミュニケーションエンジニアリングチームが実施する異文化間コミュニケーション改善活動には "Project Cenote"というコードネームがつけられています。"Cenote"はメキシコのユカタン半島に見られる地下水脈の上が陥没してできた泉のことですが、これに壁を壊すイメージと "Communication Engineering (Not Only Translation and English)"の頭文字を結び付けました。その由来の通り、英語や翻訳だけにとらわれずにコミュニケーションの改善に向けて幅広いアプローチを目指しています(と言っても、やはり英語関連は多いですが)。

今までの活動は

  • 「QAで使える英語」「誤解されにくい日本語の書き方」「ベトナム語入門」など、語学系の勉強会の企画・開催
  • 日本・中国・ベトナムの各国の文化に関する勉強会の企画・開催
  • 開発系メンバーが日常業務で必要とするちょっとした翻訳や、英作文の添削

などです。勉強会の開催は、ミネルヴァチームからの強力な支援を受けています。

blog.cybozu.io

そして最後に重要なことですが、このコミュニケーションエンジニアリングチームには今のところ私一人しかいません。そこで!

We're hiring!

今回の記事を読んで、異文化間コミュニケーション改善活動に興味を持った方はぜひ弊社採用ページをチェックしてみてください。

募集要項/エントリー | サイボウズ 採用情報(新卒・キャリア)

コミュニケーションエンジニアリングは品質保証部のもとで活動していますが、製品の試験をしているわけではないので、採用の判断基準は製品担当のQAエンジニアとは多少異なります。このあたりも近いうちに募集要項に反映させていきたいと考えています。

もちろん、製品担当QAエンジニアとしてサイボウズで働きたいという方もお待ちしています。海外拠点との業務で困ったことが発生したときには、コミュニケーションエンジニアリングチームが精いっぱいサポートさせていただきます。


プロダクトのヘルプサイトをマークダウンに移行した話

$
0
0

こんにちは!開発部テクニカルコミュニケーショングループの仲田です。

皆さんマークダウン使ってますか?(唐突)
文書記法の一つで、プログラマーにとっては馴染みがあるものだと思います。サイボウズのプロダクト仕様書もマークダウンで書かれることが多くなっています。

ですが、公式ドキュメントを作る用途として採用される例はまだ少ないように思います。数ヶ月前になりますが、プロダクトのヘルプサイトをマークダウンに移行しましたので、今回はその話をします。

なぜ移行したのか

マークダウンに移行した動機は、一言で言うとヘルプサイトの制作や更新を効率化するためです。

サイボウズでは、プロダクトのアジャイル開発化を進めています。アジャイル開発では、ウォーターフォール開発と比べてリリース間隔が短縮されます。パッケージ製品がメインだった頃には、リリースは年単位で、短くても数ヶ月ごとというスパンでした。ところが、クラウド製品がメインになり、アジャイル開発の導入も進むと、リリースが毎月、毎週と短期間に繰り返されるようになってきました。このことは、ヘルプサイトの制作、更新にかけられる時間が短くなることを意味します。プロダクトだけでなく、そのヘルプも短期間で制作、更新し、リリースすることが求められます。

また、アジャイル開発では、実際に動く画面や機能を作成し、フィードバックを得ながら計画を修正していきます。要件やリリース計画を随時見直していくため、プロダクトのヘルプ制作の計画にも変化が付いて回ります。仕様が確定するまで待っていては間に合いません。

このような背景から、ヘルプサイトの制作や更新を大幅に効率化する必要がありました。

移行前の問題

マークダウンに移行する前には、CMSに記事を入力してHTMLやCSSを生成する、Movable Typeのような仕組みのCMSを使っていました。

f:id:cybozuinsideout:20180919142608p:plain
移行前のCMS

このCMSを使っていて、次の問題がありました。

  • リリース計画の変更に弱い
  • 記事の差分管理に手間がかかる
  • 翻訳結果の取り込みに手間がかかる

それぞれ、どういうことかお話します。

リリース計画の変更に弱い

アジャイル開発では、リリースの頻度が多くなるため、ヘルプの更新は計画立てて進めていかなければなりません。リリースタイミングが異なる要件Aと要件Bを記事Aに反映する必要があれば、まず要件Aを反映し、要件Aがリリースされてから要件Bを反映する、というように、順序立てて進めていきます。ただでさえ短い制作期間がさらに短くなってしまうだけでなく、記事の管理も複雑です。

リリース計画の変更によって、要件Aのリリースが要件Bよりあとになったりすると、さらに状況は複雑化します。要件Aを反映した記事Aをいったん反映前の状態に戻して、要件Bを反映した上で、要件Bのリリースに合わせて公開します。その後また要件Aを反映し直して、要件Aのリリースに合わせて公開する、という作業が必要になります。

わかりづらい例かもしれませんが💧要するに、変化が多いアジャイル開発に対応するためにはヘルプの記事管理が複雑化する、ということがおわかりいただければ大丈夫です。このような記事管理を手動でやっていくのは辛いですよね。

サイトの差分管理

もう一つの問題は、記事の差分管理の手間です。ヘルプの記事を追加したり更新したりする際には、公開前にわかりやすさや正しさなどをチェックします。チェックを依頼するときには、どういう目的でどこを変えたのかをチェック担当者に伝える必要がありますが、それに地味に時間がかかっていました。ヘルプの制作を効率化するためには、このような作業は自動化すべきでしょう。

また、ヘルプの運用では記事の変更履歴を残していくことも必要になりますが、手動で記録していると大変です。これも自動化したいところです。

翻訳の効率化

サイボウズではプロダクトを海外展開しているため、ヘルプサイトの翻訳が必要になります。翻訳の際には、CMSから出力されたHTMLファイルを翻訳し、翻訳結果をCMSに再度取り込んでいました。

f:id:cybozuinsideout:20180919142703p:plain
翻訳したHTMLをCMSに取り込む作業が必要

この取り込みには多くの時間がかかっていました。翻訳されたHTMLをそのまま公開すればいいんじゃない?と思うかもしれませんが、販売地域ごとにヘルプの記述を書き分けるための処理をCMSで行う必要があるので、HTMLそのままの公開はできない事情がありました。

また、機械翻訳がHTMLに弱い問題がありました。ニューラル機械翻訳が登場し、近年は機械翻訳の精度が目覚ましく向上していますが、HTML文書をニューラル機械翻訳にかけると、一部のHTMLタグが消えて構造が壊れることがよくあります。ニューラル機械翻訳は文章の構文解析は行わないため、仕組み上このようなトラブルが多くなります。マークダウンのようにシンプルな形式のほうが、ニューラル機械翻訳との相性が良いようです。

マークダウンとは

上記のような問題の解決のため、ヘルプサイトをマークダウンに移行しました。マークダウンについて改めて解説すると、文書を記述するための軽量マークアップ言語の1つです。見出し、本文、箇条書き、表などの文章構造を簡単な記法で表現することができます。たとえば、次のような書き方ができます。

見出し:

# レベル1の見出し
## レベル2の見出し
### レベル3の見出し

箇条書き:

* 番号無し箇条書きの1つめの項目
* 番号無し箇条書きの2つめの項目

番号付き箇条書き:

1.  番号付き箇条書きの1つめの項目
1.  番号付き箇条書きの2つめの項目

上記のような記法を覚える必要がありますが、慣れるとリッチエディターより素早く文書を作れます。ツールを選ばず、テキストエディターさえあれば文書を作れることもメリットです。「Microsoft Visual Studio Code」など、HTMLに変換した表示をプレビューしながら文書を書ける高機能なエディターもあります。

静的サイトジェネレーター

マークダウンをHTMLに変換する「静的サイトジェネレーター」と呼ばれるツールがあります。多数のツールがあり、Jekyll、HUGO、Next、Gatsbyなどが人気のようです。

サイボウズでは、HUGOを使っています。HUGOはGo言語で作られていて、コンテンツが大量になっても高速にHTMLに変換できることが特長です。マークダウンでヘルプ記事を作る際には、リアルタイムにHTMLに変換して表示を確認しながら記事を書いていくので、HTMLへの変換速度は重要です。ヘルプサイトは大規模になるため、速度を重視しました。

ヘルプサイトでは、注意書き、補足やヒントなど標準のマークダウンにはない表現を多用します。HUGOにはマークダウンを拡張する機能があり、これらのスタイルを定義できます。また、サイボウズのヘルプサイトでは、販売地域ごとの記述の書き分けがありますが、このような拡張も実現できます。

マークダウンにするメリット

マークダウンで記事を作る最大のメリットは、GitやSubversionなどのバージョン管理システムで扱いやすいことにあります。マークダウンファイルはシンプルなテキストファイルなので、バージョン管理システムで記事を管理すれば、いつ、誰が、どのような目的で、どのように記事を変更したのかを記録できます。

マークダウンに移行することで、ヘルプ記事をGitHubで管理できるようにしました。GitHubで管理すれば、記事の差分をブランチ単位で管理できます。プロダクトの開発要件と紐づけてブランチを作っていくことで、どの要件のためにヘルプのどこを変更するのかを管理しやすくなりました。要件の実装が完了しリリースされたら、それとタイミングを合わせて、その要件に対応するブランチを公開サイトにマージします(下図)。要件のリリース計画に変更があった場合には、ブランチをマージするタイミングをずらすだけで済みます。リリース自体がキャンセルされた場合は、ブランチを破棄するだけです。

f:id:cybozuinsideout:20180919142742p:plain
GitHubの運用:プロダクトの開発要件と紐付けてブランチを作る

記事のクロスチェックには、GitHubのプルリクエスト機能を活用できます。プルリクエストは、変更したファイルの反映をリクエストする機能です。「こういう変更をしたので、問題なければ反映してください」という依頼を出すことができます。変更を反映する権限を持つ担当者が承認すると、変更が反映されます。

このプルリクエスト機能を使ったチェックでは、チェックの際に記事の変更点を見やすく表示してくれます。先述のとおり、プロダクトの開発要件と紐づけてブランチを作るので、チェックの際には、どの要件に対応するためにどの記事をどう変えたのかを把握でき、効率よくチェックできます。

さらに、マークダウンファイルはシンプルなテキストファイルなので、翻訳も簡単です。マークダウンファイルを翻訳し、翻訳されたファイルをGitHubに保存するだけで、翻訳結果の取り込みが完了します。

記事の中にコメントを書けるメリットもあります。ヘルプサイトを運用していると、プロダクト開発チームやカスタマーサポートチームなどから依頼を受けてヘルプサイトに説明を追記することもよくありますが、そのような経緯をコメントで書いておくことで、他の担当者や後任の担当者に共有できます。

システム構成

移行後のヘルプサイト管理システムの全体像が下図です。

f:id:cybozuinsideout:20180919143433p:plain
移行後のヘルプサイト管理システム

ライターはマークダウンで記事を書き、GitHubに投稿します。先述のプルリクエスト機能を使って、書いた記事の公開をリクエストします。チェック担当者によって承認されたマークダウンファイルは、自動的にWebサーバーに展開され、HTMLに変換した上で公開されます。

同時に、マークダウンファイルは翻訳システムに取り込まれます。翻訳システムには、Memsourceを使っています。Memsourceで翻訳が完了すると、翻訳されたマークダウンファイルが出力され、GitHubに取り込まれます。日本語のマークダウンファイルと同様に、他国語のマークダウンファイルもWebサーバーに自動的に展開され、HTMLに変換した上で公開されます。

現在は、記事のチェックのところをさらに効率化すべく、自動化を進めています。文章のてにおはだけでなく、翻訳しやすい文章になっているかについても自動校正することで、翻訳の工程も合わせて高速化することを狙っています。

おわりに

今回は、ヘルプサイトをマークダウンに移行した経緯と、そのメリットについてお話しました。GitHubを使ったヘルプサイト管理では、ブランチの運用が肝になりますので、次回はそのあたりを書いてみようと思います。

もちろん、まだ課題もあります。大きな課題としては、拡張を加えたマークダウンファイルが翻訳システム(Memsource)にうまく取り込まれないことがあり、対処中です。Memsourceはマークダウン形式のファイルに対応しているのですが、先述のとおりサイボウズではマークダウンに独自の拡張を加えているため、それが影響してうまく取り込まれないことがあるようです。多国語展開するドキュメントをマークダウンで制作する場合、他社でも起こるトラブルだと思いますので、解決できたら共有していければと思ってます。

QAエンジニアのAgile Testing vol.2

$
0
0

こんにちは!松山品質保証部の北地です。Agile Testing投稿の第2弾です。 前回記事では、以下2点についてご紹介しました。

  • 私たちが抱えている問題(Agile Testing導入について開発チーム間で情報が共有されにくい)
  • 対策として社内でパネルディスカッションを開催する

今回はパネルディスカッションのテーマをご紹介します。 blog.cybozu.io

パネルディスカッションのテーマ

第1回のテーマは「セキュリティテスト」に決定しました!

対象4製品のQAメンバー、及びセキュリティテスト専門メンバー計8名をパネラーとしてパネルディスカッションを行います。なお、LT/パネルディスカッションは、9月から12月にかけて毎月1回開催することにしました。テーマは都度検討予定です。

「セキュリティテスト」に至った背景

テーマについては、ブレーンストーミング形式で出し合いました。

f:id:cybozuinsideout:20180925230250j:plain
東京-松山間でのリモート会議

挙がった案として、例えば「ウォーターフォールモデルからScrumに移行した際のテストの実施方法の変化」、「非機能要件の実施方法」、「テスト自動化へのQAの関わり方」などがありました。その中から、第1回のテーマとして「セキュリティテスト」を取り上げることにしました。

サイボウズでは製品を担当するQAメンバーとは別に、セキュリティテストを専門にしているPSIRT(Product Security Incident Response Team の略)メンバーがおり、セキュリティ品質の更なる向上のため脆弱性検証を実施します。そのため、リリースに向けて必要な検証を開発チーム外のメンバーに依頼することになり、調整コストが高くなったり認識の齟齬が発生したりするという問題が生じやすくなります。 このような背景があり、多くのメンバーが「セキュリティテスト」について良いノウハウがないかと強い関心を持っていました。セキュリティテストについてディスカッションすることで、チーム間のノウハウ共有を促進することを狙っています。

パネルディスカッションの進め方

テーマ決定後、パネラーを交えパネルディスカッションの進行について話し合いました。

f:id:cybozuinsideout:20180918084733j:plain
パネラーを交えた打ち合わせ
「セキュリティテスト」と一口に言っても、大きく分けると「プロセス」、「プロダクト」の2つのテーマに分けることができます。

  • プロセスの例:セキュリティテストの実施タイミングや実施単位、QAメンバーとPSIRTメンバー間での調整や情報共有の際に行う取り組みや段取り など
  • プロダクトの例:検証の実作業で行う攻撃方法やツール など

本話し合いを通じて、各パネラーがセキュリティテストを進める上でのプロセスや、工夫している点に関して情報共有したい想いが強いことがわかったため、今回は主に「プロセス」で議論できるよう進めることにしました。各開発チームによりセキュリティテストの進め方が違うため、本ディスカッションでは、以下のような内容を問いかけ、各開発チームの情報共有や意見交換を行う予定です。

  • セキュリティテストのテスト計画はいつもどのように立案しているか
  • QAメンバーとPSIRTメンバーはどのようなやり取りを行いながらテストを実施しているか
  • 脆弱性の問題が見つかった場合、QAメンバーとPSIRTメンバーはどのように連携しながら問題解決を図っているか etc..

次回予告

次回は、パネルディスカッションの内容を交えながらイベント当日の様子をご紹介します!

We are hiring!!

サイボウズでは「日々の仕事をカイゼンしたい」「いろんな人と繋がって学び合いたい」というカイゼン意欲をもった方がチャレンジできる環境があります。

キャリア採用 QAエンジニア | サイボウズ 採用情報(新卒・キャリア)
キャリア採用 QAエンジニア(ミドルウェア) | サイボウズ 採用情報(新卒・キャリア)
キャリア採用 テストエンジニア | サイボウズ 採用情報(新卒・キャリア)

ぜひ私たちと一緒に働きましょう!

分散ユーザー管理システム「etcdpasswd」の紹介

$
0
0

こんにちは、アプリ基盤チーム兼Necoプロジェクト所属の @ueokandeです。 本日はNecoで開発しているUNIXユーザーの管理ツールである「etcdpasswd」を紹介します。

github.com

etcdpasswdは、etcdをバックエンドに持つ分散型のユーザー管理システムです。 etcdpasswdは自律型の分散システムで、一時的にホストがダウンしても、次回起動時にetcdのユーザーを参照して同期します。 etcdpasswdはLDAPのようなNSS (Name Service Switch) が外部サービスに問い合わせるのではなく、etcdpasswdが各ホストにある /etc/passwdを更新します。

なぜetcdpasswdなのか

現在のcybozu.comデータセンターでは、各ホストのユーザー追加・更新は、MySQLでユーザー管理されており、管理者が適用したタイミングで各ホストに同期されます。 この方式はシンプルですが、スクリプトを実行した瞬間にホストがダウンしていた場合に、そのホストの更新が漏れてしまうという課題がありました。

forest user management architecture

etcdpasswdは、etcdをバックエンドに持つ分散型のユーザー管理システムです。 ユーザー情報はetcd上に記録されます。 etcdpasswdでは ep-agentと呼ばれるエージェントプログラムを各ホストにインストールします。 ep-agentはetcd上の変更を監視して、変更点をローカルに反映します。 これで、仮に対象ホストが一時的にダウンしてたとしても、次回復帰時に ep-agentが起動すれば最新のユーザー情報が適用されます。 ep-agentの起動は、通常systemdなどを設定しておけば、OS起動時に自動で起動するはずです。

etcdpasswd architecture

Necoではデータンターのブートサーバー上のユーザー同期に、etcdpasswdを利用しています。 ブートサーバーは、データセンターの初期構築や、踏み台が利用できなくなったときなどの緊急時に利用しています。 初期構築や緊急時などLDAPのようなNSSが使えない環境でも、etcdpasswdは利用できます。 またNSSとは違いローカルの /etc/passwdにユーザー情報を書き込むので、バックエンドのetcdに接続しなくてもログイン可能です。 たとえばバックエンドのetcdがクラスタ崩壊して接続できなくなったとしても、ユーザーはブートサーバーに無事ログインできます。

etcdpasswdの使い方

ep-agentはユーザーを同期する各ホストにインストールします。 ep-agentを実行すると、バックエンドのetcdを監視して、変更があれば各ノードにデプロイした ep-agentがローカルのユーザー情報を追加・更新します。

$ cat /etc/etcdpasswd.yml
endpoints: [ "https://10.20.30.1:2379", "https://10.20.30.2:2379", "https://10.20.30.3:2379" ]
tls-cert-file: /etc/etcdpasswd/tls-client.crt
tls-key-file: /etc/etcdpasswd/tls-client.key

$ sudo ep-agent
2018-09-28T04:17:27.883450Z boot-1 ep-agent info: "start sync" rev=1
2018-09-28T04:17:27.884434Z boot-1 ep-agent info: "finish sync" rev=1

管理者用のCLIツール etcdpasswdはetcdに接続して、etcd上に記録されてるユーザー情報を更新します。 まずetcdpasswdを利用する前に、いくつか初期設定を適用します。

# UID/GIDの開始番号
$ etcdpasswd set start-uid 2000
$ etcdpasswd set start-gid 2000

# デフォルトグループとデフォルトの追加グループ
$ etcdpasswd set default-group wonderland
$ etcdpasswd set default-groups sudo,adm

ユーザーの操作は etcdpasswd userサブコマンドで利用できます。 またetcdpasswdはSSHの公開鍵の埋め込みにも対応しており、etcdpasswd certサブコマンドで利用できます。 登録された公開鍵は ep-agentが各ユーザーのホームディレクトリ以下の .ssh/authorized_keysに配置します。

# グループ追加
$ etcdpasswd group add wonderland

# ユーザー追加
$ etcdpasswd user add mad-hatter
$ etcdpasswd user add march-hare

# SSH鍵の追加
$ etcdpasswd cert add march-hare id_rsa.pub

以上で登録したSSH公開鍵に対応する秘密鍵を使って、 ep-agentが動いているホストにログインできます。

また管理外のユーザーのパスワード認証を無効化する機能があります。 ブートサーバーの初期設定の時のみ、インストール時に作成したユーザーでパスワード認証します。 初期設定が終わるとそのユーザーは使わないので、初期ユーザーのパスワード認証を無効化します。 etcdpasswd lockerサブコマンドで、ユーザーのパスワード認証を無効化できます。

# aliceのパスワード認証を無効化
$ etcdpasswd locker add alice

etcdpasswd internal

etcdpasswdの内部を少し案内します。 デーモンプログラム ep-agentおよび クライアントツール etcdpasswdは共にGoで記述されています。 ep-agentはetcdの状態チェックをポーリングではなく、etcdのWatch APIを利用しています。

Watch APIはイベントベースの非同期の監視用のAPIで、etcd上のキーに対する操作があれば都度通知されます。 Watch APIは非常に高信頼で扱いやすいので、Necoでは多くの場所で利用しています。 etcdはMVCC (Multiversion concurrency control) データベースで、etcd上の全ての変更が履歴として残されて、それぞれにリビジョン番号がついています。 Watch APIでもリビジョン番号を指定でき、以前購読した続きからetcdの変更を監視できるので、重複・欠損なく全てのetcd上のイベントを購読することができます。

ep-agent/etc/passwdを直接編集せず、かわりに useraddコマンドなどを呼び出しています。 Necoで etcdpasswdを実行するブートサーバー上ではUbuntuがインストールされています。 シンプルな実装ですが、実用的な多くのディストリビューションはカバーできます。

まとめ

現在のcybozu.comのインフラは、手順をベースにした「自動化」が主でした。 しかし手順の自動化は不測の状態変更に弱く、その度に人間が対応していました。 Necoでは人が理想の状態を宣言し、それぞれのシステムは「自律化」することを目指しています。 それが安定した分散システムを構築するためにNecoでは必要なことで、そのひとつの成果がetcdpasswdです。

Necoではまだまだ紹介したいアプリケーションがあるのですが、また日を改めて紹介していきたいと思います。

Necoはツラくないクラウド基盤を作ってます、という話をしてきました

$
0
0

こんにちは、Neco チームの@dulltzです。

オープンデベロッパーズカンファレンス2018にて「ツラくないクラウド運用環境を作る」という発表をしました。

この発表ではインフラ刷新プロジェクト Neco の取り組みについてお話しました。

  • インフラ刷新プロジェクト Neco の目的
  • 実機構成の話
  • 実機のライフサイクル管理の話
  • サービス運用の話
  • 開発環境の話

せっかくなので本ブログでもかいつまんで説明します。

発表資料はこちら👉 ツラくないクラウド運用環境を作る - Speaker Deck

f:id:cybozuinsideout:20180912153157p:plain

cybozu.com のインフラ

cybozu.comは弊社が提供するSaaSです。 実機管理からサービス運用まで、自社の運用チームが面倒を見ています。 cybozu.comは2011年にリリースされ、現在ではクラウド契約2.5万社100万ユーザ超のサービスに成長しました。

f:id:cybozuinsideout:20180912153436p:plain

しかしユーザ数が増えるにつれ、現行インフラにつらい点が見つかってきました。

ひとつ目は機材の運用コストです。 機材を修理に出すオペレーションのために毎週1人日の工数がかかってしまっています。

ふたつ目は性能のスケーラビリティです。 DBに高負荷がかかり障害が起きるケースが発生しています。

f:id:cybozuinsideout:20180912155033p:plainf:id:cybozuinsideout:20180912160004p:plain

インフラ刷新プロジェクト Neco

前述のつらさを解消するため、サイボウズでは Neco というプロジェクトを始動しています。

Neco は運用コストの劇的な削減スケーラビリティの向上を目標に掲げて、 新たなクラウド基盤を構築するプロジェクトです。

この目標を達成させるため、設計方針を以下の3つに定めました。

  • 宣言的なアーキテクチャスタイル
  • ソフトウェアで定義する
  • 自動テストを徹底する

f:id:cybozuinsideout:20180912172936p:plain

ここからは 機材構成、機材のライフサイクル管理、サービス運用、開発環境について具体的な話を見ていきます。

機材構成

まず機材構成について話をします。

現行のインフラでは、 L4ロードバランサ、L7ロードバランサ、キャッシュサーバ、DNSサーバ、サービスデプロイ用のコンピュートサーバ、ストレージサーバなど、 用途ごとに異なる機材構成をとっています。

f:id:cybozuinsideout:20180912173042p:plain

この構成には 増設・退役オペレーションが大変というつらさがあります。

そこでNecoでは 汎用のネットワークスイッチとラックから構成し、 用途はソフトウェアで定義することにしました。 これにより増設・退役オペレーションは大幅に楽になります。

f:id:cybozuinsideout:20180912174338p:plain

機材導入フローをアニメーションにしてみました。 こんな感じで人が機材管理ツールに情報を登録してサーバをToRのスイッチに繋げば、 あとは機材管理ツールがよしなにやってくれます。

f:id:cybozuinsideout:20181004151411g:plain

Neco ではこの機材管理ツール sabakanを自作しています。

f:id:cybozuinsideout:20180912181107p:plain

sabakan は各ネットブート用サーバ上に配置されることを想定しており、etcd によって整合性を保ちながら動作します。 sabakan はネットブートサーバとして機能するために以下の機能を持っています。

  • UEFI HTTP Bootサーバ機能
  • Ignition(CoreOSをプロビジョニングするためのユーティリティ) を組み立てる機能
  • Ignition を配信する機能
  • ファイル配信機能

ちなみにファイル配信機能を通じてアップロードされたファイルを sabakan の起動しているホスト間で自動分散するように作られています。 この機能の実装にも etcd が利用されています。

f:id:cybozuinsideout:20181004151444g:plain

機材のライフサイクル管理

現行の機材ライフサイクル管理で困っていることの中に 実際の状態と管理DB記載の状態とが乖離するケースの存在があります。

f:id:cybozuinsideout:20180927192746p:plain

これについて Neco では 機材管理ツール sabakan に保存した状態をプライマリデータとし、 残りのシステムはその状態に収束するように動作する、 あるいはモニタリングツールが故障を検知し自動でプライマリデータを更新することにしました。

機材退役フローをアニメーションにしてみました。 こんな感じで 人は四半期に一度修理対応するだけという運用を目指しています。

f:id:cybozuinsideout:20181004151511g:plain

サービス運用

次にレイヤーを上げてサービス運用について話をします。

現行インフラのサービス運用におけるつらさは主に2つです。

  • 性能面のスケーラビリティ
  • デプロイツールの複雑化

まず性能のスケーラビリティについて。今は主にストレージのスループット回りで問題になっています。

f:id:cybozuinsideout:20180927194247p:plain

Necoでは NVMe SSDのような高速なデバイスを使用することと、計算資源の割り当てを柔軟に設定可能なアーキテクチャを採用することで解決します。

さらにデプロイツールの複雑化について。 現在のインフラでは、手続きを自動化するスクリプトを書いていった結果、 暗黙的に期待する実行順が生まれ、ツールの取り扱いが難しくなってしまいました。

これについて、Necoではクラウド基盤の管理を宣言的なAPIで行えるようにすることで解決したいと考えています。

このような経緯を元にサービスを載せる環境を考えた結果、Kubernetesの採用を決めました。

f:id:cybozuinsideout:20180928115034p:plain

ただし Neco の本番環境では AWS などの IaaS を使わないので、 Kubernetes を採用してその上で動くアプリケーションのデプロイがつらくなくなったとしても、 Kubernetes の運用自体がつらいままだとしたらあまり意味がありません。

これをふまえて Neco では Kubernetes のデプロイ・アップデート作業を宣言的に行うツール CKEを開発中です。 CKE はクラスタ状態を常駐監視し、望む状態との差分を埋めるように適用していく挙動をするデプロイツールです。

f:id:cybozuinsideout:20180928115333p:plain

開発環境

開発環境について話をします。ここでいう開発環境とは開発者の手元のマシンではなく、本番環境と同じようなマシンとネットワーク構成からなる開発用の環境のことです。

現行のクラウド基盤では開発環境を開発者間で共用しています。その結果、環境をゼロから作り直すような操作は基本できない状況があります。

f:id:cybozuinsideout:20180928115415p:plain

そこでNecoでは各開発者がGCPインスタンス上に仮想データセンターを構築しその上で作業をできるようにしました。

f:id:cybozuinsideout:20180928115437p:plain

この仮想データセンターはKVMやLinux Bridgeなどから構成されるのですが、 この環境構築を宣言的に行えるツール placematを開発しました。

実際にNecoではこの環境の上で各ツールの開発を行っています。 また複数ホストを起動するような大規模な自動化テストにも利用しています。

成果物を OSS にしています

ちなみにNecoでは成果物のほとんどを 1コミット目からOSSとして公開しています。 各ツールの詳細な解説記事もそのうち投稿される予定です。

最後に

Neco は既存のアーキテクチャを一気に改善する野心的なプロジェクトです。 モダンなインフラを構築したい方、OSS を活用・貢献したい方、分散システムの経験を積みたい方、是非 Neco チームにお声がけください。

www.wantedly.com

サイボウズサマーインターン2018 報告その1〜インフラ刷新プロジェクトコース

$
0
0

みなさんこんにちは、アプリ基盤チーム兼Necoプロジェクト所属の @ueokandeです。

この夏もサイボウズではエンジニア向けのサマーインターンを東京・大阪・松山オフィスで開催しました。 今回はインターンのコースの1つである「インフラ刷新プロジェクト」コースの様子について紹介したいと思います。

集合写真

インターンの概要

インフラ刷新プロジェクトコースでは、8月6日〜10日と20日〜24日の2回開催しました。 それぞれの日程では学生が3名ずつ、合計6名の学生が参加してくれました。

サイボウズでは「Neco」と呼ばれるインフラ刷新プロジェクトが進んでいます。 インフラ刷新プロジェクトコースでは、実際にNecoで開発しているアプリケーションを触ってもらい、Necoで開発してるアプリケーションやサイボウズのインフラについて学んでもらいました。 このコースではリアルなNecoプロジェクトの活動を肌で感じてもらうため、実際に社内やcybozu.comで利用するコードを触ってもらいました。

インフラ刷新プロジェクトコースでやったこと

コースでは、Necoの開発タスクから、取り組めそうなタスクをピックアップしました。 インターンでは実際に機能を追加するまでの設計・実装をしてもらいました。 開発の進め方は実際にNecoでやっているように、kintone上でコミュニケーションをとったり、開発メンバーによる本格的なレビューもしました。 そのうえで、アプリケーションのコードだけでなく、テストコードやドキュメントなども書いてもらいました。

学生さんが書いたコードはレポジトリにもマージされ、コントリビュータにも登場しています!

sabakanのContributors

以下、いくつか取り組んでもらったタスクを抜粋します。

  • 機材情報にラベルを付与する: Necoではデータセンター内の物理機材を管理すために、sabakanというアプリケーションを開発しています。 sabakanは各機材のシリアル番号や格納ラック、IPアドレスなどを保持します。 このタスクでは、機材情報にラベルを付与できるように、sabakanの機能追加をしてもらいました。
  • ブートサーバーでカーネルパラメーターを設定: sabakanは機材データベースだけではなくネットワープブートする機能があります。 ブート時のカーネルパラメーターでは、QEMUのシリアルコンソールを有効にしたり、IOスケジューラーを設定をしており、これまではsabakanにハードコードしてました。 このタスクでは、sabakanのカーネルパラメーターをユーザーが自由に設定できるよう実装してもらいました。
  • Kubernetsクラスタのブートストラップ: NecoではKubernetesを構築・管理するためにCKE (Cybozu Kuberenetes Engine)というアプリケーションを開発しています。 CKEは対象ノードに対して、Kubernetesコンポーネントをデプロイして、Kubernetsクラスタを構築・管理します。 インターンではKubernetsコンポーネントの1つであるkube-proxyをデプロイする機能を実装してもらいました。

勉強会

取り組んでもらっているタスクとは別に、インターンを通して勉強会をいくつか開催しました。 デザイングループの小林(@sukoyakarizumu)によるWebアクセシビリティの勉強会がありました。 インフラ刷新プロジェクトコースでも、KubernetesやetcdやGoの勉強会も開催しました。

勉強会

最終発表&懇親会

最終発表は他のコースとの人たちも参加して、社員も含めて50人ちかくの人たちが参加しました。 テレビ会議システムを使って大阪・松山拠点とも接続し、合同で発表や質問を交わしました。 他のコースの発表もみんな興味津々で、活発な議論や意見交換が行われました。

最終発表で発表してるインターン生最終発表で話を聞いているインターン生

成果報告会のあとは打ち上げです!

懇親会で乾杯している様子

インターン生たちの感想

最後に、インターン生から感想を頂いたので、いくつか紹介します。

実際の業務で使用されるアプリケーションの開発にかかわることができたのがよかったです。 OSSだったので自分のGithubアカウントがContributorに入っていて感慨深い。 現場で働く雰囲気みたいなものを少しは知ることができたように思いました。 職場の雰囲気が明るく、過ごしやすい環境でインターンができて本当に良かったです。 実務に関わる機会はなかなか得られないので、今後の就職活動でも大いに参考にさせていただきたいと思います。ありがとうございました!

 

実際のプロダクト開発に携われると思っていなかったので驚きましたが、そのほうが自分も責任をもって開発ができたと感じました。 コンテナを使うような今どきのインフラ整備の初期段階に関わることができ、プログラムの実装や関連技術についての勉強会も適宜必要に応じてしていただき、ためになりました。 インフラ関連のインターンが少ない中、実際の実務を体験できる内容で良い経験でした。想像していたよりも内容が濃くて、良い意味で期待を裏切られた感じでした。

 

実際の業務で、難易度が低くもなかったので自分を燃やし尽くすことができました。 オンプレのサーバ運営を知ることができたのはありがたいです。 期間が短く、短期集中できるのはよかったです。 普段体験できない未知の領域に踏み込むことができ、かつ自分の力を総動員して立ち向かえる素晴らしいインターンでした。 一週間ありがとうございました。

まとめ

インフラ刷新プロジェクトコースの開催は今年が初めてとなります。 AWSなどのパブリッククラウドが全盛の時代、インフラの低レイヤな部分に触れる機会はすくなくなっています。 しかし、AWSを使っていてもトラブル発生時にはカーネル周りや低レイヤーの知識は必要になってきますし、サイボウズ規模のクラウドをオンプレミスで運営している会社もそう多くありません。 このインターンを通じて、少しでもインフラ技術の楽しさを伝えることができたのであれば、我々としては大成功のインターンだったと思います。

自分にとっても初めてのインターンシップ受け入れでしたが、たくさんの学生と交流できて楽しかったです。 またインターンで取り組んでもらった作業も、最終的にはマージして、サイボウズのコードに成果として取り込まれて、個人的にもよいインターンシップを開催できたと思います。 学生の皆さんの、今後の活躍も期待しています!

サイボウズサマーインターン2018 報告その2 〜 モバイルアプリ開発コース

$
0
0

f:id:cybozuinsideout:20181002140355j:plain

こんにちは!モバイルチームの刈川です。 この夏に開催されたエンジニア向けのサマーインターンシップ、前回はインフラコースの紹介でしたが今回は「モバイルアプリ開発コース」の紹介をしたいと思います。

2年目を迎えるモバイルコース

サイボウズのサマーインターン自体は今年で4年目になりますが、モバイルコースは去年新設されたので今年で2回目の開催になります。 5日間の中で様々な体験を行えるのは全コースで共通ですが、モバイルコースでは kintone の新規モバイルアプリを題材に、実際のソースコードや開発プロセスに触れてもらうことでモバイルエンジニアの1週間を体験してもらいました。(詳しい日程などはこちら

大まかな流れ

第1回目は8月6日に、第2回目は8月20日に行い、参加人数はそれぞれ3名ずつとなりました。

以下は大まかな時間割です。 f:id:cybozuinsideout:20180828163352p:plain

やったこと

f:id:cybozuinsideout:20181002141650j:plain
メンターと参加者でモブプログラミング

今回扱ったアプリはリリース前のものなので、主に新機能や足りない部分の実装を担当してもらいました。 例えば以下のような要件です。

  • ブックマーク機能
  • 未対応フィールドの実装
  • 全文検索 など

開発はスクラム形式を採用し、参加学生の3名とメンターをひとつの開発チームとみなしてスクラム開発を行いました。 モバイルコースは開催時期によってiOSアプリまたはAndroidアプリを題材にしているのですが、今回はiOSアプリの開発です。

主に必要な周辺技術としては以下のようなものが挙げられます。

  • Swift4
  • RxSwift
  • Xcode
  • AutoLayout
  • MVVM
  • Git / GitHub

もちろんこれらの技術を完璧に使いこなせる必要はなく、分からないことがあればメンターに聞いたり参加者同士で相談しながら開発を進めていきました。

進めかた

インターンではただ与えられた機能を実装するのではなく、その機能の仕様検討の段階から参加してもらいます。 スクラム開発の手法にしたがって、以下の手順で開発を行いました。

  • プロダクトバックログのリファインメント(仕様検討)
  • かんばんの作成(タスク化)
  • 実装 / コードレビュー
  • デイリースクラム(朝会)

最終日には成果発表を行いました。

f:id:cybozuinsideout:20181015142809j:plain

技術以外のこと

せっかくインターンに来てもらったので、サイボウズという会社を知ってもらうためにも技術的なこと以外も体験してもらいました。 ランチに行ったり、参加者の希望を聞いて社内で話してみたい人との面談を設定したり、社内勉強会やイベント等に参加してもらったりと様々です。

f:id:cybozuinsideout:20181015144833j:plain
モバイルチームメンバーとのランチ会
f:id:cybozuinsideout:20181002142349j:plain
社長とのランチ
f:id:cybozuinsideout:20181002142522j:plain
アクセシビリティ勉強会へ参加

インターン生の声

参加したインターン生の皆さんからいくつか感想を頂いたのでこちらでも紹介したいと思います。

多様性や個人を尊重する社風は嘘ではなく、台風の前日は8割方空席で大変驚きでした。リモートワークでMTGするエンジニアさんも当たり前にいたのが印象的です。 ファミリーdayでは子供を連れて出社してきたエンジニアさんがいたのも印象に残っています。


これまで自分のスキルに合うようなメンバーとチームを組む機会がなく、一匹狼でアプリ開発をしてきたため、プログラミングスキルが同じレベルの人とチームを組んで開発ができるというのは貴重な経験でした。 社会人プログラマと独学でやってきた学生プログラマの差を実感することができました。自分で取り入れたい心がけや技術などを沢山蓄えられました。 サイボウズの社風はインターン前に思っていた通り、かなり自分の性格に合っていると思いました。何より公明正大に働く人々の人となりに共感しました。


サイボウズの事をよく知ることができたし、圧倒的成長もできたいい機会になりました!1週間なのにとても充実していて、同じコースのインターン生の方と友達にもなれて本当にいい機会になりました!!!今回のインターンで学んだことを今後も生かしたいと思います!ありがとうございました!!!

f:id:cybozuinsideout:20181015143854j:plainf:id:cybozuinsideout:20181015143754j:plain
モバイルコース(+メンター)のみんなと

まとめ

昔からサイボウズはモバイルをやっている印象が弱いと言われることが多いのですが、 サマーインターンシップでモバイルコースが新設されたり、モバイルエキスパートチームが設立されたりと、ここ数年でモバイル需要が高まってきています。 気になっている方はきっと来年も開催されるインターンシップ/モバイルコースでサイボウズのモバイル開発を体験してみてはいかがでしょうか。是非お待ちしています!

サイボウズサマーインターン2018 報告その3 〜Webサービス開発コース (kintone)

$
0
0

こんにちは、kintone開発チームの榎原です。

サイボウズでは、8月から9月にかけて、5日間のサマーインターンを3回開催しました。
東京集合写真大阪集合写真

今回はWebサービス開発コースの様子をご紹介します。

インターンの概要

Webサービス開発コースは、東京・大阪・松山の3拠点で行いました。
Webサービス開発コースでは、サイボウズが提供しているクラウドサービス「kintone」に対して、実際にお客様から寄せられた要望を参考に、新機能のプロトタイプを作ってもらいました。
また、単に機能の実装だけでなく、 サイボウズの開発チームが普段行っている開発プロセスに沿って進めることで、実際のkintone開発業務の一連の流れを体験してもらいました。
各回とも、複数拠点で開催したことで、オンライン上のコミュニケーションやTV会議越しでのミーティング等、サイボウズらしい開発を体験してもらえたと思います。

インターンの内容

1日目

1日目は、インターンについてのオリエンテーションを行ったあと、人事やメンターと自己紹介を兼ねたランチ会を開催しました。
その後、kintoneを実際に使ってもらいながら、機能を開発する上で必要となる知識を身につける練習問題に取り組みました。

2日目

2日目は、まずお客様からの声を参考に選んだ要望リストから、各自が取り組む課題を選びました。
その後、ユーザーストーリーや利用シナリオを検討して、実装する機能の仕様書を作成しました。

3-4日目

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

5日目

5日目は、成果発表会を行いました。
成果発表会では、実装したプロトタイプの紹介やデモ、インターンを通じて学んだことなどを紹介してもらいました。
成果発表会には、たくさんの社員が参加して質疑応答や活発な意見交換が行われました。

インターンで作ったプロトタイプ

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

お気に入りアプリリストの並べ替え機能

kintoneのポータル画面では、お気に入りのアプリ一覧を表示することができます。
ただし並び順はユーザーがお気に入りに登録した順となっており、後からユーザーの希望する順序でアプリを並び替えることはできない状態でした。

このプロトタイプでは、お気に入りアプリを並べ替えるボタンを配置し、ユーザーが普段見たいアプリの並べ替えを実現しました。 プロトタイプ_アプリ並べ替え

コメント編集機能

kintoneのスレッドは、一度投稿したら編集できません。
投稿に紐付いた返信があると、誤った情報を書き込んでしまったとしても補足することしかできず、訂正できません。

このプロトタイプでは、編集ボタンを追加して、投稿後もダイアログで編集可能にしました。 プロトタイプ_コメント編集ダイアログ

インターン生の感想

今回Webサービス開発コースに参加した方の感想を一部ご紹介します。

濃厚な5日間が過ごせました。 メンターの方とのペアプロやモブプロで効率よくインプット・アウトプットできました。 成果発表で多くのインターン生が社内の雰囲気の良さや働く環境の良さに言及していたのが強く印象に残っています。 参加者の満足度が非常に高いインターンだとと思います。 サイボウズが好きになりました!5日間ありがとうございました!


普段大学の演習や趣味での開発では中々見られない、とても大規模なプロジェクトに触れられたのはとても貴重な経験でした。 また、モブプログラミングやスクラム開発など、今回配属されたkintoneチームで普段やっている開発に近い段取りを経験することもできた点もよかったです。 今回のチームには、大阪オフィスからリモートで参加しているメンバーが居て、最初は戸惑いましたが意外と快適だったので驚きました。


モブプログラミングという手法を肌で感じたり、リモート作業がしっかり運用されていれば案外いけるということがわかりました! サイボウズの社員さんが本当に各々の働き方をしていて、それを会社として尊重している文化が本当にすごかったです。


まとめ

5日間という短い期間で、仕様検討からプロトタイプの実装まで取り組んでもらいました。
サイボウズのエンジニアが日々実施している開発プロセスに合わせて課題を進めることで、実際の業務のイメージを感じてくれたようです。
また、たくさんの社員と交流して、サイボウズの文化や雰囲気を感じてくれたと思います。
今回学んでもらったことを活かして、学生の皆さんが今後活躍してもらえると嬉しいです!


LT大会!大阪のエンジニアが好きそうな話──Cybozu Meetup Osaka 開催レポート

$
0
0

はじめまして、今年9月に中途で入社したkintoneプログラマーの石井です。

2018年10月2日(火)に、サイボウズ大阪オフィスにて『Cybozu Meetup Osaka 大阪のエンジニアが好きそうな話』を開催しましたので、その内容をレポートします。

f:id:cybozuinsideout:20181024124328j:plainf:id:cybozuinsideout:20181022135020j:plain

はじめに、サイボウズ大阪オフィスのご紹介

はじめに少しだけ、サイボウズ大阪オフィスのご紹介を。

サイボウズ大阪オフィスは、梅田阪急ビルオフィスタワーの35階に位置し、営業やシステムコンサルタント、Webアプリケーションエンジニアのメンバー、約30名が在籍しており、開発メンバーは主にkintoneの開発を行っています。略歴としては、2014年にグランフロント大阪に大阪開発オフィスがオープン。その後、2015年に現在の梅田阪急ビルオフィスタワーに移転・販売拠点と統合し、今の形になったそうです。

個人的なおすすめポイントとしては、オフィスビルの35階に位置していることもあって、オフィスからの眺めがとても良いところです。 まずそこ?とツッコミを受けそうですが、デスクから開けた景色が見れるので、個人的にはかなりおすすめなポイントです。 また、大阪梅田の主要駅から徒歩数分の好立地なので交通の便も良く、オフィスビル近くに食事処が多いので、雨の日でも濡れずにおいしいお昼ご飯にありつけるのもいいところです。

また、大阪オフィスには小さなお子さんのいるエンジニアも多く、在宅勤務や勤務時間の変更でライフワークバランスを維持しつつ、みんなでまじめにモノづくりをしています。 私は入社後1ヶ月で、さっそく勤務時間を変更させてもらい、仕事と家族の時間を両立しています。 自身の希望で働き方を調整できるので、サイボウズはとても働きやすい会社だと実感していますよ。

本題、大阪のエンジニアが好きそうな話

……と、話がそれてしまいましたが、今回はそんなサイボウズ大阪オフィスの増床を記念したもので、 サイボウズ大阪オフィスでは約一年ぶりのMeetup開催となりました。

当初は、9/4(火)の開催を予定しておりましたが、台風21号の影響で残念ながら延期に…… 今回も台風24号により再延期の危機でしたが、無事開催することができました。 ご参加及びご登壇いただいた皆様ありがとうございました。

今回のテーマは『大阪のエンジニアが好きそうな話』として、参加者の方からも登壇者を募ってLT大会を行いました。 リモート開発やお金(給料交渉)の話、おいしいランチについてなど、まじめな話から少しくだけた話まで、大阪らしく振れ幅の大きなLT大会となりました。 みんなでお寿司とお酒を片手に、ワイワイガヤガヤしておりました。

トークセッション

はじめに、トークセッションでは、サイボウズから2件の発表を行いました。

大阪-松山-東京-自宅をつなぐリモートスクラム開発

By 太田 絵一郎(@kigh)

1件目はkintone開発リーダの一人である太田から、リモートスクラム開発で得られた知見を発表しました。 こちらはDevelopers Summit 2018 KANSAI(通称、デブサミ関西)で発表した内容をブラッシュアップしたものです。

以下のスライドはデブサミ関西のもの。

speakerdeck.com

現在、kintoneチームでは、開発メンバーが大阪、松山、東京の3拠点に分散して、スクラム開発を行っています。 スクラム開発では密なコミュニケーションが要求されますが、リモートではコミュニケーションの壁ができてしまう。。 そういった難しさを日々改善していき、今のkintone開発チームがあります。 今でこそ、拠点間をテレビ会議システムで常時接続するなどして、他拠点のメンバーを身近に感じることができますが、試行錯誤の積み重ねがあったのですね。

でも最難関のリモートタスク、リモート飲み会はまだ道半ば……

サイボウズの給与交渉戦 第2ラウンド

By 佐藤 鉄平(@teppeis)、三苫 亮(@mitomasan)

2件目は、開発本部のボスの佐藤、kintoneプログラマの三苫から、サイボウズの給料事情について発表しました。

前半の従業員パートでは、実際の経験を元にした、給料交渉術について。 こちらは、実際の給料の上り幅(パーセント表示ですよ)なども示され、笑いに満ちた経験談の発表となりました。 結論として、上がった下がったは重要じゃないけど、納得できるようにベストを尽くそう!とのことですが、お給料は上がった方がうれしいですよね。

f:id:cybozuinsideout:20181022133419j:plain

(※ 以下のスライドは2017年のものですが同じ事例を説明しています。)

www.slideshare.net

後半はBossSideとして、サイボウズの市場価値ベースの給与評価について発表しました。 こちらは、参加いただいた皆様よりも、サイボウズ社員の方が集中して聞いていたかもしれません。 私はその日一番の集中力が発揮されました :-)

www.slideshare.net

大阪について好き勝手しゃべるLT

ここからは、5名の方に登壇いただき、好き勝手しゃべっていただきました。

大阪っぽくおせっかいする話

By 榊原 昌彦さん(@rdlabo)

榊原さんからは、サイボウズのWebサイトをレビューした話。なんておせっかい!

f:id:cybozuinsideout:20181022133739j:plain

なんかHTML中にidが2つあったりと、思わず苦笑いな指摘もありましたが、ファイル圧縮してもOSSのライセンスが残ってたりしてGoodとのことでした。

ちなみに、SEO対策は100点だったみたいです。やるなサイボウズ!

GraphQL SQL

By ちまめさん(@chimame_rt)

ちまめさんからは、技術的なお話。GraphQLというWebAPI用のクエリ言語(のライブラリ)についての発表でした。

SQLのようなクエリを、WebAPIで実行できるようにするための言語みたいです。 不勉強のため私はGraphQLというものを初めて知りました。勉強してみようかな。

speakerdeck.com

エンジニアが好きそうな話

By 松下 航平さん (@QoopMk)

松下さんからは、大阪のおいしい昼飯処について。

松下さんはリモートで仕事をされることが多いそうですが、リモートだと通勤に時間がかからないので、その分お昼に時間の余裕を持たせて仕事の糧としているみたいです。 今回はそんな日々で開拓した、おすすめのお昼ご飯の発表でした。一言でいうと飯テロってやつですね!

紹介されたお店は以下のとおり。(リンク先は食べログ)

  1. il PePe - 北新地(イタリアン)
  2. かしわや とりあん - 中津(居酒屋)
  3. ラ ピッツァ ナポレターナ レガロ - 福島(ピザ)
  4. 藤乃 - 北新地(そば)

おいしそうなお店が多かったので、今度行ってこようかな。

大阪のローカルメディアに関わって良かったこと

By 浅川 幸宣さん(@YukinobuAsakawa)

浅川さんからは、大阪環状線内側のローカルメディア、ぼちぼちについて。

f:id:cybozuinsideout:20181022134701j:plainbochi2.net

こちらは、運営チームの一員として、浅川さん自ら記事を書いたりWordpressのカスタマイズをしているそうです。 浅川さんは現在、フリーランスとして独立されているそうですが、自身でサイトを運営することで、サイト構築や運営のノウハウを得られるので、技術的にもサイト運営はオススメとのことでした。

ITコミュニティ@大阪

by 後藤 知宏さん(@mkkn_info)

後藤さんからは、関西のITコミュニティイベントついて。

東京と比べると大阪のコミュニティ活動が少ないので、もっとコミュニティ活動しようよ!ってお話です。 エンジニアのコミュニティなので、技術でコミュニケーションしていきしましょう、とのことでした。

後藤さんはご自身でも、関西フロントエンドUGというWebフロント制作をテーマとしたコミュニティを運営しているそうです。 定期的にイベントを開催しているみたいですので、ご興味のある方は以下のConnpassページをどうぞ。

kfug.connpass.com

懇親会&記念撮影

LT大会のあとは懇親会でした。みんなでお酒片手にワイワイガヤガヤ。(私もお酒を飲んでガヤガヤしてたので、写真を撮り忘れました……)

そして、最後は記念撮影。サイボウズ(Cybozu)の"C"のポーズ。

f:id:cybozuinsideout:20181022132938j:plain

私は、今回初めてのMeetup参加となりましたが、大盛り上がりで楽しい会でした。また、大阪で開催するときは、ワイワイガヤガヤやりたいですね!

今後のイベント

サイボウズでは、今後もMeetupを開催予定です。

最近ですと10/17(水)に、東京でSRE/NecoプロジェクトのMeetupも開催されました。 今後も定期的にMeetupを開催していますので、ご興味のある方はconnpassグループ「Cybozu Inside Out」をフォローしてくださいませ。

なお、直近では東京と大阪で、Cybozu Days 2018が開催予定です。こちらはサイボウズ製品を使用した業務改善やチーム作りに関するカンファレンスになります。 サイボウズ製品をより身近に感じていただける思いますので、ご興味のある方はお気軽にエントリーくださいませ。

  • 2018/11/7(水)~8(木) Cybozu Days 2018 東京 (https://cybozuconf.com/)
  • 2018/12/3(月)~4(火) Cybozu Days 2018 大阪 (同上)

サイボウズサマーインターン2018 報告その4 〜品質保証・セキュリティコース

$
0
0

こんにちは、松山品質保証部の俊成です! 今年もサイボウズでは、8月から9月にかけて、サマーインターンを開催しました。 この記事では、東京オフィスで開催した品質保証・セキュリティコースについて紹介します!

インターン概要

品質保証・セキュリティコースは、8月20日~8月24日と9月10日~9月14日の2回開催し、合計5名の学生が参加してくれました。 本コースでは、「製品テスト」と「セキュリティテスト」の業務体験型のプログラムを実施しました。現場で実施されているテストを体験して、サイボウズの品質保証活動について学べるものとなっています。 サイボウズでは、セキュリティも製品の品質であると考えているため、サマーインターンでは「セキュリティテスト」も品質保証のコースに含めています。

f:id:cybozuinsideout:20181017134905p:plain
スケジュール
基本的な勤務時間は9時から18時です。お昼には、製品テストを担当している人やPSIRT(Product Security Incident Response Teamの略)のメンバーなど、日によって異なる属性の社員とご飯を一緒に食べてもらいました。私はインターンのメンターを担当するために東京に出張していて、何度か昼ご飯をご一緒しました。

f:id:cybozuinsideout:20181017184448j:plainf:id:cybozuinsideout:20181017141101j:plain
ランチの風景

今年も、品質保証部内で開催している勉強会にインターン生の皆さんにも参加していただきました。 ちなみに、勉強会はミネルヴァチームが主催しました!

f:id:cybozuinsideout:20181017185108j:plain
勉強会の風景

製品テスト

製品テストでは、kintoneに対して3種類の試験を実施しました。

まず、1つ目は機能試験です。機能試験では、最新機能の仕様書から試験仕様書を設計し(テストケースを書き起こす作業)、実際に試験をします。今回の試験対象の機能は「テンプレートファイルからアプリを作成する」です! 初めて行う試験設計の作業でしたが、試験対象の機能を網羅した試験仕様書ができあがりました! 設計後にはインターン生同士でのクロスレビューや、模範試験仕様書を使った解説会、社員も含めモブ形式でのレビューなどを行い試験設計の知見を深めました。

f:id:cybozuinsideout:20181017183330p:plain
試験仕様書

2つ目は改修確認です。改修確認の体験では、不具合が修正されていることを確認する試験を設計&実施します。機能試験の時には意識しなかった試験観点も必要になりますが、レビューも参考にしながら上手く影響範囲を洗い出せていました。

3つ目はアドホック試験です。アドホック試験の体験では、事前にテストケースを準備せずに、思いつきでkintoneを操作し、不具合を探します。業務でkintoneを使い慣れている私達でも、不具合を見つけることが難しい試験です。怪しい挙動を見つけたら、メンター宛に報告してもらいます。一人一つ以上、不具合を見つけることができました!

f:id:cybozuinsideout:20181017185905j:plainf:id:cybozuinsideout:20181012133437j:plain
作業風景

セキュリティテスト

セキュリティテストでは、ハンズオンと脆弱性の評価、およびセキュリティテストを行いました。

セキュリティ・脆弱性とは

まずは下記の講義を受けて、セキュリティテストに必要な知識を身につけます。

  • 脆弱性とは

  • 脆弱性の原因や対策

  • CWE識別子とは

  • サイボウズではどのような挙動を脆弱性として採用しているか

講義を終えてから、各自のPCにBurp Suiteをインストールしてもらいました。これは、ブラウザーとサーバーの通信をキャプチャして、内容を閲覧/改ざんできるローカルプロキシです。脆弱性の有無を判別するためにリクエストを改ざんし、得られたレスポンスの変化を確認してもらいます。

f:id:cybozuinsideout:20181018110814j:plain
講義風景

ハンズオン

座学だけではわからない部分について、実際に手を動かして理解してもらうことを目的としています。 サイボウズでは、過去いくつかの脆弱性を検出・改修しています。それらの記録を元に、改修前の古いバージョンをインストールした環境を用意し、再現手順をなぞって、XSS(Cross Site Scripting)やSQLi(SQL Injection)を実行してもらいました。つまり攻撃の体験です。

※ ハンズオンに使用した脆弱性はすべて改修済みです。

f:id:cybozuinsideout:20181012171830p:plain
改修済み脆弱性の記録
攻撃を成立させるという体験はとてもレア(他者が管理するシステムに対してやってしまうと犯罪)なので、実際に脆弱性が再現したときには、インターン生の皆さんから嬉しそうな声があがっていました。

脆弱性の評価

サイボウズでは、FIRST (Forum of Incident Response and Security Teams) が出している 共通脆弱性評価システム CVSS v3 (Common Vulnerability Scoring System version 3) という評価手法を使って、定量的に脆弱性を評価しています。脆弱性の深刻度を10点満点のスコアで表現する手法です。この時間では、脆弱性にスコアをつける作業を体験してもらいました。 以下のような流れです。

  1. CVSS v3 の評価ポイントをメンターからインターン生に説明

  2. CVSS v3 に慣れ親しむために、演習の評価を実施

  3. サイボウズに届いた脆弱性報告を使って、再現確認とCVSS v3 による評価を実施

評価について、インターン生同士で議論が飛び交う場面もたびたび見られました! 実業務においてもクロスレビューから議論になることはあるので、リアルな業務体験となったのではないでしょうか。

セキュリティテスト

脆弱性についてだんだん詳しくなってきたところで、続いては最後の関門、セキュリティテストに挑戦します。 こちらもハンズオンと同様、サイボウズ製品である Garoonの古いバージョンを使用しました。 どのように脆弱性をリリース前に見つけるか、そして、お客様によりセキュアな製品を届けるためにどのような取り組みをしているか、その一部を体験してもらうことが目的です。

どのような観点で検証をすればよいかを考えながら、kintoneのアプリを使って試験仕様書を作成していきました。

f:id:cybozuinsideout:20181019154408j:plain
試験仕様書

試験仕様書完成後には、セキュリティテストにいざ挑戦です。 リクエストやパラメータに対する検証を、ひとつひとつ丁寧に進めていきます。 インターン生同士、またはインターン生とメンター間で相談しながら検証を進めていった結果、いくつかの脆弱性を発見することができました。 ※ 発見された脆弱性はすでに改修済みです。

これらのインターンシップのコンテンツを通して、セキュリティの仕事の面白さを体感してくれたようでした!

f:id:cybozuinsideout:20181012173127j:plain:w300
作業風景
スタンディングデスク風に作業をしている様子です。# なぜ靴下なのでしょう(笑)

インターン生の感想

インターン生の感想を紹介します。

とても密度の高い5日間でした。 実際の業務に近いことを大量に盛り込んでいただけたので、想像していたQAのお仕事と実際のお仕事とのギャップを埋めることができました。 メンターの方々をはじめ、社員さんたちの皆さんに優しく、手厚くフォローしてくださったので安心して過ごすことができました。わからないこと、困ったことがあったときに気軽に質問できる環境での作業とても充実しました。 5日間ありがとうございました!


サイボウズ内の職員同士の仲の良さを非常に感じられました。 また、メンターの方も色々な質問に対してやさしく丁寧に教えていただいたためインターン中の業務内容の理解が非常に深まりました。 5日間色々と良くしてもらいありがとうございました。


インターンに参加してサイボウズの雰囲気の良さや良い意味での自由さが感じられてよかった。 メンターさんがとても優しく積極的に教えてくれたので質問しやすい感じだった。


1週間という短い期間で、QA、セキュリティと二つの内容を体験させていただいて非常に面白かったです。特に、報告された脆弱性の検証や評価をさせていただけて、とても貴重な体験をさせていただけました。今回のインターンシップを通じて、バグバウンティープログラムに挑戦していきたいなと思いました。ぜひ、サイボウズで働かさせていただきたいなと思いました! 5日間という短い期間でしたが、ありがとうございました。


5日間という短い間にずっしりとしたプログラムが組まれていて、品質からセキュリティまで大分深いところまで教えていただいたなと思いました。 実際に業務をどのようにやっているのかが分かりましたし、この部署の重要な役割、必要性も実感することができました。 総じていい経験ができ、会社のことも知ることができ、本当に楽しかったです。 ありがとうございました。

最後に、インターン生も自身のブログに記事を書いてくれたので紹介します。是非読んでみてください!

balius-1064.hatenablog.com

teppay.hatenablog.com

まとめ

短い期間ではありましたが、用意していたコンテンツから、しっかりと吸収して帰ってもらえてメンターとしても嬉しい限りです。素直で優秀なインターン生たちから、こちらとしても良い刺激を受けました! インターン生の皆さんの今後の活躍を期待しています。

f:id:cybozuinsideout:20181012134249j:plainf:id:cybozuinsideout:20181012134243j:plain
集合写真

サイボウズサマーインターン2018 報告その5 〜UX/UIデザイナーコース

$
0
0

みなさんこんにちは、デザイングループの西藤です。

先日、Cybozu Summer Internship 2018を開催しました! 今回はデザイングループのメンターをさせていただいた自分から、UX/UIデザインコースの様子をお届けしたいと思います!

f:id:cybozuinsideout:20180927150920j:plain
第2日程の集合写真

サイボウズのインターンとは?

サイボウズサマーインターンは毎年8月から9月にかけて3回開催されます。5日間を通して実際の業務の疑似体験をしてもらうことはもちろん、参加学生と企業がお互いをより深く知ることを目的としています。

そのため、インターンでは、業務体験以外のイベントも多く開催されています。
例えば

  • 歓迎会、懇親会
  • 社員による勉強会
  • 社長とのランチ会
  • メンター以外の気になる社員との面談
  • 社内イベントへの参加
  • 部活動への参加 など

f:id:cybozuinsideout:20181001143408j:plain
アクセシビリティ勉強会の様子
f:id:cybozuinsideout:20181022132232j:plain
デザイングループメンバーとのランチ会

ここからはUX/UIデザイナーコースで行なっている業務体験の内容を紹介いたします。

どんなことを体験できるのか

サイボウズデザイングループは、大きく分けてリサーチ、プランニング、プロトタイピングの3つのプロセスを大事にして業務を行なっています。
インターンでは、実際の業務で行なっている3つのプロセスを一週間に凝縮して体験していただきます。

f:id:cybozuinsideout:20181001105423p:plain
期間中の実際のスケジュール

今回は「チームプロジェクトを大成功させるためのモバイルアプリを考える」というテーマを設定しました。
このテーマに対して、実際の業務と同じプロセスを体験していただき、大勢の社員に向けてプレゼンするところまでやっていただきます。

f:id:cybozuinsideout:20181001105717j:plain
テーマ:チームプロジェクトを大成功させるためのモバイルアプリを考える

1. リサーチ

リサーチでは、こちらで用意したターゲットユーザーにヒアリングをしてもらいます。
ヒアリングする時のコツやポイントなどをメンターから伝えて、あとはインターン生同士で話し合いヒアリング内容を決め、自分たちで実施し、実際の悩みや不満、ユーザーの理想の状態などを引き出してもらいました。

f:id:cybozuinsideout:20181001110227j:plain
ヒアリング中の様子

2. プランニング

プランニングでは、リサーチで引き出した問題点や理想からアイデアをまとめてもらいます。
実際にサイボウズでも行う「アイデアの発散」→「アイデアシート」→「ストーリーボード」→「ペーパープロトタイプ」という流れを1日に凝縮して行います。 メンターは、常にそばにいていつでも質問を受けたり、レビューを行えるようにしています。 ペーパープロトタイプができた段階で、デザイングループ全体の前でプレゼンをしてもらい、さらなる改善につなげます。

f:id:cybozuinsideout:20181001114816j:plain
ブレストの様子
f:id:cybozuinsideout:20181002144702j:plain
インターン生の描いたペーパープロトタイプたち
f:id:cybozuinsideout:20181001111055j:plain
デザイングループへの発表

3. プロトタイピング

プロトタイピングからは個別作業となり、各々プランニングで決めた案を実際に画面に落としていきます。
1日という短い時間だったのですが、レイアウトや表現方法を多くのパターンで検討し、「ユーザーにより伝わりやすいUI」を探求してくれていました。

f:id:cybozuinsideout:20181001133101j:plain
インターン生同士でレビュー
f:id:cybozuinsideout:20181001113144j:plain
デザイングループとのフィードバック会
f:id:cybozuinsideout:20181002150019p:plain
UIを検討していた痕跡

4. プレゼンテーション

最終日のプレゼンテーションでは、大勢の社員の前で1つのチームとして発表してもらいます。
リサーチから問題発見までをチームで発表した後、それぞれが考えた解決案を個人で発表してくれました。 個々の個性も出しながら、チームとしてもまとまった発表をしいて素晴らしかったです! 最終発表を見に来た社員から「さすがデザイナーだ…」「これほしい」などの声も上がっていたので、しっかりプレゼンできた証拠ですね!

f:id:cybozuinsideout:20181022140147j:plain
最終プレゼンを見に来た人たち
f:id:cybozuinsideout:20181022140108j:plain
最終プレゼンの様子

インターン生からの感想

※実際に参加したインターン生からの感想の一部を抜粋

f:id:cybozuinsideout:20181001135505p:plain:w100:leftサイボウズなりのデザインプロセスやチームとしての動きなど、内部のことも知ることができ、周りのインターン生とも仲良くなることができてとても有意義でした!ありがとうございました!
f:id:cybozuinsideout:20181001135553p:plain:w100:leftサイボウズの一員として当事者意識を持ち、本気で問題を見つけ、改善しよう考え続けた5日間でした。チャレンジを後押ししてくれたメンターの方にも感謝です。チームとして、同じ課題を考え、一緒に頑張ったメンバーにも感謝。
f:id:cybozuinsideout:20181001135652p:plain:w100:left五日間を通して社内のいろいろな場所に行け、会社についての情報も聞けたのでサイボウズで働くことの雰囲気をかなり知れました。二日間グループワークで残り三日は個人作業という配分もちょうど良くメンターの方も随時相談や質問に答えてくれるので全ての時間が学びになりました!
f:id:cybozuinsideout:20181001135728p:plain:w100:left実際の作業の流れを5日間に凝縮して体験できたのはとても大変だったけれど、同時にとても濃密で有意義でした。とても親切にしていただきながらも、厳しい意見や議論をしてくださったメンターさん方に感謝の気持ちでいっぱいです!
f:id:cybozuinsideout:20181001135806p:plain:w100:leftサイボウズの内情が隅々までわかって良かったです。出来るだけイベントなどには参加させていただいて、様々な方と話すことができて知見も広がり良かったです。
f:id:cybozuinsideout:20181001135825p:plain:w100:leftデザインの独学を始めて半年目で独学の限界を感じていたので、このタイミングでプロの現場を体験できたのはよかった。 UX設計は書籍やWebで見たことがあるくらいだったが、実際のUX設計を経験してみると難しさや奥深さを体験した。

まとめ

今回も、5日間という短い期間にデザインプロセスをギュッと詰め込んで体験していただきました。その中で、ユーザーの抱える悩みを引き出し、各々の個性や得意分野を活かしながら素晴らしい提案をしてくれました。 また、お互いに意見交換しながら進め、チームとして最終プレゼンを大成功させてくれたことも素晴らしかったと思います。

今年も大成功に終わったサマーインターンですが、来年ももちろんやります! UX/UIデザインに興味のある学生のみなさん、ぜひ来年の夏にお会いしましょう!待っています!

インターンシップへの応募だけでなく、新卒採用、中途採用、複業採用への応募も絶賛お待ちしています! デザイングループの採用ページはこちらです!

https://cybozu.co.jp/company/job/recruitment/designgroup/

デザイングループのFacebookページ 「UX Cafe」

デザイングループの活動や、UXに関わる勉強会・ワークショップなど様々なイベントに関する情報を発信しています。

データセンター内で使う BGP の基礎知識

$
0
0

Neco プロジェクトの ymmtです。本記事では Neco のネットワークの実装を理解するために必要となる範囲で Border Gateway Protocol (BGP)の基礎知識を解説します。

BGP はインターネット全域の経路制御に使われているプロトコルで、非常に複雑なルーティング要件を実装可能ですが、本記事では詳説しません。対象読者は

「BGP? 知ってる知ってる、インターネットのあれでしょ!」

という程度のソフトウェアエンジニアです。

以下、社内向けの解説文書からコピペしているので文体が変わります。悪しからずご了承ください。

ルーティングプロトコル

ルーティングプロトコルとは、簡単に言えば目的の IPv4/IPv6 アドレスへパケットを送り届けるのにどのような経路で送れば良いか情報交換するプロトコルを指す。経路の情報交換なので、シンプルに「経路交換」とも言う。

BGP はインターネット全体のルーティングプロトコルである。データセンター内での利用については後述する。BGP 以外のルーティングプロトコルは IGP (Interior Gateway Protocol) と総称され、例えば RIP や OSPF を指す。

スタティックルーティング

ルーティングプロトコルによらず、手動でパケットの宛先情報を登録するやりかたはスタティックルーティングと呼ばれる。変更コストが高いため、非常に自明な場合(例えば単独のデフォルトゲートウェイの指定)を除き、多用はされない。

IGP の存在理由

BGP は大規模な運用ができ、障害耐性にも優れる。それなのになぜ IGP を利用する場合があるかというと、プロトコルごとに経路の収束時間やリソース消費、運用の手間などの特性が異なるため。以下の資料に良い比較表がある。

c.f. Protocol Comparison

BGP の概念

AS / ASN

BGP は Autonomous System (AS)と呼ばれるネットワーク事業者が、相互に経路交換をするよう設計されている。各 AS は一意に特定できるAS 番号 (ASN)JPNICなどの RIRから割り当てられている。

プライベート IP アドレスのように、ネットワーク内部でプライベートに割り当てられる AS 番号もある。

c.f. RFC6996

eBGP と iBGP

BGP は大きく eBGP と iBGP に大別される。

  • 異なる ASN を持つ BGP ルータ同士の接続が eBGP (exterior BGP)
  • 同一の ASN を持つ BGP ルータ同士の接続が iBGP (interior BGP)

一つの AS が複数のルータ機器を持つことは冗長化のためにごく一般的に行われる。すると同一の ASN を持つ BGP ルータが存在することになり、これらを接続するプロトコルが iBGP となる。

後述するが、eBGP と iBGP では様々な点で動作が異なる。

ピアリングとトランジット

各 AS は各々で決めたポリシーで他 AS と経路交換したりトラフィックを流す。この点をもって、自律した分散システムを構成していると言える。他の AS と経路交換をすることをピアリングと言う。

c.f. ピアリング/トランジットとは

BGP の特徴

パスベクター型

この後説明するが、BGP で交換される経路には様々な属性(attribute)が付いている。その一つにパスベクター(path vector)がある。パスベクターとは、その経路がどのAS を経由していくか列挙したもの。ASN のリストと思って良い。

パスベクターは受け取った経路がループしているかの判別などに利用される。ループの有無は自分の ASN がパスベクターに含まれているか否かで容易に判定できる。

様々な属性に基く経路選択

BGP で交換される経路には様々な必須ないしオプションの属性がある。単純に経路の長さだけでなく、各種属性に基いて柔軟に経路を選択できる。

代表的なものを以下に挙げる。

  • NEXT_HOP

    宛先にパケットを送るための BGP ルータのアドレス。後述する iBGP の場合、必ずしも経路交換している BGP ルータのアドレスとはならない。

  • AS_PATH

    前述のパスベクター。

  • LOCAL_PREF

    AS 内で受け取った経路に自由に優先度を付けられる。その値。

c.f. BGP Attributes List

差分更新と keepalive

インターネット上の全経路(フルルート)を扱うため、経路情報の更新は差分のみを送るようになっている。またパケット落ちなどに対処するため、TCP 接続を用いる。

すると、更新頻度が少ない場合にピアが落ちていることに気付けない可能性がある。そのため定期的にピア間で死活確認を行うための KEEPALIVE 通信を行う。

比較的遅い経路収束

上述したようにピア間の経路の障害検出は KEEPALIVE 通信で行うが、60 秒に一回の通信が連続 3 回といった条件で障害判定するため、故障したピアを外して経路を収束させるのに比較的時間を要する。

KEEPALIVE 間隔の調整や、BFDの併用などで素早く収束させる方法がある。

iBGP の動作

スプリットホライズン

iBGP は同一 ASN を持つルータ同士の通信であるため、経路交換時に AS_PATHを延ばさない。ということは AS_PATHを利用したループ検出はできないことになる。

そこで、iBGP ピアから受け取った経路は他の iBGP ピアに広報しないというシンプルなルールを導入することで、ループを防止する。このルールをスプリットホライズンと呼ぶ。

c.f. BGP Split Horizon

フルメッシュ接続

スプリットホライズンルールがあるため、iBGP ルータは全てが相互にピアリングをしなければ、各 iBGP ルータが持っている経路を共有することができない。このように iBGP ルータ全てを相互接続することをフルメッシュ接続と呼ぶ。

一般に iBGP ルータはフルメッシュをする必要があるとされているが、そうしなければ経路を全て共有できないというだけの話である。動作に必要な経路が揃うなら、フルメッシュ構成にしなくても良い。

ルートリフレクター

フルメッシュ接続は n 台のルータがいると n * (n-1) / 2の数の BGP セッションを必要とする。ルータの数が増えると n の二乗に比例してセッション数が増加し、負荷が高くなる。また、単純にピアを定義してまわる運用コストもかかる。

この問題を解決するために、iBGP ルータの一部をルートリフレクターにする方法がある。ルートリフレクターはピアする相手ごとにルートリフレクトクライアントかどうかの設定をもつ。ルートリフレクターがピアから経路を学習すると、その経路を全てのルートリフレクトクライアントにそのまま伝える。

(注) ルートリフレクトクライアントではない iBGP ピアには原則通り伝搬しない。

クライアントルータはルートリフレクターとのみ BGP セッションを持てば済み、負荷の増加を避けることができる。

NEXT_HOP を書き換えない

AS_PATHを書き換えないのと同様、iBGP では NEXT_HOPも書き換えられない。そのため、eBGP で受け取ったエッジルータに見えている NEXT_HOPアドレスがAS 内部の iBGP ピアにそのまま伝わる。

c.f. A fresh look at BGP’s NEXT_HOP

受け取った経路の NEXT_HOPが到達不能なアドレスであった場合、その経路は破棄されてしまう。そのため、以下のどちらかで対処しなければならない。

  1. eBGP ピアと接続しているネットワークを AS 内で共有する

    IGP, BGP, スタティックルーティングなどで事前もしくは同時に共有しておく。 ただし BIRD version 2.0.2 では未知な NEXT_HOPアドレスを BGP で同時配布しても破棄される。

  2. iBGP ピアに伝える NEXT_HOPをエッジルータ自身のアドレスに書き換える

    next hop selfというルータ設定で書き換えられるだろう。ただし、これは eBGP ピアから受け取った経路以外の NEXT_HOPも書き換える動作をするので、例えば iBGP ピアから受け取った経路をルートリフレクトする場合に望ましくない動作となりえる。

データセンター内での BGP 利用

旧来は BGP はインターネットでの経路制御のためのもので、データセンター内で利用する場合も IGP を併用するのが普通であった。しかしながら BFDによる高速な経路収束や ADDPATH 拡張など BGP の欠点を補完する機能が揃い、また BGP を実装した比較的安価なスイッチ機材が増えたため、MC-LAGのようなベンダー依存技術や IGP を排して BGP のみでデータセンター内ネットワークを構築するのが昨今の技術的な方向性となっている。

IGP や MC-LAG をどこまで排するかで技術的な難易度は変わってくる。Calico や Romana, MetalLB など Kubernetes 周辺のベアメタルネットワーク技術は全サーバーを BGP ルータとして利用する設計である。

Neco では以上の背景を元に、OS でも IGP や MC-LAG を一切利用せず BGP + BFD で耐障害性に優れ、帯域も ECMP で活用できるネットワークを構築する。

まとめ

Neco にはネットワークを専門とするエンジニアはいなかったので、プロジェクト開始時は全員

「BGP? 知ってる知ってる、インターネットのあれでしょ!」

という程度でした。

オンプレミスの Kubernetes ネットワークで BGP を採用したミドルウェアが多いことと、ネットワークチームのエンジニアから CLOS アーキテクチャでの構築を提案されて、学んだことが本記事の内容です。これから BGP を学ぶかたの一助になれれば幸いです。

ルーティングソフトウェア BIRD の使いかた

$
0
0

Neco プロジェクトの ymmtです。本記事では Neco のネットワークの実装を理解するために、ルーティングソフトウェアである BIRDの仕組みと設定方法を解説します。

公式文書がすこしとっつきにくいので、こちらを読んでから公式文書にあたるとスムーズに理解ができると思います。見所は、Invalid NEXT_HOPへの工夫をこらした各種対処方法です。

以下、社内向けの解説文書からコピペしているので文体が変わります。悪しからずご了承ください。

BIRD とは

BIRD は Linux 等で動作する BGP や RIP などのルーティングプロトコルを実装したプログラムである。2018 年 10 月時点の最新版は 2.0.2 で、2.0 と 1.6 の両系列がメンテナンスされている。

本記事の内容はバージョン 2.0.2 を対象とする。

アーキテクチャ

BIRD は単独のプロセスとして動作する。

内部に複数のルーティングテーブルを持ち、それらを protocol と呼ばれる仕組みで外部のルータや Linux カーネル(が持つルーティングテーブル)とつなげることができる。

以下で理解が必要なものについて解説する。

Routing tables

BIRD は複数のルーティングテーブルを持てる。うち、以下は最初から用意されている。

  • master4

    ipv4 nettype でデフォルトで使用されるルーティングテーブル

  • master6

    ipv6 nettype でデフォルトで使用されるルーティングテーブル

IPv4 用のテーブルを別に作るには、以下のように bird.confに書く。

ipv4 table another_table;

これらは Linux カーネルが持つルーティングテーブルとは関係がない。

BIRD のルーティングテーブルは BGP であれば AS の経路情報(aspath)など様々な属性を持つ routeを登録するもの。Linux カーネルのルーティングテーブルにはそのような属性はなく、単純に prefix match でパケットの転送先を決めるFIB (Forwarding Information Base)としての役割しか持たない。

以下、ルーティングテーブルと言えば BIRD のルーティングテーブルを指す。カーネルのルーティングテーブルは「フォワーディングテーブル」もしくは「FIB」と呼ぶ。

Routes and nettypes

Route は文字通り経路だが、IPv4/IPv6 で言えば対象となるアドレスレンジ(サブネット)と、宛先(nexthop)、それに加えこの Route を連絡してきたネタ元(source protocol instance)や優先度(preference)などなどの属性が付属しているもののこと。

nexthop は複数あることもあり、その場合どの経路をどの程度の割り合いで選ぶかの重み(weight)を持つ。全ての nexthop が同じ重みを持つ場合は Equal Cost Multipath (ECMP) となる。

nettypes には先述の ipv4, ipv6以外に flow4などあるが、我々の用途では基本的に ipv4ipv6しか利用しない。

後述する route filter は route を受け取る関数となっており、route が持つ各種属性を関数内で変数として参照できるようになっている。

Protocols and channels

Protocol はルーティングテーブルと「何か」をつなぐもの。「何か」が他のルータである場合、protocol は BGP や OSPF といったルーティングプロトコルを指す。「何か」はルータ以外のこともあり、例えば kernelプロトコルは Linux kernel が持つフォワーディングテーブル(FIB)と BIRD のルーティングテーブルとの経路交換を実現する。

Protocol は接続先に応じてインスタンスを複数持てる。例えば、BGP であればピア先のルータ毎にインスタンスを作る。これらを区別するため、protocol のインスタンスは名前を付けられる。以下は ToR 2 台と eBGP 構成を取るルータの例。インスタンスに tor1, tor2と名前を付けている。

protocol bgp tor1 {
    local AS 65000;
    neighbor IP_OF_TOR1 AS 65001;
    ...
}
protocol bgp tor2 {
    local AS 65000;
    neighbor IP_OF_TOR2 AS 65001;
    ...
}

Protocol の中には channel が書ける。channel は nettype 毎に作れるので、つまるところ ipv4ipv6が channel 名となる。BGP protocol では ipv4, ipv6両方の channel を持てるが、RIP などは一つしか持てない。この辺りはプロトコルの特性による。後述する bfdなどの特殊な protocol は channel を持つことができない。

channel は、ルーティングテーブルとその protocol インスタンスの接続先で経路を交換する方法を示す。ipv4 channel では、指定をしないと master4ルーティングテーブルと経路交換をすることになる。

protocol bgp tor1 {
    local AS 65000;
    neighbor IP_OF_TOR1 AS 65001;

    ipv4 {
        import all;
        export filter {
            if proto = "static1" then reject;
            accept;
        };
    };
}

上の例は tor1 BGP インスタンスが IPv4 の経路を master4ルーティングテーブルにどう入れるかを設定している。importは protocol の接続先からルーティングテーブルに経路を入れる設定で、allであるので neighbor AS から受け取った経路は全て master4に入ることになる。

exportmaster4から neighbor AS に伝える経路の設定で、後述する経路フィルタで一部の経路を広報しないようにしている。

channel の設定が空の場合(デフォルトのままでいい場合)は、{, }ごと省略できる。ipv4 channel であれば単に ipv4;と書くことになる。ただし BGP protocol のうち eBGP となる場合は export, importの明示が必要であり、この記法は使えない。

重要な機能

protocol template

BGP のピア毎に protocol を書いていくと、共通点が非常に多い設定が並ぶ。このような作業を効率的に行えるよう、BIRD は protocol template を提供している。以下のように使う。

template bgp tor {
    local AS 65000;
    rr client;

    ipv4 {
        import all;
        export filter {
            if proto = "static1" then reject;
            accept;
        };
    };
}

protocol bgp tor1 from tor {
    neighbor IP_OF_TOR1 AS 65001;
}
protocol bgp tor2 from tor {
    neighbor IP_OF_TOR2 AS 65001;
}

経路フィルタ

経路フィルタは、route を受け取って最終的に rejectacceptする関数。関数の中で if などの制御構文や集合を含む各種のデータ型を利用できるため、非常に柔軟な経路制御を可能としている。

フィルタの中では、route は出現せず、route が持つ属性が変数に代入されて利用できる。例えば protoという変数には、その route をルーティングテーブルに登録した protocol インスタンスの名前が入っている。

一部の属性はフィルタの中で書き換えが可能で、例えば dest属性を書き換えることで ICMP UNREACHABLE を返すように経路設定をすることができる。

関数

経路フィルタは関数だが、別途純粋な関数も定義できる。

function with_parameters (int parameter)
int local_variable;
{
    local_variable = 5;
    return parameter + local_variable;
}

プロトコル

以下、Neco で利用するものに限定して解説する。

Device

ルーティングプロトコルではなく、ルーティングテーブルとも結びつかない。BIRD が OS のネットワークインターフェイス(link)情報をスキャンする設定。

このプロトコルのインスタンスはほぼ確実に一つ作る必要がある。

scan timeは Linux の場合 OS が notify する仕組みになっているので、それほど短い値にしなくても良い。

protocol device {
    scan time 10;
}

BFD

BFDはルーティングプロトコルではなく、ルーティングテーブルとも結びつかない。ルータ機器同士で非常に短い間隔で keepalive メッセージを相互に送ることで、経路障害を迅速に検出するプロトコルである。

BFD プロトコルは必要に応じて BGP 他のプロトコルが利用する。また BFD のセッションは BGP のピア接続情報から自動的に作ることができる。そのため BFD プロトコルは有効にしておけば他に設定する必要はないことが多い。

protocol bfd {
}

Direct

Direct はカーネルが持つ L2 リンクに割り当てられた IP アドレスから自動的に FIB に登録される経路を扱う。例えば eth0192.168.16.3/24というアドレスを割り当てると、FIB には 192.168.16.0/24 via eth0という経路が自動登録される。

Direct から BIRD のルーティングテーブルに経路を import するのは、通常は必要がない。必要になるケースとしては、例えば以下のように dummy デバイスを作り /32 の代表アドレスを持たせる場合などである。

$ sudo ip link add node0 type dummy
$ sudo ip address add 192.168.16.3/32 dev node0

Direct から BIRD ルーティングテーブルに import した経路は、次に述べる Kernel プロトコルであらためて FIB に登録はしたくないはずである。以下のように、export filter で落とす。

protocol direct direct1 {
    ipv4;
    interface "node0";
}

protocol kernel {
    ipv4 {
        export filter {
            if proto = "direct1" then reject;
            accept;
        };
    };
}

Kernel

Kernel プロトコルはルーティングプロトコルではない。ルーティングテーブルの情報を OS のフォワーディングテーブル(FIB)に登録するものである。逆に、FIB に手動で登録された経路をルーティングテーブルに取り込むこともできる。

ルーティングテーブルに対して、kernel protocol は一つしかインスタンスを持てない。ルーティングテーブルを分ければ複数のインスタンスを作れるが、接続先の FIB は異なるものにしなければならない。

ipv4 table alt_v4tab;

# alt_v4tab の経路を全て FIB 8 番に登録
protocol kernel {
    kernel table 8;
    ipv4 {
        table alt_v4tab;
        export all;
    };
}

# master4 の経路を全て main FIB に登録
# main FIB の経路も learn して master4 に登録
protocol kernel {
    learn;
    persist;
    ipv4 {
        import all;
        export all;
    };
}

FIB 8 番を実際に Linux カーネルがルーティングに利用するには以下が必要。

$ sudo ip rule add priority 100 from all lookup 8

Pipe

前節で複数のルーティングテーブルを使う場面がでてきたが、ルーティングテーブル間で経路を交換するために使うのが pipe protocol である。pipe は 2 つのルーティングテーブルを繋ぐ channel というべき存在であり、その設定には export, import等の channel の設定を直に書く。

# BGP 用に経路を集約するテーブル
ipv4 table bgp_v4tab;

# master4 -> bgp_v4tab
protocol pipe {
    table bgp_v4tab;
    peer table master4;
}

# alt_v4tab -> bgp_v4tab
protocol pipe {
    table bgp_v4tab;
    peer table alt_v4tab;
}

Static

いわゆるスタティックルートを定義できる。パケットを捨てたり ICMP UNREACHABLE を返すような設定もできる。

protocol static {
    ipv4;
    route 0.0.0.0/0 via 192.168.0.1;  # default gateway
}

BGP

BGP のインスタンスは、neighbor (ピア)毎に設定をする必要がある。同一 AS 番号の neighbor なら iBGP, 異なる AS 番号なら eBGP となるが、iBGP か eBGP かで各種設定のデフォルト値が変わるので注意をすること。

また、ピアが多々ある場合はほぼ同じ設定が並ぶので、前述の protocol template を利用すると良い。

  • bfd: BFD を有効にしたければ、こう書くだけで有効になる。
  • passive: もしかすると存在しないピアである場合、自分から接続にはいかないようにする。
  • rr client: ピアに対してルートリフレクターとして振る舞うならこれ。
  • add paths: iBGP で一つの宛先に複数の経路を neighbor に伝えたり受け取ったりする。ECMP に必要。
  • direct: iBGP のピアが同一 L2 ドメインにある場合は指定する必要がある。
  • multihop: eBGP のピアが同一 L2 ドメインにない場合は指定する必要がある。

トラブルシューティング

状態の確認

birdcを使うと、ルーティングテーブルやプロトコルインスタンスの状況を確認できる。

ルーティングテーブルの表示:

bird> show route
Table master4:
0.0.0.0/0            unicast [tor1 18:55:10.191] * (100) [AS65000i]
        via 10.69.64.1 on eth0
                     unicast [tor2 18:55:09.946] (100) [AS65000i]
        via 10.69.128.1 on eth1
10.69.0.5/32         unicast [tor1 18:55:07.808] * (100) [i]
        via 10.69.64.1 on eth0
                     unicast [tor2 18:55:07.609] (100) [i]
        via 10.69.128.1 on eth1
10.69.0.4/32         unicast [tor1 18:55:10.903] * (100) [i]
        via 10.69.64.1 on eth0
                     unicast [tor2 18:55:11.059] (100) [i]
        via 10.69.128.1 on eth1
10.69.0.3/32         unicast [direct1 18:55:03.687] * (240)
        dev node0

プロトコルインスタンスの一覧:

bird> show protocols
Name       Proto      Table      State  Since         Info
device1    Device     ---        up     18:16:10.826
bfd1       BFD        ---        up     18:16:10.826
defaultgw  Static     master4    up     18:16:10.826
kernel1    Kernel     master4    up     18:16:10.826
rack0-tor1 BGP        ---        up     18:16:14.081  Established
rack0-tor2 BGP        ---        up     18:16:14.686  Established

BGP インスタンスの詳細を表示:

bird> show protocols all 'rack0-tor1'
Name       Proto      Table      State  Since         Info
rack0-tor1 BGP        ---        up     18:16:14.081  Established
  BGP state:          Established
    Neighbor address: 10.0.1.1
    Neighbor AS:      64600
    Neighbor ID:      10.0.1.1
    Local capabilities
      Multiprotocol
        AF announced: ipv4
      Route refresh
      Graceful restart
      4-octet AS numbers
      Enhanced refresh
    Neighbor capabilities
      Multiprotocol
        AF announced: ipv4
      Route refresh
      Graceful restart
      4-octet AS numbers
      Enhanced refresh
    Session:          external AS4
    Source address:   10.0.1.0
    Hold timer:       177.403/240
    Keepalive timer:  8.268/80
  Channel ipv4
    State:          UP
    Table:          master4
    Preference:     100
    Input filter:   ACCEPT
    Output filter:  ACCEPT
    Routes:         4 imported, 2 exported
    Route change stats:     received   rejected   filtered    ignored   accepted
      Import updates:              4          0          0          0          4
      Import withdraws:            0          0        ---          0          0
      Export updates:              7          4          0        ---          3
      Export withdraws:            0        ---        ---        ---          1
    BGP Next hop:   10.0.1.0

ここでは特に Channel ipv4 ->Route change statsrejectedを注目する。Export updates が先方に reject される理由は様々あり、多いのはすでにより良い経路を持っているからなどだが、next hop アドレスが到達不能アドレスになっているように修正を要するケースもある。

ログ出力

journalctl -u bird.serviceでエラーが記録されていないか確認をする。

詳細にプロトコルインスタンスの動きを知りたい場合、以下のように birdcで指示すると、ログに出力されるようになる。

bird> debug 'rack0-tor1' all

出力例:

2018-04-20 19:14:38.143 <TRACE> rack0-tor1: BGP session established
2018-04-20 19:14:38.143 <TRACE> rack0-tor1: State changed to up
2018-04-20 19:14:38.143 <TRACE> rack0-tor1: Sending KEEPALIVE
2018-04-20 19:14:38.143 <TRACE> rack0-tor1 < added 0.0.0.0/0 unicast
2018-04-20 19:14:38.143 <TRACE> rack0-tor1 < added 10.69.0.5/32 unicast
2018-04-20 19:14:38.143 <TRACE> rack0-tor1 < added 10.69.0.4/32 unicast
2018-04-20 19:14:38.143 <TRACE> rack0-tor1 < added 10.69.128.0/26 unicast
2018-04-20 19:14:38.143 <TRACE> rack0-tor1 < added 10.69.0.3/32 unicast
2018-04-20 19:14:38.144 <TRACE> rack0-tor1: Sending UPDATE
2018-04-20 19:14:38.144 <TRACE> rack0-tor1: Sending UPDATE
2018-04-20 19:14:38.144 <TRACE> rack0-tor1: Sending END-OF-RIB
2018-04-20 19:14:38.144 <TRACE> rack0-tor1: Got UPDATE
2018-04-20 19:14:38.144 <TRACE> rack0-tor1 > added [best] 10.69.64.0/26 unicast
2018-04-20 19:14:38.144 <TRACE> rack0-tor1 < rejected by protocol 10.69.64.0/26 unicast

Invalid NEXT_HOPへの対応

以下は NEXT_HOPアドレスが到達不能な経路を受け取ったときに出力されるログである。

2018-04-20 19:14:38.253 <RMT> tor2: Invalid NEXT_HOP attribute

典型的な発生シナリオは以下の通り。

  1. あるルータが /31 のサブネットで繋がっている eBGP ピアから経路を受け取る

    この経路の NEXT_HOPは /31 に属するアドレスとなる。

  2. そのルータが iBGP ピアに eBGP ピアから受け取った経路を伝える

    iBGP は NEXT_HOPを書き換えずに伝える。

  3. 受け取った iBGP ピアは、1 の /31 サブネットを知らないので Invalid として破棄する

    NEXT_HOP記載アドレスに到達ができない場合、BIRD はすぐに経路を捨ててしまう

これを回避するには以下のいずれかの対応が必要になる。

  • 事前に eBGP の IP アドレスに到達できるよう、iBGP ルータに経路を入れておく

    事前に入れる方法としては RIP などの IGP かスタティックルートを設定するかとなる。BGP で同時に広報すると、タイミング次第で先に到達不能な NEXT_HOPが弾かれてしまい、うまくいかない。

  • 経路を広報するルータが next hop selfを設定する

    BIRD や他の BGP ルータは、iBGP でよくあるこの問題に対処するため、広告する経路の NEXT_HOPを全て自ルータのアドレスにする機能を持つ。これを有効にすることで、eBGP ルータの IP アドレスを隠すことができる。ただし、ルートリフレクターでこれを設定すると eBGP ピアから受け取った経路だけでなく、 iBGP ピアから受け取った経路の NEXT_HOPも書き換えてしまう。

  • 経路を広報するルータが export filter で NEXT_HOPを手動設定する

    eBGP ピアから受け取った経路の NEXT_HOPを書き換えるといったことが条件文で書くことができる。以下に例を示す。

      protocol bgp {
          ...
    
          ipv4 {
              import all;
              export filter {
                  # eBGP からの経路のみ NEXT_HOP を書き換える
                  if proto = "eBGP" then bgp_next_hop = 10.16.0.1;
                  accept;
              };
          };
      }
    
  • 経路を受け取る側が import filter でゲートウェイを上書きする

    BIRD では igp table TABLEを指定すれば、NEXT_HOPの経路の有無はそちらのテーブルを参照する。これを利用してひとまず受け取れるようにし、 import filter で経路のゲートウェイを上書きする。

      ipv4 table dummytab;
      protocol static dummystatic {
          ipv4 { table dummytab; };
          route 0.0.0.0/0 via "lo";
      }
    
      protocol bgp {
          ...
    
          ipv4 {
              igp table dummytab;
              gateway recursive;   # direct 接続時も IGP テーブルを参照させる
              import filter {
                  # ラック内 AS (iBGP ピア)からの経路なら bgp_next_hop を維持
                  # 以下の式は送信元ルータのアドレスを 26bit サブネットに含まれるかの判定
                  if bgp_next_hop.mask(26) = from.mask(26) then {
                      gw = bgp_next_hop;
                      accept;
                  }
    
                  # そうでないなら from をゲートウェイに(next hop self 相当)
                  gw = from;
                  accept;
              };
          };
      }
    

print デバッグ

BIRD がどのような経路を広報しているか詳しく知りたい場合、以下のように export filter 中で print することで経路の情報をログに出力できる。

    ipv4 {
        export filter {
            print "route: ", net, ", ", from, ", ", proto, ", ", bgp_next_hop;
            accept;
        };
    };

備考

代表 IP アドレスの実装

Neco のネットワーク設計では、各サーバーは NIC の IP アドレスとは別に代表 IP アドレスを持つことにしている。

NIC とは別に仮想的なインターフェイスを作るには、Linux では dummy link を使う。

$ sudo ip link add node0 type dummy
$ sudo ip address add ADDRESS/32 dev node0

dummy インターフェイスは自ホスト宛てに決まっているので、FIB への登録は不要。BIRD で経路広報するには Direct プロトコルで node0インターフェイスをルーティングテーブルに import する。

protocol direct direct1 {
    ipv4;
    interface "node0";
}

protocol kernel {
    persist;
    merge paths;   # ECMP

    # direct1 の経路を FIB に取り込まないようにする
    ipv4 {
        export filter {
            if proto = "direct1" then reject;
            accept;
        };
    };
}

疑似経路集約

内部でラック等に利用している AS 番号はクラスタ間で共通なので、クラスタ外への経路広報では aspath に含めないようにする必要がある。これは Cisco 等では経路集約して summary-only指定すれば良いが、BIRD には経路集約機能がない。

代わりに、複数のルーティングテーブルを自由に利用できるため、クラスタ外の BGP ピアに広報したい経路を static protocol で登録したルーティングテーブルを用意すれば良い。

ipv4 table outertab;

protocol static myroutes {
    ipv4 { table outertab; }
    route ...;
}

protocol bgp outerpeer {
    local as ...;
    neighbor ADDRESS as ...;

    ipv4 {
        table outertab;
        import all;
        export all;
        next hop self;  # next hop self の正しい使いかた
    };
}

# BGP で受け取った経路を master4 に登録
protocol pipe outerroutes {
    table master4;
    peer table outertab;
    import filter {
        if proto = "myroutes" then reject;
        accept;
    };
    export none;
}

まとめ

ルーティングソフトウェア BIRD の仕組みと、各種設定方法やトラブルシューティングを解説しました。

複数の内部ルーティングテーブルとそれをつなぐ protocol という BIRD のアーキテクチャは、ソフトウェアの柔軟性を活かした拡張性の高い優れた設計だと思います。一度理解すれば、できないことがほとんどない便利なルーティングソフトウェアです。

BIRD、いいですよ!

Viewing all 681 articles
Browse latest View live