カテゴリー: 未分類

open-wcでWeb Componentsをつくる

f:id:seeds-std:20191024163712p:plain

こんにちは、プログラマーの衣笠です。
Web Componentsの各ブラウザでの実装がそろってきたのでそろそろ触ってみようと調べていたら、open-wcというものを見つけました。ツールを用意してくれていたので今回はこれを使って簡単なコンポーネントをひとつ作ってみたいと思います。

open-wc とは

Web Componentsを作成、共有する上での推奨事項をまとめてそれをツールとして提供することを目的とした集まりです。

open-wc.org

推奨事項は

  • Developing
  • Linting
  • Testing
  • Building
  • Demoing
  • Publishing
  • Automating

と章をわけてガイドを提供してくれています。
そこで推奨しているパッケージや設定を用意してくれていてツールで生成できるようになっています。

open-wcのツールで開発環境構築

ツールを使うと簡単に開発環境を用意してくれます。
npmが使えてプロジェクトのディレクトリを置きたい場所で

npm init @open-wc

とすると勝手にツールをダウンロードしてきて実行されます。
ツールが実行されると色々質問されます。作成されるものはその回答によって変わります。
今回は簡単は単一のコンポーネントのプロジェクトを作成したいと思うので以下のように回答すると

What would you like to do today? › Scaffold a new project
What would you like to scaffold? › Web Component
What would you like to add? › (選択なし)
What is the tag name of your application/web component? … password-input
Do you want to write this file structure to disk? › Yes
Do you want to install dependencies? › Yes, with npm  

password-input ディレクトリを以下のような構成で作成してくれます。

.
├── LICENSE
├── README.md
├── demo
│   └── index.html
├── index.js
├── package-lock.json
├── package.json
├── password-input.js
└── src
└── PasswordInput.js

テストやビルドの環境などをあとで追加したい場合、もう一度ツールを使って追加できます。

開発サーバー

ツールで生成されたディレクトリで npm run start をすると開発サーバーが立ち上がってブラウザで 自動でdemo/index.html を開きます。
開発サーバーは es-dev-server というopen-wc お手製のパッケージが使われています。
open-wcはできるだけWeb標準に近づくことで長期投資をする方針で、開発も最新のブラウザでES Modulesを活用して進めることを推しています。なので es-dev-server はビルドツールを使わない前提の仕様になっています。
ビルドの待ち時間がないっていうのはすごい魅力的ですね。
また、node_modules のパッケージもいい感じに読み込んでくれます。

WebComponentの実装

今回は最近よくある入力したパスワードの内容を見えるように切り替えられるinput要素 password-input を作ってみました。
作成したものをGlitchで埋め込んでおきます。View Appボタンでデモページに切り替えられます。

実装は src/PasswordInput.js にしていきます。demo/index.html はデモページです。
open-wcはLitElementとlit-htmlを使った実装を推奨していて、プロジェクト生成時点で使えるようになっています。
ここからはLitElementでの実装方法を説明していきます。

カスタム要素の定義

カスタム要素は通常HTMLElementクラスを継承したクラスを定義しますが、LitElementではLitElementクラスを継承して定義します。
タグ名とクラスの紐付けは password-input.js で既にされているので触る必要がありません。

要素のプロパティ、属性

LitElementではゲッター properties で返すオブジェクトで要素のプロパティを定義します。

  ...
static get properties() {
return {
value: {type: String},
visibility: {type: Boolean}
};
}
constructor() {
super();
this.value = "";
this.visibility = false;
}
...

オブジェクトのプロパティに定義したいプロパティの名前、その値のオブジェクトに設定を指定します。
基本的に定義したプロパティと同じ名前の属性も一緒に定義されます。
typeBoolean にすると disabled 属性みたいな扱いになります。
初期値はコンストラクタで設定できます。

要素のコンテンツ

Web Componentsはカスタム要素のコンテンツをShadowDOMによって定義します。
LitElementでは renderメソッドに定義していきます。

  ...
_toggleVisibility() {
this.visibility = !this.visibility
}
render() {
return html`
<input type=${this.visibility ? 'text' : 'password'}
value=${this.value}
>
<span
class="toggle"
@click=${this._toggleVisibility}
>
....
</span>
`;
}
...

render メソッドはlit-elementが用意しているタグ付きテンプレートリテラルの html を使ってコンテンツを定義します。
イベント名に接頭辞 @ を付けた属性にイベントハンドラをバインドできます。

要素のスタイル

要素のスタイルの定義は styles ゲッターに定義します。LitElementが用意している css タグ付きテンプレートリテラルを使います。
コンテンツのスタイルはShadowDOMの中に定義されてカプセル化されるので外の要素に影響しません。Vue.jsのscoped CSSと同じです。
CSSの管理が楽になるのでありがたいです。

  ...
static get styles() {
return css`
:host {
--icon-size: 24px;
display: inline-flex;
...
}
...
input {
line-height: 1em;
...
}
...
.icon {
width: var(--icon-size);
height: var(--icon-size);
}
...
`;
}
...

:host セレクタでカスタム要素のスタイルを定義します。カスタム要素のスタイルは外から変更可能です。
対してそれ以外のShadowDOMのスタイルは外から直接変更できません。
外から変更する方法のひとつにCSSカスタムプロパティを使った方法があります。
ここでは --icon-size を定義して外からパスワードの変更を切り替えるボタンのアイコンのサイズを変更できるようにしています。
他にも Shadow Parts という part 属性と ::part() セレクタを使った方法があります。

::part() – CSS: Cascading Style Sheets | MDN

まとめ

以上がopen-wcで簡単なWeb Componentをつくってみた内容になります。

今回はDevelopingのみを扱いましたが、簡単なものだったので紹介できていないこともあります。興味があればぜひ公式のガイドを読んでみてください。
文章では伝わらなかったと思いますがビルドの時間がないというのはすごく快適です。ES Modulesが普及してきたからこそだと思いますが、Web Componentsの開発環境だけではなく他の開発環境でもこのスタイルが広まればいいなと思いました。
open-wcも今年できたばかりで日本語の情報がほとんどありませんがこの記事がみなさんの触れるきっかけになれば幸いです。

Slackの新機能!「ワークフロービルダー」やってみた

f:id:seeds-std:20191019041007p:plain
クラウド事業部の川勝です。

