AWS API Gateway(3)カスタムログの出力


API Gatewayは、詳細のアクセスログをCloudWatch Logsに吐き出すことができる。CloudWatch Logsへのログ書き込みを行うためには、書き込み権限の取得とログを書き込むロググループの指定が必要となる。

IAMロールの指定

IAM上でAPI GatewayからCloudWatch Logsへの書き込み許可を持つIAMロールを作成する。IAMでは、あらかじめAmazonAPIGatewayPushToCloudWatchLogsと呼ばれるポリシーが用意されているため、このポリシーがアタッチされたIAMロールを作成する。この作成したIAMロールをAPI Gatewayの設定画面上で指定することで、API GatewayはCloudWatch Logsへの書き込み権限を取得する。

ログの指定

次にAPI Gateway上の各APIのログ/トレース設定画面にて、カスタムアクセスのログ記録を有効化する。入力項目は、CloudWatchロググループのARNと、ログ形式の2種類。ログ形式は、JSONやCLFなどの中から選ぶと自動的に入力される。

AWS API Gateway(2)Kinesisへのデータ投入

API Gatewayから大量のデータを投入し、これらのデータを解析および蓄積する場合には、API GatewayからLambdaに直接データを渡すのではなく、大規模データストリームサービスのKinesisを介した方が、バックエンドのシステムが高負荷に晒されずに安定的に稼働させられる場合がある。

API Gatewayとバックエンドのエンドポイントとの接続は、API Gateway内の統合リクエスト機能を用いて行い、統合リクエストは下の5つの統合タイプを用意している。

  • Lambda関数
  • HTTP
  • Mock
  • AWSサービス
  • VPCリンク

Mockは、バックエンドと接続せずにレスポンスを返す統合タイプで、テストを行う際や、CROSのプリフライトリクエストの返答などに用いる。

統合リクエスト

Kinesisと接続する場合は、POSTメソッドを作成し、上記のうちの「AWSサービス」を選択して以下のように各欄に必要事項を入力する。Kinesisへデータ投入する際には、Kinesis側で用意されているputRecordメソッドを使用する。

データ入力項目

項目 入力内容 備考
統合タイプ AWSサービス  
AWS リージョン 当該Kinesisのリージョン  
AWS サービス Kinesis  
AWS サブドメイン 空欄  
HTTP メソッド POST  
アクション PutRecord  
実行ロール KinesisへのputRecordをAPI Gatewayに許可するIAMロール arn:aws:iam::account-id:role/iam-role-name

IAMロールについては、KinesisへのputRecordをAPI Gatewayに許可する記述が必要で、IAM上で以下の内容を含んだIAMロールを作成する。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "kinesis:PutRecord",
                "kinesis:PutRecords"
            ],
            "Resource": "arn:aws:kinesis:*:*:stream/*"
        }
    ]
}

データマッピング

API GatewayからKinesisにデータを投入する場合は、クライアントから受信したデータをKinesisが規定するデータフォマットに変換する必要がある。これに対応するのがデータマッピング機能で、Velocity Template Languageを用いて記述することができる。

よく使われる関数および使用例を以下に挙げる。

記述 内容
#set($param = ”) 変数の定義
#if(評価式) #end if文
$context.requestTimeEpoch データの受信時刻
$input.path(‘$.param’) 入力データ内の指定タグの値
$input.path(‘$.param’).size 入力データ内の指定タグの数
$input.params().header.get(”) ヘッダ内の指定タグの値
$input.json(‘$.param’) 入力データ内の指定タグJSONデータ
$util.urlDecode($input.path(‘$’)) 入力データをURLデコード
$util.escapeJavaScript(data) 文字をエスケープ
$util.base64Encode(data) 文字をBASE64エンコード

また、これらを使用してデータマッピングを記述すると以下となる。

#set($allParams = $input.params())
{
  "params" : {
    #foreach($type in $allParams.keySet())
    #set($params = $allParams.get($type))
    "$type" : {
      #foreach($paramName in $params.keySet())
      "$paramName" : "$util.escapeJavaScript($params.get($paramName))"
      #if($foreach.hasNext),#end
      #end
    }
    #if($foreach.hasNext),#end
    #end
  }
}

