2019年9月26日木曜日

centos6.7にpython3.6のインストール方法

centos6にディフォルトpython2.6がインストールされている状態ですが、python3系を使いたいので、早速インストールしてみます。

まず、iusリポジトリーが有効にします。

# yum install -y https://centos6.iuscommunity.org/ius-release.rpm
Loaded plugins: fastestmirror, security
Setting up Install Process
Cannot open: https://centos6.iuscommunity.org/ius-release.rpm. Skipping.
Error: Nothing to do

理由はよくわからないですが、リポジトリーを足せなかったです。
むりやり、rpmファイルを落としてきます。
# wget https://centos6.iuscommunity.org/ius-release.rpm
rpmでインストールします。
# rpm -ivh ius-release.rpm
インストールできたことを確認します。
# yum repolist all | grep 'ius'
ius                    IUS for Enterprise Linux 6 - x86_64        enabled:   244
ius-archive            IUS for Enterprise Linux 6 - Archive - x86 disabled
ius-archive-debuginfo  IUS for Enterprise Linux 6 - Archive - x86 disabled
ius-archive-source     IUS for Enterprise Linux 6 - Archive - Sou disabled
ius-debuginfo          IUS for Enterprise Linux 6 - x86_64 - Debu disabled
ius-source             IUS for Enterprise Linux 6 - Source        disabled
ius-testing            IUS for Enterprise Linux 6 - Testing - x86 disabled
ius-testing-debuginfo  IUS for Enterprise Linux 6 - Testing - x86 disabled

ius-testing-source     IUS for Enterprise Linux 6 - Testing - Sou disabled

Python3.6をインストールします。

インストール可能なパッケージがあるかを確認
# yum --enablerepo=ius search python36
Loaded plugins: fastestmirror, security
Loading mirror speeds from cached hostfile
 * base: ftp-srv2.kddilabs.jp
 * extras: ftp-srv2.kddilabs.jp
 * updates: ftp-srv2.kddilabs.jp
============================================================================== N/S Matched: python36 ===============================================================================
python36u-test.x86_64 : The self-test suite for the main python36u package
python36.x86_64 : Interpreter of the Python programming language
python36-debug.x86_64 : Debug version of the Python runtime
python36-devel.x86_64 : Libraries and header files needed for Python development
python36-gunicorn.noarch : Python WSGI application server
python36-idle.x86_64 : A basic graphical development environment for Python
python36-libs.x86_64 : Python runtime libraries
python36-lxml.x86_64 : XML processing library combining libxml2/libxslt with the ElementTree API
python36-mod_wsgi.x86_64 : A WSGI interface for Python web applications in Apache
python36-pip.noarch : A tool for installing and managing Python packages
python36-redis.noarch : Python interface to the Redis key-value store
python36-setproctitle.x86_64 : Python module to customize a process title
python36-setuptools.noarch : Easily build and distribute Python packages
python36-test.x86_64 : The self-test suite for the main python3 package
python36-tkinter.x86_64 : A GUI toolkit for Python
python36u.x86_64 : Interpreter of the Python programming language
python36u-debug.x86_64 : Debug version of the Python runtime
python36u-devel.x86_64 : Libraries and header files needed for Python development
python36u-gunicorn.noarch : Python WSGI application server
python36u-libs.x86_64 : Python runtime libraries
python36u-lxml.x86_64 : XML processing library combining libxml2/libxslt with the ElementTree API
python36u-mod_wsgi.x86_64 : A WSGI interface for Python web applications in Apache
python36u-pip.noarch : A tool for installing and managing Python packages
python36u-redis.noarch : Python interface to the Redis key-value store
python36u-setproctitle.x86_64 : Python module to customize a process title
python36u-setuptools.noarch : Easily build and distribute Python packages
python36u-tkinter.x86_64 : A GUI toolkit for Python
python36u-tools.x86_64 : A collection of tools included with Python including 2to3 and idle
uwsgi-plugin-python36u.x86_64 : uWSGI - Plugin for Python support
いよいよインストールします。
# yum --enablerepo=ius install python36
インストールできたことを確認
# python36 --version
Python 3.6.8

