EC2 拡張ネットワーキング 有効化手順

EC2 拡張ネットワーキング 有効化手順

ちゃんとした情報は公式をみよう。

インスタンスタイプに応じて、ixgbevf ドライバ、もしくは amzn-drivers を利用出来る状態に設定し、AMIもしくはインスタンスに利用可能とフラグ付けを行う事によって拡張ネットワーキングが利用可能となる。

インスタンスタイプ ドライバ
c3/c4/d2/i2/r3/m4(16xlarge以外) ixgbevf
c5/f1/g3/h1/i3/m5/p2/p3/r4/x1/m4.16xlarge amzn-drivers

確認事項

Amazon Linuxの場合

通常、対応するためのカーネルモジュールがインストールされている為、作業は不要。

CentOS 6の場合

カーネルモジュールの更新が必要。

CentOS 7の場合

少なくとも 7.4.1708 以降ではカーネルモジュールがインストールされている為、作業は不要。

モジュールの確認

ixgbevfena のカーネルモジュールの状態を確認し、バージョン情報を確認する。
ixgbevf は特定のバージョン以下の場合はカーネルモジュールの更新が必要となる。

対応バージョン

ドライバ 必要バージョン
ixgbevf 2.14.2 以降
ena インストールされている事
$ modinfo ixgbevf
filename:       /lib/modules/3.10.0-693.11.6.el7.x86_64/kernel/drivers/net/ethernet/intel/ixgbevf/ixgbevf.ko.xz
version:        3.2.2-k-rh7.4
license:        GPL
description:    Intel(R) 10 Gigabit Virtual Function Network Driver
author:         Intel Corporation, <linux.nics@intel.com>
rhelversion:    7.4
srcversion:     45F26A06C9B8C3202EA1ADC
alias:          pci:v00008086d000015C5sv*sd*bc*sc*i*
alias:          pci:v00008086d000015A9sv*sd*bc*sc*i*
alias:          pci:v00008086d000015A8sv*sd*bc*sc*i*
alias:          pci:v00008086d00001564sv*sd*bc*sc*i*
alias:          pci:v00008086d00001565sv*sd*bc*sc*i*
alias:          pci:v00008086d00001530sv*sd*bc*sc*i*
alias:          pci:v00008086d00001515sv*sd*bc*sc*i*
alias:          pci:v00008086d0000152Esv*sd*bc*sc*i*
alias:          pci:v00008086d000010EDsv*sd*bc*sc*i*
depends:
intree:         Y
vermagic:       3.10.0-693.11.6.el7.x86_64 SMP mod_unload modversions
signer:         CentOS Linux kernel signing key
sig_key:        2C:BC:98:70:54:63:43:CA:3A:E1:20:C2:BC:EB:98:44:01:95:59:62
sig_hashalgo:   sha256
parm:           debug:Debug level (0=none,...,16=all) (int)
$ modinfo ena
filename:       /lib/modules/3.10.0-693.11.6.el7.x86_64/kernel/drivers/net/ethernet/amazon/ena/ena.ko.xz
version:        1.0.2
license:        GPL
description:    Elastic Network Adapter (ENA)
author:         Amazon.com, Inc. or its affiliates
rhelversion:    7.4
srcversion:     3A6B9F1766C9A0B5CBC7D01
alias:          pci:v00001D0Fd0000EC21sv*sd*bc*sc*i*
alias:          pci:v00001D0Fd0000EC20sv*sd*bc*sc*i*
alias:          pci:v00001D0Fd00001EC2sv*sd*bc*sc*i*
alias:          pci:v00001D0Fd00000EC2sv*sd*bc*sc*i*
depends:
intree:         Y
vermagic:       3.10.0-693.11.6.el7.x86_64 SMP mod_unload modversions
signer:         CentOS Linux kernel signing key
sig_key:        2C:BC:98:70:54:63:43:CA:3A:E1:20:C2:BC:EB:98:44:01:95:59:62
sig_hashalgo:   sha256
parm:           debug:Debug level (0=none,...,16=all) (int)

使用中のドライバ確認

利用可能なインスタンスタイプで起動している場合に、使用中のドライバを確認し、ixgbevf もしくは ena が使用されている事を確認する。
使用されていない場合(driverが vif となっている)は拡張ネットワーキングが有効になっていないので確認が必要。

無効時の例

