そこに仁義はあるのか(仮)

略してそこ仁!

はじめてのGoogle Chrome拡張(とVue.js)

社内サイトのちょっと手の届かないところを触りたくてGoogle Chrome拡張をはじめて作ってみたので、備忘メモ。
ツール自体はかなりサクッと作れました。はじめてのChrome拡張とはじめてのVue.jsだったけど、雑務しつつも2時間くらいで完成できました。
Selectボックスの中の要素を取ってきて、インクリメンタルサーチして、選択したらその値をSelectボックスに設定するという、それだけのツール。

構成ファイル

作ったファイルとフォルダ構成はこんな感じ。
manifest.jsonで読み込むJSファイル(vue.jsmain.js)を指定しています。

.
├── README.md
└── src
    ├── js
    │   ├── main.js
    │   └── vue.js
    └── manifest.json
{
  "manifest_version": 2,
  "name": "tool name",
  "version": "0.0.1",
  "run_at": "document_end",
  "content_scripts": [
    {
      "matches": [
        "https://example.com/roles/*",
        "https://example.com/users/*"
      ],
      "js": [
        "js/vue.js",
        "js/main.js"
      ]
    }
  ],
  "permissions": [
    "activeTab"
  ]
}

Vue.jsはcurlコマンドで格納。これでVue.jsが使える。

$ curl https://cdn.jsdelivr.net/npm/vue/dist/vue.js -o src/js/vue.js

めっちゃ雑なコード。かなりサクッと動かせてよかった。あと、わざわざ別でhtmlファイルを作らなくても画面にフォームなどをお手軽に挿入できて、Chrome拡張のためのVue.jsかと錯覚した。
画面が動的に読み込まれるので、最初に8秒待ったりしている。
拡張を挿入する画面側がjQueryでchangeイベントからHTTPリクエスト投げたりしているんだけど、Elementのvalue変えただけではchangeイベントが発火してくれなかったのでdispatchEvent(new Event("change"));で無理矢理発火させたりしてる。
拡張を更新して試さないとエラー出ないとか辛い…。コンパイルしたい…。

(function () {
    'use strict';
    setTimeout(
        function () {
            var comboboxList = document.querySelectorAll(".combobox")
            var index = 0;

            comboboxList.forEach(
                function (combobox) {
                    combobox.insertAdjacentHTML(
                        "beforebegin",
                        `
                        <style>
                        .selecting-item:hover {
                            background: #e0dfff;
                        }
                        </style>

                        <div id="vue-app-${index}">
                            Policy Filter
                            <input type="text" v-model="policyName">
                            <ul style="list-style-type: none;">
                                <li v-for="item, index in policyList" v-if="policyName && item.text.indexOf(policyName) > -1" 
                                :value="item.value" @click="selectPolicy(item, ${index})" class="selecting-item">
                                    {{ item.text }}
                                </li>
                            </ul>
                        </div>
                        `
                    );

                    var box_options = combobox.options;

                    let vue = new Vue({
                        el: "#vue-app-" + index,
                        data: {
                            policyList: box_options,
                            policyName: ""
                        },
                        methods: {
                            selectPolicy: function (item, index) {
                                combobox.value = item.value;
                                combobox.dispatchEvent(new Event("change"));
                            }
                        }
                    });

                    index++;
                }
            )
        }, 8000)
})();

読み込み方法

公開はしたくなかったので、ローカルのフォルダを読み込ませて動かしました。

1. Google Chromeの「設定」から「拡張機能」をクリック
2. 画面左上の「パッケージ化されていない拡張機能を読み込む」をクリック
3. 「src」フォルダを指定

スキーマの変更をデプロイする方法

【翻訳記事】デプロイ戦略の定義のブログでアプリケーションをデプロイする方法のパターンについて書きました。その記事のはてブにコメントをいただいた(ありがとうございます!)のですが、データベースの変更をした際のデプロイ方法についても気になるというコメントがありました。
そこで、翻訳記事の元になったブログとは違いますが、今読んでいる書籍「進化的アーキテクチャ」にデータベースの変更をデプロイするパターンについて記載されていたので、それを抜粋してブログにまとめます。
と言っても、データベースの変更はアプリケーションほどデプロイ種類があるわけではありません。データはあるか、統合点(後ほど説明します)はあるかという観点で3つのパターンにまとめられています。
そして、【翻訳記事】デプロイ戦略の定義で書いたそれぞれのデプロイ戦略をとる場合、どのケースに当てはめると良さそうなのかも考えました。諸々、私の考えが反映されているので、そうではないプレーンな情報を見たい方は書籍の「5章 進化的データ」をご参照ください。