2019年9月25日水曜日

terraformを使って、redisを作成する方法

terraformを使って、各AZに一つずつノード(合計3つ)が存在するredisクラスターを作成します。
完成イメージ は以下の通りです。






 tfファイルの内容は以下の通りです。
resource "aws_elasticache_subnet_group" "grp" {
  name = "redis-example"
  subnet_ids = ["${var.subnet_id_public_a}", "${var.subnet_id_public_c}", "${var.subnet_id_public_d}"]
}
resource "aws_elasticache_replication_group" "replica_grp" {
  automatic_failover_enabled = true
  availability_zones = ["ap-northeast-1d", "ap-northeast-1c", "ap-northeast-1a"]
  replication_group_id = "example-redis"
  replication_group_description = "This is a example for create redis by terraform."
  node_type = "cache.t2.small"
  snapshot_retention_limit = 5
  number_cache_clusters = 3
  port = 6379
  subnet_group_name = "${aws_elasticache_subnet_group.grp.name}" 
  security_group_ids = ["${var.default_security_group_id}"]
}
subnet_ids:作成されたサブネットのIDを入力します。プライベートサブネットにしましょう。
availability_zones :3つのゾーンを入力します。
snapshot_retention_limit:バックアップの保存期間になります

terraform環境毎に切り替える方法

terraformで環境毎に切り替えるにはterraform workspaceを使います。
今回はステージング環境と本番環境でそれぞれS3バケット一つの作成を例とします。具体的な操作手順は以下の通りです。

まず、ステージング環境と本番環境用workspaceを作成

  • ステージング環境のワークスペースを作成
$ terraform workspace new staging
Created and switched to workspace "staging"!
You're now on a new, empty workspace. Workspaces isolate their state,
so if you run "terraform plan" Terraform will not see any existing state
for this configuration.
  • 本番環境用ワークスペースを作成
$ terraform workspace new prod
Created and switched to workspace "prod"!
You're now on a new, empty workspace. Workspaces isolate their state,
so if you run "terraform plan" Terraform will not see any existing state
for this configuration.
  • ワークスペース一覧を確認
$ terraform workspace list
default
* prod
staging
  • ステージング環境を作業中にします。
$ terraform workspace select staging
Switched to workspace "staging".

ステージングと本番用awsアカウント情報を設定

  • aws認証情報ファイル(~/.aws/credentials)の中、以下のようにステージングと本番用アクセスキーを設定します。
$ vi ~/.aws/credentials
[stg]
aws_access_key_id = xxxxxx
aws_secret_access_key = xxxxxxxxxxxxxxxxxxx
region = ap-northeast-1
[prod]
aws_access_key_id = xxxx
aws_secret_access_key = xxxxxxxxxxxxxxxxxxx
region = ap-northeast-1
  • main.tfというファイルを作成し、以下のようにアカウントを切り替えします。
$ vi main.tf
provider "aws" {
  region = "ap-northeast-1"
  profile = "${terraform.workspace == "staging"? "stg" : "prod"}"
}
簡単に説明すると、選択さらたワークスペースによってステージングと本番のプロフィルを使い分けます。

S3バケットを作成します

  • ステージング環境と本番環境用変数を作成します。
$ vi staging.tfvars
bucket_name = "stg-workspace-test"

$ vi prod.tfvars
bucket_name = "workspace-test"
  • バケットを作成するため、s3.tfというファイルを作成します。
$ vi s3.tf
variable "bucket_name" {}
resource "aws_s3_bucket" "example" {
  bucket = "${var.bucket_name}"
  acl = "private"
}

まず、ステージング環境で作成します。

  • 初期化します。
$ terraform init
Initializing provider plugins...
  • 実行します
