Hatena::ブログ(Diary)

ablog このページをアンテナに追加 RSSフィード

2018-11-12

ECS で EC2 と Fargate の起動タイプのタスクを併用して同じアプリケーションを実行する

ECSEC2 と Fargate の起動タイプのタスクを併用して同じアプリケーションを実行してみた。ワークロードがない場合は、EC2 の1タスクだけ実行され(Fargate のタスクは 0)、EC2CPU使用率が50%を超えると EC2 に1タスク追加され、EC2CPU使用率が80% を超えると Fargate のタスクが追加されていくというのを試してみた。


EC2インスタンスから ab で負荷をかけて、

f:id:yohei-a:20181115013739p:image:w640

ECSEC2 インスタンスログインして htop でワークロードを確認するとこんな感じ。

f:id:yohei-a:20181115013720p:image:w640

CloudWatch のダッシュボードを見るとこんな感じで、CPU使用率が上がり、

f:id:yohei-a:20181115014144p:image:w640

ECSEC2 は +1、Fargate は +1 タスクがスケールアウトしている。

f:id:yohei-a:20181115013658p:image:w640

手順は以下の通り。


準備

キーペア作成
  • ECSを利用するリージョンでキーペアを作成していない場合は作成しておく。
セキュリティグループ作成
タイププロトコルポート範囲ソース
HTTPTCP80マイIP
SSHTCP22マイIP
すべてのTCPTCPすべて自分自身のセキュリティグループID

ELB

ELB作成

ECS

ECSタスク定義(EC2タイプ)作成
ECSタスク定義(Fargateタイプ)作成
クラスター作成
サービス(EC2起動タイプ)作成
  • 起動タイプ: EC2
  • タスク定義: ec2-task
  • クラスター: ec2-fg-mix-cluster
  • サービス名: ec2-service
  • タスクの数: 1
  • ELBタイプ: Application Load Balancer
  • ELB名: ec2-fg-mix-alb
  • パスパターン: /
  • 評価順:1
  • ヘルスチェックパス: /
  • Service Auto Scaling: Service Auto Scaling の設定を変更することで、サービスの必要数を調整する
  • タスクの最小数: 1
  • タスクの最大数: 2
  • 自動タスクスケーリングポリシー
    • ポリシー名: EC2ScaleOutPolicy
      • 既存のアラームの使用: EC2ScaleOutAlarm
      • スケーリングアクション: 追加 1 tasks、次の条件の場合 50 <= CPUUtilization
      • クールダウン期間: 30
    • ポリシー名: EC2ScaleInPolicy
      • 既存のアラームの使用: EC2ScaleInAlarm
      • スケーリングアクション: 削除 1 tasks、次の条件の場合 40 <= CPUUtilization
      • クールダウン期間: 30
サービス(FARGATE起動タイプ)作成
  • 起動タイプ: FARGATE
  • タスク定義: fargate-task
  • クラスター: ec2-fg-mix-cluster
  • サービス名: fg-service
  • タスクの数: 1
  • クラスター VPC: デフォルトVPC
  • サブネット: ap-northeast-1a のサブネット
  • パブリック IP の自動割り当て: ENABLED
  • セキュリティグループ: ECS-SG
  • ELBタイプ: Application Load Balancer
  • ELB名: ec2-fg-mix-alb
  • パスパターン: /
  • 評価順:1
  • ヘルスチェックパス: /
  • Service Auto Scaling: Service Auto Scaling の設定を変更することで、サービスの必要数を調整する
  • タスクの最小数: 1
  • タスクの最大数: 10
  • 自動タスクスケーリングポリシー
    • ポリシー名: FgScaleOutPolicy
      • 既存のアラームの使用: FgScaleOutAlarm
      • スケーリングアクション: 追加 1 tasks、次の条件の場合 80 <= CPUUtilization
      • クールダウン期間: 30
    • ポリシー名: Fg2ScaleInPolicy
      • 既存のアラームの使用: FgScaleInAlarm
      • スケーリングアクション: 削除 1 tasks、次の条件の場合 70 <= CPUUtilization
      • クールダウン期間: 30

CloudWatch Alarm

EC2起動タイプのスケールアウト用
  • 名前: EC2ScaleOutAlarm
  • CPUUtilization: >= 50
  • 期間: 1 / 1 データポイント
  • アクション
    • アラームが次の時: 警告
    • リソースタイプから: EC2 Container Service
    • 次から: service/ec2-fg-mix-cluster/ec2-service
    • 次のアクションを実行: EC2ScaleOutPolicy
