継続は力なり

タイトル通り定期的な更新を心掛けるブログです。

k6 のテスト実行を GitHub Actions で行う

タダです.

以前,k6 に関する記事を書いて使っているうちにテストの数も増えてきたりして繰り返しの作業になっているのでテスト実行を自動化できないかと思い,調べてみた内容をこの記事にまとめていきます.

sadayoshi-tada.hatenablog.com

GitHub Actions がマーケットプレイスにあった

k6GitHub Actions があったのでこれを使ってみることにしました.

github.com

GitHub Actions のコード

サンプルに載っていたのを流用して叩いてみます.10秒間10の仮想ユーザーがアクセスした場合のテストを行います.flagsにはローカル実行同様のオプションを使えて指定できるようです.この辺も k6 の良さが引き続き使えて良さそうです.

name: k6 autotest

on: [push]

jobs:
  k6test:
    name: Run k6 test
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Run k6 local test
        uses: k6io/action@v0.2.0
        with:
          filename: test.js
          flags: --vus 10 --duration 10s

test.js の中身は複数のテストファイルを実行するようなコードにしました.

import TestOne from "./xxx/test1.js"
import TestTwo from "./xxx/test2.js"

export default function() {
    TestOne();
    TestTwo();
}

結果

ローカルで叩いた時のように k6 の実行結果が GitHub Actions の中で表示されました.

f:id:sadayoshi_tada:20211013005513p:plain

まとめ

簡単ですが,GitHub Actions で k6 を実行してみたのでまとめてみました.これまで自分の手元でやってましたが,GitHub Actions に載せて自動化しつつ自分以外の人でも実行できるようになっていければと思います.

Pinpoint で送ったメールの開封データイベントをS3 に保存する

タダです.

Pinpoint でメールの配信をやっている中で,送った後のメールの開封状況とかを保管し,分析したいという要望からデータ収集の仕組みの検証をしたのでまとめていきます.

Pinpoint のメール開封イベントの収集

Pinpoint のメール開封イベントの収集は Kinesisに送信することが可能です.今回はドキュメントに沿って,Kinesis Data Streams にメール開封イベントを送信し,Kinesis Data Firehose -> S3 に保存するフローを作りました.なお,Firehose から S3 の連携部分は本記事の割愛します.

docs.aws.amazon.com

Pinpoint -> Kinesis Data Streams の設定

Pinpoint から Kinesis Data Streams の設定を有効化するところをみていきます.対象のプロジェクト>設定>イベントストリームの編集に画面遷移して設定します.Amazon Kinesis へのストリーミング にチェックを入れて,対象の Kinesis Data Stream と IAM ロールを指定すれば完了します.そのため,予め Kinesis Data Sreams を作成している必要があります.

f:id:sadayoshi_tada:20211009164008p:plain

IAM は次のような権限を与えればイベント送信ができます.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "kinesis:PutRecords",
                "kinesis:DescribeStream"
            ],
            "Resource": [
                "arn:aws:kinesis:ap-northeast-1:xxx:stream/xxx"
            ]
        }
    ]
}

送信されてきたイベント

Pinpoint から送られてきたイベントの中身を見てみると次のようになってました.event_type開封のステータスがきていたり,