AWS API Gateway(1)API Gatewayの概要

API Gatewayとは

API Gatewayは、完全マネージドのAPI作成サービス。受信したAPIコールと送出したデータ量に対して課金される。スロットリングによるトラフィック管理ができるため、DDoSやトラフィックの激増にも対応することが可能であり、リミットを超えたリクエストにはHTTPステータス 429が返却される。また、レスポンスはキャッシュ可能であり、レイテンシやトラフィック等を低減することができる。

API Gatewayは、IAMやCognitoを用いたアクセス認証署名付きAPIコールなどを使用することができるために柔軟にセキュリティ管理ができる。また、CloudWatchやCloudWatch Logsを用いた監視が可能で効率的なデバッグとモニタリングを実現している。

![API Gateway]https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/images/BackplaneArch.png

エンドポイント

API Gatewayは、特定のリージョンにデプロイされる。エンドポイントは以下の3種類がサポートされている。エンドポイントは、HTTPSのみサポートされている。

種類 内容
エッジ最適化 CloudFrontネットワークにデプロイ
リージョン リージョンにデプロイ。EC2 インスタンスまたは API と同じリージョン内のサービスから送られる場合に使用すると良い。
プライベート VPCからのみアクセス可能

リソースとメソッド

APIは階層構造となっており、リソースやメソッドをネストすることも可能。指定可能なメソッドは以下の通り。

種類 実行内容
POST 子リリースの作成
PUT 既存リソースの更新
DELETE リソースの削除
PATCH リソースの更新
HEAD テストシナリオに使用
OPTIONS 通信オプションに関する情報を取得する度に使用できる

CROSを有効にするためには、OPTIONSメソッドのプリフライトリクエストに対してAPIが応答することが必要であり、このリクエストに対して、HTTPステータス 200Access-Control-Allow-Method, Access-Control-Allow-Headers, Access-Control-Max-Ageヘッダを含んだレスポンスを返す。これらの挙動には、統合リクエスト/レスポンスのMockタイプを使用する。

リクエストに対して、 URLクエリ文字列パラメータHTTPヘッダHTTPボディを検証し、必須の項目が含まれているかやキャッシュを行うかなどを指定することができる。HTTPボディがapplication/json形式である場合は、JSON Schemaを用いてJSON形式を指定することもできる。

統合リクエスト/レスポンスとマッピングテンプレート

API Gatewayとバックエンドとを接続する内部インタフェース。マッピングテンプレートを用いることで、フロントエンド(API Gateway)とバックエンドのデータ形式を変換することができる。

  • Lambda関数の呼び出し
  • 他のAWSサービスの呼び出し
  • HTTPウェブサイトのアクセス

の3つのバックエンドへのアクセスに対応している。Lambdaプロキシ統合を用いることで、API GatewayとLambdaがより協力に結合され、リクエストヘッダやパス変数などがLambdaに渡される。また、HTTPプロキシとして使用することも可能である。

デプロイ

APIを利用可能とするためには、APIのリソースおよびメソッドのスナップショットであるAPIのデプロイを実施する必要がある。APIをバージョン管理できるために、新しいバージョンを簡単にテストしリリースすることが可能である。

1アカウント1リージョンあたりのAPIの上限は、10000RPSである。これ以上のアクセス負荷にも耐えうる値とする場合は上限緩和申請が必要となる。

エラーコード

API Gateway の代表的なレスポンスコードは以下の通り。

エラーコード レスポンスタイプ 内容
400 BAD_REQUEST_PARAMETERS リクエストパラメータの不整合
400 BAD_REQUEST_BODY リクエストボディの不整合
401 UNAUTHORIZED 認証の失敗
403 EXPIRED_TOKEN トークンの期限切れ
403 ACCESS_DENIED 認証の失敗
403 INVALID_API_KEY APIキーの不整合
403 INVALID_SIGNATURE 署名の不整合
403 MISSING_AUTHENTICATION_TOKEN トークンが見つからない
403 WAF_FILTERED WAFによるブロック
404 RESOURCE_NOT_FOUND リクエスト先が存在しない
413 REQUEST_TOO_LARGE リクエストが大きすぎる
415 UNSUPPORTED_MEDIA_TYPE メディアタイプの相違
429 QUOTA_EXCEEDED クオータの超過
429 THROTTLED スロットルの発生
500 API_CONFIGURATION_ERROR API 設定が無効
500 AUTHORIZER_CONFIGURATION_ERROR オーソライザーへの接続が失敗
500 AUTHORIZER_FAILURE オーソライザーの認証が失敗
504 INTEGRATION_FAILURE 統合に失敗
504 INTEGRATION_TIMEOUT 統合のタイムアウト