先日(2019年10月15日)弊社でも使用しているチャットツールSlackに新機能「ワークフロービルダー」がリリースされました!
https://slack.com/intl/ja-jp/features/workflow-automation

早速試してみましたのでご紹介したいと思います。

導入

ワークフローの自動化で作業をシンプルに
重要な仕事の妨げになるルーティン作業からチームを解放。Slack のワークフロービルダーを活用しましょう。

とキャッチフレーズがありまして簡単にいうとチャンネルに対してアクションを設定し、メッセージまたはフォーム表示できたりします。

アクションとは以下のタイミングで実行することができます。

  • ワークフローボタンから手動実行
  • チャンネルに新しい人がジョインしたとき
  • 特定の絵文字リアクションがついたとき

新しくプロジェクトにアサインした人に自動で必要情報を表示とか、毎朝のMTG内容をフォーム入力で投稿、、といったようなことができそうですね。

弊社ではスマートフォン等の検証機があり、その使用時に特定のチャンネルで通知する、というフローがあります。

f:id:seeds-std:20191019023204p:plain
端末使用時の様子

いままでは手動でこのように微妙に統一感がなく各自が投稿していましたので、今回はこちらの投稿フォームを作ってみたいと思います!

ワークフロー作成

f:id:seeds-std:20191019023537p:plain

左上のワークスペースのメニューに「Workflow Builder (NEW)」と使ってくれと言わんばかりの項目が増えています。
こちらをクリックします。

f:id:seeds-std:20191019023853p:plain

自分が作成したワークフローの管理ができます。(後述していますが、チームで作成されているすべてが無条件に表示されるわけではない)

新規作成してみましょう。

f:id:seeds-std:20191019024430p:plain

命名

f:id:seeds-std:20191019024623p:plain

次にどのチャンネルにワークフローを設定するか選択します。
ここで選択したチャンネルからのみアクションが実行されます。
short nameはワークフロー起動時に表示されている名称になります。

「Save」するとこんな感じに表示されます。

f:id:seeds-std:20191019024940p:plain

「Add Step」をクリックして、メッセージやフォームを作成してつなげていきます。
すると、、、

f:id:seeds-std:20191019024907p:plain

ちょっと飛ばしてこのようになりました。

今回だと

  • ワークフロー実行
  • フォーム入力項目設定
  • フォーム入力内容にもとづくメッセージ設定
  • メッセージについているボタンをクリックしたときのメッセージ設定

という順番になっています。

では項目設定の解説していきます。

まず「Add Step」をクリック。

f:id:seeds-std:20191019025603p:plain

すると「Send a message」 or 「Create a form」の選択がでてきます。

今回の場合だと最初は フォームがほしいので「Create a form」を選択します。

f:id:seeds-std:20191019030110p:plain

こちらはselect boxで選択肢の設定をしています。

他にも以下選択肢が設定可能です。

  • Short answer (改行NGの自由入力)
  • Long answer (改行OKの自由入力)
  • Select form list (画像のselect box)
  • Select a person (チームないのユーザを選択できるselect box)
  • Select a channel or DM (チームないのチャンネル or DMを選択できるselect box)

また確定したときDMで内容を送信したりもできます。

続いて通常のメッセージ

f:id:seeds-std:20191019030801p:plain

メッセージはどのチャンネルに送信するか選択できます。(ワークフローを起動したチャンネルと異なってもOK)
またフォームに続いてのメッセージの場合は Insert a variable でフォーム入力値の挿入ができます。
他にもアクションを起動した人、アクションを実行したチャンネルなどが挿入可能です。

あと面白いのがボタンをつけることができます。
ボタンをつけていると、次のStepでボタンをクリックしたら起動、ということが実現できます!

f:id:seeds-std:20191019031248p:plain

そうすると先に送信したメッセージのスレッドに投稿ということも可能になっています。

ここまででできたら右上の「Publish」で公開するとチャンネルからワークフローが実行可能です!

f:id:seeds-std:20191019031538p:plain

公開できたら実行してみましょう!

実行

f:id:seeds-std:20191019040321g:plain

こんな感じで実行できました!

感想

簡単に登録できてこれからどんどん活用したいなと思える機能でした。
ただ新機能ということもあってちょっとかゆいところに手が届かないなあという感じもあります。

以下は個人の感想です。

  • ワークフロービルダーで作成したものを他人が編集できるようにするにはCollaboratorsに追加しないといけないため、
    無条件でチームない共有されない。
  • 絵文字リアクションなんかは複数のチャンネルで同じワークフローを発火できたら面白そう、とおもったがそれはできない。
    ただし、アクション後のメッセージ投稿は任意のチャンネルに投稿できます。
  • アクションはチャンネルにだけ設定できる。自分用にDMに登録はできない。

今後もっと使いやすくなることに期待したいですね!

また面白い使い方が見つけたらブログにしたいと思います。

ちなみに以下にサンプルがあるので、最初はここからダウンロードしたものをインポートして作成すると作りやすいと思います。(現在英語だけみたいです…)
https://slack.com/intl/ja-jp/slack-tips/workflow-builder-examples

以上川勝でした。

Amazon QLDB 楽しいかもというお話

f:id:seeds-std:20191016131408p:plain

はじめに

みなさま、こんにちは。

WEB事業部の李です。 どうぞよろしくお願いいたします。
最近、タピオカにハマっています。
美味しいタピオカを探しております。

さて、Amazon QLDB(以降、単に「QLDB」)が東京リージョンに対応しました。
面白そうなので、ドキュメントを読みつつ、触ってみました。
本日は、QLDBの、この機能いいなと思った感想を書きたいと思います。
※機能面の詳細については、別の機会に書きたいと思います。

QLDBの紹介

まずは、QLDBってなんだ!というところですが、
ざっくり言うと、中央集権的な台帳サービスです。

例えば、データベースに履歴情報を格納して、アプリ側でそれを検索したり、
新たに登録や更新があれば、過去の改竄が無いようにデータを挿入していくといったことをしたい場合があるかと思います。

そんな時に、DB側でその保証を約束してくれるような構造になっていれば楽なのになと、毎回思ったりしますが、
QLDBは、まさにそれを実現してくれるソリューションとして登場したように感じます。

Q: Amazon Quantum Ledger Database とは何ですか?

Amazon Quantum Ledger Database (QLDB) は、台帳管理専用データベースです。
アプリケーションのデータに生じたすべての変更に関する、完全で暗号的に検証可能な履歴を提供します。

