~/.aws/(config|credentials) の設定から assume roleするラッパーをgolangで実装して、goreleaserでリリースしてみた

最近のgolangのCI周りを勉強する目的で、fujiwaraさんのaswrap – ~/.aws/(config|credentials) で定義した AssumeRole 定義から一時キーを取得してコマンドを起動してくれる wrapperをgolangで再実装してみた。

-> https://github.com/masahide/assumer

まだMFA対応のtodoが残ってたり本家より劣化しているところはありますが、一時キーのキャッシュ保存に対応させたり、rpm,deb,brewのパッケージを作成したので導入が簡単なところぐらいが少ない取り柄

今回やりたかったこと/やったこと

  • goreleaserを使ってrpm,deb,homebrewのパッケージのリリースを自動化
  • codecov.ioでカバレッジの可視化
  • gometalinterで行単位でのignore設定

goreleaser

golang製のソフトウェアのリリース処理を全部引き受けてくれてる便利なツールです。具体的には・・

  • goのクロスコンパイル
  • バイナリのtar.gzアーカイブやrpm,debパッケージ、dockerイメージの作成
  • github.comのGithub Releasesへの添付
  • dockerhubへの登録
  • homebrewのFormula作成
    などかなり幅広く対応しています。

使い方に関しては、 goreleaserを使ってGoで書いたツールのバイナリをGithub Releasesで配布する
を参考にしつつ、goreleaser自身の.travis.yml.goreleaser.ymlがとても参考になるのでこの辺りを真似ながらで基本的に問題ないかと。

codecov.ioでカバレッジの可視化

以前、 golangの静的解析,カバレッジ解析,バイナリリリースをCircleCIで簡単に整えるで使ったcoverallsより導入が簡単だった。
事前にcodecov.ioでトークンを取得して、travisのenvにCODECOV_TOKENとして設定しておいて、あとは、基本的にはこちらもgoreleaserの.travis.ymlを参考にしましたが

.travis.yml
after_success:
  - bash <(curl -s https://codecov.io/bash)

これだけで良いみたいですね。

gometalinterで行単位でのignore設定

gometalinterで様々な静的解析が走るけどその解析ツール毎にignoreを設定するのは大変だなぁと思ってたんですが・・・

https://github.com/masahide/assumer/blob/master/cmd/assumer/main.go#L170

defer cf.Close() // nolint errcheck

のように行単位で// nolint <解析ツール名> でチェックを除外できるようです。
comment-directives に記載されてます。

続きを読む

より美しくWP Offload S3 Liteに既存のメディアを登録する方法

解決したい課題

すでに運用中のwordpressサイトがあります。コンテンツが増加し動画などのメディアファイルが多くなってきて、apacheで配信しているとサイトがどんどん重くなってしまいます。

WP Offload S3 Liteプラグインを導入して新しいメディアファイルはS3から配信されるようになりましたが、既存の大量のメディアファイルをS3から配信するにはどうすればいいのか?

という問題に遭遇したので対応方法を残しておきます。

方法2:SQLでなんとかする方法(NG)

同じようなことでお困りの方が結構いらっしゃるのでググると対応方法が出てきます。その多くはSQLでpost, post_metaを直接書き換える方法がほとんどです。
ですが、レコード内の設定内容はPHPでシリアライズされており、文字数などの記録されています。
正しく書き込むには新しい内容を正しくシリアライズしなくてはいけません。
そのためにプログラムを書かなければいけないのがデメリットです。

方法2: wp_cliでなんとかする。(better)

wb_cliはwordpressの為のコマンドラインインターフェースです。オプション豊富で様々な操作が可能です。これを使ってやってみました。

wp_contents/uploadsの内容ををAWSに転送

aws cliで一発です。

aws s3 sync wp-content/uploads/ s3://awesome-site.hoge.com/wp-content/uploads/

お決まりですが、S3バケットを作成してIAMを作成して、必要な権限だけ与えてください。
{{ bucket_name }}の部分を実際のバケット名に置き換えてください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:CreateBucket",
                "s3:DeleteObject",
                "s3:Put*",
                "s3:Get*",
                "s3:List*"
            ],
            "Resource": [
                "arn:aws:s3:::{{ bucket_name }}",
                "arn:aws:s3:::{{ bucket_name }}/*"
            ]
        }
    ]
}

もう少し権限絞りたい気もしますが、Get/PutのみだとPluginから権限がないと怒られます。

post_metaにS3のパスを正しく記録する

プラグインを入れてからメディアファイルをアップロードすると
post_metaにS3のパスが記録されます。

そこで正しいpost_metaを書き込んであげることで、プラグインに正しくファイルの位置を教えることができます。

メディアファイルのIDを取得する

ここで処理したいのはすべてのmediaファイルです。
メディアファイルのPOST_IDをすべて取得するには、以下のコマンドを使えばいいみたいです。

メディアファイルはpost_typeがattachmentです。

./bin/wp-cli.phar post list --post_type=attachment --format=ids

これを配列にいれてLOOPで処理すれば良さそうです。

メディアファイルのパスを取得する。

postテーブルのレコードのなかでguidというフィールドにhttp://から始まるURIが書かれています。

このような形式で記録されています。

./bin/wp-cli.phar post get 6802
+-----------------------+-----------------------------------------------------------------------------+
| Field                 | Value                                                                       |
+-----------------------+-----------------------------------------------------------------------------+
| ID                    | 6802                                                                        |
| post_author           | 1                                                                           |
| post_date             | 2018-01-30 18:20:09                                                         |
| post_date_gmt         | 2018-01-30 09:20:09                                                         |
| post_content          |                                                                             |
| post_title            | 20130705170431                                                              |
| post_excerpt          |                                                                             |
| post_status           | inherit                                                                     |
| comment_status        | open                                                                        |
| ping_status           | open                                                                        |
| post_password         |                                                                             |
| post_name             | 20130705170431                                                              |
| to_ping               |                                                                             |
| pinged                |                                                                             |
| post_modified         | 2018-01-30 18:20:09                                                         |
| post_modified_gmt     | 2018-01-30 09:20:09                                                         |
| post_content_filtered |                                                                             |
| post_parent           | 0                                                                           |
| guid                  | http://awsome-site.hoge.com/wp-content/uploads/2018/01/20130705170431.png |
| menu_order            | 0                                                                           |
| post_type             | attachment                                                                  |
| post_mime_type        | image/png                                                                   |
| comment_count         | 0                                                                           |
+-----------------------+-----------------------------------------------------------------------------+