Ansible(5)パッケージ管理関連モジュール

Ansible

yum_repository

YUMリポジトリの追加削除を行う。

変数 デフォルト 内容 備考
name 必須 レポジトリ名  
description   詳細内容  
baseurl   ベースURL  
gpgkey   GPG KEYのURL  
gpgcheck システムに依存 GPGチェックをするかどうか  
enabled yes 有効化するかどうか  

Example

- name: Add repository
  yum_repository:
    name: epel
    description: EPEL YUM repo
    enabled: no
    baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
    gpgkey: http://download.fedoraproject.org/pub/fedora/epel/RPM-GPG-KEY-EPEL-7
    gpgcheck: yes

yum

YUMによるパッケージのインストールや更新、削除を行う。

変数 デフォルト 内容 備考
name   パッケージ名 全てを選択する場合は*
enablerepo   有効化するリポジトリ名  
security   no セキュリティ関連の更新のみインストール
state   実行内容 absent, installed, latest, present, removed

Example

- name: ensure a list of packages installed
  yum:
    name: "{{ packages }}"
    enablerepo: epel
  vars:
    packages:
    - httpd
    - httpd-tools

- name: upgrade all packages about security
  yum:
    name: '*'
    state: latest
    security: yes

Ansible(4)コマンド実行モジュール

Ansible

command

コマンドを実行する。

変数 デフォルト 内容 備考
  必須 実行するコマンド  
chdir   実行する前に移動するディレクトリ  

Example

- name: return motd to registered var
  command: cat /etc/motd
  register: mymotd

debug

コマンド実行内容を表示する。

変数 デフォルト 内容 備考
var   表示する変数  

Example

- debug:
    var: result
    verbosity: 2

expect

コマンドを実行しプロンプトに応答する。

変数 デフォルト 内容 備考
command 必須 実行するコマンド  
chdir   実行する前に移動するディレクトリ  
responses   プロンプトへの応答 正規表現にて規定する

Example

- name: Case insensitive password string match
  expect:
    command: passwd username
    responses:
      (?i)password: "MySekretPa$$word"
  # you don't want to show passwords in your logs
  no_log: true

make

Makeファイルを実行する

変数 デフォルト 内容 備考
chdir 必須 実行する前に移動するディレクトリ  
target   ターゲット install, all

Example

# Run `install` target as root
- make:
    chdir: /home/ubuntu/cool-project
    target: install
  become: yes

service

サービスの管理を行う。

変数 デフォルト 内容 備考
name 必須 サービス名  
state   実行内容 reloaded, restarted, started, stopped
enabled   ブート時に起動するかどうか  

Example

- name: Enable service httpd, and not touch the state
  service:
    name: httpd
    enabled: yes

shell

コマンドを実行する。
ワイルドカードを指定する場合はcommandモジュールではなくshellコマンドを使用する

変数 デフォルト 内容 備考
  必須 実行するコマンド  
chdir   実行する前に移動するディレクトリ  

 

Ansible(3)システム管理モジュール

Ansible

cron

cronの設定を行う。

変数 デフォルト 内容 備考
name   cron名  
job   実行コマンド  
minute *  
hour *  
day *  
month *  
month *  
state present 実行内容 absent, present

Example

- name: Ensure a job that runs at 2 and 5 exists. Creates an entry like "0 5,2 * * ls -alh > /dev/null"
  cron:
    name: "check dirs"
    minute: "0"
    hour: "5,2"
    job: "ls -alh > /dev/null"

group

グループを管理する。

変数 デフォルト 内容 備考
name 必須 グループ名  
state present 実行内容 absent, present

Example

- name: Ensure group "somegroup" exists
  group:
    name: somegroup
    state: present

