MacBook Air (M1, 2020)に買い替えて約1年が経過


2021年の初めに、それまで使用していたMacBook Air (Retina, 13-inch, 2018)からMacBook (M1, 2020)に買い替えて約1年が経過しました。スペックは、

  • 8Core CPU
  • 16GB Memory
  • 512GB SSD

と、メモリをいつも通り2倍に増設しています。

まぁとにかく速い

ここ近年、CPUの性能が格段に向上したおかげで、体感的なパフォーマンスというのがそんなに気にならなくなってはきましたが、それでも特にマシン自体の起動時や、少し重めのアプリケーションを起動させる時など、速いなという印象は強く受けています。

最近は在宅勤務下で、一旦お蔵入りしていたMacBook Air (Retina, 13-inch, 2018)を併用しているのですが、同じMacBook Airなのにチップセットが違うだけでこんなにパフォーマンスが違うものなのか、ということを改めて痛感させられます。

キーボードが打ちやすい

先代のMacBook Airで採用されていたバタフライキーボードは、使えば慣れたもののなんだか打鍵感がパタパタしていて場合によってはキーを打ちにくいなぁという印象を感じていたのですが、MacBook Air (M1, 2020)ではシザーキーボードが復活したことで、打鍵感が確実に向上しました。いくらキーを打っていても疲れることがなくなりました。

それと、先代のバタフライキーボード、使い続けていくとだんだんキーコーティングが剥げてくるんですよね。自分のもまさにそうで、矢印キーなどはどっち向きの矢印なんだかよくわからない状態(なので買い替えの際に下取りに出すことを躊躇した)なんですけれども、現在は1年間使用していてもコーティングが剥げるような事態には、今のところなっていません。確実に使用する頻度は高いのですが。

何に使っているのか

日常の作業はほとんどこの1台で完結しています。Webの閲覧、ドキュメントやメールの作成などは当たり前として、Visual Studio Codeを使用して自前でちょこちょこ開発作業などもしているので、軽い作業からそれなりに重い作業までやっている感じです。それでもストレスを感じさせず、重量の軽さも相まってどこにでも持っていくことができる点で、確実に手が離せなくなっているのは確かですね。1日平均で10時間くらいは何かしらの用途に使っているかもしれません。

これからApple シリコンを搭載したMacもどんどん進化していくのは確実なんですが、この1年間使い倒している限りでは、少なくともApple Careの保証期限が切れるまではこれ1台で切り盛りできそうな感じです。下手すれば5年くらい使えるんじゃないかな。通常は3年周期で買い替えをおこなっているのですが、だいぶ手に馴染んできているのでこれからも丁寧に使っていくつもりです。

カテゴリー: Private | タグ: , , | コメントする

Amazon EC2インスタンスの起動停止をAmazon EventBridge + AWS Lambdaでコントロールする


きっかけ

仕事の中で複数持っている自分のタスクを効率よくこなしていくのとともに、散らばっている情報を一つに集約して常に整理していくのはとても重要なことだと思っています。前者に関して、自分のプロジェクト内のタスクコントロールはヌーラボさんのBacklogで完結していて、ものすごく重宝しているのですが、Backlogで管理している課題よりももっと細かい粒度のタスクを個人レベルで管理するにあたって、ガントチャートレベルで期限日を重要度を意識しながらコントロールしていくのがどうも苦手なので、とりあえずこの目的を達するために管理の手段としてredmine使おうと思い、どうせだったら個人で保有しているAWSアカウントの中に、redmineのAMIを使用したEC2インスタンスを立ててしまえばいいじゃん、となったわけです。

ところが自分のAWSアカウント、使い始めてかれこれ数年になるので、残念ながら無料枠は使えません。なので、コスト削減のために、自分が普段のルーチンとしてタスクの棚卸をする時間帯だけ起動させるようにしたい、と思ったのがそもそものきっかけです。

せっかくならAWS Lambdaを使いたい

ちょうど同時進行で、AWS Lambdaの勉強を掘り下げていたこともあったので、せっかくならば自分でコードを書いてLambda関数を作り、その機能でコントロールさせてあげればいいなと。AWS Lambdaの特徴としては、

  1. インフラストラクチャの運用管理が不要
  2. イベントドリブンであること
  3. コスト効率が高い