$ terraform workspace select staging && terraform apply -var-file=staging.tfvars
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
+ aws_s3_bucket.example
id: <computed>
acceleration_status: <computed>
acl: "private"
arn: <computed>
bucket: "stg-workspace-test"
bucket_domain_name: <computed>
bucket_regional_domain_name: <computed>
force_destroy: "false"
hosted_zone_id: <computed>
region: <computed>
request_payer: <computed>
versioning.#: <computed>
website_domain: <computed>
website_endpoint: <computed>

Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions in workspace "staging"?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
上記、簡単に説明すると、まずstaging環境を選んで、設定ファイルstaging.tfvarsを適用した上でterraformを実行します。

本番環境で実行します。

ステージング環境で似てようで、以下のコマンドを使って本番でも実行します。
$ terraform workspace select prod && terraform apply -var-file=prod.tfvars

2019年9月24日火曜日

terraformで特定のリソースだけを削除/作成する

terraformで特定なリソースを削除

terraformでウェブアプリケーションのインフラを構築しました。
検証中にとあるリソースの設定にミスがあることに気づきました。すべて削除して再構築するには時間が…
terraformで特定のリソースだけを削除することができます。

以下、terraformで特定のresourceを削除する方法を紹介します。

以下のバケットの削除を例とします。

resource "aws_s3_bucket" "s3-example" {
    bucket = "${local.name_prefix}-example"
    acl    = "private"
}

オフィシャルサイトのドキュメントを読んだところ、特定のリソースを削除する時にオプション-target RESOURCE_TYPE.NAMEを追加するだけです。
でしたら以下のコマンドを試してみました。

$ terraform destroy --target aws_s3_bucket.s3-example

見事に上記のバケットだけが削除されました。
おまけに、複数のリソースを指定して削除を行う場合は複数回-targetfsオプションをつけることで一回の操作で複数のリソースを削除することができます。

terraform destroy -target RESOURCE_TYPE.NAME -target RESOURCE_TYPE2.NAME

terraformで特定なリソースを作成

terraformで特定なリソースを作成したい場合は削除と同じく-targetをつけます。例:

$ terraform apply --target aws_s3_bucket.s3-example

2019年9月22日日曜日

terraform workspaceとは?

terraformのworkspaceとは?

簡単に言うと、terraformで行った操作や、状態のデータなどを保持する場所です。

terraform workspaceのコマンド一覧は以下の通りです。
$ terraform workspace -h
Usage: terraform workspace

  New, list, show, select and delete Terraform workspaces.

Subcommands:
    delete    Delete a workspace
    list      List Workspaces
    new       Create a new workspace
    select    Select a workspace
    show      Show the name of the current workspace
  • terraform workspace delete:ワークスペースを削除
  • terraform workspace list:ワークスペースの一覧を表示する
  • terraform workspace new:ワークスペースを新規作成
  • terraform workspace select:ワークスペースを選択する
  • terraform workspace show:現在作業中(選択された)ワークスペースの名前を表示

terraform initで最初にワークスペースを初期化した直後に、defaultという名前のワークスペースが作られます。

2019年9月20日金曜日

terraformでRoute53にレコードを追加しようとしたら、「but it already exist」のエラーが発生しました

terraformを使って、Route53にロードバランサーのレコードを追加しようとしたら、エラーが起きました。
使ったソースコードは以下の通りです。
resource "aws_route53_record" "www" {
  zone_id = "Z1234txxxxx"
  name    = "test.com"
  type    = "A"

  alias {
    name                   = "${aws_lb.elb.dns_name}"
    zone_id                = "${aws_lb.elb.zone_id}"
    evaluate_target_health = true
  }
}
調査したところ、タイプ「A」のレコードは一件しか存在できないです。追加ではなく、もし古いレコードが存在していればそれを削除しておく必要があります。
解決方法はとても簡単です。
引数allow_overwrite = trueを追加すれば、もしレコードが存在している場合は上書きしてくれます。
変更後のソースコードは以下になります。
resource "aws_route53_record" "www" {
  zone_id = "Z1234txxxxx"
  name    = "test.com"
  type    = "A"
  allow_overwrite = true

  alias {
    name                   = "${aws_lb.elb.dns_name}"
    zone_id                = "${aws_lb.elb.zone_id}"
    evaluate_target_health = true
  }
}

