20210501のAWSに関する記事は22件です。

【AWS】サブネットとは

プログラミング勉強日記 2021年5月1日 サブネットとは  サブネットはCIDR範囲で分割したネットワークセグメント。簡単に説明すると、ネットワーク内のさらに分割された小さなネットワークのこと。1つの大きなネットワークで管理するのは大変なので、いくつかのネットワークの集まりとして管理する。  サブネットはVPC内に複数設置することができて、1つのAZを指定して配置される。複数のAZをまたいでサブネットを作ることはできない。 パブリックサブネットとプライベートサブネット  パブリックサブネットは、トラフィックがインターネットゲートウェイにルーティングされているサブネット。つまり、インターネットのアクセスができるサブネットのこと。  プライベートサブネットは、インターネットゲートウェイへのルートがないサブネット。  パブリックサブネットを作りたい場合は、「まず、パブリックサブネットを作成する!」というやり方絵はなく、プライベートサブネットを作成してそのプライベートサブネットにインターネットゲートウェイへのルートを設定する。(パブリックサブネットに変更するという方法で行う。)  一般的にはVPCにCIDR/16を設定してサブネットに/24を設定することが推奨されている。  プライベートサブネットからインターネットに接続するためにはNATゲートウェイがパブリックサブネットに必要になる。NATゲートウェイをパブリック側に設置して、そこにアクセスしてからインターネットに接続する。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CloudFrontとは

概要 AWS版のキャッシュサーバーでユーザーはEC2に直接データを取得しに行かなくても、仲介するCloudFrontにEC2などからコピーされたデータを取りに行くため、Webページの表示が早くなる。 EC2やS3といったサービスはデータを渡す処理が減り、負荷の軽減になるといったメリットがある。 サービス開始後、データの配信元を指定すると世界中のエッジロケーションにデータがコピーされる。 基本動作 ①オリジンサーバーにオブジェクト格納 ②クライアントからの初回アクセス時に、最も地理的に近いエッジサーバーのキャッシュを参照しにいき、キャッシュがなければ、オリジンサーバーから該当コンテンツを取得してキャッシュする流れです ※CDN・・・コンテンツデリバリーネットワークという意味 ※AWS WAF・・・ウェブアプリケーションファイアーウォール(サイバー攻撃からシステムを守る仕組み) 用語 Viewer・・・アクセスしてくる人 Origin・・・コンテンツの配信元(EC2,S3,ELBなど設定できる) ※TTL・・・Originに最新のデータがあるか何秒置きに確認しますかという秒数の設定 設計ポイント レポート機能が備わっており、設定後に少しずつ調節していく運用がおすすめ ・CloudFrontを利用する上で、配信先が多数ある場合の利用料金の削減に有効な方法 →エッジロケーションにあるファイル圧縮機能を使用する オリジンからファイルを取得するときに、CloudFrontは各エッジロケーションでファイルを圧縮します。コンテンツを圧縮するように CloudFront を設定すると、既にエッジロケーションにあるファイルは圧縮しません。 CloudFrontのデータ転送コストは供給されたデータの総量に基づきます。 参考 この記事はAWS初学者を導く体系的な動画学習サービス 「AWS CloudTech」の課題カリキュラムで作成しました。 https://aws-cloud-tech.com
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Serverless FrameworkでAWS Lambdaの開発環境を簡単構築

はじめに 以前Lambdaを使ってSlack通知を飛ばすような機能をつくったのですが、コンソール上でコードをベタ書きしていたのでデバッグに非常に手間がかかりました。 最近の社内勉強会でServerless Frameworkの存在を知り、これを使えばローカル環境で関数をコーディングしてAWSに簡単にデプロイできるということを知ったので早速勉強してみることにしました。 今回の記事では、Serverless Frameworkのインストールからデプロイまでの流れを簡単にまとめました。 これからServerless Frameworkを使ってみたいという初心者の方向けの内容となっています。  Serverless Frameworkとは Serverless Frameworkはサーバーレスなアプリケーションを簡単に開発、デプロイするためのツールです。 AWS、Azure、GCP等のクラウドサービスによらず利用することができ、クラウドサービスで使用できる言語(AWSであればC#, Node.js, Pythonなど)を利用することができます。 また、デプロイコマンドを実行することでクラウドサービスのリソースを構築することができます。 例えばAWSだと、ローカルで作成したLambdaのスクリプトとあわせて、Lambdaと連携するDynamoDBやAPI Gatewayなどのリソースも構築することができます。 実装 インストール、serverlessテンプレートの作成、デプロイの流れをそれぞれ簡単にまとめました。 インストール インストールの流れは以下になります。 nodeのインストール serverlessのインストール IAMユーザの作成 Serverless FrameworkにIAMユーザを設定 nodeのインストール brew install node serverlessのインストール npm install -g serverless IAMユーザの作成 AWSコンソールでIAMを開き、新しくIAMユーザを作成します。 Serverless FrameworkからAWSにアクセスするため、「プログラムによるアクセス」をチェックします。 既存のポリシーである「AdministratorAccess」を選択し、IAMユーザを作成します。 Serverless FrameworkにIAMユーザを設定 IAMユーザの作成後画面にアクセスキーIDとシークレットアクセスキーが表示されるので、これらを控えます。 ターミナルで以下のコマンド(XXX: アクセスキーID、YYY: シークレットアクセスキー)を実行します。 serverless config credentials --provider aws --key XXX --secret YYY --profile serverless-admin serverlessテンプレートの作成 テンプレート作成のあとに、Lambda関数とserverless.ymlの中身を記述します。 テンプレート作成 以下のコマンドでテンプレートを作成します。 sls create --template aws-python --path [テンプレート名] 使用する言語によって、aws-pythonの箇所をaws-nodejsなどに置き換えます。 Lambda関数の作成 hi !と表示されるだけのスクリプトです。 handler.py def hello(event, context): print("hi !") return "hello-world" serverless.ymlの作成 Lambdaのスクリプトをデプロイするときのクラウドサービスの設定をserverless.ymlに記述します。 serverless.yml provider: name: aws #選択するクラウドサービス runtime: python2.7 #言語のバージョン profile: serverless-admin #IAMユーザをserverlessに設定したときのプロファイル名 region: us-east-1 #リソースを作成するリージョン デプロイ デプロイは以下のコマンドで実行します。 sls deploy -v AWSコンソールでLambdaを開くと、ちゃんとデプロイされていることを確認することができます。 Testをクリックすると、デプロイしたLambda関数の実行内容を確認することができます。 デプロイまでの大まかな流れは以上です。 各種slsコマンド 使いそうなslsコマンドをまとめました。 invoke ターミナル上でLambda関数の実行内容を確認することができます。 sls invoke -f [function名] -l deploy function -f ~ 変更した関数のみデプロイすることができます。 sls deploy -vよりもデプロイに時間がかかりません。 sls deploy function -f [function名] logs ターミナル上でLambda関数の実行ログをリアルタイムに出力することができます。 sls logs -f [function名] -t remove デプロイしたリソースをすべて削除します。 関数だけではなく、CloudWatchのロググループやIAMロールも削除します。 sls remove Lambdaの各種設定におけるserverless.ymlの記述 オプションをserverless.ymlに記述しておくと、関数をデプロイする際にそれらの設定を反映してくれます。 IAM Lambdaはデフォルトで他のAWSサービスへのアクセス権を持っていないので、アクセスが必要な際にはIAMポリシーが必要になります。 S3のデータを取得したり保存したりする場合には、以下のようにiamRoleStatementsを記述します。 serverless.yml iamRoleStatements: - Effect: "Allow" Action: - "s3:ListBucket" Resource: { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref" : "ServerlessDeploymentBucket" } ] ] } - Effect: "Allow" Action: - "s3:PutObject" Resource: Fn::Join: - "" - - "arn:aws:s3:::" - "Ref" : "ServerlessDeploymentBucket" - "/*" メモリ、タイムアウト Lambda関数が実行時に使用するメモリ量やLambda関数が停止するまでに許可される実行時間の設定については、providerにmemorySizeとtimeoutを追記します。 serverless.yml provider: name: aws runtime: python2.7 profile: serverless-admin region: us-east-1 memorySize: 512 timeout: 2 環境変数 Lambdaで使用する環境変数は以下のように設定します。 serverless.yml environment: variable1: value1 おわりに 今度はServerless FrameworkでREST APIの構築をやってみようと思います。 参考資料
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

フロントエンドエンジニア志望のAWS基礎学習〜

はじめに 現在ReactやTypeScript中心に学習しているフロントエンドエンジニア志望として転職活動を行なっている駆け出しエンジニアです。 フロントエンドエンジニアでインフラ技術をメインにさわる事はないと思っていたんですけど、基礎知識を疎かにすると実際の業務で関わってきた時に少なからず必要になってくると思うので、今回は備忘録&アウトプットで学習を進めていこうと思っております! まずインフラって?? 自分でサービスを作れたり、課題に対してシステム全体で対応することができるようになる。また以下のメリットがあります。 自分自身でインフラを構築して、サービスをリリースできるようになる。 開発する際のテスト環境が作れる。 障害があったとき、問題を検知し切り分けることができる。 対応策を考えるとき、アプリケーションだけでなくシステム全体で対応できる。 などなどのメリットがある。 インフラの基本構築 1, サーバーの構成 サーバーを設置、OSやソフトウェアの設定 2, ネットワークの構成 ネットの接続、IPアドレスの範囲決めや割り当て、ドメインとIPアドレスの紐付けなど AWSとは AWS ... 画像でもあるようにamazon web servicesという。Amazon社が提供するクラウドサービス。クラウドサービスとして世界最大規模。 AWSの特徴 サービスの豊富さやリソースの柔軟性、使った分だけ支払う従量課金などの特徴がある。 AWSの代表的なサービス VPC(Virtual Private Cloud) AWSアカウント専用の仮想ネットワーク EC2 (Elastic Compute Cloud) AWS上に仮想サーバーを作るサービス S3(Simple Storage Service) Webサーバーやデータのバックアップ等のストレージとしてデータを保存し保護する Route 53 ドメインにIPアドレスを紐付け情報を提供するサービス 作業用(IAM)/ルートユーザーについて ルートユーザー AWSサービスやリソース全てのアクセス権をもつ特権ユーザー。 アカウントの変更や解約、サポートプランの変更などをするときだけに使用する。極力を使わない。 作業用ユーザー(IAMユーザー) AWSで作成するユーザーで認証情報とアクセス許可を個別に変更できる。 AWSの操作するコンソール画面にログインするときや通常の作業はIAMユーザーを使用する VPC について AWS上に仮想ネットワークを作成できるサービス VPCの基礎知識 リージョン AWSの各サービスが提供されている地域のこと(アメリカ、東京、アフリカ、アイルランドなど) アベイラビリティゾーン 独立したデータセンターのこと。 複数立てることで、他のアベイラビリティゾーンがダメになっても他が補うことでシステムが正常稼働してくれる。 サブネット VPCを細く区切ったネットワーク。 Webサーバーはインターネットから接続でき、DBサーバーは接続できなくする。 IPアドレス ネットワーク上の機器を識別するためのインターネットの住所。 32ビットで構成され、10進数での表現になる。 例)10101100,00010100,00000001,00000001 ? 172.20.1.1 また、IPアドレスはパブリックIPアドレスとプライベートIPアドレスの2種類がある。 パブリックIPアドレス インターネットに接続する際に使用するIPアドレス。重複を防ぐためICANNという団体が管理している。 プライベートIPアドレス インターネットで使用されないIPアドレス。下記の範囲が決まっていて自由に使用が可能。 ルーティング ネットワークとネットワークをIPアドレスを通じて接続できることを言い、ルーターがIPアドレスの行き先を管理している。 また、ルーティング処理を記録して処理を行う際に参照するのが、ルートテーブル(ルーティングテーブル)と言い「宛先のIPアドレス」と「次のルーター(ターゲット)」の書式で設定されている。 画像のルートテーブル(Custom route table)を見ると、 「10.0.0.0/16」のIPアドレスは自身のインターネット(local)に繋がり、 「0.0.0.0/0」となっているIPアドレスは、デフォルトルートと言ってルートテーブルに登録されているIPアドレスにどれにも一致してない経路を指しており、インターネットと接続をするためインターネットゲートウェイと接続する必要がある。 インターネットゲートウェイはVPCとインターネットとの間に通信を可能にする。 ネットワークを構築する作業内容 VPCの基礎知識を用いて、ネットワークを構築する流れが以下のようになります。 ①VPCの作成 ②サブネット作成(パブリック&プライベート作成) ③ルーティング設定(インターネットゲートウェイ&ルートテーブル作成) EC2について AWSクラウド上の仮想サーバー。またEC2では仮想サーバの事をインスタンスという単位で扱います。 数分で起動し、1時間または数秒単位の従量課金で、サーバーの追加・削除、マシンスペック変更も数分で可能。 EC2の基礎知識 AMI AMI(Amazon Machine Image)はインスタンス起動に必要な情報が入ったOSのイメージ。サーバーのテンプレートのようなもの。 インスタンスタイプ サーバーのスペックを定義したもの。 タイプによりCPUやメモリ、ストレージ、ネットワーク帯域が異なる。またスペックによって料金が異なる。 インスタンスファミリーは世代を表しており、数字が大きほど新しい。また、インスタンスサイズはCPUを指します。 ストレージ サーバーに紐付けるデータの保存場所。EC"のストレージには以下の2種類がある。 EBS(Elastic Block Store) 高い可溶性と耐久性を持ち、インスタンスの付け替えが可能なうえ再起動してもデータが保存されている。 EBSの料金は発生する。 インスタンスストア インスタンス専用の一時的なストレージ。インタスタンスの付け替えができず、再起動したらデータがクリアされる。 ただし、料金は無料。 仮想サーバーを作成する作業内容 ES2の基礎知識とSSHでES2インスタンスへの接続やセキュリティの設定を合わせて、以下の作業になります。 ①AMIの選択 ②インスタンスタイプの選択 ③ストレージの追加 ④セキュリティグループの設定 ⑤SSHキーペアの設定 Route 53について AWSのDNSサービス。 DNSというのは、ドメイン名の管理システム。ドメイン名をIPアドレスへ変換し、紐付けをする。 また、以下の二つから構成されている。 ネームサーバー ドメイン名に紐ずくIPアドレスが登録されているサーバー フルリゾルバ どのドメインにIPアドレスが紐づいているか教えてくれるサーバー Route 53の特徴としては、ネームサーバーの役割を果たしており、高可用性100%を示しており、ほぼサーバーが落ちることはないことを示しています。 Route 53でDNSを設定する作業手順 ①ドメインのネームサーバーをRoute 53に変更  Route 53でホストゾーンを作成  ネームサーバーをお名前.comからRoute 53へ変更 ②ドメインに紐づくIPアドレスを登録 Route 53でレコードセットを作成 S3について 安価で耐久性の高いAWSのクラウドストレージサービス。 画像やデータの保管する場所として利用されており、容量無制限で高いデータの耐久性があります。 また、実際に使用した分の料金が発生する従量課金サービスでもあります。 バケットやオブジェクトに対してアクセス制限を設定できる。 バケット オブジェクトの保存場所。バケットを作成し、その配下にデータを格納するイメージ。また複数のバケットを作成することができる。 オブジェクト データ本体を表し、S3に格納されるファイル。また、ファイルにURLが作成される。 キー オブジェクトの格納URLのパスを表す。 データベース構築の作業手順 ①AWS側の準備 ・S3のバケット作成 ・S3の権限を持ったIAMユーザーの作成 ②サイトの設定(WordPress) 参考記事 ドキュメント:https://docs.aws.amazon.com/ja_jp/ 参考記事:https://aws.taf-jp.com/blog/35503 Udemy:https://www.udemy.com/course/aws-and-infra/ 感想 正直なところインフラって何??って感じでずっとおざなりにしていたので今回はAWSという知見からインフラの知識を少し学べました。フロントエンドを学習していく中でインフラの知識がまだまだ浅いので、LinuxやDockerについてもどんどん勉強していきたい意欲が出てきました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSと比較するAzure環境構築(アカウント作成~仮想マシン起動まで)(2021年5月時点)