EC2起動タイプのスケールイン用
  • 名前: EC2ScaleInAlarm
  • CPUUtilization: <= 40
  • 期間: 1 / 1 データポイント
  • アクション
    • アラームが次の時: 警告
    • リソースタイプから: EC2 Container Service
    • 次から: service/ec2-fg-mix-cluster/ec2-service
    • 次のアクションを実行: EC2ScaleInPolicy
Fargate起動タイプのスケールアウト用
  • 名前: FgScaleOutAlarm
  • CPUUtilization: >= 80
  • 期間: 1 / 1 データポイント
  • アクション
    • アラームが次の時: 警告
    • リソースタイプから: EC2 Container Service
    • 次から: service/ec2-fg-mix-cluster/fg-service
    • 次のアクションを実行: FgScaleOutPolicy
Fargate起動タイプのスケールイン用
  • 名前: FgScaleInAlarm
  • CPUUtilization: <= 70
  • 期間: 1 / 1 データポイント
  • アクション
    • アラームが次の時: 警告
    • リソースタイプから: EC2 Container Service
    • 次から: service/ec2-fg-mix-cluster/fg-service
    • 次のアクションを実行: FgScaleInPolicy

負荷をかけてスケールアウト/インを試す

$ sudo yum -y install htop 
$ sudo yum -y install httpd
  • 負荷をかける
$ ab -k -n 900000000 -c 100 http://*****.ap-northeast-1.elb.amazonaws.com/ &
$ ab -k -n 900000000 -c 100 http://*****.ap-northeast-1.elb.amazonaws.com/ &
$ ab -k -n 900000000 -c 100 http://*****.ap-northeast-1.elb.amazonaws.com/ &
$ ab -k -n 900000000 -c 100 http://*****.ap-northeast-1.elb.amazonaws.com/ &
$ ab -k -n 900000000 -c 100 http://*****.ap-northeast-1.elb.amazonaws.com/ &
$ ab -k -n 900000000 -c 100 http://*****.ap-northeast-1.elb.amazonaws.com/ &

補足

  • ECSのサービスを作成時にスケールアウト/インポリシーを仮で作成後に、CloudWatch Alarm でスケールアウト/インのアラームを作成し、ECSのサービスを更新して作成した CloudWatch Alarm と紐付ける。
  • 同じサービス名で削除して作り直すとマネジメントコンソールでは消えていても、バックグラウンドで削除完了していないと "Unable to Start a service that is still Draining." というエラーになる模様。しばらくして作り直すと成功した。
  • 同一クラスターEC2とFARGATEのタスク共存させる場合に以下のネットワークモードの組合せは可能なことを確認済。
  • 起動タイプがEC2ネットワークモードを awsvpc にした場合、1タスクで1つのENIを使うので、EC2インスタンスの ENI の最大数を超えるタスクを起動することはできない。ENIの最大数を超えるタスクを起動しようとすると RESOURCE:ENI エラーが発生する。

RESOURCE:* (container instance ID)

タスクによってリクエストされたリソースは、指定したコンテナインスタンスで使用できません。リソースCPU、メモリ、ポート、または Ellastic Network Interface の場合は、コンテナインスタンスクラスターへの追加が必要になる場合があります。RESOURCE:ENI エラーの場合、awsvpc ネットワークモードを使用するタスクで必要な Elastic Network Interface アタッチメントポイントが、クラスターで利用できないことを示しています。Amazon EC2 インスタンスにアタッチできるネットワークインターフェイスの数には制限があり、プライマリネットワークインターフェイスも 1 つ分としてカウントされます。各インスタンスタイプでサポートされる Network Interface の数の詳細については、Linux インスタンスAmazon EC2 ユーザーガイドの「各インスタンスタイプのネットワークインターフェイスごとの IP アドレス」を参照してください。

API failures エラーメッセージ - Amazon Elastic Container Service

2018-09-17

AWS Glue の Zeppelin ノートブックで PySpark を実行して CSV を加工してみた

AWS Glue で開発エンドポイントを作成して、Zeppelin のノートブックで PySpark を実行して S3にある CSV を加工(行をフィルタ)してS3に書いてみた。S3 から読んだ CSV は Glue の DynamicFrame から SparkSQL DataFrame に変換してフィルタした後、DynamicFrame に変換してS3に書いた。DynamicFrame には単純なメソッドしかないため、SparkSQL を使って高度なデータ処理をしたい場合は、DataFrame に変換してやればよい。


準備

テストデータ作成
  • テストデータ(CSV)を作成する。
% perl -e 'printf(qq/%d,%d,%d,%d\n/,$_,2..4) for 1..100' > number.csv
% wc -l number.csv
     100 number.csv
