amareloのブログ(仮)

IT系勉強会で感じた想いや知見をメインに書いていきます。

Infra Study Meetup #3「SREのこれまでとこれから」参加レポート

6/16(火)、Infra Study Meetup #3「SREのこれまでとこれから」に参加しましたので、レポートを書きます。

目次

イベントページ

forkwell.connpass.com

SREとは

Wikipediaより引用しました

  • SRE(Site Reliability Engineering) は、Google社が提唱、実践しているシステム管理とサービス運用の方法論
  • サイト信頼性エンジニアリングと訳される場合もある
  • サイトリライアビリティエンジニアリングを担当するエンジニアをサイトリライアビリティエンジニア(SRE)と呼ぶ

※以下は自分の浅い理解のもと書いた言葉です。違っていたらツッコんでください。

  • Webシステムの信頼性を向上させ、システムそのものの価値を向上させるための取り組み

基調講演「SREの文化と組織」 株式会社はてな SRE 古川 雅大氏

資料

speakerdeck.com

SREのこれまでとこれから
  • これまでSREはGoogleの一プロセスからWebサービス事業者のプラクティスへ
  • 「企業のプラクティス」から「研究分野」へ
  • これからは?
    • 企業や組織ごとに合ったSREの実践、実装の登場
    • セキュリティ分野など他の分野との連携
      • 組織やコミュニケーション、文化の話は不可欠
      • 「SREとは」を再整理する必要がある
SREとは???
  • ソフトウェアエンジニアに運用チームの設計を依頼した時に出来上がるもの

    • 意思決定?
    • ソフトウェアエンジニアリングによる自動化?
    • システムのモニタリング?
    • DevOpsの実装?
  • SREの内容をはっきりとは表現できていない

  • SREという言葉が意味する役割と意味をもっとうまく定義する必要がある
SREを紐解く
  • システムの信頼性に焦点を当てる。信頼性に関わることならYes.
  • 信頼性こそプロダクトの基本
  • 誰も使えないシステムは有益なものではない

    • 信頼性とは
      • システムが求められる機能を、定められた条件のもとで、定められた機関にわたり障害なく運用できること
    • システムとは?

      • Webサービスには「人のシステム」(運用チーム、開発チーム、会社全体など)と「機械のシステム」(サーバ、ネットワークなど)がある
      • この2つのシステムを考慮する必要がある
    • 定められた条件(ビジネス的条件)とは?

      • 限られたコスト(人、金、時間)
      • 売り上げの増加(魅力的な新機能の開発)
      • 市場の変化への対応(スケーリング)
  • 発表者の考えるSREとは

    • 信頼性のあるWebサービスを提供するために、条件を考慮したシステムを設計、実装、運用の課題を解決すること
SREの文化
  • どういった考え方、文化を持っていれば現在のSREを生み出せるか?

    • 文化を習得すれば応用し新たなプラクティスを生み出せる。
  • 人と機械のシステム

    • Webシステムは開発運用する人の組織や利用するユーザ、機能を提供するアプリケーションやインフラなどのシステムから成り立っている
    • 開発チームと運用チームでの信頼関係、ユーザとの信頼関係を築く必要がある
      • 目標、意思決定の基準、考え方を共有すること
    • インフラやアプリケーションの信頼性は、技術で殴る!
  • 信頼性にフォーカスする

    • 判断基準を「信頼性」にし、信頼性に関して興味を持つこと
      • インシデント対応
      • 「変化」など信頼性が落ちる事項への対応、
      • 人の心理やチーム間との信頼関係
      • 他分野の信頼性に関する知見(信頼性工学、安全工学、心理学、組織論など)
  • 完全(信頼性100%)を目指さない

    • オペレーションですべてをなくせない
    • 1回のチャレンジで完全を目指さない
    • 1人で出来る必要はない
  • 信頼性とのトレードオフを理解する

  • エンジニアリング

SREと組織
  • どうやって導入するか?

    • 組織もシステム。組織にSREという大きな機能を実装すると考える
    • システムに編子を加えると信頼性が下がることを注意し、段階的に入れていく
      • 変更料と信頼性(少しずつ導入)
  • 組織が変更容易な組織か?

    • 組織の規模
    • 組織のマネジメント
    • 組織に対する変更手順が整備されているか?(リリース手順)
    • カナリアリリース(一部部署で試せるか)
    • 組織が挑戦可能で批判的でない文化か?
  • 誰に説明するか?

    • 条件を考慮したシステムを設計、実装、運用の課題を解決
      • 条件を決定できる人へSREを説明する必要がある
      • システムに関係する人に説明する必要がある
        • SREのすべてを説明するのは難しい
        • ビジネスにとってSREは便利なツールであることを示す
  • どうやってSLI/SLOを導入するか?

    • どこかのチームに導入するための準備をする
    • サービス開発と同じように構成図やデザインドキュメントを書く
    • サイクルを回すことが重要
  • その他

    • CTOなど決定権を持つ人と共同で進める
    • チーム横断的組織で進める
      • ラクティスの共有 など
  • まとめ

    • これからはより組織に合ったSREを実践、応用する必要がある
    • ラクティスをまねるだけでなく、思想、哲学、文化を理解することが大事

LT1「Incident Response」 tjun氏

資料

speakerdeck.com

  • インシデントとは

    • 予期せず提供しているサービスが提供できない状態になったり、期待している機能が提供できないこと
  • インシデントレスポンスとは

    • インシデントを解決するための組織的な仕組み
  • インシデント前にやること

    • インシデントは必ず起きる
    • 役割を決める
    • トリガーを用意する
  • インシデント中にやること

    • 慌てない
    • 必要なメンバーを招集する
    • 役割ごとに必要な対応を行う
  • インシデント後にやること

    • 人を責めない
    • ふりかえりを行う
  • インシデントレスポンスを始めよう

    • ①インシデントを定義する
    • ②コミュニケーションの仕組みを作る
    • ③インシデント対応の役割を決める
    • ④ふりかえりのテンプレを作る
    • ⑤練習する
  • まとめ

    • インシデントレスポンスはSREだけのものではない
    • 組織全体で対応することが重要

LT2「AIスタートアップにおけるSRE」大川 遥平氏

  • 各種Webサービス開発・保守

    • コーポレートサイト
    • LPの運用
  • AIの実行環境の開発・保守

    • 推論用サーバ
  • LPの運用方法

  • AI推論サーバの運用方法

    • fargateで運用し、その他AWSサービスとはVPCリンクを通じてやり取り
    • ソフトウェアに詳しくない人でもデプロイできるような仕組みを
  • まとめ

    • AIスタートアップではWebサービスがたくさんある
    • 商品やキャンペーンでは細かくたくさんある
    • AI推論のAPIサーバでは細かいチューニングが必要

LT3「Production Readyと開発プロセス改善」ぐりもお。氏

資料

speakerdeck.com

  • Production Readyとは?

    • サービスを本番トラフィックを任せられるほどの信頼がある状態
    • 本番環境にリリースできる状態ということではない
  • 一般的なProduction Readyのプラクティス

    • Production Readiness Review
    • Production Readiness Checklist
    • Production Readiness Roadmap
    • SRE Onboarding/Takeover
  • Production Ready対応(以前)

    • レビュー不十分
    • ロードマップ行えていない
    • オンボーディングも行えていない
  • 早期エンゲージメントモデル

    • Production Ready活動の導入モデルのひとつで、早い段階から開発のライフサイクルに関わること
  • OPTiM Cloud IoT OSにおける早期エンゲージメントモデル

    • 企画から運用までのプロセスを対象としている
  • プロダクションレディ対応(現在)

    • ロードマップ以外は対応できるようになった
    • サービスのドキュメントを整備
      • フォーマットをそろえ、項目の抜け漏れをなくす
  • まとめ

    • Production Readyで項目漏れや手戻りのないレビューが可能になった
    • Production Readyのアプローチはサービス/チームによって違う

全体の感想

SREという言葉は知っていましたが勉強不足でした。予習してから臨んだ方がより理解できたと思います。信頼性向上はソフトウェアやWebシステムに限った話ではないため、SREの考え方は何にでも応用できるのでは?と思いました。「SRE難しそう」と思っていて手を付けずにいましたが、これを機に勉強してみようと思いました!

以上です。最後まで読んでいただきありがとうございました!

JAWS-UG CLI専門支部 #156R EC2基礎(VPC) 参加レポート

6/8(月)、JAWS-UG CLI専門支部 #156R EC2基礎(VPC)に参加しました。今回もハンズオンの感想と学んだコマンドについて書こうと思います。

目次

イベントページ

jawsug-cli.connpass.com

ハンズオンでやったこと

以下の通りです。事前準備として、Cloud9上にハンズオン環境を構築しました。 ハンズオンでは、Cloud9のターミナルでコマンド実行しました。

  • VPC管理
  • ルーティング情報の管理
  • セキュリティグループの管理
  • サブネット管理
  • インターネットゲートウェイの管理

VPC(Virtual Private Cloud)とは

  • EC2インスタンスを配置するための仮想ネットワーク
  • VPCはリージョン単位のサービス
    • 仮想データセンタというイメージ
  • 1リージョンあたり5VPCまで作成可能
  • 他の仮想ネットワークと完全に分離されている。そのため、VPC単体で使う分にはIPアドレスが重複しても問題ない。
    • VPCどうしを接続したり、様々なネットワークと接続するケースが増えているので、その場合はアドレッシングを検討する必要はある。
  • サブネットはAZ単位のサービス

    • サブネットは一つのデータセンタというイメージ
    • インスタンスはサブネット内に構築
    • 一般的には、パブリックサブネットとプライベートサブネットで分ける。
    • インスタンスごとのグルーピング(Webサーバ、DBサーバ等)でサブネットを分けるのがよい。
    • 東京リージョンはAZが3つなので、3サブネット作成可能
  • インターネットゲートウェイはインターネットの出入口

    • サイジングや冗長化は不要(AWS側で冗長対応しているため、設定そのものがない)
  • ルートテーブル

    • サブネットのルーティングテーブル情報
    • 1つのサブネットはルートテーブルを1つだけ関連付けることができる。
    • マスタルートテーブルを使わずに、ルールごとにルートテーブルを作るのが一般的
  • セキュリティグループ

    • EC2インスタンスのステートフルアクセス制御
    • インスタンスに紐づけてアクセス制御(厳密にはENIに紐づいている)
    • 外部通信はCIDR指定、VPC内部はグループ指定が基本

感想

コマンドを駆使してネットワーク構築をする感覚で面白かったです。VPCやEC2の構築をCLIで実施するケースは少ないかもしれませんが、どのような設定を入れて何がマネジメントコンソール裏で動いているのか確認できて良い経験になりました。

ハンズオンでやったこと

今回はボリュームが多いため、主要コマンドのみ触れていこうと思います。ハンズオン手順は、こちらを参照してください。

事前作業
1.VPCの構築
  • VPCを作成するためにはcreate-vpcコマンドを使います。
    • --cidr-blockでCIDRを指定します。
aws ec2 create-vpc --cidr-block ${EC2_VPC_CIDR} \
  • ec2 create-tagsコマンドを使ってVPCタグを作ります。
    • --resourcesVPC_IDを指定します。
    • --tagsでタグキーに入れるタグ値を指定します。
aws ec2 create-tags \
  --resources ${EC2_RESOURCE_ID} \
  --tags "Key=${EC2_TAG_KEY},Value=${EC2_TAG_VALUE}"
  • 作成したVPCの存在確認をするために、describe-vpcsコマンドを実行します。
    • --filtersでタグキーとタグ値を指定します。
    • --queryVPCのタグ値を抜き出し、--output textでテキスト表示します。