必要なのはguidの中にあるcontent/uploads/内のパスですので、正規表現を使って
http://xxx.hoge.com/ みたいなプロトコル・ドメイン名を外します。

./bin/wp-cli.phar post get $ID --field=guid | sed -e 's/(http:.*)/(wp-content.*)/2/'

jqを使ってpost_metaを生成する

プラグインを入れた後にメディアファイルを追加すると以下のようなレコードがpost_metaに生成されます。KEYはamazonS3_infoです。

./bin/wp-cli.phar post meta get 6802 amazonS3_info

3つの情報が記録されています。これを新たに生成してあげればよいわけです。

array (
  'bucket' => 'site.hoge.com',
  'key' => 'wp-content/uploads/2018/01/30182009/20130705170431.png',
  'region' => 'ap-northeast-1',
)

正しいJSONを生成したいので、みんなが大好きなjqを使ってゼロからJSONを構築します。
jqはAWS CLIの結果をJSONでもらって、いろんなフィルタしたりするのに使うことが多いですが、シェルスクリプトからJSONを生成するにも便利です。

実際に実行すると、このような結果が得られます。

jq -Mncr ".bucket = "bucket-name" | .key = "GUID" | .region = "ap-northeast-1""
{"bucket":"bucket-name","key":"GUID","region":"ap-northeast-1"}

こうして生成したJSONを変数にいれて、wp-cliを使ってpost_metaを追加します。

JSON=`jq -Mncr ".bucket = "$BUCKET" | .key = "$GUID" | .region = "ap-northeast-1""`
echo $JSON | ./bin/wp-cli.phar post meta add $ID amazonS3_info --format=json

ちなみにpost_metaを削除することも可能です。

./bin/wp-cli.phar post meta delete $ID amazonS3_info

出来上がり

でき当たったシェルスクリプトがこれです。
すべてのメディアファイルをWP Offload S3 LiteをつかってS3で配信することができるようになりました。

#!/bin/bash

ARRAY=(`./bin/wp-cli.phar post list --post_type=attachment --format=ids`)
for ID in "${ARRAY[@]}"; do
    GUID=`./bin/wp-cli.phar post get $ID --field=guid | sed -e 's/(http:.*)/(wp-content.*)/2/'`
    BUCKET='bucket-name.hoge.com'
    JSON=`jq -Mncr ".bucket = "$BUCKET" | .key = "$GUID" | .region = "ap-northeast-1""`
    echo $JSON | ./bin/wp-cli.phar post meta add $ID amazonS3_info --format=json
done

続きを読む

[AWS][Terraform] Terraform で Amazon Inspector を導入する

TerraformAmazon Inspector を導入して、CloudWatch Events で定期実行させるための手順。
Terraform は v0.11.2 を使っています。

Inspector の導入

Inspector を導入するには、Assessment targets (評価ターゲット) と Assessment templates (評価テンプレート) を設定する必要があります。

Assessment targets の設定

Terraform で Assessment targets を設定するには、aws_inspector_resource_group, aws_inspector_assessment_target リソースを使用します。
こんな感じです。

inspector_target.tf
variable "project" { default = "my-big-project" }
variable "stage"   { default = "production" }

resource "aws_inspector_resource_group" "inspector" {
    tags {
        project   = "${var.project}"
        stage     = "${var.stage}"
        inspector = "true"
    }
}

resource "aws_inspector_assessment_target" "inspector" {
    name               = "my-inspector-target"
    resource_group_arn = "${aws_inspector_resource_group.inspector.arn}"
}

aws_inspector_resource_group では、対象となるインスタンスを特定するための条件を記述します。
上記の例だと、以下のタグが設定されているインスタンスを対象にします。

Name Value
project my-big-project
stage production
inspector true

aws_inspector_assessment_target では、aws_inspector_resource_group で定義した条件を元に Assessment targets を作成します。

Assessment templates の設定

Terraform で Assessment templates を設定するには、aws_inspector_assessment_template リソースを使用します。
こんな感じです。

inspector_template.tf
variable "inspector-rule" = {
    type = "list"
    default = [
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-7WNjqgGu",
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-bBUQnxMq",
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-gHP9oWNT",
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-knGBhqEu"
    ]
}

resource "aws_inspector_assessment_template" "inspector" {
    name       = "my-inspector-template"
    target_arn = "${aws_inspector_assessment_target.inspector.arn}"
    duration   = 3600

    rules_package_arns = [ "${var.inspector-rule}" ]
}

output "assessment_template_arn" {
    value = "${aws_inspector_assessment_template.inspector.arn}"
}

rules_package_arns では、利用可能な Inspector rule package の ARN を設定します。
variable にしておくと、後で rule package を変更したい時に楽ですね。
こんな感じで、使用する rule package を変更できます。

terraform.tfvars
"inspector-rule" = [
    "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-7WNjqgGu",
    "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-bBUQnxMq"
]

使用できる rule package は、aws-cli で取得してください。

# パッケージ一覧の表示
$ aws --region ap-northeast-1 inspector list-rules-packages
{
    "rulesPackageArns": [
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-7WNjqgGu",
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-bBUQnxMq",
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-gHP9oWNT",
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-knGBhqEu"
    ]
}
# 詳細を確認
$ aws --region ap-northeast-1 inspector describe-rules-packages 
  --rules-package-arns "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-7WNjqgGu"
{
    "rulesPackages": [
        {
            "description": "The CIS Security Benchmarks program provides well-defined, un-biased and consensus-based industry best practicesto help organizations assess and improve their security.nnThe rules in this package help establish a secure configuration posture for the following operating systems:nn  -   Amazon Linux version 2015.03 (CIS benchmark v1.1.0)n  n    ",
            "version": "1.0",
            "name": "CIS Operating System Security Configuration Benchmarks",
            "arn": "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-7WNjqgGu",
            "provider": "Amazon Web Services, Inc."
        }
    ],
    "failedItems": {}
}