2019年9月19日木曜日

gitのエラー「fatal: refusing to merge unrelated histories」の解消方法

 git push -u origin masterでソースコードをリモートにpushしようとしたら、以下のエラーがおきました。

$ git push -u origin master
To https://git.xxxx.com/test/xxx.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'https://git.xxxx.com/test/xxx.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.

hint: See the 'Note about fast-forwards' in 'git push --help' for details.

どうや先にpullしないとだめみたいです。$ git pull origin masterでpullをしたら、今度またエラーがおきました。
fatal: refusing to merge unrelated histories
解決方法は、オプション--allow-unrelated-historiesを追加することです。

以下で無事に解決できました。
$ git pull origin master --allow-unrelated-histories
From https://git.xxxx.com/test/xxx.git
 * branch            master     -> FETCH_HEAD
Merge made by the 'recursive' strategy.
 README.md | 2 ++

 1 file changed, 2 insertions(+)

aws cliでインターネットゲートウェイを削除するコマンド

一つのVPCの中、インターネットゲートウェイが一つしか作れないです。

自分が間違って2回作成コマンドを押してしまいました。そしたら以下のようにエラーが起きました。
* aws_internet_gateway.gw: error attaching EC2 Internet Gateway (igw-094efbee9f367a97a): Error attaching internet gateway: InvalidParameterValue: Network vpc-43332a1a already has an internet gateway attached
status code: 400, request id: befcb4ad-c9a6-4a08-9622-0686b048a69b



detached状態なインテーネットゲートウェイを削除するには、もちろんコンソール上からできますが、いちいちコンソールにログインするのは少し手間なので、コマンドで削除します。
コマンドは以下の通りになります。
$ aws ec2 delete-internet-gateway --internet-gateway-id igw-c0a643a8
おまけに、本操作ではなく事前動作検証をしたいなら、--dry-run をつければ動作可能かどうかをチェックしてくれます。

2019年9月18日水曜日

aws 失敗したNATゲートウェイを削除する方法

AWSのNATゲートウェイ作成に失敗すると、コンソールから削除できなくなります。

削除するにはaws cliからするしかないです。
削除するコマンドは以下の通りです。


aws ec2 delete-nat-gateway --nat-gateway-id nat-04ae55e711cec5680

2019年9月17日火曜日

Pythonでselenium 要素の存在を判定する方法

Seleniumで存在しない要素を使うと、Message: Unable to locate element:xxx のエラーが起きます。
事前に要素の存在をチェックしておきたいですね。

たまに以下のようなtryで例外処理をする方法をみかけますが、実はlenでも判定することはできます。

try:
    driver.find_element_by_id('test').click()
except:
  # 存在しない
ポイントはdriver.find_element_by_idの代わり、driver.find_elements_by_idを使います。一見同じように見えますが、前者の場合は要素が存在しない時に異常が発生します。後者なら、要素が存在しなくでも異常が発生しないです。
具体的に以下ように使います。

if len(driver.find_elements_by_id('test') > 0) :
    ele = driver.find_element_by_id('test')
 # 存在する時の処理
else:
  # 存在しない時の処理
driver.find_elements_by_idの他、driver.find_elements_by_namedriver.find_elements_by_xpathdriver.find_elements_by_class_namedriver.find_elements_by_css_selectordriver.find_elements_by_link_textdriver.find_elements_by_tag_nameなどなどが存在します。基本的にfind_element_by_xxとセットとなっています。

2019年9月13日金曜日

Golang言語でAWS SESを介してメールを送信する方法

Golangで開発したウェブアプリケーションからメール送信機能が必要になりました。インフラはAWS上にあるので、AWS SES(Simple Email Service)を使うことにしました。AWS SESサービスの開始から、Golangで送信までの手順をまとめてみました。