進化的アーキテクチャ ―絶え間ない変化を支える

進化的アーキテクチャ ―絶え間ない変化を支える

そもそも、今回紹介するスキーマ変更のパターンは、書籍「データベース・リファクタリング」にて説明されているexpand/contractパターンと呼ばれる一般的に利用されているリファクタリングパターンとのことです。

  • まず最初に:データベースの統合点とは
  • expand / contractパターンとは
  • expand / contract パターンの選択肢
    • 選択肢1 : 統合点も従来のデータもない
      • アプリケーションのデプロイ戦略では
    • 選択肢2 : レガシーデータはあるが、統合点はない
      • アプリケーションのデプロイ戦略では
    • 選択肢3 : 既存のデータがあり、統合点もある
      • アプリケーションのデプロイ戦略では
  • まとめ
続きを読む

マイクロサービスではどんな単位でサービスを分割すればいいか

最近、マイクロサービスアーキテクチャについて耳にすることが増えていますが、サーバレスのコンテンツと共に語られているケースもあり、「そのサービス単位では分割しすぎなのでは?」とたまに思います。
もちろん、何が正しいかはその現場のコンテキストによるとは思いますが、書籍「マイクロサービスアーキテクチャ」の第3章にサービスの分割についての考え方が記載されており、しっくりくるとても良い内容だったので、それをまとめてみました。
サービス単位を適度に適切に分割することでマイクロサービスの利点をより享受できるようになると思います。まずは、サービス分割のために重要になる概念を説明し、その後、サービス単位をどのように定めるのか記載していきます。

マイクロサービスアーキテクチャ

マイクロサービスアーキテクチャ

  • 作者:Sam Newman
  • 発売日: 2016/02/26
  • メディア: 単行本(ソフトカバー)

2つの重要な概念

マイクロサービスで優れたサービスを作っていくためには、「疎結合」と「高凝集性」という2つの概念を意識する必要があります。この二つの概念によって関連する振る舞いは一箇所にまとめ、他のサービスとの境界は通信ができる限り「疎」になるよう適切にサービスを分割していきます。「疎結合」ばかりに注目し、「高凝集性」を蔑ろにすると、必要以上にバラバラになったサービス群ができてしまって変化に対するスピードが遅くなってしまうのではと思います。

疎結合

マイクロサービスでは、あるサービスを変更しても他のサービスに影響や変更がなくデプロイできることが重要になります。
サービスはお互いが疎結合であることが求められます。疎結合のサービスは、連携する他のサービスに関して必要最低限のことだけしか把握しません。

高凝集性

機能を変更する際、その変更をできるだけ早くリリースするために、関連する振る舞いは一緒にまとめておく必要があります。
機能変更のために様々な箇所で修正が必要になると、その分多くのサービスをリリースする必要が出てくるのでリスクや変更にかかる時間が大きくなってしまいます。

サービス分割の考え方

例えば経理部門と倉庫を管理している部門があったときに、それぞれの仕事内容は全く異なります。経理部門に所属する人は倉庫の内部作業の知識は必要ありませんし、逆もまた然りです。
他の部署とのやりとりは、在庫報告書や給与明細など、決まったインターフェースを持ちます。

f:id:syobochim:20200430220602j:plain

経理部門は倉庫の詳細な内部作業の知識は必要ありませんが、例えば下の図のように在庫状況を把握して企業評価の帳簿を最新に保つという業務があったときは「在庫品目」の情報が必要になります。
この「在庫品目」が経理部門と倉庫の2つのコンテキスト間の共有モデルになります。ここで注意が必要なのが、他の不要な項目は公開する必要はないということです。内部の情報を共有しないことで、結合が密になるのを防ぎます。

f:id:syobochim:20200430222822p:plain

マイクロサービスでは、「倉庫」と「経理部門」のような、それぞれのコンテキストが分割される箇所と一致するようにサービスを分割していきます。(境界づけられたコンテキスト。)初めは粒度の荒いサービスになるでしょう。そして、そのうち、倉庫のサービスの中を、注文、在庫管理、入荷などの機能に分解できることに気づくと思います。
マイクロサービスの境界を検討する際には、まず大きく粒度の荒いコンテキストの観点で考えて、それからさらに分割する利点を考えていきます。時期尚早にサービス分割してしまうと、サービスリリースの際に多くのサービスの変更が必要になってしまい、結果として変更に関するコストが上がるので注意してください。