参考URL: Terraform v0.8.5でAWS Inspectorに対応します

これで terraform apply すれば Assessment targets, templates が作成されます。

動作確認

実際に Inspector が実施されるか確認して見ましょう。

$ aws inspector start-assessment-run 
  --assessment-template-arn arn:aws:inspector:ap-northeast-1:************:target/0-xxxxxxxx/template/0-xxxxxxxx
{
    "assessmentRunArn": "arn:aws:inspector:ap-northeast-1:************:target/0-xxxxxxxx/template/0-xxxxxxxx/run/0-7WNjqgGu"
}

実行状況の確認は aws inspector describe-assessment-runs

$ aws inspector describe-assessment-runs 
  --assessment-run-arns arn:aws:inspector:ap-northeast-1:************:target/0-QOvPswHA/template/0-uCIUy636/run/0-n9nnWOem

CloudWatch Events Schedule による定期実行

当初は CloudWatch Events で定期実行するには Lambda から呼び出すようにしなければいけませんでした。
しかし、CloudWatch Event から直接 Inspector を実行できるようになったため、Lambda を使用しなくても aws_cloudwatch_event_targetaws_cloudwatch_event_rule だけで定期実行設定が可能です。

CloudWatch Events で使用する IAM ロールの作成

まずは、CloudWatch Events で使用する IAM ロールを作ります。

cloudwatch-events-iam-role.tf
esource "aws_iam_role" "run_inspector_role" {
    name               = "cloudwatch-events-run-inspector-role"
    assume_role_policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "events.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
POLICY
}

resource "aws_iam_policy" "run_inspector_policy" {
    name        = "cloudwatch-events-run-inspector-policy"
    description = ""
    policy      = <<POLICY
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "inspector:StartAssessmentRun"
            ],
            "Resource": "*"
        }
    ]
}
POLICY
}

resource "aws_iam_role_policy_attachment" "run_inspector_role" {
    role       = "${aws_iam_role.run_inspector_role.name}"
    policy_arn = "${aws_iam_policy.run_inspector_policy.arn}"
}

CloudWatch Events への登録

CloudWatch Events に登録するために aws_cloudwatch_event_target リソースと aws_cloudwatch_event_rule を作りましょう。

cloudwatch-events.tf
variable "schedule"    { default = "cron(00 19 ? * Sun *)" }

resource "aws_cloudwatch_event_target" "inspector" {
  target_id = "inspector"
  rule      = "${aws_cloudwatch_event_rule.inspector.name}"
  arn       = "${aws_inspector_assessment_template.inspector.arn}"
  role_arn  = "${aws_iam_role.run_inspector_role.arn}"
}

resource "aws_cloudwatch_event_rule" "inspector" {
  name        = "run-inspector-event-rule"
  description = "Run Inspector"
  schedule_expression = "${var.schedule}"
}

schedule_expression の cron() は UTC で設定する必要があるので注意してください。
記述方法は、以下を参考に
参考URL: Rate または Cron を使用したスケジュール式

EC2 への IAM Role の設定と、ユーザーデータによる Inspector エージェントのインストール

評価ターゲットとなる EC2 には、Inspector エージェントがインストールされていて、適切なインスタンスロールが設定されている必要があります。
導入するには、こんな感じ

インスタンスロール

inspectora エージェントを使用するために必要なポリシーをアタッチしたインスタンスロールの作成はこんな感じです。

ec2-instance-role.tf
resource "aws_iam_role" "instance_role" {
    name               = "my-ec2-role"
    path               = "/"
    assume_role_policy = <<POLICY
{
"Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
POLICY
}

resource "aws_iam_instance_profile" "instance_role" {
    name = "my-ec2-role"
    role = "${aws_iam_role.instance_role.name}"
}

resource "aws_iam_policy" "inspector" {
    name        = "my-ec2-iam-policy-inspector"
    description = ""
    policy      = <<POLICY
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeAvailabilityZones",
                "ec2:DescribeCustomerGateways",
                "ec2:DescribeInstances",
                "ec2:DescribeTags",
                "ec2:DescribeInternetGateways",
                "ec2:DescribeNatGateways",
                "ec2:DescribeNetworkAcls",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DescribePrefixLists",
                "ec2:DescribeRegions",
                "ec2:DescribeRouteTables",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeSubnets",
                "ec2:DescribeVpcEndpoints",
                "ec2:DescribeVpcPeeringConnections",
                "ec2:DescribeVpcs",
                "ec2:DescribeVpn",
                "ec2:DescribeVpnGateways",
                "elasticloadbalancing:DescribeListeners",
                "elasticloadbalancing:DescribeLoadBalancers",
                "elasticloadbalancing:DescribeLoadBalancerAttributes",
                "elasticloadbalancing:DescribeRules",
                "elasticloadbalancing:DescribeTags",
                "elasticloadbalancing:DescribeTargetGroups",
                "elasticloadbalancing:DescribeTargetHealth"
            ],
            "Resource": "*"
        }
    ]
}
POLICY
}

resource "aws_iam_role_policy_attachment" "inspector" {
    role       = "${aws_iam_role.instance_role.name}"
    policy_arn = "${aws_iam_policy.inspector.arn}"
}

ユーザーデータによる inspector エージェントのインストール

OS は Amazon Linux を想定してます。
ユーザーデータに書いておけば、インスタンス起動直後に inspector エージェントインストールできますね。
参考URL: Amazon Inspector エージェントをインストールする

ssh-key.pemssh-key.pem.pubssh-keygen で適当に作っておきましょう。

ec2.tf
## AMI
##
data "aws_ami" "amazonlinux" {
    most_recent = true
    owners      = ["amazon"]

    filter {
        name   = "architecture"
        values = ["x86_64"]
    }

    filter {
        name   = "root-device-type"
        values = ["ebs"]
    }

    filter {
        name   = "name"
        values = ["amzn-ami-hvm-*"]
    }

    filter {
        name   = "virtualization-type"
        values = ["hvm"]
    }

    filter {
        name   = "block-device-mapping.volume-type"
        values = ["gp2"]
    }
}

## SSH Key Pair
##
resource "aws_key_pair" "deployer" {
    key_name   = "ssh-key-name"
    public_key = "${file(ssh-key.pem.pub)}"
}