SESサービスを開始

AWSのSimple Email Serviceコンソール画面を開きます。
最初はリージョン選択になります。日本リージョンがないので、3つから任意の一つを選びます。

ドメイン認証

左メニュー「Domains」/「Verify a New Domain」順にドメイン認証画面を開きます。
自分のドメインを入力し、「Generate DKIM Settings」もチェックします。

確認画面の「Use Route 53」ボタンをクリックします。

Use Route 53画面の「Create Record Sets」ボタンをクリックします。
※一つ注意してほしいのは、もし「Email Receiving Record」にチェックを入れたら、MXタイプのレコードが全部上書きされることになります。回避するにはここでチェックを外して、Route 53の管理画面から手動でレコードを追加することです。

Route53の管理画面に、対象ドメインに先程のレコードが追加されたことを確認できます。
そのまましばらく待つと、認証ステータスが「verified」に変わります。

「FROM Domain」の設定

FROMドメインを設定しないと、メールの送信元はamazonses.comとなってしまいます。以下の手順で自分のドメインに変えられます。
「Domains」/「対象ドメイン名」/「MAIL FROM Domain」/「Set MAIL FROM Domain」の順にクリックします。
FROMドメインの設定画面に、MAIL FROMドメインの名前を入力します。例:info
そして、「Use amazonses.com as MAIL FROM」をチェックします。

次の画面に、「Publish Records Using Route 53」ボタンをクリックします。

更に次のUse Route 53画面に、「MX Record」と「SPF Record」にチェックを入れて、「Create Record Sets」ボタンをクリックします。

前のステップと同じくしばらく待つと、ステータスが「pending verification」から「verified」に変わります。

最後、サンドボックスの外への移動

サンドボックスから"脱出"するに、上限申請が必要です。
「Sending Statistics」/「Request a Sending Limit Increase」の順に申請画面に移動します。

申請する上限数のところに、自分の負荷に応じで必要な数値を入力します。
申請後1日、2日を待ってば処理されます。

ちなみに、申請が通りまでに、テストメールを送信すると、以下のエラーが起きます。

Email address is not verified. The following identities failed the check in region US-EAST-1: test@gmail.com (Request ID: 32301551-966e-462e-bdab-6a23ef58f6a4)


最後、Golangで送信する

まず、以下の4つのパッケージをインストール

  go get github.com/aws/aws-sdk-go/aws
  go get github.com/aws/aws-sdk-go/aws/credentials
  go get github.com/aws/aws-sdk-go/aws/session
  go get github.com/aws/aws-sdk-go/service/ses
次に、メールを送信(送信部分のソースコードのみ)
awsAccessKey := "awsのアクセスキー"
awsSecretKey := "awsのシークレットキー"
awsSession := session.New(&aws.Config{
Region:      aws.String("us-east-1"),
Credentials: credentials.NewStaticCredentials(awsAccessKey, awsSecretKey, ""),
})
client := ses.New(awsSession)
input := &ses.SendEmailInput{
Destination: &ses.Destination{
ToAddresses: []*string{
aws.String("送信先のメールアドレス"),
},
},
Message: &ses.Message{
Body: &ses.Body{
Text: &ses.Content{
Charset: aws.String("UTF-8"),
Data:    aws.String("メール本文"),
},
},
Subject: &ses.Content{
Charset: aws.String("UTF-8"),
Data:    aws.String("メール件名"),
},
},
Source: aws.String("送信元のメールアドレス"),
}
_, err := client.SendEmail(input)

Macのメモ帳が勝手に先頭文字を大文字に変換する問題

久々自宅用新しいMacを購入しました。
メモ帳を使ってメモを取ろうとしたら、入力した英単語が勝手に大文字に変換されてしいました。確かにデフォルトその仕様だったことを思い出しました。
その解消方法はとても簡単です。

システム環境設定...

左上のアップルアイコンから「システム環境設定...」画面を開きます。