機能ごとにサービスを分割した方が効果的であると判断した場合は、それぞれのサービスを他の連携先のマイクロサービスから隠し、入れ子の状態にしておくと、結合も密になりにくく、テストもしやすくなるので効果的です。
ただ、サービスを入れ子にしておくのとトップレベルに切り出すか、入れ子にするかの選択に厳格な規則はありません。
判断する上で優先する事項として、組織構造に合わせてサービスを分割した方が管理がしやすいです。「倉庫」の仕組みを1チームで管理している場合は入れ子に、それぞれのサービス単位でチームがある場合はトップレベルに切り出しましょう。

f:id:syobochim:20200430234608p:plain

最後に、「入れ子の方がテストもしやすくなる」を少しだけ深堀りします。
サービスを入れ子にしておくと、テストのときに各サービスをスタブ化する必要がなくなります。他のサービスと連携するような粗い粒度のAPIだけをスタブ化しておけば十分になるので、テストが簡単になります。
例えば「在庫管理」のサービスをテストしたい場合、データ連携しているサービスが多いと、以下のようにスタブ化しなければならない範囲が増えてしまいます。

f:id:syobochim:20200501005457p:plain

まとめ

もちろん組織やサービスの状況などによって、どのようにサービスを分割するかという選択は様々だと思います。
ただ、「疎結合」ばかりに着目するのではなく、「疎結合」と「高凝集性」という2つの概念をバランスよく考え、組織構造と連携させるようにサービス分割するのが変更速度の高い状態を維持できるマイクロサービスになるのではと思います。
最初に記載しましたが、この内容は書籍「マイクロサービスアーキテクチャ」の第3章により詳細が載っています。マイクロサービスの利点や考慮すべきことが書籍を通して書かれており、とても面白い本なのでオススメです!

マイクロサービスアーキテクチャ

マイクロサービスアーキテクチャ

  • 作者:Sam Newman
  • 発売日: 2016/02/26
  • メディア: 単行本(ソフトカバー)

初心者から達人までの道を学ぶ「リファクタリング・ウェットウェア 〜達人プログラマーの思考法と学習法〜」を読んだ

人の学びの過程や効果の高い学習方法が知りたくて「リファクタリング・ウェットウェア」を読みました。
この本では、ドレイファスモデルによって技能の習得レベルを5段階にわけ、その最上位である達人になるための道のりを示してくれています。達人までの道のりは遠い(本によると、最低10年は努力する覚悟が必要!)ですが、明日から始められる一歩から書かれています。人の思考方法など、「なるほど、確かに。」と思うような内容もあり、読んでいて面白かったです。

リファクタリング・ウェットウェア ―達人プログラマーの思考法と学習法

リファクタリング・ウェットウェア ―達人プログラマーの思考法と学習法

  • 作者:Andy Hunt
  • 発売日: 2009/04/27
  • メディア: 単行本(ソフトカバー)

📖 目次

  • 1章 初心者から達人への道
  • 2章 脳の構造
  • 3章 Rモードへの転換
  • 4章 アタマをデバッグ
  • 5章 意識的な学び
  • 6章 経験の積み重ね
  • 7章 集中のコントロール
  • 8章 達人になってから

1.2 ドレイファスモデルの5段階

ドレイファスモデルでは技能ごとに習得レベルを5段階評価に分類しています。ほとんどの人は中級者に位置しています。この本ではこのモデルの達人に向けて進んでいく方法が記載されています。

初心者はルールに基づいて自分たちのパフォーマンスを改善できました。ところが、達人に自らが作ったルールに従わせて見たところ、パフォーマンスは著しく低下してしまいます。初心者はルールに、達人は直感にしたがって行動するのが、パフォーマンスが最も出る方法です。

  • 初心者
    • 従うべきルールが与えられれば、ある程度効果的に仕事を遂行できる。
    • うまくやり遂げる能力が自分にあるかどうかを気にしている。指標になる経験がほぼないので、自分の行動の全てに関してうまくいくかの検討がつかない。
  • 中級者
    • 決まったルールから少しだけ離れられるようになる。独力で仕事ができるが、問題解決にはまだ手こずる。
    • 全体的な理解はしておらず、理解したいとも思っていない。
  • 上級者
    • 独力で問題に対処でき、それまで直面したことのない新しい問題の解決方法を考え出せるようになる。
    • 指導力があり、臨機応変な対応ができる。チームの指導者的役割を担う傾向にある。
  • 熟練者
    • 技能を取り巻くさらに大きな概念の枠組みを探索し、理解しようとする。単純化しすぎた情報には苛立ちを覚える。
    • 経験と判断力があり、適切にコンテキストにレシピを当てはめることができる。
    • 他人の経験からも学ぶことができる。ケーススタディや失敗したプロジェクトの噂話を聞いたりするだけで、そこから効果的に学べる。
  • 達人
    • 絶えず物事を行うより良い方法を模索している。膨大な経験があり、それを上手に引き出してぴったりの状況で応用できる。
    • 「理由があってそうする」のではなく、「直感」に従って何かをする。直感的に振る舞うので、他のものからは魔法使いのように見える。
    • 全人口の1%〜5%