よくある質問 – Amazon QLDB | AWS

また、開発者ドキュメントのチュートリアルでは、
自動車とその所有者の所有履歴を管理する台帳を例で挙げられていました。
世の中履歴データだらけなので、自動車以外にも対象はかなり多そうです。

docs.aws.amazon.com

ユースケースとして、金融や小売での利用が紹介されてました。

・金融

銀行では多くの場合、顧客の銀行口座間のクレジットカードおよびデビットカードによる取引などの重要データの追跡に一元管理台帳的なアプリケーションが必要になります。
複雑な監査機能を持つカスタム台帳を構築する代わりに、QLDB ですべての金融トランザクションの正確かつ完全な記録を簡単に保存できます。

・小売 & サプライチェーン

小売業では、製品原産地や出荷製品の品目数、出荷先、出荷担当者など、製品サプライチェーンのあらゆる段階に関する情報にアクセスしなければならないことが多々あります。
QLDB を使用すると、製品がどの物流局面にあっても在庫および物流に関する完全な履歴を確認し追跡できます。

↑どちらも有用そうです。

特徴

さて、QLDBは下記のような、特徴があります。
・フルマネージドであること。かつ、サーバーレス(->自動スケーリング)。
・すべての変更が透過的で、イミュータブルであること。
・トランザクションログが、暗号的に検証可能であること。

aws.amazon.com

アプリ開発の時には、JAVAのドライバーが用意されていますので、下記のチュートリアルをご参考ください。

docs.aws.amazon.com

この機能いいなと思った感想

さて、色々便利そうで、素敵な機能があるのですが、
その中で、個人的にこりゃ便利だなと思った機能を二点あげたいなと思います。

改竄出来ないDBであること

新規だろうが、更新だろうが、削除だろうが、全て履歴に残してくれます。
また、その時々のメタ情報を残してくれますので、アプリ側で云々する必要が無いです。
ちなみにミスった操作も、全て保存され、かつ検証可能です。
※誤操作や誤情報を登録しないようなフローや制限などはアプリ側で考慮は必要です。それらも全て記録されますので、その辺は仕様によります。

PartiQLでクエリ可能であること

sqlチックな言語で、保存されたデータをクエリできちゃいます。
ネストされたデータをクエリできるのは、素敵だなと思います。
※2019/10/17現在、すべての PartiQL オペレーションをサポートしているわけでは無いらしいです。

おわりに

クロスリージョンレプリケーションはサポートされていないなど、
出始めのサービスなので、まだまだ成長段階かと思いますが、
ポテンシャルはめちゃくちゃ大きいような気がします。(=楽できる。 )

開発者やデザイナーは要注意?!シーズ社員達がMac OSをCatalinaへアップデートした体験談。

f:id:seeds-std:20191011110224p:plain

はじめまして!WEB事業部の小川です。

新しいMac OS(Catalina)が登場し、シーズの新しい物好きな社員達(自分を含む)はアップデートしてみました。

更新した感想等を書いていこうと思いますので、アップデートを検討されている方の参考になればと思います。

とりあえず Sidecarが便利

iPadユーザーには朗報であったSidecarが便利で、今まで有料のアプリやハードを使わないと出来なかったiPadのサブディスプレイ化が手軽に出来るのはいいですね!

f:id:seeds-std:20191011110625j:plain
シーズの社員も早速使いこなしておりました
※トレーダーではありません

やっぱりあった Catalinaの問題点とは?

特に開発者に問題がありそうだったのが、Catalina + Google Chromeで発生しているであろう問題点を中心に書いていきたいと思います。

1. input type=”number” のstepが実際のstepの2倍になる問題

stepの指定はしていませんが、Catalina + Google Chromeの方は増やしていくと2ずつ増えていきます。問題ない場合は1ずつ増えていきます。


※Chrome Canaryでは修正されて?発生しない様子。

Chromeの対応待ちですかね。

2. ヒラギノ角ゴPro/ProNが無くなった?

Catalina + Google Chromeではヒラギノ角ゴPro/ProN(Sans Serif)が明朝体で表示されてしまう問題が発生しています。
Apple公開しているmacOS 10.15 Catalinaの組み込みフォントリストには存在しているので「ヒラギノ角ゴPro/ProNが無くなった」と言うことでは無さそうです。
デザイナーやフロントエンドエンジニア の方は要注意ですね。

f:id:seeds-std:20191011112730p:plainf:id:seeds-std:20191011112737p:plain
左がChrome 右がSafari

これもChromeの対応待ちですかね。。

3.Gitが使えなくなった?問題

Catalinaにして、エディターを開いてみると。。

xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

こんなエラーが出ていました。
エラー文言でググればすぐ解決法はありました。

こちらのコマンドで対応出来ました。

xcode-select --install

4. zipファイルが解凍出来なくなった問題

f:id:seeds-std:20191011115340p:plain

zipファイルが解凍出来ない問題があるようです。
解凍出来ないパターンとして最初に考えられたのは

・日本語ファイルがダメ?
・暗号化されているとダメ?
・日本語のファイル名が含まれてても文字コードがUTF-8ならOK?
 と言うことが考えられました。

圧縮時の文字コードはUTF-8にしている場合が多いと思いますが、Windowsを想定している場合はSJIS-WINに変更している可能性もありますね。

回避策として

「ファイル名をアルファベットにしておく」が1番安全

と言うことになりそうです。

最後に

セキュリティの面やSidecarが便利すぎる点では更新した方がいいのでしょうが、新しいが故の問題点もあるので、注意は必要ですね。

この手のアップデートは時間がかかります。

かったりーな・・・

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

LaravelのPivotのincrementingがfalseになっていた件

f:id:seeds-std:20191011113251p:plain

みなさま、初めまして。

WEB事業部の李です。 どうぞよろしくお願いいたします。
最近、カップヌードルの味噌味にハマっています。
昼は基本おむすびです。

www.nissin.com

本題

さて、本日は、
Laravelを5.6から5.8にアップグレードした際に、
Pivotクラスのidをデフォルトでは取得できなかった話を書きたいと思います。

結論

先に結論ですが、LaravelのPivotのincrementingが5.8からdefaultでfalseに設定されていたためでした。
trueにオーバーライドすると取れました。
オーバーライドもどうだろうというのはありますが。。

経緯など詳細

