AWS アカウント内の不要なリソースをシンプルにチェックしてくれる unusd.cloud を利用してみた

まもなく金曜日の夕方ですし、意図しないリソースが起動したままになっていないか、サクッとチェックしてみませんか?
2023.04.14

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

クラウドコストを最適化する上で、利用していないリソースによって料金が発生しないように停止や削除することは重要な取り組みの一つとなります。そのために、コストをモニタリングしたり AWS Trusted Advisor やコスト管理サービスからの情報を利用して、定期的にリソースを棚卸しされている方も多いのではないかと思います。

クラウドコストあるあるかもしれませんが、"開発や検証するために起動した AWS リソースの停止・削除を失念してしまい(削除したけど全て削除できていなかった)、慌てて停止したり、気付けず結構な金額になってしまったということはありませんか?"私はあります、、特に金曜日までに気づかないと土日もそのままになってしまうため、ショックが大きいです。

本記事では、定期的なしっかりとした棚卸しではなく、"安心して休日を迎えられることを目的として"、サードパーティ製品を利用して主要な AWS サービスで不要なリソースがないか(削除漏れがないか)をチェックしてみたいと思います。利用するサービス自身が安心して休日を迎えることをコンセプトとしたサービスではありません。単なる私個人の目的です。あらかじめ、ご了承くださいませ。

利用するサービスは unusd.cloud というサービスを利用します。

unusd.cloud では現在(23/04/14)、下記のサービスをチェック対象となります。

  • EC2 Instances
  • IAM Principals (Users, Roles)
  • RDS Instances
  • Orphan EBS Volumes
  • Unused Elastic IPs
  • Redshift Clusters
  • SageMaker Notebooks
  • Glue DevEndpoints

引用元: ? Garbage collector for your AWS Accounts

事前準備

利用する前に、下記3つだけ準備を行います。

  • unusd.cloud へサインアップ(メールアドレスが必要)
  • AWS アカウントと紐付け
    • AWS CloudFormation を利用して IAM Role 作成(unusd-cloud-spoke-role)
  • チェック(スキャン)実行タスクの設定

unusd.cloud へサインアップ(メールアドレスが必要)

サイトへアクセス >>> Start saving now! を選択

Sign up を選択

ユーザー名とパスワードを登録して、認証コードを受け取り、入力します。

AWS アカウントと紐付けと AWS CloudFormation を利用して IAM Role 作成(unusd-cloud-spoke-role)

Add AWS account へチェックしたい AWS アカウントIDを入力 >>> Create を選択

Deploy the IAM Role を選択すると AWS CloudFormation 画面へ遷移します。

実行される yaml は下記の通りです。
読み取り権限のみなので心配ないかと思います。AWS CloudFormation の画面に沿って実行します。

AWSTemplateFormatVersion: "2010-09-09"
Description: "Provides **READ ONLY** capabilities to unusd.cloud to perform scans of your AWS accounts."

##################################################################
Parameters:
  ##################################################################
  ExternalID:
    Description: >-
      unusd.cloud role uses an ExternalID in order to protect
      the cross-account session role. Please do not change this value!
    Type: String
    MinLength: "36"
    MaxLength: "36"
    AllowedPattern: '[\w+=,.@:\/-]*'
    ConstraintDescription: 'Invalid ExternalID value.  Must match pattern [\w+=,.@:\/-]*'
##################################################################

##################################################################
Resources:
  ##################################################################
  SpokeRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              AWS:
                - arn:aws:iam::<unusd.cloud AWS ID>:root
            Action: "sts:AssumeRole"
            Condition:
              StringEquals:
                "sts:ExternalId": !Ref ExternalID
      Policies:
        - PolicyName: unusd-cloud-policy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - ce:GetCostAndUsage
                  - ce:GetCostForecast
                  - cloudwatch:GetMetricStatistics
                  - ec2:DescribeAddresses
                  - ec2:DescribeInstances
                  - ec2:DescribeInstanceStatus
                  - ec2:DescribeRegions
                  - ec2:DescribeVolumes
                  - glue:GetDevEndpoints
                  - glue:GetTags
                  - iam:GetAccessKeyLastUsed
                  - iam:GetRole
                  - iam:ListAccessKeys
                  - iam:ListAccountAliases
                  - iam:ListRoles
                  - iam:ListUsers
                  - pricing:GetProducts
                  - rds:DescribeDBInstances
                  - rds:ListTagsForResource
                  - redshift:DescribeClusters
                  - sagemaker:ListNotebookInstances
                  - sagemaker:ListTags
                Resource: "*"
      RoleName: unusd-cloud-spoke-role
      Description: unusd.cloud spoke role
      MaxSessionDuration: 3600
      Tags:
        - Key: "SaaS"
          Value: "https://unusd.cloud"
        - Key: "Contact"
          Value: "support@unusd.cloud"
        - Key: "Version"
          Value: "0.3"

  DeploymentCallback:
    Type: "Custom::DeploymentCallback"
    Version: "1.0"
    Properties:
      ServiceToken: !Sub "arn:${AWS::Partition}:sns:${AWS::Region}:<unusd.cloud AWS ID>:unusd-cloud-deployment-callback-prod"
      AwsPartition: !Ref "AWS::Partition"
      AwsAccountId: !Ref "AWS::AccountId"
      AwsRoleName: !Ref "SpokeRole"
      AwsRoleExternalId: !Ref "ExternalID"
      TemplateVersion: "0.3"

##################################################################
Outputs:
  ##################################################################
  RoleArn:
    Description: unusd.cloud IAM Role Arn
    Value: !GetAtt SpokeRole.Arn

チェック(スキャン)実行タスクの設定

タスク一覧 >>> 3点リーダー >>> Edit を選択

日次、週次、月次、カスタムで設定が可能です。

実行と結果

環境

手元の検証環境はクリーンな状態になっていて、"やってみる" にならないので、下記のリソースを作成しておきます。

  • Amazon EC2 x1

  • EIP x2(そのうち1つは未使用)

  • EBS x2(そのうち1つは未使用)

想定としては、EIP と EBS でそれぞれ利用していないリソースがあることを知らせてくれることを期待しています。

実行

スケジュール実行以外にも、すぐに実行することが可能なため、 Scan now から実行してみます。

結果

今回は、メール通知設定を行っているので、しばらくするとメールで結果が届きます。他にも slack や Microsoft Teams へ通知が可能です。

冒頭で、現在コストや今月までの予測コストが記載されています。
意図した EBS と EIP もレポートとして報告されました!

利用していない IAM Role も結構ありますね、、こちらは精査しなくては、、

英語ではありますが、見た目も良くて、わかりやすいですね!

さいごに

AWS アカウント内の不要なリソースをチェックしてくれる unsud.cloud を利用してみました。対象となっているサービス以外にも、Nat Gateway や ELB もチェックして欲しいなという声も聞こえてきそう(私自身の声かもしれない)ですが、簡易チェックとしては十分ではないでしょうか。

こういった活動は、実施することもさることながら、出来るだけ特定個人や人の手からサービスや自動化へオフロードし、適切なチームにダイレクトに届けるような仕組みにしていくのも大切ですね。また、今回紹介したサービス以外にも多くのサービスや方法が存在しているかと思います、自分達の要件にマッチしたものを採用して、平日は存分にクラウドを利用して、土日は安心して過ごしましょう!