5.3 プラグマティック投資計画の作成

自分のなりたい目標を決めたら、その目標を達成するための計画を立てていきます。計画を立てるにあたって重要な点は以下の通り。

  • 具体的な計画を立てる
    • 時間軸に沿って様々な段階の目的を考えだす
      • 現在(すぐにでもできること)
      • 翌年の目標
      • 5年後の目標
  • 多様性を持たせる
    • プログラミング言語や環境、技術、業界、非技術系の分野などをうまく組み合わせる
  • 受け身にならず、積極的に投資する
    • 「フィードバック」が重要
    • 常に現在に照らして計画の良し悪しを見極め、進行状況を現実的に評価する
    • 以前は考えなかった新しい要素を追加したり、良い結果の出ていない計画を取りやめにしたりする時期かもと定期的に見直しをする
  • 定期的に投資する
    • 最低限の時間を定期的に投資すると決める。

6.3 失敗を活かす

達人になる上で大切なのが経験を積むことです。経験を積むには失敗を恐れず学びに活かす必要がありますが、あるアイデアを探求し、発明し、応用すると言っても、それが自分自身、自分の所属するチームや組織にとって安全でなければ試せません。
何かを試行するには以下に挙げた条件を満たす必要があります。

  • 自由に試行できる
    • 最適な解決方法が複数ある場合にはやっぱり両方試したい。時間的に余裕がないなら、両方のプロトタイプだけでも作って試してみよう。見積もりの際にはこのような過程を必要な時間として確保する必要がある。また、この試行がチームメンバーに悪影響にならないよう取り計らわなければいけない。
  • 安全な状態に戻れる
    • 実験がうまくいかなかった時に安定した状態に戻れて、そこからもう一度トライできる。目指すのは最終的にうまくいくこと。
  • 以前のあらゆる状態を再現できる
    • 今までの開発工程中の任意の段階のプログラムを再稼働しなければならない。去年動作していたバージョン、または先月動作していたバージョンを今稼働させることができる?
  • 進展していることを証明できる
    • フィードバックなくして前進はありえない。試行は代替案よりもうまく動作した?どうしてそう言える?プロジェクトは進展している?先週よりも今週のほうが多く昨日が稼働している?

ソフトウェア開発であれば、上記の条件を満たす環境はバージョンコントロール、ユニットテスト、プロジェクト自動化で実現できます。

8.1 効果的な変化

個人も組織も変える(変わる)ことはとても大変で複雑なことです。本当に効果の上がる変化を実現する上で役立つことを紹介します。

  • 計画を立ててから始める
    • 一定期間のおおまかな計画を立て、その実現を目指して努力する。どれだけ実行できたかを記録し、努力が足りないのではと思ったら記録を見て検討する。意外に成果は上がっているかも。
  • 敵は過ちではなく無為無策
    • 失敗は恐れなくていい。
    • 無為無策が危険。
  • 習慣づけには時間が必要
    • 新しい習慣を定着させるには最低でも3週間は必要。
  • 信じれば実現する
    • 我々の思考が脳内の配線を物理的にかえ、脳内の化学物質の作用を変える。変化は可能だと信じる必要がある。
  • 次の一歩は小さく踏み出す
    • 実行できそうなちょっとした目標を掲げ、達成できたら自分にご褒美をあげよう。そしてそれを繰り返す。

💬 まとめ