aws ec2 describe-vpcs \
  --filters Name=tag:Name,Values=${EC2_VPC_TAG_NAME}  \
  --query 'Vpcs[].Tags[?Key == `Name`].Value' \
  --output text
2.インターネットゲートウェイ(IGW)の作成
  • create-internet-gatewayコマンドでインターネットゲートウェイを作成します。
aws ec2 create-internet-gateway \
  • create-tagsコマンドでインターネットゲートウェイにタグ付けをします。
    • --resourcesでインターネットゲートウェイのIDを指定します。
    • --tagsでタグキーとタグ値を指定します。
aws ec2 create-tags \
  --resources ${EC2_RESOURCE_ID} \
  --tags "Key=${EC2_TAG_KEY},Value=${EC2_TAG_VALUE}"
  • describe-internet-gatewaysコマンドでIGWの存在確認をします。
    • --filterでタグキーとタグ値を指定します。
    • Tagの値を取得し、テキストで表示します。
aws ec2 describe-internet-gateways \
  --filters Name=tag:Name,Values=${EC2_IGW_TAG_NAME}  \
  --query "InternetGateways[].Tags[].Value" \
  --output text
3.IGWのアタッチ
  • VPC_IDを取得し、変数[EC2_VPC_ID]に指定します。
    • describe-vpcsコマンドでVPC情報を取得し、VpcIdの値をテキスト出力します。
EC2_VPC_ID=$( \
  aws ec2 describe-vpcs \
    --filters Name=tag:Name,Values=${EC2_VPC_TAG_NAME}  \
    --query 'Vpcs[].VpcId' \
    --output text \
) 
  • IGW_IDを取得します。
    • descrive-internet-gatewaysコマンドでIGW情報を取得し、InternetGatewayIdの値をテキスト表示します。
EC2_IGW_ID=$( \
  aws ec2 describe-internet-gateways \
    --filters Name=tag:Name,Values=${EC2_IGW_TAG_NAME} \
    --query "InternetGateways[].InternetGatewayId" \
    --output text \
) 
  • IGWをVPCにアタッチします。
    • attach-internet-gatewayコマンドを使って、IGWをVPCにアタッチします。
      • --internet-gateway-idでアタッチするIGWを指定します。
      • --vpc-idでIGWをアタッチするVPCを指定します。
aws ec2 attach-internet-gateway \
  --internet-gateway-id ${EC2_IGW_ID} \
  --vpc-id ${EC2_VPC_ID}
  • VPCにIGWがアタッチされていることを確認します。
aws ec2 describe-internet-gateways \
  --filters Name=tag:Name,Values=${EC2_IGW_TAG_NAME}  \
  --query "InternetGateways[].Attachments[?VpcId == \`${EC2_VPC_ID}\`].VpcId" \
  --output text
4. ルートテーブルの作成
  • create-route-tableコマンドでルートテーブルを作成します。
    • --vpc-idでルートテーブルを作成するVPCを指定します。
aws ec2 create-route-table --vpc-id ${EC2_VPC_ID} 
  • 作成したルートテーブルにタグ付けをします。
    • --resourcesでタグ付けするルートテーブルを指定します。
    • --tagsでタグキーとその値を指定します。
aws ec2 create-tags --resources ${EC2_RESOURCE_ID} \
  --tags "Key=${EC2_TAG_KEY},Value=${EC2_TAG_VALUE}"
  • describe-route-tablesコマンドでルートテーブルがVPC内に存在することを確認します。
aws ec2 describe-route-tables --filters Name=vpc-id,Values=${EC2_VPC_ID} \
            Name=tag:Name,Values=${EC2_ROUTE_TABLE_TAG_NAME}  \
  --query "RouteTables[].Tags[?Key == \`Name\`].Value" \
  --output text
5. ルートの作成
  • create-routeコマンドでルートテーブルにルートを作成します。
    • --route-table-idでルートを作成するルートテーブルを指定します。
    • --destination-cidr-block送信先CIDRを指定します。
    • --gateway-idでターゲットのIGWを指定します。
aws ec2 create-route \
  --route-table-id ${EC2_ROUTE_TABLE_ID} \
  --destination-cidr-block ${EC2_ROUTE_DEST_CIDR} \
  --gateway-id ${EC2_IGW_ID}
  • describe-route-tablesコマンドを使って、ルートテーブルに指定したルートが存在することを確認します。
    • --filterVPCとタグキー及びルートテーブルのタグ値を指定します。
    • 宛先CIDRが${EC2_ROUTE_DEST_CIDR}(ハンズオンでは、0.0.0.0/0)のルートがあるルートテーブルをテキストで出力します。
aws ec2 describe-route-tables \
  --filters Name=vpc-id,Values=${EC2_VPC_ID} \
            Name=tag:Name,Values=${EC2_ROUTE_TABLE_TAG_NAME}  \
  --query "RouteTables[].Routes[?DestinationCidrBlock == \`${EC2_ROUTE_DEST_CIDR}\`].DestinationCidrBlock" \
  --output text
  • 送信先へのルートが指定のIGWに設定されていることを確認します。
aws ec2 describe-route-tables \
  --filters Name=vpc-id,Values=${EC2_VPC_ID} \
            Name=tag:Name,Values=${EC2_ROUTE_TABLE_TAG_NAME}  \
  --query "RouteTables[].Routes[?DestinationCidrBlock == \`${EC2_ROUTE_DEST_CIDR}\`].GatewayId" \
  --output text
6. サブネットの作成
  • create-subnetコマンドでサブネットを作成します。
    • --vpc-idでサブネットを作成するVPCを指定します。
    • --cidr-blockでサブネットのアドレスレンジを指定します。
    • --availability-zoneでサブネットを作成するAZを指定します。
aws ec2 create-subnet \
  --vpc-id ${EC2_VPC_ID} \
  --cidr-block ${EC2_SUBNET_CIDR} \
  --availability-zone ${EC2_AZ_NAME} 
  • サブネットのタグを作成するためにcreate-tagsコマンドを使います。
    • resources でEC2のリソースが必要だし、
aws ec2 create-tags \
  --resources ${EC2_RESOURCE_ID} \
  --tags "Key=${EC2_TAG_KEY},Value=${EC2_TAG_VALUE}"
VPCに指定のサブネットが存在することを確認します。
  • describe-subnetsコマンドでサブネット情報を取得します。
    • --filterVPCとタグキーとタグ値を指定します。
aws ec2 describe-subnets \
  --filters Name=vpc-id,Values=${EC2_VPC_ID} \
            Name=tag:Name,Values=${EC2_SUBNET_TAG_NAME}  \
  --query 'Subnets[].Tags[?Key == `Name`].Value' \
  --output text
7. ルートテーブルとサブネットの関連付け
  • associate-route-tableコマンドを使ってルートテーブルとサブネットの関連付けをします。
    • --subnet-idで関連付けするサブネットを指定します。
    • --route-table-idで関連付けするルートテーブルを指定します。
aws ec2 associate-route-table \
  --subnet-id ${EC2_SUBNET_ID} \
  --route-table-id ${EC2_ROUTE_TABLE_ID}
  • 指定のサブネットとルートテーブルが関連付いていることを確認します。
aws ec2 describe-route-tables \
  --route-table-ids ${ARRAY_EC2_ROUTE_TABLE_IDS} \
  --query "RouteTables[].Associations[?SubnetId == \`${EC2_SUBNET_ID}\`].RouteTableAssociationId" \
  --output text
8. サブネット属性の有効化
  • modify-subnet-attributeコマンドでサブネット属性の設定変更をします。
    • --subnet--idで設定変更するサブネットを指定します。
    • --map-public-ip-on-launchで「パブリック IPv4 アドレスの自動割り当て」を有効にします。
aws ec2 modify-subnet-attribute \
  --subnet-id ${EC2_SUBNET_ID} \
  --map-public-ip-on-launch
  • サブネットのmap-public-ip-on-launch属性(パブリック IPv4 アドレスの自動割り当て)が有効(True)になっていることを確認します。
    • describe-subnetsコマンドを使います。
      • --filterでタグキーと値を指定します。
      • パブリック IPv4 アドレスの自動割り当てのステータスを取り出します。
EC2_SUBNET_ATTRIBUTE_MAP_PUBLIC_IP_ON_LAUNCH=$( \
  aws ec2 describe-subnets \
    --filters Name=tag:Name,Values=${EC2_SUBNET_TAG_NAME} \
    --query 'Subnets[].MapPublicIpOnLaunch' \
    --output text \
) \
  && echo ${EC2_SUBNET_ATTRIBUTE_MAP_PUBLIC_IP_ON_LAUNCH}
9. セキュリティグループの作成
  • create-security-groupコマンドでセキュリティグループを作成します。
    • --group-nameでセキュリティグループ名を指定します。
    • --descriptionでセキュリティグループの説明を指定します。
    • --vpc-idでセキュリティグループを作成するVPCを指定します。
aws ec2 create-security-group \
  --group-name ${EC2_SECURITY_GROUP_NAME} \
  --description "${EC2_SECURITY_GROUP_DESC}" \
  --vpc-id ${EC2_VPC_ID}
  • describe-security-groupsコマンドで指定のVPCに指定のセキュリティグループ名のグループがある場合は、テキスト表示します。
    • --filterVPC_IDとセキュリティグループ名を指定します。
aws ec2 describe-security-groups \
  --filter Name=vpc-id,Values=${EC2_VPC_ID} \
    Name=group-name,Values=${EC2_SECURITY_GROUP_NAME} \
  --query 'SecurityGroups[].GroupName' \
  --output text
10. セキュリティグループのIngressルール追加(TCP80の許可を追加)
  • authorize-security-groups-ingressコマンドでルールを作成します。
    • --group-idでルールを追加するセキュリティグループIDを指定します。
    • --protocolでルールに追加するプロトコルTCPUDP)を指定します。
    • --portでルールに追加するポート番号(80など)を指定します。
    • --cidrでルールに追加するIPアドレス(CIDR)を指定します。
aws ec2 authorize-security-group-ingress \
  --group-id ${EC2_SECURITY_GROUP_ID} \
  --protocol ${EC2_SECURITY_GROUP_PROTOCOL} \
  --port ${EC2_SECURITY_GROUP_PORT} \
  --cidr ${EC2_SECURITY_GROUP_CIDR}
  • 指定のVPCのセキュリティグループに、許可するプロトコルとポート番号の通信が作成されていることを確認します。
aws ec2 describe-security-groups \
  --filter Name=vpc-id,Values=${EC2_VPC_ID} \
    Name=group-name,Values=${EC2_SECURITY_GROUP_NAME} \
    Name=ip-permission.protocol,Values=${EC2_SECURITY_GROUP_PROTOCOL} \
    Name=ip-permission.to-port,Values=${EC2_SECURITY_GROUP_PORT} \
    Name=ip-permission.cidr,Values=${EC2_SECURITY_GROUP_CIDR} \
  --query "SecurityGroups[].IpPermissions[?IpProtocol == \`${EC2_SECURITY_GROUP_PROTOCOL}\` \
    && ToPort == \`${EC2_SECURITY_GROUP_PORT}\` \
    && IpRanges[?CidrIp == \`${EC2_SECURITY_GROUP_CIDR}\`]].IpRanges[][].CidrIp" \
  --output text