Laravelのバージョンが5.6の時に、中間テーブルを複数またぐような構造のデータを作成する必要がありました。
実装としては、pivotクラスのormを利用して登録後のidを取得し、さらに中間テーブルを作成するというプログラムが既に作られていました。

モデル->Hoge(※中間テーブル)->Hoge2(※中間テーブル)->….

上の例で、Hoge2に、Hogeのidを登録するという流れですが、
5.8へアップグレードするとhogeのレコードを作成後idが取れなくなっていました。。。
※Hogeのidは、auto_incrementで定義されています。

$hoge = Hoge::create($data); // $hoge->id 取れない。。
$hoge = new Hoge;
・
・
・
$hoge->save();  // $hoge->id 取れない。。

まじかよ。。と、もう一度アップグレードガイドを見たりしたのですが、
特に記述はなく、あの手この手と試してみたりしてたのですが、やはり取れず。。
まさかのlastInsertIdメソッド記述しないといけないのかと若干気持ちが沈んでいた頃、
あるエンジニアの方から、もしかしてこれじゃないですか?と指摘を受け、

venderの方のpivotクラスをのぞいてみると、

public $incrementing = false;

の記述がありました。
そこで、Modelクラスのsaveメソッドを少し追いかけてみると、ありました。

performInsertメソッド!これやん!!と。。

この中で、下記のような記述がありました。

//・・・省略
// If the model has an incrementing key, we can use the "insertGetId" method on
// the query builder, which will give us back the final inserted ID for this
// table from the database. Not all tables have to be incrementing though.
$attributes = $this->getAttributes();
if ($this->getIncrementing()) {
$this->insertAndSetId($query, $attributes);
}
// If the table isn't incrementing we'll simply insert these attributes as they
// are. These attribute arrays must contain an "id" column previously placed
// there by the developer as the manually determined key for these models.
else {
if (empty($attributes)) {
return true;
}
$query->insert($attributes);
}
//・・・省略

“which will give us back the final inserted ID”<-まさにですね。

getIncrementingメソッドは下記のような記述でした。

public function getIncrementing()
{
return $this->incrementing;
}

念の為、Laravelframeworkリポジトリで、バージョン5.6のpivotクラスを見てみると、
incrementingプロパティの記述がありません。
PivotクラスはModelクラスを継承しており、Modelクラスのプロパティには、$incrementing=trueとあったので、
バージョン5.6では、idを取得出来ていたのですね。

github.com

ちなみに、create()メソッドは、Illuminate\Database\Eloquent\Builderクラスのcreateメソッドで、結局saveを使っているみたいです。

public function create(array $attributes = [])
{
return tap($this->newModelInstance($attributes), function ($instance) {
$instance->save();
});
}

というわけで、問題のHogeクラスに、

public $incrementing = true;

と、オーバーライドするとidが取れるようになりました。

frameworkでの詳しい経緯は下記のPRご参考ください。

github.com

以上です。
すでに6.xがLTSとなってますが、Pivotクラスのincrementingプロパティのデフォルトはfalseになっていますので、
この記事が皆様のご参考になればと思います。

CircleCI + GitHub + ECR + ECS (+ Fargate) で継続的デリバリー環境を構成する

クラウド事業部の上野です。

AWSにあるコンテナサービスを使ってみたい!今後の弊社のサービスで活用できるかも!ついでにCIツールでデプロイまで自動化したい!
ということでECS(Amazon Elastic Container Service)とECR(Amazon Elastic Container Registry)で継続的デリバリー環境を作ってみました。
今回はCIツールとしてCircleCIを利用してみます。

簡単に各サービスを説明しますと、

CircleCIはCI/CD(継続的インテグレーション/継続的デリバリー)を行うサービスです。

ECSはDocker コンテナをサポートするAWSのコンテナオーケストレーションサービスです。

ECRはAWS完全マネージド型のDockerコンテナレジストリです。

これらのサービスを使って、GitHubにプッシュしたら自動的にDockerイメージをビルドし、最終的にECSのコンテナにデプロイされるという環境を作ってみたいと思います。

今回の構成としてはこのような形です。

f:id:seeds-std:20190911152413p:plain
構成図

では、環境を作っていきましょう。

ECRの作成

まずはDockerのコンテナを保管するECRを作成します。
AWSマネジメントコンソールよりECRのダッシュボードを開き、リポジトリ名を入力して作成します。
今回はお試しということでnginxのDockerイメージを使います。

ECRにリポジトリを作成すると”プッシュコマンドの表示”というボタンが押せるようになります。
これはDockerイメージの作成からECRへのプッシュまで、具体的にどういうコマンドを実行すればいいか教えてくています。
親切ですね、具体的には下記のコマンドになります。

$(aws ecr get-login --no-include-email --region ap-northeast-1)
docker build -t seeds-test .
docker tag seeds-test:latest XXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/seeds-test:latest
docker push XXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/seeds-test:latest

上記コマンドを実行してECRにプッシュするとこのようになります。

f:id:seeds-std:20190911153941p:plain
ecr_push

ECSクラスター作成

ECRのリポジトリにDockerのイメージを準備できましたので、次はECSを準備していきます。
まずは土台となるECSクラスターを作成します。ECSクラスターとはコンテナインスタンスの集合体のことです。
コンテナインスタンスにはAWSがマネージドしてくれるAWS Fargateと自分自身で管理するEC2インスタンスの2種類がありますが、今回はAWSが管理してくれるFargateを利用します。
クラスター作成時にコンテナを動作させるVPCを新たに作成するか聞かれますが、今回は既存のVPCを使用するためVPCの新規作成は行わずにクラスター名だけ記入して作成します。

f:id:seeds-std:20190911155655p:plain
ecs-cluster

ECSタスク定義の作成

次はECSタスク定義を作成します。
ECSタスク定義とはアプリケーションの設計図です。どういったコンテナをどの程度のスペック(CPU、メモリ)で起動するかといった内容を定義します。
タスクの定義には起動タイプをFargateかEC2のいずれかを選択する必要があります。今回はFargateを選択します。

タスク定義名とタスクメモリとタスクCPUを指定し、それ以外はデフォルトのままにします。
設定の中段あたりにコンテナの定義という項目がありますので、そこで「コンテナの追加」ボタンを押してタスクで起動するコンテナの設定を行います。
コンテナ追加の画面でコンテナのイメージを選択する部分がありますので、ここでECRリポジトリに登録したイメージのURIを指定します。
ポートのマッピングは今回はnginxのコンテナですのでhttpの80番ポートをマッピングします。