{"event_type":"_email.delivered","event_timestamp":1633673088121,"arrival_timestamp":1633673089905,"event_version":"3.1","application":{"app_id":"xxx","sdk":{}},"client":{"client_id":"xxx"},"device":{"platform":{}},"session":{},"attributes":{"feedback":"delivered","tags":null},"awsAccountId":"xxx","facets":{"email_channel":{"mail_event":{"mail":{"message_id":"xxx,"message_send_timestamp":1633673088121,"from_address":"test@exmaple.com","destination":["tada@xxx"],"headers_truncated":false,"headers":[{"name":"From","value":"test@exmaple.com"},{"name":"To","value":"tada@xxx"},{"name":"Subject","value":"test"},{"name":"MIME-Version","value":"1.0"},{"name":"Content-Type","value":"multipart/alternative;  boundary=\"xxx\""}],"common_headers":{"from":"test@exmaple.com","to":["tada@xxx"],"subject":"test"}},"delivery":{"smtp_response":"250 2.0.0 OK  xxx xxx.xxx - xxx","reporting_mta":"xxx.ap-northeast-1.amazonses.com","recipients":["tada@xxx"],"processing_time_millis":1784}}}}}
{"event_type":"_email.send","event_timestamp":1633673088121,"arrival_timestamp":1633673088273,"event_version":"3.1","application":{"app_id":"xxx","sdk":{}},"client":{"client_id":"xxx"},"device":{"platform":{}},"session":{},"attributes":{"feedback":"received","tags":null},"awsAccountId":"xxx","facets":{"email_channel":{"mail_event":{"mail":{"message_id":"xxx,"message_send_timestamp":1633673088121,"from_address":"test@exmaple.com","destination":["xxx@xxx"],"headers_truncated":false,"headers":[{"name":"From","value":"test@exmaple.com"},{"name":"To","value":"xxx@xxx"},{"name":"Subject","value":"test"},{"name":"MIME-Version","value":"1.0"},{"name":"Content-Type","value":"multipart/alternative;  boundary=\"xxx""}],"common_headers":{"from":"test@exmaple.com","to":["xxx@xxx"],"subject":"test"}},"send":{}}}}}
{"event_type":"_email.open","event_timestamp":1633673088121,"arrival_timestamp":1633673142677,"event_version":"3.1","application":{"app_id":"xxx","sdk":{}},"client":{"client_id":"xxx"},"device":{"platform":{}},"session":{},"attributes":{"feedback":"opened","tags":null},"awsAccountId":"xxx","facets":{"email_channel":{"mail_event":{"mail":{"message_id":"xxx,"message_send_timestamp":1633673088121,"from_address":"test@exmaple.com","destination":["tada@xxx"],"headers_truncated":false,"headers":[{"name":"From","value":"test@exmaple.com"},{"name":"To","value":"tada@xxx"},{"name":"Subject","value":"test"},{"name":"MIME-Version","value":"1.0"},{"name":"Content-Type","value":"multipart/alternative;  boundary=\"xxx\""},{"name":"Message-ID","value":"null"}],"common_headers":{"from":"test@exmaple.com","to":["tada@xxx"],"subject":"test"}},"open":{"ip_address":"xxx","user_agent":"Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko Firefox/11.0 (via ggpht.com GoogleImageProxy)"}}}}}

まとめ

Pinpoint から Kinesis Data Streams でメール開封イベントを取ることができました.S3 に保存しておけばデータを整形したり,集計もできると思うので,マーケティング分析したりしていけそうです.

CodePipeline と CodeBuild で Git のタグを使ったリリースで切り戻し方を考えた

タダです.

タグリリースを CodePipeline と CodeBuild でやろうとしたときの記事を以前書きました.実際に運用しようと思ったとき,通常は最新のバージョンでいいけど,変更を加えたら意図せず障害が起こり安定したバージョンに障害復旧のために切り戻したいケースが出てくることが想定されます.そのケースに対して対応を考えてみたので記事にします.

sadayoshi-tada.hatenablog.com

結論

今回,CodePipeline で CodeBuild のジョブで使う環境変数を設定できます.切り戻したいバージョンを環境変数に設定して,パイプラインを走らせて切り戻します.画像では CodePipeline で関連づけた CodeBuild に環境変数を指定できて RESTORE_TAG_VERSION を設定してます.

f:id:sadayoshi_tada:20211001013438p:plain

また,buildspec.ymlでは次のような条件分岐を使って,設定してない場合は最新のバージョンを変数を設定している場合は,指定バージョンをチェックアウトするような動作ができます.これで CodePipeline のリリースをスタートすれば切り戻しができます.ただ,切り戻す時は環境変数の値を設定し,切り戻せたらその設定を取り外さなきゃ障害じゃないのに最新のコードをデプロイできなくなる点は運用上注意です.

version: 0.2

phases:
  build:
    commands:
      - echo Checkout tags
      - git fetch --tags
      - |
        if [ "$RECOVEY_TAG_VERSION" = "" ]; then
          git checkout $(git describe --tags --abbrev=0)
        else
          git checkout $RECOVEY_TAG_VERSION
        fi
~中略~

関連情報

aws.amazon.com

AWS CLI で実行する場合

今回のオペレーションを画面操作ではなく AWS CLI でやったらどうなるかも最後に確認しておきます.2つの作業が必要で1つ目は環境変数の値のセット,2つ目は CodePipeline のリリースを開始する作業です.それぞれ以下のコマンドで実行できます.

環境変数の値のセット

aws codepipeline update-pipeline --cli-input-json file://xxx.json

CodePipeline のリリースを開始する

aws codepipeline start-pipeline-execution --name xxx

関連情報

docs.aws.amazon.com

docs.aws.amazon.com

まとめ

タグリリース運用時に考えられる,切り戻しの方法を検証したので記事にしました.環境変数をセットする時としない時が運用上発生するので,この辺は仕組み化していかないと繰り返しの作業になってしまうので検討しなきゃいけない課題があります.仕組み化してまた記事にしたいと思います.

CI に Trivy を組み込んで脆弱性スキャンを行った結果を Slack に通知する

タダです.

業務の中で CodeBuild にてコンテナビルド後,Trivy によるコンテナイメージの脆弱性スキャンをして Slack に通知する仕組みを作る検証を行ったので,検証した内容をこの記事にまとめていきます.

Trivy について

コンテナ脆弱性スキャンツールとして有名で自分も知っていたものの使う機会がなかった中,脆弱性をチェックしていくことを定期的にやっていくべきだと言う理由から Trivy を使っていくことにしました.開発者は Teppei Fukuda さんで,このブログも見たことある方多いのではないでしょうか?

github.com

Trivy の特徴はドキュメントにもあるように脆弱性データベースから OS や言語別のパッケージの脆弱性を検出することができます.また,単一のバイナリをインストールするだけで使えるため,導入のハードルも低いなと感じます.

Trivy detects vulnerabilities of OS packages (Alpine, RHEL, CentOS, etc.) and language-specific packages (Bundler, Composer, npm, yarn, etc.)

Just install the binary and you're ready to scan.

CodeBuild への Trivy 組み込み

CodeBuild への Trivy を組み込むのに際しては,AWS の『How to build a CI/CD pipeline for container vulnerability scanning with Trivy and AWS Security Hub』を参考に進めました.ブログでは Security Hub に診断結果を入れて管理していましたが,相談した結果脆弱性スキャンの結果はHIGHCRITICALが出たら Slack に通知するのを仕込むことにしました(管理は別の場所で行う).

CodeBuild の buildspec.yml の定義

CodeBuild のbuildspec.ymlこちらを参考に進めました.検証では下記のような定義を作りました.

phases:
  install:
    commands:
      - "apt update"
      - "apt install rpm -y"
      - "wget https://github.com/aquasecurity/trivy/releases/download/v0.19.2/trivy_0.19.2_Linux-64bit.deb"
      - "dpkg -i trivy_0.19.2_Linux-64bit.deb"
~中略~
  build:
    commands:
      ~中略~
      - trivy -f json -o results.json --exit-code 0 --severity HIGH,CRITICAL [コンテナイメージ名]
~中略~
  post_build:
    commands:
      ~中略~
      - echo trivy scan results S3 upload on `date`
      - aws s3 cp results.json s3://[アップロードするバケット名]
~中略~

Slack 通知のためにやったこと

Trivy ではスキャンの結果を JSON 出力できるため,JSON ファイルを S3 にアップロードしてバケットにデータを保管し,S3 へのPUT をトリガーに Lambda を発火するようにしました.

f:id:sadayoshi_tada:20210921174348p:plain f:id:sadayoshi_tada:20210921174423p:plain

Lambda が Slack に投稿する内容は以下の項目を抽出して投稿しています.

  • CVE番号
  • ライブラリ名
  • 対象バージョン
  • 緊急度
  • 脆弱性のURL

投稿のイメージ f:id:sadayoshi_tada:20210921223327p:plain

コードはこちらのコードを参考に書いています.サンプルコードの中では JSON の要素的に1つ目で Vulnerabilities があるときはいいのですが,ない時もあるため JSON の要素数分繰り返して Vulnerabilities があるかどうかを判定するようにしました.

response = s3.get_object(Bucket=bucket, Key=key)
body = response['Body'].read()
scan_data = json.loads(body)
json_lens = len(scan_data)
for i in range(json_lens):
     if 'Vulnerabilities' in scan_data[i]:
         for p in scan_data[i]['Vulnerabilities']:
               cveId = str(p['VulnerabilityID'])
               packageName = str(p['PkgName'])
               installedVersion = str(p['InstalledVersion'])
               aquaUrl = str(p['PrimaryURL'])
               trivySeverity = str(p['Severity'])

まとめ

CodeBuild の CI で Trivy を導入,脆弱性スキャンを行ってみたのとその結果を Slack に通知する仕組みを検証したのでその模様をまとめました.今回は CodeBuild の中に入れましたが,GitHub Actions も用意されているためこちらも使ってみたいと思います.

github.com

Amazon ES のバージョンを6.3 -> 6.8 にインプレースバージョンアップグレードする

タダです.

Amazon Elasticsearch Service(先週 Amazon OpenSearch Service に名称が変更されました)のバージョンを6.3->6.8にアップグレードする機会があったので,この記事に設定を方法をまとめていきます.

バージョンアップ方法

Amzon ES ではインプレースバージョンアップグレードがサポートされており,今回はこの手法を使っていきます.

この新しい機能では、数回のクリックだけで、同じメジャーバージョン内での最新リリース (例えば 5.3 から 5.6 など) に、またはメジャーバージョンの最新リリースから次のメジャーバージョンの最新リリース (例えば 5.6 から 6.3) に移行できます

aws.amazon.com

インプレースバージョンアップグレード方法

次に,インプレースバージョンアップグレードを試していきます.テスト環境で画像のものを用意し,これをバージョンアップしていきます.

f:id:sadayoshi_tada:20210915005945p:plain

バージョンアップの適格性の確認

いきなりバージョンアップするのではなく,バージョンアップの確認をしていきます.バージョンアップの適格性の確認を実行していきます.

f:id:sadayoshi_tada:20210915010217p:plain f:id:sadayoshi_tada:20210915010247p:plain

実行し,数分経つと処理が完了します.結果,6.3->6.8へのバージョンアップは問題なく実施できそうなことを確認できました.

f:id:sadayoshi_tada:20210915010558p:plain

インプレースバージョンアップグレードの実施

事前確認が終わったのでインプレースバージョンアップグレードを行なっていきます.バージョンアップが始まると,バージョンアップの適格性の確認->スナップショットの取得が走ります.

f:id:sadayoshi_tada:20210915010756p:plain f:id:sadayoshi_tada:20210915010857p:plain

スナップショット取得後,バージョンアップが走ります.自分が見ていた感じては,30分以内に処理が完了しました.

f:id:sadayoshi_tada:20210915011038p:plain f:id:sadayoshi_tada:20210915011109p:plain

バージョンが6.8に上がっていることも確認できました.

f:id:sadayoshi_tada:20210915011220p:plain

注意点

注意すべきは,AWS のブログにも記載ありますが,アップデートが走ったら止められず完了するまで待ち,その間はドメインの変更ができないことです.

アップグレードプロセスは取り消すことができないので、一時停止またはキャンセルすることはできません。アップグレード中は、ドメインの構成を変更することはできません。実際に、コンソールはクラスタ上の構成変更を呼び出すのに使用できるボタンをすべて無効にします。ドメインは、インデックスの読み書き操作に使用できるため、サービスのドメインとやりとりすることは可能です。

まとめ

Amazon ES のバージョンを6.3 -> 6.8にインプレースバージョンアップグレードで行いました.ボタンを数クリックでバージョンアップが完了したのはプロセスが簡略化されててありがたい機能です.