11.ユーザデータの作成

-ファイルのフルパスを変数[FILE_USER_DATA]に格納します。 - ${DIR_USER_DATA}にはユーザデータのディレクトリを事前に格納します。 - ${USER_DATA_NAME}にはユーザデータ名を事前に格納します。

FILE_USER_DATA="${DIR_USER_DATA}/${USER_DATA_NAME}.bash" 
cat << EOF0 > ${FILE_USER_DATA}
#!/bin/bash
yum -y update

EC2_METADATA_SECOND='600'

EC2_METADATA_TOKEN=\$( \\
  curl -s \\
    -X PUT "http://169.254.169.254/latest/api/token" \\
    -H "X-aws-ec2-metadata-token-ttl-seconds: \${EC2_METADATA_SECOND}" \\
)

EC2_METADATA_HEADER="X-aws-ec2-metadata-token: \${EC2_METADATA_TOKEN}"

EC2_AZ_NAME=\$( \\
  curl -s -H "\${EC2_METADATA_HEADER}" \\
    http://169.254.169.254/latest/meta-data/placement/availability-zone \\
)

EC2_INSTANCE_ID=\$( \\
  curl -s -H "\${EC2_METADATA_HEADER}" \\
    http://169.254.169.254/latest/meta-data/instance-id \\
) 

# setup httpd
yum install -y httpd
systemctl start httpd.service
systemctl enable httpd.service

# setup contents
cat << EOF > /var/www/html/index.html
<!DOCTYPE html>
<title>AZ: \${EC2_AZ_NAME}</title>
<h1>AZ: \${EC2_AZ_NAME}</h1>
<p>ID: \${EC2_INSTANCE_ID}</p>
EOF

EOF0

cat ${FILE_USER_DATA}
12. EC2インスタンスの起動
  • run-instancesコマンドでEC2インスタンスを実行します。
    • --image-idでAMI(Amazon Linux2)を指定します。
    • --instance-typeインスタンスタイプ(ハンズオンではt2.micro)を指定します。
    • --security-group-idsでセキュリティグループを指定します。
    • --tag-specificationsでタグの文字列を指定します。
    • --subnet-idインスタンス作成先サブネットを指定します。
    • --user-dataでユーザデータファイルを指定します。
aws ec2 run-instances \
  --image-id ${EC2_IMAGE_ID} \
  --instance-type ${EC2_INSTANCE_TYPE} \
  --security-group-ids ${ARRAY_EC2_SECURITY_GROUP_IDS} \
  --tag-specifications ${STRING_TAG_CONF} \
  --subnet-id ${EC2_SUBNET_ID} \
  --user-data file://${FILE_USER_DATA}
aws ec2 describe-instances \
  --filters Name=tag-key,Values=Name \
            Name=tag-value,Values=${EC2_INSTANCE_TAG_NAME} \
            Name=instance-state-name,Values=running \
  --query Reservations[].Instances[].Tags[].Value \
  --output text
13.EC2インスタンスへのCLIブラウザアクセス
curl ${CURL_TARGET_URL}
  • EC2インスタンスのコンテンツにアクセスし、ステータスコード200が返ってくることを確認します。
    • curlコマンドのオプションは以下の通りです。
      • -L(--location)ステータスコード3xxが返された場合に自動でリダイレクトする。
      • -l(--list-only):LISTコマンドの代わりにNLISTコマンドを使用する。
      • -s(--silent):プログレスメーターを非表示にする。
      • -S(--show-error)プログレスメーターのエラー情報を非表示にせず表示する。
      • -o(--output):ファイルに出力する。
      • -w:出力フォーマットを指定する。以下のコマンドではHTTPのステータスコードを出力する。
curl -LI -Ss -o /dev/null -w '%{http_code}\n' ${CURL_TARGET_URL}
14.EC2インスタンスの終了
aws ec2 terminate-instances \
  --instance-ids ${ARRAY_EC2_INSTANCE_IDS}
  • describe-instancesコマンドで、ステータスが"running"のEC2インスタンスが存在しないことを確認します。
aws ec2 describe-instances \
  --filters Name=tag-key,Values=Name \
            Name=tag-value,Values=${EC2_INSTANCE_TAG_NAME} \
            Name=instance-state-name,Values=running \
  --query Reservations[].Instances[].Tags[].Value \
  --output text
後始末

ハンズオン環境が不要になったら、ハンズオン手順の後始末1と2、Cloud9用ロールからのポリシーのデタッチを実施します。

  • セキュリティグループのIngressルール削除
  • セキュリティグループの削除
  • ルートテーブルの更新
  • サブネットの削除
  • ルートテーブルの削除
  • IGWのデタッチ
  • IGWの削除
  • VPCの破棄
  • ハンズオン用ディレクトリの削除
  • Cloud9用ロールからのポリシーのデタッチ

最後に

次回はEBS、その後はAMI、IAMに関するハンズオンが続きます。楽しみながらハンズオンと復習をしていこうと思います。

最後まで読んでいただきありがとうございました。

JAWS-UG CLI専門支部 #153R SNS入門 復習

5/19(火)JAWS-UG CLI専門支部 #153R SNS入門 に参加しました。 こちらもブログの執筆をしていなかったため、復習しながらブログを書きます。

目次

イベントページ

jawsug-cli.connpass.com

ハンズオンでやったこと

以下の通りです。事前準備として、Cloud9上にハンズオン環境を構築しました。 ハンズオンでは、Cloud9のターミナルでコマンド実行します。

  • SNSトピックの構築
  • SNSトピックの購読
  • SNSトピックへの配信

Amazon Simple Notification Service (SNS) とは

マイクロサービス、分散型システム、およびサーバーレスアプリケーションの分離を可能にする、高可用性で、耐久性に優れたセキュアな完全マネージド型 pub/sub メッセージングサービスです(公式より引用)。

SNSのポイントは以下の通りです。誤りなどありましたら、ご指摘いただけると幸いです。

  • AWSの様々なサービスと連携して疎結合サービスを実現できる。
    • Cloudwatch(Billing アラートの通知、メトリクスの閾値超過アラートの通知など)
    • S3(ファイルがアップロードされたときの通知など)
    • など
  • 様々なプロトコルで通知することができる。
    • email
    • SQS
    • HTTP/HTTPS
    • Lambda
    • SMS(モバイル通信)
  • メッセージ通信順番は保証されない。
  • メッセージサイズは最大256KB(SQSと同じ)
  • 一度メッセージを発行したら、メッセージを保持しない。
    • SQSはメッセージを取得しても即時削除されない。メッセージ保持期間(60秒~14日間)を定義する必要がある。
  • SNSはプッシュ型通信。SQSはポーリング型通信。

ハンズオン

事前作業

以下の2つの事前作業を行います。

1.SNSトピックの構築
環境変数に東京リージョンを指定します。
  • 環境変数を設定するときはexportコマンドを使います。
export AWS_DEFAULT_REGION='ap-northeast-1'
②変数[SNS_TOPIC_NAME]にSSNSトピック名を指定します。
SNS_TOPIC_NAME='handson-cli-sns-topic'
③変数に正しいパラメータが格納されているか確認します。
cat << END

  # 0. AWS_DEFAULT_REGION:"ap-northeast-1"
       AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION}"

  # 1. SNS_TOPIC_NAME:"handson-cli-sns-topic"
       SNS_TOPIC_NAME="${SNS_TOPIC_NAME}"