f:id:seeds-std:20190911161504p:plain
ecs

これでタスク定義の作成は完了です。
タスク定義は今後リビジョンとして管理され、更新する度にリビジョンの数値が増えていきます。

ECSサービスの作成

ECSサービスとはECSクラスター上で起動させるタスクの数やAutoScalingの設定を管理します。
起動タイプはFARGATEを選択し、タスク定義とクラスターは事前に作成したものを指定します。
タスクの数の項目でサービス上で何個のタスクを起動させるかを指定できますので、今回はタスクの数を2に指定して、nginxのコンテナが2つ(タスクごとに1つのコンテナ)起動するようにします。

f:id:seeds-std:20190911165301p:plain
ecs-service

次にネットワーク構成を定義します。
ここでECSサービスが起動するVPCや利用されるセキュリティグループ、ロードバランサーを指定します。
VPCやセキュリティグループ、ロードバランサは事前に用意しておいたものを指定しています。

f:id:seeds-std:20190911165942p:plain
ecs-service
f:id:seeds-std:20190911165957p:plain
ecs-service

サービスを作成するとサービスで定義した内容でコンテナが起動してきます。

f:id:seeds-std:20190911173503p:plain
ecr-service

この状態でELBのDNS名にアクセスするとnginxのウェルカムページが表示され、コンテナが正常に稼働できていることを確認できます。

ここまででECRとECSの構築は完了です。

CircleCIとGitHubの設定

ここまでの作業でAWSを利用したコンテナサービスとしては稼働していますが、CircleCIとGitHubを使って継続的デリバリーな環境を作ります。
まず、CircleCIからECRとECSを操作するためのIAMユーザ(CircleCI用のアクセスキー)を作成します。ポリシーは下記のものを付与してください。作成時に表示されるアクセスキーとシークレットアクセスキーは後ほど利用しますのでメモしておいてください。

ユーザ名 circleci
ポリシー AmazonEC2ContainerRegistryFullAccess
     AmazonEC2ContainerServiceFullAccess

次にGitHubにDocker用のリポジトリを作成します。

f:id:seeds-std:20190911174844p:plain
github

GitHubでリポジトリが用意出来たらCircleCIにアクセスします。CircleCIではGitHubのアカウントを利用してサインアップできます。
GitHubのアカウントを利用してサインアップするとGitHubに用意したリポジトリが表示されていますのでFollowします。

f:id:seeds-std:20190911175327p:plain
circleci

これでGitHubとCircleCIの連携の準備ができました。

次にCircleCIのジョブの設定を行います。CircleCIのジョブの画面よりEnvironment Variablesを開き、環境変数をセットします。

  • AWS_ACCESS_KEY_ID(circleciユーザのアクセスキー)
  • AWS_SECRET_ACCESS_KEY(circleciユーザのシークレットアクセスキー)
  • AWS_ACCOUNT_ID(AWSのアカウント番号)
  • AWS_ECR_ACCOUNT_URL(ECRのリポジトリURL XXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/seeds-test)
  • AWS_REGION(ap-northeast-1)

GitHubにプッシュされた場合にCircleCIの動作を制御するための設定ファイルを用意します。
.circleciというフォルダを作成し、その中にconfig.ymlというファイルを作成します。
config.ymlでCircleCIの動作を制御するのですが、ECRリポジトリへのアップロードやECSのタスク定義やサービスを更新するためのOrbs(※ジョブ、コマンドなどの設定要素をまとめた共有可能なパッケージのこと)をCircleCIが公式に提供しています。
これらを利用してGitHubにプッシュされた場合、DocerkイメージをビルドしてECRにアップロードし、アップロードされたイメージを元にECSのタスク定義とサービスを更新するといった内容のconfig.ymlを作成します。

circleci/aws-ecr@6.3.0

circleci/aws-ecs@0.0.11

config.ymlの内容

version: 2.1
orbs:
aws-ecr: circleci/aws-ecr@6.1.0
aws-ecs: circleci/aws-ecs@0.0.8
workflows:
build_and_push_image:
jobs:
- aws-ecr/build-and-push-image:
region: AWS_REGION
account-url: AWS_ECR_ACCOUNT_URL
repo: 'seeds-test' # GitHubのリポジトリ名
tag: "${CIRCLE_SHA1}"
- aws-ecs/deploy-service-update:
requires:
- aws-ecr/build-and-push-image
family: 'seeds-test-task' # ECSのタスク定義名
cluster-name: 'seeds-test-container' # ECSクラスター名
service-name: 'seeds-test-service' # ECSのサービス名
container-image-name-updates: 'container=seeds-test,tag=${CIRCLE_SHA1}' # タスク定義で指定しているコンテナ名

それではnginxのDocerfileと作成したconfig.ymlをGitHubにプッシュしてみましょう。

f:id:seeds-std:20190911193036p:plain
github

CircleCIをみるとプッシュを検知してジョブが動いていることを確認できます。

f:id:seeds-std:20190911193415p:plain
circleci

ECRの画面をみると新しいイメージが登録されていることを確認できます。

f:id:seeds-std:20190911193818p:plain
ecr

ECSのタスク定義も更新されています。

f:id:seeds-std:20190911194011p:plain
ecs

ECSのサービスで指定されるタスク定義も新しいものに更新され、自動でAutoScalingが実行されています。

f:id:seeds-std:20190911194141p:plain
ecs

これでCircleCI + GitHub + ECR + ECS で継続的デリバリー環境が構築できました。
今回構築した環境はとりあえず動く環境という状態を作りましたが、細かい設定をしていけばより柔軟な環境が作り上げることができます。例えばdevelopブランチにプッシュした場合は開発環境のECSにデプロイ、prodcutブランチにプッシュした場合は本番環境のECSにデプロイするといったことも可能です。

今回は案件の関係でCircleCIを利用する機会があったため、CIツールにCircleCIを利用しましたが、AWSにはもともとAWS CodeBuildやAWS CodePipelineなどのCIツールが用意されています。次回はこれらを使って継続的デリバリーの環境を作ってみたいと思います。

ISUCON 9 予選に京都スイーツ(b・ω・)bで参加して本戦出場できました!(15,490イスコイン / PHP / 総合11位?)

