ChatOpsで最新版のOSSのデプロイを行う

## FUJITSU Advent Calendar 6日目
初めて参加します。このエントリは個人の立場で書いております。

## ChatOpsで最新版のOSSのデプロイを行う
本日は、Mattermostを利用したChatOpsのご紹介です。構築の詳細は省きますが、システム構成の全体像をご紹介します。

## 作業背景
私達のチームでは、コミュニケーションツールとしてMattermostを利用しています。そこで、コミニュケーションツールとしてだけでなく、業務作業をChatでできないかと思い、検証も兼ねて実装しました。最後の方には、ChatOpsの課題やそれに対する私なりの意見も書いております。皆さんのご意見もいただけると、嬉しいです。

## 具体的な内容について
以下が具体的な内容です。

1. OSS(今回はmattermost)のリリース情報を監視し、最新バージョンがリリースされていればMattermostで通知を行います。
2. その際に、独自カスタマイズを行ったDocker Imageの作成および、デプロイを行うかをユーザに問いかけます。
3. ユーザは、任意の操作を選択します。

以下が簡単なシステム構成図です。

![システム構成図.png](https://qiita-image-store.s3.amazonaws.com/0/62976/ae6204ef-0cab-7eeb-c4ae-8e9a5922cfa5.png)

以降、システム構成図にある手順について、一つずつご紹介していきます。

## ①RSS取得
OSSはGitHubで公開されていることがほとんどかと思います。GitHub上のリリース情報は、リリースページのURL末尾に、`.atom`をつけることでRSS化して参照することができます。これをcronなどで定期的に監視します。

`https://github.com/mattermost/mattermost-docker/releases.atom`

``` https://github.com/mattermost/mattermost-docker/releases.atom
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xml:lang="en-US">
  <id>tag:github.com,2008:https://github.com/mattermost/mattermost-docker/releases</id>
  <link type="text/html" rel="alternate" href="https://github.com/mattermost/mattermost-docker/releases"/>
  <link type="application/atom+xml" rel="self" href="https://github.com/mattermost/mattermost-docker/releases.atom"/>
  <title>Release notes from mattermost-docker</title>
  <updated>2018-11-16T04:18:11+09:00</updated>
  <entry>
    <id>tag:github.com,2008:Repository/47103470/5.5.0</id>
    <updated>2018-11-16T04:20:31+09:00</updated>
    <link rel="alternate" type="text/html" href="https://github.com/mattermost/mattermost-docker/releases/tag/5.5.0"/>
    <title>5.5.0</title>
    <content type="html">&lt;p&gt;Merge pull request &lt;a class=&quot;issue-link js-issue-link&quot; href=&quot;https://github.com/mattermost/mattermost-docker/pull/338&quot;&gt;#338&lt;/a&gt; from cpanato/5.5.0&lt;/p&gt;

&lt;p&gt;Bump to 5.5.0&lt;/p&gt;</content>
    <author>
      <name>pichouk</name>
    </author>
    <media:thumbnail height="30" width="30" url="https://avatars2.githubusercontent.com/u/8401692?s=60&amp;v=4"/>
  </entry>
  <entry>
    <id>tag:github.com,2008:Repository/47103470/5.4.0</id>
    <updated>2018-10-17T03:50:38+09:00</updated>
    <link rel="alternate" type="text/html" href="https://github.com/mattermost/mattermost-docker/releases/tag/5.4.0"/>
    <title>5.4.0</title>
    <content>No content.</content>
    <author>
      <name>pichouk</name>
    </author>
    <media:thumbnail height="30" width="30" url="https://avatars2.githubusercontent.com/u/8401692?s=60&amp;v=4"/>
  </entry>
  <entry>
    <id>tag:github.com,2008:Repository/47103470/5.3.1</id>
    <updated>2018-09-19T17:25:26+09:00</updated>
    <link rel="alternate" type="text/html" href="https://github.com/mattermost/mattermost-docker/releases/tag/5.3.1"/>
    <title>5.3.1</title>
    <content>No content.</content>
    <author>
      <name>pichouk</name>
    </author>
    <media:thumbnail height="30" width="30" url="https://avatars2.githubusercontent.com/u/8401692?s=60&amp;v=4"/>
  </entry>
・
・
・
</feed>
```

## ②RSS解析
RSSを解析して、最新バージョンがリリースされているか確認します。私は、hubotを利用しているので、Node.jsのライブラリである**request**を利用してHTTPリクエストを投げてRSSを取得し、**parse-rss**を利用して解析をおこないました。前回のリリース情報に関しては、単純にテキストファイルに書き込んで保存するようにしました。

## ③バージョンの更新情報を通知 / ④image作成問いかけ / ⑤応答 / ⑥job呼び出し / ⑧結果応答
OSSにバージョンの更新があると、以下のようにMattermostに通知が来るようにしました。

![release_info.PNG](https://qiita-image-store.s3.amazonaws.com/0/62976/37c29bd9-321d-5ca9-b6c4-e7d1a2d01d66.png)

**【ちょっと待った】**をクリックすると。。。

![release_info2.PNG](https://qiita-image-store.s3.amazonaws.com/0/62976/a577f74a-67de-3b48-e8b8-809677bf2e4b.png)

jenkinsのおじさんが反応してくれます。【作成する】をクリックすると、jenkinsのjobを実行するためのHTTPリクエストが送信されて、イメージ作成jobが実行されます。

![create_image.PNG](https://qiita-image-store.s3.amazonaws.com/0/62976/d483f871-b4e1-21ae-89ec-799cc00a09bb.png)

某黄色いネズミ的な生き物が、jobの状態をMattermostに通知してくれます。アスキーアートやってみたかっただけです。

## ⑦jobの実行
jobの処理の流れを簡単にご紹介します。

  1. OSSのリポジトリを、jenkinsのワークディレクトリにcloneします。
  2. sedやawkを使って、独自カスタマイズを加えます。
  3. 編集後のDockerファイルの静的検査を行います。検査には**hadolint**を用いました。jenkinsの画面からは以下のように見えます。

    ![hadolint.PNG](https://qiita-image-store.s3.amazonaws.com/0/62976/86fd7281-d342-0842-dfc6-55f2b3507f16.png)

  4. プライベートのGitlabにDockerfileなどをcommit, pushします。
  5. Dockerfileから Docker Image を作成します。
  6. プライベートのregistryにpushします。
    * Rancherから簡単にコンテナのデプロイができるように、事前にimageをpushしておきます。

## ⑨デプロイの問いかけ / ⑩応答
jenkinsでjobの実行が成功すると、以下のように、新しく作成したimageからコンテナをデプロイするかをMattermostで聞きます。

![deploy.PNG](https://qiita-image-store.s3.amazonaws.com/0/62976/09213c30-d152-2a70-adf3-f6118dcc8fc9.png)

**【デプロイする】**をクリックすると、RancherのAPI経由で、kubernetesクラスタにコンテナが払い出されます。永続化ボリュームの作成などの細かい部分は作りきれませんでしたが、コンテナの払い出し部分のHTTPリクエストの例だけご紹介します。

``` data.json
{
    "containers": [{
        "allowPrivilegeEscalation": false,
        "image": <イメージの指定>,
        "imagePullPolicy": "IfNotPresent",
        "initContainer": false,
        "name": <コンテナの名前>,
        "privileged": false,
        "readOnly": false,
        "resources": {
            "type": "/v3/project/schemas/resourceRequirements"
        },
        "restartCount": 0,
        "runAsNonRoot": false,
        "stdin": true,
        "stdinOnce": false,
        "terminationMessagePath": "/dev/termination-log",
        "terminationMessagePolicy": "File",
        "tty": true,
        "type": "/v3/project/schemas/container"
    }],
    "name": <コンテナの名前>,
    "namespaceId": <名前空間の指定>
}

```

```
# curl -k -v -H "Accept: application/json" -H "Content-type: application/json" -u <Rancher APIのAPI Key情報> -X POST -d @data.json  https://<RancherサーバIP>/v3/project/<プロジェクトID>/workloads
```

## ⑪デプロイ指示 / ⑫image pull / ⑬コンテナデプロイ
Mattermostから、Rancher API経由でkubernetesクラスタへ、コンテナの払い出し指示が行われると、kubernetesクラスタがregistryからイメージをpullしてデプロイを行います。

![deploy2.PNG](https://qiita-image-store.s3.amazonaws.com/0/62976/86f3b3fb-b593-dd2d-d93e-c6d27c918347.png)

ほとんど隠れてますが、Rancherから確認するとデプロイされていることが確認できました。

以上で、検証は終了です。

## ChatOpsのメリット
* imageの作成から、デプロイまでボタン一つでできるので簡単。スキルがなくても同じ品質の作業が可能
* Chatに参加しているメンバーが、オペレーションを確認できる。
* 楽しい!!


## ChatOpsのデメリット
* 簡単にデプロイできるので、誤ってデプロイしてしまいそう
    * 対策として考えたのは
        * 一度ダイレクトメッセージで、承認者への承認を挟む
        * デプロイまでのステップを、何段階か挟む
* mattermostは、slackに比べてできることが少ない
    * アップデートで少しずつ改善されているよう 

## 今後
次は、コンテナの監視などを行って、問題が起こったらMattermostに通知するなど、王道の使い方を実装したいと思います。