END
SNSトピックを作成します。
  • SNSトピックを作る場合は、sns create-topicコマンドを使います。
  • `--name <トピック名>' でトピック名を指定します。
aws sns create-topic --name ${SNS_TOPIC_NAME}
SNSトピック"handson-cli-sns-topic"が存在することを確認します。
  • SNSトピックの存在確認には、sns list-topicsコマンドを使います。
aws sns list-topics --query "Topics[?contains(TopicArn, \`${SNS_TOPIC_NAME}\`)].TopicArn" \
--output text
2.SNSトピックの購読
環境変数に東京リージョンを指定します。
export AWS_DEFAULT_REGION='ap-northeast-1'
②変数[SNS_TOPIC_NAME]にSNSトピック名を指定します。
SNS_TOPIC_NAME='handson-cli-sns-topic'
③変数[SNS_SUBSCRIPTION_PROTOCOL]にSNS通知プロトコル名を指定します。
SNS_SUBSCRIPTION_PROTOCOL='email'
  • 今回はメール送信のため、emailと書きます。他にもsmslambdasqshttphttpsを指定することができます。
④通知先エンドポイントを指定します。
  • 事前準備で指定したtmpファイルを指定します。
    • tmpファイルに書かれているメールアドレスを読み取るためです。
DIR_TMP="${HOME}/environment/tmp-handson-cli-sns"
FILE_TMP="${DIR_TMP}/mail_address.tmp" \
  && echo ${FILE_TMP}
  • 一時ファイルをsourceコマンドで読み込みます。
    • sourceコマンドは、ファイルに書かれているコマンドを、開いたシェルで実行するためのコマンドです。
source ${FILE_TMP}
  • 変数[SNS_SUBSCRIPTION_ENDPOINT]に通知先エンドポイントを指定します。
SNS_SUBSCRIPTION_ENDPOINT="${MAIL_ADDRESS}" \
  && echo ${SNS_SUBSCRIPTION_ENDPOINT}
⑤正しいパラメータ値が格納されていることを確認します。
cat << END

  # 0. AWS_DEFAULT_REGION:"ap-northeast-1"
       AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION}"
  # 1. SNS_TOPIC_NAME:"handson-cli-sns-topic"
       SNS_TOPIC_NAME="${SNS_TOPIC_NAME}"
  # 2. SNS_SUBSCRIPTION_PROTOCOL:"email"
      SNS_SUBSCRIPTION_PROTOCOL="${SNS_SUBSCRIPTION_PROTOCOL}"
  # 3. SNS_SUBSCRIPTION_ENDPOINT:"<通知先メールアドレス>"
       SNS_SUBSCRIPTION_ENDPOINT="${SNS_SUBSCRIPTION_ENDPOINT}"

END
⑥トピックARNを取得します。
SNS_TOPIC_ARN=$( \
  aws sns list-topics \
    --query "Topics[?contains(TopicArn, \`${SNS_TOPIC_NAME}\`)].TopicArn" \
    --output text \
) \
  && echo ${SNS_TOPIC_ARN}
SNSトピックを購読(サブスクリプションを作成)します。
  • SNSトピックにサブスクリプションを作成するためには、sns subscribeコマンドを使います。
  • --topic-arnでトピックのarnを指定します。
  • --protocolでサブスクライブするエンドポイントのタイプ を指定します。
  • --notification-endpointで、サブスクライブ先を指定します。
aws sns subscribe --topic-arn ${SNS_TOPIC_ARN} \
  --protocol ${SNS_SUBSCRIPTION_PROTOCOL} \
  --notification-endpoint ${SNS_SUBSCRIPTION_ENDPOINT}
  • コマンド実行後、以下のように表示されます。
{
    "SubscriptionArn": "pending confirmation"
}
  • 登録したメールアドレスに"AWS Notification - Subscription Confirmation"という標題のメールが届きます。
  • "Confirm subscription"リンクをクリックして承認します。
サブスクリプションが存在することを確認します。
  • sns list-subscriptions-by-topic コマンドを使って、エンドポイントの存在確認とサブスクリプションARNが存在確認をします。

  • 通知先の存在確認をします。

    • --topic-arnでトピックARNを指定します。
aws sns list-subscriptions-by-topic --topic-arn ${SNS_TOPIC_ARN} \
  --query "Subscriptions[?Endpoint == \`${SNS_SUBSCRIPTION_ENDPOINT}\`].Endpoint" \
  --output text
aws sns list-subscriptions-by-topic --topic-arn ${SNS_TOPIC_ARN} \
  --query "Subscriptions[?Endpoint == \`${SNS_SUBSCRIPTION_ENDPOINT}\`].SubscriptionArn" \
  --output text
3.SNSトピックへのメッセージの配信
環境変数に東京リージョンを指定します。
export AWS_DEFAULT_REGION='ap-northeast-1'
②変数[SNS_TOPIC_NAME]にSNSトピック名を指定します。
SNS_TOPIC_NAME='handson-cli-sns-topic'
③変数[SNS_MESSAGE_BODY]にメッセージ本文を指定します。
SNS_MESSAGE_BODY='Hello World!'
④変数[SNS_MESSAGE_SUBJECT]にメールタイトルを指定します。
SNS_MESSAGE_SUBJECT='Message handson-cli-sns'
⑤通知先エンドポイントを指定します。
  • 事前準備で指定したtmpファイルを指定します
DIR_TMP="${HOME}/environment/tmp-handson-cli-sns"
FILE_TMP="${DIR_TMP}/mail_address.tmp" \
  && echo ${FILE_TMP}
  • 一時ファイルをsourceコマンドで読み込みます。
source ${FILE_TMP}
  • 通知先エンドポイントを指定します。
SNS_SUBSCRIPTION_ENDPOINT="${MAIL_ADDRESS}" \
  && echo ${SNS_SUBSCRIPTION_ENDPOINT}
⑥変数に正しいパラメータ値が格納されていることを確認します。
cat << END

  # 0. AWS_DEFAULT_REGION:"ap-northeast-1"
       AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION}"
  # 1. SNS_TOPIC_NAME:"handson-cli-sns-topic"
       SNS_TOPIC_NAME="${SNS_TOPIC_NAME}"
  # 2. SNS_MESSAGE_BODY:"Hello World!"
       SNS_MESSAGE_BODY="${SNS_MESSAGE_BODY}"
  # 3. SNS_MESSAGE_SUBJECT:"Message handson-cli-sns"
       SNS_MESSAGE_SUBJECT="${SNS_MESSAGE_SUBJECT}"
  # 4. SNS_SUBSCRIPTION_ENDPOINT:"<通知先メールアドレス>"
       SNS_SUBSCRIPTION_ENDPOINT="${SNS_SUBSCRIPTION_ENDPOINT}"

END
⑦トピックARNを取得します。
SNS_TOPIC_ARN=$( \
  aws sns list-topics \
    --query "Topics[?contains(TopicArn, \`${SNS_TOPIC_NAME}\`)].TopicArn" \
    --output text \
) \
  && echo ${SNS_TOPIC_ARN}
SNSトピックにメールメッセージを配信します。
  • publistコマンドを使ってメッセージを配信します。
    • --topic-arnでトピックのARNを指定します。
    • --messageでメッセージ本文を指定します。
    • --subjectでメールタイトルを指定します。
aws sns publish \
  --topic-arn ${SNS_TOPIC_ARN} \
  --message "${SNS_MESSAGE_BODY}" \
  --subject "${SNS_MESSAGE_SUBJECT}"
  • コマンド実行後、エンドポイントにメール送信されます。
  • メールを受信していることを確認します。
4.後片付け

ハンズオン環境が不要な場合は、以下の作業を実施します。

最後に

明日6/8(月)のEC2基礎(VPC)を前に、これまでの復習が完了して良かったです!コマンドの復習だけでなく、サービスの概要も復習することができました。SAAやプラクティショナーを受験する前に受けておきたかった内容でした。プラクティショナー受験前からCLI専門支部の活動は知っていたのですが…もっと早く参加するべきでした…(涙)

最後まで読んでいただき、ありがとうございました!

JAWS-UG CLI専門支部 #152R SQS入門 ハンズオン復習

もう1か月前になりますが、5/7(木)JAWS-UG CLI専門支部 #152R SQS入門 に参加しました。 ブログの執筆をしておらず、ハンズオンもついていくのがやっとでした。 今日改めて復習しながらブログを書きます。

目次

イベントページ

jawsug-cli.connpass.com

ハンズオンでやったこと

以下の通りです。事前準備として、Cloud9上にハンズオン環境を構築しました。 ハンズオンでは、Cloud9のターミナルでコマンド実行します。

  • SQSキューの構築
  • VisibilityTimeoutの更新
  • SQSキューへのメッセージ送信
  • SQSキューからのメッセージ受信

Amazon Simple Queue Service (SQS)とは

  • 完全マネージド型のメッセージキューイングサービスである。
  • AWS SDK でサポートされている任意のプログラミング言語からアクセスできる。

■ 標準キューとFIFOキューについて

  • 標準キュー
    • 配信順序が保証されていないため、取得のタイミングによっては同一メッセージが2回配信されることもある。
  • FIFOキュー
    • 配信順序が保証されている。そのため、処理速度は標準キューよりは劣る。

■ショートポーリングとロングポーリングがある。

  • ショートポーリング(デフォルト)
    • リクエストを受けたら、メッセージの有無にかかわらず即レスポンスを返す。
  • ロングポーリング
    • リクエストを受けてもメッセージがなければ、設定されたタイムアウト値になるまでレスポンスを返さない。

■ VisibilityTimeout(可視性タイムアウト)とは?

  • あるクライアントがメッセージを受信中に、他のクライアントがメッセージを受信することを防ぐために設定するタイムアウト値。
    • メッセージを受信しただけではSQSから削除されないため、このような仕組みが必要。
    • デフォルト30秒。最大12時間まで設定可能。

ハンズオン手順

1.SQSキューの構築
環境変数に東京リージョンを指定します。
  • 環境変数を設定するときはexportコマンドを使います。
export AWS_DEFAULT_REGION='ap-northeast-1'
②変数[SQS_QUEUE_NAME]にSQSキュー名を指定します。
SQS_QUEUE_NAME="handson-cli-sqs-queue"
③変数に正しいパラメータが格納されているか確認します。
cat << END

  # 0. AWS_DEFAULT_REGION:"ap-northeast-1"
       AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION}"

  # 1. SQS_QUEUE_NAME:"handson-cli-sqs-queue"
       SQS_QUEUE_NAME="${SQS_QUEUE_NAME}"

END
④SQSキューを作成します。
  • SQSキューを作る場合は、sqs create-queueコマンドを使います。
  • `--queue-name <キュー名>' でキュー名を指定します。
aws sqs create-queue --queue-name ${SQS_QUEUE_NAME}
⑤SQSキューが存在することを確認します。
  • SQSキューの存在確認には、sqs list-queuesコマンドを使います。
  • --queue-name-prefix <キュー名> でキュー名を指定します。
aws sqs list-queues --queue-name-prefix ${SQS_QUEUE_NAME} \
--query "QueueUrls[?contains(@,\` ${SQS_QUEUE_NAME}\`)]" \
--output text
2.VisibilityTimeoutの更新
環境変数に東京リージョンを指定します。
  • 環境変数を設定するときはexportコマンドを使います。
export AWS_DEFAULT_REGION='ap-northeast-1'
②変数[SQS_QUEUE_NAME]にSQSキュー名を指定します。
SQS_QUEUE_NAME="handson-cli-sqs-queue"
③変数[SQS_QUEUE_ATTRIBUTE_NAME]にSQSキューの属性名を指定します。
SQS_QUEUE_ATTRIBUTE_NAME="VisibilityTimeout"
④変数[SQS_QUEUE_ATTRIBUTE_VALUE]にSQSキュー属性値を指定します。
  • 今回は60秒を指定します。
SQS_QUEUE_ATTRIBUTE_VALUE="60"
⑤正しいパラメータ値が格納されていることを確認します。
cat << END

  # 0. AWS_DEFAULT_REGION:"ap-northeast-1"
       AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION}"

  # 1. SQS_QUEUE_NAME:"handson-cli-sqs-queue"
       SQS_QUEUE_NAME="${SQS_QUEUE_NAME}"
  # 2. SQS_QUEUE_ATTRIBUTE_NAME:"VisibilityTimeout"
       SQS_QUEUE_ATTRIBUTE_NAME="${SQS_QUEUE_ATTRIBUTE_NAME}"
  # 3. SQS_QUEUE_ATTRIBUTE_VALUE:"60"
       SQS_QUEUE_ATTRIBUTE_VALUE="${SQS_QUEUE_ATTRIBUTE_VALUE}"