キーボード/ユーザ辞書の順にクリックします。

デフォルトだと、「文字を自動的に大文字にする」にチェックを入れられています。そのチェックを外して、メモ帳を再起動すれば問題が解消できます。

sudoでコマンドを実行しようとしたら、sudo: sorry, you must have a tty to run sudo のエラーが発生しました。


centosでsudoコマンドを実行しようとしたら、以下のエラーがでました。
sudo: sorry, you must have a tty to run sudo

調査したところ、sudoコマンド実行する時にttyが必須と設定されています。

>less /etc/sudores
上記のコマンドでファイルを確認すると、以下の行が見つかるはずです。
Defaults    requiretty
その行をコマンドアウトすれば解決できますが、セキュアではないので、おすすめできません。

必要なユーザーのみ許可した方がいいので、必要なユーザーだけの設定方法は以下の通りになります。ユーザーhogehogeを例とします。
Defaults:hogehoge !requiretty

2019年9月4日水曜日

Terrafom入門編ー設定、及びEC2インスタンスを作成

作業用フォルダを作成

作成するフォルダ名はterraform_test1を例します。
$mkdir terraform_test1

AWSにアクセス用認証情報を設定

AWSコンソール画面でterraform用IAMユーザーを作成し、accessキーとsecretキーを控えておきます。

terraform.tfvars というファイルを作成、以下のようにAWSアクセスキーとシークレットキー情報を入れます。
PS:terraform.tfvars や、*.auto.fvars というファイル名にしておきば、自動的に変数を読み込んでくれます。
aws_access_key = "AKIXXXXXXXPNN6KXXXXXXX"
aws_secret_key = "6sGivXXXXXXXXXXXbyd1ssLXXXXXY"

EC2インスタンスを作ってみる

ec2.tfというファイルを作成します。中身は以下の通りです。
variable "aws_access_key" {}
variable "aws_secret_key" {}

provider "aws" {
    access_key = "${var.aws_access_key}"
    secret_key = "${var.aws_secret_key}"
    region = "ap-northeast-1"
}

resource "aws_instance" "example" {
  ami           = "ami-02757f631"
  instance_type = "t3.nano"
}
簡単に説明すると、AMIami-02757f631をベースにしてインスタンスタイプt3.nanoのEC2一台を作成します。アクセスキーとシークレットキーはterraform.tfvars に設定した値を使用します。

初期化

terraform init コマンドを使って初期化します。

$ terraform init
Initializing the backend...
Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "aws" (terraform-providers/aws) 2.25.0...
The following providers do not have any version constraints in configuration,
so the latest version was installed.
To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.
* provider.aws: version = "~> 2.25"
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

文法チェック

terraform plan コマンドを使って先程作成したec2.tfファイルの正しさをチェックします。
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
Terraform will perform the following actions:
  # aws_instance.example will be created
  + resource "aws_instance" "example" {
      + ami                          = "ami-031b61f0c1afb3454"
      + arn                          = (known after apply)
      + associate_public_ip_address  = (known after apply)
      + availability_zone            = (known after apply)
      + cpu_core_count               = (known after apply)
      + cpu_threads_per_core         = (known after apply)
      + get_password_data            = false
      + host_id                      = (known after apply)
      + id                           = (known after apply)
      + instance_state               = (known after apply)
      + instance_type                = "t3.nano"
      + ipv6_address_count           = (known after apply)
      + ipv6_addresses               = (known after apply)
      + key_name                     = (known after apply)
      + network_interface_id         = (known after apply)
      + password_data                = (known after apply)
      + placement_group              = (known after apply)
      + primary_network_interface_id = (known after apply)
      + private_dns                  = (known after apply)
      + private_ip                   = (known after apply)
      + public_dns                   = (known after apply)
      + public_ip                    = (known after apply)
      + security_groups              = (known after apply)
      + source_dest_check            = true
      + subnet_id                    = (known after apply)
      + tenancy                      = (known after apply)
      + volume_tags                  = (known after apply)
      + vpc_security_group_ids       = (known after apply)
      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }
      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }
      + network_interface {
          + delete_on_termination = (known after apply)
          + device_index          = (known after apply)
          + network_interface_id  = (known after apply)
        }
      + root_block_device {
          + delete_on_termination = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }
    }