クラウド事業部の原口です。

毎年恒例のISUCONに参加してまいりました。使用言語はPHPです 。

isucon.net

今年は同僚のkawakattunとkuuと僕(cs_sonar)の3人で参加してまいりました!
予選の参加者合計 1561名だそうで、、、すごく大きいイベントになりましたね。
僕は9回目。kawakattunは3回目、kuuは初めてのisuconです。
毎年「今年こそは!」と心に闘志を燃やして参加し、いつも予選敗退するのですが今年はなんと本戦出場できました!

やったーーー嬉しい!

まがいなりにもCTOなので毎年ISUCON出るたびに社内人権が脅かされるのですが、、、今年は人権があってよかったです。
最終的な構成は WEB+Proxy / DB の2台構成でした

前日 && 前々日

業務終わりにISUCON4で練習。ISUCON4を選んだのはAWSにAMIがあってベンチ内包型だったからです。
役割分担などは正式に決めてないのですが、流れで以下のようになっていました

僕 -> インフラ全般
kawakattsun -> アプリ全般
kuu -> 実装と仕様チェック、レギュレーションチェックの情強

当日の流れ

設営をさくっと終わらせて開始!10分遅れたおかげで朝ごはんをたべきれました。
とりあえずアリババクラウドで共有されたイメージで5台ほど立ち上げ。
それぞれのメンバーで触れるようにしました

ベンチを流しても同じ点数しか出ないと思ったら、トランザクション成功数でなるほどな、と思った記憶があります。
ひとまずDB側のitemsにインデックス貼りを実施。

ALTER TABLE items
ADD INDEX seller_id_idx (`seller_id`),
ADD INDEX status_idx (`status`),
ADD INDEX buyer_id_idx (`buyer_id`);

mysqlの最低のチューニング

innodb_flush_log_at_trx_commit = 0
innodb_buffer_pool_size=1000M
innodb_flush_method = O_DIRECT

上限をあげておく

systemctl

net.ipv4.ip_local_port_range = 10240 65000
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 3
net.core.netdev_max_backlog = 30000
net.ipv4.tcp_no_metrics_save=1
net.core.somaxconn = 262144
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_max_tw_buckets = 56384

limits.confは既に65535に設定されていました。

これらを実行してもスコアは全然変わらなく、、、だけど明らかにmysqlの負荷などは減っていいたので
一旦還元率を1にしてみたら6410イスコインになってこの時のTOPに!

引き続いてアプリ側の改修を実施。
ここはkawakattunとkuuがやってくれました
このあたりですでに13:00くらい。

・categoryをすべて配列でプログラム側で持つ
・statusのSQLのINを消す
・セッションにユーザーデータを入れる
・transaction で外部api叩かなくする

などの改修を行ったのですが、特にスコアに変化なく…
同時に行っていたnginxの改修を反映したところスコアが10,000まで上昇。
インフラで止まってた部分を修正する事でアプリの修正も活きた感じがします

nginx

・静的ファイルをnginxで返すように修正
・Cache-Controleでmax-ageとかpublicとかつける
・gzip圧縮するよう設定
・worker_connections 100000
・worker_processes 8
・アクセスログ破棄

しかし、ここからが低迷。
発生する503のエラーのログがどこに吐かれるのかわからずphpのログ出し設定をいろいろいじいじしてたのが結局時間がかかってしまいました。
php実装にはmonologが入ってる事に気づいたのが後半で…
エラー内容がログなくてもかろうじて気づけるSQLのシンタックスエラーじゃなければ死んでたかもしれないです。
またこの時にアクセスログを切ってしまったのは早すぎた。意外とtail -fしてると気づける事ってあるよなーと後から思いました。
/buyが詰まってたのは多分気づけてたと思います。

この間、ボトルネックは完全にphp側に傾いていたので、DBサーバーを分ける事を決意。
分けた時に以下の点にはまり1時間くらいはかかってしまったかもしれないです

・プログラム内のmysqlサーバーのIP指定
・env.shでのmysqlサーバーの指定 ←はまる
・アリババクラウドのセキュリティグループ修正 ←はまる
・my.cnfでbind 127.0.0.1 になっているのを0.0.0.0に修正 ←はまる

普段RDSとかELBで楽してるツケが来ている感じがしました。
これでメモリに余裕ができたのでphp-fpmの設定を変更

php-fpm

以下を60くらいに設定
pm dynamic
pm.max_children
pm.start_servers
pm.min_spare_servers
pm.max_spare_servers
・読まれてるxdebugを切る
・OPCacheを有効化

ここで13,000くらいでした。
また、redisを入れようとしたのですが、うまく立ち上がらず諦め。。。(IPv6系の問題だったそうです)
php-fpm側のネックだったので、残り1台を使って処理を2台に分けようとしましたが、上記のredisが入らないのでセッションどう共有するかという問題と 画像をどう共有するかという問題があって時間的に不可能と思い、断念しました。
/loginのURLに絞る事を考えれたら良かったのになー、と感想部屋見て悔しかったです。

この間にアプリチームが結構長い間、行っていた改修がついに反映されます

・/users/transactions , /new_itemsのn+1をsqlのjoinで回避
・新着一覧から自分のitemとsold outをsqlで除外

自分のitemとsold outをsqlで除外する改修は、最初はカテゴリーのitemsのほうも一緒の対応してたらベンチでitemがありませんってなってしまい。
この改修はすごく時間がかかりました。
Kuuがベンチのエラーをきっちり見てくれて、エラーはカテゴリーの方だけだ、と気付き、新着一覧からのみ除外する事でベンチが通りました。
これが、15790で今回の最高スコア。

最後の17:30からはもう作業は停止。
再起動試験とベンチガチャ回しに勤しみました。
結果は残り5分くらいで 15,490 が出て作業を完全にやめました!

振り返り

f:id:cs_sonar:20190909231445p:plain

考えてみたら、サーバーのチューニング以外はほとんど何もできていません。
感想部屋でのお話を見て「なるほどー」という感じで… /buy の対策などは何もできていなかったりしていました。
本戦までにはプロファイラーをきちんと使い、ボトルネックをきちんと計測できるようにしたいと思いました。
ただ、今回のISUCONがプログラムが膨大だったので、まともに計測してたら何もできずに終わってたかもしれないな、とも思いますので…結果オーライです