$ ethtool -i eth0
driver: vif
version:
firmware-version:
bus-info: vif-0
supports-statistics: no
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no

ixgbevfが有効時の例

$ ethtool -i eth0
driver: ixgbevf
version: 3.2.2-k-rh7.4
firmware-version:
expansion-rom-version:
bus-info: 0000:00:03.0
supports-statistics: yes
supports-test: yes
supports-eeprom-access: no
supports-register-dump: yes
supports-priv-flags: no

カーネルモジュールのインストール

事前準備

kernel kernel-headers kernel-develのバージョンを合わせる必要がある。

最新のkernelにアップデートする事を推奨しますが、旧カーネルの場合は kernel-headerskernel-devel をバージョン指定してインストールを行う事により対応が可能となる。

CentOS 6の中でも最新マイナーバージョン以下を利用する際はyumリポジトリが既にミラーから削除されている為、vault.centos.orgのリポジトリを利用する様に修正が必要となる。

# cat /etc/centos-release
CentOS release 6.2 (Final)

# sed -i.bak -E 's/^mirrorlist=/#mirrorlist=/' /etc/yum.repos.d/CentOS-Base.repo
# sed -i -E 's@^#?baseurl=http://mirror.centos.org/centos/$releasever/@baseurl=http://vault.centos.org/6.2/@' /etc/yum.repos.d/CentOS-Base.repo

CentOSのバージョンに合わせてsedの 6.2 となっている部分を修正する。

また、dkms によるカーネルアップデート時の自動コンパイル設定を行う事を推奨するため、epel リポジトリを有効化する。

準備

epelが設定されていない場合

# yum install -y epel-release
# sed -i -E 's/^enabled=1$/enabled=0/' /etc/yum.repos.d/epel*

各種パッケージのインストール

先にkernel-headersとkernel-develをインストールしておく。
また、ビルド時にperlが要求される場合があるので合わせてインストールする。

# yum install -y kernel-headers-$(uname -r) kernel-devel-$(uname -r) perl

既にkernel-headersがインストールされており、かつkernelよりバージョンが新しいものとなっている場合はダウングレードを行う。

# yum downgrade kernel-headers-$(uname -r)

dkmsはEPELからインストールを行う。

# yum --enablerepo=epel install -y dkms

ixgbevf のインストール

VER_IXGBEVF=4.3.3

curl -L -o "ixgbevf-${VER_IXGBEVF}.tar.gz" "https://downloads.sourceforge.net/project/e1000/ixgbevf%20stable/${VER_IXGBEVF}/ixgbevf-${VER_IXGBEVF}.tar.gz?r=https%3A%2F%2Fsourceforge.net%2Fprojects%2Fe1000%2Ffiles%2Fixgbevf%2520stable%2F${VER_IXGBEVF}%2Fixgbevf-${VER_IXGBEVF}.tar.gz%2Fdownload%3Fuse_mirror%3Djaist&ts=`date +%s`"
tar -xzvf ixgbevf-${VER_IXGBEVF}.tar.gz
rm -f ixgbevf-${VER_IXGBEVF}.tar.gz
mv ixgbevf-${VER_IXGBEVF} /usr/src/

echo 'PACKAGE_NAME="ixgbevf"
PACKAGE_VERSION="'${VER_IXGBEVF}'"
CLEAN="cd src/; make clean"
MAKE="cd src/; make BUILD_KERNEL=${kernelver}"
BUILT_MODULE_LOCATION[0]="src/"
BUILT_MODULE_NAME[0]="ixgbevf"
DEST_MODULE_LOCATION[0]="/updates"
DEST_MODULE_NAME[0]="ixgbevf"
AUTOINSTALL="yes"' | tee /usr/src/ixgbevf-${VER_IXGBEVF}/dkms.conf

dkms add -m ixgbevf -v ${VER_IXGBEVF}
dkms build -m ixgbevf -v ${VER_IXGBEVF}
dkms install -m ixgbevf -v ${VER_IXGBEVF}

amzn-drivers (ena) のインストール

VER_AMZN_DRIVERS=1.5.0

curl -L -o "ena_linux_${VER_AMZN_DRIVERS}.tar.gz" "https://github.com/amzn/amzn-drivers/archive/ena_linux_${VER_AMZN_DRIVERS}.tar.gz"
tar -xzvf ena_linux_${VER_AMZN_DRIVERS}.tar.gz
rm -f ena_linux_${VER_AMZN_DRIVERS}.tar.gz
mv amzn-drivers-ena_linux_${VER_AMZN_DRIVERS} amzn-drivers-${VER_AMZN_DRIVERS}
mv amzn-drivers-${VER_AMZN_DRIVERS} /usr/src/