の3つが挙げられるのですが、何気に2番目って、自分の観測範囲ではなかなか使われていなかったので、この機会に使ってみようと思ったわけです。使いたい時間だけ使えるようにすればいいので、Amazon EventBridgeを使ってLambda関数と連携してあげればOK。

というわけでさっくりとLambda関数上でワークフローを組み上げました。そんなに難しいことはしていません。

とりあえず器として”EC2-Auto-Start-Stop”というLambda関数を作成し、トリガーとしてEC2インスタンスを起動するためのEventBridgeトリガーと、EC2インスタンスを停止するEventBridgeトリガーを追加。一応念のため、ちゃんとEC2インスタンスが起動停止したよということをSMSとして送信するためのAmazon SNSトピックも送信先として追加。

これだけなんですけれどもね。

Amazon EventBridge側の設定

まず最初に、それぞれのEventBridgeのトリガーとして、今回はスケジュールで実行するので、起動・停止したい時刻をcron式で定義してあげます。

次に、イベントを起動してあげたいLambda関数を指定します。この時、EC2インスタンスのタグを読み取ってイベントを起動する、というやり方もあるのですが、自分の場合は、Lambda関数のevent引数の中に、起動対象のEC2インスタンスが所属するリージョン情報と、起動したいのか、停止したいのかを示すフラグをjsonで渡してあげるようにしました。

Lambda関数にコードを書く

ここで、いよいよLambda関数のコードを書いていきます。今回はサクッと書きたいためにラインタイムは”Python3.9″を選択。せっかくなのでアーキテクチャは採用されたばかりの”arm64″を選択します。

で、デフォルトで作成される”lambda_function.py”に書いたコードは以下の通り。

import boto3
import logging
import traceback

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):

    try:
        region = event['Region']
        action = event['Action']
        client = boto3.client('ec2', region)
        responce = client.describe_instances(Filters=[{'Name': 'tag:AutoStartStop', 'Values': ['1']}])
        target_instance_ids = []

        for reservation in responce['Reservations']:
            for instance in reservation['Instances']:
                target_instance_ids.append(instance['InstanceId'])
        
        print(target_instance_ids)

        if not target_instance_ids:
            print('There are not instances subject to automatic start or stop.')
        else:
            if action == 'start':
                client.start_instances(InstanceIds=target_instance_ids)
                print('Started Instancess.')
            elif action == 'stop':
                client.stop_instances(InstanceIds=target_instance_ids)
            else:
                print('Invalid action.')

        return {
            "statusCode": 200,
            "message": 'Finished automatic start or stop EC2 instances process. [Region: {}, Action: {}]'.format(event['Region'], event['Action'])
        }

    except Exception as e:
        logger.error(e)
        print(traceback.format_exc())
        return {
            "statusCode": 500,
            "message": 'An error occured at automatic start or stop EC2 instances process.'
        }

ざっくり解説すると、EventBridgeの入力の設定で設定したリージョン情報と起動・停止のフラグを読み込んで、EC2インスタンスのタグで自動起動停止設定が”1″(true)になっているインスタンスIDを探し出し、順繰りに起動または停止してあげるだけというものすごく簡単なコードです。簡単すぎて申し訳ない。。。

まとめ

こんな感じで、意外にも簡単に、EC2インスタンスを決まった時間に自動的に起動停止する仕組みが出来上がりました。

実際にこうして簡単なコードを書いてみることで、Amazon EventBridgeからLambda関数がイベントドリブンでどのように連携されていくのかということをハンズオンレベルで理解ができるというのはいいですね。

またこういった問題って、AWS認定SysOps アドミニストレーター アソシエイト試験(AWS SOA)でも出てきたりするので侮れないです。

これからもこんな感じで楽しみながらコーディングしたり設計したりしつつ、AWSの持つ各サービスの仕組みを理解していきたいと思います。

カテゴリー: AWS | タグ: , , | コメントする

ANA MILEAGE CLUB Bronzeのステータスに到達


2021年もCOVID-19の影響で外出自粛が求められている中ではありましたが、感染状況を見極めていきながら、20年近く利用しているANAに搭乗する事で支援していきたい、ということで、ワーケーションや親戚に会いに、羽田 – 福岡間を往復していたところ、どういうわけかANAマイレージクラブのBronzeのステータスに到達してしまいました。