lvol

LVMボリュームを作成する。

変数 デフォルト 内容 備考
vg   ボリュームグループ名  
lv   論理ボリューム名  
size   ボリュームサイズ  
state present 実行内容 absent, present

Example

- name: Create a logical volume of 512m
  lvol:
    vg: firefly
    lv: test
    size: 512

mount

ファイルシステムをマウントする。

変数 デフォルト 内容 備考
path 必須 マウントポイント  
state 必須 実行内容 absent, mounted, present, unmounted
src   マウントパス  
fstype   ファイルシステム  

selinux

SELinuxのポリシーを変更する。

変数 デフォルト 内容 備考
state None 実行内容 enforcing, permissive, disabled

Example

# Enable SELinux
- selinux:
    policy: targeted
    state: enforcing

sysctl

sysctl.confを管理する。

変数 デフォルト 内容 備考
name 必須 キー  
value    
state present 実行内容 absent, present

Example

# Set vm.swappiness to 5 in /etc/sysctl.conf
- sysctl:
    name: vm.swappiness
    value: 5
    state: present

user

ユーザを管理する。

変数 デフォルト 内容 備考
name 必須 ユーザ名  
password   パスワード  
groups   グループ名  
shell   シェル  
createhome yes ホームディレクトリを作るかどうか  
home   ホームディレクトリ  

Example

- name: Add the user 'johnd' with a specific uid and a primary group of 'admin'
  user:
    name: johnd
    comment: John Doe
    uid: 1040
    group: admin

timezone

タイムゾーンを設定する。

変数 デフォルト 内容 備考
name   タイムゾーン  

Example

- name: set timezone to Asia/Tokyo
  timezone:
    name: Asia/Tokyo

Ansible(2)ファイル関連モジュール

Ansible

blockinfile

ファイル内にテキストブロックを追加/削除する。

変数 デフォルト 内容 備考
path 必須 ファイルパス  
block   挿入するテキストブロック  
insertafter EOF 何の後にテキストブロックを追加するか  
insertbefoer   何の前にテキストブロックを追加するか  
marker # {mark} ANSIBLE MANAGED BLOCK テキストブロック前後に挿入されるマーカー  
backup no バックアップファイルを作成するかどうか  
owner   所有者  
group   グループ  
mode   ファイルパーミッション  
state present 実行内容 absent, present

Example

- name: Add mappings to /etc/hosts
  blockinfile:
    path: /etc/hosts
    block: |
      {{ item.ip }} {{ item.name }}
    marker: "# {mark} ANSIBLE MANAGED BLOCK {{ item.name }}"
  with_items:
    - { name: host1, ip: 10.10.1.10 }
    - { name: host2, ip: 10.10.1.11 }
    - { name: host3, ip: 10.10.1.12 }

copy

リモートサーバへファイルをコピーする。

変数 デフォルト 内容 備考
src   コピー元のファイルパス  
remote_src no コピー元のファイルパスがリモートサーバのパスであるかどうか  
backup no バックアップファイルを作成するかどうか  
owner   所有者  
group   グループ  
mode   ファイルパーミッション  

Example

- name: example copying file with owner and permissions
  copy:
    src: /srv/myfiles/foo.conf
    dest: /etc/foo.conf
    owner: foo
    group: foo
    mode: 0644

file

ファイル属性を変更する。

変数 デフォルト 内容 備考
path   コピー元のファイルパス  
owner   所有者  
group   グループ  
mode   ファイルパーミッション  
state file ファイルの状態 absent, directory, file, hard, link, touch

Example

# change file ownership, group and mode
- file:
    path: /etc/foo.conf
    owner: foo
    group: foo
    # when specifying mode using octal numbers, add a leading 0
    mode: 0644

get_url

ファイルのダウンロードを行う。

変数 デフォルト 内容 備考
url 必須 ファイルのURL  
dest 必須 ダウンロードしたファイルを設置するディレクトリの絶対パス  
timeout 10 タイムアウト  
force no 既にファイルが存在していたとしても毎回ダウンロードを行うかどうか  
insertbefoer   何の前にテキストブロックを追加するか  
backup no バックアップファイルを作成するかどうか  
owner   所有者  
group   グループ  
mode   ファイルパーミッション  