弊社のエースエンジニアのkawakattunはもちろんの大活躍でしたが、
今回初参加のkuuがレギュレーションにしっかり目を通し、それを踏まえた案をだしてくれるのはとてもよかったです
僕とkawakattunは多分、ゲームの説明書読まずに始めるタイプなので…w
そういう意味でのチームとして相性がよく、仲間に恵まれた、というのを実感しています。

今まで予選を突破した事がなかったので嬉しいです。
これまでのISCUONを振り返ると惜しい回も結構多かったなーとしみじみ…


ISUCON1 京都スイーツ : fail

ISUCON2 京都スイーツ : (記録がなかったので不明)
#isucon2にていいかんじにスピードアップできなかった話 – SEEDS Creator's Blog

ISUCON3 うさぎ工房 : 5300 予選敗退
isucon3 予選で敗退しました(うさぎ工房) – SEEDS Creator's Blog

ISUCON4 京都スイーツ : 37513 予選敗退&失格
#isucon 4 予選に参加しました(スコア 37513) – SEEDS Creator's Blog

ISUCON5 京都スイーツnext : 13094 予選敗退
ISUCON5に「京都スイーツnext」で参加してきました – SEEDS Creator's Blog

ISUCON6 京都スイーツ : 17000くらい 予選敗退

ISUCON7 ガトリンガー葉の仲間たち : 72,285 55位くらい 予選敗退
ISUCON7に「ガトリンガー葉の仲間たち」で参加して今年も惨敗しました – SEEDS Creator's Blog

ISUCON8 ドラえもんズ : 30,699 27位 予選敗退

ISUCON9 京都スイーツ : 15,490 11位くらい 本戦出場!!


毎度の事ながら、本当に楽しかったです。
運営の皆様、本当にありがとうございました!
そして、今年は本戦でも宜しくお願い致します!

ISUCON7に「ガトリンガー葉の仲間たち」で参加して今年も惨敗しました

毎年恒例のISUCONに参加してまいりました。
毎年今年こそは!と心に闘志を燃やして参加するのですが、今年も予選敗退でした。残念。

ISUCONとは「いい感じにスピードアップコンテスト」の略で
与えられたお題のWEBアプリケーションをできるだけ早くし、ベンチマークの出す点数で競うコンテストです。

isucon.net

今回は社内の方々にお誘い活動を行って捕まえたkawakattsun、luccafortと僕(cs_sonar)の3名で参加しました。
僕はISUCON1から参加していて、kawakattsun、luccafortは今回がISUCON初参加でしたので
裏テーマとして二人がISUCONを本気で楽しんでもらえたら嬉しいなーと思っていたのですが
実際はものごっつい楽しんでもらえたようで結果は惨敗でしたがそういう意味ではとても成功だったと思います。

順位は暫定55位で点数は72,285。言語はPHPです。

そういえばISUCON1は複数台構成だったなぁと思い出しました。

事前準備

業務の忙しさにかまけてあまり事前準備してなかったです。
2ヶ月前くらいにみんなでPixivのISUCON問題をじっくり解きましたので
今回非常構成が似ていたのでそれがよかったです

・とりあえずベンチ回す
・レギュレーションを熟読する
・git
・phpに切り替え
・SSH簡易接続設定
・mysqlのdata dir をコピー
・アクセスログ解析(analog)
・netdataつかってみる?
・app armor注意
・プログラムDBで明らかに重いところを潰す
・インフラ関連のチューニングを行う
・ある程度のチューニングができたら抜本的な構造変更の対策を検討
ボトルネックを常に潰していく
同時に改修は行わない。
なにがよくて何がだめだったかがわからなくなるから

という方針だけ前日10分くらいでざっくり作って共有。

本番での流れ

もうあたふたしてたので詳細は覚えてないですが・・・

  • 9:30 会社に到着。会社にいた方がエナジードリンクを差し入れしてくれた。
  • 10:00 開始が遅れるらしい。 これはこれで非常に有意義な時間だった。お祭り感。
  • 11:30 もう今日はないのでは?と、昼から飲みに行く気に半分くらいなってた
  • 13:00 開始・・・されない。このズコーー!がお祭り感がさらに加速。
  • 13:10 本当開始!とりあえずSSH鍵認証。
  • 13:12 初期ベンチ pythonで6189
  • 13:30 各サーバーどこからでも ssh {web1|web2|db}で接続できるように設定
  • 13:30 DBサーバーのID/PASSをあふあふ探す
  • 13:30 PHPに切り替えてベンチで4157
  • 14:00 DBが重かったので簡単にチューニング。innodb_flush_log_at_trx_commit = 0 くらいですが。6397
  • 14:15 さくっとanalogでアクセス数だけ確認。loginとadd_channelとかが多い
  • 15:00 slow_logから明らかに画像の部分がボトルネックなので静的に書き出し、nginxでiconsから返すように設定。8293
  • 16:00 mysqlのINDEX貼る、N+1改善、php-fpmプロセス数上げる、などなどで12000
  • 17:00 疲れが見え始めた所に社内の方が差し入れでお菓子とジュースをくれる。ありがたい。余ったけど。
  • 17:10 nginx <=> php-fpmをunix domain socketに変更するのに僕が結構はまる。20000
  • 18:00 php-fpm <=> DB をスレッドプールするようにした。mysql-pdoでいうparsistantの設定。点数はメモってなかった
  • 18:30 静的ファイルの接続でエラー出るので帯域でつまってる事にやっと気づく。

じゃぁ3台から返せばいいんじゃね?という事でこの時間で大きな構成変更をした。ベンチ対象は全台に変更。

[app1]    [app2]    [app3]
web        web      web
app        app      db
  • app3への接続は静的ファイルはそのまま返し、それ以外はロードバランス的にapp1/app2 に振り分け。
  • iconsの共有はnfsを使用。app1をnfsサーバーにしてapp2/app3はnfsクライアントとしてmountする形に。
  • 静的ファイルを304で返せるように expire 10d;を追加。 (ここがpublicつけないといけなかったなどの話)
  • これで59000
  • 20:15 SQLのストリクトモード消したりして73160が出た。これが最高得点。
  • 20:30 ここからベンチガチャがあって15000 ~ 70000まで大きく振れまくる・・・304レスポンスの数で変わってたのかな
  • 21:00 再起動テストをする。nfsマウントしてたので起動順によってはマウントされない事態が発覚。autofs入れて対応。
  • 21:10 ベンチ&ベンチ&ベンチ&ベンチで72285が出たのでやめる