一部抜粋してご紹介しましたが、この他に集中をコントロールする方法や効果的な読書方法など、様々な達人までの道のりが書かれていました。
私も、まずは書籍の内容のうち、以下を試してみようと思いモレスキンのノートを買ってみました。モレスキンのノートは2年前くらいまで使っていたのですが、最近のメモは全てEvernoteにとっていました。Evernoteは全文検索できてとても便利ですが、改めてノートを見返してみるとノートを使っていた時の方が雑多な内容も気軽に書いていて、書籍の内容をやってみるのにちょうど良いと思いました。

  • アイデアを書き留める
    • いつもノート(できれば無地のもの)を持ち歩き、これを使って気ままにいたずら書きやマインドマップ作成、メモなどをする。
  • モーニングページ
    • 直感、問題解決、創造性を司る脳の機能を活かせるようになるため、朝一番に思いつくままノートに3ページ書く。
  • ToDoリストの作成
    • コンテキストスイッチを無駄に切り替えないために、頭の中のリストを動的に更新するのをやめる。
  • プラグマティック投資計画を作成する

これから自分がどういうスキルを習得したいのか、そのためにどうやって一歩一歩進んで行けば良いのかをきちんと考えてみようと思います!

リファクタリング・ウェットウェア ―達人プログラマーの思考法と学習法

リファクタリング・ウェットウェア ―達人プログラマーの思考法と学習法

  • 作者:Andy Hunt
  • 発売日: 2009/04/27
  • メディア: 単行本(ソフトカバー)

認知バイアスを知って考えのズレを意識する

認知バイアスとは、人間が何かを考えたり記憶したりする際に持ってしまう先入観のことです。良く聞く「希望的観測」や「生存バイアス」もこの認知バイアスの中の一つです。
本来は論理的かつ合理的な決定をしなければならないときに、認知バイアスの影響をうけてしまうと結論がズラされてしまう可能性があります。認知バイアスを理解し、意識することで、思考が逸れてしまうことを防ぐようにしなければいけません。
もしくは、逆に認知バイアスがかかることを逆手に取れば、物事を円滑に進められるかも。
Wikipediaを見ると、数多くの認知バイアスが掲載されています。一つ一つを見ると、「確かにやってしまいがちかも。」と思うような認知バイアスが数多く紹介されていました。

f:id:syobochim:20200418173624p:plain
Category:認知バイアス - Wikipedia

以下は、Wikipediaと書籍『リファクタリング・ウェットウェア』を参考に、いくつかの認知バイアスを短くまとめてみました。
発生していそうな状況も書いてみたので、「もっとこういう例の方が良いよ!」などアドバイスあればコメントいただけると嬉しいです。

  • 後知恵バイアス
  • アンカリング
  • 確証バイアス
  • 偽の合意効果
  • 希望的観測
  • コンコルド効果
  • 根本的な帰属の誤り
  • 自己奉仕バイアス
  • 心理的財布
  • 正常性バイアス
  • 生存バイアス
  • ゼロサム思考
  • ダニング=クルーガー効果
  • 単純接触効果
  • ツァイガルニク効果
  • ホーソン効果
  • レイク・ウォビゴン効果
  • 🤔 認知バイアスとどう向き合うのか
  • 最後に
続きを読む

【翻訳記事】デプロイ戦略の定義

この記事は2017/11の以下のブログ記事の翻訳です。
blog.itaysk.com

まずはじめに、翻訳を快く許可していただいた@itayskさんに感謝いたします。

3年前の記事ですが、デプロイ戦略についてここまで網羅的にまとめられた記事が日本語で見つけられなかったので翻訳してみようと思いました。
初めての翻訳記事であり、かつ翻訳時に多少の意訳を含んでいます。私の翻訳ミスがある可能性も十分にご了承ください。
何か間違いやわかりにくいところがあれば、コメントいただけますと幸いです。



デプロイの話をしましょう。このトピックは、以前は面白くない細かい実装だと考えられていましたが、現在はモダンなシステムの基本要素になりつつあります。全ての人がデプロイの重要性を理解して、それを中心にソリューションを構築しようとしているように感じますが、私たちはデプロイ戦略の構造と定義をしていません。人々は同じ意味なのに違う言葉を使ったり、違う意味なのに同じ言葉を使ったりしています。これは、人々が問題を解決しようとして車輪の再発明をすることにつながります。私たちはより良いツールを構築し、より良い決定を下し、お互いのコミュニケーションをシンプルにするために、このトピックについての共通の理解が必要です。
この記事は、私が以下のように呼んでいる一般的なデプロイメント戦略について一覧化し、定義しています。

  • 無謀なデプロイ (Reckless Deployment)
  • ローリングアップグレード (Rolling Upgrade)
  • ブルーグリーンデプロイ (Blue/Green Deployment)
  • カナリアデプロイ (Canary Deployment)
  • バージョンデプロイ (Versioned Deployment)