JetLoversのログを辿るとこんな感じです。

  • 2021/3/21 NH243 HND – FUK (JA609A / 2K)
  • 2021/3/22 NH258 FUK – HND (JA811A / 2A)
  • 2021/6/25 NH245 HND – FUK (JA804A / 30J)
  • 2021/6/27 NH262 FUK – HND (JA808A / 7H)
  • 2021/8/28 NH245 HND – FUK (JA821A / 2K)
  • 2021/8/29 NH256 FUK – HND (JA816A / 1A)
  • 2021/10/30 NH247 HND – FUK (JA815A / 6G)
  • 2021/10/31 NH256 FUK – HND (JA834A / 5K)

普段なら羽田 – 福岡間4往復では、プレミアムクラスを使ったとしてもBronze到達条件になる30,000プレミアムポイントまでは到達できないのですが、2021年は2回プレミアムポイント2倍キャンペーンがあったのがかなり大きかったですね。そういう意味ではかなりラッキーなBronze到達だったのかもしれません。

何故このご時世に飛行機で旅行なんて、と眉を顰める方もいるかもしれませんが、航空機そのものが衛生面ではかなり安全な乗り物であるということと、搭乗便と座席番号がきちんと乗客名簿に記録されるので、万が一の時があっても行動を追跡してもらえやすいというところは大きいですね。なので逆に不特定多数の人が利用する新幹線の方が万が一の時のリスクは大きいのではないかという。

もともと福岡は好きな街ですし、なんなら移住したいくらいのつもりでいるので、2022年もガッツリ登場して、Bronzeのステータスの恩恵をいただきたいと思っています。

ANAは日本の航空会社の中では一番好きなので、苦境の航空業界の中にあっても引き続き搭乗して支援していきたいと思っています。

カテゴリー: Private | タグ: | コメントする

レイヤーを含むLambda関数からAmazon S3バケットにアクセスしようとして難儀した話


つい最近Lambda関数の実装をしていまして、その中で困ったことと解決したことがあったので、自分への備忘も兼ねて共有します。

一応エチケットシートとして。この記事は投稿時点(2021/6/20時点)において検証した結果に基づいており、今後Amazon Web ServicesのBoto3ライブラリの仕様が変更された場合には、必ずしもこの検証通りの結果にならない可能性があることだけ、ご了承ください。

やろうとしていたこと

  • Amazon S3バケットからS3.PutObjectを行う処理のみを、Lambda関数のレイヤーとして切り出す
  • 上記で作成したレイヤーをimportしているビジネスロジックの部分をLambda関数上で実装する
  • レイヤー、Lambda関数ともにPython3.8で実装
  • Lambda関数を実行すると、S3バケットにファイルが格納される

ちなみにレイヤーのコードはざっくりこんな感じです。もうほとんどBoto3のドキュメントのお作法そのまんまです。

import boto3

def put_object(fileObject, bucketName, filePrefix, Key):

    if filePrefix != '':
        key = filePrefix + Key

    s3 = boto3.resource('s3')
    object = s3.Object(bucketName, Key)

    response = object.put(
        Body=fileObject,
        ContentEncoding='utf-8',
        ContentType='text/plain'
    )

困ったこと

このレイヤーを含むLambda関数をリリースして、同じAWSアカウント内にS3バケットを作成。ブロックパブリックアクセスは有効にしています。

ブロックパブリックアクセスを有効にしている場合でも、デフォルトでは特に作成したS3バケットへのファイルの格納は普通にできる、と思っていたのですが、いざLambda関数を実行してみると、ファイルが格納されないわけです。で、デバッグのためにCloudWatch Logsの該当ロググループを確認すると、

botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

お決まりのAccess Deniedが出力されているわけで。

危ないと知りながらも、一旦S3バケットのブロックパブリックアクセスを無効にしてみたり、それでも解決しないので、再度ブロックパブリックアクセスを有効にして、Lambdaの実行ロールに対してPutObjectとPutObjectACLを有効にしてあげるバケットポリシーを書いてみたりしてもどうにも解決せず、途方に暮れていました。

解決方法