echo 'PACKAGE_NAME="ena"
PACKAGE_VERSION="'${VER_AMZN_DRIVERS}'"
CLEAN="make -C kernel/linux/ena clean"
MAKE="make -C kernel/linux/ena/ BUILD_KERNEL=${kernelver}"
BUILT_MODULE_LOCATION[0]="kernel/linux/ena"
BUILT_MODULE_NAME[0]="ena"
DEST_MODULE_LOCATION[0]="/updates"
DEST_MODULE_NAME[0]="ena"
AUTOINSTALL="yes"' | tee /usr/src/amzn-drivers-${VER_AMZN_DRIVERS}/dkms.conf

dkms add -m amzn-drivers -v ${VER_AMZN_DRIVERS}
dkms build -m amzn-drivers -v ${VER_AMZN_DRIVERS}
dkms install -m amzn-drivers -v ${VER_AMZN_DRIVERS}

カーネルモジュールの有効化

depmod
cp /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r).img.bak
dracut -f

この後、インスタンスを停止する。

拡張ネットワーキングの有効化

属性確認

インスタンスに属性が付与されているかを確認する。
属性が付与されていない場合は無効化されている状態のため、設定を行う。

これらはコンソール上では現れない情報の為、CLIにて作業を行う。

SriovNetSupport の確認

# aws ec2 describe-instance-attribute --attribute sriovNetSupport --region ap-northeast-1 --instance-id <インスタンスID>
{
    "InstanceId": "<インスタンスID>",
    "SriovNetSupport": {}
}

SriovNetSupportが空の場合は無効な為、有効化する必要がある。

EnaSupport の確認

# aws ec2 describe-instances --query 'Reservations[].Instances[].EnaSupport' --region ap-northeast-1 --instance-ids <インスタンスID>
[
]

EnaSupportが空の場合は無効な為、有効化する必要がある。

SriovNetSupport の設定

# aws ec2 modify-instance-attribute --sriov-net-support simple --region ap-northeast-1 --instance-id <インスタンスID>

# aws ec2 describe-instance-attribute --attribute sriovNetSupport --region ap-northeast-1 --instance-id <インスタンスID>
{
    "InstanceId": "<インスタンスID>",
    "SriovNetSupport": {
        "Value": "simple"
    }
}

EnaSupport の有効化

# aws ec2 modify-instance-attribute --ena-support --region ap-northeast-1 --instance-id <インスタンスID>

# aws ec2 describe-instances --query 'Reservations[].Instances[].EnaSupport' --region ap-northeast-1 --instance-ids <インスタンスID>
[
    true
]

属性の設定後、インスタンスを対応タイプで起動し、ethtool -i eth0 で確認する。

続きを読む

terraformでS3バケットのACLに権限を付与する

CloudFrontのアクセスログをS3に保存させる事はごくごく普通にあると思いますが、terraformで環境を構築しているとS3作成時に特殊なACLは設定できず、CloudFront作成時にログ出力指定をしていると権限不足で落ちてしまいます。

参考: アクセスログ – Amazon CloudFront

terraformだけで解決できれば一番良いのですが、2017年6月現在ではissueが出ているものの反映されるのはまだ先になりそうな感じです。

GUIからぽちぽちしてると勝手にACLを作ってくれるので、手で作った後にterraformに記載するとかいう意味のない作業をしていたのですが、そんな作業やりたくなかったので無理やり気味ではありますがterraform applyを実行するだけでS3にACLを付与し、CloudFrontの構築まで一気通貫で行えるようにちょっとした工夫を加えてみました。

準備するもの

linux/mac前提です。windowsの場合はbash on windowsであれば動作可能です。

必須

  • terraform
  • AWS CLI

推奨

  • direnv

準備するスクリプト

bin/AssignAwsdatafeedsAcl
#!/bin/sh

# 自身のディレクトリパスを取得
CURRENT_DIR=$(cd $(dirname $0);pwd)/