AWSは知っているがAzure初心者という人は最初はAzureに戸惑うと思います。 私もその一人でした。 そこで、AWSの構築手順を前提としながら、Azureで構築した場合はどのような差異があるかを整理してみました。差異が分かると、Auzreの理解も早まるかと思います。 ■■ 筆者情報 ■■ ・インフラエンジニア ・AWSは8資格取得済み(体験談①)(体験談②)(体験談③) ・AzureはAZ-900:Azure Fundamentals取得済み(体験談) ■■ この記事を読んでほしい対象 ■■ ・AWSの有識者だがAzureは初心者で、Azureに苦戦している人。 ■■ 参照にするドキュメントについて ■■ 今回はそれぞれの公式ユーザガイドをベースとします。 区分 ユーザガイド AWS AWSドキュメント Azure Azureドキュメント ■■ 動作検証の前提 ■■ 今回は仮想マシンを1台起動させてインターネットからの接続を可能にする構成を作成します。 とてもシンプルな環境です。 ただ、このシンプルな環境を比較することで、2つのクラウドの差異が見えてきます。 まずはAWS有識者の方がAzureを利用した時に最初に感じる違和感について簡単に説明します。 以下はAWSとAzureの構成図となります。 メモで記載していますが、地域やAZの設定単位が異なります。 Azureはリソースグループ以下のリソースがすべて個別に地域を設定できます。 また、AZも仮想マシン単位で設定することになります。 AWSと大きく異なるので、ここは意識しておく必要があります。 区分 AWS Azure 課金単位 AWSアカウント単位 サブスクリプション単位 地域単位 Region単位 リソース単位 AZ単位 subnet単位 リソース単位 次にインターネット接続に関しての前提です。 Azureでは当初からインターネット接続が前提となっています。 その為、AWSのようにIGWをアタッチする必要があります。 その前提を認識した上で、以下から設定作業を実施します。 ■■ 初期設定手順 ■■ 初期設定手順の比較になります。 基本的にAWSの初期設定をベースに比較しながら進めました。 ①アカウント登録 クラウドを利用する自分のアカウントを作成します。アカウント登録後から1年間の無料利用枠があるので、やる気になったタイミングで登録することをお勧めします。特にAzureは「開始30日間で¥22,500のクレジット」があります。 区分 手順 12ヵ月無料利用枠 AWS アカウント作成 無料利用枠 Azure アカウント登録 無料利用枠 ②ルートユーザのMFA設定 ルートユーザへの2要素認証設定です。 双方とも同じような処理が必要になります。 区分 手順 機能 AWS ルートユーザのMFA設定 マイセキュリティ資格情報 Azure MicrosotアカウントのMFA設定 Microsoftアカウント AWSのユーザ管理はIAMで実施しますが、ルートユーザはそこにはいません。ルートユーザのMFA設定をする場合は「マイセキュリティ資格情報」からアクセスする必要があります。 AWSのルートユーザに相当するのがAzureのMicrosoftアカウントになります。 Azrueのユーザ管理はAzureADで実施しますが、Microsoftアカウントはそこにはいません。MicrosoftアカウントのMFA設定をする場合は「Microsoftアカウント」からアクセスする必要があります。 ③操作ログ証跡の作成 AWSもAzureも操作ログは初期設定のままで90日間は保存されますが、 それ以上の期間保存したい場合は以下の設定を実施します。 特にAWSに関しては、証跡作成を推奨しています。 区分 手順 機能 ログ保存先 AWS CloudTrail証跡作成 CloudTrail ・S3・CloudWatch Azure ログ保存設定 アクティビティログ-診断設定 ・ストレージ アカウント・Log Analyticsワークスペース・Event Hubs ④請求アラームの設定追加 設定した金額以上に課金が発生した場合に通知してくれる設定を実施します。 AWSもAzureも同じような設定が実施できます。 区分 手順 機能 AWS 請求アラームの設定追加 CloudWatch Azure コストアラートの追加 コストアラート Azureは1つの予算設定の中で下記のように複数のアラートを設定ができ、アラート通知メールも日本語です。AWSは金額単位で個別にアラートを作成する必要があり、メールも英語一択なので、ここはAzureの方が使いやすいと感じました。ただ、AWSはアラートを越えた場合のアクション(サーバを停止する等)を設定できるので、運用面ではAWSにしかないメリットもあります。 ⑤パスワードポリシーの設定 AWSはパスワード条件を設定できます。 Azureはルール固定のため変更できませんが、カスタム禁止パスワードを設定することができます。 区分 手順 機能 AWS パスワードポリシーの設定 IAM Azure カスタム禁止パスワードの構成 AzureAD ⑥管理者ユーザ作成 最初に作成される「ルートユーザ」は普段の作業では使用しないのがAWSのベストプラクティスです。Azureの「Microsoftアカウント」に関しては、特にこの方針はないようですが、作成可能です。 区分 手順 機能 権限 AWS 管理者ユーザ作成 IAM 管理ポリシー「AdministratorAccess」 Azure ⅰ:管理者ユーザ作成 ⅱ:Azureロールの割当 ⅰ:AzureADⅱ:サブスクリプション ⅰ:AzureADロール「グローバル管理者」ⅱ:Azureロール「所有者」 Azure環境は環境別にロールが存在します。AWSのようにIAMロール一択ではありません。どのようなロールが存在するかは「従来のサブスクリプション管理者ロール、Azure ロール、および Azure AD ロール」を参照して下さい。 ⑦管理者ユーザでログイン 作成した管理者ユーザでログインします。これ以降、基本的にルートユーザは利用しません。 区分 手順 機能 AWS 管理者ユーザでログイン IAM Azure Azureにログイン AzureAD ■■ 基本環境作成 ■■ ここから環境構築に入ります。 最初に説明した通り、以下のようなシンプルな構成で作成します。 ①リソースグループの作成 Azureのリソースは必ず1つのリソースグループに所属させる必要があります。 その為、リソースグループを最初に作成する必要があります。 AWSにはこの概念はありません。 区分 手順 機能 AWS なし なし Azure リソースグループの作成 リソースグループ ②仮想ネットワークの作成 仮想ネットワークを作成します。AWSの場合はマネージドコンソール画面でリージョンを指定してからVPCを作成します。Azureはリソース単位でリージョンを設定します。ここが大きな違いです。 区分 手順 機能 リージョンの指定 AWS VPC作成 VPC リソース単位では指定しない Azure 仮想ネットワークの作成 仮想ネットワーク リソース単位で指定する ③サブネット作成 サブネットを作成します。AWSはサブネットにAZを設定しますが、AzureはサブネットとAZはリンクしておらず、仮想マシンを作成する際に設定します。この前提からAzureはAZ障害が発生した場合でもサブネットは死なない、ということになり、単体サブネットの中で仮想マシン単にでAZを変更する構成が可能となります。 区分 手順 機能 AZ AWS ②サブネット作成 VPC-サブネット 複数のAZから1つを選択 Azure 仮想ネットワークの作成 仮想ネットワーク-サブネット - 例えば3つの仮想マシンのAZを分割した冗長化構成にしたい場合は、以下のようになります。 ④インターネットゲートウェイ(IGW)を作成 AWSではIGWを作成します。インターネットに接続する場合はVPCにIGWをアタッチする必要があります。Azureは逆で標準でインターネット接続が可能です。その為、インターネット接続をさせたくない場合にFW等で通信抑止する必要があります。 区分 手順 機能 AWS インターネットゲートウェイ(IGW)を作成 VPC-IGW Azure なし なし ⑤ルートテーブル作成 AWSはDefultルートテーブルとカスタムルートテーブルを選択可能です。 Azureは必ずシステムルートがサブネットに設定されます。変更したい場合はカスタムルートを上書きする形で設定可能です。 区分 手順 機能 AWS ルートテーブル作成 VPC-ルートテーブル Azure ルートテーブル作成※変更が必要な場合実施 仮想ネットワーク-ルートテーブル なお、Azureのシステムルートは以下の通りです。 赤枠で囲っているのがインターネットへの接続設定となります。 ⑥ルートテーブルとIGWの関連付け AWSはルートテーブルにIGWをアタッチすることにより「パブリック用のルートテーブル」になります。 区分 手順 機能 AWS ルートテーブルとIGWの関連付け VPC-ルートテーブル Azure なし なし ⑦ルートテーブルとサブネットの関連付け AWSでは「パブリック用のルートテーブル」を関連付けられたサブネットは「パブリックサブネット」になります。これは、インターネット接続が可能なサブネットになったということです。 Azureは当初からインターネット接続が可能なので、この作業はありません。 区分 手順 機能 AWS ルートテーブルとサブネットの関連付け VPC-サブネット Azure なし なし ⑧セキュリティグループの作成 AWSとAzureの両方ともセキュリティグループを作成します。 RDPのプロトコルの許可を与えます。 区分 手順 機能 AWS セキュリティグループの作成 VPC-セキュリティグループ Azure NSGの作成 NSG なお、FW機能であるセキュリティグループおよびACLの設定内容は以下の通りです。 AWS側は今回の作業ではネットワークACLは利用しません。 ⑨フローログ発行用IAMロールの作成 AWS認定資格試験ではよく登場するフローログですが、出力するためには設定が必要になります。権限付与したIAMロールを作成する必要があります。 一方、AzureにはIAMロールのような必須設定はありません。近いものとしサービスプリンシパルがあります。 区分 手順 機能 AWS フローログ発行用IAMロールの作成 IAM-IAMロール Azure なし なし ⑩フローログの作成 AWSのフローログ作成と比較して、Azureの設定項目は非常に多いと感じました。 複数の資料を確認しないと、設定できないレベルです。 区分 手順 機能 ログ保存先 AWS フローログの作成 VPC,EC2-フローログ CloudWatch(S3も指定可能) Azure ⅰ.Network Watcherの有効化ⅱ.NSG作成ⅲ.NSG フロー ログ設定の有効化 ⅰ.Network Watcherⅱ.サブスクリプションⅲ.Network Watcher Log Analyticsワークスペース ⑪フローログの確認 フローログが可視化できることを確認します。 区分 手順 機能 AWS フローログの確認 Cloudwatch-logs Azure トラフィック分析の表示 Network Watcher-Traffic Analytics ■■ EC2起動と初期設定(WindowsOS) ■■ OSはWindowsを前提とし、私が作業がしやすくなると思う設定を実施しました。また、AWS資格試験で頻出していたフローログの設定も実施しました。 ①キーペア作成 AWSではインスタンスへの接続に必要になるキーペアを作成します。 Azureではキーペアという概念はありません。 VertualMachineを作成する際にユーザとパスワードを入力します。 区分 手順 機能 AWS キーペア作成 EC2 Azure なし なし ②仮想マシンの起動 仮想マシンを起動します。 区分 手順 機能 価格 AWS EC2の起動 EC2 オンデマンド Azure 仮想マシンの追加 Virtual Machines 従量制 AzureとAWSの仮想マシンには幾つか違いがあるので記載します。 ディスク領域について AWSはディスク領域をEBSで設定します。ディスク容量等も設定できます。 Azureはイメージ内にOSディスク領域が含まれており、サイズに一時ディスク領域が含まれています。それぞれを選択すると容量も自動的に決まるため、容量変更はできません。 容量指定が必要な場合は、仮想マシン作成後に「サイズおよびパフォーマンス」からディスクのサイズを変更する必要があります。また、Azureのディスク領域はデフォルトで暗号化されています。 区分 CPU メモリ ディスク AWS 〇 〇 ×(EBS) Azure 〇 〇 〇(C,Dドライブ自動作成、暗号化済)C:OS領域(128GB等、イメージにより固定)D:一時領域(サイズにより固定) もう少しAzureについて補足します。 Azureのイメージについては以下のように表示されており、OSディスクの容量は解りません。 AzureのOSディスクの容量は次のルールがあります。以下はWindows2019の例です。 名前にsmalldiskとついているかどうかで容量が変わります。 イメージ OSディスク容量 Windows Server 2019 Datacenter -Gen 1 128 GB [smalldisk]Windows Server 2019 Datacenter -Gen 1 30 GB Azureの一時ディスクの容量は仮想マシン作成後の「サイズ」画面で表示されます。 データ自体置いてはいけない領域なので、あまり意識する必要はないかと思います。 ※以下の「データディスク」が一時ディスクを指しています。 AZ(可用性ゾーン)について AZについてはAWSがサブネットで設定していますが、Azureは仮想マシン単位で設定します。AzureではAZのことを可用性ゾーンと言います。 Azureには可用性ゾーン以外に可用性セットという冗長化方式もあります。冗長化する場合は、どちか一方を選択する必要があります。Azureの可用性セットはAWSだとスプレッドプレイスメントグループに近いイメージとなります。 その他、以下の設定が必要です。 AzureにはIAMロールのような必須ロール設定はありません。近いものとしサービスプリンシパルがありますが、追加的要素の為、説明は割愛します。 区分 プライベートIP FW設定 ロール AWS IP設定(指定可能) セキュリティグループ IAMロール Azure 自動IP設定(指定不可) NSG なし なお、パブリックIPはAzureもAWSも自動でIP設定されます。 上記の点を考慮して、仮想マシンを作成します。 仮想マシンの作成が完了したら、以下の作業を継続で実施します。 ③プライベートIPアドレスの設定 Azureは仮想マシン作成時にはプライベートIPアドレスを指定できない為、仮想マシン作成後に変更します。 区分 手順 機能 AWS 不要 不要 Azure 静的プライベート IP アドレスを追加 Virtual Machines-Networking ④OSディスクサイズの変更 Azureは仮想マシン作成時にはOSディスクの容量を指定できない為、仮想マシン作成後に変更します。 区分 手順 機能 AWS 不要 不要 Azure OSディスクサイズ変更 Virtual Machines-Disks ⑤仮想マシンへの接続 RDPで接続します。 WindowsのOS環境が起動します。 区分 手順 機能 接続方式 AWS EC2への接続 EC2 RDP Azure WindowsVMへの接続 Virtual Machines RDP ⑥EC2_日本語化対応(OS) 英語のままだと解りにくいのでOSを日本語化します。 ⑦EC2_タイムゾーン変更(OS) 日本時間に変更します。 これで最低限の設定が完了し、利用可能な状況となります。 ■■ 仮想マシン運用上の注意点 ■■ 運用面でAWSと仕様が異なる点があります。 AWSはOSからシャットダウンした場合はインスタンスは停止して課金が止まりますが、AzureはOSからシャットダウンした場合は、課金が止まりません。注意が必要です。 操作 Azure AWS OSからシャットダウンした場合 「停止済み」 (継続課金) 「停止済み」 (課金停止) ポータルからシャットダウンした場合 「停止済み(割り当て解除)」 (課金停止) 「停止済み」 (課金停止) ■■ まとめ ■■ AWSとAzureを比較したながら仮想マシンが起動するところまで記載しました。 AWSの有識者でもAzureだと仕様が異なるところがあり、戸惑うかと思います。 今回の記事を参考にして頂ければと思います。 また、時間があれば監視・バックアップ等に関しても比較資料を作成したいと思います。 以  上
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】 リージョンとアベイラビリティゾーンとは?

はじめに AWSの基礎学習した内容をアウトプットしていきます。 リージョンとは 地理的に離れた領域を示します。 例:東京、大阪、シドニー、ソウル アベイラビリティゾーン(AZ)とは それぞれのリージョン内に設置された地理的、電源、ネットワークが自律しているデータセンターの集合の単位です。 特徴 複数リージョン/AZで、システムを分散配置することで、火災や地震などの災害発生時に障害耐性を高めることができます。 この記事は以下の情報を参考にして執筆しました。 AWS初学者を導く体系的な動画学習サービス「AWS CloudTech」 Regions and Availability Zones
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CloudFormation で VPC の cidr を変更しようとしてみた

内容 CloudFormation で VPC の cidr を変更しようとハマった時のポイントについて記載する。 まず、そもそもの前提として VPC の プライマリの cidr を変更することはできない。(セカンダリとして拡張することは可能。) 参考:Amazon VPC の IPv4 アドレス範囲を変更するにはどうすればよいですか? その前提で、 VPC、サブネットを CloudFormation から変更を試みるとどんな挙動になるのか。 基本的にこの記事は、CloudFormation でエラーが表示されたときにどんな対処をすべきか考えていくためのものです。 構成 検証目的なので、リソースは半端です。実際にスタックを作成してみていただくことをお進めします。 AWSTemplateFormatVersion: 2010-09-09 Description: cidr reduction Resources: #VPC1 Vpc1: Type: AWS::EC2::VPC Properties: CidrBlock: 192.168.0.0/20 EnableDnsSupport: true EnableDnsHostnames: true #Subnet1 Subnet1: Type: AWS::EC2::Subnet Properties: AvailabilityZone: !Select - 0 - !GetAZs Ref: AWS::Region CidrBlock: 192.168.1.0/24 VpcId: !Ref Vpc1 RouteAssociation1: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref RouteTable SubnetId: !Ref Subnet1 #Subnet2 Subnet2: Type: AWS::EC2::Subnet Properties: AvailabilityZone: !Select - 1 - !GetAZs Ref: AWS::Region CidrBlock: 192.168.2.0/24 VpcId: !Ref Vpc1 PriAssociation2: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref RouteTable SubnetId: !Ref Subnet2 #RouteTable RouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref Vpc1 #ELB elb1: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Scheme: internal SubnetMappings: - PrivateIPv4Address: 192.168.1.10 SubnetId: !Ref Subnet1 - PrivateIPv4Address: 192.168.2.10 SubnetId: !Ref Subnet2 Type: network Target1: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckEnabled: true HealthCheckPath: /health_check HealthCheckPort: 80 HealthCheckProtocol: HTTP Name: elbtg TargetType: ip Port: 80 Protocol: TCP VpcId: !Ref Vpc1 PriNlbListener: Type: AWS::ElasticLoadBalancingV2::Listener Properties: DefaultActions: - Type: forward TargetGroupArn: !Ref Target1 LoadBalancerArn: !Ref elb1 Port: 80 Protocol: TCP #VPC2 Vpc2: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 EnableDnsSupport: true EnableDnsHostnames: true #VPCPeer VpcPeer: Type: AWS::EC2::VPCPeeringConnection Properties: VpcId: !Ref Vpc1 PeerVpcId: !Ref Vpc2 ToMainVpcRoute: Type: AWS::EC2::Route Properties: DestinationCidrBlock: 10.0.0.0/16 RouteTableId: !Ref RouteTable VpcPeeringConnectionId: !Ref VpcPeer #SG Sg1: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Sg GroupName: Sg SecurityGroupIngress: - CidrIp: 192.168.0.0/20 FromPort: 80 IpProtocol: tcp ToPort: 80 VpcId: !Ref Vpc1 ##VPCep EC2Vpce: Type: AWS::EC2::VPCEndpoint Properties: PrivateDnsEnabled: true ServiceName: !Sub com.amazonaws.${AWS::Region}.ec2 SecurityGroupIds: - !Ref Sg1 SubnetIds: - !Ref Subnet1 - !Ref Subnet2 VpcEndpointType: Interface VpcId: !Ref Vpc1 UPDATE_FAILED 1 まずしないと思いますが、VPC1 Subnet1 Subnet2 ELB の Cidr を別のネットワークに変更してみた。 次のような理由で、UPDATE_FAILED となった。 CloudFormation cannot update a stack when a custom-named resource requires replacing. Rename XXXXXXXXXXXX and update the stack again. 次のページに書かれている内容を確認してみる。 AWS CloudFormation の「Cannot update a stack when a custom-named resource requires replacing」エラーを解決する方法を教えてください。 まず、CloudFormation の基本的な動作として、 CloudFormation によりリソースの置き換えが発生する場合は、まず置き換え用のリソースを作成し、その後で既存のリソースを削除する動作となっている。 そのため、一時的に新旧 2 つのリソースが同時に並存する形となり、リソース名の重複が許されないリソースについては、既存のリソースが存在している状態で置き換え用のリソースを作成することができない。 今回、カスタム名を利用しているリソースは置き換えが必要であり、いずれかの変更が必要である。 カスタム名は必須でないので、そもそも利用しない。 リネームする。 今回は後者のリネームで対処してみる。 (例) Name: elbtg ↓ Name: elbtg2 UPDATE_FAILED 2 UPDATE_FAILED 1 は解消されたようだが、次は別の問題が記録された。 Resource handler returned message: "The following target groups are in a different VPC than load balancer ロードバランサーが属する VPC と、ロードバランサーに指定したターゲットグループの VPC が異なるためエラーが発生している。 これは、VPC、サブネットの cidr の変更に伴い、VPC、サブネットは置き換えが発生した。 置き換えが発生しないロードバランサーは、旧VPCに属する。 置き換えが発生するターゲットグループは新VPCに属する。 ということになる。 変更セットから、置Z換えが発生するかは確認可能であり、この辺りの考慮が甘かった。 CloudFormation からスタックを更新する場合は、変更セットを利用する。 ドキュメントで置き換えが発生するか(Update requires: Replacement)確認する。 ことが重要だ。 明示的に置き換えが発生するようにロードバランサーのプロパティに Name を入れてみた。 変更セットを確認してみると今度はロードバランサーも置き換えられるようだ。 これでうまくいった、というよりも VPCが新しく作成されると、まるっと入れ替えになるので、やる人も考える人もいないと思うので、トラブルシュートの考え方とし書いておいた。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Bitnamiのロゴを除去する方法

はじめに WordPressブログを作るとき、EC2インスタンスの立ち上げの際、「WordPress power by Bitnami」というAMIを用いると、サイトの右下に以下のようなロゴのリンクが表示されます。これを除去する方法をメモしました。 除去方法 (1) ターミナルでEC2インスタンスに接続 ssh -i KEYFILE.pem bitnami@パブリックIPアドレス (2) 以下のコマンドで、Bitnamiのロゴを非表示 sudo /opt/bitnami/apps/wordpress/bnconfig --disable_banner 1 (3) 以下のコマンドで、Apacheを再起動したら完了 sudo /opt/bitnami/ctlscript.sh restart apache (4) ロゴが消えているか確認
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【2021年4月版】『M5Stack Core2 for AWS - ESP32 IoT開発キット』 入門 後編 〜Getting Started Deep Dive〜