END
⑥SQSキューのURLを取得します。
  • キューのURLを取得するために`sqs get-queue-url'コマンドを使います。
SQS_QUEUE_URL=$( \
 aws sqs get-queue-url --queue-name ${SQS_QUEUE_NAME} \
 --output text \
) \
&& echo ${SQS_QUEUE_URL}
⑦VisibilityTimeout値を60に更新します。
  • キューの設定値を変更するためにはsqs set-queue-attributesコマンドを使います。
aws sqs set-queue-attributes --queue-url ${SQS_QUEUE_URL} \
 --attributes ${SQS_QUEUE_ATTRIBUTE_NAME}=${SQS_QUEUE_ATTRIBUTE_VALUE}
⑧VisibilityTimeout値を60に変更されたことを確認します。
aws sqs get-queue-attributes --queue-url ${SQS_QUEUE_URL} \
 --attribute-names ${SQS_QUEUE_ATTRIBUTE_NAME} \
 --query "Attributes.${SQS_QUEUE_ATTRIBUTE_NAME}" \
 --output text
3.SQSキューへのメッセージ送信
環境変数に東京リージョンを指定します。
  • 環境変数を設定するときはexportコマンドを使います。
export AWS_DEFAULT_REGION='ap-northeast-1'
②変数[SQS_QUEUE_NAME]にSQSキュー名を指定します。
SQS_QUEUE_NAME="handson-cli-sqs-queue"
③変数[SQS_MESSAGE_BODY]にSQSメッセージのボディを指定します。
SQS_MESSAGE_BODY='Hello World!'
④変数に正しいパラメータ値が格納されていることを確認します。
CAT << END

  # 0. AWS_DEFAULT_REGION:"ap-northeast-1"
       AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION}"
  # 1. SQS_QUEUE_NAME:"handson-cli-sqs-queue"
       SQS_QUEUE_NAME="${SQS_QUEUE_NAME}"
  # 2. SQS_MESSAGE_BODY:"Hello World!"
       SQS_MESSAGE_BODY="${SQS_MESSAGE_BODY}"

END
⑤SQSキューのURLを取得します。
SQS_QUEUE_URL=$( \
  aws sqs get-queue-url \
    --queue-name ${SQS_QUEUE_NAME} \
    --output text \
) \
 && echo ${SQS_QUEUE_URL}
⑥SQSキューにメッセージを送信します。
  • メッセージを送信するためには、sqs send-messageコマンドを使います。
  • --queue-url "<キューURL>" でキューURLを指定します。
  • --message-body "<メッセージ>" でメッセージを指定します。
aws sqs send-message --queue-url "${SQS_QUEUE_URL}" \
  --message-body "${SQS_MESSAGE_BODY}"
⑦メッセージが送信されたこと(利用可能なメッセージが1であること)を確認します。
  • キューの属性を取得するにはsqs get-queue-attributes コマンドを使います。
  • --attribute-names で利用可能なメッセージ[ApproximateNumberOfMessages]を指定します。
aws sqs get-queue-attributes \
  --queue-url ${SQS_QUEUE_URL} \
  --attribute-names ApproximateNumberOfMessages \
  --query 'Attributes.ApproximateNumberOfMessages' \
  --output text
4.SQSキューからのメッセージ受信
環境変数に東京リージョンを指定します。
  • 環境変数を設定するときはexportコマンドを使います。
export AWS_DEFAULT_REGION='ap-northeast-1'
②変数[SQS_QUEUE_NAME]にSQSキュー名を指定します。
SQS_QUEUE_NAME="handson-cli-sqs-queue"
③SQSメッセージ用ディレクトリを指定します。
DIR_SQS_MESSAGE="${HOME}/environment/tmp-handson-cli-sqs"
ディレクトリを作成します。
mkdir -p ${HOME}/environment/tmp-handson-cli-sqs
ディレクトリが存在することを確認します。
ls -d ${HOME}/environment/tmp-handson-cli-sqs
⑥SQSメッセージファイルを指定します。
FILE_SQS_MESSAGE="${DIR_SQS_MESSAGE}/$(date +%Y-%m-%d)-${SQS_QUEUE_NAME}.json" \
  && echo ${FILE_SQS_MESSAGE}
⑦変数が正しく格納されているか、確認します。
cat << END

  # 0. AWS_DEFAULT_REGION:"ap-northeast-1"
       AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION}"

  # 1. SQS_QUEUE_NAME:"handson-cli-sqs-queue"
       SQS_QUEUE_NAME="${SQS_QUEUE_NAME}"
  # 2. DIR_SQS_MESSAGE:"${HOME}/environment/tmp-handson-cli-sqs"
       DIR_SQS_MESSAGE="${DIR_SQS_MESSAGE}"
  # 3. FILE_SQS_MESSAGE:"${HOME}/environment/tmp-handson-cli-sqs/2020-05-20-handson-cli-sqs-queue.json"
       FILE_SQS_MESSAGE="${FILE_SQS_MESSAGE}"

END
⑧SQSキューのURLを取得します。
SQS_QUEUE_URL=$( \
  aws sqs get-queue-url \
    --queue-name ${SQS_QUEUE_NAME} \
    --output text \
) \
 && echo ${SQS_QUEUE_URL}
⑨SQSキューからメッセージを受信します。
  • メッセージを受信するにはsqs receive-message コマンドを使います。
aws sqs receive-message --queue-url "${SQS_QUEUE_URL}" \
  > ${FILE_SQS_MESSAGE} \
    && cat ${FILE_SQS_MESSAGE}
⑩ReceiptHandleを取得します。
SQS_MESSAGE_RECEIPT_HANDLE=$( \
  cat ${FILE_SQS_MESSAGE} \
  | jp.py 'Messages[].ReceiptHandle' \
  | sed 's/[]\"\[]//g' \
) \
  && echo ${SQS_MESSAGE_RECEIPT_HANDLE}
⑪ReceiptHandle値でメッセージを特定して、メッセージを削除します。
  • メッセージを削除するにはsqs delete-message コマンドを使います。
aws sqs delete-message --queue--url "${SQS_QUEUE_URL}" \
 --receipt-handle ${SQS_MESSAGE_RECEIPT_HANDLE}
⑫SQSキューに利用可能なメッセージが残っていないこと(0であること)を確認します。
aws sqs get-queue-attributes \
  --queue-url ${SQS_QUEUE_URL} \
  --attribute-names ApproximateNumberOfMessages \
  --query 'Attributes.ApproximateNumberOfMessages' \
  --output text
5.後片付け

ハンズオン環境が不要な場合は、以下の作業を実施します。

最後に

ハンズオン当日は環境準備がおぼつかなくてついていくのがやっとでした。日を改めてじっくりとハンズオン環境を準備して、一つ一つコマンドの意味や挙動を理解しようとしながら取り組むことができ、理解が深まりました。2回ハンズオンを受けて復習もしたためか、コマンドで何をするかが少しずつ分かってきた気がします。SNS入門の復習もしてまたブログに書きます!

最後まで読んでいただき、ありがとうございました!

DevRel Meetup in Tokyo #52 〜オンラインカンファレンス〜 参加レポート

6/3(水) DevRel Meetup in Tokyo #52 〜オンラインカンファレンス〜 に参加しましたので、レポートを書きます。

目次

イベントページ

devrel.connpass.com

全体の感想

オンラインカンファレンスやオンライン勉強会が当たり前になっていますが、 ものすごく大変な準備をされていることを知り、驚きました。 自分は勉強会を主催している方ではなく参加するばかりですが、 参加させていただけることにもっと感謝しなければ… オンラインでも難なく勉強会が開催されているのは、運営の皆さんの綿密な準備によって成り立っている。今後はそれを自覚して参加したいと思いました。

また、このご時世だからこそ、オンラインで新しいことに挑戦することができる。新しい価値を提供することができる。 自分も何かできないか、考えてみたくなりました。

セッション内容

オンラインイベント開催のポイント by 宮原徹さん@びぎねっと
資料

www.slideshare.net

概要
  • リハーサル最重要!
  • マイクとネットワーク重要!
    • カメラは無くても良い。飾り!
  • 運営は役割分担と連絡連携が大事!
  • YouTube Liveが気軽に見れる。
  • 懇親会は人数コントロールをうまくやれると楽しくなる。

  • リハーサルの目的

    • 講師側の環境を事前確認
    • ツール使用の練習
    • スタッフとの連携確認、当日進行方法の確認
  • リハーサルの詳細

    • 基本的には全員リハーサルを行う。
    • 音声、カメラ、ネットワークのチェックをする。
      • 内臓マイクの人はイヤホンだけでも準備してもらう。
    • ネットワーク環境に合わせた対応を。
      • モバイルルータは途中で切れることがある。聞いている方はストレスになる。
    • 講師側から見え方が分からない。
      • ホスト、スタッフの連携をチェック。
    • スタッフのリハーサルもやる。
  • スタッフの役割

    • Zoomのオペレーション
    • ホストのサポートと監視
    • スタッフ間はSlackで連携 など
  • YouTubeLiveとの連携

    • Zoomからの配信をYouTubeで連携する。
    • Zoomの100名制限にかからない。
    • アカウント不要。
    • 録画しておいてくれる。
  • 懇親会

    • 100名以内ならば1会場で。
    • ブレイクアウトルームで5~6名にランダムに割り振り20分×2で実施。
  • オンラインのメリット

    • メリット

      • 気軽に参加できる。
      • 移動する必要がない。
      • 仕事や食事しながらでも聞ける。
    • デメリット

      • 参加している感が少なくなる。
      • 内輪になりやすい。発見を与えるのがイベントの役目。
今年の de:code、オンラインでやるってよ(´Д` )!! by おだしょーさん@Microsoft
概要
  • 昨年との相違点

    • 昨年はオフライン。2日間。参加費65,000~80,000円。
    • 今年はオンライン。2週間。参加費無料。
    • セッションタイムテーブルなし。
    • 今年からCommunityというトラックができた。
  • 開催に向けての歩み

    • COVID-19でざわつき、オンライン開催に踏み切った。
    • オフラインと変わらぬ体験を。
  • セッション収録方法

    • PowerPointでスライドごとに音声を記録することができる。
    • Teamsでスライドを画面共有、レコーディング機能を使って収録できる。ただし一発取り。
  • 今年のおだしょーさんの役割

    • トラックオーナー(新設コミュニティトラックの責任者)
    • セッションスピーカー
    • コミュニティイベント
      • Build Community Connection
      • de:code夏祭り(Teams、YouTube Live で配信)
オンラインカンファレンスとBacklog World 2020 のチームビルディング  西馬さん
資料

speakerdeck.com

概要
  • 前例踏襲できないプロジェクト運営

    • リスクに対応
    • 変化に対応
  • 完全オンライン

    • 全員別々の場所で参加した。
    • 運営メンバのうち配信に関わる3,4人だけ集まるつもりだったが、感染拡大の影響により変わってきた。

      • 完全オンラインに切り替えた。
      • 冷静なリスクマネジメントが必要だった。
    • 現地開催で準備していたものを引き継いだ。

    • 配信ノウハウはないので、天神放送局に依頼した。
  • オンラインにして

    • 無料になった。
    • 登壇者数は10人になった。
    • 参加者は200人⇒634人になった。
    • オフラインの準備は9か月だったが、オンラインの準備は1か月で完了した。
    • オフラインではウォーターフォールだが、オンラインではアジャイルに進めた。
    • 事務局たたき台方式ではなく、みんなで決める方式にした。
    • 定例会は週2回行った。
    • 急いでやったので抜け漏れが多かったが、助け合いも多かった。
  • テーマとイベント名

    • ONE:   - チームで一丸となる。
      • コミュニティに関わる人たちを一つにする。
    • re:Union
      • 熱い思いを持った運営メンバーの再会、チーム再結成。
      • 中止になったイベントをあきらめない「再」開催。
  • オンライン配信の成果

    • 既成概念は崩れた。
      • 熱気はオフラインで感じるもの。
      • イベントは現地が基本。参加できた人のもの。
      • 出会いは現地でリアルに。
  • 完全オンラインの難しさ

    • 合図や気配が全く分からない。
    • 運営メンバと登壇者のやり取りが分からない。
    • リハーサルを何度も繰り返した。リハーサルは重要。
      • 落ち着いて勧められたのはリハーサルのおかげ。
  • オンライン時代に挑戦しましょう

    • いい汗かきましょう。
    • オフラインと違う価値との出会い、価値を届ける。
    • 逆境に負けず挑戦を。
    • コミュニティの新しい形の在り方、ニューノーマルの模索を。

LT

社内外の勉強会の取り組み 石川陽一さん
資料

speakerdeck.com

  • 昨年から勉強会に参加するようになった。
  • 自分でも勉強会を開催し始め、ほぼ毎日勉強会をやっている。
  • Qiitaにも記事を投稿している。
感想

とにかくアウトプット量が凄い!と思いました。自分も勉強会、登壇、ブログ執筆などやってても量はまだまだ。 もっと積極的に素早くアウトプットしたいと刺激をもらいました!

Zoom ウェビナーについて kihara さん

※中座しており聞くことができませんでした。申し訳ありません…

オンラインカンファレンスいいよ! 中津川さん
  • 良いところ

    • どこからでも参加できる。
    • 大抵無料。
    • アーカイブ公開が早い。YouTubeならば字幕がある。
    • 英語が苦手でもOK。
    • CFP出し放題。
  • 悪いところ

    • 寝不足になる。
    • 飽きやすい。
    • 起きたら終わってる等、すっぽかしてしまう。
    • タイムゾーンよくわからない。

最後に

今回の話は、オンラインカンファレンスに限りません。 勉強会を含め、自分の身の回りでこれまで大小限らず企画されたイベントの主催者もしっかりと準備して臨んでいるはず。 そう思うと改めて感謝の気持ちがこみ上げてきました。 自分がイベントを主催するのはいつになるかわかりませんが、自分がイベントを主催した時にも綿密に準備をして、 参加者に楽しんでもらえるよう全力で臨まなければならないと思いました!

JAWS-UG CLI専門支部 #155R EC2入門 参加レポート

5/28(木)、JAWS-UG CLI専門支部 #155R EC2入門 に参加しました。 今回も感想とやったことの手順(再構築)を書きます。

目次

イベントページ