# 引数のチェックを行う
if [ $# -ne 1 ]; then
    exit 1
fi

# バケット名を引数から取得
BUCKET_NAME=$1

TEMP_FILE=$(mktemp)

# S3待ち(waitが無い場合にエラーが発生)
sleep 2

# 現在のバケットACL情報を取得する
aws s3api get-bucket-acl --bucket ${BUCKET_NAME} > ${TEMP_FILE}
if [ $? -ne 0 ]; then
    # テンポラリファイルを削除する
    rm -f ${TEMP_FILE}
    exit 1
fi

# ACLにawsdatafeeds権限が含まれていない場合は追加する
grep awsdatafeeds ${TEMP_FILE}
if [ $? -eq 1 ]; then
    # 追記する文字列を取得
    INPUT_LINES=$(perl -p -e 's/n/\n/' ${CURRENT_DIR}acl.txt)
    if [ $? -ne 0 ]; then
        # テンポラリファイルを削除する
        rm -f ${TEMP_FILE}
        exit 1
    fi

    # 権限情報を追記
    sed -i -e "s/("Grants": *[)/1n${INPUT_LINES}/" ${TEMP_FILE}
    if [ $? -ne 0 ]; then
        # テンポラリファイルを削除する
        rm -f ${TEMP_FILE}
        exit 1
    fi

    # 権限情報をS3バケットに反映
    aws s3api put-bucket-acl --bucket ${BUCKET_NAME} --access-control-policy "$(cat ${TEMP_FILE})"
    if [ $? -ne 0 ]; then
        # テンポラリファイルを削除する
        rm -f ${TEMP_FILE}
        exit 1
    fi
fi

# テンポラリファイルを削除する
rm -f ${TEMP_FILE}

exit 0
bin/acl.txt
        {
            "Permission": "FULL_CONTROL",
            "Grantee": {
                "DisplayName": "awsdatafeeds",
                "ID": "c4c1ede66af53448b93c283ce9448c4ba468c9432aa01d700d3878632f77d2d0",
                "Type": "CanonicalUser"
            }
        },

上記2ファイルをパスが通ったところに配置しておきます。
シェルスクリプトの方にはちゃんと実行権限を付与しましょう。

ちなみにdirenvを使って、terraform実行パスなどでPATHを追加するのが推奨です。

.envrc
export AWS_DEFAULT_PROFILE=[AWSプロファイル名]
export AWS_DEFAULT_REGION=[デフォルトとするリージョン]

export AWS_PROFILE=$AWS_DEFAULT_PROFILE
export AWS_REGION=$AWS_DEFAULT_REGION

PATH_add `pwd`/bin

terraformの記述

s3.tf
resource "aws_s3_bucket" "sample" {
    bucket = "sample-cfn-logs"
    acl    = "private"
    tags {
         Name = "sample-cfn-logs"
    }

    provisioner "local-exec" {
         command = "AssignAwsdatafeedsAcl ${aws_s3_bucket.test.bucket}"
    }
}

概要

terraformのprovisionerにlocal-execという、実行マシンでのコマンド実行機能があります。

これはリソースが作成されたのちに実行されるので、S3リソースが作成された後にシェルスクリプトを実行し、AWS CLIを利用してS3バケットにACLを付与しています。

上記スクリプトでは下記の様な処理を行っています。

  1. aws cli: S3バケットの設定済みACLを取得
  2. shell: 取得したACLにawsdatafeedsの権限が付与されているかチェックする
  3. shell: 権限がない場合、権限の内容を取得したACLに追記する
  4. aws cli: 改変したACL情報をS3バケットに反映する

S3バケットが構築されてからAPIで叩けるまでに微妙なタイムラグがあるらしく、sleepが入っていないとAPIを叩いた時にバケットが存在しないと怒られてしまいます。

ちゃんとするならば、APIのレスポンスを見て待つ処理を入れるのが良いのですが、terraformがMulti ACLに対応するまでの暫定的な対応なのでsleepで濁しています。

配置したスクリプトにパスが通っていないとlocal-execの指定時にわざわざパスを書いてあげる必要があるので、direnv使ってパス通しちゃいましょう。

相対パスがどこからになるのか知らない。

ちなみにacl.txtの内容を変えると好きな権限を入れれます。でもあまり使わないですし変更検知もされないので推奨はしません。

どうしてもという場合はaws_s3_bucketリソースの代わりにnull_resourceリソースを使って毎回スクリプトをキックするようにした上で、前回実行のACLと反映するACLに差分がある時に実行するなど工夫をしてみてください。

結論

はよterraform自体で対応して。

続きを読む