"Getting Started" Deep Dive 前編ではM5Stack Core2の開発環境構築からGetting Startedプログラムを動かしてみて、Core2とスマホアプリ RainMakerの挙動について確認いたしました。 それでは今回は、このプロジェクトの実装についてちょいとソースコードの海へ潜り込んでみましょう。 まずはプロジェクトのフォルダ構成です。 % tree -L 2 . ├── CMakeLists.txt ├── LICENSE ├── Makefile ├── README.md ├── cli │   ├── html │   ├── rainmaker.py │   ├── requirements.txt │   ├── rmaker_cmd │   ├── rmaker_lib │   ├── rmaker_tools │   └── server_cert ├── components │   ├── app_reset │   ├── app_wifi │   ├── button │   ├── core2forAWS │   ├── esp-cryptoauthlib │   ├── esp_rainmaker │   ├── esp_schedule │   ├── json_generator │   ├── json_parser │   ├── qrcode │   └── ws2812_led ├── docs │   ├── Doxyfile │   ├── Makefile │   ├── README.md │   ├── _static │   ├── c-api-reference │   ├── conf.py │   ├── gen-dxd.py │   ├── index.rst │   ├── link-roles.py │   ├── local_util.py │   ├── make.bat │   ├── python-api-reference │   └── requirements.txt ├── main │   ├── CMakeLists.txt │   ├── app_driver.c │   ├── app_main.c │   ├── app_priv.h │   ├── component.mk │   ├── display.c │   ├── display.h │   ├── fan.c │   ├── fan.h │   ├── fan_1.c │   ├── fan_2.c │   ├── fan_3.c │   ├── fan_4.c │   ├── fan_5.c │   ├── fan_6.c │   ├── fan_off.c │   ├── house_off.c │   ├── house_on.c │   ├── hsv2rgb.c │   ├── hsv2rgb.h │   ├── light.c │   ├── light.h │   ├── temperature.c │   ├── temperature.h │   ├── thermometer.c │   └── user_parameters.h ├── partitions_4MB_sec.csv ├── platformio.ini ├── sdkconfig └── sdkconfig.defaults 23 directories, 46 files メインは main フォルダ内のソースコードで、cliやcomponentsはベースとなるツールやライブラリ、docsはまぁそのままドキュメント生成プロジェクトであろうかと思います。 今回は main フォルダの中身についてさらに潜っていきたいと思います。 1. app_*.* → "RainMaker アプリ"の実装 app_*.* を主な部分だけざっと貼り付けますと、 app_driver.c ... esp_err_t app_init(void) { return ESP_OK; } app_priv.h ... #pragma once app_main.c ... static const char *TAG = "app_main"; extern SemaphoreHandle_t spi_mutex; void app_main() { /* Initialize Application specific hardware drivers and * set initial state. */ spi_mutex = xSemaphoreCreateMutex(); Core2ForAWS_Init(); Core2ForAWS_PMU_Init(3300, 0, 0, 2700); display_init(); Core2ForAWS_Button_Init(); /* Initialize NVS. */ esp_err_t err = nvs_flash_init(); ... /* Initialize Wi-Fi. Note that, this should be called before esp_rmaker_init() */ app_wifi_init(); /* Initialize the ESP RainMaker Agent. * Note that this should be called after app_wifi_init() but before app_wifi_start() * */ esp_rmaker_config_t rainmaker_cfg = { .enable_time_sync = false, }; esp_rmaker_node_t *node = esp_rmaker_node_init(&rainmaker_cfg, "ESP RainMaker Device", "Fan"); ... light_init(node); temperature_init(node); fan_init(node); esp_rmaker_schedule_enable(); /* Start the ESP RainMaker Agent */ esp_rmaker_start(); /* Start the Wi-Fi. * If the node is provisioned, it will start connection attempts, * else, it will start Wi-Fi provisioning. The function will return * after a connection has been successfully established */ err = app_wifi_start(POP_TYPE_RANDOM); ... } エラーチェックの箇所や長いコメント、includeなどは割愛させていただきました。ヘッダー2つについては特に特筆することはないと思います。 さて、app_main.cのざっくりの流れとしては、 Core2本体の状態初期化 Wifiの初期化 フラッシュメモリの初期化 RainMaker Agentのインスタンス生成 "機器"の登録("Fan","Light","Temperature")と初期化 RainMaker Agentの立ち上げ Wifiの接続 といった感じです。 RainMaker とやりとりする RainMaker Agent を立ち上げております。 このAgentがCore2とスマホアプリの通信を宜しくラッピングしてくれている、ということであります。まさに "RainMaker アプリ"の実装ですね。 2. display.* → タッチディスプレイの制御 まず display.h で外側から見たモジュールの構造を俯瞰してみましょう。 display.h #ifndef DISPLAY_H #define DISPLAY_H void display_init(); void display_fan_init(); void display_house_init(); void display_temperature_init(void); void display_lights_off(void); void display_lights_on(int h, int s, int v); void display_fan_speed(int s); void display_fan_off(void); void display_fan_on(void); void display_temperature(float c); #endif ここではディスプレイの初期化と表示の切り替え関数を宣言しているようですね。 "Light"のオン/オフで表示が切り替わったり、Fanもオン・オフ、スピードの変化について表示が切り替わるようです。 温度については表示のみ、といった感じでしょうか。 なるほど、大体の構造はわかりました それではヘッダで宣言されている流れに沿って、display.c の中身をざっくりとご紹介いたします。 2-1. LCDおよびタッチセンサー まずは display_init 関数ですね。ここではLCDとタッチセンサーそのものの初期化処理を行なっております。 display.c void display_init() { FT6336U_Init(); Core2ForAWS_LCD_Init(); Core2ForAWS_LCD_SetBrightness(100); } はい、出ましたFT6336U。これが静電容量式タッチセンサーでございます。これの初期化して使用する準備万端、ということですね。 続いてCore2本体のLCDスクリーンの初期化と明るさ最大にしております。 これが画面全体の初期化処理です。この関数は app_main.c から呼ばれております。 2-2. "Fan" 箇所の画面要素定義 続きまして display_fan_init 関数です。 display.c void display_fan_init() { xSemaphoreTake(xGuiSemaphore, portMAX_DELAY); ESP_LOGI(TAG,"configuring the fan"); fan_object = lv_img_create(lv_scr_act(), NULL); lv_img_set_src(fan_object, &fan_off); lv_obj_align(fan_object, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -20, 0); ESP_LOGI(TAG,"configured fan_object"); fan_strength_slider = lv_slider_create(lv_scr_act(), NULL); lv_obj_set_width(fan_strength_slider, 8); lv_obj_set_height(fan_strength_slider, 80); lv_obj_align(fan_strength_slider, fan_object, LV_ALIGN_OUT_RIGHT_MID, 0, 0); lv_obj_set_event_cb(fan_strength_slider, strength_slider_event_cb); lv_slider_set_value(fan_strength_slider, 0, LV_ANIM_OFF); lv_slider_set_range(fan_strength_slider, 0, 5); ESP_LOGI(TAG,"configured fan_strength_slider"); fan_sw1 = lv_switch_create(lv_scr_act(), NULL); lv_obj_set_size(fan_sw1, 60, 20); lv_obj_align(fan_sw1, fan_object, LV_ALIGN_OUT_BOTTOM_MID, 0, 0); lv_obj_set_event_cb(fan_sw1, sw1_event_handler); lv_switch_off(fan_sw1, LV_ANIM_OFF); ESP_LOGI(TAG,"configured fan_sw1"); xSemaphoreGive(xGuiSemaphore); xTaskCreatePinnedToCore(spin_update, "fan", 4096, NULL, 2, NULL, 1); ESP_LOGI(TAG,"fan configured"); } これですこれ、タッチパネルのプログラミングって感じですよね。 ちょっとイメージしづらいとおもいますので、"Fanの箇所"の画像を貼ります。 左上というかメインのFanが後ほどアニメーションしますが、その右の赤い丸がついた上下のスライダーがファンのスピード、下のスライドスイッチがオン・オフを表しています。 このイメージをしつつ流れを掻い摘んでご紹介しますと、 lv_img_create、lv_img_set_src でファン画像の描画 fan_strength_slider = lv_slider_create でスライダーコントロールの生成と描画 lv_obj_set_event_cb(fan_strength_slider, strength_slider_event_cb) でスライダコントロールのイベントハンドラ割り当て fan_sw1 = lv_switch_createでスライドスイッチの生成と描画 lv_obj_set_event_cb(fan_sw1, sw1_event_handler) でスイッチのイベントハンドラ割り当て xTaskCreatePinnedToCoreでFanの画像書き換え非同期タスクの登録=アニメーションの実行 という感じになるかと思います。このFanのサンプルだけでタッチスクリーンのGUIプログラミングの要素が色々汲み取れてしまいますね。素晴らしいです。というか Getting Started にしては詰め込みすぎなんじゃないかと思うくらいです笑 ではさらに、イベントハンドラや非同期タスクの中身について深掘りして参りましょう。 2-2-1. strength_slider_event_cb スライダーイベント スライダーに触れた時のイベントハンドラです。(スライダ小さいのでおじさんの指じゃもうタッチもなかなかしんどいのですが) display.c tatic void strength_slider_event_cb(lv_obj_t * slider, lv_event_t event) { if(event == LV_EVENT_VALUE_CHANGED) { fan_set_speed(lv_slider_get_value(slider)); fan_speed_report(); } } はい、eventでスライダコントロールに割り当てた範囲の"値"が直接、渡してもらえます。で、Fanのスピード変えて、fan_speed_reportで "RainMaker Agent" を通してAWS IoT/MQTT に Fan の速度を通知しています。 地味ですが、イベントハンドラが static 関数というのは今でも健在なんですね〜。 2-2-2. sw1_event_handler ボタンイベント スイッチボタンに触れた時のイベントです。 display.c static void sw1_event_handler(lv_obj_t * obj, lv_event_t event) { if(event == LV_EVENT_VALUE_CHANGED) { fan_set_power(lv_switch_get_state(obj)); fan_power_report(); } } はい、こちらもコントロールに割り当てた値が変化したら"Fanの電源"を切り替えて、電源の状態をAgentに通知してもらっております。 2-2-4. spin_update Fanの回転アニメーション ここではFan画像の切り替えチェックとアニメーションを行なっています。 static void spin_update(void *priv) { int fan_index = 0; int speed_skip=0; while(1) { vTaskDelay(pdMS_TO_TICKS(50)); if(pdTRUE == xSemaphoreTake(xGuiSemaphore, 0)) { if(g_fan_speed && g_fan_power) { if(speed_skip == 0) { lv_img_set_src(fan_object, fanImages[fan_index++]); if(fan_index >= (sizeof(fanImages)/sizeof(*fanImages))) fan_index = 0; speed_skip = 5 - g_fan_speed; } else { speed_skip --; } } else { lv_img_set_src(fan_object, &fan_off); } xSemaphoreGive(xGuiSemaphore); } } } ざっくりと流れを紹介いたしますと、 vTaskDelay(pdMS_TO_TICKS(50));で50tick毎に処理を行う xSemaphoreTakeで画面への書き込み処理が他の処理と衝突しないようにチェック g_fan_speed && g_fan_power でFanがオフなら"fan_off"画像データを書き込む "speed_skip"カウンタが0になったら次のインデクスのfan画像データを書き込む 画像のインデクスが画像数を超えたら0に戻す Fanの速度に応じて"speed_skip"カウンタを増やす という感じです。 キモは、スピードが早い方がカウンタが増えない→スピードが早ければ書き換え回数も早い、というところですね。ちゃんとFanのスピード上げれば画像の更新速度も上がっていき、早くすればスピードに応じたFanのアニメーションが行われるようです。 Fanの回っている感じ、伝わるでしょうか? Getting Started の割にはガチめの演出がされています。 Fanの箇所だけでも色々なギミックがありましたね。タッチディスプレイですしれっきとしたGUIなんですが、やはりサイズ感からか"機器"の"ギミック"に感じますね。いや〜楽しいです。 2-3. "House" 箇所の画面要素定義 さて、Fanだけでも若干お腹いっぱい感がありますがまだまだ続きます。次は "House" の部分です。 先程の画面を思い出していただくために、"House" の部分を貼っておきます。 この箇所の初期設定と初期の描画が以下の処理となっております。 display.c void display_house_init(void) { xSemaphoreTake(xGuiSemaphore, portMAX_DELAY); ESP_LOGI(TAG,"configuring the house"); light_object = lv_img_create(lv_scr_act(),NULL); lv_img_set_src(light_object, &house_off); lv_obj_align(light_object,lv_scr_act(),LV_ALIGN_IN_TOP_LEFT,0,0); window_object = lv_canvas_create(lv_scr_act(),NULL); lv_obj_align(window_object, light_object, LV_ALIGN_CENTER,-CANVAS_WIDTH/2,-20); lv_canvas_set_buffer(window_object, window_buffer, CANVAS_WIDTH, CANVAS_HEIGHT, LV_IMG_CF_INDEXED_1BIT); lv_canvas_set_palette(window_object,0,LV_COLOR_TRANSP); lv_canvas_set_palette(window_object,1,LV_COLOR_RED); lv_color_t c; c.full = 1; lv_canvas_fill_bg(window_object,c,LV_OPA_100); lv_obj_move_background(window_object); lv_img_set_src(light_object, &house_off); lv_obj_align(light_object,lv_scr_act(),LV_ALIGN_IN_TOP_LEFT,0,0); xSemaphoreGive(xGuiSemaphore); ESP_LOGI(TAG,"house configured"); } light_object = lv_img_createで画像オブジェクトが生成されて、lv_img_set_src(light_object, &house_off);にて、house_offの画像データが初期表示されます。ここまではなんてことのない処理です。 ここで特筆すべきは次の window_object = lv_canvas_create です。house_offの画像とは別に window_object が透明色で用意されています。。。窓の部分だけ、別なのは・・・?! この効果については後ほど述べたいと思います。 2-4. "Temperature" 箇所の画面要素定義 続いて温度計の部分の表示処理についてご紹介いたします。 例によって該当部分の画像を貼ります。 で、ここの表示処理は以下のようになっております。 display.c void display_temperature_init(void) { xSemaphoreTake(xGuiSemaphore, portMAX_DELAY); ESP_LOGI(TAG,"configuring the temperature"); temperature_object = lv_img_create(lv_scr_act(),NULL); lv_img_set_src(temperature_object, &thermometer); lv_obj_align(temperature_object,lv_scr_act(),LV_ALIGN_IN_BOTTOM_RIGHT,0,-10); thread_object = lv_canvas_create(lv_scr_act(),NULL); lv_obj_align(thread_object, temperature_object, LV_ALIGN_IN_TOP_LEFT,15,0); lv_canvas_set_buffer(thread_object, temperature_buffer, THREAD_WIDTH, THREAD_HEIGHT, LV_IMG_CF_INDEXED_1BIT); lv_canvas_set_palette(thread_object,0,LV_COLOR_GRAY); lv_canvas_set_palette(thread_object,1,LV_COLOR_ORANGE); lv_color_t c; c.full = 0; lv_canvas_fill_bg(thread_object,c,LV_OPA_100); lv_obj_move_background(thread_object); lv_obj_t *label = lv_label_create(lv_scr_act(), NULL); lv_obj_align(label, temperature_object, LV_ALIGN_IN_RIGHT_MID, -75, -15); lv_label_set_align(label,LV_LABEL_ALIGN_CENTER); lv_label_set_text(label, "Internal\nTemperature"); temperature_label = lv_label_create(lv_scr_act(),NULL); lv_obj_align(temperature_label, label, LV_ALIGN_OUT_BOTTOM_MID, 0, 5); lv_obj_set_width(temperature_label,75); _lv_obj_set_style_local_ptr(temperature_label, LV_OBJ_PART_MAIN, LV_STYLE_TEXT_FONT, &lv_font_montserrat_16); /*Set a larger font*/ lv_label_set_align(temperature_label,LV_LABEL_ALIGN_CENTER); lv_label_set_text(temperature_label,""); xSemaphoreGive(xGuiSemaphore); ESP_LOGI(TAG,"temperature configured"); } この温度計画面、派手なイベントはないですがGUIでのテキスト表示とテキストの動的な変更のエッセンスが詰まっております。地味だけど重要、な箇所ですね。 詳しい処理内容はよくわかりませんが、ざっくりと以下のような流れでしょうか temperature_object = lv_img_createとlv_img_set_src(temperature_object, &thermometer);にて温度計画像の配置 thread_object = lv_canvas_createとlv_canvas_set_palette(thread_object,0,LV_COLOR_GRAY);、lv_canvas_set_palette(thread_object,1,LV_COLOR_ORANGE);で温度計のカラーバーを設置 lv_label_set_text(label, "Internal\nTemperature");で固定テキストの設置 temperature_label = lv_label_create(lv_scr_act(),NULL);で温度の表示用テキストエリアを定義 ということで、温度計のバーの部分と温度のテキストは動的に更新できる準備を行なっています。 2-5. display_lights_off, display_lights_on 続いて"Light"のオンオフの処理を見てみましょう。 display.c void display_lights_off(void) { ESP_LOGI(TAG,"lights off"); xSemaphoreTake(xGuiSemaphore, portMAX_DELAY); lv_img_set_src(light_object, &house_off); xSemaphoreGive(xGuiSemaphore); } まずはオフの時の表示切り替えです。これは簡単ですね。house_offの画像をソースに指定してます。 続いてオンの場合です。 display.c void display_lights_on(int h, int s, int v) { xSemaphoreTake(xGuiSemaphore, portMAX_DELAY); lv_color_t c = lv_color_hsv_to_rgb(h,s,v); lv_canvas_set_palette(window_object,1,c); lv_img_set_src(light_object, &house_on); xSemaphoreGive(xGuiSemaphore); } スイッチがオンの場合の処理では引数にHSVカラーを受け取り、lv_color_hsv_to_rgbにてRGBに変換した後、lv_canvas_set_paletteにて窓部分の塗りつぶしパレットの色を更新しています。このように窓の部分の色をリモコンに追随させています。 で、house_onの画像に差し替えています。 このようにオンの処理で窓の部分の色を変更しています。 2-6. display_fan_speed, display_fan_off, display_fan_on Fan の表示切り替え部分の処理は以下のようになっております。 display.c void display_fan_speed(int s) { lv_slider_set_value(fan_strength_slider,s,LV_ANIM_OFF); ESP_LOGI(TAG,"fan spinning %d",s); g_fan_speed = s; } void display_fan_off() { ESP_LOGI(TAG,"fan off"); lv_switch_off(fan_sw1, LV_ANIM_OFF); g_fan_power = false; } void display_fan_on() { ESP_LOGI(TAG,"switch on"); lv_switch_on(fan_sw1, LV_ANIM_OFF); g_fan_power = true; } Fanの画面要素についてはコントロールとイベントハンドラがバインドされているのでコントロールのプロパティを変更するだけでOKですね。 2-7. display_temperature さて、温度計部分の表示処理です。以下のようになっております。 display.c void display_temperature(float c) { const float maxTemp_c = 100.0; const float minTemp_c = 0.0; int rect_height = (int)(((float)THREAD_HEIGHT * (c - minTemp_c)) / (maxTemp_c - minTemp_c)); xSemaphoreTake(xGuiSemaphore, portMAX_DELAY); lv_color_t tc; tc.full = 0; lv_canvas_fill_bg(thread_object,tc,LV_OPA_100); tc.full = 1; for(int x=0;x<THREAD_WIDTH;x++) { for(int y=0;y<rect_height;y++) { lv_canvas_set_px(thread_object,x,THREAD_HEIGHT-y,tc); } } lv_label_set_text_fmt(temperature_label,"%dC",(int)c); xSemaphoreGive(xGuiSemaphore); } ついにCanvasに対して直接、描画する処理が出てまいりました。 rect_heightで温度に応じた矩形の高さを求め、lv_canvas_fill_bgでいったん背景をクリアにするか塗りつぶし、lv_canvas_set_pxで1点ずつ描画しているように見えますね。lv_color_tの使い方やパレットカラーの使い方がわからないのでなんとなくですが。。。 そして、lv_label_set_text_fmtにて、floatで渡された温度cを%dで整数として表示するようにしています。 表示の処理は大体、以上となります。 説明は省略しておりましたが各所でxGuiSemaphoreをチェックして描画処理がバッティングしないようにしております。xSemaphoreTakeとxSemaphoreGiveでセマフォを取ったりあげたりしているわけです。 なるほど、大変だこりゃ。 3. fan.* → "Fan機器"の制御 いよいよやって参りましたFan機器の制御部分です。 まず、タッチパネル画面に表示する画像データを定義するファイルがいくつかありますが、以下では中身の解説は省略致します。 "fan_1.c"〜"fan6.c"、"fan_off.c"などのファイルでは画像データがベタ書きされております。これについては特にいうことはないかと思います。以降の機器についても画像データを定義する *.c ファイルがありますがこれについての紹介は省略させていただきます。 ではまず、fan.h の中身で全体像を把握致しましょう。 fan.h ... #include <esp_rmaker_core.h> void fan_init(esp_rmaker_node_t *node); void fan_set_speed(int speed); void fan_set_power(bool power); void fan_power_report(void); void fan_speed_report(void); ... RainMakerエージェントに対する初期化処理と、パワーのオンオフ、スピードの変更処理に加えて、パワーの状態とスピードの状態を通知する処理があるようですね。 ではそれぞれの処理について見ていきましょう。 3-1. fan_init "Fan機器"の初期化処理です。以下のようになっております。 fan.c void fan_init(esp_rmaker_node_t *node) { /* Create a Fan device and add the relevant parameters to it */ fan_device = esp_rmaker_fan_device_create("Fan", NULL, DEFAULT_FAN_POWER); esp_rmaker_device_add_cb(fan_device, fan_cb, NULL); esp_rmaker_device_add_param(fan_device, esp_rmaker_speed_param_create(ESP_RMAKER_DEF_SPEED_NAME, DEFAULT_FAN_SPEED)); esp_rmaker_node_add_device(node, fan_device); display_fan_init(); } esp_rmaker_fan_device_createで"Fan機器"の定義を行なっております。関数がFan機器専用になっておりますのでこの中身について軽く触れておきましょう。 components/esp_rainmaker/src/standard_types/esp_rmaker_standard_devices.c esp_rmaker_device_t *esp_rmaker_fan_device_create(const char *dev_name, void *priv_data, bool power) { esp_rmaker_device_t *device = esp_rmaker_device_create(dev_name, ESP_RMAKER_DEVICE_FAN, priv_data); if (device) { esp_rmaker_device_add_param(device, esp_rmaker_name_param_create(ESP_RMAKER_DEF_NAME_PARAM, dev_name)); esp_rmaker_param_t *primary = esp_rmaker_power_param_create(ESP_RMAKER_DEF_POWER_NAME, power); esp_rmaker_device_add_param(device, primary); esp_rmaker_device_assign_primary_param(device, primary); } return device; } esp_rmaker_device_createで機器の登録を行い、ESP_RMAKER_DEF_NAME_PARAM=名称パラメータとESP_RMAKER_DEF_POWER_NAME=電源パラメータを追加、そして電源パラメータの方を"primary_param"に"assign"しています。primary_paramの具体的な効能はわかりませんが、これが"主たるパラメータ"なのでしょう。 さて元のfan_initに戻りましょう。 続いて重要な処理がesp_rmaker_device_add_cbです。スマホのRainMakerアプリ上での操作に対するコールバック関数を指定しています。 このコールバック関数については次に紹介します。 続いてesp_rmaker_device_add_paramで"Fan機器"に対して、ESP_RMAKER_DEF_SPEED_NAME=スピードパラメタを追加しています。 そしてこれらの機器設定をまとめて、esp_rmaker_node_add_deviceでRainMaker Agentに通知しています。 これらの処理が完了したのち、display_fan_init()を呼び出して表示の初期化処理を行なっております。 Fan機器の初期化の処理については以上ですね。あの振動モーターは特別な初期化処理なしで使えるのでしょう。 ではコールバック関数について紹介いたします。 3-1-1. fan_cb コールバック関数は以下のようになっております。 fan.c static esp_err_t fan_cb(const esp_rmaker_device_t *device, const esp_rmaker_param_t *param, const esp_rmaker_param_val_t val, void *priv_data, esp_rmaker_write_ctx_t *ctx) { if (ctx) { ESP_LOGI(TAG, "Received write request via : %s", esp_rmaker_device_cb_src_to_str(ctx->src)); } const char *device_name = esp_rmaker_device_get_name(device); const char *param_name = esp_rmaker_param_get_name(param); if (strcmp(param_name, ESP_RMAKER_DEF_POWER_NAME) == 0) { ESP_LOGI(TAG, "Received value = %s for %s - %s", val.val.b? "true" : "false", device_name, param_name); fan_set_power(val.val.b); } else if (strcmp(param_name, ESP_RMAKER_DEF_SPEED_NAME) == 0) { ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name); fan_set_speed( val.val.i); } else { /* Silently ignoring invalid params */ return ESP_OK; } esp_rmaker_param_update_and_report(param, val); return ESP_OK; } いろいろと処理を行なっているように見えますがキモはparam_nameの値によってfan_set_powerかfan_set_speedを呼び出しています。パラメタ名に応じた処理関数の呼び出しを切り替えているわけです。 またここで処理に応じて値の"データ型"が変わるので、val.val.bかval.val.iかを渡すのも切り替えています。 3-2. fan_set_speed fan_set_speedはスピードが変化した時の機器の制御処理です。 fan.c void fan_set_speed(int speed) { g_fan_speed = speed; if(g_fan_power) { Core2ForAWS_Motor_SetStrength(g_fan_speed * 20); } display_fan_speed(g_fan_speed); } 振動モーターの強さを変えて表示を変えているだけですね。 これだけではつまらないのでCore2ForAWS_Motor_SetStrengthの中身も紹介します。 3-2-1. Core2ForAWS_Motor_SetStrength モーターの制御はここで行なっています。 components/core2forAWS/core2forAWS.c void Core2ForAWS_Motor_SetStrength(uint8_t strength) { static bool motor_state = false; if (strength > 100) { strength = 100; } uint16_t volt = (uint32_t)strength * (AXP192_LDO_VOLT_MAX - AXP192_LDO_VOLT_MIN) / 100 + AXP192_LDO_VOLT_MIN; Axp192_SetLDO3Volt(volt); if (strength == 0 && motor_state == true) { motor_state = false; Axp192_EnableLDO3(0); } else if(motor_state == false) { motor_state = true; Axp192_EnableLDO3(1); } } AXP192が振動モーターのようです。で、渡されたstrengthに応じた電圧を計算して、Axp192_SetLDO3Voltしてます。 motor_stateはstaticで状態が保存されるようになっており、voltが0になったらAxp192_EnableLDO3(0)でモーターオフ、そうでなければAxp192_EnableLDO3(1)でモーターがオンになるようにしております。 なるほど、電圧の高さを調整することで振動モーターの振動の強さとオンオフ同時に制御してるんですね。 3-3. fan_power_report, fan_speed_report RainMaker Agent を通じてMQTTによるパラメタの通知を行います。 fan.c void fan_power_report(void) { esp_rmaker_param_update_and_report( esp_rmaker_device_get_param_by_type(fan_device, ESP_RMAKER_PARAM_POWER), esp_rmaker_bool(g_fan_power)); } void fan_speed_report(void) { esp_rmaker_param_update_and_report( esp_rmaker_device_get_param_by_type(fan_device, ESP_RMAKER_PARAM_SPEED), esp_rmaker_int(g_fan_speed)); } esp_rmaker_param_update_and_reportが通知する関数ですが、ここでも通知する"値の型"に応じてesp_rmaker_boolやesp_rmaker_intなどのように値のシリアライズ?方法が変わるようです。 3-4. fan_set_power パワーのオンオフした場合の処理です。 fan.c void fan_set_power(bool power) { g_fan_power = power; if (power) { int speed = g_fan_speed * 20; ESP_LOGI(TAG,"power up, speed=%d",speed); Core2ForAWS_Motor_SetStrength(speed); display_fan_on(); } else { Core2ForAWS_Motor_SetStrength(0); display_fan_off(); } } パワーがオンの時に初期スピードを設定して振動モーターをオンにし、パワーがオフの場合は振動モーターの強さ0にしています。 同時に表示の切り替え処理も呼び出しております。 "Fan機器"の制御は以上です。 4. hsv2rgb.* → HSVとRBGの色空間変換 ここではこの変換アルゴリズムについて本質ではないので実装をさらっと紹介して終わります。 hsv2grb.c uint32_t hsv2rgb(uint16_t h, uint8_t s, uint8_t v) { h = (uint32_t)((uint32_t)h * 255) / 360; s = (uint16_t)((uint16_t)s * 255) / 100; v = (uint16_t)((uint16_t)v * 255) / 100; uint8_t r, g, b; uint8_t region, remainder, p, q, t; if(s == 0) { return v<<24|v<<16|v<<8; } region = h / 43; remainder = (h - (region * 43)) * 6; p = (v * (255 - s)) >> 8; q = (v * (255 - ((s * remainder) >> 8))) >> 8; t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8; switch(region) { case 0: r = v; g = t; b = p; break; case 1: r = q; g = v; b = p; break; case 2: r = p; g = v; b = t; break; case 3: r = p; g = q; b = v; break; case 4: r = t; g = p; b = v; break; default: r = v; g = p; b = q; break; } return r<<16|g<<8|b; } これはもう、こういうことですね・・・。はい。 5. light.* → "Light機器"の制御 Light機器の制御処理についてついて見ていきましょう。 例によって light.h にて全体像の把握からです。 light.h #include <esp_rmaker_core.h> void light_init(esp_rmaker_node_t *node); void light_set_on(bool on); void light_set_hue(int hue); void light_set_saturation(int hue); void light_set_brightness(int brightness); bool light_is_on(void); int light_get_hue(void); int light_get_saturation(void); int light_get_brightness(void); なるほど、照明の調光は Core2 本体では行えないので、スマホからの指示を受けて制御するのみとなっておりますね。 5-1. light_init "Light機器"の初期化処理は以下のようになっております。 light.c void light_init(esp_rmaker_node_t *node) { display_house_init(); Core2ForAWS_Sk6812_Init(); Core2ForAWS_Sk6812_SetBrightness(255); light_set_on(false); /* Create a Light device and add the relevant parameters to it */ light_device = esp_rmaker_lightbulb_device_create("Light", NULL, DEFAULT_LIGHT_POWER); esp_rmaker_device_add_cb(light_device, light_cb, NULL); esp_rmaker_device_add_param(light_device, esp_rmaker_brightness_param_create(ESP_RMAKER_DEF_BRIGHTNESS_NAME, DEFAULT_LIGHT_BRIGHTNESS)); esp_rmaker_device_add_param(light_device, esp_rmaker_hue_param_create(ESP_RMAKER_DEF_HUE_NAME, DEFAULT_LIGHT_HUE)); esp_rmaker_device_add_param(light_device, esp_rmaker_saturation_param_create(ESP_RMAKER_DEF_SATURATION_NAME, DEFAULT_LIGHT_SATURATION)); esp_rmaker_device_add_attribute(light_device, "Serial Number", "012345"); esp_rmaker_device_add_attribute(light_device, "MAC", "xx:yy:zz:aa:bb:cc"); esp_rmaker_node_add_device(node, light_device); } Fan機器とほぼ同様ですが、ざっくりと流れをご紹介いたします。 esp_rmaker_lightbulb_device_createでLight機器の定義 esp_rmaker_device_add_cbでコールバックを登録 BRIGHTNESS、HUE、SATURATIONのパラメタを追加 "Serial Number"、"MAC"の"属性値"(読み取り専用)を追加 Agent にLight機器を通知 esp_rmaker_device_add_attributeにて属性が追加できるのですね。 続いてコールバックについてもさっとご紹介いたします。 5-1-1. light_cb コールバックは以下のようになっております。 light.c static esp_err_t light_cb(const esp_rmaker_device_t *device, const esp_rmaker_param_t *param, const esp_rmaker_param_val_t val, void *priv_data, esp_rmaker_write_ctx_t *ctx) { if (ctx) { ESP_LOGI(TAG, "Received write request via : %s", esp_rmaker_device_cb_src_to_str(ctx->src)); } const char *device_name = esp_rmaker_device_get_name(device); const char *param_name = esp_rmaker_param_get_name(param); if (strcmp(param_name, ESP_RMAKER_DEF_POWER_NAME) == 0) { ESP_LOGI(TAG, "Received value = %s for %s - %s", val.val.b? "true" : "false", device_name, param_name); light_set_on(val.val.b); } else if (strcmp(param_name, ESP_RMAKER_DEF_BRIGHTNESS_NAME) == 0) { ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name); light_set_brightness(val.val.i); } else if (strcmp(param_name, ESP_RMAKER_DEF_HUE_NAME) == 0) { ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name); light_set_hue(val.val.i); } else if (strcmp(param_name, ESP_RMAKER_DEF_SATURATION_NAME) == 0) { ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name); light_set_saturation(val.val.i); } else { /* Silently ignoring invalid params */ return ESP_OK; } esp_rmaker_param_update_and_report(param, val); return ESP_OK; } ここでも基本はパラメタに応じて呼び出す処理とデータ型の指定です。bool型は val.val.b、int型はval.val.iとなっております。 5-2. light_set_on Light機器のメインとなる電源オン・オフの処理です。 light.c void light_set_on(bool on) { isOn = on; if(on) { //uint32_t color = hsb_to_rgb_int(hue,saturation,brightness); uint32_t color = hsv2rgb(hue,saturation, brightness); Core2ForAWS_Sk6812_SetSideColor(SK6812_SIDE_LEFT, color); Core2ForAWS_Sk6812_SetSideColor(SK6812_SIDE_RIGHT, color); Core2ForAWS_Sk6812_Show(); display_lights_on(hue,saturation,brightness); } else { Core2ForAWS_Sk6812_SetSideColor(SK6812_SIDE_LEFT, 0); Core2ForAWS_Sk6812_SetSideColor(SK6812_SIDE_RIGHT, 0); Core2ForAWS_Sk6812_Show(); display_lights_off(); } } やっていることはシンプルですね。 オンの場合は、HSVからRGBを求めて、LEDであるSK6812に色指定をして点灯、画面の更新、です。 オフの場合は、LEDを"真っ黒にして点灯"=消灯、画面の更新、です。 Core2ForAWS_Sk6812_SetSideColorとCore2ForAWS_Sk6812_Showについても、ご紹介いたします。 5-2-1. Core2ForAWS_Sk6812_* → LEDの制御 LEDの制御部分についても簡単にご紹介します。 components/core2forAWS/core2forAWS.c ... void Core2ForAWS_Sk6812_SetSideColor(uint8_t side, uint32_t color) { if (side == SK6812_SIDE_LEFT) { for (uint8_t i = 5; i < 10; i++) { np_set_pixel_color(&px, i, color << 8); } } else { for (uint8_t i = 0; i < 5; i++) { np_set_pixel_color(&px, i, color << 8); } } } ... void Core2ForAWS_Sk6812_Show() { np_show(&px, RMT_CHANNEL_0); } ... 面白いのはnp_set_pixel_colorに渡すインデクス0〜4が右側のLED、5〜9が左側のLEDとなっている箇所、そしてuint32_tのcolorを8bitシフトして先頭から24bitの整数として渡していますね。 そしてCore2ForAWS_Sk6812_Showではnp_showでpxの色データを送信している模様です。 プログラムやデータが回路の構造に合わせて調整されているのがよくわかります。 5-3. Setter/Getter 残りの関数は Setter/Getter となっておりますのでさっとご紹介いたします。 light.c void light_set_hue(int h) { hue = h; light_set_on(true); } void light_set_saturation(int s) { saturation = s; light_set_on(true); } void light_set_brightness(int b) { brightness = b; light_set_on(true); } bool light_is_on(void) { return isOn; } int light_get_hue(void) { return hue; } int light_get_saturation(void) { return saturation; } int light_get_brightness(void) { return brightness; } 後半のGetterは特筆するべきことはないですが、前半のlight_set_hue、light_set_saturation、light_set_brightnessのSetterではそれぞれ値をセットした後にlight_set_on(true);が呼ばれており、上記でご紹介いたしましたLEDの点灯処理が走っております。 Light機器では調光処理の呼び出しはSetter側からキックで統一している、ということですね。 6. temperature.* → "Temperature"機器の制御 いよいよ最後の機器である "Temperature"についてです。 早速、temperature.hを見て見ましょう。 temperature.h #include <esp_rmaker_core.h> void temperature_init(esp_rmaker_node_t *node); はい、温度計に関しては"見るだけ"なのでも、外部から見える処理は初期化しかありません。 それでは実装はどうなっているのでしょうか。見ていきましょう。 6-1. temperature_init 温度センサーは読み取り専用ですが非常に重要な機能である"タイマーによる定時観測"を行う実装を含んでおります。 さて肝心の初期化処理は以下のようになっております。 temperature.c void temperature_init(esp_rmaker_node_t *node) { MPU6886_Init(); /* Create a Temperature Sensor device and add the relevant parameters to it */ temp_sensor_device = esp_rmaker_temp_sensor_device_create("Temperature Sensor", NULL, DEFAULT_TEMPERATURE); esp_rmaker_node_add_device(node, temp_sensor_device); /* Start the update task to send the temperature every so often */ esp_timer_create_args_t sensor_timer_conf = { .callback = temperature_sensor_update, .dispatch_method = ESP_TIMER_TASK, .name = "temperature_sensor_update_tm" }; if (esp_timer_create(&sensor_timer_conf, &sensor_timer) == ESP_OK) { esp_timer_start_periodic(sensor_timer, 250000U); } display_temperature_init(); } まずMPU6886_Init();にて6軸モーションセンサー兼温度センサーである "MPU6886"の初期化処理が行われます。 続いてesp_rmaker_temp_sensor_device_createで"Temprature機器"の宣言とAgentへの通知が行われます。これについてはもういいでしょう。 さて、次の箇所ですね。esp_timer_create_args_tでタスクを定義し、esp_timer_createでタイマーの作成、esp_timer_start_periodicでタイマーの開始、の手続きとなっております。 esp_timer_start_periodicの第二引数は"マイクロ秒"です。つまりここでは250msを指定している、ということでしょう。 このような手順で定時監視のタスクを作成するようです。 そしてdisplay_temperature_initで画面表示の初期化処理が呼び出されます。 それではタイマーで呼び出されるタスクの実装を見て見ましょう。 temperature.c static void temperature_sensor_update(void *priv) { const int reportReload = REPORTING_PERIOD * 4; static int reportingCount = reportReload; float temperature; float avg_temperature = 0; MPU6886_GetTempData(&temperature); avg_temperature = floatFIR(temperature); display_temperature(avg_temperature); reportingCount --; if(!reportingCount) { esp_rmaker_param_update_and_report( esp_rmaker_device_get_param_by_type(temp_sensor_device, ESP_RMAKER_PARAM_TEMPERATURE), esp_rmaker_float(avg_temperature)); reportingCount = reportReload; } } MPU6886_GetTempDataで温度データを読み込んでいます。 その後、floatFIRという処理を行なっており、temperatureについてなんらかの処理を行なってavg_temperatureとしています。この処理の中身については本質ではないので触れないでおきましょう。 まぁ、"観測データの補正"を行なっているのでしょう。 続いて、"display_temperature"で温度計部分の表示の書き換え処理を呼び出しています。 その後、reportingCountを減算し、ゼロになったら esp_rmaker_param_update_and_report で温度の値をブロードキャストしています。 画面の表示とアプリへの通知はタイミングが違う、というか毎度、AWSにあげるのはコストが高いので何回かに1回に通知処理を呼び出すようにしているようです。 以上でざっくりではございますが、Getting Startedプロジェクトに含まれる機器の制御処理についてご紹介いたしました。 まとめ Getting Started、いやはや侮るなかれでございます。Getting Startedにしては大変、中身の濃いというか極めて重要な基本機能がいろいろてんこ盛りでございました。 "機器"が3つも出てきますがそれぞれ以下のようなポイントがあるかと思います。 Light: スマホからの制御、画像とキャンバスでの塗りつぶしの重ね合わせ、LEDの制御、機器の"属性値"の設定 Fan: スマホとタッチスクリーンの双方向での制御、画像切り替えによるアニメーション、GUIコンポーネント(スイッチ、スライダー)、振動モーターの制御 Temperature: ESPでの高精度タイマー、キャンバスへの直接描画、文字列の表示制御、MPU6886センサー値の読み取り いや〜Getting Startedなのにめちゃくちゃ濃いプロジェクトでした。 センサーというかチップによって扱いや振る舞いが異なるので、それぞれしっかりと取り扱い方を押さえておかなければなりませんね。。。 またRainMakerのおかげでスマホとのやり取りに関してはほぼ気にすることなく処理が書けるかと思います。 まだまだ触ってみた、だけのレベルではございますが、M5Stack Core2 入門 後編はここまでにしたいと思います。 お疲れ様でした!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】WordPressとMySQLでブログを構築しよう