% head -3 number.csv
1,2,3,4
2,2,3,4
3,2,3,4
% tail -3 number.csv
98,2,3,4
99,2,3,4
100,2,3,4
S3バケットにデータを置く
Glue で開発エンドポイントと Zeppelin ノートブックを作成

実行

  • Zeppelin ノートブックを開いて以下の PySpark のコードを実行する。
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.dynamicframe import DynamicFrame
from awsglue.job import Job
from pyspark.sql import SparkSession
from pyspark.sql.functions import udf
from pyspark.sql.types import StringType

glueContext = GlueContext(SparkContext.getOrCreate())

# S3 location for input
input_dir = "s3://az-handson/input"

# S3 location for output
output_dir = "s3://az-handson/output"

# Read CSV
dyf = glueContext.create_dynamic_frame.from_options(connection_type = "s3", 
    connection_options = {"paths": [ input_dir ]}, format="csv", format_options={ "withHeader": False})

# Convert to DataFrame
df = dyf.toDF()

# Filter
filtered_df = df.where(df['col0'] > 50)

# Turn it back to a dynamic frame
output_dyf = DynamicFrame.fromDF(filtered_df, glueContext, "nested")

# Write it out in CSV
glueContext.write_dynamic_frame.from_options(frame = output_dyf, connection_type = "s3", connection_options = {"path": output_dir}, format = "csv")

結果

  • S3 に加工結果が出力されている

f:id:yohei-a:20180917161311p:image:w640

f:id:yohei-a:20180917161512p:image:w640

  • Zeppelin でフィルタ後の DataFrame を表示してみる。
filtered_df.show()

f:id:yohei-a:20180917161746p:image:w640


メモ

  • DynamicFrame の定義を確認する
dyf.printSchema()
  • dataframe の定義を確認する
df.describe()

参考

2018-07-16

「コスパのいいシステムの作り方」の紹介

三菱UFJインフォメーションテクノロジーの南さんから献本いただきました。南さんとは一緒に仕事をさせていただいたこともありますが、難易度の高いミッションクリティカルプロジェクトを成功させられていて、こういうベンダーに騙されない目利きができる優秀なPMはユーザー企業の宝だと思っていました。

南さんのようなユーザー企業でリスペクトしている方々に共通しているのは会社のお財布は自分のお財布という感覚を持ち、各分野のスペシャリストと個人的なコネクションを持たれ、ドライな技術からウエットな組織まで筋の通った骨太な考え方を持たれて、馬力があって肝が座られてるところです。ちょっとマネできないなと感じます。

こういうスキルはなかなか人に伝えることは難しいと思いますが、本書はそれを可能な限り搾り出した一冊だと思います。自分がユーザー企業に転職することがあれば、本書を参考にさせていただきたいと思います。

著者が経験を通じて得た経験と勘(暗黙知)を脳内バッファから書出したような一冊です。

システムの「コストパフォーマンス(費用対効果)」に限らずインフラの要素技術、勉強の仕方、後輩の育て方、組織についてなど経験から得られた暗黙知が簡潔に書かれています。

日本のIT業界は内製せずにSIerに委託しているユーザー企業が多いですが、その場合、プロジェクトの成否は製品やソリューションの選定、ベンダーコントロールなどユーザー企業のプロジェクト担当の目利きや腕にかかっていると感じます。

よく、この人はこの会社にいてもらわないとと思うことがあります。

本書はユーザー企業のインフラエンジニアはもちろん、そこに提案に行くベンダーも役に立つと思います。以下、構成と目次です。


概要

「うちって,システムにお金をかけすぎじゃない?」

そんな問いに的確な判断を下すにはどうすればいいか。

「勘に頼らない技術を求めても,結局は勘に頼る部分が少なからずある」

「過去の事例と比較しても,元のコストがまちがっていれば誤りの連続になるし,すぐに陳腐化する」

そんなジレンマに悩む方のために,大規模システムを多数経験してきた著者が,最小限のコストで最大の効果を得る「勘と経験」の本質を教えます。

コスパのいいシステムの作り方 ?しっかり見積もりたいのに勘を使うジレンマに向き合う:書籍案内|技術評論社

構成

本書では,テーマごとに私の経験と勘を明らかにしていこうと思いますが,以下のスキルが重要になります。

  • ITインフラを自分で構築できるスキル
  • システムの目的(SLA)を正確に把握するスキル
  • 採用する製品の動きや仕様を把握するスキル
  • アプリケーションの動作をイメージし,どのようにリソースが使われるかを推察するスキル
  • インフラを構成する要素技術の変化,今後の見通し,価格動向を把握するスキル