jawsug-cli.connpass.com

ハンズオンでやったこと

以下の通りです。事前準備として、Cloud9上にハンズオン環境を構築しました。 ハンズオンでは、Cloud9のターミナルでコマンド実行します。

EC2とは

  • Elastic Compute Cloud(EC2)
  • EC2インスタンスVPC内に作られる。
  • ネットワークインターフェースにセキュリティグループ(ファイアウォール機能)が紐づけられている。
  • 公開鍵はEC2内にて管理されている。ユーザは触ることができない。
  • デフォルトVPCの配下にはインターネットゲートウェイとデフォルトサブネットが設定されている。
    • 検証環境として使う場合は手早く使える。
    • 本番環境の場合は、最初に削除した方が良いもの。仕事で使うのは微妙。
  • EC2コマンドの分類は大きく以下の通り(400近くある)

感想

ハンズオン手順が長くなるので、感想を先に書きます。

前回にも増してボリュームのあるハンズオンでしたが、今回もハンズオンを終わらせて、細かくは後で復習するというスタンスで臨みました。CLIでの作成は初でしたが、CLIで作っていく方がサーバやネットワークを構築しているという感覚になって面白かったです。前回のように復習時にコマンドのことを深掘りして操作することで、何をやっているのかを理解することができてコマンド操作が楽しくなってきました。これを機にLinuxコマンドやシェルについてももっと勉強しようと思いました。SQS入門とSNS入門のハンズオンももう一度復習したくなりました!

次回ハンズオン(6/8 EC2基礎(VPC))も参加します!

ハンズオン手順

事前作業として、IAMロールにIAMポリシ「AmazonEC2FullAccess」をアタッチします。

1.デフォルトVPCの構築

※デフォルトVPCがある場合は、この手順は実行不要です。

①変数[AWS_DEFAULT_REGION]にデフォルトリージョンを指定します。
  • 東京リージョンを指定します。
export AWS_DEFAULT_REGION='ap-northeast-1'
②各変数に正しいパラメータ値が格納されていることを確認します。
cat << END

  # 0. AWS_DEFAULT_REGION:"ap-northeast-1"
       AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION}"

END
③デフォルトVPCを作成します。
  • デフォルトVPCは、create-default-vpcで作成できます。
  • 以下のコマンドを実行して、VPCを作成します。
aws ec2 create-default-vpc 
2. EC2キーペアの作成
①変数[AWS_DEFAULT_REGION]にデフォルトリージョンを指定します。
  • 東京リージョンを指定します。
export AWS_DEFAULT_REGION='ap-northeast-1'
②変数[EC2_KEY_PAIR_NAME]にEC2キーペア名を指定します。
EC2_KEY_PAIR_NAME="handson-cli-ec2-getting_started-keypair"
③変数[DIR_KEY]に鍵ファイルディレクトリを指定します。
DIR_KEY="${HOME}/.ssh"
④鍵ファイルディレクトリを作成します。
  • chmod コマンドでディレクトリのアクセス権限を指定します。
  • 700は、所有者(自分)はフルアクセス許可という意味です。
mkdir -p ${HOME}/.ssh && chmod 700 ${HOME}/.ssh
AWS IDを取得します。
  • アカウントIDの取得は、sts get-caller-identityコマンドを使います。
  • オプションをつけないと、UserIDとArnとAccountを表示するため、query オプションを使ってAccountのみを出力します。
AWS_ID=$( \
  aws sts get-caller-identity \
    --query 'Account' \
    --output text \
) \
  && echo ${AWS_ID}
SSH秘密鍵ファイル名を指定します。
FILE_SSH_KEY_SECRET="${DIR_KEY}/${EC2_KEY_PAIR_NAME}-${AWS_ID}-${AWS_DEFAULT_REGION}-ec2.pem" \
  && echo ${FILE_SSH_KEY_SECRET}
⑦EC2キーペアを作成します。
  • キーペアは、create-key-pairコマンドで作成します。
  • key-nameオプションでキーペア名を指定します。
  • chmodコマンドの400は所有者のみに読み取り権限を付与するという意味です。
aws ec2 create-key-pair \
  --key-name ${EC2_KEY_PAIR_NAME} \
  --query 'KeyMaterial' --output text \
> ${FILE_SSH_KEY_SECRET} \
&& cat ${FILE_SSH_KEY_SECRET} \
&& chmod 400 ${FILE_SSH_KEY_SECRET}
⑧EC2キーペアが存在することを確認します。
  • キーペアを確認するためには、ec2 describe-key-pairsコマンドを使います。
aws ec2 describe-key-pairs \
  --query "KeyPairs[?KeyName == \`${EC2_KEY_PAIR_NAME}\`].KeyName" \
  --output text
SSH秘密鍵が存在することを確認します。
ls ${FILE_SSH_KEY_SECRET}
3.ユーザーデーターの作成
①変数[DIR_USER_DATA]にユーザデータ用ディレクトリを指定します。
DIR_USER_DATA="${HOME}/environment/conf-handson-cli-ec2-getting_started"
ディレクトリを作成します。
mkdir -p ${HOME}/environment/conf-handson-cli-ec2-getting_started
ディレクトリが存在することを確認します。
ls -d ${HOME}/environment/conf-handson-cli-ec2-getting_started
④変数[USER_DATA_NAME]にユーザデータ名を指定します。
USER_DATA_NAME='handson-cli-ec2-getting_started-userdata'
⑤変数[FILE_USER_DATA]にユーザデータファイル名を指定します。
FILE_USER_DATA="${DIR_USER_DATA}/${USER_DATA_NAME}.bash" \
  && echo ${FILE_USER_DATA}
⑥変数[PORT_SSHD]にSSHポート番号'22022'を指定します。
PORT_SSHD='22022'
⑦以下のコマンドを実行して、ユーザデータファイルを作成します。
cat << EOF1 > ${FILE_USER_DATA}
#!/bin/bash

# configure sshd
cat << EOF >> /etc/ssh/sshd_config

Port ${PORT_SSHD}
EOF
systemctl restart sshd.service


# yum
yum update -y
EOF1
  • ファイルの中身を確認します。
cat ${FILE_USER_DATA}
⑧ユーザデータが存在することを確認します。
ls ${FILE_USER_DATA}
4.デフォルトVPCセキュリティグループへのIngressルール追加
①リージョンを指定します。
export AWS_DEFAULT_REGION='ap-northeast-1'
②変数[EC2_SECURITY_GROUP_NAME]にセキュリティグループ''default'を指定します。
EC2_SECURITY_GROUP_NAME='default'
③変数[EC2_SECURITY_GROUP_PROTOCOL]にプロトコル'tcp'を指定します。
 EC2_SECURITY_GROUP_PROTOCOL='tcp'
④変数[EC2_SECURITY_GROUP_PORT]にSSHポート番号'22022'を指定します。
EC2_SECURITY_GROUP_PORT='22022'
⑤対象となるIPアドレスの範囲を指定します。
  • 指定のURLよりIPアドレスを取得し、変数[IP_ADDR_LOCAL]に格納します。
  • curlの -s(--silent)オプションは、ダウンロードの進捗やエラーを表示しないためのオプションです。