僕はプログラムをまったく見ておらずインフラばかり見てました。
php-fpmのsocket化の権限関係でえらいハマってしまい、プログラム見る時間がなかったです・・・
のでプログラム部分はkawakattsun、luccafortがいろいろとやってくれていたのだと思います!

アクシデント

  • gitのリポジトリのdbディレクトリを含めてしまい、復旧用dumpが含まれてしまった為にどえらい重いリポジトリに
  • 画像の静的化の時にDBをやらかしてしまいdumpから復元する事態に
  • php-fpmの設定ファイルのコメントが#ではない事に気づくのがかなり最後の方だった
  • 開始が3時間遅れたので、後に予定のあったluccafortが途中で抜けてしまう

アクシデントを含めてのISUCON!!

感想

開始が遅れるという所で、運営側が本当に大変だったんだな、と改めて感謝です。
毎年こんなにも楽しい時間をくれて頭が上がりません。

今回の問題も本当によく考えられてて本当に楽しかったです!
メモリ1GBしかない所なんてとても素敵でした。

今年はシーズからもう1チーム出てたのですが競技終了後に「あそこどうした?」みたいな反省会は本当に楽しい
問題のリポジトリも公開されましたので、これからも社内で2次会して楽しみたいと思います!

しかし、、、とっても悔しい!くやしーーー!!!
僕はこれからブラウザキャッシュの設定で Cache-Control: public の設定をしない事はないでしょう。

ISUCONは本当に最高です!

AWS 中国(北京)リージョンの利用でハマった所をご紹介します

f:id:cs_sonar:20161118201515p:plain

原口です。

AWS China(Beijing) [中国(北京)リージョン] を触らせていただく機会がありまして触ってみた感じをお伝え致します。

中国リージョンは結構前から追加されていますが、通常のアカウントのリージョン一覧には出てきません。

中国リージョンを利用するには他のリージョンとは異なり、専用のアカウントを作成しなければ利用できません。

基本情報

[リージョン]
cn-north-1
[アベイラビリティゾーン]
cn-north-1a
cn-north-1b

無許可でのポート80 / 443 / 8080 のポートによるページ公開ができない

中国では、ウェブサイトを勝手に公開できないようで、AWS側にて上記のポートは接続できないようになっています。ICPライセンスというものを登録しなければ公開できません。基本的にはAWSアカウントにライセンスが紐づいているようでライセンスが紐づけば公開が可能となるようです。

注意点として、ELBやEC2などでは接続できないときはブラウザくるくるですが、s3の接続できないエラーは401レスポンス(UnauthorizedAccess)を返します。401(UnauthorizedAccess)はs3のgetObjectがない場合でも出すのでICPライセンスが原因である、、、という判別がつきにくいところでハマりやすいので注意です。

ちなみにELBやEC2は待ち受けポートを適当なポートに変えてやれば無理やり公開する事は可能でした。

ARNやドメインネームが変わっているので注意

ドメイン名は
ec2.amazonaws.comec2.amazonaws.com.cnと、完全に別のドメインになっていますし、
ARNもarn:awsarn:aws-cn と変わっているので注意が必要です。

cloudformationやterraformのテンプレートなど既存のノウハウを生かそうと流用すると
arnを直接指定している部分などではまります。

ないサービスが多い

以下の一覧でも確認できます

リージョン – グローバルインフラストラクチャ | AWS

今回は

  • route53
  • lambda
  • RDS(Aurora)

あたりがなかったので困りました。

既存リージョンからAMIはコピーできない

完全別サービスみたいな感じですので、既存のリージョンで作成していたAMIなどを共有する事ができません。
これはかなりつらかったので・・・以下のようにディスクイメージを作成してコピーする方法を用いました。

インスタンスコピーの手順

AmazonLinux (HVM)を使用した場合。

移行したいAMIのsnapshotからVolumeを作成し、適当なインスタンスにアタッチします。
アタッチしたボリュームをddコマンドでイメージファイル化します。
(/dev/xvdfとしてアタッチした場合)

dd if=/dev/xvdf of=image.img bs=1M

イメージファイルを中国側に作成したインスタンスに転送します

scp -i chn.pem ./image.img ec2-user@***.***.***.***:/home/ec2-user/

中国側インスタンスで空のVolumeを作成し、アタッチします。
この時、空のVolumeサイズはコピー元のVolumeサイズと同じにしてください。

このアタッチした空Volumeにddコマンドでイメージファイルを書き込みます
(/dev/xvdfとしてアタッチした場合)

dd if=./image.img of=/dev/xvdf bs=1M oflag=direct

※独自OSを使っている場合などはこの際にboot関連の項目を書き換えたりしないといけないかもしれないですがAmazonLinuxでは特に修正なくできました。

Volumeをデタッチしてsnapshotを作成します。
そしてsnapshotからAMIを作成。
この際のパラメータはHVM(Hardware-assited VM)に。
カーネルIDなどはデフォルトでOKです。

これで、既存リージョンのAMIを北京リージョンに持ってくる事ができた事になります。

このとき、作成したAMIを北京リージョンで立ち上げるとうまく立ち上がってこない事があります。
マネージメントコンソールからget_systemlogで見ると以下のようなのが出てる場合・・・

http://packages.ap-northeast-1.amazonaws.com/2016.09/main/20160901f6a8/x86_64/repodata/repomd.xml?instance_id=i-******************************&region=ap-northeast-1: [Errno 12]
Timeout on http://packages.ap-northeast-1.amazonaws.com/2016.09/main/20160901f6a8/x86_64/repodata/repomd.xml?instance_id=i-******************************&region=ap-northeast-1: (28, 'Connection timed out after 10000 milliseconds')
Trying other mirror.`

Amazon Linuxはcloud-initでyum update(セキュリティのみのもの)が走るのですがそれが途中で止まっているのが原因です。
止まってしまった場合は再起動すればOKです。
これはたぶん以下の変数が書き換わっていないからではないかと思います。

/etc/yum/vars/awsdomain
/etc/yum/vars/awsregion

同様にRDSのスナップショットも移動できないです。こっちはダンプ持ってく感じになりますね

よく接続切れる、またはめちゃくちゃ遅くなったりする

南北問題と言うらしいです・・・。

(参考)
qiita.com

© SEEDS Co.,Ltd.