AWS
drone.io
Slack
ChatOps
opsidian.ai

[ChatOps]Opsidianとdroneを使って、SlackからAWSへデプロイしてみた

はじめに

 先日【drone.ioを使ってCI環境を構築したので、色々整理してみた___<基本編>】を書きました。タイトルは揃っていませんが、今回はそれの続編で、Slackからデプロイコマンドを打って、droneがおとなしく指示通りにやってくれる方法について書きます、。

SlackでのChatOps

 (AWS寄りになってしまいますが)Slackを使って、ChatOpsをする時に、下記API Gatewayを使うパータンがよくあるのではないかと思います。もちろん、SlackからHubotを呼ぶのもあります。
スクリーンショット 0029-08-01 20.56.17.png
 ちなみに、Slack → API Gateway → Lambdaにご興味がある方は、下記、昨年私が書いた記事を見て頂ければと思います。
【Slack de AWS CLI】SlackのChannelからAWS CLIを実行できるようにしてみました!

 元々、自分もAPI Gatewayを使うと考えていました...が、つい先日(夜眠れない日)に、「なんか面白いツールないかな」とSlackのインテグレーションを漁っていて、偶然に見つかったのはOpsidianというツールです。正確的にはOpsidian.aiという名で、aiが付いています...よ。Opsidian.aiにご興味がある方は、是非Opsidian.aiの公式ページを見てください。面白いことをいっぱい書いてあります。
※ 私はあまりにも感動しすぎて、めちゃくちゃの英語でこのツールの親であるewadwornikowskaさんにメッセージを送りました。

 話を戻りますと、最終的にAPI Gatewayを辞めて、こんな感じにしました。

スクリーンショット 0029-08-01 21.00.52.png
 一見、API GatewayのかわりにOpsidianを使っているだけじゃんというツッコミもありますが、個人的にはOpsidianのほうが結構楽だと思います。
 API Gatewayもそれなりの使い方がありますので、ChatOpsをやる時に、選択肢が1つ増えたという捉え方のほうがいいと思っています。

 API GatewayとOpsidianを簡単に比べてみますと、

 1. API Gatewayの設定より、Opsidianのほいうが楽
 2. API Gatewayを利用する場合、認証とか入れないと、エンドポイントがバレたら、だれでも叩けるようになる。一方、OpsidianはSlackに設定したアクセスキーでLambdaをinvokeするので、安全(?)かも
 3. だれがLambdaを呼べるかの処理は、Opsidian側で制御可能。
 4. Opsidianって、ただLambdaをinvokeするだけではなく、AWSリソースのモニタリングもできる。
 ※ 私個人的な意見にはなりますが、OpsidianってChatOpsの神ツールだと思っています。

SlackからAWS ECRにイメージプッシュまでやってみる

 流れ的には、こんな感じになります。
 Slack → Opsidian → Lambda → GitHub → drone → AWS ECR
 何をやっているかとざっくり説明しますと、
 1: Slackからデプロイの指示を出します
 2: Opsidianはその指示通りにLambdaをinvokeします。
 3: invokeされたLamndaはGitHubへdeploy APICallします。
 4: GitHubはdeployのWebhookをdroneに送信します。
 5: droneは受信したWebhookからソースを取得し、ビルドを実行し、AWS ECRへイメージをpushします。

 細かい設定とかは割愛します。今後時間がありましたら、書くかもしれません。...と言っても、簡単に何を設定しているかを書きます。

1: SlackからOpsidianを呼べるようにしました。
  - Opsidianのインストールはこちら
  - Opsidianの設定はこちら

2: OpsidianがinvokeするLambdaを作りました。
  - OpsidianのDashboardにて、Slackから呼べるLambdaのコマンドdeployを設定しました。
  WechatIMG27.jpeg

  - 下記、超雑なLambdaサンプルコード
   ※ Opsidianのコマンドから渡された引数を使って、GitHubへdeploy APICall
   ※ GithubのPersonal access tokenはlambdaの環境変数GIT_KEYに設定しています。

deploy
import boto3
import json
import os
import http.client

def lambda_handler(event, context):
    conn = http.client.HTTPSConnection("api.github.com")
    print(event)
    args = event["args"].split(" ")
    repo    = args[0]
    branch  = args[1]
    env     = args[2]
    payload = {
        "ref": branch,
        "auto_merge": False,
        "environment": env,
        "description": "Deploy to "+ env,
        "required_contexts": []
    }

    headers = {
        'authorization': "token " + os.environ['GIT_KEY'],
        'User-Agent': "Awesome-Octocat-App"
    }

    conn.request("POST", "/repos/"+ repo +"/deployments", json.dumps(payload).encode("utf-8"), headers)

    res = conn.getresponse()
    data = res.read()

    print(data.decode("utf-8"))
    return json.dumps({'message': 'Hello world!'})

3: Github
  - 下記2つのファイル(あくまでもサンプル)が対象のリポジトリの配下に格納しました。

.drone.yml
# masterブランチに対して、
# GitHubのevnetがdeploymentかつenvironmentがproductionと指定された場合
# ビルドを実行

pipeline:
  ecr:
    image: plugins/ecr
    region: ap-northeast-1
    repo: 284****1948.dkr.ecr.ap-northeast-1.amazonaws.com/ecr
    tags: [ latest,drone-test ]
    secrets: [ ECR_ACCESS_KEY,ECR_SECRET_KEY ]
    when:
      branch: master
      event: deployment
      environment: production
Dockerfile
FROM centos:6

RUN set -x && \
    yum install -y httpd

4: drone
  - AWS ECRへpushできるdroneのプラグインplugins/drone-ecrを利用しています
    ※ ソースコードはこちら
  - 対象ブランチを有効化しました。
  1.jpeg
  
  - droneにecrへpushできる権限のキーを設定しました。
   ※ plugins/drone-ecr利用時、設定する環境変数はECR_ACCESS_KEYECR_SECRET_KEYになります。
 2.jpeg

  - 今回はGitHubのdeploymentの場合ですので、「Settings」の「Deploy Hook」を有効にしました。
3.jpeg

5: ECR
  - droneがビルドしたdockerイメージのpush先を予め用意しました。
WechatIMG16.jpeg

Slackからやってみる

1: Slackから /ops run deploy [repository] [branch] [environment]を打ってみます。
W1.jpeg

2: Opsidianから返信が来ました. やっはり Hello worldにすべきじゃなかったかもしれません。微妙に違和感が感じますが、一旦よしとします。
W2.jpeg

3: droneが動いていますね。
W3.jpeg

W4.jpeg

W5.jpeg
ちゃんとpushまでできましたね!

4: ECRにpushされたことも確認できました。
W7.jpeg

5: 終了

最後

 Opsidianとdroneで、SlackからAWS ECRへイメージをpushするまでについて整理しました。繰り返しにはなってしまいますが、Opsidianが結構便利なツールなので、ChatOpsだけではなく、モニタリングとかにも活用したいと思っています。
 今日はとりあえずここまでにします。