2&>1

AWSとかGCPとかGolangとかとか

Postfixのバウンスログを集計するシェルスクリプト

#!/bin/bash

# ログファイルのパスを指定
LOGFILE="/tmp/sample_maillog.txt"

# 出力ファイル名を生成する関数(ファイル名に日付を付ける)
generate_output_filename() {
    local current_date=$(date +%Y%m%d)
    echo "bounce_report_${current_date}.txt"
}

# バウンスログを集計してファイルに保存する関数
collect_bounce_logs() {
    local logfile=$1
    local output_file=$2

    # バウンスログを抽出して集計
    grep "status=bounced" $logfile | awk '
    {
        # メールアドレスとバウンス理由を抽出
        if ($0 ~ /to=<[^>]+>/) {
            match($0, /to=<[^>]+>/);
            email = substr($0, RSTART+4, RLENGTH-5);
        }
        if ($0 ~ /status=bounced.*\((.*)\)/) {
            match($0, /status=bounced.*\((.*)\)/, arr);
            reason = arr[1];
        }
        if (email && reason) {
            # バウンスメールアドレスと理由をキーにカウント
            bounce[email "|" reason]++;
            email = ""; reason = "";
        }
    }

    END {
        # 一時ファイルに出力する
        for (key in bounce) {
            split(key, arr, "|");
            printf "%-10s | %-30s | %s\n", bounce[key], arr[1], arr[2];
        }
    }' | sort -nr > $output_file # 回数でソートして出力
}

# メイン処理
main() {
    # 出力ファイル名を生成
    output_file=$(generate_output_filename)

    # バウンスログを集計
    collect_bounce_logs $LOGFILE $output_file

    # 完了メッセージ
    echo "バウンスログの集計が完了しました。出力ファイル: $output_file"
}

# スクリプトの実行
main

こんな感じで出力

54         | user2@example.com              | host mail.example.com said: 550 5.1.1 <user2@example.com>: user unknown
51         | user4@example.com              | host mail.example.com said: 550 5.1.1 <user4@example.com>: spam detected
49         | user4@example.com              | host mail.example.com said: 550 5.1.1 <user4@example.com>: connection timed out
44         | user5@example.com              | host mail.example.com said: 550 5.1.1 <user5@example.com>: user unknown
44         | user5@example.com              | host mail.example.com said: 550 5.1.1 <user5@example.com>: host not found
44         | user4@example.com              | host mail.example.com said: 550 5.1.1 <user4@example.com>: mailbox full
44         | user1@example.com              | host mail.example.com said: 550 5.1.1 <user1@example.com>: mailbox full
43         | user3@example.com              | host mail.example.com said: 550 5.1.1 <user3@example.com>: spam detected
42         | user3@example.com              | host mail.example.com said: 550 5.1.1 <user3@example.com>: user unknown
42         | user1@example.com              | host mail.example.com said: 550 5.1.1 <user1@example.com>: user unknown
41         | user4@example.com              | host mail.example.com said: 550 5.1.1 <user4@example.com>: user unknown
41         | user2@example.com              | host mail.example.com said: 550 5.1.1 <user2@example.com>: spam detected
40         | user2@example.com              | host mail.example.com said: 550 5.1.1 <user2@example.com>: host not found
40         | user1@example.com              | host mail.example.com said: 550 5.1.1 <user1@example.com>: connection timed out
39         | user5@example.com              | host mail.example.com said: 550 5.1.1 <user5@example.com>: mailbox full
39         | user5@example.com              | host mail.example.com said: 550 5.1.1 <user5@example.com>: connection timed out
38         | user1@example.com              | host mail.example.com said: 550 5.1.1 <user1@example.com>: spam detected
37         | user3@example.com              | host mail.example.com said: 550 5.1.1 <user3@example.com>: connection timed out
35         | user5@example.com              | host mail.example.com said: 550 5.1.1 <user5@example.com>: spam detected
35         | user4@example.com              | host mail.example.com said: 550 5.1.1 <user4@example.com>: host not found
35         | user2@example.com              | host mail.example.com said: 550 5.1.1 <user2@example.com>: mailbox full
33         | user3@example.com              | host mail.example.com said: 550 5.1.1 <user3@example.com>: host not found
31         | user3@example.com              | host mail.example.com said: 550 5.1.1 <user3@example.com>: mailbox full
31         | user1@example.com              | host mail.example.com said: 550 5.1.1 <user1@example.com>: host not found
28         | user2@example.com              | host mail.example.com said: 550 5.1.1 <user2@example.com>: connection timed out

IAM Identity Center のユーザーへのcloud9共有方法

以下のユーザー条件に該当する人にCloud9環境を共有します。

「 IAM Identity Centerのユーザー」もしくは「IAM Identity Center によって作成された IAM ロール」

通常はIAMユーザーを作成して共有できます。

しかしコントロールタワーなどでユーザー管理している場合はIAMユーザーとは違います。

その場合は以下でユーザーのARNを確認。

1.共有したいユーザーからCloudshellにログインする