鍵はバケットポリシーの書き方に違いない! というところまではなんとなく勘がついていたので、試しに以下のようにバケットポリシーを書き換えてあげたら、普通に該当するS3バケットにファイルが格納されるようになったではないですか!

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:sts::(AWSアカウント):assumed-role/(レイヤー名)",
                    "arn:aws:iam::(AWSアカウント):role/(Lambda関数の実行ロール)",
                    "arn:aws:sts::(AWSアカウント):assumed-role/(Lambda関数の実行ロール)/(Lambda関数名)"
                ]
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::(S3バケット名)/*"
        }
    ]
}

どうも、同一アカウント内でS3バケットに対する操作を行う場合でも、Lambda関数とレイヤーからの操作を受け入れるためのassumed roleを明示的に書かないと、S3バケットに対する操作ができないようです。

今回の構成では、Amazon S3向けのVPC Endpointは実装していないので、Lambda関数からS3へのアクセスの通信が、一旦インターネットに出ていっているが故に、明示的にこういったポリシーの設定をしてあげないとダメなのかもしれません。まだVPC Endpointを設定していないので、断定的なことは言えないのですが。

まぁとにかくやりたいことは実現できたのですが、Amazon S3とLambda関数の関係は、まだまだ勉強しなければいけないですね。。。日々精進です。

カテゴリー: AWS | タグ: , , , | コメントする

AWS認定ソリューションアーキテクト プロフェッショナル(AWS SAP-C01)に合格しての感想


1回目の受験では684点のスコアで残念ながら不合格になってしまったのですが、そこから気を取り直して学習を続け、2回目で無事に、824点のスコアで合格することができました。いやぁ嬉しいです。なんとか登るべき山を一つ登り切ったというか。

どんな風に勉強したのか

どんな風に勉強したのかといっても、合格体験記は検索すればきっとたくさん出てくるのではないかと思うので、それらの勉強方法は一通りやったという感じです。もちろんAWS クラウドサービス活用資料集は片っ端から読みまくったし、参考書がなかなかない中でオンラインの問題集を、1日の中で時間を決めて順繰りに解いていったりということはやってきました。

強いて言えば、現在携わっているプロジェクトの中で、AWS Direct ConnectからDirect Connect Gatewayの移管に関わったり、IAM関連の設計や実装に関わったりすることで、座学だけでは得られない経験を得られたというのは大きかったと思います。そういう意味では、Amazon Web Servicesがこの試験の受験対象として記している「2年以上の実務経験」というのは本当に合っているのかもしれません。

とはいえ、個人で所有しているAWSアカウントでは、どうしてもコストの兼ね合い上無尽蔵にAWSリソースを作りまくるというのは現実的にはかなり厳しいので、座学中心の学習になってしまうことは仕方がないとも思います。個人でAWS Organizationsあたりを構築するのは容易ではないですしねぇ。

ここまでの所感

これまで、

  • 2019年6月: AWS認定クラウドプラクティショナー (AWS CLF-01)
  • 2020年3月: AWS認定ソリューションアーキテクト アソシエイト (AWS SAA-C01)
  • 2020年9月: AWS認定デベロッパー アソシエイト (AWS DVA-C01)

と、ひとつひとつ段階を追うようにAWS認定資格を取得してきましたが、やはりいきなり飛び級的にAWS SAAを取得しようとは思わずに、AWS CLFから取得してきたのは、知識の積み上げとしては良かったのかなぁと思っています。

そして、実はアソシエイトレベルの試験を突破するのが一番難しいんじゃないかなぁと思ったりもしています。AWS認定SysOpsアドミニストレーター アソシエイト(AWS SOA)も2021年7月下旬をもってバージョンが上がるのが確実になっていますし、難易度も確実に上がってくるんでしょうね。なので、もしも実務に関わっている人であれば、CLF → SAA → SOAを経由してSAPに挑んだ方がもしかしたらいいのかもしれません。あくまで個人的な感覚ですが。

次の目標

次の目標として確実にマイルストーンとなってくるのは、当然のことながらAWS SOA-C02に合格することになってきます。頭では分かっていても、それを実技として相応のスキルがあるということを証明できないと、AWS系のエンジニアとしてそれ相応のスキルを持っていますよということを認識してもらうことができるというのが難しいという風に感じるようになってきたので。そういう意味では自分の中では超難関ですね。

もちろん、試験に受かって認定資格を得ることが目的ではなくて、認定資格を取得しているだけの知見を持つことが目的であることには変わりないのですが、それを定量的に示す指標として、これからも変わらず、次の試験に挑むために知識と経験を積み重ねていきたいと思っています。

カテゴリー: AWS | タグ: | コメントする