IP_ADDR_LOCAL=$( curl -s http://checkip.amazonaws.com/ ) \
  && echo ${IP_ADDR_LOCAL}
  • CIDRの値を変数[EC2_SECURITY_GROUP_CIDR]に格納します。
EC2_SECURITY_GROUP_CIDR="${IP_ADDR_LOCAL}/32" \
  && echo ${EC2_SECURITY_GROUP_CIDR}
⑥以下のコマンドを実行して、セキュリティグループにルールを追加します。
  • セキュリティグループにルールを追加するには、ec2 authorize-security-group-ingressコマンドを使います。
aws ec2 authorize-security-group-ingress \
  --group-name ${EC2_SECURITY_GROUP_NAME} \
  --protocol ${EC2_SECURITY_GROUP_PROTOCOL} \
  --port ${EC2_SECURITY_GROUP_PORT} \
  --cidr ${EC2_SECURITY_GROUP_CIDR}
5.EC2インスタンスの構築
①リージョンを指定します。
export AWS_DEFAULT_REGION='ap-northeast-1'
②EC2インスタンスのタグ名を指定します。
EC2_INSTANCE_TAG_NAME='handson-cli-ec2-getting_started-instance'
③起動時に利用するAMIイメージ名を指定します。
EC2_IMAGE_NAME="amzn2-ami-hvm-2.0.20190823.1-x86_64-gp2"
④EC2インスタンスインスタンスタイプを指定します。
EC2_INSTANCE_TYPE="t2.micro"
⑤ユーザデータファイル名を指定します。
DIR_USER_DATA="${HOME}/environment/conf-handson-cli-ec2-getting_started"
USER_DATA_NAME="handson-cli-ec2-getting_started-userdata"
  • 変数[FILE_USER_DATA]にユーザデータファイル名を指定します。
FILE_USER_DATA="${DIR_USER_DATA}/${USER_DATA_NAME}.bash" \
  && echo ${FILE_USER_DATA}
⑥キーペア名を指定します。
EC2_KEY_PAIR_NAME="handson-cli-ec2-getting_started-keypair"
⑦イメージIDを取得します。
  • イメージIDを取得するためには、ec2 describe-imagesコマンドを使います。
EC2_IMAGE_ID=$( \
  aws ec2 describe-images \
    --filters Name=name,Values="${EC2_IMAGE_NAME}" \
    --query 'Images[].ImageId' \
    --output text \
) \
  && echo ${EC2_IMAGE_ID}
⑧タグキーを生成します。
EC2_TAG_KEY='Name'
⑨タグ文字列を生成します。
STRING_TAG_CONF="ResourceType=instance,Tags=[{Key=${EC2_TAG_KEY},Value=${EC2_INSTANCE_TAG_NAME}}]" \
  && echo ${STRING_TAG_CONF}
⑩以下のコマンドを実行して、EC2インスタンスを作成します。
  • EC2インスタンスを作成するためには、ec2 run-instancesコマンドを使います。
    • --associate-public-ip-addressでパブリックIPアドレスを有効にします。
aws ec2 run-instances \
  --image-id ${EC2_IMAGE_ID} \
  --instance-type ${EC2_INSTANCE_TYPE} \
  --tag-specifications ${STRING_TAG_CONF} \
  --user-data file://${FILE_USER_DATA} \
  --key-name ${EC2_KEY_PAIR_NAME} \
  --associate-public-ip-address

インスタンスの存在確認をします。

  • EC2のインスタンス情報を表示させるには、ec2 describe-instancesコマンドを使います。
  • 以下のコマンドを実行して、ステータスが'running'のEC2インスタンスが存在することを確認します。

インスタンスが作成され、'running'状態になるまで数分程度かかることがあります。

aws ec2 describe-instances \
  --filters Name=tag-key,Values=Name \
            Name=tag-value,Values=${EC2_INSTANCE_TAG_NAME} \
            Name=instance-state-name,Values=running \
  --query Reservations[].Instances[].Tags[].Value \
  --output text
6.EC2インスタンスへのSSHログイン
①リージョンを指定します。
export AWS_DEFAULT_REGION='ap-northeast-1'
②鍵ファイルディレクトリを指定します。
DIR_KEY="${HOME}/.ssh"
③EC2キーペア名を指定します。
EC2_KEY_PAIR_NAME="handson-cli-ec2-getting_started-keypair"
AWS IDを取得します。
AWS_ID=$( \
  aws sts get-caller-identity \
    --query 'Account' \
    --output text \
) \
  && echo ${AWS_ID}
SSH秘密鍵ファイル名を取得します。
FILE_SSH_KEY_SECRET="${DIR_KEY}/${EC2_KEY_PAIR_NAME}-${AWS_ID}-${AWS_DEFAULT_REGION}-ec2.pem" \
  && echo ${FILE_SSH_KEY_SECRET}

⑥EC2インスタンス名を指定します。

EC2_INSTANCE_TAG_NAME='handson-cli-ec2-getting_started-instance'

SSHポート番号を22022に指定します。

PORT_SSHD='22022'

⑧EC2インスタンスグローバルIPアドレスを取得します。

EC2_PUBLIC_IP=$( \
  aws ec2 describe-instances \
    --filters Name=tag-key,Values=Name \
              Name=tag-value,Values=${EC2_INSTANCE_TAG_NAME} \
    --instance-ids ${ARRAY_EC2_INSTANCE_IDS} \
    --query "Reservations[].Instances[].PublicIpAddress" \
    --output text \
) \
  && echo ${EC2_PUBLIC_IP}

⑨EC2インスタンスSSHでログインします。

ssh ${EC2_PUBLIC_IP} \
  -i ${FILE_SSH_KEY_SECRET} \
  -l ec2-user \
  -p ${PORT_SSHD}

⑩EC2インスタンスにログインしていることを確認します。

curl -q http://169.254.169.254/latest/meta-data/public-ipv4
7.EC2インスタンスメタデータの取得
①IMDSv2で利用するトークンを取得して、ヘッダー形式で変数に格納します。
EC2_METADATA_SECOND='900'
メタデータトークンを取得します。
  • curlコマンドの-X(--request)オプションで、HTTPメソッドを変更します(下記コマンドの場合は、PUTメソッドに変更します)。
  • -H(--header)は、カスタムヘッダを追加するオプションです。
EC2_METADATA_TOKEN=$( \
  curl -s \
    -X PUT "http://169.254.169.254/latest/api/token" \
    -H "X-aws-ec2-metadata-token-ttl-seconds: ${EC2_METADATA_SECOND}" \
) \
  && echo ${EC2_METADATA_TOKEN}
メタデータトークンをヘッダ形式として変数[EC2_METADATA_HEADER]に格納します。
EC2_METADATA_HEADER="X-aws-ec2-metadata-token: ${EC2_METADATA_TOKEN}" \
  && echo ${EC2_METADATA_HEADER}
④EC2インスタンスメタデータ一覧を取得します。
curl -H "${EC2_METADATA_HEADER}" \
  http://169.254.169.254/latest/meta-data/
  • 以下の通り表示されます。
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
iam/
identity-credentials/
instance-action
instance-id
instance-type
local-hostname
local-ipv4
mac
metrics/
network/
placement/
profile
public-hostname
public-ipv4
reservation-id
security-groups
⑤以下コマンドの<メタデータ>に、取得したい項目を入れて実行します。
EC2_INSTANCE_TYPE=$( \
  curl -s -H "${EC2_METADATA_HEADER}" \
    http://169.254.169.254/latest/meta-data/<メタデータ> \
) \
  && echo ${EC2_INSTANCE_TYPE}
EC2_INSTANCE_TYPE=$( \
  curl -s -H "${EC2_METADATA_HEADER}" \
    http://169.254.169.254/latest/meta-data/instance-type \
) \
  && echo ${EC2_INSTANCE_TYPE}
EC2_AZ_NAME=$( \
  curl -s -H "${EC2_METADATA_HEADER}" \
    http://169.254.169.254/latest/meta-data/placement/availability-zone \
) \
  && echo ${EC2_AZ_NAME}
  • リージョン情報だけはメタデータから取得できます。取得したい場合は、AZを取得し、末尾の文字を省いて表示させる必要があります。

    • AZを取得したら、sedコマンドにて末尾のa~zを削除して表示させます。
EC2_REGION_NAME=$( \
  curl -s -H "${EC2_METADATA_HEADER}" \
    http://169.254.169.254/latest/meta-data/placement/availability-zone \
  | sed -e 's/[a-z]*$//' \
) \
  && echo ${EC2_REGION_NAME}
⑥作業が終わったら、EC2インスタンスからログアウトします。
exit
8.後片付け

今回のハンズオン環境が不要になったら、以下の後片付けをします。 自分はまだ残したいため未作業です。以下リンクを参照してください。

以上です。最後まで読んでいただき、ありがとうございました。

JAWS-UG CLI専門支部 #154R S3入門 参加レポート

5/25 JAWS-UG CLI専門支部 #154R S3入門 に参加しましたので、レポートを書くのと同時に、ハンズオンでやったことの復習を書きます。

目次

イベントページ

jawsug-cli.connpass.com

今回のハンズオンでやったこと

以下の通りです。事前準備として、Cloud9上にハンズオン環境を構築しました。 ハンズオンでは、Cloud9のターミナルでコマンド実行します。

S3について

今回話に上がったポイントを以下に示します。

  • S3はオブジェクトストレージ
  • バケット」というオブジェクトコンテナにオブジェクト(ファイル)を格納する。
    • バケットは世界でユニーク(一意)である必要がある。
  • オブジェクトは、オブジェクトデータとメタデータで構成される。
  • オブジェクトは、バケット+キー+バージョンIDの組み合わせで、一意に識別される。
  • 耐久性はイレブンナイン(可用性は99.99%)
  • S3は結果整合性モデルが使われているため、データの更新と削除の場合は即時反映されない。
  • 仮想ホスティングとWebホスティングは違う。
    • 仮想ホスティングの場合は、ファイルフルパスでないとアクセスできない。
    • Webサイトとして公開したいならば、Webホスティングを設定すること。
  • グローバルサービスだが、バケット作成の際はリージョンを指定する必要がある。

また、開発者ガイドの「はじめに」を読むだけでも、S3への理解が深まるとのことです。

docs.aws.amazon.com

感想

この後、ハンズオンで実施した手順を自分の解釈も追記して書こうと思います。長くなるので、先に全体の感想を書きます。

SQSとSNSの時も参加しましたが、ブログには書きませんでした。しかし、CLIハンズオンガイドに、

  • 「完了すること」を最優先すること
  • 必ず復習すること
  • オリジナル手順をアウトプットすること

について書かれていました。今回からこの点に言及されたことにより、今回のハンズオンからはとにかく体感し、自分なりの解釈をインプットし、それをブログでアウトプットすることに努めようと思いました。

そのためか、余裕をもって完走出来ました。SQSとSNSの時も楽しかったものの、ついていくのがやっとでした。今回は、純粋にハンズオンは楽しいと思えて、前回以上に受講して良かったと思えました。

過去のSQS入門、SNS入門のハンズオンもやり直して、サービスの理解とコマンドの理解を深めたくなりました。

ハンズオンで実施した手順(再構成)

今回のハンズオンの手順は以下にあります。しかし、自分自身の理解のために、波田野さんの手順より細かく書こうと思います。くどいかもしれませんが、ご容赦ください。

※ハンズオン手順(波田野さん作成) prototype-handson-cli.s3-website-ap-northeast-1.amazonaws.com

事前準備

ハンズオンでは、IAMロールを作りIAMロール「AmazonS3FullAccess」を付与しました。これがないと、S3にバケットを作ることもオブジェクトを作ることもできません。

事前作業. Cloud9用ロールへのIAMポリシー追加 — ハンズオン(簡易版): S3入門 - ハイレベルコマンド活用

1.S3バケットの構築
①デフォルトリージョンの設定
  • AWSデフォルトリージョンを変数[AWS_DEFAULT_REGION]に格納します。
export AWS_DEFAULT_REGION='ap-northeast-1'
バケットプレフィックスを指定
S3_BUCKET_PREFIX='handson-cli-s3'
AWS_IDの取得と設定
  • AWS_IDを取得して変数[AWS_ID]に格納します。変数の値を出力して確認します。
AWS_ID=$( \
  aws sts get-caller-identity \
    --query 'Account' \
    --output text \
) \
  && echo ${AWS_ID}
バケット名設定
S3_BUCKET_NAME="${S3_BUCKET_PREFIX}-${AWS_ID}" \
  && echo ${S3_BUCKET_NAME}
⑤変数格納状況の確認
  • 変数が想定通りに格納されているか確認します。
  • ちゃんと格納されていれば、変数部分に想定している値が表示されます。
cat << END

  # AWS_DEFAULT_REGION:"ap-northeast-1"
    AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION}"
  # S3_BUCKET_NAME:"handson-cli-s3-XXXXXXXXXXXX"
    S3_BUCKET_NAME="${S3_BUCKET_NAME}"

END
バケット構築

mb はバケット作成コマンドです。--region でバケットを作成するリージョンを指定します。

aws s3 mb s3://<バケット名> --region <リージョン>

変数が正しく格納されていることを確認したら、以下のコマンドを実行します。 - ①で指定したリージョンに、④で設定した変数のバケットを作成します。

aws s3 mb s3://${S3_BUCKET_NAME} \
  --region ${AWS_DEFAULT_REGION}
バケットの存在確認

aws s3 ls コマンドで、S3上に存在するバケットをリスト表示します。

  • S3バケットが存在することを確認するために、以下のコマンドを実行します。
aws s3 ls | grep ${S3_BUCKET_NAME}
2.S3オブジェクトの操作

バケット名変数[S3_BUCKET_NAME]の指定は省略します(1.②~④と同じため)。

(1)一時ファイル用ディレクトリの作成
①変数[DIR_TMP]にディレクトリを指定します。
DIR_TMP="${HOME}/environment/tmp-handson-cli-s3"
ディレクトリを作成します。
  • mkdirコマンドの- pオプション(--parentsオプション)は、ディレクトリがなくてもエラーを出さずにディレクトリを作成するオプションです。
mkdir -p ${HOME}/environment/tmp-handson-cli-s3
ディレクトリが存在することを確認します。
  • lsコマンドの -d オプション(--directory オプション)は、ディレクトリそのものの情報を表示するオプションです。
ls -d ${HOME}/environment/tmp-handson-cli-s3
④変数に正しい値がに格納させていることを確認します。
  • 合っていれば、正しいパラメータ値に値が入っています。
cat << END

  # 1. S3_BUCKET_NAME:"handson-cli-s3-XXXXXXXXXXXX"
       S3_BUCKET_NAME="${S3_BUCKET_NAME}"
  # 2. DIR_TMP:"${HOME}/environment/tmp-handson-cli-s3"
       DIR_TMP="${DIR_TMP}"

END
(2)ファイルアップロード
①一時ファイル用ディレクトリに移動します。
cd ${DIR_TMP}
②S3バケットにオブジェクトが存在しないことを確認します。