構成図 それでは順に作っていきましょう! 1. AWSへログイン 2. 東京リージョンになっていることを確認 3. VPCを作成(IP:10.0.0.0/21) ■ルート コンソールで「VPC」と検索→左ペイン内の「VPC」を選択→「VPCを作成」を選択 4. サブネットを作成(IP:10.0.0.0/24, 10.0.2.0/24) ■ルート コンソールで「VPC」と検索→左ペイン内の「サブネット」を選択→「サブネットを作成」を選択 Public Subnetを作成 WordPressに使うサブネットを作成します。 Private Subnetを作成 RDB(MySQL)に使うサブネットを作成します。 5. Publicサブネット内にEC2を構築 ■ルート コンソールで「EC2」と検索→左ペイン内の「インスタンス」を選択→「インスタンスを起動」を選択 ■ステップの流れ STEP1 Amazon Linux 2 AMI STEP2 t2.micro STEP3 「ネットワーク」、「サブネット」、「パブリックIP」を変更 STEP4 そのままでOK STEP5 Name=WEBSERVER1で設定 STEP6 セキュリティグループを変更 STEP7 キーペアの作成 6. Publicサブネットをインターネットに接続するためにInternet Gatewayを作成 ■ルート コンソールで「VPC」と検索→左ペイン内の「インターネットゲートウェイ」を選択→「インターネットゲートウェイの作成」を選択 これではVPCとアタッチできていないので、インターネットへ接続できません。 なのでアタッチさせましょう! これでアタッチしました。 7. EC2がインターネット接続するためにルートテーブルを作成 ■ルート コンソールで「VPC」と検索→左ペイン内の「サブネット」を選択→「Public-Subnet1」を選択→「ルートテーブル」を選択→「ルート」へ移動→「ルートを編集」を選択 8. SSH接続でログイン ターミナル // ①キーペアがあるところへ移動 $ cd desktop // ②キーペア発見 $ ls -l keypair.pem -rw-r--r--@ 1 ryo staff 1704 5 1 14:38 keypair.pem // ③権限を400に変更 $ chmod 400 keypair.pem // ④SSH接続 $ ssh -i keypair.pem ec2-user@(パブリックIPアドレス) __| __|_ ) _| ( / Amazon Linux 2 AMI ___|\___|___| 9. PrivateサブネットにRDSを構築 RDSには、エンドポイント通信という機能がありました。 もし通信障害などが発生して、親のRDSが使えなくなった時子のRDSに接続してくれる機能です。 つまり、このことから異なるAZにサブネットがないとRDSは使えません。 ということで複数のサブネットにまたがる形でRDSは構築されるので、 サブネットグループというものが必要になります。 ■ルート コンソールで「RDS」と検索→左ペイン内の「サブネットグループ」を選択→「DB サブネットグループを作成」を選択 それでは次に、DBを作成していきましょう。 ■ルート コンソールで「RDS」と検索→左ペイン内の「データベース」を選択→「データベースの作成」を選択 次にRDSで作ったセキュリティグループを修正します。 ■ルート コンソールで「VPC」と検索→左ペイン内の「セキュリティグループ」を選択→「RDS-SG-1」を選択 DBは重要な情報が入っているため誰でも彼でもアクセスできると困ります。 なので、PublicサブネットのEC2(セキュリティグループ→WEB-SG-1)からしか触れないように修正します。 10. EC2にWordPressを導入 ターミナル // 権限が足りないので権限をrootに移動 $ sudo su - // EC2のパッケージを最新の状態にアップデート $ yum -y update // WordPressが動くために必要なツールをダウンロード(PHP, Apache, MySQL) $ amazon-linux-extras install php7.2 -y $ yum -y install mysql httpd php-mbstring php-xml gd php-gd // Apacheが再起動後も自動的に動くようにする $ systemctl enable httpd.service // Apacheをスタート状態に $ systemctl start httpd.service // カレントディレクトリにWordPressの最新パッケージを入れる $ wget http://ja.wordpress.org/latest-ja.tar.gz ~/ // あるか確認する $ ls -l total 16076 -rw-r--r-- 1 root root 16458939 Apr 21 00:00 latest-ja.tar.gz(あった) // 拡張子がgzなので展開しましょう $ tar zxvf ~/latest-ja.tar.gz // ディレクトリごと/var/www/htmlへコピーする $ cp -r ~/wordpress/* /var/www/html/ // /var/www/htmlをapacheのユーザーに権限変更 $ chown apache:apache -R /var/www/html 11. WordPressが開けるか確認 ■ルート コンソールで「EC2」と検索→左ペイン内の「インスタンス」を選択→「パブリックIPアドレス」をコピー パスワードは自分が決めたパスワードを入力してください。 データベースのホスト名は、RDSのエンドポイントとなります。 入れました!! 成功です!!!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

超初心者がAWSについて勉強してみた①~サブネット編~

概要 アラフォーのAWS初心者が学んだことをつらつら書いていきます。 今回の目標 サブネットを作成する。 教材 AWS CloudTechで学びはじめました。 AWSを学びたい人は心者でも丁寧にまた安価(参考書1冊分+コーヒー2缶)で学べるのでお勧めです。 前提 VPC編が完了していること。 用語集 構築するのに最低限必要な用語を書きます。 ★アベイラビリティーゾーン(通称;AZ) データセンタの集合群のこと。AWSの東京リージョンでは、通常3つ使用できる。 障害に備えて、一つのシステムを複数のAZで使用(マルチAZ)ということもできる。 ★サブネット 1つのネットワークを小さく分割した小規模のネットワークと思ってもらえれば。 理解するのはそんなに難しいことではないが、言語化が困難なので、ググってもらえれば分ると思います。 ★パブリックサブネット 公開用のサブネット。外部(インターネット)から接続できる機能を持たせたサブネット。 ★プライベートサブネット 非公開用のサブネット。外部(インターネット)からの接続ができないようにしているサブネット 構成図 今回作成する構成図となります。作成する部分は赤枠で囲った部分になります。 サブネットについて 若干解説します。 10.0.0.0/21のネットワークを/24のサブネットに分割する場合について見ていきます。 VPCには、10.0.0.0/21のネットワークが設定してあります。これをさらに、/24のネットワークに分割して、そのネットワーク内でIPアドレスを割り当てていきます。/21や/24は何を表しているかというと、ビット数でネットワークを決めています。図にするとわかりやすいですかね。。 ちなみにAWSでは一つのVPCにデフォルト200個までサブネットを作成できるようです。サブネットが/24で200個のサブネットを作成する場合、VPCは/16にする必要があります。 サブネット作成 ではサブネットを作成していきましょう。 まずパブリックサブネット10.0.0.0/24を作成します。ここではパブリック(公開用)の機能を持たせるわけではないので、後々パブリックサブネットになるサブネットを作成するんだなということをとどめておいてください。 まず、AWSのマネージメントコンソールでVPCを検索してVPCのダッシュボードを開きます。 そしてサブネットを選択します。 サブネット作成を押します。 以下入力・選択します。 VPC・・・test-vpc サブネット名・・・Public_subnet_1a_0 アベイラビリティーゾーン・・・アジアパシフィック(東京)/ap-northeast-1a IPV4 CIDRブロック・・・10.0.0.0/24 サブネットを作成を押します。 はい、作成されましたね。念のため、作成した内容に間違いないか確認しましょう。間違っていた場合、サブネットを編集する画面がなかったので、アクションから一度削除していただき、再度作成するしかないようです。 続きまして、同じようにプライベートサブネットを作成します。プライベートサブネットは作成した時点で非公開なので、そのままプライベートサブネットになります。 サブネット作成ボタンを押した後、以下を入力します。内容はパブリックサブネットと同様なので、画像は省略します。 VPC・・・test-vpc サブネット名・・・Private_subnet_1a_2 アベイラビリティーゾーン・・・アジアパシフィック(東京)/ap-northeast-1a IPV4 CIDRブロック・・・10.0.2.0/24 最後に、プライベートサブネットが正しく作成されたか確認します。 はい、作成されました。 次回は、Public_subnet_1a_0に公開機能を持たせるべくインターネットゲートウェイの作成・ルートテーブルの設定を実施していきます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Lambdaによるリアルタイムデータ処理は本当にコストが高いのか?

1.はじめに IoTデバイスデータの収集や計測を行う等のリアルタイム性の高いシステムを構築する場合、 LambdaよりEC2を利用した方がコストメリットが大きくなる場合があると聞きますが、 どのくらいの規模からコストが逆転するのか?疑問だったので試算してみました。 今回は、ストレージやデータ通信の料金は含まず、 EC2 または Lambdaを利用した場合のコンピューティング料金だけに焦点を当て考えてみます。 2.比較方法 次の2つのアーキテクチャについてコンピューティング料金を試算することでコスト比較を行ってみたいと思います。 ① EC2 構成 ※Lambdaと同等の可用性を確保するという前提条件でEC2はマルチAZ構成とします。 ② Lambda 構成 3.コスト試算 ① EC2 コスト 汎用ワークロード向けのM5インスタンスを利用した場合の月額コストを試算してみます。 月額コスト = 時間単価(※1) x 24時間 x 30日 x 2インスタンス(※2) ※1 オンデマンド料金 ※2 マルチAZ構成 インスタンス名 vCPU メモリ 時間単価 月額(マルチAZ) m5.large 2 8GiB 0.124USD 178.56USD m5.xlarge 4 16GiB 0.248USD 357.12USD m5.2xlarge 8 32GiB 0.496USD 714.24USD m5.4xlarge 16 64GiB 0.992USD 1428.48USD m5.8xlarge 32 128GiB 1.984USD 2856.96USD EC2料金:https://aws.amazon.com/jp/ec2/pricing/on-demand/ ② Lambda コスト Lambda実行時間 = 200ms/リクエスト とした場合の月額コストを試算してみます。 月額コスト = リクエスト料金(※1) + 実行時間料金(※2) ※1 リクエスト料金 = リクエスト単価 x リクエスト数 / 100万リクエスト ※2 実行時間料金 = 時間単価 x 実行時間 x Lambdaメモリ / 1024MB リクエスト数 月額(128MB) 月額(256MB) 月額(512MB) 100 RPS 159.9USD 267.9USD 483.9USD 200 RPS 319.7USD 535.7USD 967.7USD 300 RPS 479.6USD 803.6USD 1451.6USD 400 RPS 639.4USD 1071.4USD 1935.4USD 500 RPS 799.3USD 1339.3USD 2419.3USD Lambda料金:https://aws.amazon.com/jp/lambda/pricing/ コスト比較 m5.2xlarge インスタンスで 300 RPS のデータを処理するケースで比較してみましょう。 Lambdaメモリが128MBの場合は、Lambdaコスト < EC2コストとなりますが、 Lambdaメモリが256MBの場合は、Lambdaコスト > EC2コストとなり、コストが逆転します。 Lambdaのコストとして大きな割合を占めるのが実行時間料金となる為、 Lambdaが常時実行される場合は、コンピューティング料金の割高感が否めない結果となりました。 逆に実行時間が短い場合は、Lambdaのメリットを最大限に活かすことが出来そうです。 各サービスの特徴を理解して選択することが重要ですね。 4.まとめ Lambdaが常時実行されるようなユースケースの場合は、コンピューティング料金だけを比較するとEC2 より Lambdaの方が高額となる傾向にあると思います。 ただ、リアルタイム性の高いシステムでも1時間に1回通信をする等の場合は、Lambdaの実行時間が短くなる為、Labmdaの方がコストメリットがあると思います。 EC2 と Lambda を選択するときは、リクエスト頻度だけではなく実行時間を考慮して、アーキテクチャを選択することが重要だと思います。 今回は、EC2 と Lambda のコンピューティング料金に焦点を当て考えてみましたが、本当に前提条件が1つ異なるだけで違う結果になると思います。 一般的な事例だけで判断するのではなく、まずは一度比較検してみてはどうでしょうか? 個々のユースケースに応じてベストな選択は、きっと変わるはず!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Amazon Lightsail でハニーポット (T-Pot 20.06) を構築