これらのスキルを,本書では3部構成でまとめています。まず第1章から第8章までは,システムを構築するうえでの前提知識をまとめました。システム構築は単に技術力があればできるものではありません。幅広い知識と経験が必要で,その要素をまとめています。続いて第9章から第12章まではインフラのテクニカル要素をレイヤーごとに記載しています。何か1つの製品については触れず,どのような製品を使っても役に立つ考え方を記載しています。最後に第13章は,それ以前の章の総まとめです。実際のシステムのパターンごとに,第12章までの知識を集約して考え方を整理しています。

これらのスキルは私のこれまでの経験によるものですが,どのように考えてきたかをお伝えすることで,みなさんの経験と勘にプラスできることを願っています。


目次

出版社の紹介は コスパのいいシステムの作り方 ?しっかり見積もりたいのに勘を使うジレンマに向き合う:書籍案内|技術評論社 をご覧ください。

第1章 どうやって予算を確保するか
文化の違いで変わる見積りへの影響
プロジェクトごとの予算確保から案件化まで
予算が決まった後にすべきこと

第2章 製品を安く買うための工夫
「製品は安く、工数はほどほどに」がコツ
製品の強み、弱みを正確に把握する
ダブルスタンダードで価格をコントロールする
購入時に確認すべき3つのこと

第3章 開発費を削減するための工夫
インフラのコストを下げる基本原則
内製化を検討する
契約で考えるべき4つのポイント

第4章 可用性、性能、運用性を考慮する
システムのコストとSLA
可用性について考察する
性能について考察する
運用性について考察する
後から変わるSLAで不幸にならないためにすべきこと
後々SLAでもめないためのインフラのポイント

第5章 OSSかプロプライエタリか
バグの対処の方法によってコストは大きく変わる
OSSの強みとは
OSSの向き不向きを考える

第6章 標準化でコストダウンは図れるのか
標準化の功罪とは
コスト効率と安全性を追求する標準化の進め方

第7章 運用・保守の効率化を考える
増えていくシステム、減らしにくいランニングコスト
保守作業を合理化するための考え方
運用フェーズのコスト削減のポイント
開発・運用の分離とDevOps

第8章 教育コストと体制維持コストの負担
エンジニアが成長するための4つの基本
技術スキルの伸ばし方
教育のためのコストを捻出する

第9章 サーバー(IaaS)のコストを考える
「速いか遅いか」「壊れにくいか壊れやすいか」の2軸でコストを考える
CPUの費用対効果
メモリの強みを理解する
ディスクの故障とシステム停止を想定する
ラックマウントサーバーか、ブレードサーバーか

第10章 仮想化でリソースを効率的に扱う
見積もりとコントロールがうまくできないから仮想化が必要になる
リソースをリニアに追加・削除するときの注意点
集約率を高め、効果的に仮想化するには

第11章 ストレージを効率的に使い切る
ブロックストレージの投資対コスト
思ったよりも使えないディスク容量
ディスクの特性と価格変動を考える
ブロックストレージ以外のストレージを使いこなす

第12章 ミドルウェアがコストに与える影響を理解する
ライセンスコストが問題になりにくいAPサーバー
高額でプロプライエタリなRDBMS製品を使う理由
RDBMSで無駄なリソースを使う問題をどう解決するか
NoSQLの活用でコストは減らせるか
アプライアンス製品か、汎用品か

第13章 システムタイプごとの高コスト、低コスト
シンプルなAP、DBの構成
同時実行ユーザーが多いシステム
ミッションクリティカル系
スパコン・HPCの場合

2017-12-10

MySQL Connector/J(JDBC Driver) で接続時に任意の collation_connection をセットする

MySQL Connector/J(JDBC Driver) で接続時に任意の collation_connection をセットする には以下の用に JDBC URL に「connectionCollation=utf8mb4_bin」のように設定すれば良い。

jdbc:mysql://aurora01.cluster-*******.ap-northeast-1.rds.amazonaws.com:3306/mydb?connectionCollation=utf8mb4_bin

参考