Plan: 1 to add, 0 to change, 0 to destroy.
------------------------------------------------------------------------
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

インスタンスを作成

terraform apply コマンドを使ってインスタンを作成します。
$ terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
Terraform will perform the following actions:
  # aws_instance.example will be created
  + resource "aws_instance" "example" {
      + ami                          = "ami-031b61f0c1afb3454"
      + arn                          = (known after apply)
      + associate_public_ip_address  = (known after apply)
      + availability_zone            = (known after apply)
      + cpu_core_count               = (known after apply)
      + cpu_threads_per_core         = (known after apply)
      + get_password_data            = false
      + host_id                      = (known after apply)
      + id                           = (known after apply)
      + instance_state               = (known after apply)
      + instance_type                = "t3.nano"
      + ipv6_address_count           = (known after apply)
      + ipv6_addresses               = (known after apply)
      + key_name                     = (known after apply)
      + network_interface_id         = (known after apply)
      + password_data                = (known after apply)
      + placement_group              = (known after apply)
      + primary_network_interface_id = (known after apply)
      + private_dns                  = (known after apply)
      + private_ip                   = (known after apply)
      + public_dns                   = (known after apply)
      + public_ip                    = (known after apply)
      + security_groups              = (known after apply)
      + source_dest_check            = true
      + subnet_id                    = (known after apply)
      + tenancy                      = (known after apply)
      + volume_tags                  = (known after apply)
      + vpc_security_group_ids       = (known after apply)
      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }
      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }
      + network_interface {
          + delete_on_termination = (known after apply)
          + device_index          = (known after apply)
          + network_interface_id  = (known after apply)
        }
      + root_block_device {
          + delete_on_termination = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }
    }
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.
  Enter a value: yes
aws_instance.example: Creating...
aws_instance.example: Still creating... [10s elapsed]
aws_instance.example: Creation complete after 16s [id=i-054c4a5d5f65d7633]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

作成したインスタンを確認

terraform show コマンドを使ってインスタンを確認します。

$ terraform show
# aws_instance.example:
resource "aws_instance" "example" {
    ami                          = "ami-031b61f0c1afb3454"
    arn                          = "arn:aws:ec2:ap-northeast-1:994787028884:instance/i-054c4a5d5f65d7633"
    associate_public_ip_address  = true
    availability_zone            = "ap-northeast-1a"
    cpu_core_count               = 1
    cpu_threads_per_core         = 2
    disable_api_termination      = false
    ebs_optimized                = false
    get_password_data            = false
    id                           = "i-054c4a5d5f65d7633"
    instance_state               = "running"
    instance_type                = "t3.nano"
    ipv6_address_count           = 0
    ipv6_addresses               = []
    monitoring                   = false
    primary_network_interface_id = "eni-068a1099ebe134ed4"
    private_dns                  = "ip-172-31-45-252.ap-northeast-1.compute.internal"
    private_ip                   = "172.31.45.252"
    public_dns                   = "ec2-13-231-108-188.ap-northeast-1.compute.amazonaws.com"
    public_ip                    = "13.231.108.188"
    security_groups              = [
        "default",
    ]
    source_dest_check            = true
    subnet_id                    = "subnet-8a04efc2"
    tenancy                      = "default"
    volume_tags                  = {}
    vpc_security_group_ids       = [
        "sg-3b359644",
    ]
    credit_specification {
        cpu_credits = "unlimited"
    }
    root_block_device {
        delete_on_termination = true
        encrypted             = false
        iops                  = 300
        volume_id             = "vol-03eedb71c41a89002"
        volume_size           = 100
        volume_type           = "gp2"
    }
}