これらのリストにはおそらく他の名前や用語があるかもしれません。ここに無い用語は、これらの主要なデプロイ戦略の変形とみなせると主張します。

記事を読む前の注意点:この記事は定義・方法論・アプローチについて書かれたものであり、どのような技術スタックで実装するかについては書かれていません。技術的なチュートリアルについては別のポストで書く予定です。お楽しみに!

無謀なデプロイ (Reckless Deployment)

別名:Highlander*1 , Simple

要約: 古いものを壊して、新しいものを構築する。結果は気にしない。

これは最も簡単な戦略です。全てを破棄し、新しいバージョンを再構築します。通常は、開発/テストのシナリオか影響度がとても小さいアプリケーションに適しています。これ以上の説明はありません…

f:id:syobochim:20200317190111p:plain

ローリングアップグレード (Rolling Upgrade)

別名: Gradual Deployment

要約:既存の環境に新しいバージョンのコードを導入し、古いコードを廃止しながら徐々に新しい環境を増やしていきます。

これは新しいコードを既存の環境に追加していく際の基本の戦略です。既存の環境は古いバージョンと新しいバージョンの混在プールになり、最終的にはゆっくりと古いインスタンスが新しいインスタンスに置き換わります。「インスタンス」と「プール」という用語は採用技術(VM、コンテナ、プロセスなど)によって違う意味になります。

f:id:syobochim:20200317190831p:plain

ヘルスチェックと監視

この戦略の重要な側面は、ヘルスチェックと監視です。新しいコードを徐々に導入していくことへの重要なポイントは、新しいコードで予期しない問題が発生した場合に、障害を制御できることです。そのためには、新しいバージョンがどう動作しているかを知らなければなりません。そのため、ヘルスチェックと監視が不可欠です。

ロールバック

デプロイがうまくいっていないと判断したら、リリースを止めてデプロイをキャンセルし、元に戻すこともできます。(別名:ロールバック)

後方互換性

新しいコードと古いコードが共存しているので、ユーザーはどちらのバージョンにもルーティングされる可能性があり、この戦略を使っている場合は後方互換性が主な懸念点になります。

ちなみに

あなたは、一部のユーザーが一貫して特定のバージョンを取得する、または、一部のユーザーのみに新しいバージョンを公開するために、ユーザーをスマートにルーティングすることを検討しているかもしれません。それは正しいですが、私はそれをローリングアップグレードとは呼びません。私が何を言おうとしてるのかはこのまま読み続ければわかります。

ブルーグリーンデプロイ (Blue/Green Deployment)

別名:Red/Black, Staged deployment, Swapping Slots

要約:現在の環境に影響を与えず、分割された新しい環境に新しいバージョンをデプロイします。

これは最も安全な戦略で、多くの本番環境で利用されています。安全性を確保するために、現在実行中の環境には一切手を加えず、アプリケーション全体のコピーやアップグレードするモジュールを別の環境に用意します。デプロイの範囲を決める(または分離の範囲)を決めるのはあなた次第です。
例えば
・システム全体を再構築するのか、更新があるモジュールだけをアップデートするのか。
・新しいバージョン用にロードバランサーを新規構築するのか、既存のロードバランサーに新しいルールを追加するのか。
・バージョン間で設定値を共有するのか。
これらは考えられる質問の一部に過ぎず、どう決めるかはあなたかあなたのツール次第です。
1つ確かなことは、新しいバージョンは現在のバージョンのデプロイから完全に分離されるべきということです。これは、アップグレードの間に新旧のコードが環境に混在するローリングアップグレードとは対照的です。その結果、後方互換性は必須ではありません。
新しいバージョンが公開されたら、それをテストすべきです。現行のバージョンはまだ稼働中なので、デプロイ完了を急ぐ必要はありません。この時点では、ユーザーはまだアップデートに気づいていません。
バージョンの品質に十分自身が持てたら、ユーザーを古いバージョンではなく新しいバージョンに切り替え始めます。一度に全てのユーザーを切り替える(別名:カットオフまたはカットオーバー)ことも、新しいバージョンに徐々にユーザーを追加することもできます。

f:id:syobochim:20200317212121p:plain

ドレイン