はじめに Amazon Lightsail にハニーポットである T-Pot 20.06 をインストールしました。 本記事では、T-Pot の構築方法について説明します。 インスタンスの選定 インスタンスタイプについて 結論として、システム要件を満たしつつ安価に利用できる Lightsail を使用することにしました。 システム要件は System Requirements に記載されています。 Depending on the installation type, whether installing on real hardware or in a virtual machine, make sure the designated system meets the following requirements: 8 GB RAM (less RAM is possible but might introduce swapping / instabilities) 128 GB SSD (smaller is possible but limits the capacity of storing events) Network via DHCP A working, non-proxied, internet connection これを満たすインスタンスの料金を EC2 と Lightsail で比較しました。 インスタンスタイプ 料金 EC2 (t3a.large, On-demand) $72.83/month EC2 (t3a.large, RI 1年, 前払いなし) $45.04/month EC2 (t3a.large, RI 3年, 前払いなし) $23.73/month Lightsail (8GB メモリ) $40/month 3年のリザーブドインスタンスが最も安いですが、個人の趣味の範囲で3年後もハニーポットを運用している自信が無かったため、Lightsail を選択しました。 また、EC2 のオンデマンドインスタンスよりも Lightsail の方が安価であることは予想できましたが、1年のリザーブドインスタンスよりも安いというのは意外でした。 OS について Debian 10.8 (buster)でインスタンスを起動しました。 これは、インストールドキュメントの Post-Install User には以下のように記載されており、T-Pot が Debian 10 上で動作することを前提としているためです。 In some cases it is necessary to install Debian 10 (Buster) on your own: また、Amazon Linux 2 と Ubuntu でもインストールを試みましたが、それぞれ以下の理由によりインストールができませんでした。 Amazon Linux 2 の場合 T-Pot のインストーラーが apt を前提としています。そのため、パッケージマネージャとして yum を採用している Amazon Linux 2 は対応していませんでした。 Ubuntu 20.04 の場合 パッケージマネージャとして apt を採用している Ubuntu でもインストールは不可能でした。 T-Pot のインストーラーを実行したところ、インストーラー内で OS のチェックをしており、Debian focal (Ubuntu 20.04)はサポートしていないというエラーメッセージが表示されました。 sudo ./install.sh --type=auto --conf=tpot.conf [sudo] password for user: ### Checking for root: [ OK ] ### Installing apt-fast --2021-04-30 23:44:30-- https://raw.githubusercontent.com/ilikenwf/apt-fast/master/apt-fast Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.111.133, 185.199.110.133, ... Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 22286 (22K) [text/plain] Saving to: ‘/usr/local/sbin/apt-fast’ /usr/local/sbin/apt-fast 100%[===================================================================================================================>] 21.76K --.-KB/s in 0s 2021-04-30 23:44:30 (51.9 MB/s) - ‘/usr/local/sbin/apt-fast’ saved [22286/22286] ### Checking for installer dependencies: [ OK ] Aborting. Debian focal is not supported. T-Pot のインストール T-Pot をインストールします。 USERNAME=new-user-name # ユーザ名を設定します sudo apt update && sudo apt upgrade -y sudo apt install git sudo adduser ${USERNAME} sudo gpasswd -a ${USERNAME} sudo sudo su ${USERNAME} # SSH の設定 ## 接続元のローカル PC 側で事前にキーペアを作成してください ## $ ssh-keygen -t ed25519 cd ${HOME} mkdir .ssh vim .ssh/authorized_keys # 公開鍵を設定 chmod 700 .ssh chmod 600 .ssh/authorized_keys # T-Pot のインストール git clone https://github.com/dtag-dev-sec/tpotce cd tpotce/iso/installer/ cp tpot.conf.dist tpot.conf vim tpot.conf # myCONF_WEB_USER と myCONF_WEB_PW に管理画面のユーザ名とパスワードを指定します。 sudo ./install.sh --type=auto --conf=tpot.conf sudo reboot 管理用ポートの開放 T-Pot をインストール後に再起動した時点で SSH のポートが変更されます。そのため、 22 番ポートで SSH 接続ができなくなります。 そこで、以下のポートで管理用途のアクセスができるように設定します。 - 64295 (SSH 用) - 64297 (Web 管理画面用) また、念の為に接続元 IP アドレスを自宅のみに制限しています。 管理画面へのアクセス Web ブラウザで https://<IPアドレス>:64297/ を開きます。 「この接続ではプライバシーが保護されません」と表示されますが、「詳細設定」から「<IPアドレス> にアクセスする(安全ではありません)」を選択してください。 インストールに成功していた場合、以下のような画面が表示されます。 攻撃を受けるためのポート開放 1~64000 番ポートを全世界に開放します。 動作確認 ポートを開放してから数分で攻撃を観測することができました。 追加の設定 追加で2点、設定を変更します。 ホスト名の設定 T-Pot インストール後に SSH 接続すると、ホスト名が roughblackboard に変更されています。 この状態では sudo コマンド実行すると sudo: unable to resolve host roughblackboard: Name or service not known というエラーが発生します。 そこで、/etc/hosts を編集し、名前解決ができるようにしました。 $ sudo vim /etc/hosts #127.0.1.1 ip-172-26-12-88.ap-northeast-1.compute.internal ip-172-26-12-88 127.0.1.1 ip-172-26-12-88.ap-northeast-1.compute.internal ip-172-26-12-88 roughblackboard スワップの作成 T-Pot を起動した時点で既にメモリの使用率が高く、システムが安定しませんでした。 free コマンドでメモリの使用量を確認してみると、約80%程度使用している事が分かります。 $ free -m total used free shared buff/cache available Mem: 7979 6402 147 21 1429 1355 Swap: 0 0 0 そこで、スワップメモリを作成し、有効化します。 Debian 10 でスワップを作成する方法 - Tutorial Crawler を参考に設定しました。 sudo fallocate -l 8G /swapfile # 8GB のスワップファイルを作成します sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0 0' | sudo tee -a /etc/fstab echo 'vm.swappiness = 10' | sudo tee -a /etc/sysctl.conf sudo sysctl -p スワップメモリが正常に追加されました。 $ free -m total used free shared buff/cache available Mem: 7979 6416 148 21 1414 1343 Swap: 8191 0 8191 まとめ T-Pot の構築方法について説明しました。 また、ハニーポットを運用していく上で何か知見があれば投稿しようと思っています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

S3の機能だけで、数GBある複数ファイルを1つのzipファイルにまとめる方法