MySQL クライアントプログラム mysql、mysqladmin、mysqlcheck、mysqlimport、および mysqlshow は、次のように、使用するデフォルトの文字セットを特定します。

  • ほかの情報が欠如している場合、プログラムは、コンパイル時のデフォルトの文字セット (通常は latin1) を使用します。
  • プログラムは、オペレーティングシステム設定 (たとえば、Unix システムでは LANG や LC_ALL ローカル環境変数の値、Windows システムではコードページ設定) に基づいて、使用する文字セットを自動検出できます。ロケールが OS から利用できるシステムの場合、クライアントはコンパイル時のデフォルトを使用するのではなく、このロケールを使用してデフォルトの文字セットを設定します。たとえば、LANG を ru_RU.KOI8-R に設定すると、koi8r 文字セットが使用されます。したがってユーザーは、MySQL クライアントが使用できるように、自身の環境内でロケールを構成できます。OS 文字セットは、正確に一致するものがない場合は、もっとも近い MySQL 文字セットにマップされます。一致した文字セットをサポートしていない場合、クライアントはコンパイルイ時のデフォルトを使用します。たとえば、ucs2 は接続文字セットとしてはサポートされていません。

C アプリケーションは、サーバーに接続する前に次のように mysql_options() を呼び出すことによって、OS 設定に基づいて文字セットの自動検出を使用できます。

mysql_options(mysql,
              MYSQL_SET_CHARSET_NAME,
              MYSQL_AUTODETECT_CHARSET_NAME);
  • プログラムは --default-character-set オプションをサポートしており、ユーザーはこのオプションを使用すると文字セットを明示的に指定でき、クライアントがそれ以外のどのデフォルトを指定していても、それをオーバーライドできます。
no title

Use characterEncoding=utf8mb4& for jdbc url

jdbc:mysql://x.x.x.x:3306/db?useUnicode=true&characterEncoding=utf8mb4
java - utf8mb4 in MySQL Workbench and JDBC - Stack Overflow

connectionCollation

If set, tells the server to use this collation via 'set collation_connection'

Since version: 3.0.13

no title

2017-12-07

Aurora MySQL互換に LOAD コマンドで CSV ファイルをロードしようとすると "ERROR 1148 (42000)" で失敗する

Aurora MySQL互換というより MySQL の話です。


事象

  • mysql クライアントで接続して、LOAD DATA ステートメントで CSV ファイルをロードしようとすると、"ERROR 1148 (42000): The used command is not allowed with this MySQL version" と怒られる。
% mysql  --local-infile -h aurora01.cluster-******.ap-northeast-1.rds.amazonaws.com -u awsuser -p
mysql> LOAD DATA LOCAL INFILE '.test.csv' INTO TABLE TEST FIELDS TERMINATED BY ',' ENCLOSED BY '"';
ERROR 1148 (42000): The used command is not allowed with this MySQL version

原因


解決策

  • --local-infile オプションをつけて mysql クライアントで接続してロードする。
% mysql  --local-infile -h aurora01.cluster-******.ap-northeast-1.rds.amazonaws.com -u awsuser -p
mysql LOAD DATA LOCAL INFILE 'test.csv' INTO TABLE TEST FIELDS TERMINATED BY ',' ENCLOSED BY '"';

参考

LOAD DATA ステートメントの LOCAL バージョンのサポートに関しては、セキュリティーについての潜在的な問題が 2 つあります。

  • クライアントホストからサーバーホストへのファイルの送信は、MySQL サーバーによって開始されます。理論的には、パッチ適用済みサーバーを構築して、LOAD DATA ステートメントでクライアントによって指定されたファイルでなく、サーバー選択するファイルを転送するようサーバーがクライアントプログラムに指示するようにすることができます。そのようなサーバーは、クライアントユーザーが読み取りアクセス権を持つクライアントホスト上のすべてのファイルにアクセスできます。
  • クライアントが Web サーバーから接続する Web 環境で、ユーザーは LOAD DATA LOCAL を使用して、Web サーバープロセスが読み取りアクセス権を持つすべてのファイルを読み取ることができます (ユーザーが SQL Server に対してあらゆるコマンドを実行できる場合)。この環境では、MySQL サーバーを基準にしたときのクライアントは実際には Web サーバーであって、Web サーバーに接続するユーザーによって実行されているリモートプログラムではありません。
no title

You can specify that as an additional option when setting up your client connection:

mysql -u myuser -p --local-infile somedatabase

This is because that feature opens a security hole. So you have to enable it manually in case you really want to use it.

sql - ERROR 1148: The used command is not allowed with this MySQL version - Stack Overflow

mysql コマンド行クライアントの場合、--local-infile[=1] オプションを指定することによって LOAD DATA LOCAL を有効にするか、--local-infile=0 オプションを指定することによってこれを無効にします。mysqlimport の場合、ローカルデータファイルのロードはデフォルトでオフになっており、--local または -L オプションを使用してこれを有効にします。いずれの場合でも、ローカルロード操作を正常に使用するには、サーバーがこの操作を許可していることが必要。

no title