- 投稿日:2020-01-14T23:51:41+09:00
DynamoDBのテーブルデータをNodejsでS3にBackupする
はじめに
DynamoDBに大量にあるテーブルのデータを一括でS3にバックアップしたい。。みたいな状況があったので、メモとして書いておきます。
ちなみにテーブルが少量であれば、Data Pipelineを使って簡単に出来ます!!
aws-sdkではData Pipelineの細かいオプションは設定出来なかったようなので、nodejsでData Pipelineを操作することはしていません。環境
- Nodejs v11.1.0
- DynamoDB
事前準備
バックアップを行うためにS3に専用のバケットを作成しておいてください。
この記事ではbackupsというバケットを作成したという例で進めます。プロジェクトを作成
適当ですが、
dynamodb-backuperみたいなディレクトリを作成して進めていきます。$ mkdir dynamodb-backuper $ cd dynamodb-backuper $ npm init $ npm install aws-sdk dynamodb-backup-restore --save $ touch export.js restore.jsexport.js
export.jsはその名通りDynamoDBから全テーブルのbackupを行うファイルです。'use strict' const AWS = require('aws-sdk') const DynamoDB = new AWS.DynamoDB({region: 'ap-northeast-1'}) async function main(){ let tables = await getAllTableLists() tables.forEach((v) => { exportToS3(v) }) } // 実行 main() // Get all table names from DynamoDB async function getAllTableLists() { let params = {} let tables = [] while(true) { let response = await DynamoDB.listTables(params).promise() tables = tables.concat(response.TableNames) if (!response.LastEvaluatedTableName) { break } else { params.ExclusiveStartTableName = response.LastEvaluatedTableName } } return tables } // Function to perform backup function exportToS3(tableName){ const Backup = require('dynamodb-backup-restore').Backup let config = { S3Bucket: 'backups', // 必須 - バケット名 S3Prefix: tableName, // 任意 - 保存するS3のサブフォルダ名 S3Encryption: 'AES256', // 任意 - 暗号化 S3Region: 'ap-northeast-1', // 必須 - リージョン DbTable: tableName // 必須 - エクスポートするテーブル名 } let backup = new Backup(config) backup.full() }以下でエクスポートを実行出来ます。
$ node export.jsrestore.js
restore.jsもそのままですが、export.jsでS3にエクスポートしたデータを今度はDynamoDBの指定のテーブルにインポートします。リストアを行う前に事前にインポートするテーブルを作成しておく必要があります。
今回はnewTest1というテーブルを作ったとして進めます。
この時に注意が必要なのが、データ量によっては無料枠ではキャパシティーレベルが超えてしまうため、データサイズに応じてオンデマンドに変更してください。以下のコードでは、
execRestore関数の第一引数にS3にバックアップをとったtest1というサブフォルダを指定し、インポート用に作成したnewTest1というテーブル名を第二引数に設定します。'use strict' function execRestore(bucketName, tableName){ const Restore = require('dynamodb-backup-restore').Restore let config = { S3Bucket: 'backups', // 必須 S3Prefix: bucketName, // 任意 S3Region: 'ap-northeast-1', // 必須 DbTable: tableName, // 必須 DbRegion: 'ap-northeast-1', // 必須 } Restore(config) } // 実行 execRestore('test1', 'newTest1')以下でリストアを実行出来ます。
$ node restore.js
- 投稿日:2020-01-14T22:16:35+09:00
Amazon EKS のチュートリアルで Kubernetes を理解する #03 メトリクス&ダッシュボード
はじめに
本記事は、以下の内容の続きになります。
前回、k8sクラスタにアプリケーションをデプロしてみたので、
今回は、クラスタやアプリケーションのモニタリングを行ってみます。前提条件
- k8sのクラスタが作成されており、ワーカーノードが稼働していること。
Kubernetes Metrics Server の構築
Kubernetesには、メトリクスサーバー(metrics-server)というモノがあり、
これを利用することで、クラスタに登録された各種リソースの情報を簡単に取得できるようになります。Kubernetes Metrics Server のデプロイ
ここでは、最新版をダウンロードして、クラスタに登録を行います。
$ cd /Users/$USERNAME/MyWork/amazon-eks $ DOWNLOAD_URL=$(curl -Ls "https://api.github.com/repos/kubernetes-sigs/metrics-server/releases/latest" | jq -r .tarball_url) $ DOWNLOAD_VERSION=$(grep -o '[^/v]*$' <<< $DOWNLOAD_URL) $ curl -Ls $DOWNLOAD_URL -o metrics-server-$DOWNLOAD_VERSION.tar.gz $ mkdir metrics-server-$DOWNLOAD_VERSION $ tar -xzf metrics-server-$DOWNLOAD_VERSION.tar.gz --directory metrics-server-$DOWNLOAD_VERSION --strip-components 1 $ kubectl apply -f metrics-server-$DOWNLOAD_VERSION/deploy/1.8+/ clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created serviceaccount/metrics-server created deployment.apps/metrics-server created service/metrics-server created clusterrole.rbac.authorization.k8s.io/system:metrics-server created clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created動作確認
以下で、metrics-serverのDeploymentで、必要な数のポッドが実行されていることが確認できます。
$ kubectl get deployment metrics-server -n kube-system NAME READY UP-TO-DATE AVAILABLE AGE metrics-server 1/1 1 1 2m55sKubernetes Dashboard の構築
metrics-server単体では、メトリクスの可視化はされません。
メトリクスの可視化を行うために、Kubernetes ダッシュボード を構築します。Kubernetes Dashboard のデプロイ
まずは、Kubernetes のGitHubリポジトリで公開されているダッシュボードの定義を取得し、クラスタにデプロイします。
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta4/aio/deploy/recommended.yaml namespace/kubernetes-dashboard created serviceaccount/kubernetes-dashboard created service/kubernetes-dashboard created secret/kubernetes-dashboard-certs created secret/kubernetes-dashboard-csrf created secret/kubernetes-dashboard-key-holder created configmap/kubernetes-dashboard-settings created role.rbac.authorization.k8s.io/kubernetes-dashboard created clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created deployment.apps/kubernetes-dashboard created service/dashboard-metrics-scraper created deployment.apps/dashboard-metrics-scraper createdサービスアカウント/クラスターロールバインディングの作成
デフォルトでは、Kubernetes ダッシュボードへのアクセスは制限されています。
そのため、管理者レベルのアクセス権限を使用してダッシュボードに安全に接続するために使用できるようにします。「eks-admin-service-account.yaml」というファイルを作成します。
$ touch eks-admin-service-account.yamlそのファイルに、以下の内容を定義します。
ここでは、サービスアカウントと、eks-admin と呼ばれるクラスターロールバインディングを定義しています。apiVersion: v1 kind: ServiceAccount metadata: name: eks-admin namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: eks-admin roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: eks-admin namespace: kube-system上記内容を、クラスタにデプロイします。
$ kubectl apply -f eks-admin-service-account.yaml serviceaccount/eks-admin created clusterrolebinding.rbac.authorization.k8s.io/eks-admin createdダッシュボードへの接続
先の手順で、クラスタの状態を表示可能な管理者サービスアカウントを作成したため、このサービスアカウントを使用してダッシュボードに接続します。
まず、サービスアカウントの認証トークンを取得します。
$ kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep eks-admin | awk '{print $1}')以下のような内容が出力されるので、そこから
<authentication_token>の値をコピーしておきます。
このトークンを使用してダッシュボードに接続します。Name: eks-admin-token-jnn96 Namespace: kube-system Labels: <none> Annotations: kubernetes.io/service-account.name: eks-admin kubernetes.io/service-account.uid: e9201e83-3454-11ea-bc0a-0e7ed5a45fb2 Type: kubernetes.io/service-account-token Data ==== ca.crt: 1025 bytes namespace: 11 bytes token: <authentication_token>ローカル環境から、ダッシュボードへアクセスできるよう、
kubectl proxyを開始します。
以下のコマンドを実行したら、そのまま実行中の状態になるため、ダッシュボードへの接続確認ができるまで、
コンソールはそのままにしておきます。kubectl proxyブラウザで以下のリンクを開いて、ダッシュボードのエンドポイントにアクセスします。
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#!/loginさらに、[トークン] を選択して、先の手順でコピーしておいた
<authentication_token>の内容を [トークン] フィールドに貼り付け、[サインイン] を押下します。
接続に成功すると、以下のようなダッシュボード画面が表示されます。このダッシュボード画面から、ノードの状態や、PodやReplicaSetなどのワークロードの情報など、
各種のクラスタの情報を確認することができます。まとめ
Kubernetes Metrics Server/Kubernetes Dashboard を利用することで、
クラスタの構成や各種リソースの状況などを簡単に確認できるようになるので、
まずはクラスタ構成や動作を理解するには、このダッシュボードの画面を確認しながら操作してみると、
効率的に内容を把握できるかと思います。
- 投稿日:2020-01-14T20:34:53+09:00
AWS APIGateway/LambdaとJavascriptで簡易問い合わせサイトをつくる
概要
問い合わせフォーム(javascript) ⇒ APIGateway ⇒ Lambda(Node.js) ⇒ Lambda(Node.js) の流れで簡単な問い合わせサイトを作ります。
一応レスポンシブにします。
バリデーションもあります。
index.htmlのコーディング
index.html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <link rel="stylesheet" href="style.css" /> <title>問い合わせ</title> </head> <body> <div class="header"> <a href="#" class="logo">Hoge Hoge Company</a> <a class="active" href="#">Home</a> </div> <main class="main-container"> <h2>問い合わせフォーム</h2> <div class="container"> <form id="form"> <div class="row"> <div class="col-20"> <label for="name">名前</label> </div> <div class="col-80"> <input type="text" id="name" name="name" placeholder="Your name.." /> </div> </div> <div id="name-alert" class="alert-message" hidden>入力値が不正です。</div> <div class="row"> <div class="col-20"> <label for="email">E-Mail</label> </div> <div class="col-80"> <input type="email" id="email" name="email" placeholder="Your E-Mail.." /> </div> </div> <div id="email-alert" class="alert-message" hidden>入力値が不正です。</div> <div class="row"> <div class="col-20"> <label for="dept">所属</label> </div> <div class="col-80"> <input type="text" id="dept" name="dept" placeholder="Ex: Example Co., Ltd." /> </div> </div> <div id="dept-alert" class="alert-message" hidden>入力値が不正です。</div> <div class="row"> <div class="col-20"> <label for="body">内容</label> </div> <div class="col-80"> <textarea id="body" name="body" placeholder="お気軽にお問い合わせください。" style="height:200px"></textarea> </div> </div> <div id="body-alert" class="alert-message" hidden>入力値が不正です。</div> <div class="row"> <button id="submitBtn">送信</button> </div> </form> </div> <!-- The Modal --> <div id="myModal" class="modal"> <!-- Modal content --> <div id="modal-content"> <span class="close">×</span> <p id="result"></p> <p id="detail" style="font-size: small;"></p> </div> </div> </main> <script src="main.js" defer></script> </body> </html>CSSのコーディング
style.css* { margin: 0; padding: 0; font-family: "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", "メイリオ", Meiryo, "MS Pゴシック", sans-serif; } /* Style the header with a grey background and some padding */ .header { display: flex; flex-flow: row wrap; align-items: center; justify-content: space-between; background-color: #000000; padding: 20px 10px; } /* Style the header links */ .header a { color: #f2f2f2; text-align: center; padding: 12px; text-decoration: none; font-size: 18px; line-height: 25px; border-radius: 4px; } /* Style the logo link (notice that we set the same value of line-height and font-size to prevent the header to increase when the font gets bigger */ .header a.logo { font-size: 25px; font-weight: bold; } /* Change the background color on mouse-over */ .header a:hover { background-color: #ddd; color: black; } /* Style the active/current link*/ .header a.active { background-color: dodgerblue; color: white; } /* Add media queries for responsiveness - when the screen is 500px wide or less, stack the links on top of each other */ @media screen and (max-width: 500px) { .header { justify-content: center; } .header a { padding: 12px; } } .main-container { width: 90%; margin: auto; } .main-container h2 { margin-top: 12px; } /* Style inputs, select elements and textareas */ input, textarea { width: 100%; padding: 12px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; resize: vertical; } .alert-red { border: #ff4500 2px solid; } .alert-green { border: #00ff7f 2px solid; } .alert-message { color: #ff4500; font-size: small; text-align: end; margin-bottom: 10px; } /* Style the label to display next to the inputs */ label { padding: 12px 12px 12px 0; display: inline-block; } /* Style the submit button */ #submitBtn { background-color: #4caf50; color: white; padding: 10px 18px; border: none; border-radius: 4px; cursor: pointer; font-size: 15px; float: right; } /* Style the container */ .container { border-radius: 5px; background-color: #f2f2f2; padding: 20px; } /* Floating column for labels: 25% width */ .col-20 { float: left; width: 20%; margin-top: 6px; } /* Floating column for inputs: 75% width */ .col-80 { float: left; width: 80%; margin-top: 6px; } /* Clear floats after the columns */ .row:after { content: ""; display: table; clear: both; } /* Responsive layout - when the screen is less than 600px wide, make the two columns stack on top of each other instead of next to each other */ @media screen and (max-width: 600px) { .col-20, .col-80, #submitBtn { width: 100%; margin-top: 0; } } /* The Modal (background) */ .modal { display: none; /* Hidden by default */ position: fixed; /* Stay in place */ z-index: 1; /* Sit on top */ left: 0; top: 0; width: 100%; /* Full width */ height: 100%; /* Full height */ overflow: auto; /* Enable scroll if needed */ background-color: rgb(0, 0, 0); /* Fallback color */ background-color: rgba(0, 0, 0, 0.4); /* Black w/ opacity */ } /* Modal Content/Box */ #modal-content { background-color: #fefefe; margin: 15% auto; /* 15% from the top and centered */ padding: 20px; width: 80%; /* Could be more or less, depending on screen size */ } .request-loading { border: 1px solid #888; } .request-success { border: 1px solid #00ff7f; } .request-fail { border: 1px solid #ff4500; } /* The Close Button */ .close { color: #aaa; float: right; font-size: 28px; font-weight: bold; } .close:hover, .close:focus { color: black; text-decoration: none; cursor: pointer; }javascriptのコーディング
変数URLはAPIGatewayで発行してから実装します。
main.jsconst URL = 'https://'; // APIGatewayで作成したURL const LOADING = '処理中...'; const RESULT_OK = 'リクエストを受け付けました。'; const RESULT_OK_DETAIL = "正常に処理が完了すると 'support@hogehoge.com' からメールが配信されます。"; const RESULT_NG = 'リクエストの受付に失敗しました'; const RESULT_NG_DETAIL = '大変申し訳ありません。担当者へ直接お問い合わせください。'; const DOMAIN = '@sample.com'; document.getElementById('email').value = DOMAIN; (() => { const modal = document.getElementById('myModal'); const modalContent = document.getElementById('modal-content'); const sendBtn = document.getElementById('submitBtn'); const span = document.getElementsByClassName('close')[0]; const result = document.getElementById('result'); const form = document.getElementById('form'); const nameAlert = document.getElementById('name-alert'); const emailAlert = document.getElementById('email-alert'); const deptAlert = document.getElementById('dept-alert'); const bodyAlert = document.getElementById('body-alert'); const resultDetail = document.getElementById('detail'); const inputValueClear = () => { form.name.value = ''; form.name.setAttribute('class', ''); form.email.value = DOMAIN; form.email.setAttribute('class', ''); form.dept.value = ''; form.dept.setAttribute('class', ''); form.body.value = ''; form.body.setAttribute('class', ''); result.innerHTML = ''; }; // When the user clicks on <span> (x), close the modal span.onclick = () => { if (result.innerHTML !== LOADING) { modal.style.display = 'none'; if (result.innerHTML === RESULT_OK) inputValueClear(); } }; // When the user clicks anywhere outside of the modal, close it window.onclick = event => { if (event.target === modal) { if (result.innerHTML !== LOADING) { modal.style.display = 'none'; if (result.innerHTML === RESULT_OK) inputValueClear(); } } }; sendBtn.addEventListener('click', async event => { event.preventDefault(); const name = form.name.value.trim(); form.name.value = name; const email = form.email.value.trim(); form.email.value = email; const dept = form.dept.value.trim(); form.dept.value = dept; const body = form.body.value.trim(); form.body.value = body; // validation check if (validation(name, email, dept, body)) return; result.innerHTML = LOADING; modalContent.setAttribute('class', 'request-loading'); modal.style.display = 'block'; const jsonData = JSON.stringify({ name, email, dept, body }); try { const res = await fetch(URL, { method: 'POST', mode: 'cors', cache: 'no-cache', body: jsonData, headers: { 'Content-Type': 'application/json; charset=utf-8' } }); console.log('Response!!', res.status); modalContent.setAttribute('class', 'request-success'); result.innerHTML = RESULT_OK; resultDetail.innerHTML = RESULT_OK_DETAIL; } catch (error) { console.log(error); modalContent.setAttribute('class', 'request-fail'); result.innerHTML = RESULT_NG; resultDetail.innerHTML = RESULT_NG_DETAIL; } }); const validation = (name, email, dept, body) => { let validationResult = false; if (!name.length) { form.name.setAttribute('class', 'alert-red'); nameAlert.hidden = false; validationResult = true; } else { form.name.setAttribute('class', 'alert-green'); nameAlert.hidden = true; } if (!email.length || !/^[^@]+@sample.com$/.test(email)) { form.email.setAttribute('class', 'alert-red'); emailAlert.hidden = false; validationResult = true; } else { form.email.setAttribute('class', 'alert-green'); emailAlert.hidden = true; } if (!dept.length) { form.dept.setAttribute('class', 'alert-red'); deptAlert.hidden = false; validationResult = true; } else { form.dept.setAttribute('class', 'alert-green'); deptAlert.hidden = true; } if (!body.length) { form.body.setAttribute('class', 'alert-red'); bodyAlert.hidden = false; validationResult = true; } else { form.body.setAttribute('class', 'alert-green'); bodyAlert.hidden = true; } return validationResult; }; form.name.addEventListener('input', event => { const name = event.target.value.trim(); if (!name) { event.target.setAttribute('class', 'alert-red'); nameAlert.hidden = false; } else { event.target.setAttribute('class', 'alert-green'); nameAlert.hidden = true; } }); form.email.addEventListener('input', event => { const email = event.target.value.trim(); event.target.value = email; if (!email || !/^[^@]+@sample.com$/.test(email)) { event.target.setAttribute('class', 'alert-red'); emailAlert.hidden = false; } else { event.target.setAttribute('class', 'alert-green'); emailAlert.hidden = true; } }); form.dept.addEventListener('input', event => { const dept = event.target.value.trim(); event.target.value = dept; if (!dept) { event.target.setAttribute('class', 'alert-red'); deptAlert.hidden = false; } else { event.target.setAttribute('class', 'alert-green'); deptAlert.hidden = true; } }); form.body.addEventListener('input', event => { const body = event.target.value.trim(); if (!body) { event.target.setAttribute('class', 'alert-red'); bodyAlert.hidden = false; } else { event.target.setAttribute('class', 'alert-green'); bodyAlert.hidden = true; } }); })();AWS SES(Simple Email Service)を設定
※ドメインはRoute53で取得済みの前提
※併せてACM(AWS Certificate Manager)で証明書を取得済み
※SESは送信のみの設定です。
- AWSへログイン
- SESのコンソールへ移動
- リージョンはバージニア北部を選択
- 左のナビゲーションから
Domainsを選択![]()
をクリック
- ↓のように入力。自分のドメインとDKIM設定をチェックして、
をクリック
![]()
- 次のモーダルではCNAMEやTXTが表示され、登録しろと指示が出る。Route53を利用している場合は、このモーダル上でDNSの登録がすべて完了する。
- こんな感じになればOK!(※現時点ではサンドボックス上での制限された利用が可能)
![]()
- 左のナビゲーションで
Email Addressesを選択![]()
Veryfy a New Email Addressでサンドボックス上で利用できるメールアドレスを登録する。- 登録したメールアドレスを
Send a Test Emailで登録したドメインからメールが送られるかテストして正常な動作を確認最後に起動するLambdaを作成
- Lambdaのコンソールページへ移動
をクリック
を選択
適当な関数名を入力
- ランタイムは
Node.js 12.xを選択- そのほかはデフォルトのままでOK
をクリック
- 環境変数へ配信元のアドレスを設定
![]()
- 実行ロールにはSESの権限を許可
![]()
- 関数コードへ↓のコードを実装
index.js'use strict' const SES = require("aws-sdk/clients/ses"); const ses = new SES({ region: "us-east-1" }); // 米国東部(バージニア北部) const FROM = process.env.FROM; // 環境変数から取得 exports.handler = async (event) => { console.log(event); const TO = [event.email]; const params = { Destination: { ToAddresses: TO }, Message: { Body: { Text: { Data: [ event.dept + ' ' + event.name + ' 様', ' ', 'Hoge Hoge Companyです。', 'お問い合わせしていただきありがとうございます。', '下記の内容で承りました。', ' ', '[お問い合わせ内容]' + "\n" + event.body, ].join("\n"), Charset: "utf-8" } }, Subject: { Data: '受付完了:Webからの問い合わせ', Charset: "utf-8" } }, // From Source: FROM }; const result = {statusCode: 200}; try { const response = await ses.sendEmail(params).promise(); console.log('Response: ', response); result.body = 'OK!!!!!'; } catch (error) { console.log('Error: ', error); result.statusCode = error.code; result.body = error.message; } return result; };※
process.envでは環境変数で設定したキーと値が利用可能(暗号化も可能)最後に起動するLambdaのテスト
テストイベントの選択をクリック
- ↓のようにテストを作成(※emailキーにはSESで登録したアドレスを記載すること)
![]()
をクリックしてテスト実行
- 成功となればOK。失敗ならログを確認。
![]()
- テストでemailキーに指定したアドレスにメールが配信されていればOK
最初に起動するLambdaを作成
- Lambdaのコンソールページへ移動
をクリック
を選択
適当な関数名を入力
- ランタイムは
Node.js 12.xを選択- そのほかはデフォルトのままでOK
をクリック
- 環境変数へ配信元のアドレスと受付先のアドレスを入力
![]()
- 実行ロールはSESとLambdaの権限を追加
![]()
- 関数コードへ↓のコードを実装
index.js'use strict' const SES = require("aws-sdk/clients/ses"); const ses = new SES({ region: "us-east-1" }); // 米国東部(バージニア北部) const TO = [process.env.TO]; // 環境変数からの値を取得 const FROM = process.env.FROM; // 次のLambdaを起動するための設定 const Lambda = require("aws-sdk/clients/lambda"); const lambda = new Lambda({ region: "ap-northeast-1" }); exports.handler = async (event) => { const name = event.form.name; const email = event.form.email; const dept = event.form.dept; const body = event.form.body; const sesParams = { Destination: { ToAddresses: TO }, Message: { Body: { Text: { Data: [ '[名前] : ' + name, '[メールアドレス] : ' + email, '[所属部署] : ' + dept, '[お問い合わせ] : ' + "\n" + body, ].join("\n"), Charset: "utf-8" } }, Subject: { Data: 'Webからの問い合わせ', Charset: "utf-8" } }, // From Source: FROM }; // 次のLambdaに送るデータ const payload = { name, email, dept, body }; console.log('payload: ', payload); const lambdaParams = { FunctionName: "inpuirySendMailForm_2nd", // 最後に起動するLambdaの名称 InvocationType: "Event", Payload: JSON.stringify(payload) }; const result = {statusCode: 200}; try { const response = await ses.sendEmail(sesParams).promise(); console.log('Response: ', response); const callLambda = await lambda.invoke(lambdaParams).promise(); console.log("Lambda Response: ", callLambda); result.body = 'OK!!!!!'; } catch (error) { console.log('Error: ', error); result.statusCode = error.code; result.body = error.message; } return result; };最初に起動するLambdaのテスト(次のLambdaも起動する)
テストイベントの選択をクリック
- ↓のようにテストを作成
![]()
をクリックしてテスト実行
- 成功となればOK。失敗ならログを確認。
![]()
- テストでemailキーに指定したアドレスに受付完了メールが配信され、環境変数でTOに指定した受付先アドレスへ問い合わせ内容が配信されていればOK
APIGatewayの設定
をクリック
REST APIの構築を選択![]()
API名と説明を入力してAPIの作成をクリック(他はデフォルト)![]()
- アクション⇒リソースの作成を選択⇒リソース名を入力(リソースパスは自動入力)⇒CORSを有効化⇒リソースの作成をクリック
- アクション⇒メソッドの作成⇒POSTを選択⇒セットアップで最初に起動するLambda関数名を入力⇒保存をクリック
- 統合リクエストをクリック⇒マッピングテンプレートを追加⇒Content-Typeは
application/json⇒テンプレートには↓を入力⇒保存をクリック{ "form": { "name": "$util.escapeJavaScript($input.path('$.name'))", "email": "$util.escapeJavaScript($input.path('$.email'))", "dept": "$util.escapeJavaScript($input.path('$.dept'))", "body": "$util.escapeJavaScript($input.path('$.body'))" } }APIGatewayのテスト
APIGatewayのステージを作成
今回はv1というステージを作成
APIGatewayのデプロイ
リソース⇒アクション⇒APIのデプロイを選択⇒v1ステージを選択して⇒デプロイをクリック
発行されたURLをjavascriptのURL変数へ割り当て
全体の動作確認
問い合わせフォームへSESで登録したアドレスと必要事項を入力し、送信ボタンをクリックして動作を確認
実用化に向けて
- LambdaのSDK呼び出しは動作確認ができているバージョンが呼び出されるようにする必要あり。
- SESの上限緩和申請が必要。
- APIGatewayでリソースポリシーを指定して不要なアクセスを防ぐ
最後に
かなり大雑把に書きました。
小規模利用なら十分かと思います。
役に立つかな?
計画性なく作ってしまったのでここからブラッシュアップ
- 投稿日:2020-01-14T19:25:53+09:00
AWSでsshコマンドで接続できない場合の対処
AWSでEC2インスタンスを作成した際にキーペアを作成してダウンロードしたかと思います。
※キーペアとは拡張子.pemのことです。キーペアが存在しているディレクトリにまでcdコマンドを使い移動します。
$ cd downloads
rooter:downloads ユーザー名
私の場合downloadsディレクトリに中にキーペアが存在しています。ディレクトリまで移動ができましたら下記sshコマンド実行!
$ ssh -i "book.pem" ec2-user@52.218.324.29接続できました!
@の後ろは人によるパブリックアドレスが違います。
下記画像でいうところのIPv4パブリックIPと赤枠で囲っている部分です。
- 投稿日:2020-01-14T19:25:53+09:00
AWSでsshコマンドで接続できない場合2STEPで対処しよう!
以前AWSを使用していてsshで接続ができていたのに、寝て起きたら接続できなくなり焦ったのでまとめてみました。(; ・`д・´)
1.まずAWSでEC2インスタンスを作成した際にキーペアを作成してダウンロードしたかと思います。
※キーペアとは拡張子.pemのことです。キーペアが存在しているディレクトリにまでcdコマンドを使い移動します。
$ cd downloads
rooter:downloads ユーザー名
$ pwd
User/ユーザ名/downloads
※私の場合downloadsディレクトリの中にキーペアが存在しています。2.ディレクトリまで移動ができましたら下記sshコマンド実行!
$ ssh -i "book.pem" ec2-user@13.218.324.29
※book.pemとは私のキーペア名です。接続できました!
@の後ろはパブリックアドレスが人により違います。
下記画像でいうところのIPv4パブリックIPと赤枠で囲っている部分です。
- 投稿日:2020-01-14T18:29:38+09:00
【AWS】SSM Session Managerの利用方法について
Session Manager用のEC2ロールを作成する
アタッチするポリシー
- AmazonSSMManagedInstanceCore
System Managerサービスコア機能にアクセスするために必要なアクセス許可- AmazonSSMDirectoryServiceAccess
Windows Server の EC2 インスタンスを Microsoft AD ディレクトリに結合する場合にのみ必要なアクセス許可- CloudWatchAgentServerPolicy
メトリクスを読み取り、インスタンスにデータのログを記録して、Amazon CloudWatch に書き込むために、インスタンスにCloudWatchエージェントをインストールして実行する場合に必要なアクセス許可EC2へのロール割り当て
設定したいEC2インスタンスを選択し、
IAMロールの割り当てを押します。
設定したいIAMロールを選択し、
適用をクリックします。EC2の再起動を行い、設定を反映させます。
再起動できない場合は、SSMサービスの再起動でも良いそうです!
※ 15分ほど待てば反映されます。接続してみる
AWS System Managerのセッションマネージャーの項目に移動し、セッションの開始を選択します。
正しく接続されていると思います。
プライベートEC2に接続する為には
VPC内のプライベートなEC2を作成して以下の手順をおこなってください。
1.SSMエージェントの確認
SSMエージェントがインスタンスにインストールされていることを確認します。
2.IAMロールの作成
上記で作成したSystem Manager用のIAMロールを作成してください。
3.IAMロールの割り当て
上記で作成したSystem Manager用のIAMロールをEC2に割り当ててください。
4.VPC IDとSubnet IDの確認
Amazon EC2コンソールを開いてからインスタンスを選択し、VPC IDとSubnet IDをメモします。
5. エンドポイントの作成 × 3個
System Manager用のVPCエンドポイントを3つ作成します。
1個目 : com.amazonaws.region.ssm
こちらのページで作成します。
サービスを名前で検索をクリックし、
Service Name で com.amazonaws.region.ssm を入力し、検証を押します。
regionの値は自分の環境で置き換えてください。
東京の場合:com.amazonaws.ap-northeast-1.ssmVPC で、ご自身のインスタンスの
VPC IDを選択します。
サブネット でインスタンスのSubnet IDを選択します。
Enable Private DNS Name で
このエンドポイントで有効にするを選択します。
Security Group をクリックし、既存のセキュリティグループを選択するか、新しいセキュリティグループを作成します。セキュリティグループはポート 443 でインスタンスからのインバウンドトラフィックを許可する必要があります。
今回は、新しくセキュリティーグループを作成します。
セキュリティーグループの作成をクリックし、適当な「名前」と「説明」を入力します。
また、VPCは現在、対象としているVPCを選択してください。
セキュリティーグループの新規作成が完了したら、インバウンドのルールを設定します。
タイプで
HTTPSを選択し、
ソースは、操作したいEC2インスタンスが所属するSubNetのCRIDを選択します。
新しいセキュリティグループを作成する場合は、Group ID をメモします。
エンドポイントの作成画面へ戻り、先ほど作成したセキュリティーグループを選択します。
2個目 : com.amazonaws.region.ec2messages
Service Name で com.amazonaws.region.ec2messages を入力し、
検証を押します。
regionの値は自分の環境で置き換えてください。
東京の場合:com.amazonaws.ap-northeast-1.ec2messages
VPCとサブネット・セキュリティーグループも1個目と同様に選択します。3個目 : com.amazonaws.region.ssmmessages
Service Name で com.amazonaws.region.ssmmessages を入力し、
検証を押します。
regionの値は自分の環境で置き換えてください。
東京の場合:com.amazonaws.ap-northeast-1.ssmmessages
VPCとサブネット・セキュリティーグループも1個目と同様に選択します。接続してみます
選択する欄に表示され接続する事ができました。
参考サイト
Systems Manager を使用してインターネットアクセスなしでプライベート EC2 インスタンスを管理できるように、VPC エンドポイントを作成するにはどうすればよいですか?
- 投稿日:2020-01-14T18:03:24+09:00
無駄なEBSスナップショットをLambdaで定期削除する
「不要になったAMIを登録解除したけど、EBSスナップショットは消し忘れちゃって無駄なスナップショットがたくさん残っちゃってる...」ってこと結構あると思います。
こういう明らかに不要なスナップショットは、Lambdaの定期実行などを利用して自動的に削除されるようにしちゃいましょう。無駄なスナップショットを残しておくと、スナップショットの管理が煩雑になるし、そのスナップショットにも費用がかかるので、消しちゃうに越したことはありません。
まずAMI登録解除時に消し忘れたスナップショットを一括削除するLambdaは以下のようになります。
import boto3 ec2 = boto3.client("ec2") def lambda_handler(event, context): #AMIと共に作られたsnapshotを抽出 response = ec2.describe_snapshots( Filters=[ { 'Name': 'description', 'Values': [ 'Created by CreateImage*', ] }, { 'Name': 'owner-id', 'Values': ['************'] #AWSアカウントID } ] ) is_unnecessary = {} for snapshot in response['Snapshots']: is_unnecessary[snapshot['SnapshotId']] = True #現在登録中のAMIを抽出 response = ec2.describe_images( Filters=[ { 'Name': 'owner-id', 'Values': ['************'] #AWSアカウントID } ] ) #現在登録中のAMIで使われているsnapshotのみFalseにする for image in response['Images']: for bdm in image['BlockDeviceMappings']: try: is_unnecessary[bdm['Ebs']['SnapshotId']] = False except KeyError: continue i = 0 for snapshot_id in is_unnecessary.keys(): if is_unnecessary[snapshot_id]: ec2.delete_snapshot(SnapshotId=snapshot_id) i = i + 1 print('Delete ' + str(i) + ' Snapshots')これを
CloudWatch Eventsを使って定期実行させます。
cron式を使えば簡単に定期実行させることができます。
Schedule Expressions for Rules
例えば月次実行とかにしたい場合は0 0 1 * ? *とかで大丈夫です。これで定期的に無駄なEBSスナップショットが削除されるようになります。
※注意: ここでいう「不要なスナップショット」はAMI登録解除時に消し忘れたスナップショットのことだけを指します。各々が手動で作成したスナップショットは、タグ付けなどをして自己で管理してください。
- 投稿日:2020-01-14T13:20:26+09:00
CodebuildでS3に静的ホスティングを自動化
概要
- 10分程で設定可能です。
- AWS Codebuildでビルドを行う。
- Amazon S3に静的ホスティングをする。
- GithubをWebhookして、上記を自動化する。
登場人物の紹介
AWS Codebuild
AWS CodeBuild は、クラウドで動作する完全マネージド型のビルドサービスです。CodeBuild はソースコードをコンパイルし、ユニットテストを実行して、すぐにデプロイできるアーティファクトを生成します。CodeBuild により、独自のビルドサーバーのプロビジョニング、管理、スケーリングが不要になります。Apache Maven、Gradle などの一般的なプログラミング言語とビルドツール用のパッケージ済みのビルド環境を提供します。CodeBuild のビルド環境をカスタマイズして、独自のビルドツールを使用することもできます。CodeBuild はピーク時のビルドリクエストに合わせて自動的にスケーリングします。 公式
要するに、『ビルドを行い、ユニットテストを実行し、すぐにデプロイできるバイナリファイル的なものを作成する』です。
Amazon S3
Amazon S3は、Amazon Simple Storage Service はインターネット用のストレージサービスです。また、ウェブスケールのコンピューティングを開発者が簡単に利用できるよう設計されています。
Amazon S3 のウェブサービスインターフェイスはシンプルで、いつでも、ウェブのどこからでも容量に関係なくデータを格納および取得できます。これにより、すべての開発者が、スケーラブルで信頼性が高く、かつ高速で安価なデータストレージインフラストラクチャを利用できるようになります。このインフラストラクチャは、Amazon が使用しているウェブサイトのグローバルネットワークと同じものです。このサービスの目的は、規模の拡大や縮小のメリットを最大限に活かし、開発者に提供することです。要するに、『ほぼ無限大に入るストレージ』です。公式
Github
省略
以上で登場人物の紹介を終わります。
具体的な設定等
ディレクトリ構造
AWSでCodeBuildする際は、ディレクトリ構造を正確に把握しておくことが非常に重要です。
私の場合は、以下のようなディレクトリ構造になっています。
今回、AWS Codebuildでビルドを行い、デプロイしようとしているのは、frontディレクトリの中身です。 これらのコードをbackendやdatabaseも含めてGithubの任意のリポジトリにPushしておきます。
package.jsonのscript部分の内容
"scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" },buildspec.ymlの内容
version: 0.2 phases: install: runtime-versions: nodejs: 10 pre_build: commands: - echo Installing source NPM dependencies... - cd front - yarn install build: commands: - yarn build post_build: commands: - echo Build completed on `date` - echo Distributing to S3... - aws s3 sync --exact-timestamps --delete build s3://[デプロイ先バケット名]ディレクトリ構造によっては、pre_buildの
cd frontなどが不必要 (各々のディレクトリ構造に合わせて下さい)。CodeBuild設定
- AWSマネジメントコンソールにログイン
- ログイン後、CodeBuildサービスを選択し、プロジェクトの作成を押下
送信元の設定
・ソースプロバイダ・・Github
・リポジトリ・・Githubアカウントのリポジトリ
・Githubリポジトリ・・先ほどのコードをPushしたリポジトリを選択
プライマリソースのウェブフックイベント設定
・ウェブフックオプショナル・・・チェック
・イベントタイプ・・・PULL_REPULL_REQUEST_MERGEDを選択(任意のイベントタイプを選択可)6. 環境の設定
・環境イメージ・・・マネージド型イメージ
・オペレーティングシステム・・・Ubuntsu
・ランタイム・・・Standard
・イメージ・・・最新のもの
・イメージのバージョン・・・最新のもの
・環境タイプ・・・Linux7. サービスロールの設定
以下の画像では、既存のサービスロールとなっていますが、初めて使用する方は、新しいサービスロールを選択してください。選択すると、自動でロールのARNが入力されます。8. Buildspec設定&アーティファクト設定
・ビルド仕様・・・buildspecファイルを使用
・Buildspec名オプショナル・・・front/.buildspec.yml(ディレクトリ構造を紹介した際に、frontの階層の下に、.buildspec.ymlファイルを置いているのがわかるように、今回ビルドする際の設定ファイルをfront/.buildspec.ymlに置いているので、ここを指定します。)
・アーティファクト・・・特に設定しない以上でCodebuildの設定が終了です。
Amazon S3設定
- AWSマネジメントコンソールにログイン
- ログイン後、Amazon S3サービスを選択し、バケットの作成を押下
- 任意のバケット名を入力し、作成
4. 作成後、バケットのプロパティの、Static website hostingを選択
5. Static website hosting設定
・インデックスドキュメント・・・任意のルートファイル(大抵はindex.htmlとなる。)6. バケットのプロパティのアクセス権限設定のブロックパブリックアクセス設定
以下の画像のように設定する。
7. バケットのプロパティのアクセス権限設定のバケットポリシー設定(セキュリティレベルは自己のサービスなどに合わせて、変更お願いします。)
以上でAmazon S3の設定が終了です。
動作確認
Githubのリポジトリに対して、PullRequestがマージされると、CodeBuildが自動で走り、以下の画像のように全てSuccessとなると成功です。S3のホスティングしているURLにアクセスすると、任意のものが表示されるのを確認してください。
以上で全ての設定が終了です。
次回はバックエンド側(Go)のデプロイフローとして、CodePipeline, CodeBuild, CodeDeploy, ECSを使用した方法について書こうと思います。
- 投稿日:2020-01-14T13:16:59+09:00
AWS Amplify フレームワークの使い方Part4〜API実践編〜
はじめに
今回は、AmplifyのAPI設定後、Nuxt.jsのアプリケーション内でどのように利用しているかを中心に書いていきます。
Nuxt.jsの構成
基本的にDB取得のAPIの呼び出しはstoreのactionでのみ行っています。取得したDBデータをmutationでstateに書込み、必要に応じてgettersから取得する形にしています。
準備
store/index.jsの上部に以下を宣言します。store/index.jsimport { API, graphqlOperation } from 'aws-amplify' import * as gqlQueries from '../graphql/queries' // read import * as gqlMutations from '../graphql/mutations' // create, update, delete import * as gqlSubscriptions from '../graphql/subscriptions' // 監視importしたこれらを使っていくことで、CRUDの実行とデータの監視を行うことができます。
API設定時に、自動生成されるgraphqlフォルダ内には、3つのファイルが作られており、その中に記載されているAppSyncを実行するqueryやmutationを使っていきます。以下、user情報を取得することを例に解説していきます。
Queries
getUser
idを指定してユーザーの情報を取得します。まず、
queris.jsには以下のように定義されているので、index.jsから以下のように呼び出すことで、user情報が取得できます。graphql/queries.jsexport const getUser = `query GetUser($id: ID!) { getUser(id: $id) { id name age createdAt updatedAt } } `store/index.jsconst user = await API.graphql( graphqlOperation(gqlQueries.getUser, { id: 'tanaka' // userテーブルの取得したいデータのID }) ) const userData = user.data.getUser // ユーザーのDB情報返り値
以下のように取得しますが、GraphQLで取得したデータは様々な情報を含んだオブジェクトで返ってくるため、
user.data.getUserとすることで、実際にほしいユーザー情報を取得できます。補足
基本的には、自動生成されたgraphqlに加工を加えたものを利用していますが、イレギュラーで必要な値だけ取得したいときは、以下のようqueryを自分で宣言した取得もできます。
index.js// 例:IDがkatoのニックネームだけの情報が欲しい場合 // クエリを個別に宣言 const _query = `query GetUser($id: ID!) { getUser(id: $id) { name } } ` // 実行 const user = await API.graphql( graphqlOperation(_query, {id : 'tanaka'}) ) const userData = user.data.getUser // name情報のみが入っています。listUsers
ユーザーの一覧情報を取得したいときは、
queris.jsに宣言されているlistを使います。graghql/queris.jsexport const listUsers = `query ListUsers( $filter: ModelUserFilterInput $limit: Int $nextToken: String ) { listUsers(filter: $filter, limit: $limit, nextToken: $nextToken) { items { id name age createdAt updatedAt } nextToken } } `store/index.jsconst users = await API.graphql( graphqlOperation(gqlQueries.listUsers) ) const usersList = users.data.listUsers.items返り値
listの場合は、
const usersList = users.data.listUsers.itemsにすることで、user情報をlist型で取得することができます。filter
filterを宣言することで、返り値をフィルタリングすることができます。filterの特徴として、データはすべて取得した上で、返り値にフィルタリングをかけるだけのため、データの取得コストには差はありません。(SQLのクエリで必要な情報だけ取得するのとは違う)limit
取得するデータの個数です。指定しない場合のデフォルト値は10(多分)となっています。スキーマ設計時にソートキーを指定してない場合は、sortの順番としては、IDのアルファベット順で返ってきます。
nextToken
次のデータの取得するためのトークン情報です。例えば、100個データがあって、はじめの10個を取得して、次の10個のデータを取得したい場合は、はじめの10個のデータを取得した際のnextTokenを次の10このデータを取得するquery内に引きすとして渡すことで、次の10個のデータが取得できます。
Mutations
createUser
createは以下のように行います。
graghql/mutations.jsexport const createUser = `mutation CreateUser($input: CreateUserInput!) { createUser(input: $input) { id name createdAt updatedAt } } `store/index.jsconst user = await API.graphql( graphqlOperation(gqlMutations.createUser, { input: { name: '田中太郎', } }) const userData = user.data.createUser // createしたユーザー情報返り値
mutations.jsで宣言したものが、返り値として返ってきます。id
idについては、graphqlのスキーマで IDを設定している場合は、自動で一意なIDを勝手に書き込んでくれます。IDを設定していない場合は、値を渡す必要があります。
createdAt, updateAt
自動で入力してくれます。便利ですね。別記事で詳細はまとめる予定ですが、@keyでソートキーに指定する場合は、自動入力の機能は使えないので注意が必要です。(ソートキーに設定するためにnon-nullにする必要があり、non-nullの場合は自動入力の機能が使えないため)
updateUser
updateしたいデータのIDとupdateしたい情報を渡すだけで更新が可能です。
graghql/mutations.jsexport const updateUser = `mutation UpdateUser($input: UpdateUserInput!) { updateUser(input: $input) { id name createdAt updatedAt } } `store/index.js// 例: const user = await API.graphql( graphqlOperation(gqlMutations.updateUser, { input: { id: 'tanaka', name: '田中次郎' } }) ) const userData = user.data.updateUser // 更新したユーザー情報返り値
updateした情報だけが返ってくるのではなく、
mutation.js内で宣言したデータがすべて返り値として返ってきます。deleteUser
削除も簡単で、削除したいデータのIDを渡すだけで実行できます。nameだけ削除したいなどのカラム指定の削除はできません。
graghql/mutations.jsexport const deleteUser = `mutation DeleteUser($input: DeleteUserInput!) { deleteUser(input: $input) { id name createdAt updatedAt } } `store/index.jsconst user = await API.graphql( graphqlOperation(gqlMutations.deleteAnswer, { input: { id: 'tanaka' } }) ) const userData = user.data.deleteAnswer // 削除したユーザー情報返り値
deleteしたuser情報の
mutation.js内で宣言したデータがすべて返り値として返ってきます。Subscriptions
onCreateUser,onUpdateUser,onDeleteUser
それぞれ、user情報のcreate、update、deleteを検知してそのユーザー情報を取得できます。
現在作成しているサービスでは、リアルタイム性は求められていないので、未検証な部分です。おわりに
これで、最低限の基本的なCRUDはできるようになったかと思います。AmplifyのAPIの肝はここではなく、スキーマ設定での
@model、@auth、@key、@connectionなどが何よりも重要になってきますので、そのあたりについては別記事で詳しくまとめていきたいと思います。関連記事
AWS amplify フレームワークの使い方Part1〜Auth設定編〜
AWS Amplify フレームワークの使い方Part2〜Auth実践編〜
AWS Amplify フレームワークの使い方Part3〜API設定編〜
- 投稿日:2020-01-14T12:51:17+09:00
マストドン構築1日目 on AWS
経緯
半年ほど前に AWS & Docker ド素人の状態から
なんとかインスタンスをたてて運用していました。EC2の上にDockerで本番運用していましたが、だんだん辛くなってきたのでDockerから降ろすことにしました。
その作業ログです。環境 / ツール
macOS Mojavi 10.14.6
AWS参考にしたもの
マストドンGitHub
https://github.com/tootsuite/mastodon
公式ドキュメント
https://docs.joinmastodon.org/admin/prerequisites/AWSでEC2インスタンスの作成
環境を合わせるため、以前の構築時に使用したAMIを利用します。
なぜeks用Ubuntuを利用したのかは謎です。半年前の自分に問い詰めたいです。
Ubuntuであれば大丈夫だと思います。
- あと半年間はAWS無料枠でいけるのでt2.microです。
- セキュリティグループは80番と443番と22番ポートをあけます。
- EC2インスタンスのたて方はAWSの公式チュートリアルが参考になります。
サーバー内での作業
$ ssh ubuntu@3.112.***.*** -i ~/.ssh/hoge.pemrootユーザーで作業します。
$ sudo su -以下、公式ドキュメントの手順通りに進めます。
https://docs.joinmastodon.org/admin/prerequisites/システムパッケージを更新。
$ apt update && apt upgrade -yviもvimも入っていなかったのでいれます。
$ apt install vimfail2banをインストール
fail2banをインストールして、繰り返しログイン試行をブロック。
$ apt install fail2ban
/etc/fail2ban/jail.confを編集。[DEFAULT] destemail = your@email.here sendername = Fail2Ban [sshd] enabled = true port = 22 [sshd-ddos] enabled = true port = 22最後にfail2banを再起動。
$ systemctl restart fail2banファイアウォールをインストールし、SSH、HTTP、HTTPSポートのみをホワイトリストに登録。
$ apt install -y iptables-persistentrules.v4ファイルを編集します。
$ vim /etc/iptables/rules.v4 *filter # Allow all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0 -A INPUT -i lo -j ACCEPT -A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT # Accept all established inbound connections -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Allow all outbound traffic - you can modify this to only allow certain traffic -A OUTPUT -j ACCEPT # Allow HTTP and HTTPS connections from anywhere (the normal ports for websites and SSL). -A INPUT -p tcp --dport 80 -j ACCEPT -A INPUT -p tcp --dport 443 -j ACCEPT # Allow SSH connections # The -dport number should be the same port number you set in sshd_config -A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT # Allow ping -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT # Log iptables denied calls -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7 # Reject all other inbound - default deny unless explicitly allowed policy -A INPUT -j REJECT -A FORWARD -j REJECT COMMIT手動で読み込みます。
$ iptables-restore < /etc/iptables/rules.v4以下のドキュメントを参考にして
必要なものをインストールしていきます。https://docs.joinmastodon.org/admin/install/
Node.jsをインストール
$ curl -sL https://deb.nodesource.com/setup_8.x | bash -Yarnをインストール
$ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -$ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.listシステムパッケージをインストール
$ apt update$ apt install -y \ imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev file git-core \ g++ libprotobuf-dev protobuf-compiler pkg-config nodejs gcc autoconf \ bison build-essential libssl-dev libyaml-dev libreadline6-dev \ zlib1g-dev libncurses5-dev libffi-dev libgdbm5 libgdbm-dev \ nginx redis-server redis-tools postgresql postgresql-contrib \ certbot python-certbot-nginx yarn libidn11-dev libicu-dev libjemalloc-devMastodonユーザーを作成
$ adduser --disabled-login mastodonユーザーを切り替えます。
$ su - mastodonRubyのインストール
rbenvを使用してRubyのバージョンを管理します。
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv $ cd ~/.rbenv && src/configure && make -C src $ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc $ echo 'eval "$(rbenv init -)"' >> ~/.bashrc $ exec bash $ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build正しいRubyバージョンをインストール。
$ RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 2.6.5 $ rbenv global 2.6.5ruby_2.6.0に同梱されているデフォルトのgemバージョンは最新のバンドラーと互換性がないため、gemを更新。
$ gem update --systemBundlerをインストール
$ gem install bundler --no-documentrootユーザーに戻る。
$ exit番外 ~PostgreSQLのバージョンは9.6~
事情: Docker上にあったPostgreSQLのバージョンは9.6でした。
UbuntuにPostgreSQLをインストールするとデフォルトでバージョン10が入るため、いったん10を削除して
9.6バージョンを指定して入れる必要があります。
(その場合は、別途aptリポジトリ※後述を作成しなければいけませんでした)以下これから新規でインスタンスを建てる場合には、不要な工程です。
需要が謎ですが、一応ハマりポイントだと感じたので自分用の備忘ログです。
/etc/postgresql以下で$ ls 10=> 「9.6に揃えたいなぁ」
$ apt remove postgresql postgresql-contrib(参照) https://www.postgresql.org/download/linux/ubuntu/
※ubuntuのaptリポジトリを追加。
18.04なので$ vim /etc/apt/sources.list.d/pgdg.list deb http://apt.postgresql.org/pub/repos/apt/ bionic-pgdg mainリポジトリ署名キーをインポートし、パッケージリストを更新。
$ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -sudo apt-get update9.6を指定してインストール。
$ apt-get install postgresql-9.6PostgreSQLの設定
以下を参考にPostgreSQLの設定を行います。
https://pgtune.leopard.in.ua/#/こんな便利なジェネレーターツールがあったんですね。
DBのバージョンやインスタンスのサイズを入力していきます。
PostgreSQLの設定については別途記事
『PostgreSQLの設定 ~PGTuneを使ってみて~』
に、まとめてみました。
$ vim /etc/postgresql/9.6/main/postgresql.conf設定が完了したら、再起動です。
$ systemctl restart postgresqlMastodonが使用できるPostgreSQLユーザーを作成。
$ sudo -u postgres psql CREATE USER mastodon CREATEDB; \q次回予告
2日目はマストドンのセットアップです。
作業が進み次第、Qiitaに作業ログを残したいと思います。
- 投稿日:2020-01-14T11:55:41+09:00
AWS IAMロール、IAMポリシーについて整理(初心者向け)
AWSサービスを利用する際に、(AWS)IAMのロールとポリシーについてよく分からなかったので整理しました。
AWS初心がまとめる記事なので、解釈にずれが生じていたり、理解が浅い部分もあると思いますが
ざっくりした理解には役立つかと思います。ロールやポリシーの整理の前に、まずAWS IAMというサービスについて整理します。
IAMとは?
「Identity and Access Management」の略称で
「(AWS)リソースへのアクセスを安全に管理するためのウェブサービスです。
IAM を使用して、リソースを使用するために認証 (サインイン) され、許可された (アクセス許可を持つ) ユーザーを制御します。」(AWS引用)AWSのサービスはたくさんあって、いろんなサービスを組み合わせたり、いろんなアカウントでサービスを利用するため、IAMを使えば安心してサービスを管理・利用できるようになるわけですね。
(自分で書きながら、やっとわかった気がしますw)続いて、ロールとポリシーについてもまとめていきます。
IAMポリシーとは?
- 「誰が」
- 「どのAWSサービスの」
- 「どのリソースに対して」
- 「どんな操作を」
- 「許可する(許可しない)」』
という内容をまとめたルールです。
設定項目と選択肢は、AWSが予め用意してくれているので、各項目を自分で選んで組み合わせるだけのアクセス設定のイメージです。ポリシーでは結構細かくアクセス制限を設定することができるんですね。
この説明でやっとわかりました!IAMロールとは?
複数のIAMポリシーをまとめたもの
例えば、
「Amazon S3を利用できるユーザーは UserA, UserBにして、
UserAはデータの更新(編集)はできるけど、UserBはデータの追加だけで編集まではできないよ」的な感じでしょうか。ポリシーもいろんなバリエーションがあるから、サービスごとにある程度分けて管理するにはロールがあると便利そうです。
ついでにIAMロール、ポリシー関連の資料には「アタッチ」という言葉がたくさん出てきますので、それについても私なりの解釈を少し説明します。
アタッチとは?
『付着する、帰属する、取り付ける、添付する、加える、所属させる、などの意味を持つ英単語。 名詞形は「アタッチメント」(attachment)、対義語は「デタッチ」(detach)。ITの分野では、システム上で何らかの主体に対象を取り込んで有効にする動作や操作などをこのように呼ぶ。』(e-Words)とあり、
イメージ的には部品の
取り付け工事と機能を使えるようにする操作(機能の有効化)をまとめて表現した言葉のようです。ひとまず、これでスッキリしました。
もっと詳しい説明は以下のページが参考になると思いますので、
そちらも合わせてごらんください。追加で他にもわかりやすいページをご存じの方がいらっしゃれば、コメントいただけるとありがたいです。
- 投稿日:2020-01-14T11:55:41+09:00
AWS IAMロール、ポリシーについて整理
AWSサービスを利用する際に、(AWS)IAMのロールとポリシーについてよく分からなかったので整理しました。
AWS初心がまとめる記事なので、解釈にずれが生じていたり、理解が浅い部分もあると思いますが
ざっくりした理解には役立つかと思います。ロールやポリシーの整理の前に、まずAWS IAMというサービスについて整理します。
IAMとは?
「Identity and Access Management」の略称で
「(AWS)リソースへのアクセスを安全に管理するためのウェブサービスです。
IAM を使用して、リソースを使用するために認証 (サインイン) され、許可された (アクセス許可を持つ) ユーザーを制御します。」(AWS引用)AWSのサービスはたくさんあって、いろんなサービスを組み合わせたり、いろんなアカウントでサービスを利用するため、IAMを使えば安心してサービスを管理・利用できるようになるわけですね。
(自分で書きながら、やっとわかった気がしますw)続いて、ロールとポリシーについてもまとめていきます。
ポリシーとは?
- 「誰が」
- 「どのAWSサービスの」
- 「どのリソースに対して」
- 「どんな操作を」
- 「許可する(許可しない)」』
という内容をまとめたルールです。
設定項目と選択肢は、AWSが予め用意してくれているので、各項目を自分で選んで組み合わせるだけのアクセス設定のイメージです。ポリシーでは結構細かくアクセス制限を設定することができるんですね。
この説明でやっとわかりました!ロールとは?
複数のポリシーをまとめたもの
例えば、
「Amazon S3を利用できるユーザーは UserA, UserBにして、
UserAはデータの更新(編集)はできるけど、UserBはデータの追加だけで編集まではできないよ」的な感じでしょうか。ポリシーもいろんなバリエーションがあるから、サービスごとにある程度分けて管理するにはロールがあると便利そうです。
ついでにIAMロール、ポリシー関連の資料には「アタッチ」という言葉がたくさん出てきますので、それについても私なりの解釈を少し説明します。
アタッチとは?
『付着する、帰属する、取り付ける、添付する、加える、所属させる、などの意味を持つ英単語。 名詞形は「アタッチメント」(attachment)、対義語は「デタッチ」(detach)。ITの分野では、システム上で何らかの主体に対象を取り込んで有効にする動作や操作などをこのように呼ぶ。』(e-Words)とあり、
イメージ的には部品の
取り付け工事と機能を使えるようにする操作(機能の有効化)をまとめて表現した言葉のようです。ひとまず、これでスッキリしました。
もっと詳しい説明は以下のページが参考になると思いますので、
そちらも合わせてごらんください。追加で他にもわかりやすいページをご存じの方がいらっしゃれば、コメントいただけるとありがたいです。
- 投稿日:2020-01-14T11:55:41+09:00
AWS IAMロール、IAMポリシーについて整理
AWSサービスを利用する際に、(AWS)IAMのロールとポリシーについてよく分からなかったので整理しました。
AWS初心がまとめる記事なので、解釈にずれが生じていたり、理解が浅い部分もあると思いますが
ざっくりした理解には役立つかと思います。ロールやポリシーの整理の前に、まずAWS IAMというサービスについて整理します。
IAMとは?
「Identity and Access Management」の略称で
「(AWS)リソースへのアクセスを安全に管理するためのウェブサービスです。
IAM を使用して、リソースを使用するために認証 (サインイン) され、許可された (アクセス許可を持つ) ユーザーを制御します。」(AWS引用)AWSのサービスはたくさんあって、いろんなサービスを組み合わせたり、いろんなアカウントでサービスを利用するため、IAMを使えば安心してサービスを管理・利用できるようになるわけですね。
(自分で書きながら、やっとわかった気がしますw)続いて、ロールとポリシーについてもまとめていきます。
IAMポリシーとは?
- 「誰が」
- 「どのAWSサービスの」
- 「どのリソースに対して」
- 「どんな操作を」
- 「許可する(許可しない)」』
という内容をまとめたルールです。
設定項目と選択肢は、AWSが予め用意してくれているので、各項目を自分で選んで組み合わせるだけのアクセス設定のイメージです。ポリシーでは結構細かくアクセス制限を設定することができるんですね。
この説明でやっとわかりました!IAMロールとは?
複数のIAMポリシーをまとめたもの
例えば、
「Amazon S3を利用できるユーザーは UserA, UserBにして、
UserAはデータの更新(編集)はできるけど、UserBはデータの追加だけで編集まではできないよ」的な感じでしょうか。ポリシーもいろんなバリエーションがあるから、サービスごとにある程度分けて管理するにはロールがあると便利そうです。
ついでにIAMロール、ポリシー関連の資料には「アタッチ」という言葉がたくさん出てきますので、それについても私なりの解釈を少し説明します。
アタッチとは?
『付着する、帰属する、取り付ける、添付する、加える、所属させる、などの意味を持つ英単語。 名詞形は「アタッチメント」(attachment)、対義語は「デタッチ」(detach)。ITの分野では、システム上で何らかの主体に対象を取り込んで有効にする動作や操作などをこのように呼ぶ。』(e-Words)とあり、
イメージ的には部品の
取り付け工事と機能を使えるようにする操作(機能の有効化)をまとめて表現した言葉のようです。ひとまず、これでスッキリしました。
もっと詳しい説明は以下のページが参考になると思いますので、
そちらも合わせてごらんください。追加で他にもわかりやすいページをご存じの方がいらっしゃれば、コメントいただけるとありがたいです。
- 投稿日:2020-01-14T10:05:40+09:00
【これからプログラミング&クラウドを始める人向け】AWS Cloud9 を利用して Ruby の開発環境を作ってみる② - AWS Cloud9 の環境構築
はじめに
この記事は 【これからプログラミング&クラウドを始める人向け】AWS Cloud9 を利用して Ruby の開発環境を作ってみる① - AWSアカウント準備編 の続きになります。
AWS Cloud9 のセットアップ
AWS Cloud9 の画面説明
その他 Tips
Tab Size の設定
テキストファイルのタブを開いた状態で右下の「Spaces」をクリックすると「Tab Size」が変更できます
ここで Tab Size を「2」に変更することでタブキーを押したときのスペースの入力回数が設定できます
スペース等の不可視文字の可視化
スペースや改行に印をつける設定です。これもテキストファイルのタブを開いた状態で行います
右下の歯車キーをクリックして Show Invisibles にチェックマークをつけます
まとめ
前回作成した IAM ユーザー を使用してクラウド上に IDE を構築し初期設定を行いました。
びっくりするくらいサクッと立ち上がるのでこれからプログラミングを勉強していきたい人に是非試してみてほしいです。
次回以降はプログラムのバージョン管理について説明していきたいと思います。お楽しみに!
- 投稿日:2020-01-14T10:03:32+09:00
【これからプログラミング&クラウドを始める人向け】AWS Cloud9 を利用して Ruby の開発環境を作ってみる① - AWSアカウント準備編
はじめに
前置き
プログラミングを勉強しよう!と思ったときに躓くポイントでもある開発環境の構築
今回は AWS を利用してクラウド上に開発環境を作っていく手法を紹介していきます
勉強をスタートしたタイミングで同時にクラウドを触ることでモダンな開発環境も理解していきましょうAWS Cloud9 とは
- Cloud9 というブラウザで利用できる IDE (統合開発環境)をAWSが買収
- AWS の各種サービスと連携しやすいサービスとして2017年末にリリース
- クラウド最大手からクラウド上での開発サービスを提供し、開発環境もクラウド上で持つトレンドが出来つつある
利用にあたって必要なもの
AWS 登録のために以下の登録が必要です
- メールアドレス
- クレジットカード(課金が発生しない無料利用も可能)
- ユーザー認証用の電話番号
- ブラウザの設定
- 広告ブロック用のアドオンを導入している場合はオフ
AWS Cloud9 の利用料金の話
課金の仕様
- AWS Cloud9 の利用そのものは課金対象外(=無料)
- AWS Cloud9 の実行環境であるサーバ料金(EC2)は課金対象(=有料)
- ただし無料利用枠内であれば無料
- 新規アカウント作成から12ヶ月の期間、月間750時間まで無料利用枠で利用可能
- 1ヶ月間1日24時間利用したとしても無料利用枠内で使用可能
無料利用枠についての参考情報 (公式)
AWS アカウントの準備
ここからは AWS のアカウントが作成できていることを前提に進めていきます
AWS を利用する際に使うアカウントについて
- ルートアカウント (初回登録で作成されたアカウント)
- 請求に関連する操作も含め権限範囲が非常に広く、日常利用をしないことが推奨されます
- IAM ユーザー (このあとに作成するアカウント)
- 開発など日常的に使用するアカウント
- IAM ( Identity and Access Management ) という機能を利用して権限の制御が可能
今回作成する IAM ユーザーについて
- AWS の管理者ユーザー を作成
- AWS 初学者が一人で利用することが前提
- 今回作成するユーザーで権限のない操作はルートアカウントで操作を行う
IAM ユーザーの作成
ユーザー名を入力
AWS マネジメントコンソールへのアクセスを選択
利用料アラートの設定 (無料利用枠内のため)
目的
- 想定外の請求を防ぐために設定を推奨します (特に個人利用の場合)
- 無料利用枠範囲内でのアラートを受信
- メールをチェックしないと意味がなくなるので要注意
設定方法
まとめ
この記事では開発環境構築のために AWS のアカウント作成と無料で使い切るための設定を紹介していきました。
入門者には手間に感じる部分かもしれませんがクラウド上の開発環境を利用する AWS Cloud9 は非常に強力なサービスなので、ぜひ試してみてください!
次回以降の記事から AWS Cloud9 の構築を進めていきます。お楽しみに!続き→ 【これからプログラミング&クラウドを始める人向け】AWS Cloud9 を利用して Ruby の開発環境を作ってみる② - AWS Cloud9 の環境構築
- 投稿日:2020-01-14T09:12:47+09:00
CloudfrontにAWS WAFのManagedRuleを適用してみた
目的
AWS WAFが便利と聞いておりましたが、まだ実運用したことがなかったので環境に適用してみました。
設定完了がゴールです。構成図
手順
AWS WAFの作成のため、WEB ACLsを作成します。
resource typeを選択します。cloudfront構築済環境ですので、cloudfrontを選択し、対象のresourceを選択します。
次に進み、ルールを選択します。今回はmanaged rule groupを選択します。
Add managed rule groupsからルールを選択します。
今回はS3静的サーバレス環境、かつ初めてなので「Admin protection」のみを適用しますが、WordPressやAP+DB構成を採用している場合は別の構成も検討した方がよさそうです。「Default web ACL action for requests that dont't match any rules」と聞かれるので「Allow」を選択します。
試しておりませんが、blockを選択するとアクセスできなくなると思われます。Set rule priorityを聞かれるのでルールの優先順位を設定します。今回は一件なのでデフォルトのまま、次へを選択します。
configure metricsを聞かれるので、チェックしてメトリックを設定します。
設定を確認し、create web ACLsをクリックします。
気づき
1.設定の確認が難しそう
ACLの動作確認を行なう方法は、選択したルールに合わせた脆弱性診断を実施することだと考えられますが、簡単には実施できないので代替手段を検討すべきだと考えております。2.利用料金
他のAWSサービスと同様に、使った分だけ課金されます。
今回設定した内容だとWebACL1つ、ルール一つなので\$5+\$1+\$0.6=$6.6/月ほどの利用料金となる予定です。
他のライセンスに比べて安いてすが、個人サイトでどこまで守るかは要検討だと考えております。Wordpress環境の場合PHP対策のルールやSQLiを利用した方がよいと考えてます。https://aws.amazon.com/jp/waf/pricing/
リソースタイプ 料金 Web ACL 5.00USD、月あたり (時間で案分) ルール 1.00USD、月あたり (時間で案分) リクエスト 0.60USD 100 万リクエストあたり
- 投稿日:2020-01-14T09:05:16+09:00
AWS ElasticBeanstalk 環境を切り替える方法(EB CLI)
はじめに
一つのサービスを提供する場合でも、Blue-Green Deploymentをする時は複数の環境を使用することになります。
EB CLIを使って、 ElasticBeanstalk の環境を切り替える方法をすぐに確認できるようにまとめさせていただきました。関連リンク
関連リンクを下記に載せておくので、必要であれば参考にしてください。。
- ElasticBeanstalk Blue-Green Deployment
- AWS CLI アカウントを切り替える方法
EB CLI
Elastic Beanstalk コマンドラインインターフェイス(EB CLI)の略。
Elastic Beanstalk をターミナルからコマンドを操作することで、ローカルリポジトリからの環境の作成、更新、およびモニタリングを簡素化することができる。数個の EB CLI のコマンドさえ覚えておけば、アプリケーションをデプロイできてしまう素晴らしいサービス・コマンドラインです。
インストール・設定・基本事項
個人的にまとめるよりも、公式にてまとめられているものが非常にわかりやすく理解しやすいと思いますので、リンク先を載せておきます。
- EB CLI のインストール
- EB CLI の設定
- EB CLI による Elastic Beanstalk 環境の管理
環境を切り替える方法(同じアカウント内での変更)
$ eb use ${環境名}環境を切り替える方法(別のアカウント内での変更)
$ eb use ${環境名} --profile ${別アカウント名}別アカウントの名前を確認する方法は、下のリンクを参照してみてください。
- AWS CLI アカウントを切り替える方法
まとめ
まとめてはみたものの、結局は前に書いた記事と同じ方法+αになってしまいました。
- 投稿日:2020-01-14T06:47:54+09:00
EC2 インスタンスの作成手順
マネジメントコンソールへログインし、EC2のダッシュボードへ移動します。
インスタンスの作成
1.EC2>インスタンスのダッシュボードへ移動し、「インスタンスの作成」ボタンをクリック。
2.次にマシンの選択。初学者の方は基本的の無料利用枠の下記のマシンを選択。
3.インスタンスタイプの選択。こちらも無料利用枠でデフォルトで設定されている「t2.micro」を選択しましょう。
4.インスタンスの詳細を設定しましょう。
※VPCを先に設定したりしますがまだ設定してないのでデフォルトのVPCを利用します。後ほど設定します。
5.ストレージの追加。ここも基本的に変更を加える箇所はないので次へ
7.セキュリティグループの設定。webサーバにつなげるために「HTTP」「HTTPS」も追加します。
8.最後に作成するインスタンスの詳細が出るので確認しましょう。
また、起動ボタンを押したらSSH接続する際に必要なキーペアの作成画面が出るので作成しましょう。
作成後インスタンスを作成できます。
※キーペアの作成画面は今回は省かせていただきます。インスタンスが無事作成できました!!
- 投稿日:2020-01-14T03:47:09+09:00
バーチャルホストとやり方
- 投稿日:2020-01-14T03:47:09+09:00
バーチャルホストのやり方
- 投稿日:2020-01-14T02:10:27+09:00
LambdaでCloudWatchLogsのログ保存期間を変更する
0. 筆者環境
AWS Lambda: Python 3.8
1. 概要
今回はCloudWatchLLogsの特定のロググループに対してログ保存期間の変更が必要になったので、
他環境への汎用も考えLambdaを叩けば一括で変更できるような仕組みを作った。2. 使い方
Lambdaを作成、Lambdaの環境変数に以下を設定し実行。
days: 変更したいログ保存期間
pattern: 変更したいロググループの名前(正規表現)
region: 対象のリージョン(東京リージョンならap-northeast-1でよい)3. こーど
Gistにあげることにしました。
簡素なコードなので以下挙動の概要のみ。
- ロググループを全て取得(get_Loggroups)
- ログ保存期間とロググループのlist作成(create_Policies)
- ログ保存期間設定(set_Logretention)
https://gist.github.com/tunalight/63d2f5260563de5103f844a1f4010b3d
- 投稿日:2020-01-14T00:52:37+09:00
Amazon EKS のチュートリアルで Kubernetes を理解する #02 アプリのデプロイ
はじめに
本記事は、以下の内容の続きになります。
前回、k8sクラスタを作成したので、そこにアプリケーションをデプロイしてみます。
前提条件
- k8sのクラスタが作成されており、ワーカーノードが稼働していること。
チュートリアル:Guestbook
Kubernetesのサンプルアプリケーションである Guestbook を利用します。
フロントエンドの画面と、Redis(マスター/スレーブ構成)からなるアプリケーションです。Guestbook の詳細については、以下のページを参照してください。
Pod/Serviceの登録
PodやServiceの定義ファイルは、すでに上記GitHubに登録されているので、それを利用してデプロイしていきます。
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-master-controller.json replicationcontroller/redis-master created $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-master-service.json service/redis-master created $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-slave-controller.json replicationcontroller/redis-slave created $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/redis-slave-service.json service/redis-slave created $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/guestbook-controller.json replicationcontroller/guestbook created $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook-go/guestbook-service.json service/guestbook created登録されたサービスの状態を確認すると、以下のようになっています。
$ kubectl get services -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR guestbook LoadBalancer 10.100.197.132 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxx.us-west-2.elb.amazonaws.com 3000:31789/TCP 10s app=guestbook kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 63m <none> redis-master ClusterIP 10.100.21.24 <none> 6379/TCP 43s app=redis,role=master redis-slave ClusterIP 10.100.203.61 <none> 6379/TCP 26s app=redis,role=slave登録したサービスが一通り確認できますが、
guestbookのサービスのみ外部に公開される設定になっています。また、
kubectl getコマンドにより、PodやNodeの情報を確認することができます。
Guestbook のアプリケーションをクラスタにデプロイした結果、Guestbookのコンテナは3つ動作しており(レプリカ:3)、Redisは、マスタのコンテナが1つ(レプリカ:1)、スレーブのコンテナが2つ(レプリカ:2)、動作していることが分かります。$ kubectl get pod,node NAME READY STATUS RESTARTS AGE pod/guestbook-4gp4c 1/1 Running 0 13m pod/guestbook-8d7k2 1/1 Running 0 13m pod/guestbook-xfvck 1/1 Running 0 13m pod/redis-master-q8568 1/1 Running 0 25m pod/redis-slave-4g8c8 1/1 Running 0 14m pod/redis-slave-xwjtn 1/1 Running 0 14m NAME STATUS ROLES AGE VERSION node/ip-192-168-0-148.us-west-2.compute.internal Ready <none> 73m v1.14.7-eks-1861c5 node/ip-192-168-61-197.us-west-2.compute.internal Ready <none> 73m v1.14.7-eks-1861c5 node/ip-192-168-88-66.us-west-2.compute.internal Ready <none> 73m v1.14.7-eks-1861c5さらに
kubectl describeを使うことで、Podの構成や稼働状態などの詳細情報を確認できます。$ kubectl describe pod guestbookWeb画面の表示
先の
kubectl get services -o wideコマンドで確認した内容で、guestbookのEXTERNAL-IPの部分をコピーしておきます。
また、PORT(S)の部分を見ると、このアプリケーションが、3000番ポートで公開されていることが分かります。そのため、ブラウザを開き、以下のURLでアクセスすると、Guestbookの画面が表示されます。
これで、k8s上にデプロイしたアプリケーションが動作していることを確認できました。http://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxx.us-west-2.elb.amazonaws.com:3000
まとめ
今回は、k8sクラスタにアプリケーションをデプロイしてみました。
k8sが生成するLoadBalancerを介して、冗長化構成で動作しているアプリケーションにアクセスすることができました。PodやServiceの定義ファイルの内容は、ここでは説明しませんが、実際にデプロイした内容と定義の内容を、合わせて確認すると、定義されている内容も理解しやすいかと思います。
次は、k8sクラスタのモニタリングを行ってみます。
- Amazon EKS のチュートリアルで Kubernetes を理解する #03 メトリクス&ダッシュボード
- 投稿日:2020-01-14T00:52:01+09:00
Amazon EKS のチュートリアルで Kubernetes を理解する #01 クラスタ作成
はじめに
これまで Kubernetes をちゃんと触ったことが無かったのですが、2019年11月に マネージド型ノードグループがリリース されて、ノードの管理などもより簡単になったそうなので、Aamazon EKS のチュートリアルを元に、Kubernetes の理解をしていこうかと思います。
今回、クラスタの作成にはeksctlを利用します。
- Aamazon EKS のチュートリアル
環境
開発環境は以下の通りです。
環境/ツール バージョン macOS Catalina(10.15.2) Python 3.7.6 Homebrew 2.2.2 awscli 1.17.0 Kubernetesクラスタ構築手順
何はともあれ、まずはクラスタを構築してみます。
eksctl のインストール
最初に、 Amazon EKS での k8sクラスタの管理用ツールである
eksctlをインストールします。$ brew tap weaveworks/tap $ brew install weaveworks/tap/eksctl $ eksctl version [ℹ] version.Info{BuiltAt:"", GitCommit:"", GitTag:"0.12.0"}クラスタの新規作成
eksctlを利用して、k8sクラスタを作成します。
2020年1月時点では、ワーカーノードとして、Fargateを利用するのか、EC2を利用するのかが選択できますが、
ここでは、EC2を利用することとします。eksctl create cluster \ --name dev \ --version 1.14 \ --region us-west-2 \ --nodegroup-name standard-workers \ --node-type t3.medium \ --nodes 3 --nodes-min 1 --nodes-max 4 \ --managed
オプション 説明 --name dev "dev"という名称で、k8sのクラスタを作成します。 --version 1.14 k8sのバージョンは、1.14を使用します。 --region us-west-2 AWSの環境はオレゴンリージョンを利用します。 --nodegroup-name standard-workers "standard-workers"という名称で、ノードグループを作成します。 --node-type t3.medium ノードとして、"t3.medium" のインスタンスを利用します。 --nodes 3 --nodes-min 1 --nodes-max 4 初期環境として3ノードで作成します。最小は1ノード、最大は4ノードです。 --managed マネージド型ノードグループ を利用します。 クラスタ作成のコマンドを実行すると、以下のような内容がコンソールに表示されます。
クラスタ作成には、10~15分程度かかります。[ℹ] eksctl version 0.12.0 [ℹ] using region us-west-2 [ℹ] setting availability zones to [us-west-2c us-west-2b us-west-2a] [ℹ] subnets for us-west-2c - public:192.168.0.0/19 private:192.168.96.0/19 [ℹ] subnets for us-west-2b - public:192.168.32.0/19 private:192.168.128.0/19 [ℹ] subnets for us-west-2a - public:192.168.64.0/19 private:192.168.160.0/19 [ℹ] using Kubernetes version 1.14 ・・・・・・ [ℹ] kubectl command should work with "/Users/takanorig/.kube/config", try 'kubectl get nodes' [✔] EKS cluster "dev" in "us-west-2" region is ready作成されたクラスタを、AWSコンソール画面で見ると、以下のような感じになります。
クラスタの作成と共に、kubectlの接続設定ファイルである kubeconfig も、以下に出力されます。
/Users/$USERNAME/.kube/config関連ツールのインストール
k8sクラスタを操作するために、
kubectlおよびaws-iam-authenticatorをインストールします。
kubectlは、k8sクラスタをコマンドラインから操作するためのツールで、アプリケーションのデプロイや、クラスタのリソース管理などを行うことができます。
aws-iam-authenticatorは、「AWS IAM Authenticator for Kubernetes」のことで、k8sクラスタの認証に IAM を使用してアクセスできるようになります。kubectl のインストール
まず、他のツールなどのインストールのために、すでに別の
kubectlがインストールされている可能性があるため、既存の環境を確認します。$ which kubectl /usr/local/bin/kubectl私の場合は、Docker と合わせて
kubectlがインストールされていました。
バージョンが合っていれば、そのまま使えるとは思いますが、本チュートリアルの操作では、新たにAWSが提供する媒体をインストールすることとします。ここでは、以下にインストールします。
実際の開発や運用時は、/usr/local/binなど、適切なディレクトリにインストールしてください。$ mkdir -p /Users/$USERNAME/MyWork/amazon-eks/bin$ cd /Users/$USERNAME/MyWork/amazon-eks/bin $ curl -o kubectl https://amazon-eks.s3-us-west-2.amazonaws.com/1.14.6/2019-08-22/bin/darwin/amd64/kubectl $ chmod +x ./kubectl※ バージョンは、k8sのバージョンに合ったものをダウンロードしてください。
以下のコマンドで、インストールされているバージョンを確認できます。
$ ./kubectl version --short Client Version: v1.14.7-eks-1861c5 Server Version: v1.14.9-eks-c0ecccパスを設定しておきます。
ここでは、一時的に指定するだけですが、永続化する場合は、~/.zprofileなどにPATHの指定を記載してください。export PATH=/Users/$USERNAME/MyWork/amazon-eks/bin:$PATHaws-iam-authenticator のインストール
aws-iam-authenticatorは、Homebrewを利用してインストールします。$ brew install aws-iam-authenticator以下のコマンドで、インストールされているバージョンを確認できます。
$ aws-iam-authenticator version {"Version":"v0.4.0","Commit":"c141eda34ad1b6b4d71056810951801348f8c367"}クラスタの状態確認
kubectl getコマンドを利用して、クラスタの状態を確認できます。
現状、クラスタを作成しただけなので、k8s本体だけが動作している状況です。$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 26mクラスタの構成
eksctlを利用して作成した場合、クラスタは以下のような構成になります。
出典:https://aws.amazon.com/jp/quickstart/architecture/amazon-eks/
- マルチAZ構成で、1つのVPC内に Publicサブネットx3、Privateサブネットx3 が作成されます。
- k8sノードが配置されるのは、Privateサブネットの方になります。
AWSコンソールで確認すると、以下のような内容で、VPC/サブネットが作成されていました。
クラスタの削除
Amazon EKS でクラスタを作成した場合、作成したk8sクラスタごとに 0.20 USD/時間 の料金が発生します(ワーカーノードとなるEC2インスタンスの費用は別)。
そのため、不要なクラスタは、削除しておきましょう。$ eksctl delete cluster --name=devまとめ
AWSコンソールからだと、各パラメータの指定なども理解していないと難しい部分がありますが、
eksctlを利用することで、ほぼコマンド1つで、k8sクラスタやワーカーノードを作成することができました。
このように作成された内容を元に、構成などを確認すると理解もしやすいです。次は、k8sクラスタにアプリケーションをデプロイしてみます。
- 投稿日:2020-01-14T00:29:48+09:00
CFnの戻り値(Ref,Fn::GetAtt属性)が少しわかったので共有
CFnの戻り値(Ref,Fn::GetAtt属性)の説明
戻り値とは、指定されると何かしらの値を返してくれる値と言うイメージです。
自動販売機でボタン押すと指定したものに準じて、飲み物を提供してくれる的な感じ?いい例が浮かびません(笑)
GetAttはリソースごとに決められている物理ID(*)を引っ張ってくる感じです
なのでリファレンスを見に行かないとわかりません。
Fn::GetAtt属性リファレンスです。パラメータ
logicalNameOfResource
必要な属性を含むリソースの論理名 (論理 ID とも呼ばれます)。attributeName
必要としている値のある、リソース固有の属性の名前です。各リソースタイプで使用できる属性の詳細については、リソースの参照ページに説明されています。CFnのテンプレートの中で決めたリソース名のことを論理名と言います。
attributeNameはリソース固有の属性名で、指定されると物理IDとして返してくれます
(※)物理IDとはリソースが作られたときにAWSによって割り振られたIDのこと。下記画像で言うとこのネットワークインターフェイスID
!RefはCFnのテンプレートの中で決めたリソース名の物理IDを返します。
Ref属性リファレンスです。
組み込み関数 Ref は、指定したパラメータまたはリソースの値を返します。
パラメータの論理名を指定すると、それはパラメータの値を返します。
リソースの論理名を指定すると、それはそのリソースを参照するために通常使用できる値を返します (物理 ID)。
以上を踏まえてEIPをを関連付けするときの方法を見ていきます。
下記は”AWS::EC2::EIP”リファレンスの引用です。
ここに表示されているものが戻り値(参照値)になります。
リソース(例 AWS::EC2::EIP)ごとに決まっています。他のリソースで!GetAttで指定されると参照されます。戻り値
Refは
Elastic IP アドレスを このリソースの論理 ID を組み込みの Ref 関数に渡すと、Ref は次を返します: 。For more information about using the Ref function, see Ref.
Fn::GetAtt
Fn::GetAtt 組み込み関数は、このタイプの指定された属性の値を返します。以下には、利用可能な属性とサンプル戻り値のリストが示されます。Fn::GetAtt 組み込み関数の使用方法の詳細については、「Fn::GetAtt」を参照してください。
AllocationId
Amazon VPC で使用するアドレスの割り当てを表すために AWS によって割り当てられた ID。この値は、VPC の Elastic IP アドレスに対してのみ返されます。たとえば、eipalloc-5723d13e と指定します。例)
Resources: ControlPortAddress: Type: AWS::EC2::EIP Properties: Domain: vpc AssociateControlPort: Type: AWS::EC2::EIPAssociation Properties: AllocationId: !GetAtt ControlPortAddress.AllocationId (読み:論理IDのAllocationIdという戻り値を参照) NetworkInterfaceId: !Ref controlXface(読み:論理名(controlXface)で作成された物理ID(※)を値として利用する) controlXface:(これが作られたときに物流IDが付与される) Type: AWS::EC2::NetworkInterface Properties: SubnetId: !Ref SubnetId Description: Interface for controlling traffic such as SSH GroupSet: - !Ref SSHSecurityGroup SourceDestCheck: true Tags: - Key: Network Value: Control

















































































