## EC2
##
resource "aws_instance" "ec2" {
    ami                         = "${data.aws_ami.amazonlinux.id}"
    instance_type               = "t2.micro"
    key_name                    = "${aws_key_pair.deployer.key_name}"
    iam_instance_profile        = "${aws_iam_instance_profile.instance_role.name}"

    user_data                   = <<USERDATA
#!/bin/bash
# install inspector agent
cd /tmp
/usr/bin/curl -O https://d1wk0tztpsntt1.cloudfront.net/linux/latest/install
/bin/bash install -u false
/bin/rm -f install
USERDATA

    tags {
        project   = "${var.project}"
        stage     = "${var.stage}"
        inspector = "true"
    }
}

現場からは以上です。

続きを読む

AWS Elastic Beanstalkで、デプロイ時に一つのインスタンスにだけ実行

Elastic Beanstalk へのデプロイで、一つのインスタンスにだけ実行するには container_commandsleader_only というフラグを立てれば良いと思われるが、上手く動作しなかった。しかもオートスケール時には動作しないらしい。

ので、ELB に問い合わせて自身のインスタンスIDと比較するという方法を取った。下記のスクリプトを配置すれば可能。

#!/usr/bin/env bash

if aws elb describe-load-balancers --query 'LoadBalancerDescriptions[].Instances' --region ap-northeast-1 --output text 
    | cat -n 
    | grep $(curl http://169.254.169.254/latest/meta-data/instance-id) 
    | awk '{print $1}' 
    | grep -q 3
then
    echo 'HOME=/tmp' | sudo tee /var/spool/cron/webapp
    echo '* * * * * php /var/app/current/artisan schedule:run >> /dev/null 2>&1' | sudo tee -a /var/spool/cron/webapp
fi
  • grep -q 3 は決め打ちの番号なので、環境で調整する必要あり。
  • インスタンスの中で curl http://169.254.169.254/latest/meta-data/instance-id とすると、そのインスタンス自身のIDが取得できる。
  • IAMロールの設定が別途必要。Elastic Beanstalkに振られているIAMロールに AWSElasticBeanstalkFullAccess を付与すれば良い。

参考

https://qiita.com/idaaki/items/a356d1785a59d4150358

続きを読む

オートヒーリングでゆるーくEIPもヒーリングしてみた

こんにちは、臼田です。 今回はAutoScalingを利用したインスタンスの自動復旧(オートヒーリング)時にEIPもヒーリングする方法を考えたのでご紹介します。 目的 例えば下記のようにWebサーバの環境で、低コストに抑 […] 続きを読む

copy files from local to aws S3 Bucket(aws cli + s3 bucket)

                       **AWS CLI and S3 Bucket**

maxresdefault.jpg

In my current project, I need to deploy/copy my front-end code into AWS S3 bucket. But I do not know how to perform it. One of my colleagues found a way to perform this task.

here are the guidelines from start to end, how to install aws cli, how to use aws cli and other functionalities.

So, let’s start from the beginning.
In my mac, I do not installed aws cli, so I got the error when running the following command.
Open your terminal,

$ aws --version

output
-bash: aws: command not found

(Here I got the solution, https://qiita.com/maimai-swap/items/999eb69b7a4420d6ab64)

So now let’s install the brew, if you do not installed yet.
Step1. Install the brew

$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Step2. check the brew version

$ brew -v

output
Homebrew 1.5.2
Homebrew/homebrew-core (git revision 58b9f; last commit 2018-01-24)

Step3. install aws cli, use the following command

$ brew install awscli

Step4. check the aws cli version

$ aws --version

output
aws-cli/1.14.30 Python/3.6.4 Darwin/17.3.0 botocore/1.8.34

that’s great, now it’s time to configure the AWS credential.
Step5. now configure the aws profile

$ aws configure
AWS Access Key ID [None]: <your access key>
AWS Secret Access Key [None]: <your secret key>
Default region name [None]: <your region name>
Default output format [None]: ENTER

All settings are done.
now you can access your s3 bucket.

now from here, we can learn how to manage our bucket.
Managing Buckets
aws s3 commands support commonly used bucket operations, such as creating, removing, and listing buckets.

1.Listing Buckets

$ aws s3 ls

output
2017-12-29 08:26:08 my-bucket1
2017-11-28 18:45:47 my-bucket2

The following command lists the objects in bucket-name/path (in other words, objects in bucket-name filtered by the prefix path/).

$ aws s3 ls s3://bucket-name

2.Creating Buckets

$ aws s3 mb s3://bucket-name

(aws s3 mb command to create a new bucket. Bucket names must be unique.)

3.Removing Buckets
To remove a bucket, use the aws s3 rb command.

$ aws s3 rb s3://bucket-name

By default, the bucket must be empty for the operation to succeed. To remove a non-empty bucket, you need to include the –force option.

$ aws s3 rb s3://bucket-name --force

This will first delete all objects and subfolders in the bucket and then remove the bucket.

Managing Objects
The high-level aws s3 commands make it convenient to manage Amazon S3 objects as well. The object commands include aws s3 cp, aws s3 ls, aws s3 mv, aws s3 rm, and sync. The cp, ls, mv, and rm commands work similarly to their Unix

The cp, mv, and sync commands include a –grants option that can be used to grant permissions on the object to specified users or groups. You set the –grants option to a list of permissions using the following syntax:

--grants Permission=Grantee_Type=Grantee_ID
         [Permission=Grantee_Type=Grantee_ID ...]

Each value contains the following elements:
* Permission – Specifies the granted permissions, and can be set to read, readacl, writeacl, or full.
* Grantee_Type – Specifies how the grantee is to be identified, and can be set to uri, email address, or id.
* Grantee_ID – Specifies the grantee based on Grantee_Type.
* uri – The group’s URI. For more information, see Who Is a Grantee?
* email address – The account’s email address.
* id – The account’s canonical ID.

aws s3 cp file.txt s3://my-bucket/ --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers full=emailaddress=user@example.com

For more details, please go through the aws official link.
https://docs.aws.amazon.com/cli/latest/userguide/using-s3-commands.html

thank you for taking your precious time to read.

Enjoy coding.:grinning::grinning:

Thanks & Best Regards,
Alok Rawat

続きを読む

Amazon Linux 2 で Rails アプリケーションのサーバーを構成してみる

Amazon Linux 2 の特徴

  • AWS INTEGRATION

    • AWS tools (e.g. AWS CLI) と cloud-init が入った
  • LONG TERM SUPPORT
  • EXTRAS REPOSITORY FOR SOFTWARE PACKAGES
    • amazon-linux-extras で nginx などのパッケージを管理できる
  • ON-PREMISES USE
    • オンプレ利用用途に VM Image などが用意されている
  • SYSTEMD SUPPORT
  • TUNED LTS KERNEL AND NEW TOOLCHAIN
  • SECURITY CONFIGURATIONS
  • SECURITY UPDATES

インスタンスの作成

AMI 選択画面で Amazon Linux 2 LTS Candidate AMI 2017.12.0 (HVM), SSD Volume Type (ami-c2680fa4) を選択してインスタンスを立てる.

公開鍵の追加

vi ~/.ssh/authorized_keys

ユーザーの追加

sudo adduser deploy

ライブラリのインストール

sudo yum -y install 
git make gcc-c++ patch 
openssl-devel 
libyaml-devel libffi-devel libicu-devel 
libxml2 libxslt libxml2-devel libxslt-devel 
zlib-devel readline-devel 
mysql mysql-server mysql-devel 
ImageMagick ImageMagick-devel 
epel-release protobuf-devel

デプロイ先フォルダの用意

sudo mkdir /var/www
sudo chown deploy /var/www/
sudo mkdir /var/www/deploy
sudo chown deploy /var/www/deploy/

nginx のインストール

Amazon Linux 2 では amazon-linux-extras で入れる.

# 確認する
amazon-linux-extras
# install する
sudo amazon-linux-extras install nginx1.12
# ついでに emacs も入れる
sudo amazon-linux-extras install emacs

nginx の起動

# 起動
sudo systemctl start nginx.service
# ステータスの確認
sudo systemctl status nginx.service
# systemd を有効化
sudo systemctl enable nginx.service
# 有効になっているか確認
systemctl is-enabled nginx.service

nginx の設定

# nginx の設定ファイル
sudo vi /etc/nginx/nginx.conf
# 設定再読込
sudo nginx -s reload

ffmpeg

sudo rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-1.el7.nux.noarch.rpm
mkdir ~/tmp
cd ~/tmp
wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
sudo yum -y localinstall epel-release-latest-7.noarch.rpm
sudo yum -y install ffmpeg ffmpeg-devel

wkhtmltoimage

https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.4/wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
tar -xvf wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
sudo mv wkhtmltox/bin/wkhtmltoimage /usr/bin/wkhtmltoimage

NodeJS

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash
source ~/.bashrc
nvm install v8.9.4
nvm use v8.9.4
nvm alias default v8.9.4

Ruby

sudo git clone https://github.com/sstephenson/rbenv.git /usr/local/rbenv
sudo git clone https://github.com/sstephenson/ruby-build.git /usr/local/rbenv/plugin/ruby-build
sudo /usr/local/rbenv/plugin/ruby-build/install.sh
sudo vi /etc/profile.d/rbenv.sh
sudo su -
source /etc/profile.d/rbenv.sh
rbenv install 2.4.3
rbenv global 2.4.3
gem install bundler --no-ri --no-rdoc

タイムゾーン, host の修正

timedatectl, hostnamectl を利用する.

sudo timedatectl set-timezone Asia/Tokyo
sudo hostnamectl set-hostname deploy.dot.com
sudo reboot

New Relic Infrastructure の追加

https://rpm.newrelic.com/accounts/813076 でライセンスキー確認

echo "license_key: YOUR_LICENSE_KEY" | sudo tee -a /etc/newrelic-infra.yml
sudo curl -o /etc/yum.repos.d/newrelic-infra.repo https://download.newrelic.com/infrastructure_agent/linux/yum/el/7/x86_64/newrelic-infra.repo
sudo yum -q makecache -y --disablerepo='*' --enablerepo='newrelic-infra'
sudo yum install newrelic-infra -y

公開鍵

sudo su - deploy
mkdir ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
# デプロイするサービスの公開鍵を追加
vi ~/.ssh/authorized_keys

refs

続きを読む

AWS Batchで固定されたEC2インスタンスのGPUを使う

背景

AWS Batchでは、Jobの定義とAMIの指定を行うことで、
1. 自動でEC2インスタンスを立ち上げ
2. Dockerコンテナを起動
3. コンテナ終了時にEC2インスタンスの自動削除
を行ってくれます。

しかし、EC2インスタンスの料金体系では、毎回インスタンスを立ち上げ・削除するのはコスパが悪いため、Jobが実行されるEC2インスタンスを固定して、実行中以外は削除ではなく、「停止」にしたい!

ということで、その手順をまとめました。
AWS Batch、あるいはAmazon ECS(Elastic Container Service)でGPUを使うための設定も含まれていますので、インスタンスの固定はいいや、という方にも参考になれば、と思います。

AWS Batchの設定

Compute environments(=ECS Cluster)

AWS Batch > Compute environments > Create environment から、AWS BatchのJobを実行する計算環境を作成します。この計算環境は、ECSのClusterとして保存されます。(ECS Clusterが自動で生成され、Compute environmentsに紐付けされます。)

  • Managed:
    AMIを指定しておくことで、Jobの実行時にそのAMIで新たにEC2インスタンスを立ち上げてくれます。
  • Unmanaged:
    Compute environmentsに紐付いたECS Clusterを生成します。EC2インスタンスは、自分でそのClusterに登録する必要があります。

作成されたClusterをECSコンソールから確認しましょう。後ほど使います。
<EnvironmentName>_Batch_<ランダムっぽい文字列> のような名前担っているはずです。

Job Queue

Job Queueは、上記で作成したEnvironmentを選択してください。

Job Definition

Volumes

Name Source path
nvidia /var/lib/nvidia-docker/volumes/nvidia_driver/latest

Mount points

Container path Source volume Read only
/usr/local/nvidia nvidia false

ECSで使える(Dockerが動かせる)EC2インスタンスを用意する

ECS用に最適化されたAMIはAWSから提供されていますが、GPUが載ったものでECS用に最適化されたAMIは提供されていません。

用いるAMIを決める

AWS Batchのドキュメント GPU ワークロードの AMI の作成 にある例では Deep Learning AMI with Source Code (CUDA 9, Amazon Linux) を使用していますが、今回は Deep Learning Base AMI (Amazon Linux) を使用することにしました。
(AWS Batchを用いる = Dockerを用いるので、Hostマシンに機械学習ライブラリは不要。 & Cuda, CuDNNのバージョンが複数あるので、動かすDockerImageが変わった時に助かりそう。)
ここは、必要に応じてaws marketplaceでいろいろ探してみるとよいかと思います。

インスタンスを起動する

IAM

インスタンスからECSに向けたIAM Roleが必要です。Roleの設定がない場合は、EC2コンソールから設定をしましょう。

UserData

UserData
#!/bin/bash
echo "ECS_CLUSTER=<ClusterName>" >> /etc/ecs/ecs.config

Dockerが使えるようにする

上記のAMIのままでは、Dockerが使えないので、ドキュメントを参考に、ECSで使える状態のインスタンスを作成していきます。

configure-gpu.sh
#!/bin/bash
# Install ecs-init, start docker, and install nvidia-docker
sudo yum install -y ecs-init
sudo service docker start
wget https://github.com/NVIDIA/nvidia-docker/releases/download/v1.0.1/nvidia-docker-1.0.1-1.x86_64.rpm
sudo rpm -ivh --nodeps nvidia-docker-1.0.1-1.x86_64.rpm

# Validate installation
rpm -ql nvidia-docker
rm nvidia-docker-1.0.1-1.x86_64.rpm

# Make sure the NVIDIA kernel modules and driver files are bootstraped
# Otherwise running a GPU job inside a container will fail with "cuda: unknown exception"
echo '#!/bin/bash' | sudo tee /var/lib/cloud/scripts/per-boot/00_nvidia-modprobe > /dev/null
echo 'nvidia-modprobe -u -c=0' | sudo tee --append /var/lib/cloud/scripts/per-boot/00_nvidia-modprobe > /dev/null
sudo chmod +x /var/lib/cloud/scripts/per-boot/00_nvidia-modprobe
sudo /var/lib/cloud/scripts/per-boot/00_nvidia-modprobe

# Start the nvidia-docker-plugin and run a container with 
# nvidia-docker (retry up to 4 times if it fails initially)
sudo -b nohup nvidia-docker-plugin > /tmp/nvidia-docker.log
sudo docker pull nvidia/cuda:9.0-cudnn7-devel
COMMAND="sudo nvidia-docker run nvidia/cuda:9.0-cudnn7-devel nvidia-smi"
for i in {1..5}; do $COMMAND && break || sleep 15; done

# Create symlink to latest nvidia-driver version
nvidia_base=/var/lib/nvidia-docker/volumes/nvidia_driver
sudo ln -s $nvidia_base/$(ls $nvidia_base | sort -n  | tail -1) $nvidia_base/latest

スクリプトの実行(Step 4.)

bash ./configure-gpu.sh

これで環境は完成していますが、念のため動作確認(Step 5. )

sudo docker run –privileged -v /var/lib/nvidia-docker/volumes/nvidia_driver/latest:/usr/local/nvidia nvidia/cuda:9.0-cudnn7-devel nvidia-smi

DockerからGPUが使えることを確認できたら(以下のような $ nvidia-smi の結果が見られれば) OKです。

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 384.81                 Driver Version: 384.81                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla V100-SXM2...  Off  | 00000000:00:17.0 Off |                    0 |
| N/A   43C    P0    42W / 300W |     10MiB / 16152MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

ECS Clusterにインスタンスを登録する

Check 1
インスタンスからECSに向けたIAM Roleが必要です。Roleの設定がない場合は、EC2コンソールから設定をしましょう。

Check 2
Clusterにインスタンスを登録するには、インスタンス側での設定が必要です。インスタンス起動時のユーザデータで下記ファイルがきちんと作られていることを確認。できていなければ作りましょう。

/etc/ecs/ecs.config
ECS_CLUSTER=<ClusterName>

ドキュメント のStep 6., 7.的なことをしてあげると、Clusterにインスタンスが登録されます。(しばらく時間がかかります)

sudo docker rm $(sudo docker ps -aq)

sudo docker rmi $(sudo docker images -q)

sudo restart ecs

Submit Job

お好きなフックでどうぞ

EC2インスタンスを停止する

Managedであれば自動でインスタンスを削除してくれますが、Unmanagedの場合、インスタンスの停止も自分で行わなければなりません。
今回は、Jobの成功、失敗にかかわらず停止したいので、以下のpythonスクリプトを自作し、AWS Lambda x CloudWatchEventsで走らせることにしました。

  • [‘SUBMITTED’, ‘PENDING’, ‘RUNNABLE’, ‘STARTING’, ‘RUNNING’] のいずれかの状態のJobがあればそのまま。
  • いずれの状態のJobもなければ、停止。
import os
import boto3

JOB_NAME = os.environ['JOB_NAME']
JOB_QUEUE = os.environ['JOB_QUEUE']
INSTANCE_ID = os.environ['INSTANCE_ID']


def is_running():
    batch = boto3.client('batch')

    check_status = ['SUBMITTED', 'PENDING', 'RUNNABLE', 'STARTING', 'RUNNING']
    for s in check_status:
        list = batch.list_jobs(
            jobQueue=JOB_QUEUE,
            jobStatus=s
        )['jobSummaryList']
        if list:
            print(f"{[j['jobId'] for j in list]} are still {s}.")
            return True
    else:
        return False


def ec2_stop():
    ec2 = boto3.client('ec2')

    response = ec2.describe_instances(
        InstanceIds=[INSTANCE_ID]
    )
    if response['Reservations'] and response['Reservations'][0]['Instances']:
        state = response['Reservations'][0]['Instances'][0]['State']['Name']

        if state in {'pending', 'running'}:
            print(f"Start to stop the instance: {INSTANCE_ID}")
            response = ec2.stop_instances(
                InstanceIds=[INSTANCE_ID]
            )
        else:
            print(f"The instance {INSTANCE_ID} is not running.")
    else:
        raise ValueError(f'No Such Instances: [{INSTANCE_ID}]')

def lambda_handler(event, context):
    if not is_running():
        ec2_stop()

最後に

こんなことするくらいなら、最初からBatchじゃなくて、ECSにしとけばよかったんちゃうか、と思いながら。
ただ新しいものに触れて、上記以外の学びも得たので、それはまた別の時に。

続きを読む

NixOpsを使ってAWS EC2にGPUクラスタを作ってChainerMNを動かしてみた

使用するもの

NixOS

  • Linuxディストリビューションの1つ

    • 関数型パッケージ管理ツールNixを使用している
    • パッケージ自体はnixpkgsのリポジトリで管理・開発されている(個々のパッケージはhttps://nixos.org/nixos/packages.html# で検索できる)
  • 環境の構築が楽にできる
    • 1つのファイルでシステム全体の設定ができる -> 管理が楽
    • システムのアップデート -> システムのロールバック ということが楽にできる
    • sudoとかしなくてもパッケージを用意できる(たとえばpythonでnumpyとmatplotlibを使いたい時は以下のようにする)
$ nix-shell -p python3 -p pythonPackages.numpy -p pythonPackages.matplotlib

NixOps

  • NixOSの環境をリモートマシンにdeployするためのツール
  • 基本的な使い方は以下のような感じ
登録
$ nixops create [deployする環境を書いた.nixファイル(複数可)] -d [環境の名前]

インスタンスの作成&deploy
$ nixops deploy -d [環境の名前]

インスタンスの破棄
$ nixops destroy -d [環境の名前]

Chainer

  • ニューラルネットワーク記述用のpythonフレームワーク

ChainerMN

  • Chainerで複数のGPU上での分散処理を行うための追加パッケージ

はじめに

NixOpsでは、Nixのコードを書くことで、Nixパッケージマネージャを利用した環境をリモートにdeployすることができます。
これを使ってGPUクラスタをデプロイできないかということでやってみました。

利用環境

AWSのEC2のp2.xlargeのインスタンスを使用しました。
GPUはTesla K80になります。

CUDAはCUDA 9.0、cudnnはv7.0、NCCLはv2.1.2を使用します。
MPIはOpenMPIのv1.10です。
これらはすべて利用したnixpkgsに含まれているものを使用します。
(これを書いている時点ではnixpkgsは自前で用意しています)

コード

NixOpsで使用するコード
https://github.com/hyphon81/ec2-gpu-cluster-with-NixOps

./ec2-gpu-cluster-with-NixOps というディレクトリがある想定で書きます。

nixpkgs
https://github.com/hyphon81/nixpkgs/tree/add/chainermn

これについても、 ./nixpkgs が存在する前提で書きます。

事前準備

AWSの準備

  • 当然、アカウントを作ります。
  • NixOpsのマニュアルで説明されてるように、AWS IAMのアクセスキーIDとアクセスキーを入手します。
  • AWS EC2インスタンスで使用するセキュリティグループの設定をします。これは以下の設定を含む必要があります。
    • sshポートの許可
    • 同じセキュリティグループ内でのパケットの許可
  • AWS EC2で使用するsshキーペアを入手します。
  • p2.xlargeインスタンスを使用する場合、インスタンス作成の上限数が1に設定されていると思うので、上限規制緩和の申請を行います。

※これらの手順等についてはここでは説明しません。

ファイルの準備

~/.ec2-keys
<アクセスキーID> <アクセスキー> <IAMユーザ名>
~/.aws/credentials
[<IAMユーザ名>]
aws_access_key_id = <アクセスキーID>
aws_secret_access_key = <アクセスキー>
  • ./ec2-gpu-cluster-with-NixOps/ec2-info.nix を次のように用意します。
./ec2-gpu-cluster-with-NixOps/ec2-info.nix
{ config, pkgs, ... }:

with pkgs.lib;

{
  deployment.ec2.accessKeyId = "<アクセスキーID>";
  deployment.ec2.keyPair = "<AWS EC2のsshキーペア名>";
  deployment.ec2.privateKey = "<ssh秘密鍵ファイルのパス>";
}
  • インスタンス間のssh接続に使用するsshキーペア(ed25519)を用意します。
$ ssh-keygen -t ed25519
...
$ cp ~/.ssh/id_ed25519* ./ec2-gpu-cluster-with-NixOps/

NixOpsによるデプロイ

①. nixops create コマンドを実行し、設定を作ります。

$ nixops create ./ec2-gpu-cluster-with-NixOps/ec2gpu-cluster.nix -d ec2-gpu-cluster

②. 早速 nixops deploy コマンドでAWS EC2インスタンスの作成→環境のデプロイを行います。

$ nixops deploy -d ec2-gpu-cluster -I nixpkgs=./nixpkgs

以上です。
コマンドは2行とあっけないですが、デプロイに結構時間がかかります。
私の場合は1〜2時間ぐらい待ちました。
NVIDIAのドライバやCUDAなどを含むため、デプロイするファイルサイズの合計が5GBぐらいになるようです。

デプロイする環境の設定について

今回用意したファイルは以下のようになっています。

./ec2-gpu-cluster-with-NixOps/ec2gpu-cluster-conf.nix
{ region, ami, instanceType, securityGroups, publicKey, secretKey, hosts }:

{ config, pkgs, resources, ...}:
let
  ## この辺は使用するパッケージの設定です。
  python = pkgs.python3;
  cudatoolkit = pkgs.cudatoolkit;
  mpi = pkgs.openmpi.overrideDerivation (attrs: {
    configureFlags = [ "--with-cuda=${pkgs.cudatoolkit}" ];
  });
  gpu-test1 = pkgs.callPackage ./gpu-test1.nix {
    mpi = mpi;
  };
  gpu-test2 = pkgs.callPackage ./gpu-test2.nix {
    python = python;
    cython = python.pkgs.cython;
    mpi = mpi;
    cudnnSupport = true;
    cudatoolkit = cudatoolkit;
    cudnn = pkgs.cudnn;
    nccl = pkgs.nccl;
  };
in
{ imports = [ ./ec2-info.nix ];
  deployment.targetEnv = "ec2";
  deployment.ec2.ami = ami;
  deployment.ec2.region = region;
  deployment.ec2.instanceType = instanceType;
  deployment.ec2.securityGroups = securityGroups;
  deployment.ec2.ebsInitialRootDiskSize = 20;

  nixpkgs.config.allowUnfree = true;

  environment.systemPackages = [
    python
    mpi
    cudatoolkit
    gpu-test1
    gpu-test2
  ];

  ## 以下が環境設定です。
  services.xserver = {
    enable = true;
    videoDrivers = [
      "nvidia"
    ];
  };

  services.openssh = {
    enable = true;
    hostKeys = [
      { bits = 4096; path = "/etc/ssh/ssh_host_rsa_key"; type = "rsa"; }
      { path = "/etc/ssh/ssh_host_ed25519_key"; type = "ed25519"; }
      { path = "/etc/root/ssh/id_ed25519"; type = "ed25519"; }
    ];
    knownHosts = hosts;
    passwordAuthentication = false;
    challengeResponseAuthentication = false;
  };

  environment.etc = {
    "/root/ssh/id_ed25519" = {
      enable = true;
      user = "root";
      group = "root";
      mode = "0600";
      source = secretKey;
    };
  };

  ## LD_LIBRARY_PATHに必要なライブラリを含めるためにこんなことやってしまっています。
  ## もっとかっこいい方法をご存じの方がいたらぜひ教えてください。
  hardware.opengl = {
    extraPackages = [
      mpi
      pkgs.linuxPackages.nvidia_x11
      cudatoolkit
      cudatoolkit.lib
    ];
  };

  networking.firewall.enable = false;

  users.users.root = {
    openssh.authorizedKeys.keyFiles = [ publicKey ];
  };

  programs.bash.shellInit = ''
    if [ ! -e ~/.ssh/id_ed25519 ] ; then
      if [ -f /etc/root/ssh/id_ed25519 ] ; then
        /run/current-system/sw/bin/ln -s /etc/root/ssh/id_ed25519 .ssh/id_ed25519
      fi
    fi
  '';
}
./ec2-gpu-cluster-with-NixOps/ec2gpu-cluster.nix
let
  ## ここでデプロイする先のAWS EC2の設定を記述しています
  region = "ap-northeast-1"; ## 東京リージョン
  ami = "ami-89b921ef"; ## 東京リージョンのNixOSのAMI https://nixos.org/nixos/download.html
  instanceType = "p2.xlarge"; ## インスタンスタイプ
  ec2 = import ./ec2gpu-cluster-conf.nix;

  securityGroups = [ "allow-ssh" ]; ## インスタンスが所属するセキュリティグループ名を入れてください
  secretKey = ./id_ed25519;
  publicKey = ./id_ed25519.pub;

  hosts = [
    { hostNames = [ "node1" ]; publicKeyFile = publicKey; }
    { hostNames = [ "node2" ]; publicKeyFile = publicKey; }
    { hostNames = [ "node3" ]; publicKeyFile = publicKey; }
    { hostNames = [ "node4" ]; publicKeyFile = publicKey; }
  ];
in
{
  network.description = "An ec2 gpu cluster create test";

  node1 = ec2 {
    inherit region ami instanceType securityGroups publicKey secretKey hosts;
  };
  node2 = ec2 {
    inherit region ami instanceType securityGroups publicKey secretKey hosts;
  };
  node3 = ec2 {
    inherit region ami instanceType securityGroups publicKey secretKey hosts;
  };
  node4 = ec2 {
    inherit region ami instanceType securityGroups publicKey secretKey hosts;
  };
  ## 4ノード作成します
}

デプロイ完了後の操作(動作確認)

①. NVIDIAドライバインストールがあったため、ドライバの読み込み等必要になるので、一度全ノードをrebootしたほうが良いです。

$ nixops ssh-for-each -d ec2-gpu-cluster -p reboot

②. その後少し待ってnode1に接続します。

$ nixops ssh -d ec2-gpu-cluster node1
...
[root@node1]#

③. 今回用意したnixコードでは以下のパッケージを含み、テストができます。
(こちらに記載されているテストコードをそのまま使用しています。)

// gpu-mpi-test
// mpiパッケージがCUDA-Awareに対応しているか確認するプログラムです。
// 問題なければOKと出るだけです。
[root@node1]# gpu-mpi-test
OK.

// check_mpi4py
// mpi4pyが動作するかの確認です。
// node1〜node4が表示されれば問題ありません。
[root@node1]# mpiexec --allow-run-as-root -n 4 -host node1,node2,node3,node4 check_mpi4py
node1 0
node2 1
node3 2
node4 3

まぁ、Nixなので一度動作を確認できた環境なら同じコード使えば同じように動くはずなんですが・・・

ChainerMNを使用したMNISTの学習の動作

コード自体はここに従って用意しています。

実際に動作させてみたときの動画がこちらです
※ 6分程度と長いのでBGMつけました。音が出ます。

ビデオが開けなかった場合に表示されます

一応、動作していました。

余談

ChainerMNでMNISTの学習が動作できたのですが、
ノードを1つだけ使ったときのほうが計算が早く終わりました。

ビデオが開けなかった場合に表示されます

ChainerMNの論文を見る限り、
ノード増やすとほぼリニアにスピードアップするグラフが乗っているので、
何か間違ったかと思っていました。
https://arxiv.org/abs/1710.11351

ですが、こちらのスライドではそもそもMNISTの学習は
ChainerMNの速度の測定に使用するには向かない旨の注意が書いてありました。
https://www.slideshare.net/pfi/20171128chainermn

というわけで、ノード増やしてスピードアップすることを確認するには、
ちゃんとしたベンチマークになりうるプログラムを用意する必要がありそうです。

とりあえず、NixOpsでChainerMNが動作する環境の構築はできたということで、
今回はここまでです。

続きを読む

(JSON取得によるRedmineチケット駆動) – Qiita

AWS-CLIによるAMI作成と削除(JSON取得によるRedmineチケット駆動) – Qiita. #!/bin/bash #JSON形式でチケット情報を取得(終了チケットを含めて取得) JSON=$(curl -v -H “Content-Ty… 続きを表示 #!/bin/bash #JSON形式でチケット情報を取得(終了チケットを含めて取得) JSON=$(curl -v -H “Content-Type: … 続きを読む