2.以下コマンド実行

aws sts get-caller-identity

以下のような出力

{
    "UserId": "AROAVAHUIBHHJJNJ:hoge.hogeo",
    "Account": "*******",
    "Arn": "arn:aws:sts::****:assumed-role/AWSReservedSSO_************/hoge.hogeo"
}

3.ARNをメモ

4.Cloud9のShere設定から取得したARNを入力

これでCloud9環境を共有できます

AWS コスト削減のポイント(自分流)

クラウドのいいとこは使った分だけっていうのはあるけど使った分はしっかり請求されます。

なるべく抑えましょう

コストタグをつける

現状を把握が必要です。 どのリソースがどのくらい費用がかかっているかCost Explorerで明らかにしましょう。 以前はコストタグを付けたときからの費用計算しかできなかったのでしばらく待つ必要ありましたが、最近のアップデートで12ヶ月遡って計算してくれるようになりました。

AWS コスト配分タグが遡及適用のサポートを開始

リザーブインスタンス、savingplanの活用

基本の木です。EC2はもちろんECS,lambdaも対象になるのでインスタンス立ち上げぱなしの環境はまず購入。 savingplanに関しては7日以内のキャンセルが可能なので購入時のボタンを押す緊張感が若干なくなりました。

AWS が Savings Plans の 7 日間の返品期間と発表

これで一番恩恵を感じられるのはRDSやopenserch serviceじゃないでしょうか。 ただでさえ高いですからその分割引された金額が安く感じます。(ServerlessはRIないので注意) RIだとインスタンススペックの柔軟性がなくなるのがきついなーって場合はあるとおもいます。同じインスタンスタイプ内でスペックを1つ上げる場合は購入したRIは適応されるので損にはならないです。 1つ下げるときは購入した半分は未適応状態になるのでちょっと損です。

インスタンスを夜間停止する

ステージング環境など業務時間だけ触って夜間は触らないような環境は停止したほうが安い場合が多いです。8時起動→20時停止など稼働率50%だとRI契約は高くつきます。 EventBrigeで自動停止・自動起動させるようにしましょう。RDS、ECSなどもできるので忘れずに。

EventBridgeスケジューラを使ってEC2の定期起動/停止を行う方法 | DevelopersIO

スペックの最適化

使用リソースに基づいて各インスタンスのスペックを決めましょう。え?難しい?「AWS Compute Optimizer」に任せましょう。いい感じにしてくれます。 このサービスメモリをデフォルトで見てくれないの改善しないかなぁ。。 古いインスタンスタイプを使用している場合は、最新の同じインスタンススペックに変更するだけで安くなります。 ECSのスペック決めは課題が残る。。

お金のかかる不要リソース削除

「Elastic IP」「ELB」検証だけで立てたものがそのまま残ってる場合が多々あります。こまめに削除しましょう。 Elastic IPも1つづつ課金させるようになってるので注意です。

スナップショットなど数年前に作成したもの残ってないですか?そんなもので今リソースを再構築することないので消しましょう。

ここまでは即効性のある対策。ここからはちょっと手間がかかるかも。

ECSログの吐き出し先

ECSからログの出し方はいくつかありますが一番シンプルで楽なのがCloudwatch logsに出す方法です。しかしログの量によってはとてつもない費用がかかるのがCloudwatch logs。

保管費用もよりも吐き出したときにかかる費用が高いです。東京リージョンでUSD0.76/GBもかかります。

Cloudwatch logsはログ監視もできて便利ですが吐き出すログは取捨選択しましょう。

おすすめはエラーログだけCloudwatch logsに出してそれ以外はS3に放り投げる。

Cloudwatch のメトリクス設定しすぎない

Cloudwatchの監視は標準メトリクスの他にカスタムメトリクスを作って監視項目を設定できます(メモリ監視みたいなの)

カスタムメトリクスの場合無料枠が10個まででそれ以上は監視するたびに費用が発生します。何も考えずにあれこれと数字だけ取ることを目的とした設定をしていると合算したとき高くつくときがあります。ある程度まとまらないとわからない点など注意です。 監視が必要な値に絞りましょう。

まとめ

もともと高いサービスは注意が行きやすいけど、合算したとき人知れず高くなるものは注意が必要ですね。

円安な今気をつけましょう。。

Akamai構成のKeepAlive設定を決めた

AkamaiCDNが前段にあるシステムで後ろに控えるALBやApacheのKeepAlive設定を検証しました。

さらには先日リリースされた以下機能でALBに追加された項目を確認。

aws.amazon.com

項目名は以下の2つが関連する。

「Connection idle timeout」

「HTTP client keepalive duration」

項目の意味合いとしはこんな感じ

実際にはどのような挙動になるのかを確認する

Connection idle timeout

ClientとTargetに対してidle状態(無通信状態)でコネクションを保持する時間

HTTP client keepalive duration

Clientに対してのkeepalive時間

(この時間だけはなにがあろうとコネクションを残しておくということ)

確認手順