概要 目的:数GB分の複数ファイルをS3から取得、Lambdaで1つのzipファイルにまとめる 環境:AWS Lambda, S3, Java8(どの言語でもできますが、サンプルの都合でJavaを使います) 実現方法:無圧縮zip, S3マルチパートアップロード機能 構成の概要 実現すること こんな要件があったとします。 数GB分のファイルがS3に配置されていて、それを1つのzipファイルにまとめたい。 既存機能の都合でVPCやECSは使えないため、LambdaとS3だけで実現したい。 一見すると単純ですが、(普通は)実現できない構成です。 参考:要件の構成をSAMのYAMLファイルにしたもの(クリックで開きます) template.yaml AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-10-31 Description: SAM Resources: S3Bucket: Type: "AWS::S3::Bucket" Properties: BucketName: !Sub "zip-lambda-create-${AWS::StackName}" JavaLambdaFunction: Type: AWS::Serverless::Function Properties: CodeUri: build/distributions/zip_s3_create.zip Handler: zip_s3_create.Handler Runtime: java8 Description: Java function MemorySize: 512 Timeout: 900 Environment: Variables: S3_BUCKET: !Ref S3Bucket Policies: - S3CrudPolicy: BucketName: !Ref S3Bucket 難しい理由 難しい理由は2つあります。 ・ファイルが大きすぎること  → Lambdaのストレージ(/tmpディレクトリ)には512MBの制限があります。  → 数GBのzipを作ろうとすれば容量不足になります。 ・LambdaがVPC外にあること  → EFS(Lambdaのストレージを増やすサービス)を使えば、512MBの制限を超えるファイル操作ができます。  → EFSを使うには条件があり、LambdaがVPCの中にあることが必要です。 ですので、このLambdaで数GBのzipファイルを作ることはできません。 それならどうするのか Lambdaの中で作ることができないので、S3のマルチパートアップロード機能を使って、S3に無圧縮zipファイルを作らせます。 マルチパートアップロードって何? 複数のファイルをアップロードすることで、S3がそれぞれのファイルを結合して、一つのファイルを作る機能です。 「Hello,」と書いたテキストファイルと、「World」と書いたテキストファイルをそれぞれアップロードすると、S3に「Hello,World」と書いたテキストファイルが1つ保存されるようなイメージです。 どの言語でも実装できる機能ですが、AWSの公式ではJavaのサンプルが充実しています。 【マルチパートアップロードのコピー】 https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/CopyingObjctsMPUapi.html ※「最後のパートを除いて、送信する一つのパートは5MB以上であること」の制限があるため、実際には「Hello,」ほど小さなファイルは送れません。 無圧縮zipって何? 圧縮をかけないzip形式は単純な構造をしていて、まとめる前のデータをそのまま並べたようなバイナリになります。 ただ、そのまま並べると展開した後のファイル名などがわからないので、「ローカルファイルヘッダ」として格納しています。 ローカルファイルヘッダには、いくつかの定数と、ファイルパス、ファイルの日時、CRC32、ファイルサイズを書き込みます。 セントラルディレクトリに書き込む情報は、ローカルファイルヘッダとほとんど同じです。 つまり、以下のような実装にすれば、S3のマルチパートアップロードで無圧縮zipを作ることができます。 詳細なzipの仕様はここでは省略します。ソースコードにあるJavaのソースと、こちらをご参照ください。 公式の仕様(英語) 「略して仮」さんの日本語の解説 シーケンス Lambdaの実装は、S3からファイルを取ってきて、少しだけ情報を足して、S3へのスルーパスを繰り返す形になります。 例えば3つのファイルを圧縮してzipにする処理をシーケンスとしてまとめ直すと、以下のようになります。 ソースコード ソースコードはこちらです。※右向き三角をクリックすると開きます CRC32はLambda内でも計算できるのですが、データ全体を読み込む必要があるため時間がかかります。 今回はあらかじめS3にアップロードする時点で計算しておいて、CRCをMetadataとして登録しています。 Lambdaのソースコード:実際の処理ロジック:Handler.java Lambdaのソースコード(Handler.java) public class Handler implements RequestHandler<Map<String, String>, String> { // マルチパートアップロードの仕様で、(最後のパートを除いて)5MB未満のパートのアップロードはできない private static long FILE_SIZE_5MB = 5L * 1024 * 1024; // メタデータにCRC32の値を設定しておく(アップロード時に指定しておく) private static String USER_METADATA_CRC32 = "crc32"; /** * Lambdaのエントリポイント */ public String handleRequest(Map<String, String> event, Context context) { // 出力するzipファイル名 String outputFileName = "export.zip"; // 並行処理するスレッド数(大きいほどメモリ量が大きくなるのでLambdaの設定に合わせる) int pararelThreadCount = 5; // 接続するバケット名 String s3BucketName = System.getenv("S3_BUCKET"); // リソースファイルのあるS3内のフォルダ名 String resourceFolderName = "resources"; try { // 処理を実行する execute(s3BucketName, resourceFolderName, outputFileName, pararelThreadCount); // 処理成功をレスポンスとして返す return new String("200 OK"); } catch (RuntimeException ex) { // 例外をログ出力 ex.printStackTrace(); // サーバエラーをレスポンスとして返す return new String("500 ERROR"); } } /** * zip化処理の実行 * * @param s3BucketName 接続するバケット名 * @param resourceFolderName 処理対象のフォルダパス * @param outputFileName 出力するzipファイル名 * @param pararelThreadCount 並行処理するスレッド数 */ public void execute(String s3BucketName, String resourceFolderName, String outputFileName, int pararelThreadCount) { try { // 並列実行のスレッドを管理する ExecutorService executor = Executors.newFixedThreadPool(pararelThreadCount); // S3への接続クライアントを取得(ローカルなら.awsの設定, クラウドならロール)から取得する AmazonS3 client = AmazonS3ClientBuilder.defaultClient(); // アップロードするファイルにContent-Type : application/zipを設定する ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType("application/zip"); // マルチパートアップロードを初期化 InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(s3BucketName, outputFileName).withObjectMetadata(metadata); InitiateMultipartUploadResult initResult = client.initiateMultipartUpload(initRequest); // etagの一覧を格納する配列(マルチスレッドで格納するのでsynchronizedにしておく) List<PartETag> etagList = Collections.synchronizedList(new ArrayList<>()); // S3にある対象ファイルを一覧で取得する ListObjectsV2Result targetFileList = client.listObjectsV2(s3BucketName, resourceFolderName); List<Future<Optional<ZipHeader>>> uploadResultList = targetFileList.getObjectSummaries().stream() // 5MBに満たないファイルはzip格納の対象外とする .filter(targetFile -> targetFile.getSize() >= FILE_SIZE_5MB) // 5MB以上の全ての対象ファイルに対して、マルチスレッドでzip格納処理を適用する .map(targetFile -> { return executor.submit(() -> { // 非同期処理の実行結果 ZipHeader header = null; // 読み込みストリームを開く S3Object object = client.getObject(targetFile.getBucketName(), targetFile.getKey()); // メタデータを参照する ObjectMetadata meta = client.getObjectMetadata(targetFile.getBucketName(), targetFile.getKey()); try (S3ObjectInputStream input = object.getObjectContent()) { // オンメモリに書き込みストリームを用意する try (ByteArrayOutputStream headerBytes = new ByteArrayOutputStream()) { // ファイルヘッダを出力 header = new ZipHeader(targetFile.getKey(), BigInteger.valueOf(targetFile.getSize()), // メタデータからCRC32を参照する(アップロード時に設定しておく) Long.valueOf(meta.getUserMetaDataOf(USER_METADATA_CRC32))); BigInteger headerSize = header.writeLocalFileHeaderToBuffer(headerBytes); // ファイルヘッダの大きさを登録 header.setChunkSizeFromFileSize(headerSize); // 書き込みストリームを読み込みストリームに変換、ファイルデータを後ろにつける try (SequenceInputStream writeStream = new SequenceInputStream( headerBytes.toInputStream(), input)) { // パート番号を取得する int partNumber = targetFileList.getObjectSummaries().indexOf(targetFile) + 1; // 書き込みを実行、実行結果はetagの一覧として格納する etagList.add(client.uploadPart(new UploadPartRequest() // バケットを指定 .withBucketName(s3BucketName) // ファイル名を指定 .withKey(outputFileName) // ファイルサイズを指定 .withPartSize(header.getChunkSize().longValue()) // アップロードファイルの書き込みストリームを指定 .withInputStream(writeStream) // マルチパートアップロード:アップロードIDを指定 .withUploadId(initResult.getUploadId()) // マルチパートアップロード:パートに連番をつける .withPartNumber(partNumber)).getPartETag()); } } } catch (Exception e) { // 例外をログ出力 e.printStackTrace(); // 処理に失敗したのであればOptional.nullを返す header = null; } // 非同期処理の実行結果を返す return Optional.ofNullable(header); }); }) // 実行中のマルチスレッド処理を配列に変換する .collect(Collectors.toList()); // マルチスレッドへの格納を終了する executor.shutdown(); // 成功した処理だけを格納する List<ZipHeader> zipHeaders = new ArrayList<ZipHeader>(); for (Future<Optional<ZipHeader>> future : uploadResultList) { future.get().ifPresent(header -> { zipHeaders.add(header); }); } // 最後の処理を追加、書き込みストリームを用意する try (ByteArrayOutputStream headerBytes = new ByteArrayOutputStream()) { // 各ファイルのセントラルディレクトリ情報を出力 MutableInt offset = new MutableInt(); MutableInt centralDirectorySize = new MutableInt(); zipHeaders.forEach(header -> { // 各ファイルのセントラルディレクトリヘッダを出力 BigInteger centralHeaderSize = header.writeCentralDirectoryHeaderToBuffer(headerBytes, offset.getValue()); centralDirectorySize.add(centralHeaderSize); offset.add(header.getChunkSize()); }); // 終端にあるセントラルディレクトリ情報を出力 zipHeaders.get(0).writeEndOfCentralDirectoryHeaerToBuffer(headerBytes, centralDirectorySize.getValue(), offset.getValue(), BigInteger.valueOf(zipHeaders.size())); // パート番号を取得する int partNumber = targetFileList.getObjectSummaries().size() + 1; // 書き込みを実行、実行結果はetagの一覧として格納する etagList.add(client.uploadPart(new UploadPartRequest() // バケットを指定 .withBucketName(s3BucketName) // ファイル名を指定 .withKey(outputFileName) // ファイルサイズを指定 .withPartSize(headerBytes.size()) // アップロードファイルの書き込みストリームを指定 .withInputStream(headerBytes.toInputStream()) // マルチパートアップロード:アップロードIDを指定 .withUploadId(initResult.getUploadId()) // マルチパートアップロード:パートに連番をつける .withPartNumber(partNumber)).getPartETag()); // 完了通知を送信 client.completeMultipartUpload(new CompleteMultipartUploadRequest(s3BucketName, outputFileName, initResult.getUploadId(), etagList)); } } catch (Exception e) { // 処理中の例外はランタイム例外に変換して投げる throw new RuntimeException(e); } } } Lambdaのソースコード:zipのヘッダを作るクラス:ZipHeader.java zipのファイルヘッダを作るクラス(ZipHeader.java) public class ZipHeader { // ローカルファイルヘッダ private static String LOCAL_FILE_HEADER_SIGNATURE = "50,4B,03,04"; // セントラルディレクトリヘッダ private static String CENTRAL_FILE_HEADER_SIGNATURE = "50,4B,01,02"; // 終端セントラルディレクトリヘッダ private static String END_OF_CENTRAL_FILE_HEADER_SIGNATURE = "50,4B,05,06"; // 作成情報(Windows, Zip Version 1.0) private static String CREATE_INFO = "0A,00"; // Zip Version 1.0 private static String ZIP_VERSION = "0A,00"; // 圧縮オプション private static String OPTION = "00,08"; // 圧縮アルゴリズム(無圧縮) private static String ALGORITHM = "00,00"; // エクストラフィールド長 private static String EXTRA_FIELD_LENGTH = "00,00"; // コメント長 private static String COMMENT_LENGTH = "00,00"; // ディスク分割 private static String NO_DISK_SEPARATE = "00,00"; // ファイルタイプ private static String FILE_TYPE = "00,00"; // ファイル権限情報 private static String FILE_PERMISSION = "00,00,00,00"; private String mFileName; private BigInteger mFileSize; private long mCrc; private LocalDateTime mDate; private BigInteger mChunkSize; public ZipHeader(String fileName, BigInteger fileSize, long crc) { mFileName = fileName; mFileSize = fileSize; mCrc = crc; mDate = LocalDateTime.now(); } public void setChunkSizeFromFileSize(BigInteger headerSize) { mChunkSize = mFileSize.add(headerSize); } public BigInteger getChunkSize() { return mChunkSize; } private String integerToBinaryString(long value, int length) { return String.format(String.format("%%%ds", length), Long.toBinaryString(value)).replace(" ", "0"); } private void writeBinaryString(OutputStream stream, String binaryString, MutableInt length) throws Exception { int bytes = binaryString.length() / 8; for (int i = (bytes - 1); i >= 0; i--) { String oneByte = binaryString.substring(i * 8, (i + 1) * 8); stream.write(Integer.parseUnsignedInt(oneByte, 2)); } length.add(bytes); } private void appendLastModeFileDateTime(OutputStream stream, MutableInt length) throws Exception { LocalDateTime date = mDate; // 時分秒 String hour = integerToBinaryString(date.getHour(), 5); String minute = integerToBinaryString(date.getMinute(), 6); String second = integerToBinaryString(date.getSecond() / 2, 5); writeBinaryString(stream, hour + minute + second, length); // 年月日 String year = integerToBinaryString(date.getYear() - 1980, 7); String month = integerToBinaryString(date.getMonthValue(), 4); String day = integerToBinaryString(date.getDayOfMonth(), 5); writeBinaryString(stream, year + month + day, length); } private void appendCRC32(OutputStream stream, MutableInt length) throws Exception { String binary = integerToBinaryString(mCrc, 32); writeBinaryString(stream, binary, length); } private void appendBytesFromString(OutputStream stream, String data, MutableInt length) { Arrays.asList(data.split(",")).forEach((hex) -> { try { stream.write(Hex.decodeHex(hex)); length.add(1); } catch (DecoderException | IOException e) { } }); } private void appendFileSize(OutputStream stream, MutableInt length) throws Exception { String binary = integerToBinaryString(mFileSize.longValue(), 32); writeBinaryString(stream, binary, length); writeBinaryString(stream, binary, length); } private void appendFileName(OutputStream stream, MutableInt length) throws Exception { String fileNameLength = integerToBinaryString(mFileName.length(), 16); writeBinaryString(stream, fileNameLength, length); } private void appendBuffer(OutputStream stream, byte[] buffer, MutableInt length) throws Exception { stream.write(buffer); length.add(buffer.length); } /** * ファイルヘッダを出力する * * @param stream 出力先ストリーム */ public BigInteger writeLocalFileHeaderToBuffer(OutputStream stream) { try { MutableInt lengthBuffer = new MutableInt(); // ローカルファイルヘッダを登録 this.appendBytesFromString(stream, LOCAL_FILE_HEADER_SIGNATURE, lengthBuffer); // Versionを登録 this.appendBytesFromString(stream, ZIP_VERSION, lengthBuffer); // 圧縮オプションを登録 this.appendBytesFromString(stream, OPTION, lengthBuffer); // 無圧縮アルゴリズムを登録 this.appendBytesFromString(stream, ALGORITHM, lengthBuffer); // 最終更新日時を登録 this.appendLastModeFileDateTime(stream, lengthBuffer); // CRCを登録 this.appendCRC32(stream, lengthBuffer); // 圧縮後サイズを登録 this.appendFileSize(stream, lengthBuffer); // ファイル名の長さを登録 this.appendFileName(stream, lengthBuffer); // エクストラフィールド長を登録 this.appendBytesFromString(stream, EXTRA_FIELD_LENGTH, lengthBuffer); // ファイル名を登録 this.appendBuffer(stream, mFileName.getBytes(), lengthBuffer); // データ長を返却 return lengthBuffer.getValue(); } catch (Exception ex) { throw new RuntimeException(ex); } } /** * セントラルディレクトリヘッダを出力する * * @param stream 出力先ストリーム * @param fileOffset ファイルのオフセット位置 */ public BigInteger writeCentralDirectoryHeaderToBuffer(OutputStream stream, BigInteger fileOffset) { try { MutableInt lengthBuffer = new MutableInt(); // セントラルディレクトリヘッダを登録 this.appendBytesFromString(stream, CENTRAL_FILE_HEADER_SIGNATURE, lengthBuffer); // 作成情報を登録 this.appendBytesFromString(stream, CREATE_INFO, lengthBuffer); // Versionを登録 this.appendBytesFromString(stream, ZIP_VERSION, lengthBuffer); // 圧縮オプションを登録 this.appendBytesFromString(stream, OPTION, lengthBuffer); // 無圧縮アルゴリズムを登録 this.appendBytesFromString(stream, ALGORITHM, lengthBuffer); // 最終更新日時を登録 this.appendLastModeFileDateTime(stream, lengthBuffer); // CRCを登録 this.appendCRC32(stream, lengthBuffer); // 圧縮後サイズを登録 this.appendFileSize(stream, lengthBuffer); // ファイル名の長さを登録 this.appendFileName(stream, lengthBuffer); // エクストラフィールド長を登録 this.appendBytesFromString(stream, EXTRA_FIELD_LENGTH, lengthBuffer); // コメント長を登録 this.appendBytesFromString(stream, COMMENT_LENGTH, lengthBuffer); // ファイルは分割しない this.appendBytesFromString(stream, NO_DISK_SEPARATE, lengthBuffer); // ファイルタイプを指定 this.appendBytesFromString(stream, FILE_TYPE, lengthBuffer); // 権限情報を登録 this.appendBytesFromString(stream, FILE_PERMISSION, lengthBuffer); // ファイルのオフセット位置を登録 String fileOffsetBinary = integerToBinaryString(fileOffset.longValue(), 32); this.writeBinaryString(stream, fileOffsetBinary, lengthBuffer); // ファイル名を登録 this.appendBuffer(stream, mFileName.getBytes(), lengthBuffer); // データ長を返却 return lengthBuffer.getValue(); } catch (Exception ex) { throw new RuntimeException(ex); } } /** * ファイル終端のセントラルディレクトリ情報を返却する * * @param stream 出力先ストリーム * @param centralSize セントラルディレクトリヘッダの合計サイズ * @param fileOffset ファイルのオフセット位置 * @param fileCounts zipに格納したファイルの総数 */ public BigInteger writeEndOfCentralDirectoryHeaerToBuffer(OutputStream stream, BigInteger centralSize, BigInteger fileOffset, BigInteger fileCounts) { try { MutableInt lengthBuffer = new MutableInt(); // 終端セントラルファイルヘッダを登録 this.appendBytesFromString(stream, END_OF_CENTRAL_FILE_HEADER_SIGNATURE, lengthBuffer); // ファイル分割はしない this.appendBytesFromString(stream, NO_DISK_SEPARATE, lengthBuffer); // ファイル分割はしない this.appendBytesFromString(stream, NO_DISK_SEPARATE, lengthBuffer); // ファイル数 String fileCountsBinary = integerToBinaryString(fileCounts.longValue(), 16); this.writeBinaryString(stream, fileCountsBinary, lengthBuffer); this.writeBinaryString(stream, fileCountsBinary, lengthBuffer); // セントラルディレクトリサイズを登録 String centralSizeBinary = integerToBinaryString(centralSize.longValue(), 32); this.writeBinaryString(stream, centralSizeBinary, lengthBuffer); // ファイルのオフセット位置を登録 String fileOffsetBinary = integerToBinaryString(fileOffset.longValue(), 32); this.writeBinaryString(stream, fileOffsetBinary, lengthBuffer); // コメント長を登録 this.appendBytesFromString(stream, COMMENT_LENGTH, lengthBuffer); // データ長を返却 return lengthBuffer.getValue(); } catch (Exception ex) { throw new RuntimeException(ex); } } } Lambdaのソースコード:そのほかのクラス:MutableInt .java MutableInt.java public class MutableInt { private BigInteger mValue; public MutableInt() { mValue = BigInteger.valueOf(0); } public void add(int value) { mValue = mValue.add(BigInteger.valueOf(value)); } public void add(BigInteger value) { mValue = mValue.add(value); } public BigInteger getValue() { return mValue; } } build.gradle build.gradle /* * This file was generated by the Gradle 'init' task. * * This generated file contains a sample Java Library project to get you started. * For more details take a look at the Java Libraries chapter in the Gradle * User Manual available at https://docs.gradle.org/6.3/userguide/java_library_plugin.html */ plugins { // Apply the java-library plugin to add support for Java Library id 'java-library' } repositories { // Use jcenter for resolving dependencies. // You can declare any Maven/Ivy/file repository here. jcenter() } dependencies { // This dependency is exported to consumers, that is to say found on their compile classpath. api 'org.apache.commons:commons-math3:3.6.1' // This dependency is used internally, and not exposed to consumers on their own compile classpath. implementation 'com.google.guava:guava:28.2-jre' // https://mvnrepository.com/artifact/commons-io/commons-io implementation group: 'commons-io', name: 'commons-io', version: '2.8.0' // https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-s3 implementation group: 'com.amazonaws', name: 'aws-java-sdk-s3', version: '1.11.1005' implementation 'com.amazonaws:aws-lambda-java-core:1.2.1' implementation 'com.amazonaws:aws-lambda-java-events:3.1.0' runtimeOnly 'com.amazonaws:aws-lambda-java-log4j2:1.2.0' // Use JUnit test framework testImplementation 'junit:junit:4.12' } // Task for building the zip file for upload task buildZip(type: Zip) { from compileJava from processResources into('lib') { from configurations.runtimeClasspath } } java { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } build.dependsOn buildZip S3にCRC32のついたファイルをアップロードするスクリプト upload.py import binascii import boto3 from pathlib import Path from argparse import ArgumentParser import io # 実行引数を読み取る parser = ArgumentParser() parser.add_argument("--folder", type=str, required=True) parser.add_argument("--bucket", type=str, required=True) args = parser.parse_args() def get_crc_from_file(file_path): """ ファイルからCRC32を取得する Parameters ------------ file_path : Path 対象のファイルパス Return ------------ CRC32 : str 文字列型のCRC32 """ with open(file_path, mode = "rb") as fp: return str(binascii.crc32(fp.read())) def main(args): """ ファイルをアップロードする Parameters ------------ args : ArgumentParser * folder 対象ファイルの配置先フォルダ(相対パス) * bucket アップロード先のバケット名 """ # クライアントを作成する s3_client = boto3.client('s3') # フォルダ以下のファイルを一覧で取得する for file_name in Path(args.folder).glob("*"): # CRCを取得する crc = get_crc_from_file(file_name) # OS依存のパスをS3のパス形式に変換する s3_key_name = "/".join(file_name.parts) # アップロードする s3_client.upload_file( str(file_name), args.bucket, s3_key_name, ExtraArgs={ "Metadata": { "crc32": crc } }) if __name__ == "__main__": main(args) 実際に動かしたところ S3に、jpgやビットマップファイルを置いています。 39ファイル、合計サイズ1.0GBのファイルを対象にします。 処理完了後、S3にファイルが配置されました もちろんzipファイルをダウンロードして、問題なく展開することができます Lambdaの実行情報 96秒で処理を完了、実行中に使用した最大メモリは150MB、/tmpディレクトリの使用はありません。 5スレッドで動かしていますが、スレッド数を増やすほどメモリ使用量は大きく、処理時間を短くすることができます。 まとめ 実際にS3の機能だけでzipを作成できることの確認と、処理速度の計測をしました。 ZIP64への対応は必要になりますが、10GBくらいの大きさのzipファイルであれば、S3+Lambdaだけで作ることができそうです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EC2のルートボリューム交換を試す。

はじめに 先日、EC2のルートボリュームをインスタンス停止無しで復元できる機能が公開されました。 EC2 でルートボリュームを交換することにより、迅速な復元とトラブルシューティングが可能に 通常は以下の様にインスタンスを停止してデタッチ・アタッチで交換しますが、ルートボリュームをインスタンス停止無しで復元できるってどうやっているんだ?っていうことでどういう動作をしているのか確認してみました。 以前のスナップショットを使用した Amazon EBS ボリュームの置き換え 検証準備 今回はインスタンス2台で検証してみようと思います。 1台はルートボリューム交換を試すためのインスタンス、もう1台はボリューム交換するインスタンスからsyslogを受け取ってログ確認するためのインスタンスを準備してみます。 syslog転送設定 syslog転送を行うための設定を行います。 送信側syslogは全てのシステムログを転送するため、「### RULES ###」直下に記載しておきます。 受信側syslog設定 $ModLoad imudp $UDPServerRun 514 送信側syslog設定 #### RULES #### *.* @[受信側インスタンスのIPアドレス]:514 セキュリティグループ設定 今回は検証なので適当に。 タイプ プロトコル ポート範囲 ソース カスタムUDP UDP 514 0.0.0.0/0 ルートボリューム交換検証 ルートボリュームの交換はAWSマネジメントコンソールのEC2から「インスタンス」→「アクション」→「モニタリングとトラブルシューティング」→「ルートボリュームを置き換える」から行います。 次の画面でルートボリューム置き換え先のスナップショットを指定して「置き換えタスクを作成」を選択します。 スナップショットを指定しない場合は使用AMIのデフォルトに戻るようです。 ちなみにコマンドで実行する場合は以下コマンドとなります。 コマンドからのルートボリューム交換 aws ec2 create-replace-root-volume-task --instance-id [インスタンスID] [--snapshot-id [スナップショットID]] create-replace-root-volume-task 検証結果 ログを見たところ、やはり無停止でルートボリューム交換を行っているわけでは無く、一度停止を行ってから交換後のボリュームで起動させるような動作を行っているようです。 ルートボリューム交換実施時にpingも送信してみましたが、大体40秒程度応答がありませんでした。 交換後のボリュームは、ルートボリューム交換の実行を行ったタイミングで新たに作成されるようなので、以下の様な作業を実施していると考えられます。 ルートボリューム置き換えタスク作成 交換後ボリューム作成 インスタンスの停止 交換前ルートボリュームのデタッチ 交換後ルートボリュームのアタッチ インスタンスの起動 上記の動作だけ見れば、通常のボリューム交換作業とあまり変わりがありませんが、利点としてEC2インスタンスの状態としてはルートボリューム交換実施時も「実行中」状態となっており、停止状態に切り替わることはありませんでした。 そのため、EIPの設定を行わないとインスタンス停止時に変わってしまうグローバルアドレスも、今回のルートボリュームの交換ではアドレスが変更されることもありませんでした。 以下ルートボリューム交換時に出力されたログです。 ルートボリューム交換実施時の出力ログ May 1 02:14:13 ip-172-21-0-34 systemd: Received SIGINT. May 1 02:14:13 ip-172-21-0-34 systemd: Stopped target Timers. May 1 02:14:13 ip-172-21-0-34 systemd: Stopping Timers. May 1 02:14:13 ip-172-21-0-34 systemd: Stopping Session 8 of user root. May 1 02:14:13 ip-172-21-0-34 systemd: Stopped target Cloud-init target. May 1 02:14:13 ip-172-21-0-34 systemd: Stopping Cloud-init target. May 1 02:14:13 ip-172-21-0-34 systemd: Removed slice system-selinux\x2dpolicy\x2dmigrate\x2dlocal\x2dchanges.slice. May 1 02:14:13 ip-172-21-0-34 systemd: Stopping system-selinux\x2dpolicy\x2dmigrate\x2dlocal\x2dchanges.slice. May 1 02:14:13 ip-172-21-0-34 systemd: Stopping Session 2 of user ec2-user. May 1 02:14:13 ip-172-21-0-34 systemd: Stopped Execute cloud user/final scripts. May 1 02:14:13 ip-172-21-0-34 systemd: Stopping Execute cloud user/final scripts... May 1 02:14:13 ip-172-21-0-34 systemd: Removed slice system-ec2net\x2difup.slice. May 1 02:14:13 ip-172-21-0-34 systemd: Stopping system-ec2net\x2difup.slice. May 1 02:14:13 ip-172-21-0-34 systemd: Stopped Dump dmesg to /var/log/dmesg. May 1 02:14:13 ip-172-21-0-34 systemd: Stopping Dump dmesg to /var/log/dmesg... May 1 02:14:13 ip-172-21-0-34 systemd: Stopped target rpc_pipefs.target. May 1 02:14:13 ip-172-21-0-34 systemd: Stopping rpc_pipefs.target. May 1 02:14:13 ip-172-21-0-34 systemd: Unmounting RPC Pipe File System... May 1 02:14:13 ip-172-21-0-34 systemd: Stopped target Graphical Interface. May 1 02:14:13 ip-172-21-0-34 systemd: Stopping Graphical Interface. May 1 02:14:13 ip-172-21-0-34 systemd: Stopped target Multi-User System. 後片付け ルートボリューム交換前のボリュームが残ってしまうので、不要となるボリュームは削除しましょう。 おわりに ボリュームのデタッチ・アタッチなどの操作を行わずに、ボタン一発で指定のスナップショットや初期AMIの状態に戻せるのは良いですね。 アドレス変更等されることもないため、調査目的だけではなく、他の用途にも使えるかなと感じました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSソリューションアーキテクトアソシエイトに1ヶ月半で合格したよ

はじめに AWSソリューションアーキテクトアソシエイト(AWS SAA)を合格しました。 AWS初心者には結構おすすめの資格だと思うので、参考までに自分の受験記録を残しておきます。 自分のスキル AWSのスキル EC2インスタンスを立てたことがある AWSのIAMの言葉を知っているくらい 周りにAWSを使っている同僚がいたが、全く用語理解できず 一般的なITスキル EC2にsshでログインして、ちょっとした検証をしたことがある 商用システムを触ったことがない ちょっとした自作のアプリを作ったことがある コーディングには全く自信がなく、基本的にググってコピペして修正するくらい 基本情報は持っている 受験に至った背景 社内でのAWS活用の普及 在宅勤務が進む中で、様々な会議でAWSを使っていこう、という話を聞くようになった VMの概念くらいはざっくり知っていたので、EC2はなんとなく理解できた しかし、IAMやらVPCやらAMIやら、全然わからない用語が多い AWSでアプリを作るイメージをつかみたい 自作のアプリはラズパイを使って作成した でもラブパイにつけているファンがうるさいので、クラウド上で作りたい AWSのEC2とかlambdaとか使った方が楽そうな気もした でもネットワーク設定方法とかとかわからない 若干時間ができた 社内での重めの仕事がひと段落ついた そういえば自分資格あんまり持ってないな なんか勉強しようかな 勉強方法 教材 Udemy これだけでOK! AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座(SAA-C02試験対応版) https://www.udemy.com/course/aws-associate/ これだけで合格できた。書籍は買ってない 確か、1500円くらいで購入できた。時期がよかったのかも? 実際に手を動かすハンズオンがある、模試が3回分受けられる、などの特徴がある。 AWSの公式サンプル問題 問題のレベル感を掴める 10問くらいだけだが、解答付き 勉強記録ツール Notion https://www.notion.so/ 日々の記録は基本的にNotionでとる 紙のノート 自分でイメージを整理するときに、ざっくりと図を書くときに使う AWSでは似たようなサービスがたくさんあるので、それらの違いを紙にざっくりイメージ図を書くことで、自分の理解度の確認ができる 勉強時間 平日 1時間-2時間くらい たまに30分くらいの時も 休日 2-3時間くらい 試験前とかは、4-5時間くらいの時も 勉強期間 一ヶ月半 勉強スケジュール 1,2週目 AWS公式のサンプル問題10問解いてみる 全然解けないし、理解できないことを確認して、勉強のモチベにする Udemyの各講座の動画を1.5倍速で聞く 話を聞きながら、Notionにメモを取る ハンズオンの講義では、実際に自分のAWSアカウントで手を動かす 料金がかからないように、EC2などはなるべく頻繁にサービスを削除するようにしておいた。 レッスンで使ったAWSの料金は確か数十円くらい。RDSとかで、高そうな商品を使うハンズオンは見るだけにしたものもあった。 各章ごとにある小テストもちゃんと解く 3週目 模試を2回分解く 本番に近い形で模試を解くことができるので、必ず2回は解く 初回の正答率は必ずメモする 模試の間違えた箇所を勉強 各講座の動画に戻って勉強し直す 4週目 2週目で解いた模試2回分に再チャレンジ 前回よりも正答率が上がっていることに喜ぶこと 間違えた箇所を徹底的に勉強 2回も間違えるということは、ちゃんと理解できてないはず 複数のサイトをみて、理解する 5週目 1,2週目で解いた各章の小テストを再チャレンジする 意外と忘れていて解けない問題が多い 解けない悔しさを味わい、間違えたところを勉強する 6週目 模試3つ目を解く 初見の問題だが、意外と解けるようになっている ここで7割くらい取れていれば、結構合格は近い 模試の間違えた箇所を勉強 各講座の動画に戻って勉強し直す 試験日の予約をする ここら辺で、受かりそうという自信がついたら、即試験を予約する 7週目 模試3つ目を再挑戦する ここまで来れば、大体ほぼ正解できるようになっている 今までのNotionの記録を見返す 今までの勉強をざっと復習する 試験を受ける 自信がついたらモチベが下がる前に早めに受けよう 勉強時の工夫 わからない用語だらけなので、Notionのテーブルにわからない用語リストを作成する 納得するまでGoogleで検索して調べる 似たようなサービスの違いをちゃんと理解する 自分で紙のノートに図を書いて、違いを確認できるようにした 次の日にちょっとだけ見直す 受験当日 試験前 8時くらいに軽めのご飯を早めに食べる トイレにいく(重要) 試験 試験を受けた時間帯 確か11時くらい 試験中 若干日本語がわからない箇所があった 英語にも切り替えることができるので、英文を読むとざっくり理解できた そこまで難しい単語は少なそう 耳当てがとてもよかった 手汗が止まらない 見直す時間は結構あったが、結局全問見直す時間はなかった 試験後 その場で結果が出る 8割弱取れてました ラーメンとか美味しいものを食べる これ、重要 カフェでカフェラテを頼み、ボーッとする とても重要、試験からの解放感を楽しむこと 受験して得られたこと AWSの基本的な機能がどんな動きをするのがざっくり理解できる 簡単なWebサービスをAWSで作ろうとしたときに、AWSの基本的な機能を使ったシステム設計のざっくりとしたイメージくらいは持てるようになった(はず) AWS上で構築されたシステムの各コンポーネントの役割がざっくり理解できるように EC2やRDSを組み合わせたシステムを作っているチームがいた システムアーキテクチャ図を共有してもらったら、意外と理解できた 要件に沿ったAWSサービスを選ベる自信がちょっとだけついた ちゃんと商用システムの設計しようとするのであれば、まだまだ知らないサービスもたくさんあるので、AWS SAAの合格知識だけでは足りないと思う。 終わりに AWSの基本的な知識をつけられたのでよかった 資格を取れると、ちょっとした自信になる また、勉強の目標ができると、勉強が進む AWSをこれから触っていく方にはとてもおすすめな資格だと思う 勉強開始から2ヶ月後くらいに試験を受けるのがモチベーションが保てて良さそう
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】IAMについてまとめてみた

IAMとは? AM(Identity and Access Management)とは、AWSのサービスで「認証」と「認可」の設定を行うことができるサービスです。 「認証」「認可」を正しく設定することで、AWSの利用者や、AWSのサービスがアクセスできる範囲を制御することができます。 IAMは最低限この5つは覚えよう! IAMユーザー アクセスキー 2つのアクセスの方法があります。 ・プログラムによるアクセス ・AWSマネジメントコンソールへのアクセス プログラムによるアクセス アクセスキーIDとシークレットアクセスキーの2種類が発行されます。 両方ともランダムな文字列であり、こちらさえあれば遠隔操作が可能になります。 なので、これが漏洩するとヤバい!!! AWSマネジメントコンソールへのアクセス パスワードでログインします。 こちらは2段階認証を入れることが多いので最悪漏れてもなんとかなるはず。。 IAMグループ IAMグループとは、複数のIAMユーザーの集合体です。 IAMポリシー AWSで操作できる権限を表したものです。 JSON形式で記述された設定ファイルであり、 認証主体(Identity)にアタッチして使用します。 (こちらはあまり推奨されていないやり方です。ロールを使うのが一般的です。) また、ポリシーは2種類あります。 AWSが定めた、AWS管理ポリシーとユーザーがJSONで作成したカスタマー管理ポリシーです。 以下のケースであれば、 「EC2の権限をすべて付与」した形となります。 カスタマー管理ポリシーを書いてみよう { "Version": "2012-10-17", "Statement": [ { "Sid": "ListBucketRstIP", "Effect": "Allow", "Principal": "*", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::sample-bucket", "Condition": { "StringEquals": { "aws:SourceIp": "12.34.56.78" } } } ] } それでは順に説明していきます。 Sid idを指します。 Effect 許可するか拒否するかを判別します。 Allow ↔︎ Deny ここからが大事です。 この4つの頭文字をとって、PARCモデルと呼ばれます。 Principal アクセスできるアカウントを指します。 * → この場合すべてのアカウント "AWS":"arn:aws:iam::123456789012:root" → IAM情報(ユーザーのARN)が一致したアカウント Action どのサービスを使えるようにするか明記します。 上記の場合は、s3のListBucketが使えるようになります。 Resource リソースを特定します。 上記の場合は、s3のsample-bucketです。 Condition IPアドレスやこのポリシーがいつまで使えるかなどを明記します。 上記の場合は、IPアドレス=12.34.56.78の時のみ使えます。 IAMロール IAMポリシーを複数アタッチして権限をひとまとめにすることを指します。 これだけじゃわからないって人も多いでしょうし、私もまとめきれなかったのでわかりやすい記事を紹介します。 IAMユーザーとIAMポリシー、IAMロールの位置関係をわかりやすく明記しています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【2021年4月版】『M5Stack Core2 for AWS - ESP32 IoT開発キット』 入門 前編 〜開封の儀〜

M5Stack Core2 for AWS が到着いたしました。 「M5Stack Core2 for AWS」がやっと?入手できましたので環境準備と言いますか、Getting Start を動かしてどんな風に動いているのか、確かめてみたレポートをお届けしたいと思います。 まずは パッケージ、ですがスイッチサイエンスのサイトでは8000円以上で送料無料なので本体以外にも追いセンサしてしまい。。。 どーーーん!! ・・・はい、M5Stack初心者ですがどっさり購入してしまいました。 しかし改めて感じるのは非常に小さい、ということですね。カタログのスペック考えたら色々てんこ盛りなのにこのコンパクトさ。 分かりにくいですが、以下のようなサイズ感です。 下に敷いてあるPCはMacBookの13インチ、右側のiPhoneはSEなので小さいやつです。 で、M5Stack Core2と追いセンサ達です。 非常にコンパクトでパワフル、といった感じでございます。 これらのスペックというかセンサーは以下のようなものでございます。 M5Stack Core2 for AWS ESP32-D0WDQ6-V3。最大240 MHzのXtensa32ビットLX6デュアルコア 2.4 GHz Wi-Fi Bluetooth 4.2 BR/EDR、BLE 16 MB フラッシュ、8 MB PSRAM ATECC608Aハードウェア暗号化チップ内蔵 2.0インチの静電容量性タッチスクリーン SPM1423デジタルマイク 内蔵スピーカー プログラム可能な10個のSK6812 RGB LED 6軸IMU(慣性計測ユニット)兼温度センサ 振動モーター microSDカードスロット(最大16GB対応) 500 mAhリチウムバッテリ 電源ボタン、RSTボタン 画面前面にはプログラム可能な仮想タッチボタン3個 USB Type-C x 1 GROVE PORT-A, HY2.0-4P PORT-B,C 底面の充電用POGO PINでI2C可能 2.環境センサユニット ver.2(ENV II) SHT30 高精度デジタル温湿度センサ BMP280 絶対大気圧センサ 3.赤外線送受信ユニット 赤外線発信器 赤外線受信器 4.PIRセンサユニット パッシブ型赤外線センサ 5.回転角ユニット 10kΩポテンショメーター搭載つまみ ・・・です。 特に Core2 の全部盛り感がハンパないです。てんこ盛りです。 また追いセンサについてもぼちぼちご紹介できればと思います。 環境構築 手元の環境は以下の通りです。 macOS Big Sur 11.3 Core i5 1.4GHz 8G DDR3 VS Code で、Androidに ESP RainMakerアプリを入れています。 Macでの始め方は AWS サイトの公式ガイドに従えばそのままちゃんと動きました。 さらっと流れをご紹介いたしますと、 macOS 用のSilicon Labs CP210x driverをこちらダウンロードしてインストール。 セキュリティの警告&確認でますが、許可 PC再起動(しなくても認識してたけど念の為) VSCode のExtensionsから 'PlatformIO'を検索してインストール VSCode 再起動 https://github.com/m5stack/Core2-for-AWS-IoT-EduKit.git をクローン USB-C ケーブルでCore2とMacを接続 PlatformIOの'Devices'リストからCore2が接続されているUSBポートのIDをメモっておく スマホでアプリストアから 'ESP RainMaker' を検索してインストール ESP RainMaker でアカウント作るかGithubアカウントなどでログインして、使えるようにしておく でOKです。 Core2に付属のケーブルはType-C=Type-A変換ケーブルでMacには刺さらないので、Macに付属のType-Cだけのケーブルで接続しています。 良好です。 いや、準備も簡単ですね〜。。。 Getting Start を動かしてみる。 さて、準備が整ったところで早速、"Getting Start"プロジェクトを動かしてみましょう。 クローンしたリポジトリのGetting-Startedプロジェクトを開く PlatformIOからターミナルを開きpio run --environment core2forawsを叩く pio run --environment core2foraws --target uploadを叩く pio run --environment core2foraws --target monitor を叩く 先ほどメモったUSBポートのIDを入力 でしばらく待ちます。 ただし、uploadしてからCore2の画面に灯が灯る前にmonitorしないとQRコードのログが流れてしまうので要注意です。uploadしたらさっさとmonitorしておきましょう。 後はスマホでBluetoothとWiFiをオンにし、ESP RainMakerアプリから "Add Device" でQRコードを読ませると Core2 と通信してゴニョゴニョとセットアップをやってくれます。 通信時のログでは AWSのMQTTに接続していることが読み取れます。 [0;32mI (178777) app_wifi: Provisioning successful␛[0m ␛[0;32mI (178807) esp_rmaker_mqtt: Initialising MQTT␛[0m ␛[0;32mI (178807) esp_rmaker_mqtt: Connecting to xxxxxxxxxxxxx-ats.iot.us-east-1.amazonaws.com␛[0m ␛[0;32mI (178807) esp_rmaker_mqtt: Waiting for MQTT connection. This may take time.␛[0m ␛[0;32mI (181317) esp_rmaker_mqtt: MQTT Connected␛[0m なるほど、Core2からAWS IoT Core の MQTT経由している、ということが確認できました。 MQTTについては以下の公式ドキュメントも後で読んでおこう・・・ というか今更ですがこれ、WiFi 環境必須ですね。まぁ、無ければPCにUSBのWiFi挿してそっちを親機にする、とかでなんとかなりますか。 さて、しばらくするとCore2側で以下のような画面に変わります。 そして、スマホのRainMakerアプリでは、 のように3つの"機器"が追加されました。 どうやらこの3つの"機器"をスマホからリモートでコントロールできるようなイメージなんですね。なるほど! これらの"機器"をタップすると詳細が表示されます。 まず、'Light'から見てみましょう。 機器の名称とオンオフ、そしてHSVでの調光が可能な模様です。 試しにLightをオンにしてゲージを以下のようにいじってみると 画面に表示されているのお家の窓の色が変わります。Core2 本体に付いている LED の色も変わります。 芸が細かい!ただしLEDを直接カメラで撮ると白く飛んでしまうので反射光で感じてください。。。 多少のタイムラグは当然ありますが(MQTTでus-east-1まで飛んで帰ってきてるんで)、スマホの操作で機器がリモート操作、双方向通信できてるのが確認できます。 続いて Fan の機器を見てみましょう。 こちらは換気扇をエミュレート?しておりまして、PowerをONにすると振動モーターが回ります。 スピードも5段階調整できます。 ちなみにこれはCore2の前面のタッチパネルからも操作できます。 振動モーターが起動するとFanが回っているアニメーションに変わります。 スピードに合わせてFanのアニメーションも回転速度が変わります。こちらも芸が細かい。 振動モーターがブリブリ回っているのをお伝えできないのが誠に残念です。。。 最後に Temperature Sensor です。 これはそのまま温度計、ですね。ただしCore2内部の温度ですので、画面では摂氏(C)表記ですが室温とはズレがあります。 画面の温度計も温度に連動してバーが上下しています。 先程のLEDを点灯させている時の画像と比べると微妙に温度計の目盛りが変わっているのがわかると思います。細いのでわかりにくいですが・・・ Getting Started プロジェクトの動作確認は以上です。ざっくりですが、機器とスマホがそれぞれどのような動きをするかのイメージは掴んでいただけたかと思います。 それでは後編として、"Getting Started" プロジェクトの中身について探っていきたいと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】VPCの概要を解説します。no.6

こんにちは。まゆみです。 AWSについての記事をシリーズで書いています。 今回は第6回目になります。 今回と次回の記事を使って、AWSサービスを動かしている仕組みの概要について説明していきます。 どんな仕組みになっているのか大局を見てから、細かな部分を解説していきますね。 今回は、 AWSのVPCについての概要を書いていきます。 ではさっそく始めていきますね。 VPCとは? VPCとは、より大きなネットワーク(AWS)の中に作るプライベートネットワーク(Virtual Private Cloud)のことです。 このVPC内に、AWSのリソースであるEC2やデータベース等々...を配置することができ、それらをあなた自身がコントロールすることができます。 身近な例でイメージしやすい物で言えば、例えばInstagram やFacebook。 より大きなネットワークの中に、あなたのページを作り 写真や動画を投稿したり 削除したり アクセスをコントロールしたり することができますよね。 そしてそのあなたのページ内に置いては完全にコントロール権を持つことになります。 それと同じように、AWSではあなた自身のプライベートネットワーク(VPC)を作ることができます。 また、後述するネットワークセキュリティについて、『subnet』という用語もでてくるので、ここでsubnetの説明を軽くしておきますね。 subnetとは、あるネットワークのなかのサブセクションになります。 VPCの中にさらに作るネットワークがsubnetになります 引用元:Amazon Virtual Private Cloudユーザーガイド ネットワークセキュリティについて subnet レベルと、EC2インスタンスレベルにおいて、ファイアーウォールを設定する事ができます。 ファイアウォール(英: Firewall)は、コンピュータネットワークにおいて、ネットワークの結節点となる場所に設けて、コンピュータセキュリティ上の理由、あるいはその他[注釈 1]の理由により「通過させてはいけない通信」を阻止するシステムを指す。Wikipediaより引用 ファイアーウォールを身近な例えで言えば、 手紙・メールは受けてもらえるが 実際に会うことはできない など、受けることができるものと、受けることができないことを設定する事です。 上記の例で言えば、あなたに物理的に会えないようにしている門番が『ファイアーウォール』であり、手紙・メール・実際に会いにいくと言った、手段がプロトコールとして例えることができます そのようなファイアーウォールを サブネットレベルで設置するのが『Network Access Control Lists(ACL)』 EC2(インスタンス)レベルで設置するのが『Security Group(SG)』 になります。 まとめ VPCの概要はこれくらいで締めくくらせていただきます。 次回の記事では、EC2についてのざっくりした内容を書いていきますね。 その後、VPCやEC2の細かな内容を書いていきます
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

HTTPS通信でアクセス ハンズオン

HTTPS通信 HTTPと比べてHTTPSは通信が暗号化されており、第三者によって通信の中身を見ようとしても見れず、セキュリティ対策となり個人情報が守られます。 他にも、ページの表示速度が速くなるといったメリットもあります。 準備 ・EC2,RDSが起動していること ・前回のハンズオンで作成したブログがドメイン名で正常にアクセスできること AWS Certificate Manager(ACM)とは https通信をするのに証明書が必要だが、このサービスは証明書を管理できるサービス AWSで無料の証明書を作成して、ELBにアタッチをすることでクライアントはhttps通信が可能となります。 利用する際は、 ・通信を受け付ける設定でhttpsを追加、 ・ELBのセキュリティグループでhttps通信を許可する設定が必要です ロードバランサーでリスナーを追加 リスナー・・・通信を受け付けるポートの許可設定のこと EC2< ロードバランシング< ロードバランサー< タブにあるリスナーからリスナーを追加を選択 プロトコル:ポートに HTTPSを選択 転送先にターゲットグループ(TG-1)を選択 新しいACM証明書をリクエストを選択 ドメイン名の追加フォームでドメイン名にblog.aws-demo.gaを入力して次へを選択 検証方法の選択とは、証明書を発行するにあたって、本人確認のようなものが必要で方法が2種類あります 1, DNSの検証 (←今回はこちらを選択) 2, Eメールの検証 タグの追加では証明書のタグを作成できます。 確認画面の後、確定とリクエストを選択 検証方法はRoute53でのレコードの作成というところでCNAMEのDNSレコードを作成したRoute53のポストゾーンに追加する 検証状態が準備完了となればOK ボタンで自動的にレコードが作成されて追加される Route53の画面に切り替え、更新してみると 今回検証用のDNSレコードが自動的に追加されていることが確認できます。 ELBのリスナー追加フォーム画面に戻り、デフォルトのSSL証明書に、先ほど作成したACMが選択項目にあがる 保存を選択して成功ELBはHTTPS通信を受け付けられるようになります。 セキュリティグループの設定 現状HTTP通信しか受け付けられないので設定を変更します EC2< ネットワーク&セキュリティ< セキュリティグループを開く ロードバランサー用に作成したセキュリティグループを選択後、インバウンドルールを編集を選択します インバウンドルール< ルールを追加を選択 タイプ< プロトコルの選択フォームでHTTPSを選択、 ソース元(通信してくる元)は0.0.0.0/0(全て)でルールを保存を選択 以上でHTTPS通信の設定は完了 補足1: httpsでwordpressを閲覧する wordpressの表示の仕様により表示が崩れます。(注: wordpressの詳しいことは分かりません) # EC2にsshで接続します ssh -i キーペアファイル名 ec2-user@パブリックIPアドレス # 接続したら今回は権限をroot権限に切り替えておきます sudo su - # ディレクトリ移動 & 内部確認 cd /var/www/html/ ll # viコマンドでwp-config.phpを編集 vi wp-config.php wp-config.php ... if($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') { $_SERVER['HTTPS'] = 'on'; $_ENV['HTTPS'] = 'on'; } /* ↑にコードを貼り付ける */ /* 編集が必要なのはここまでですと書かれた行があります ~~ */ この作業を別に稼働しているEC2にもログインしてコードの貼り付けを行います。 補足2: セキュリティ面向上 動作確認の都合上同時に行わなかったが、 このままだとロードバランサーがHTTP通信を受け付ける状態なので設定を削除していきます EC2< セキュリティグループ< インバウンドルールを編集を選択 HTTP通信を削除し、ルールを保存します。 続いてリスナーの設定 ロードバランサーの画面< リスナー HTTPの方を選択し、削除を行う 以上で完了 参考・注意 この記事はAWS初学者を導く体系的な動画学習サービス 「AWS CloudTech」の課題カリキュラムで作成しました。 https://aws-cloud-tech.com このハンズオンでは料金が約10〜11円/時間かかります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSアソシエイト試験に向けて5(EC2関係)

EC2の特徴 端的に言うと従量課金制の仮想サーバーでPaaSよりのIaaSと言う感じでOSまで用意してくれるタイプのサービス。 OSはAMI(Amazon Machine Image)という形で提供され、AWSが用意してくれているものやマーケットプレイスで売られているものもある。 このAMIにOSの設定をしておいて保存しておくことでそのOSの再利用や複製が可能になる。 アーキテクチャはIntel。 → つまり、IaaSであるがOSより上のレイヤーを利用する形のサービスになる(厳密にはPaaSになるのかもしれない) AZに対してインスタンスとして設置することで利用できる。 インスタンスファミリー EC2のインスタンスは用途に応じて様々な種類のインスタンスが用意されている。 起動時にインスタンスタイプを用途に応じて検索して、最初から指定して起動することもできる。 以下その例。 汎用 無料枠で使えるT2.microはここに入る。 Tがインスタンスファミリーのタイプ、2がその世代、nanoがサーバーの容量を示す。 このグループの特徴は バランスの取れたリソースが提供されるので、インスタンスのリソースを同じ割合で利用していくアプリケーションに適している というところになる。 代表的なインスタンスファミリーはA1、M5、T3など。 ちなみにMacインスタンスもあるらしい(Mac Mini(i7、6コア12スレッド、RAM32GB)) コンピューティング最適化 汎用よりさらに性能の高いプロセッサを要求するアプリケーションに使っていくインスタンス。 主な用途は バッチ処理ワークロード メディアトランスコード 高性能なWebサーバー HPC(ハイパフォーマンスコンピューティング) 科学モデリング 専用ゲームサーバーおよび広告サーバーエンジン 機械学習推論 などが挙げられる。 代表的なインスタンスファミリーはC5、C6gなど。 メモリ最適化 メモリ内の大きいデータセットを処理するワークロードに対して、高速なパフォーマンスを期待したいときに使う。 代表的なインスタンスファミリーはX1、R5、ハイメモリ、z1dなど。 ストレージ最適化 ローカルストレージの大規模データセットに対して高いシーケンシャル読み取り(連続してデータにアクセスするタイプの読み出しのやり方、ファイルコピーとかはこのタイプ)及び書き込みアクセスを必要とするワークロードに最適。 つまり、ファイルの読み書きを頻繁にやる予定があるサーバーなどに向いている。 特徴として 数万IOPS(1秒あたりの実行可能なIOの数。IOは読み書き操作のこと)を低レイテンシー(遅延)で実行できる ランダムIOオペレーションに最適 ということが挙げられる。 プロビジョンドIOPSのEBSと併用するケースが多い。 代表的なインスタンスファミリーはH1、D2、I3、I3enなど。 高速コンピューティング コンピューティング最適化のインスタンスと似ている感じがするが、こちらはハードウェアアクセラレーターの役割や演算処理の高速化、より高度な処理機能が求められる場合に用いるインスタンスのようだ。 ブロックチェーンのノード(FPGA) 浮動小数点計算 グラフィックス処理 データパターン照合 GPU的役割(G4) といったことに使われる。 ドキュメントを見る限り、NVIDIAおよびAMDドライバーを使うこともできるので演算の並列処理やグラフィック処理を期待してもGPU機能としての役割を期待されて使用されるものと推測する。 インスタンスの購入方式 インスタンスは無料枠以上になると従量課金が基本だが予め用途や利用期間などが決まっていればそれに応じて割安で利用できる場合がある。 以下その例。 オンデマンドインスタンス これが基本のインスタンスの課金方式。 無料枠を超えたら使ったら使った分だけ決まった料金を秒単位で払う。 その代わりインスタンスのライフサイクルはユーザーの自由になるので、起動から終了(インスタンスの削除)はもちろん一時停止、休止、再起動……までユーザーが裁量を持てる。 ただし、インスタンスは終了しないと利用しているとみなされ課金対象になるので注意。 リザーブドインスタンス 1年または3年の利用期間を先に押さえておくことでその分割引価格で利用できる。 上記の期間のみ利用、または長期間の利用が想定される場合は当然こちらの利用方法のがベター。 また災害対策などのキャパシティ予約が可能庵アプリケーションもこちらのインスタンスがベター。 特定のAZかまたはリージョン内で押さえるか2パターンの利用方法がある。 また注意する点として以下の点が挙げられる。 利用方法としてスタンダードかコンバーティブルという2つのプランが有る それぞれ1年(ST……40%引き/Co……31%引き)と3年(ST……60%引き/Co……54%引き)単位でインスタンスを押さえることができる スタンダードの場合はインスタンスファミリー・OS・テナンシー・支払いオプションの4点の変更ができない AZ・インスタンスサイズ・ネットワークタイプの変更はどちらも可能 コンバーティブルはリザーブドインスタンスマーケットプレイス(押さえた期間より早く利用停止する場合、残りの期間を売ることができるマーケット)で2021/4現在では販売できない。 リザーブドインスタンスとSavings Plans 1年間にわたり毎日・毎週・毎月……と決まった開始時間及び期間でインスタンスを押さえておくという利用方式。 例えば毎週木曜の21時から5時間だけメンテナンス及びバッチ処理の適用のためのアプリケーションを動かしたいという利用形態であるならこの利用方法を選択するのがベター。 Savings Plansは以下の2つのプランがある。 Compute Saving Plans FargateとLambdaもセットになったプラン EC2 Instance Saving Plans EC2インスタンスのみのプラン リザーブドインスタンスとSavings Plansとの違い - キャパシティの予約 リザーブドインスタンスやSavings Plansとは違い、インスタンスではなくインスタンスを作るスペースだけを押さえる。 これはインスタンスを大量に作る際(フリート機能などで)にスペーズの調達が間に合わずにエラーになってしまうことがあるため、大量にインスタンスを作ることがわかっている場合はインスタンスタイプ・プラットフォーム・AZ・テナンシー・インスタンス数を入力してスペースだけ予約しておくというサービスになる。 以下のように設定できる。 スポットインスタンス こちらはAWSが予め管理用に保持しているリソースをAWSが利用していない分だけユーザーに間借りさせてくれる利用方式。 大幅な割引(最大90%引き)で利用できるものの、AWSがそのリソースを利用するとなった場合問答無用で利用を中断させられるデメリットがある。 永続的リクエスト(押さえていたスポットインスタンスがAWSに差し押さえられたとき、別のスポットインスタンスを代わりに自動でリクエストする)やスポットブロック(割増になる代わりに1~6時間の内指定した時間内はインスタンスが中断されなくなる)である程度リスケはできる仕組みはあるものの基本的には実行時間に柔軟性があることが前提のインスタンスの利用方法となる。 リクエストするには以下のようにインスタンスの起動時にオプションで設定するか、スポットリクエストから直接リクエストするかの2択になる。 またスポットインスタンスを削除する際にはスポットリクエストをキャンセルする、インスタンス自体を削除してもリクエストが残っていると復活する。 インスタンスに対して物理的な対応がしたい 要件や案件、または社内規範等でインスタンスを物理的に分離しないといけないという事案が発生することがある。 そういう条件の場合に用いるインスタンスの利用方式(もちろん追加費用がかかる)。 なお、Dedicated InstanceとDedicated Hostのことをテナンシーと呼ぶことがあり、EC2インスタンスの起動設定のオプションのところに設定項目がある。 ハードウェア専有インスタンス(Dedicated Instance) 専用のハードウェアのVPCで実行されるインスタンス。 通常のインスタンスは仮想サーバー内ではそもそもAZやVPCなどでユーザーの使用領域ごとに分割されているので一見、それぞれのインスタンスは分離されているように見えるが、ハードウェア的には仮想サーバーを展開している物理サーバーは他のAWSインスタンスと共有してしまっている。 このインスタンスはホストハードウェア、つまり仮想サーバーを展開している物理サーバーの段階から他のAWSアカウントと分離したいという要件で使えるインスタンスとなる。 但し、同じAWSアカウントとはハードウェアを共有する必要があることだけ注意(つまり、当該インスタンスを完全に分離する目的としては使えない) Dedicated Host こちらはDedicated Instanceよりさらに踏み込んだインスタンスの分離方法で同じAWSアカウント(IAMユーザーやグループ)とも物理的なサーバーを共有しない形で仮想サーバーを展開し、EC2インスタンス容量を当該IAMユーザー(またグループ)が完全に占用できる形でインスタンスを作成できる。 サーバーにバインドされた既存のソフトウェアライセンスを使用したい場合はこれを選ぶ。 これはオンプレ環境からAWS環境へ移行を検討している際に、オンプレ環境側でライセンスが付与されたソフトウェアを使っている……といったときにAWS側で対応していればそのまま移行できるよというユースケース。 以下のように設定できる。 Bare Metal 物理的なサーバーに対して直接オンデマンドでアクセスできる仕組み。 アプリケーションが基盤となるサーバーのプロセッサーとメモリに直接アクセスができるインスタンスを作ることができる。 つまり、通常のインスタンスではOSの選択とそれより上のレイヤーのコントロール(仮想サーバー内の領域のコントロール)までしかできなかったところを、仮想サーバーを展開している物理ハードウェアレベルまでコントロールできるようになったインスタンス利用形式ということになる。 EC2のストレージ AWSのストレージとしてはS3やCloud watchがあるが、EC2が直接利用するストレージというものもある。 以下の2種。 インスタンスストア ホストコンピュータ内蔵のディスクでEC2と不可分になっているブロックレベルの物理ストレージ。 EC2に関する一時的なデータの保存場所であり、停止または終了でクリアされる。 なので主な役割としてはインスタンスの休止からの再起動の際にデータを保持しておくというところになる。 Elastic Block Storage 通称EBS。 EC2内で用いられるブロックレベルのストレージでネットワークで接続されている。 特徴としては -ネットワークで接続されたブロックレベルのストレージでEC2とは独立して管理されている。(ただしAMIイメージにはSnapshotとともに含まれる) 上記の特性上、EC2インスタンスを削除してもEBSボリュームは保持することができる デフォルトではルートボリュームがEBSの場合はインスタンス削除と同時にEBSも削除 バックアップの形としてSnapshotが存在する ボリュームデータはデフォルトでAZ内の複数のハードウェアにレプリケートされていて、冗長化が不要 セキュリティグループでアクセスを制御できない(=ポートが通ってなくてもEBS自体は利用可能) データは永続的に保持される インスタンスで使用するOSTやアプリケーション、データの置き場……etcと使いみちは様々 サイズは1GB~16TBまでで指定する ほぼ100%の可用性を持つ AZ内に紐付くので他のAZからは利用できない(ただし、Snapshotを経由してコピーは可能) インスタンスへの付け替えは自由にできる(同じAZ内) 複数のEBSを1つのインスタンスに紐つける事はできるが、複数のインスタンスに同じEBSを紐つけることはできない ただし、プロビジョンドIOPSのEBSのみは複数のインスタンスで共有できる(ストレージ最適化インスタンスでビックデータを扱う場合、複数インスタンスで共有した方がいいケースがあるから) 無料枠を超えると有料であり、サイズと利用機関で課金される ということが挙げられる。 さらにインスタンスと同じくユースケースによって性能やコストが異なる。 汎用SSD 1番シンプルなやつで無料枠では実質的にこれしか使えない。 サイズは1~16TBでユースケースは 仮想デスクトップ 低レイテンシーを要求するアプリ 小中規模のDB 開発環境 プロビジョンドIOPS 高IOPSを要求される場面ではこのタイプのストレージを選択する。 主な例としてはストレージ最適化インスタンスと一緒に使ってビックデータを扱う場合など。 サイズは4~16TBでその他のユースケースは 高IOPSを要求されるDB、NoSQLDB、アプリ(つまり高速で読み書きする必要があり、かつ頻繁なアクセスを要求するもの) NitroシステムやAmazon EC2インスタンス、EBS最適化インスタンス等で高速化を図りたい スループット最適化HDD 用途的にはプロビジョンドIOPSの廉価版である(ただしSSDではなくHDD)。 ルート(インスタンスのブートボリューム)ボリュームとしては使えない。 サイズは500~16TBでありユースケースとしては ビッグデータ DWH 大規模なETL処理やログ分析 コールドHDD アクセス頻度が低いデータ、あるいはS3を使うところでそれを使用せずにバックアップ等取りたいときに使う。 サイズは500~16TBでありユースケースとしては ログデータ バックアップ、アーカイブ Magnetic 一応無料枠だが基本的には利用しない。 サイズは1GB~1TBでデータへのアクセス頻度が低いワークロードで使う。 Snapshot EBSをバックアップする機能。 特徴としては フルボリュームでバックアップした以降は増分形式でバックアップされる フルボリューム(1世代目)を削除しても復元は可能 S3に保存される(故に無料枠を超えたら課金対象) 作成時にブロックレベルで圧縮して保管するため、圧縮後の容量に対して課金が行われる 作成時には静止点を作ることが推奨されている(つまりデータの整合性が取れるような状態を作る)が、作成自体はEBS使用中でも実行可能 保存期間や世代数は無制限(なので管理を怠ると無駄な課金が発生する) 世代管理が必要な場合はAWS CLIやAPI等で自動化を図る DLMを利用してスケジューリングできる 別アカウントに対しても権限を移譲することでSnapshotからEBSを複製できる という点が挙げられる。 AMIとSnapshotの違い Snapshotはストレージ/EBSのその時点での断面のバックアップとして保持し、ストレージの復元・複製に使用するがAMIはEC2インスタンス自体をイメージとしてOS設定などともにEBSやSnapshotまで含めてイメージとして保持している。 要するにインスタンス丸ごとバックアップするかストレージ/EBSをバックアップしているのかという違い。 EBS作成 実際に作る場合は以下のように作る。 ボリュームタイプ 利用するサイズ この2つの指定でIOPSが決まる。 あとは AZ スナップショットID(Snapshotから作成する場合) 暗号化 の3点を指定する。 暗号化はキーペアとは別でKMSキーが作られて管理される。 作成が終わると以下のようにアタッチをしたり、Snapshotを作ることができる。 Snapshotあれこれ スナップショットの作成画面は以下の通り。 作られたことが確認できる 活用方法としては壊れたルートボリュームの代わりに、バックアップから復元したルートボリュームを再アタッチしたいというケースが考えられる。 外付けのように使う場合はアタッチの際に任意のディレクトリを指定すればその領域が新たなボリュームとして機能するが、置き換えの場合は元のディレクトリを正しく指定しないといけない。 その場合はボリュームのディレクトリを以下のように確認しておくことが大切である。 あとは 作業するインスタンスを停止 元のルートボリュームをデタッチ ディレクトリを指定して復元したルートボリュームをアタッチ としてやればいい。 DLM(データライフサイクルマネージャー) Snapshotの管理を自動化してくれる機能。 ポリシータイプでどうバックアップを取るのか決める。 EBSスナップショットポリシーであるなら単純にSnapshotのバックアップのポリシー、EBS-based AMIポリシーであるならEBSをルートボリュームにしているインスタンスに対してAMIイメージを取得するというアクションに対してのポリシーということになる。 アカウント間コピーのイベントポリシーはSnapshotをアカウント間でやり取りしてそこからEBSを複製する場合に対するポリシー。 次にリソースタイプでインスタンスに紐ついているEBSのSnapshotなのか、それともボリューム自体なのかを指定する。 例えばボリュームを指定するとボリュームについてるタグから任意のボリュームを指定できる。 複数指定することも可能。 IAMロールはDLMを実行する上での権限が必要になるのでそのためのロールを作る部分。 自分で作ることもできるし、AWSに作ってもらうこともできる。 スケジュールはSnapshotの管理スケジュールを設定する部分になる。 静止点であろう時間に設定しておくのが推奨される。 高速スナップショットはプロビジョンドIOPS用途の場合選択する部分。 クロスリージョンはDLMを利用してSnapshotのコピーを複数のリージョンにも同時に作成するという機能。 クロスアカウント機能はこのDLMで作られたSnapshotをアカウント間で共有するかの設定。 アカウントIDでやり取りする。 以上を設定するとSnapshotの管理を自動化できる。 例えば自動で取得したSnapshotは10日おきに削除される……といったこともできる。 EC2におけるアーキテクチャパターン 作成したEC2インスタンスはApacheのようなWebサーバー(アプリケーションサーバー)にもMySQLを入れてデーターベースサーバーにもできる。 問題はその構成をどうするかという点でユースケースは大きく3つに分かれる。 一つのAZかつ1つのインスタンスに両方配置する 冗長性なし シンプルかつそんなに大したページアプリケーションではない場合に向く 手軽 一つのAZに2つインスタンスを作り、プライベートサブネットにMySQLサーバーを置く レイヤーがわかれているので保守性が上がる DBサーバーはプライベートサブネットにおけるので安全性が上がる アンマネージド型なのでOS設定と物理サーバー管理以外はすべてユーザーが行う 一つのAZに2つインスタンスを作り、プライベートサブネットにRDSのMySQLを置く MySQLサーバーをプライベートサブネットに置く場合と比べて、インスタンスが情報を持たないのでより冗長性があがる マネージド型なので物理サーバー管理、OS設定、メンテナンス、バックアップ、スケーリングまでAWSが用意してくれている EC2インスタンスの起動あれこれ 接続方法 セキュリティグループにもよるが、公開鍵認証方式を使ってSSH経由でアクセスし操作することが多い。 EC2インスタンスの作成時にキーペアという形式で作成される。 .pemファイルで秘密鍵が作られ、次回以降のインスタンスで使い回すことができる(同じ鍵穴の形をした南京錠をかけるイメージ)。 ただし、例えばリージョンを変えてインスタンスを作る場合など使い回さず新規に.pemファイルを作成することが良いこともある。 以下のようにインスタンスを作成後に接続に必要な情報を確認することもできるが、 基本的にはssh -i ".pemへのディレクトリパス" ec2-user@IPアドレスというsshコマンドで接続していく。 なお、ec2-userの部分はAMI(OS)イメージによって変化し、IPアドレスは動的なものを避けた方が好ましい(ex. インスタンス間の連携にIPアドレスを使う)場合はElastic IPアドレスを関連付けて代わりに指定するようにする。 ユーザーデータの活用 インスタンスは基本的に作成したら管理権限でyum update -yをかけてインスタンスを更新したり、例えばWebサーバーならApache、DBサーバーならMySQLライブラリをインストールしないといけない等々作業が必要になる。 こういった初期設定の作業を自動化をインスタンスを作る際に以下のように設定することができる。 具体的には以下のようなコマンド。 #!/bin/bash # サーバーの設定変更(インスタンスのユーザー名(ec2-userの部分)の変更) sed -i 's/^HOSTNAME=[a-zA-Z0-9\.\-]*$/HOSTNAME=udemy-bash/g' /etc/sysconfig/network hostname 'udemy-bash' cp /usr/share/zoneinfo/Japan /etc/localtime sed -i 's|^ZONE=[a-zA-Z0-9\.\-\"]*$|ZONE="Asia/Tokyo"|g' /etc/sysconfig/clock echo "LANG=ja_JP.UTF-8" > /etc/sysconfig/i18n # Apacheのインストール sudo yum update -y sudo yum install httpd -y # Apacheのディレクトリへ移動 sudo cd /var/www/html # Apache起動 systemctl start httpd # 以後インスタンスが起動する度に自動でApache起動 systemctl enable httpd ==== これで自動的にApacheがインストールされ、ec2-userの代わりにudemyというホスト名がついたインスタンスが作られる。 MySQLの場合はApacheの部分が以下のコマンドとなる。 yum localinstall https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm -y yum install mysql-community-server -y systemctl start mysqld systemctl enable mysqld 使いたいインスタンスタイプが決まっている場合 以下のように直接インスタンスタイプを検索してそこから起動ウィザードへ入ることができる。 起動テンプレートを作る ユーザーデータはインスタンスの初期設定であったが、こちらはそもそもインスタンスの起動からテンプレートにして使い回したいときに使える機能。 AMIからインスタンスタイプ……etcと起動ウィザードで設定する項目を指定して作れば次回から同じものはこのテンプレートから作成できる。 フリート フリートは複数のインスタンスを1つのグループ(フリート)としてまとめて管理するもの。 スポットインスタンスで例を見てみる。 まず、スポットリクエストから普通に作っていく。 ここでフリートを構成するインスタンス数とインスタンスの中断処理、インスタンスのコスト設定を行う。 スポットインスタンス中断時に別のインスタンスをリクエストして続行したい場合はキャパシティーの再調整にチェックを入れる。 ここでフリートの設定。 推奨事項の欄にチェックを入れればAWS側がおすすめの選択してくれるが以下のように自分で任意のインスタンスタイプを選択した上でAWSにその範疇で配分してもらうこともできる。 ここで重要なのがフリートの強度が十分であるかどうかで、ここで不足していると出てる場合はインスタンスタイプの組み合わせを変える必要がある。 なお、指定できるインスタンスは最小コンピュートユニットで指定したインスタンスタイプなどで変わる(最小コンピュートユニットをt2.microで指定した場合はt2.small、t2.micro、m1.small、m1.medium、m3.mediumしか指定できない。) フリートの配分戦略の部分がAWSがフリートリクエストで指定されたインスタンスタイプからスポットインスタンスのリクエストを満たしていくかの基準となる部分。 あとは設定を確認して作成すればOK。 AMI AMI(Amazon Machine Image)はOSイメージのこと。 OSイメージとはなにかというと仮想サーバー上で展開するOSの種類・設定・サーバーの構成情報・ルートボリュームに構成されたEBS、インスタンスのデータ……etcのことになる。 つまり、これまで起動ウィザードで作ってきたインスタンスのバックアップ的な存在でもありかつ起動ウィザードでこれまでAMIを選択してきたのはその点から見るとインスタンスの初期化を行っていたとも考えられる。 なので、作成したインスタンスからAMIを作っておけば同じインスタンスをそのAMIから複製することができる。 これを利用して東京リージョンで作ったインスタンスをAMIにして、別のリージョンにそのAMIをコピーしてインスタンスを作る……ということもできる。 実際には以下のようにしてAMIを作ることができる。 特徴としては AMIはリージョンで一意である(ただし上記のようにリージョンを跨いだAMIのコピーは可能) AWS提供のものと自作のインスタンスから作成したものの他に、サードパーティ製のものがマーケットプレイスで売られている サーバーのOSとしての選択肢であり、かつ利用していたサーバーのバックアップでもある EC2インスタンスのバックアップでもあるため、EBSボリュームのスナップショットも内包されるためEBSのバックアップであるとも言える 利用するにあたって最適なEC2インスタンスの構成(ゴールデンイメージ)がある場合、それをAMIイメージとしてバックアップを取ることで使い回すことができる 共有ができる(AWSアカウントID経由で共有する) EC2ImageBuilderを使って更新管理を自動化できる(後述) という点が挙げられる。 EC2 Image Builder EC2 Image Builder は、AWS またはオンプレミスで使用するための仮想マシンとコンテナイメージの構築、テスト、およびデプロイを簡素化します。 作成したAMIイメージのバージョン管理を自動で行ってくれるサービス。 スケジュールを設定しておけば、AMIイメージ内のソフトウェアの更新に際してテストを実行し問題なければ更新を行ってくれる。 Docker的に考えるとコンテナに引っ張ってきたイメージに更新があった場合、自動で構築をテストして更新してデプロイしてくれる……ということなのだろうか。 ともあれ自動更新がまずいという状況を除けば、保守の部分がかなり楽になるのは間違いないと感じる。 利点は以下のようなことが挙げられている。 イメージの更新・テスト・デプロイを自動化してくれる(この自動化のフローのことをパイプラインと呼ぶ) セキュリティリスクの低下(セキュリティパッチを自動で適用してくれる) 最新の仮想マシンとコンテナイメージを構築、保護、テストするためのワンストップショップが提供される(公式より) 本番環境に適用する前にAWS提供あるいはユーザー作成のテストでイメージの機能・互換性、セキュリティ・コンプライアンスを検証することを手助けしてくれる(ex. テストに通らなければデプロイはされない) AMIイメージをバージョン管理することができる AWS Resource Access Manager、AWS Organizations、Amazon ECRとの統合でAWSアカウント全体でEC2 Image Builderにおける自動化スクリプト、レシピ、AMIイメージの共有を行える 実際には以下のように作成する。 まずはパイプラインを作る。 ここではスケジュールリング部分を設定していく。 拡張メタデータ収集の欄にはチェックを入れるのがベター。 あとはスケジュールを決めるだけ。 依存関係の更新をトリガーとしてパイプラインは実行されるが、それを指定したスケジュールで確認して行うか、依存関係の更新が確認できたらスケジュールの週日部分を無視して、指定されている時間で実行するか選択できる。 次はレシピを作る。 以下をみればわかるがAMIの他にDockerイメージとしても作ることができる。 次にソースのイメージを選択する。 自作のAMIイメージがある場合は画像の通り指定する。 もし、1から作る場合はOSを選択することになる。 次にビルドコンポーネントを設定する。 ビルドコンポーネントはそのAMIを生成するために必要となるコンポーネント。 例えば、Apacheを入れてWebサーバーとしていたインスタンスをAMI化し、それをEC2 Image Builderで管理しようという事になった場合にはここでApacheを検索して選択しておかないといけない。 テストコンポーネントはイメージをビルドするときに実行するテストを選択できる。 以下のようにAWS提供のものもあれば、ユーザー自身で作成することもできる。 次はインフラストラクチャの設定。 ビルドをする際のテストに関わる部分。 パイプライン実行時にEC2インスタンスを自動で立ち上げてその中でテストを行うという仕組みになるので、そのEC2インスタンスの構成(それ故にインフラストラクチャ)をここで決めることができる。 自分で作ることもできるし、デフォルトで良ければAWSが勝手に作ってくれる。 ディストリビューションの設定。 テストで問題なければAMIイメージはビルド(デプロイ)されることになるので、その際に暗号化はするのか? 起動許可はどうするのか? ビルドじたAMIイメージはどのアカウントなら起動できるのか……といったセキュリティに関する部分を設定できる。 問題なければ以下のようにパイプラインが作成され、アクションから手動で実行もできる。 実行するとインスタンスが立ち上がって一連の処理が行われ、バージョンが割り振られたイメージが新しく作られる。 プレイスメントグループ 複数のインスタンスを論理的にグループ化して、パフォーマンスの向上や耐障害性の向上を図る機能。 3つのグループパターンがあるがそれぞれ構成するにあたって使えるインスタンスタイプが決まっている。 例えばクラスタープレイスメントグループの場合は 汎用……A1、M4、M5、M5a、M5ab、M5d、M5dn、M5n コンピューティング最適化……C3、C4、C5、C5d、C5n、cc2.8xlarge メモリ最適化……cr1.8large、R3、R4、R5、R5a、R5ad、R5d、R5dn、R5n、X1 ストレージ最適化……D2、H1、hs1.8large、I2、I3、I3en 高速コンピューティング……F1、G2、G3、G4dn、P2、P3、P3dn 以上のインスタンスタイプでしか構成できない。 なお実際に構成する場合はグループを作っておき、インスタンスを新しく作る際にそのグループに入れるように指定をすることで構成していく。 クラスタープレイスメントグループ 単一AZかつ単一パーティション内に複数のインスタンスを構成する。 特徴としては 単一AZ内のインスタンスを論理的にグループ化した構成 同じリージョン内の複数のピアVPCにまたがることも可能(VPC Peeringで連携されているVPC間) グループ内のインスタンスは、TCP/IPトラフィックのフローあたりのスループット(コンピュータシステムが単位時間に実行できる処理の件数や、通信回線の単位時間あたりの実効伝送量など)上限が高くなり、ネットワークの二分帯域幅の広い同じセグメントに配置され、インスタンス間通信が向上する 低ネットワークレイテンシー、高いネットワークスループットを実現するアプリ向け というものがある。 パーティションプレイスメントグループ クラスタープレイスメントグループ複数から構成されるグループ。 特徴としては 障害に対応するために構成するグループ パーティションで論理的なセグメントとしてクラスタープレイスメントグループが分割される プレイスメントグループ内の各パーティションにそれぞれ一連のラック(サーバーを入れる箱みたいなもの)があり、プレイスメントグループ内のパーティション同士は同じラックを共有しない。 ラックを分離することでアプリケーション内のハードウェア障害による影響を隔離して軽減する というものがある。 スプレットプレイスメントグループ 単一AZかつ単一パーティション内に1つのインスタンスを構成したものを並列に複数並べたもの。 特徴として それぞれに独自のネットワークおよび電源が異なるラックに別々にインスタンスが配置される つまり、インスタンスそれぞれが完全に分離される形になる 例として1つのAZ内の当該グループに配置された7つのインスタンスは、、7つの異なるラックに配置されることになる 少数の重要なインスタンスを互いに分離して保持できるので、同時障害のリスクを軽減することができる というものがある。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS 認定セキュリティの取得に向けた対策

はじめに 以前、こちらの記事でAWS認定セキュリティ取得に向けたポイントをまとめた AWS 認定セキュリティの取得に向けての学習 具体的にどのように取り組んでいくかを記載する。 ちなみに、私は『AWS 認定ソリューションアーキテクト – プロフェッショナル』を取得しているため、ある程度AWSの全体概要を理解している状態である。(ただし、実務経験はなし) 準備するもの 市販:要点整理から攻略する『AWS認定 セキュリティ-専門知識』 AWS サービス別資料 AWS 初心者向けハンズオン AWS Well-Architected Framework のセキュリティの柱 AWSデジタルコンテンツ(無料) AWSデジタルコンテンツ セキュリティ関連で日本語のコンテンツは下記がある Getting Started with AWS Security, Identity, and Compliance (Japanese) AWS Security Fundamentals (Second Edition) (Japanese) AWS Foundations: Securing Your AWS Cloud (Japanese) Deep Dive with Security: AWS Identity and Access Management (IAM) Protect Your Web-facing Workloads with AWS Security Services Exam Readiness: AWS Certified Security – Specialty 第1フェーズ 対策本:要点整理から攻略する『AWS認定 セキュリティ-専門知識』をまずは一通り、目を通してどのようなサービスが問題として出て、それぞれがどのような機能なのかの全体像を掴む。 カテゴリ AWSの公式より、問題の配分と分野は下記の通りである。 分野 出題の比率 インシデント対応 12% ログ記録とモニタリング 20% インフラストラクチャのセキュリティ 26% Identity and Access Management 20% データ保護 22% これらに各サービスを当てはめて整理する。 このようにしてみると、どのサービスから学ぶべきか見えてくると思います。 またBlackBeltに資料があるかの有無も記載した。 ※▲はメイン情報がないことを示している。(アップデート情報などはある) インシデント対応(12%) AWS Config | blackbelt◯ AWS Systems Manager | blackbelt◯ Amazon CloudWatch | blackbelt◯ AWS Trusted Advisor | blackbelt◯ AWS CloudTrail | blackbelt◯ AWS CloudFormation | blackbelt◯ Amazon Macie | blackbelt◯ Amazon GuardDuty | blackbelt◯ AWS Security Hub | blackbelt◯ Amazon Detective | blackbelt◯ ログ記録とモニタリング(20%) Amazon CloudWatch | blackbelt◯ AWS Config | blackbelt◯ AWS CloudTrail | blackbelt◯ AWS X-Ray | blackbelt◯ Amazon Inspector | blackbelt◯ S3 | blackbelt◯ Amazon Athena | blackbelt◯ VPCFlow Logs | blackbelt× Amazon QuickSight | blackbelt▲1 blackbelt▲2 Amazon Kinesis | blackbelt◯ Amazon Elasticsearch Service | blackbelt◯ インフラストラクチャのセキュリティ(26%) AWS WAF | blackbelt▲ AWS Shield | blackbelt◯1 blackbelt◯2 AWS Firewall Manager | blackbelt× Amazon Route53 | blackbelt◯1 blackbelt◯2 Amazon CloudFront | blackbelt◯ Elastic Load Balancing | blackbelt◯ AWS Auto Scaling | blackbelt◯ Amazon API Gateway | blackbelt◯ Amazon Virtual Private Cloud | blackbelt◯ Security Group | blackbelt× AWS Artifact | blackbelt◯ Identity and Access Management(20%) AWS IAM | blackbelt◯1 blackbelt◯2 AWS Directory Service | blackbelt◯ Amazon Cognito | blackbelt◯ AWS Organizations | blackbelt◯ データ保護(22%) AWS Key Management Service | blackbelt◯ AWS CloudHSM | blackbelt◯ Amazon Elastic Block Store | blackbelt◯ Amazon RDS | blackbelt◯ Amazon DynamoDB | blackbelt◯ Amazon S3 | blackbelt◯ AWS Secrets Manager&Parameter Store | blackbelt× 第2フェーズ 各サービスがどのような機能なのかを説明できるように、本やBlackBeltを熟読する。 まずは、サービス名が出された時に、機能を一言で表せるかどうかで判断する。 参考として下記に一言で表した表を用意した。 サービス名 機能 IAM AWSのサービスとリソースに対する認証認可を提供する Directory Service AWS内でマネージド型のMS ADを利用する Cognito Web/モバイルAPPのユーザーの認証認可を行う Organizations 複数AWSアカウントをまとめる AWS WAF Web Application Firewallのマネージドサービス AWS Shield DDos攻撃からシステムを守る AWS Firewall Manager AWS WAF、AWS Shield Advanced、VPC SGのポリシーを一言管理 Route53 DNSのマネージドサービス CloudFront 静的・動的データを高速に配信するCDN ELB アプリケーションへのトラフィックを複数のターゲットに分散させる Auto Scaling 事前設定に応じてサービス構成するリソースを自動増減させる API Gateway APIを作成、公開するためのサービス VPC AWS上に論理的に分離された領域を作成し、仮想NW環境を作る Security Group インスタンスに対する送受信トラフィックへのアクセス制御を行う AWS Artifact AWSのコンプライアンスドキュメントをダウンロードできる KMS データ暗号化に使用される暗号化キーの作成と管理を行う CloudHSM (より厳重に)データ暗号化に使用される暗号化キーの作成と管理を行う EBS EC2で使用されるストレージボリューム RDS リレーショナルデータベースを提供する DynamoDB NoSQLデータベースサービス S3 インターネットストレージサービス Secrets Manager パスワードなどの認証情報を管理する Secrets ManagerのParameter Store (プレーンな)パスワードなどの認証情報を管理する CloudWatch AWSサービスのメトリックス、ログ、イベントといったデータを収集し、可視化する Config AWSリソースやEC2、オンプレサーバの設定変更管理、変更履歴のモニタリングを行う CloudTrail AWSアカウントに対する操作のイベントログを記録する X-Ray APP内で発生するサービス間リクエストを収集&分析する Inspector セキュリティ評価のためのサービス S3にログ収集 ログファイルや結果ファイルがS3バケットに保存 Athena S3に格納されているデータに対し、SQL分析できる VPCFlow Logs VPC内のIPトラフィック状況をログとして保存するVPC機能 QuickSight マネージド型のビジネス分析(BI)する Kinesis ストリームデータを高速に取り込み、集約する Elasticsearch Service RESTful分析検索/分析エンジン(Elasticsearch)のクラスタをAWS上にデプロイして、利用する Systems Manager EC2やオンプレサーバを制御、管理する Trusted Advisor AWSが推奨するベストプラクティスに則り、アドバイスを提供 CloudFormation JSON/YAML形式でAWSリソースをテンプレートファイル化し、構築を自動化する Macie S3にある個人情報などを機密データとして自動発見し、通知/保護処理を実行する GuardDuty AWSで発生する不正やセキュリティイベント等の脅威を検出するサービス Security Hub AWSのセキュリティ状況やコンプライアンス準拠状況を1箇所で確認できる Detective AWSサービス情報をインプットに、潜在的なセキュリティ問題/不審なアクティビティを分析/調査できる その後、詳しい機能の理解を身につけていく。 AWSドキュメント 主要なサービスにはAWSが提供するドキュメントやベストプラクティスがあるので、そちらも熟知する IAMのベストプラクティス 一般的な Amazon Cognito シナリオ AWS Managed Microsoft AD のユースケース 第3フェーズ 以下の観点で各サービスの機能の理解をする。 視点 どの範囲のセキュリティサービスなのか どのように設定をするのか どのような仕組みなのか どのような選択肢があるのか どのような制限があるのか 知識 データの保護・暗号化方法 セキュアな通信方法 AWSリソースの保護(セキュア対策)方法 ログの収集と監視および確認方法 セキュリティ問題が起こったときの対応方法 日常的な運用とリスク 設定の確認や評価の方法 各AWSサービス同士の連携 第4フェーズ 次に、問題を解いてみる。 対策本:要点整理から攻略する『AWS認定 セキュリティ-専門知識』の各ページにある問題や巻末にある問題にチャレンジしてみた。大体7割〜8割取れたら良い方と思われる。 また、もっと問題を解きたいと言う人は下記にもチャレンジしてみると良い。 サンプル問題 模擬試験 4,000 円(税別) 第5フェーズ 問題も解いて、繰り返し対策本やBlackBeltを読み込んで自信がついたら試験にチャレンジ!! 申し込みはこちらから可能です。 持ち物や申し込みの仕方やオンライン試験も対応しており、初めての方は焦るかもしれませんが、その辺りはググってみてください!! 最後に AWS認定セキュリティの取得に向けた対策をまとめました!ぜひご参考に
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む