Example

- name: Download foo.conf
  get_url:
    url: http://example.com/path/file.conf
    dest: /etc/foo.conf
    mode: 0440

git

gitプロジェクトをデプロイする。

変数 デフォルト 内容 備考
dest 必須 gitプロジェクトのチェックアウト先  
repo 必須 gitリポジトリ  

Example

# Example git checkout from Ansible Playbooks
- git:
    repo: 'https://foosball.example.org/path/to/repo.git'
    dest: /srv/checkout
    version: release-0.22

lineinfile

ファイル内にテキスト行を追加/削除する。

変数 デフォルト 内容 備考
path 必須 ファイルパス  
line   挿入するテキスト  
insertafter EOF 何の後にテキストブロックを追加するか  
insertbefoer   何の前にテキストブロックを追加するか  
backup no バックアップファイルを作成するかどうか  
owner   所有者  
group   グループ  
mode   ファイルパーミッション  
state present 実行内容 absent, present

Example

# Before 2.3, option 'dest', 'destfile' or 'name' was used instead of 'path'
- lineinfile:
    path: /etc/selinux/config
    regexp: '^SELINUX='
    line: 'SELINUX=enforcing'

replace

特定の文字列を置換する。

変数 デフォルト 内容 備考
path 必須 ファイル名  
regexp 必須 対象文字列の正規表現  
replace   変換後の文字列  
backup no バックアップファイルを作成するかどうか  
owner   所有者  
group   グループ  
mode   ファイルパーミッション  

Example

- replace:
    path: /etc/hosts
    regexp: '(\s+)old\.host\.name(\s+.*)?$'
    replace: '\1new.host.name\2'
    backup: yes

template

テンプレートファイルをリモートサーバに設置する。

変数 デフォルト 内容 備考
src 必須 Playbook上のテンプレートファイルの名前  
dest 必須 リモートサーバ上のパス  
backup no バックアップファイルを作成するかどうか  
owner   所有者  
group   グループ  
mode   ファイルパーミッション  

Example

- template:
    src: /mytemplates/foo.j2
    dest: /etc/file.conf
    owner: bin
    group: wheel
    mode: 0644

unarchive

アーカイブを展開する。

変数 デフォルト 内容 備考
src 必須 展開するアーカイブのパス  
remote_src no 展開するアーカイブがリモートサーバにあるかどうか  
dest 必須 リモートサーバ上のパス  
owner   所有者  
group   グループ  
mode   ファイルパーミッション  

Example

- name: Unarchive a file that is already on the remote machine
  unarchive:
    src: /tmp/foo.zip
    dest: /usr/local/bin
    remote_src: yes

Ansible(1)Ansibleの概要

Ansible

Ansibleとは

Ansibleは、インフラストラクチャを自動構成可能(Infrastructure as Code)な構成管理ツールで、作業の省人化と効率化によるコスト削減やコード化による高度な品質保証を実現することができる。

Ansibleは、操作対象マシンにエージェントアプリケーションをインストールすることが不要(エージェントレス)であることが特徴で、SSHでログインできる端末であれば操作可能となるので、エージェントアプリケーションをインストールすることができないネットワーク機器なども、Ansibleの操作対象とすることができる。

Inventory

操作対象となるマシンへの接続情報を記したファイル。API経由でマシンへの接続情報を収集してInventory情報を自動生成するDinamic Inventryという機能を使用することもできる。INI形式もしくはYAML形式で記述できる。グループを定義して[グループ名 vars]でグループごとの変数を定義することができる。

変数名 内容
ansible_user SSHでログインするユーザ
ansible_ssh_pass SSHでログインする際のパスワード
ansible_ssh_private_key_file SSHでログインする際の秘密鍵
ansible_become root権限で実行する

Playbook

site.ymlとして定義されるマスタープレイブック。実行するプレイを順に羅列する。

変数名 内容 備考
name
hosts
remote_user
vars_files
roles
environment

Module

Ansibleで実行するコマンド。YAMLで記述する。変更が生じるときのみ実行され、ある操作を何度事項しても常に同じ結果となる冪等性を担保している。