`aws s3 ls s3://<バケット名>/' でバケット内のオブジェクトをリスト表示します。

  • 以下の通りコマンド実行します。この時点では結果に何も出力されません。
aws s3 ls s3://${S3_BUCKET_NAME}/
③変数[S3_OBJECT_NAME]にアップロード用ファイル名を設定します。
S3_OBJECT_NAME='upload.txt'
④変数[FILE_UPLOAD]にファイルアップロード用フォルダパスを格納します。
FILE_UPLOAD="${DIR_TMP}/${S3_OBJECT_NAME}"  && echo ${FILE_UPLOAD}
⑤アップロード用のファイルを作成します。
  • touch コマンドは、ファイルのタイムスタンプを変更するコマンドですが、ファイルが存在しない場合は、空(0バイト)のファイルを作成します。
touch ${FILE_UPLOAD}
⑥作成したファイルをS3にアップロードします。

ローカルディレクトリからS3バケットにオブジェクト(ファイル)をアップロードする場合は、cpコマンドを使います。

aws s3 cp <ローカルディレクトリ名> s3://<バケット名>

以下の通りコマンドを実行して、⑤で作成したファイルをアップロードします。

aws s3 cp ${FILE_UPLOAD} s3://${S3_BUCKET_NAME}/
⑦S3バケットにファイルが作成(アップロード)されたことを確認します。

※コマンドだけでなく、マネジメントコンソールからもファイルが作成されたか確認します。

aws s3 ls s3://${S3_BUCKET_NAME}/
(3)オブジェクトダウンロード
①変数[S3_OBJECT_NAME]にダウンロードするS3オブジェクトを指定します。
S3_OBJECT_NAME='upload.txt'
②変数[FILE_DOWNLOAD]にダウンロードファイルのローカル保存名を指定します。
FILE_DOWNLOAD="${DIR_TMP}/download.txt" && echo ${FILE_DOWNLOAD}
③S3オブジェクトをダウンロードします。
  • オブジェクトをダウンロードする際も、cpコマンドを使います。
aws s3 cp S3://<バケット名>/<オブジェクト名> <ダウンロード先ディレクトリ>
  • 以下のコマンドを実行して、ファイルをダウンロードします。
aws s3 cp s3://${S3_BUCKET_NAME}/${S3_OBJECT_NAME} ${FILE_DOWNLOAD}
④ダウンロードしたファイルが存在することを確認します。
ls ${FILE_DOWNLOAD}
(4)S3オブジェクトの削除
①S3オブジェクトを削除します。
  • オブジェクトを削除する際は、rmコマンドを使います。
aws s3 rm s3://<バケット名>/<オブジェクト名>
  • 以下のコマンドを実行して、ファイルを削除します。
aws s3 rm s3://${S3_BUCKET_NAME}/${S3_OBJECT_NAME}
  • ファイルが削除されたことを以下のコマンド実行、またはマネジメントコンソールより確認します。
aws s3 ls s3://${S3_BUCKET_NAME}/
(5)ファイルのアップロード(バケット/ディレクトリ)
①変数[S3_OBJECT_PREFIX]に、ファイルのアップロード先ディレクトリを指定します。
S3_OBJECT_PREFIX='dir1'
②S3バケットにアップロードします。
  • 以下のコマンドを実行した際、S3_OBJECT_PREFIXで指定したフォルダがなければ、作成されます。
aws s3 cp ${FILE_UPLOAD} s3://${S3_BUCKET_NAME}/${S3_OBJECT_PREFIX}/
(6)S3オブジェクトの移行
①移動元のS3バケット名とS3オブジェクトパス名を指定します。
  • S3オブジェクトを移動させるためには、mvコマンドを使います。
aws s3 mv <移動元オブジェクト名> <移動先オブジェクト名>
  • 以下のコマンドを実行して、移動元オブジェクトを指定します。
S3_BUCKET_NAME_SOURCE="${S3_BUCKET_NAME}"
S3_OBJECT_PREFIX_SOURCE='dir1/upload.txt'
②移動先のS3バケット名とS3オブジェクトパスを指定します。
S3_BUCKET_NAME_DESTINATION="${S3_BUCKET_NAME}"
S3_OBJECT_PREFIX_DESTINATION='dir2/moved.txt'
③以下のコマンドでS3オブジェクトを移動します。
aws s3 mv s3://${S3_BUCKET_NAME_SOURCE}/${S3_OBJECT_PREFIX_SOURCE} \
  s3://${S3_BUCKET_NAME_DESTINATION}/${S3_OBJECT_PREFIX_DESTINATION}
④移動元にS3オブジェクトが存在しないことを確認します。
! aws s3 ls s3://${S3_BUCKET_NAME_SOURCE}/${S3_OBJECT_PREFIX_SOURCE}
⑤移動先にS3オブジェクトが存在することを確認します。
aws s3 ls s3://${S3_BUCKET_NAME_DESTINATION}/${S3_OBJECT_PREFIX_DESTINATION}
(6)S3オブジェクトのパス単位削除
①変数[S3_OBJECT_PREFIX]に、削除するS3ディレクトリ名を格納します。
S3_OBJECT_PREFIX=dir2
②削除前に、削除するディレクトリが存在することを確認します。
aws s3 ls s3://${S3_BUCKET_NAME}/${S3_OBJECT_PREFIX}
③以下のコマンドで、ディレクトリ配下のオブジェクトを含めてすべて削除します。
  • recursiveオプションをつけることで、再帰的にディレクトリ内のファイルを含めて削除します。
aws s3 rm \
  --recursive \
    s3://${S3_BUCKET_NAME}/${S3_OBJECT_PREFIX}
④削除したディレクトリが存在しないことを確認します。何も表示されなければ完了です。
! aws s3 ls s3://${S3_BUCKET_NAME}/${S3_OBJECT_PREFIX}
3.Gitリポジトリ取得~S3バケットへの転送

今回は事前に用意されていたGitリポジトリからコンテンツを取得しました。これは4.で使うものです。

①Gitリポジトリの取得元を指定します。
GIT_REPOSITORY_ORIGIN='https://github.com/opelab/jawsug-cli-sample-web.git'
リポジトリ保存用ディレクトリを指定します。
DIR_PARENT="${HOME}/environment/contents-handson-cli-s3"
リポジトリ保存用ディレクトリを作成します。
mkdir -p ${HOME}/environment/contents-handson-cli-s3
ディレクトリが作成されたことを確認します。
ls -d ${HOME}/environment/contents-handson-cli-s3
⑤Gitリポジトリディレクトリ名を指定します。
GIT_REPOSITORY_NAME='jawsug-cli-sample-web'
⑥Gitリポジトリを取得します。
cd ${DIR_PARENT} \
  && git clone ${GIT_REPOSITORY_ORIGIN}
⑦Gitリポジトリディレクトリが存在することを確認します。
ls -d ${DIR_PARENT}/${GIT_REPOSITORY_NAME}
⑧転送ファイル用ディレクトリを指定します。
DIR_S3_TRANSFER="${HOME}/environment/contents-handson-cli-s3/jawsug-cli-sample-web"
⑨転送除外オブジェクトを指定します(gitignoreなどgitを含むファイルとします)。
S3_SYNC_EXCLUDE=".git*"
⑩S3バケット上のディレクトリに転送します。
  • S3バケットとローカルを同期させたい場合は、syncコマンドを使います。
  • exclude オプションで動機対象外のオブジェクトを指定、aclオプションはアクセス公開範囲を指定します。
aws s3 sync <ローカルファイルのディレクトリ> s3://<バケット名> --exclude <同期対象外オブジェクト> --acl <公開範囲>
  • 以下のコマンドでオブジェクトを転送します。
dir_current=$(pwd)
cd ${DIR_S3_TRANSFER} \
  && aws s3 sync . "s3://${S3_BUCKET_NAME}/" \
    --exclude "${S3_SYNC_EXCLUDE}" \
    --acl public-read \
  && cd ${dir_current}
⑪S3バケットに転送オブジェクトが存在することを確認します。
aws s3 ls s3://${S3_BUCKET_NAME}/

結果、以下のように表示されます(例)。

2020-05-25 01:23:45        186 error.html
2020-05-25 01:23:45      55560 img.jpg
2020-05-25 01:23:45        255 index.html
⑫仮想ホスティングエンドポイントを取得します。
S3_BUCKET_ENDPOINT=" \
  ${S3_BUCKET_NAME}.s3.$( \
    aws s3api get-bucket-location \
      --bucket ${S3_BUCKET_NAME} \
      --output text \
  ).amazonaws.com" \
  && echo ${S3_BUCKET_ENDPOINT}
⑬オブジェクトにアクセスできることを確認します。
  • 変数[S3_OBJECT_NAME]にオブジェクト名を指定します。
S3_OBJECT_NAME='img.jpg'
  • オブジェクトURLを出力し、表示されたURLにアクセスできることを確認します。
URL_S3_OBJECT="${S3_BUCKET_ENDPOINT}/${S3_OBJECT_NAME}" \
  && echo ${URL_S3_OBJECT}
4.webサイトホスティングの設定

バケット名変数[S3_BUCKET_NAME]の指定は省略します(1.②~④と同じため)。

①インデックスドキュメント名を指定します。
S3_DOC_INDEX='index.html'
②エラードキュメント名を指定します。
S3_DOC_ERROR='error.html'
③Webサイトホスティング設定をします。
aws s3 website "s3://<バケット名>" --index-document <indexファイル名> --error-document <エラーページファイル名>
aws s3 website "s3://${S3_BUCKET_NAME}" \
  --index-document ${S3_DOC_INDEX} \
  --error-document ${S3_DOC_ERROR}
④Webサイトエンドポイントにアクセスできるか確認します。
  • 以下のコマンドを実行後、出力されたURLにアクセスできることを確認します。
S3_BUCKET_WEBSITE_ENDPOINT=" \
  ${S3_BUCKET_NAME}.s3-website-$( \
    aws s3api get-bucket-location \
      --bucket ${S3_BUCKET_NAME} \
      --output text \
  ).amazonaws.com" \
  && echo ${S3_BUCKET_WEBSITE_ENDPOINT}
⑤エラードキュメントにアクセスできるか確認します。
  • ④で出力されたURL末尾に適当な文字(/z/ など)を加えて実行します。
  • エラー画面が表示されることを確認します。
5.署名付きURLの利用

バケット名変数[S3_BUCKET_NAME]の指定は省略します(1.②~④と同じため)。

①署名対象S3オフジェクトを指定します(「img.jpg」とした場合)。
S3_OBJECT_NAME='img.jpg'
②署名付きURLの有効期限(秒)を指定します。
S3_PRESIGN_SECONDS='120'
③オブジェクトの署名付きURLを作成します。
  • 署名付きURLを発行するには、presign コマンドを使います。
aws s3 presign s3://<バケット名>/<オブジェクト名> --expires-in <有効期限(秒)>
  • 以下のコマンドを実行して、署名付きURLを発行します。
aws s3 presign s3://${S3_BUCKET_NAME}/${S3_OBJECT_NAME} \
  --expires-in ${S3_PRESIGN_SECONDS}
④結果に表示されたURLにアクセスできることを確認します。
⑤指定した有効期限が過ぎたら、URLにアクセスできなくなったことを確認します。
  • 「This XML file does not appear to have any style information associated with it. The document tree is shown below.」と表示されます。
6.後始末

使わないS3バケット、ハンズオン用ディレクトリを削除します。また、Cloud9ロールからS3フルアクセスポリシーをデタッチします。

後始末手順は以下の通りです。自分はこのブログを書いたり復習するために残していますので、まだ実施していません。

後始末1. S3バケットの破棄

後始末2. ハンズオン用ディレクトリの削除

事後作業. Cloud9用ロールからのポリシーのデタッチ

※Cloud9環境も不要ならば、事前準備の5以降(後始末も含みます)を実施します。

以上で終了です。

最後に

ハンズオンの復習をすることで、CLIについて、S3の動きについて、理解を深められたと実感できました。 今後のハンズオンは、必ず復習ありきで臨もうと思います。できる限りブログも書こうと思います。 かなり長いブログになってしまいましたが、最後まで読んでいただいた方は本当にありがとうございました!