一般的な方法は移行前に古いデプロイを「ドレイン」することです。「ドレイン」とは、現在のアクティブなセッションが自然に終了し、新しいバージョンのみを使用して新しいセッションを開始することを意味しています。

スイッチバック

通常は、完全に移行した後も古いバージョンを保持しておき、簡単に元に戻してスイッチバックできるようにします。

ステージ

この戦略の一般的なバリエーションには、段階的なデプロイとスロット交換があります。デプロイのスコープ(または分離の範囲)はアプリケーション全体です。(つまり、システム全体のコピーがスタンバイ状態になっています。)この方法では、アップグレードが実行中でなくても、私たちは常にアプリケーションとインフラのコピーを2つ持つことになります。一つの環境は本番環境で、もう一つの環境は「ステージ」と呼ばれる本番前の環境です。私たちはQA / UAT / Repros(再現) / CIなどのために、定期的にステージを利用できます。私たちは常に本番環境ではなくステージにデプロイします。よって、ステージは常に本番環境の前にあり、最新の本番環境候補になります。通常のブルーグリーンデプロイのように、本番環境に影響を与えずにステージのテストと検証をすべきです。デプロイに成功したら、2つの環境間でルーティングを切り替えるだけで、ステージが本番環境になり、本番環境がステージになります。これは通常、DNSレコードの更新を利用します。(必ずしもそうではありませんが。)ここでも、何か問題が発生したら、簡単に元に戻せます。

ちなみに

あなたは、ステージ環境(または新しい「グリーン」なデプロイ)を公開して、実際のユーザーが環境を試すことを検討しているかもしれません。それは良いアイデアです。私はそれをカナリアデプロイと読んでいます。次の章で説明します。

カナリアデプロイ (Canary Deployment)

別名: Ringed Deployment, Feature toggling, Dark features, Silent launch, A/B testing, Testing in production.

要約:新しいバージョンを古いバージョンと一緒にデプロイして、新しいバージョンを使用するユーザーを慎重に制御します。検証を監視し、調整しつつ、徐々に人口を増やしていきます。

これはデプロイ方法の聖杯です。また、達成が最も困難です。
これは、前述の戦略を高度に使用したものと考えることができます。システムに新しいコードを導入する場合は、実際のユーザーが新しいバージョンを本番環境で使えるという重要な違いがあり、どの戦略でも使用できます。当然、全てのユーザーが全ての新機能を使える必要はないので、どのユーザーが新バージョンのどの部分を使うかコントロールする必要があります。これは、ロードバランサやプロキシレイヤーで実装することも、アプリケーションの設定を使うことも、ランタイムを使うことも、その他の方法で実装することもできます。カナリアの基本的で一般的な実装では、ブルーグリーンデプロイを利用し、一部のユーザーを新しい「グリーン」バージョンにスマートルーティングします。

f:id:syobochim:20200317221056p:plain

より高度な実装では、拡張されたブルーグリーンデプロイのテクニックを超えて、より詳細なレベルでデプロイします。カナリアはコントロールと監視が全てであり、コンポーネントをより細かくコントロールできるほど、カナリアデプロイはより高度になります。

さらなる監視

前述しましたが、今回はさらに重要な意味を持ってもう一度説明します。これらの高度なパターンは、いずれも適切な監視なしでは機能しません。カナリアでは、基本的な死活監視だけでなく、パフォーマンスやユーザーエクスペリエンスの指標の監視を検討してください。良い可観察性のカナリアによって、動作するバージョンをデプロイすることから、最適なバージョンをデプロイすることへと考えを移行できます。

A/Bテスト

高度な違いは、複数の異なるバージョンを本番環境へデプロイし、各バージョンでの実際のユーザーと彼らのリアクションの実験をしていることです。ここではデプロイメント戦略から成熟した製品計画アプローチに話題が移りますが、デプロイ戦略はこれらの高度なビジネス関連の戦略の重要な基盤であり、2つが密接に関連していることが多いので、ここで言及しています。

ダークフィーチャー

本番環境のカナリアデプロイ / テストの極端なバージョンでは、機能をオフにして本番環境にデプロイし、一部のユーザー(ベータ版やプレビュー版のテスター)に対して選択的に機能をオンにします。このように動作させるには、システムをモジュール化してデザインする必要があります。つまり、デプロイの単位が機能毎になっており、アプリケーションは個別に切り替え可能な機能で動的に構成されます。この場合、どの機能がどのユーザーに対して有効になっているかを管理するための専用リリース管理システムがあることは、悪いアイデアではありません。