ALBに対してtelnetでアクセス

 telnet test-local-frt-alb01-1038675640.ap-northeast-1.elb.amazonaws.com 80
telnet test-local-frt-alb01-1038675640.ap-northeast-1.elb.amazonaws.com 80
Trying 54.95.144.247...
Connected to test-local-frt-alb01-1038675640.ap-northeast-1.elb.amazonaws.com.
Escape character is '^]'.
GET / HTTP/1.1     ←入力
Host: localhost  ←入力
         ←エンター入力
HTTP/1.1 200 OK
Date: Tue, 09 Apr 2024 01:26:24 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 12
Connection: keep-alive
Server: Apache/2.4.58 (Amazon Linux)
Last-Modified: Mon, 08 Apr 2024 09:24:32 GMT
ETag: "c-615925f82a5c5"
Accept-Ranges: bytes

test server

「test server」の表示でるとHTTPアクセス成功

「Connection closed by foreign host.」 の表示が出るまでは同じコネクションで通信していることになる

設定値は以下

確認1

初回アクセスから20秒放置すると「Connection closed by foreign host.」が出力されて切断

確認2

初回アクセスから60秒放置しても切断されず。 120秒放置すると「Connection closed by foreign host.」が出力されて切断

60秒以降120秒までの間にアクセスするとステータス成功した後「Connection closed by foreign host.」が出力されて切断

結果

「Connection idle timeout」は強制的に切断される

「HTTP client keepalive duration」は強制切断はされない

Apache側のkeepaliv値により違いはクライアント側の挙動では確認できず。

ただしALB-Apache間ではコネクションの切断再接続は起きていると想像。

(パケットキャプチャーなどでみると都度都度コネクションの張り直しが発生しているはず)

Akamai含めての設定値

セオリーとしては前段システムのkeepaliveは長く、後ろは短く。

後ろが長いと後ろ側だけ成功してて前には失敗が返ってしまう可能性があるため。

今回はAkamaiでの処理を最優先で発揮させるためにakamai-alb間のコネクションを最大限つなげる

ALBでのHTTPステータスコードとTargetでのHTTPステータスコードを監視しておくことでkeepaliveによる返り値の違いを把握できる。

Akamai Community

Organizationsな組織アカウントでCloudwatchグラフを共有したいときにできなかったこと

やりたいこと

モニタリングアカウントを用意して監視を集約したい。 Cloudwatchグラフを作成してモニタリングアカウント経由で組織アカウントのだれでもサクッと見れるようにしたい。

やり方

具体的な設定方法はよくあるものなので以下とか参考に

[Organizations]CloudWatchを別アカウントに共有する際にOrganization account selectorを使ってみた | DevelopersIO

なにができないの?

この設定をしたときに設定したアカウント以外から見たときにグラフの選択肢が出てこなかったのです。

具体的にはここ

他のアカウントからはアカウントの一覧を選択する欄が表示されなかった。

原因

モニタリングアカウントのCloudwatch設定で「アカウントセレクタを有効化」する項目がデフォルトだと何も選択されいない状態だったため

でもこれ設定したアカウントで有効化したんですよ。

どうやらこれはログインしているアカウントユーザー毎の設定でした。 (サポート確認済み)

だから各ユーザー毎に有効化しないといけないです。

どうしたのか

理想としては各ユーザー毎の作業必要なく見れるのがベストです。(無用な問い合わせを避けるためにも)

各アカウントでパブリックなcloudwatchダッシュボード作成して展開するのが無難かなと考え中。

Amazonlinux2023にTeratermから接続できなかった話

謎が溶けました。

弊社環境ではサーバなど構築した際、秘密鍵を作成して開発担当者やチーム内で連携するのですがとある担当者が作成したキーだけ 他のモノが使えない事象が出ていました。

キーを間違えてるのか、キーが壊れているのかなど思ってたのですが作成した担当者は使えてるようです。

ほんとに同じキー?とおもって見てみると作成者は使えて、他の者は使えないキーは同じでした。

弊社の作業PCはwindowsMACがいます。作成者はMACです。windowsSSHクライアントはteraterm使ってます。

作成したサーバはAmazonlinux2023です。

そうですね。

原因

Amazonlinux2023の秘密鍵の違いでした。

Amazonlinux2023では「SSH-RSAが無効化」されているためです。 そして新規で「rsa-sha2-256」「rsa-sha2-512」が有効化されています。

teratearm4.0系ではこの無効化されたものを使います。 teratearm5.0系では新規で追加されたものが使えます。

解決策

teratearm5.0に変更

teraterm4.0でも接続できるようにすることはできるがセキュリティ上古いものを有効化する必要がある。 わざわざすることも無いので新しいものに切り替え。

新しいは正義

Zabbix_AgentがAllowRoot=1でrootになれないときに

Zabbxiでログ監視をするときはrootにならないといけないときありますよね。 (ならなくてもいいときもある)

zabbix_agent.confで

AllowRoot=1

としてもAgentがroot実行されずハマりました。

結論

続きを読む