バージョンデプロイ (Versioned Deployment)

要約:ユーザーが使用するバージョンを選択できるようにしながら、全てのバージョンを維持します。

これは厳密なデプロイ方法ではなく、アーキテクチャパターンまたはAPIデザインパターンの境界線なので、ここに属しているかはわかりませんでした。それでもデプロイ戦略に影響を与えるかもしれないので、ここでデプロイ戦略として挙げています。
各バージョンを選択する必要がなく、常に全てのバージョンを本番環境で稼働させたらどうでしょう?この魅力的な戦略は、API開発者の間で特に人気があります。この例では、全てのAPIバージョンが常に使用可能(作業バージョンを削除しない)で、ユーザーは使いたいバージョンを選んで使えます。これは、私たち(ユーザーではない)がユーザーが使うバージョンを決める他の戦略とは対照的です。
明らかな問題はレガシーバージョンをホストするための追加の容量と、バージョン間でデータソースを共有することです。しかし、もし後方互換性に十分に注意し、予備の追加容量を確保できるのであれば、こうした問題よりも利点の方が大きくなります。
このデプロイ戦略はとても単純で、新しいバージョンをデプロイするだけです。全てが常に明示的にバージョン管理されているので、新しいバージョンのデプロイを簡単に捨てても影響がありません。優れているところは、新しいバージョン(または任意のバージョン)の使用を明示的に要求する必要があるところです。そのため、デプロイ環境ではバージョン間のユーザーの移行を気にする必要がありません。

f:id:syobochim:20200317224903p:plain

APIデザイン

この記事はAPIの設計に関するものではないので、ここでは具体的な例を取り上げません。しかし、この戦略に興味がある場合は、MicrosoftがAzure Resource Manager(ARM) APIをどのように設計したかを見てみてください。これは、このパターンの素晴らしい例であり、一般的なREST APIの設計にも適しています。

まとめ

以上です!これらは私が不可欠だと考えているデプロイ戦略であり、それらがどう定義され、どう違うと私が考えているかを説明しました。
以下の戦略についてカバーしました。

  • 無謀なデプロイ (Reckless Deployment) - 何も気にしない時
  • ローリングアップグレード (Rolling Upgrade) - ロールバックする時間を確保するために、徐々にデプロイする
  • ブルーグリーンデプロイ (Blue/Green Deployment) - 変更の操作から本番サービスを守り、横の環境で変更を操作することで、安全性を高める
  • カナリアデプロイ (Canary Deployment) - 実際のユーザーに新しいバージョンを公開する
  • バージョンデプロイ (Versioned Deployment) - 複数のバージョンを永久に共存させる特別な目的の設計

*1:翻訳者コメント:Wikipediaを見ると、「外界と隔離にまでは行かないにしても交流が困難で、文明の浸透が遅く、生活環境が快適とは言いがたいハイランド」に住む人とあるので、時代遅れという意図のようです。

「DevRel/Online #1 〜初のオンライン開催〜」に参加してオンライン勉強会のノウハウを得ました! #devreljp #devrel

DevRel Meetup in Tokyo主催の勉強会がオンラインで開催されたので参加しました!
コロナの影響で初のオンライン開催になったそうですが、家でご飯の準備をしながら見られるので気軽に参加できて嬉しい。
そしてtwitterを見ていると東京以外にお住まいの方も参加されていたようで、「DevRel Meetup in Tokyo」の幅が広がったのを目の当たりにした感じで、すごくよかったです!
ただ、今回はWebEXを利用した勉強会でしたが、ネットワークや音声、画面共有でのトラブルが多く、時間がかなり伸びていました。オンライン勉強会の課題ですね…。
イベントのメインテーマはイベントページでは定義されていないようですが、アジェンダ的には「オンライン勉強会のノウハウ」に関するセッションばかりでした。

イベントページはこちら
devrel.connpass.com

  • 💬 DevRelの基本とオンラインミートアップの作り方 by アツシさん
    • イベントの基本的な作り方
      • 2. イベントを企画する
      • 4. イベントを実施する
      • 5. 参加者を保持する
  • 💬 オンラインイベントを実施する上で私は何を考えどう行動したか by 鈴木さん
  • 💬 Online Demoを通じてスピーカーの注意点をまとめてみる(´Д` )テスト by おだしょーさん
  • 🤔 セッション中のDEMOについて
  • 🙌 おまけ
  • 最後に
続きを読む