Elastic BeanStalkの環境別のタグ付を忘れたときにどうすんの?って話

1年ぐらい前からBeanStalk使ってます。
なんつうのか、この辺のAWSのマネージドサービスっていうの?ってほんとすごいですよね。
インフラエンジニアなんか必要なくなりますよね。
AWSの機能をガリガリ使って一昔前の3-tier systemなんて、ネットワークの知識もインフラ系のIeasの知識もなくアプリ屋さんがポチポチやってればいつでも復元できるシステム!が出来上がっちゃうんですもんね。
しかもはやりのECSつかったDockerコンテナの仕組みもつかって・・・
「あ〜〜Dockerとか最近ちゃってもう最近開発とか楽でさ〜〜、インフラ屋?いるの?仕事おせえよあいつら」とかほざけるわけです。

俺なんか無職まっしぐらです。

Beanstalkってなんぞや?

さて、まぁ今更ですがBeanStalkってなんぞやって人に簡単に説明しておきますと、
要は初見殺しとも言えるAWSの「CloudFomartion」を”比較的”わかりやすいUIで設定できるというマネージメントシステムです。
基本はネットワーク層+3tier+インスタンススケーリング何かをある程度コントロールしてくれます
更にアプリケーションのデプロイはソースをまとめておくとECR上にコンテナイメージとして作成してくれたり、そこまで必要ない人でもPHP用のAMIを使ってちょっとPHPで動作させたいコンテンツを作ってデプロイしてみたいな事ができます。
この辺、コンソールでポチポチやってると、たしかに時間的にそれなりのリソースを取られますしで開発したアプリケーションのバージョン管理もソレナリにしてくれるので何度も言いますがとても便利なサービスだと思っています。

BeanStalkのアレなところ

こんなに便利そうなBeanStalkなんですが、サーバサイド(アプリケーション開発者)にはなり針を振り気味なサービスなので、少しでも込み入ったことを始めるととたんに出来ないことが出てきます。
そこで、「.ebextentions」というファイルを作ってアプリ層のレポジトリに拡張設定をおいて設定を入れたりする訳です。
まぁ、デフォルトで設定されるCloudFormationの設定項目をアプリ層に置くようにするわけで、インフラ屋のいない会社なんかだと違和感ないというかとても理にかなっているようにみえるんですが、タスクをサーバサイド・インフラサイドと別けているチームなんかだと

インフラ屋がアプリ屋に土下座をしてネットワーク設定なんかを開発アプリレポジトリに入れてもらう

なんていう状態が発生してしまい、なんとなく自分の存在意義を感じられなくなってきたりもします。

そこで、インフラ屋さんは「EBとかつかってらんねぇよ、せめてCloudFormationでやろうぜ・・・(JSON書きたくないけど)」とか言い始めるわけです。

あ、個人的にはterraformに逃げましたw

本題の環境ごとのタグの調べ方について

なんか、閑話休題のボリュームがいつもまとまらず多めになってしまう訳ですが
本当に書きたかったEBで作った環境に対してのタグの後付とかに関してです。

EBで環境を作るとEBにおけるタグを設定しておけば、そのアプリケーションで起動したEC2インスタンスなどには一応Nameタグがついてくれてどの環境かわかりやすくなるのですが、SecurityGroup・ELB/ALBなどには最初にタグを付け忘れたりすると、どの環境で使っているSG・LBなのかを探すのが非常に困難になります。

具体的には例えばSecurityGroupなんかだと下記のようなタグが付くことになります
– awseb-a-3xxxxx2xxxx-stack-AWSEBSecurityGroup-HOGEFUGE1HOGE

まぁ訳わんないですよね。SGに関してはまだNameのタグを設定しておけば自分で任意に環境名をつけられますが
ELBとかだとName=「ユニークな文字列:DNS名」になっているのでAWSのコンソールやawscliコマンドの返り値だけでは一見どの環境用セット用の機材なのかが全くわからない状態になってしまっています。

また、タグ自体も起動段階で設定していないと、環境をすべてEB的に再構築しない限り(つまり環境内のすべてを捨ててもう一度構築し直す処理)を入れないと追加したNameタグなどは設定されない状況に陥ります。

これをあとでチクチクと手作業で入れることになるんですが、
– awseb-a-3xxxxx2xxxx-stack-AWSEBSecurityGroup-HOGEFUGE1HOGE

この文字列はEBの中身を見ているだけだと判別がつかない物なのです。
なぜか
この文字列自体がCloudformationで作られている物だからですwww。
なのでこのELBがどのEBアプリケーションで使われているのか?というのを調べるためには

  • まず、上記の文字列のうち、「awseb-a-3xxxxx2xxxx-stack」までの部分を抜き出し
  • CloudFormationのスタック一覧のFilterをその文字列に入れ
  • 説明欄にちゃんと記載されている「AWS Elastic Beanstalk environment (Name: ‘hogefuge-app’)」を確認するという作業が必要になります。

まぁ調べる方法がある分マシですがね・・・この辺もうデフォルトでNameダグとしてすべての環境に入れてしまってもいいと思うんですけどね

以上、ちょっとしたボヤキでした。
ちなみに、サーバサイドの方の「構築の手間が楽になるからEB使うことを強く推したい」という要望であるプロジェクトでEB使いましたがもう本サービス運用では二度と使いたくありません・・・・

続きを読む

AWS Powershell で MFA必須のAssumeRoleを使う

いまどき、AssumeRoleにMFA必須は当然ですよね。
awscliがMFA対応しているのは有名ですが、AWS PowershellもMFA対応していました。

プロファイルを保存してデフォルト設定します。

Set-AWSCredential -StoreAs Default -AccessKey <アクセスキー> -SecretKey <シークレットキー>
Set-AWSCredential -StoreAs AdminRole -SourceProfile Default -RoleArn <RoleARN> -MfaSerial <MFASerial>
Initialize-AWSDefaultConfiguration -ProfileName AdminRole -Region ap-northeast-1

この状態で Get-EC2Instance とか実行するとMFA Codeを求められるので入力してください。
保存したプロファイルは毎回入力する必要はありません。
プロファイル名やリージョンは好きなものを指定してください。
アクセスキー、シークレットキー、RoleARN、MFASerialはIAMから指定された値です。
有効期間(1時間?)を過ぎるか、プロセス終了まで有効です。
子プロセスには引き継がれるようですが、兄弟プロセスには引き継がれないようです。
VSCodeの統合シェルでもOKでした。

ただし、PowerShell ISEだとMFA Codeを入力する間もなくエラーになりました。
試行錯誤したところ、下記のようにすれば大丈夫なようです。

$targetrole = Get-AWSCredential -ProfileName AdminRole
$role = Use-STSRole -RoleArn $targetrole.RoleArn -RoleSessionName $targetrole.RoleSessionName -ProfileName Default -SerialNumber $targetrole.Options.MfaSerialNumber -TokenCode (Read-Host "MFA Code")
Get-EC2Instance -Credential $role.Credentials

取得したクレデンシャルをデフォルト指定する方法をご存知の方は教えてください。

続きを読む

バンドルされたインストーラを使用してインストールした AWS CLI をアンインストールする

結論

バンドルされたインストーラ (Linux, macOS, or Unix) を使用して AWS CLI をインストールする – AWS Command Line Interface

バンドルされたインストーラでは、オプションのシンボリックリンク以外は、インストールディレクトリの外に何も置きません。そのため、アンインストールはこの 2 つの項目を削除するだけでシンプルです。

$ sudo rm -rf /usr/local/aws
$ sudo rm /usr/local/bin/aws

背景

久しぶりにawsコマンドを使おうと思ったらエラーが出ました。

~ aws --version
Traceback (most recent call last):
  File "/usr/local/bin/aws", line 15, in <module>
    import awscli.clidriver
  File "/usr/local/aws/lib/python2.7/site-packages/awscli/clidriver.py", line 31, in <module>
    from awscli.help import ProviderHelpCommand
  File "/usr/local/aws/lib/python2.7/site-packages/awscli/help.py", line 20, in <module>
    from docutils.core import publish_string
  File "/usr/local/aws/lib/python2.7/site-packages/docutils/core.py", line 20, in <module>
    from docutils import frontend, io, utils, readers, writers
  File "/usr/local/aws/lib/python2.7/site-packages/docutils/frontend.py", line 41, in <module>
    import docutils.utils
  File "/usr/local/aws/lib/python2.7/site-packages/docutils/utils/__init__.py", line 20, in <module>
    import docutils.io
  File "/usr/local/aws/lib/python2.7/site-packages/docutils/io.py", line 18, in <module>
    from docutils.utils.error_reporting import locale_encoding, ErrorString, ErrorOutput
  File "/usr/local/aws/lib/python2.7/site-packages/docutils/utils/error_reporting.py", line 47, in <module>
    locale_encoding = locale.getlocale()[1] or locale.getdefaultlocale()[1]
  File "/usr/local/aws/lib/python2.7/locale.py", line 543, in getdefaultlocale
    return _parse_localename(localename)
  File "/usr/local/aws/lib/python2.7/locale.py", line 475, in _parse_localename
    raise ValueError, 'unknown locale: %s' % localename
ValueError: unknown locale: UTF-8

macOS で AWS Command Line Interface をインストールする – AWS Command Line Interface の手順でpip installする前に古いバージョンをアンインストールしたかったです。
方法をメモします。

続きを読む

CloudFrontキャッシュを削除するシェルスクリプトを書いてみた。

AWS CLI を使えば、 AWS Console へアクセスすることなく
CloudFrontキャッシュの削除も行えます。

削除対象が多い場合はその対象を記したjsonファイルを用意して、
AWS CLI からそのjsonファイルを利用して CloudFrontキャッシュ の削除を行うのですが、
毎回書き換えが必要な項目がjsonファイル内にあります。

手作業で毎回書き換えてましたがさすがに面倒になってきたので
シェルスクリプトを書きました。

Macユーザーなので Macでの作業想定で書きます。

概要

AWS Consoleアクセスすれば、
Cloud Frontのキャッシュ手動削除はできるのですが、
面倒なので AWS CLI を使ってシェルスクリプトから
削除できるようにしたものです。

必要な準備

AWS CLI のローカルインストール

詳しいインストール手順はこちら

macOSの場合は Python 2.6.3 以降が必要なので

$ curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
$ sudo python get-pip.py

で pip をインストールしてから

$ sudo pip install awscli

して

$ aws help

でヘルプが出ればOKです。

AWS CLI の設定

CLI利用するのに専用の configure 設定を一度行う必要があります。
これも上記URLに設定方法があるのですが、

  • AWS Access Key ID(以下 AKID)
  • AWS Secret Access Key(以下 SAK)
  • region name
  • output format

の4つが必要です。
この設定プロファイルは

~/.aws/credentials # AKID と SAK

~/.aws/config # region name と output format

に入ります。

プロファイル名を付ければ複数のプロファイルを格納できます。
この2ファイルは1回設定しちゃえばあとはいじらなくてOKです!

↓こんな感じ

~/.aws/credentials
[profile hogehoge]
aws_access_key_id=****************      # AKID
aws_secret_access_key=****************  # SAK
~/.aws/config
[profile hogehoge]
region=ap-northeast-1                   # region name
output=json                             # output format

invalidation-batch の準備

削除対象を指定するバッチファイル(json)を作成します。
↓こんな感じです。

invbatch.json
{
    "Paths"  : {
        "Quantity": 5,
        "Items"  : [
            "/",
            "/sp/",
            "/css/main.css",
            "/js/libs.js",
            "/js/main.js"
        ]
    },
    "CallerReference": "YYYYMMDD-HHNNSS"
}

Itemsに削除対象を DocumentRoot からのパスで指定します。
ワイルドカード()も使えます。
この指定方法は **AWS Console
* での指定方法と一緒です。

注意点

CallerReference は毎回ユニークな値を入れておかなければいけません。
これが意外と面倒なのでこの部分の書き換え込みでシェルスクリプト化しました。

Note:
削除対象が変われば ItemsQuantity も変えなきゃです、、

このファイルは削除対象の変更がなければ、1回設定しちゃえばあとはいじらなくてOKです!

キャッシュ削除用シェルスクリプト設定

シェルスクリプトに実行権限$ chmod a+x ***を与えておいて、実行します。
中身は↓こんな感じです。

clear_cache.sh
#!/bin/bash

# 設定用変数
dist_id="*******************"   # AWS CloudFrontのDistribution ID
batch_json="invbatch.json"      # nvalidation-batchファイル名
profile="hogehoge"              # プロファイル名
url="http://hogehoge.jp"        # サイトURL

# 実行部分
echo "Move directory ..."
cd `dirname $0`
echo "Invbalidation-batch json update"
echo `less $batch_json_base | jq '.CallerReference |= "'$profile'_'$time_stamp'"'` > $batch_json
echo "CloudFront cache clear ..."
echo `aws cloudfront create-invalidation --distribution-id $dist_id --invalidation-batch "file://$batch_json" --profile $profile`

※ jq使ってjsonの書き換えを行なっているのでjqのインストールが必要です。

jqのインストール方法
https://stedolan.github.io/jq/download/

コード内のコメントにありますが、

  • AWSのCloudFrontDistribution ID
  • nvalidation-batch ファイル名
  • プロファイル名
  • サイトURL

が必要です。

このファイルは1回設定しちゃえばあとはいじらなくてOKです!

キャッシュ削除シェルスクリプト実行

$ ./clear_cache_shupure.sh
Move directory ...
Invbalidation-batch json update
CloudFront cache clear ...
{ "Invalidation": { "Status": "InProgress", "InvalidationBatch": { "Paths": { "Items": [ "/images/girls/*.png", "/", "/images/sakabar/*.png", "/images/events/*.jpg", "/sp/gekijo/", "/sp/sakabar/", "/gekijo/", "/sp/", "/images/girls/0924.png", "/css/main.css", "/sakabar/" ], "Quantity": 11 }, "CallerReference": "shupure_1506515279" }, "Id": "I2N11BY0PH6UI9", "CreateTime": "2017-09-27T12:28:03.125Z" }, "Location": "https://cloudfront.amazonaws.com/2017-03-25/distribution/E1JZGHRP8PFLBD/invalidation/I2N11BY0PH6UI9" }
CURL check ...
 % Total  % Received % Xferd Average Speed  Time  Time   Time Current
                 Dload Upload  Total  Spent  Left Speed
 0 50672  0   0  0   0   0   0 --:--:-- --:--:-- --:--:--   0
 X-Amz-Cf-Id: eHRIZxCp2k5-aecSw1ABCI-OB7aPtK_EEs4y0elK8bucqB6e1B-zrA==

CloudFront キャッシュ削除のレスポンスjsonが改行されてないのが気持ち悪いですが、
InProgressが表示されていればキャッシュ削除スタートしてます。

キャッシュ削除されてるかはcurlなどでレスポンスヘッダを確認してください。

$ curl -I http://hogehoge.jp

続きを読む

フロントエンド環境+CircleCI+AWS環境構築メモ

0.やること

  • WebpackベースでReact&Redux環境を構築する
  • GitHubにプッシュしたらCircleCIが自動テストを行い、S3に用意した検証環境にデプロイ
  • テスト結果をSlackに通知する

準備物

  • AWSのIAMユーザー情報
  • S3バケット
  • GitHubアカウント(BitBacketでもOK)

1.React&Redux&Webpack

ベースとなる環境はreact-redux-starter-kitを利用しました。公式が提供しているcreate-react-appと迷いましたが、Reduxとreact-routerが設定済みということもありreact-redux-starter-kitを選択しました。

react-redux-starter-kitはreact-routerのバージョンが3系なので、開発の様子を見てアップデートしていく必要がありそうです。

Node.jsは推奨版が6系でしたが、8系でも特に問題なく動作したのとNode.jsはあっという間ににバージョンアップされるのでNodeは最新版を選択しました。

$ node -v
v8.4.0
$ npm -v
5.4.2

react-redux-starter-kitでプロジェクト作成
$ git clone https://github.com/davezuko/react-redux-starter-kit.git <PROJECT_NAME>
$ cd <PROJECT_NAME>
$ npm start

http://localhost:3000/ にアクセスしてアヒルの画像が表示されたら環境構築成功です。

webpack-dev-serverが起動しているので、ソースの変更、保存を検知して自動でリロードしてくれます。ディレクトリの構成はAtomicDesignで構成したいので実際の開発ではかなり触ります。

[参考資料]

React + ReduxのプロジェクトにAtomic DesignとImmutable.jsを使ったらいい感じになった話

アメブロ2016 ~ React/ReduxでつくるIsomorphic web app ~

2.GitHubへのプッシュを検知してCircleCIが自動テストと検証環境へのデプロイを行う

CrcleCIとGitHubを接続

CircleCIとGitHubを連携します。CircleCIの公式から「Start Building Free」→「Start With GitHub」の順に進みます。GitHubのアカウントでログインした後「Project」ページの「Add Project」をクリックします。GitHubでログインしている場合はのリポジトリをが自動的に読み込んでくれるので、利用するリポジトリを選択します。Setup Projectの設定はそのままで「StartBuilding」をクリックして完了です。

CircleCIとAWSを接続

ソースコードをAWSのS3にデプロイするので、CircleCIとAWSを連携させます。「Project」→「Setting」→「AWS Permissions」に進んでAccessKeyIdとSecretAccessKeyを入力して完了です。

circle.ymlを作成

CircleCIで行いたいことはcircle.ymlに書きます。今回はESLintの構文チェック結果とKarmaのテスト結果をTestSummaryにレポートを表示させます。

circle.yml
machine:
  node:
    version: 8.4.0
  post:
    - npm install -g npm@5
  timezone: Asia/Tokyo

dependencies:
  pre:
    - sudo pip install awscli

test:
  override:
    - ./node_modules/.bin/eslint --format=junit -o $CIRCLE_TEST_REPORTS/eslint/report.xml .
    - cross-env NODE_ENV=test karma start build/karma.config --reporters junit

deployment:
  branch: master
  commands:
    - npm run build
    - cp -Rf dist/. ./
    - aws s3 cp dist s3://<S3_BACKET_NAME>/ --recursive --acl public-read

circle.ymlの記述方法

machine:

仮想マシンの設定を記述します。デフォルトでもNodeをインストールしてくれますが、バージョンが0系だったのでフロントの環境に合わせて8系をインストールするように設定しました。postは指定したコマンドの後に実行されます。この例ではNodeをインストールした後にnpmのバージョンを上げています。逆に指定したコマンドの前に行いたい処理はpreに記述します。

dependencies:

プロジェクト固有の依存関係をインストールします。今回はaws-cliを利用するのでここでインストールしました。

test:

ここで実際のテストが走ります。package.jsonのtestを自動的に実行してくれるのですが、今回はjunitのxmlを出力してCircleCI上でレポートが見たいのでoverrideを記述してpackage.jsonのtestを上書きました。

deployment:

Webサーバにコードを展開します。今回はシングルページアプリケーションで、ビルドされたソースは静的なので、AWSのS3を選択しました。ここでリポジトリ上のソースをそのまま展開できればいいのですが、webpackでReactをビルドする必要があるので、package.jsonにか書かれているnpm run buildを走らせます。その後生成されたdistフォルダをコンテナのルートに移動させてからaws-cliのコマンドでS3にアップロードしています。branch: masterはmasterブランチにプッシュされた場合のみ実行する記述です。

[参考資料]
Configuring CircleCI

AWS S3にデプロイ

作成したバケットにStatic website hostingを有効します。
※検証環境で利用するのにBasic認証が必要でした。S3にBasic認証をかけるのには一手間必要なので今後CodeDeployを利用してEC2にデプロイしたいと思っています。

Slackと接続

通知したいSlackのWorkspaceのURLを用意します。「Project」→「Setting」から「ChatNotification」に進み、SlackのURLを入力して「Save」します。

これで準備はOKです。

3.動作チェック

適当にソースを変更してmasterブランチにプッシュします。今はmaterに直接プッシュしていますが、開発ではタスクごとのブランチにプッシュしてテストが通ったらmasterやreleaseブランチにプルリクエストを飛ばしてmaterブランチにマージ、プッシュされたらS3に展開という運用を考えています。今回はテストが成功しようが失敗しようが問答無用にS3に展開されます。

circle.ymlに書かれたプロセスが順に実行されています

task1.png

4.結果

TestSummaryに出力

task3.png

Reactがビルドされてサーバに展開

スクリーンショット 2017-09-29 22.15.29.png

Slackへの通知

スクリーンショット 2017-09-29 22.16.36.png

感想

  • CIツールそのものの環境構築を意識せず導入できるので取っ付き易い
  • 基本的な設定はpackage.jsonのscriptとcircle.ymlの記述だけで済むので設定が簡単
  • 黒画面でできる事は大体実現できる

CircleCIは出来ることが多いので、この環境をベースに試行錯誤しながらベストプラクティスを見つけたい思います:v_tone2:

続きを読む

ansibleでCloudWatch Logsを導入する

ログをいい感じに管理したいよねーってことでawsのCloudWatch Logsを導入することになったのでまとめました。

ansibleなんぞやって人は、以前に調べたのでこちらをどうぞ
ansibleで疎通確認とplaybookの実行

やろうとしていること

CloudWatch Logsのクイックスタートに記載されている内容をansibleを使って実行できるようにします。

ansibleを使わないでやるとこんな感じですかね。

1. awslogs パッケージをインストール
[ec2-user ~]$ sudo yum install -y awslogs

2. 追跡するログを設定

3. awslogs サービスを開始
[ec2-user ~]$ sudo service awslogs start

4. システム起動時に毎回 awslogs サービスを起動する設定
[ec2-user ~]$ sudo chkconfig awslogs on

ansibleで書いていく

全体的な構成

site.ymlが実行するファイルで、rolesにcloudwatch-logs用ディレクトリを作成して、site.ymlから呼び出します。

.
└── ansible
    ├── roles
    │   └── cloudwatch-logs
    │       ├── tasks
    │       │   └── main.yml
    │       └── templates
    │           ├── awscli.conf.j2
    │           └── awslogs.conf.j2
    │   
    └── site.yml

各ファイル

site.yml

site.ymlが実際に実行をするファイルです。

こちらではcloudwatch-logsをincludeして利用しています。
なんとなく書いていたのですが、becomeはroot権限で実行する場合にyesにします。

/ansible/site.yml
---
- hosts: all
  vars:
  remote_user: ec2-user
  become: yes

  roles:
    - { role: cloudwatch-logs }

main.yml

こちらがcloudwatch-logsのタスクを定義しているメインのファイルです。
冒頭のやろうとしていることに書いたansibleを使わないでやる場合のコマンドの代わりに
こちらを実行するイメージを持ってもらえれば良いと思います。

どのログファイルを管理するかなどの設定は、別ファイルを作成してそれを読み込みます。

start agentの部分で起動させ、enabled=yesを指定することで、再起動させた時に自動で起動させるようにします。

/ansible/roles/cloudwatch-logs/tasks/main.yml
---
- name: install awslogs
  yum: name=awslogs state=latest disable_gpg_check=yes

- name: copy conf files
  template: src={{ item }}.j2 owner=root dest=/etc/awslogs/{{ item }}
  with_items:
        - awscli.conf
        - awslogs.conf

- name: start agent
  service: name=awslogs state=started enabled=yes state=started

awscli.conf.j2

regionは使っているところに合わせてもらえれば良いかと。

/ansible/roles/cloudwatch-logs/tmplates/awscli.conf.j2
[plugins]
cwlogs = cwlogs

[default]
region = ap-northeast-1

awslogs.conf.j2

このファイルでどのファイルをCloudWatch Logs側に送るのか、ログの名前はどうするのかということを指定します。
今回は/var/log/httpdディレクトリにあるアクセスログとエラーログを全てCloudWatch Logsに送ります。
それぞれaccess_logerror_logというロググループを作成して、その中にhostnameごとに管理していきます。

/ansible/roles/cloudwatch-logs/tmplates/awslogs.conf.j2
[general]
state_file = /var/lib/awslogs/agent-state

[/var/log/httpd/access_log]
datetime_format = %b %d %H:%M:%S
buffer_duration = 5000
log_stream_name = {hostname}.access_log
initial_position = start_of_file
file = /var/log/httpd/access_log.*
log_group_name = access_log

[/var/log/httpd/error_log]
datetime_format = %b %d %H:%M:%S
buffer_duration = 5000
log_stream_name = {hostname}.httpd_error_log
initial_position = start_of_file
file = /var/log/httpd/error_log.*
log_group_name = error_log

dry-run

準備ができたのでdry-runで確認します。
1つfailedがありますが、こちらはawslogsをstartさせようとしたけどinstallされてないからできないということですね。
(dry-runなので実際にはinstallが行われていません。)

 $ ansible-playbook site.yml -i hosts -C

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [127.0.0.1]

TASK [cloudwatch-logs : install awslogs] ***************************************
changed: [127.0.0.1]

TASK [cloudwatch-logs : copy conf files] ***************************************
changed: [127.0.0.1] => (item=awscli.conf)
changed: [127.0.0.1] => (item=awslogs.conf)

TASK [cloudwatch-logs : start agent] *******************************************
fatal: [127.0.0.1]: FAILED! => {"changed": false, "failed": true, "msg": "no service or tool found for: awslogs"}
  to retry, use: --limit @/Users/username/workspace/aws/aws/ansible/site.retry

PLAY RECAP *********************************************************************
127.0.0.1              : ok=3    changed=3    unreachable=0    failed=1


ansibleの実行

丁寧にやるならinstall前後の処理で分けて実行すれば、dry-runでOKのtaskだけをサーバに反映できると思います。
が、失敗しても問題はない環境なのでそのまま実行します。できた。

$ ansible-playbook site.yml -i hosts         

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [127.0.0.1]

TASK [cloudwatch-logs : install awslogs] ***************************************
changed: [127.0.0.1]

TASK [cloudwatch-logs : copy conf files] ***************************************
changed: [127.0.0.1] => (item=awscli.conf)
changed: [127.0.0.1] => (item=awslogs.conf)

TASK [cloudwatch-logs : start agent] *******************************************
changed: [127.0.0.1]

TASK [Set hostname.] ***********************************************************
ok: [127.0.0.1]

PLAY RECAP *********************************************************************
127.0.0.1              : ok=5    changed=4    unreachable=0    failed=0

気をつけること

・ログデータをどのように管理するのかを考えて構成を考える
・実際にコンソール画面を見てみる
・権限周りで詰まったらクイックスタート + IAM Policy Simulatorで確認

参考

http://dev.classmethod.jp/cloud/ansible-cloudwatch-logs-play-framework/
http://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/QuickStartEC2Instance.htm

続きを読む

AWS CloudWatch で、Amazon Linux のパフォーマンスとログの監視をしてみる

0.はじめに

Amazon Linuxを利用していますが、
パフォーマンス監視は Zabbix を使って、
ログ監視は特に何も、
という感じでした。

CloudWatch のメトリクスの保存期間も長くなったみたいですし、
運用の手間やリスク、コスト削減も考慮して、
パフォーマンス監視を CloudWatch、
ログ監視を CloudWatch Logs、
にしようかと思います。

1.IAM Role へのポリシーのアタッチ

  1. 以下の IAM ポリシーを作成します。

    • ポリシー名 : GSCloudWatchWriteOnlyAccess ※ 任意
    • 説明 : ※ 任意
    • ポリシードキュメント :
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "Stmt1459146265000",
                "Effect": "Allow",
                "Action": [
                    "cloudwatch:PutMetricData"
                ],
                "Resource": [
                    "*"
                ]
            },
            {
                "Sid": "Stmt1459146665000",
                "Effect": "Allow",
                "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                ],
                "Resource": [
                    "arn:aws:logs:*:*:*"
                ]
            }
        ]
    }
    

  2. 作成したポリシーを EC2 インスタンスに割り当てられている IAM Role に付与します。

1.CloudWatch へのメトリクスデータの送信

  1. 色々調べたところ、collectd と その CloudWatch 用プラグインを利用するのが一般的みたいなので、今回はその手順で進めていきます。

  2. collectd をインストールします。

    $ sudo yum -y install collectd
    

  3. collectd の CloudWatch 用プラグインをインストールします。

    $ git clone https://github.com/awslabs/collectd-cloudwatch.git
    $ cd collectd-cloudwatch/src
    $ sudo ./setup.py
    
    Installing dependencies ... OK
    Installing python dependencies ... OK
    Downloading plugin ... OK
    Extracting plugin ... OK
    Moving to collectd plugins directory ... OK
    Copying CloudWatch plugin include file ... OK
    
    Choose AWS region for published metrics:
      1. Automatic [ap-northeast-1]
      2. Custom
    Enter choice [1]: 
    
    Choose hostname for published metrics:
      1. EC2 instance id [i-00484bb5ac67e244d]
      2. Custom
    Enter choice [1]: 
    
    Choose authentication method:
      1. IAM Role [testuekamawindowsserver]
      2. IAM User
    Enter choice [1]: 
    
    Enter proxy server name:
      1. None
      2. Custom
    Enter choice [1]: 
    
    Enter proxy server port:
      1. None
      2. Custom
    Enter choice [1]: 
    
    Include the Auto-Scaling Group name as a metric dimension:
      1. No
      2. Yes
    Enter choice [1]: 
    
    Include the FixedDimension as a metric dimension:
      1. No
      2. Yes
    Enter choice [1]: 
    
    Enable high resolution:
      1. Yes
      2. No
    Enter choice [2]: 
    
    Enter flush internal:
      1. Default 60s
      2. Custom
    Enter choice [1]: 
    
    Choose how to install CloudWatch plugin in collectd:
      1. Do not modify existing collectd configuration
      2. Add plugin to the existing configuration
      3. Use CloudWatch recommended configuration (4 metrics)
    Enter choice [3]: 
    Plugin configuration written successfully.
    Creating backup of the original configuration ... OK
    Replacing collectd configuration ... OK
    Replacing whitelist configuration ... OK
    Stopping collectd process ... NOT OK
    Starting collectd process ... NOT OK
    Installation cancelled due to an error.
    Executed command: '/usr/sbin/collectd'.
    Error output: 'Error: Reading the config file failed!
    Read the syslog for details.'.
    

  4. collectd の起動に失敗しています。collectd の python 用ライブラリが足りないみたいなので、インストールします。

    $ sudo yum -y install collectd-python
    

  5. collectd を起動します。

    $ sudo service collectd start
    

  6. collectd の自動起動の設定をします。

    $ sudo chkconfig collectd on
    $ sudo chkconfig --list | grep collectd
    
    collectd           0:off    1:off    2:on    3:on    4:on    5:on    6:off
    

  7. /etc/collectd.conf の設定を変更します。

    $ sudo cp -frp /etc/collectd.conf /etc/collectd.conf.ORG
    $ sudo vi /etc/collectd.conf
    
    • cpu :

      • LoadPlugin cpu をコメント解除し、以下の設定を行う。
      <Plugin cpu>
              ReportByCpu false
              ReportByState true
              ValuesPercentage true
      </Plugin>
      
    • df :

      • LoadPlugin df をコメント解除し、以下の設定を行う。
      <Plugin df>
      #       Device "/dev/hda1" 
      #       Device "192.168.0.2:/mnt/nfs" 
      #       MountPoint "/home" 
      #       FSType "ext3" 
      #       IgnoreSelected false
              ReportByDevice false
              ReportInodes false
              ValuesAbsolute true
              ValuesPercentage true
      </Plugin>
      
    • load :

      • LoadPlugin load をコメント解除し、以下の設定を行う。
      <Plugin load>
              ReportRelative true
      </Plugin>
      
    • memory :

      • LoadPlugin memory をコメント解除し、以下の設定を行う。
      <Plugin memory>
              ValuesAbsolute true
              ValuesPercentage true
      </Plugin>
      
    • swap :

      • LoadPlugin swap をコメント解除し、以下の設定を行う。
      <Plugin swap>
              ReportByDevice false
              ReportBytes false
              ValuesAbsolute false
              ValuesPercentage true
      </Plugin>
      

  8. /opt/collectd-plugins/cloudwatch/config/whitelist.conf の設定を変更します。以下のメトリクスの中で不要なものがあれば、適当に削除して下さい。

    $ cd /opt/collectd-plugins/cloudwatch/config/
    $ sudo cp -frp whitelist.conf whitelist.conf.ORG
    $ sudo vi whitelist.conf
    
    cpu-.*
    df-root-df_complex-free
    df-root-df_complex-reserved
    df-root-df_complex-used
    df-root-percent_bytes-free
    df-root-percent_bytes-reserved
    df-root-percent_bytes-used
    load--load-relative
    memory--percent-free
    memory--percent-used
    memory--memory-free
    memory--memory-used
    swap--percent-cached
    swap--percent-free
    swap--percent-used
    

  9. collectd を再起動します。

    $ sudo service collectd restart
    

  10. CloudWatch のマネジメントコンソールの左側ペインから、「メトリクス」を選択します。カスタム名前空間の「collectd」→「Host, PluginInstance」→ EC2 インスタンスの ID でフィルタをかけて、設定したメトリクスのデータがあるか確認します。

    • FireShot Capture 165 - CloudWatch Management Console_ - https___ap-northeast-1.console.aws.png

    • FireShot Capture 166 - CloudWatch Management Console_ - https___ap-northeast-1.console.aws.png

    • FireShot Capture 171 - CloudWatch Management Console_ - https___ap-northeast-1.console.aws.png

2.CloudWatch Logs へのログデータの送信

  1. awslogs をインストールします。

    $ sudo yum -y install awslogs
    

  2. /etc/awslogs/awscli.conf の設定を変更します。

    $ sudo cp -frp /etc/awslogs/awscli.conf /etc/awslogs/awscli.conf.ORG
    $ sudo vi /etc/awslogs/awscli.conf
    
    [plugins]
    cwlogs = cwlogs
    [default]
    region = ap-northeast-1
    

  3. /etc/awslogs/awslogs.conf の設定を変更します。

    • apache や nginx の設定もしています。不要であれば、削除して下さい。
    $ sudo cp -frp /etc/awslogs/awslogs.conf /etc/awslogs/awslogs.conf.ORG
    $ sudo vi /etc/awslogs/awslogs.conf
    
    [/var/log/messages]
    datetime_format = %b %d %H:%M:%S
    file = /var/log/messages
    buffer_duration = 5000
    log_stream_name = {instance_id}
    initial_position = start_of_file
    log_group_name = AmazonLinux/var/log/messages
    
    [/var/log/cron]
    datetime_format = %b %d %H:%M:%S
    file = /var/log/cron
    buffer_duration = 5000
    log_stream_name = {instance_id}
    initial_position = start_of_file
    log_group_name = AmazonLinux/var/log/cron
    
    [/etc/httpd/logs/access_log]
    datetime_format = [%a %b %d %H:%M:%S %Y]
    file = /etc/httpd/logs/access_log
    buffer_duration = 5000
    log_stream_name = {instance_id}
    initial_position = start_of_file
    log_group_name = AmazonLinux/etc/httpd/logs/access_log
    
    [/etc/httpd/logs/error_log]
    datetime_format = [%a %b %d %H:%M:%S %Y]
    file = /etc/httpd/logs/error_log
    buffer_duration = 5000
    log_stream_name = {instance_id}
    initial_position = start_of_file
    log_group_name = AmazonLinux/etc/httpd/logs/error_log
    
    [/etc/httpd/logs/ssl_access_log]
    datetime_format = [%a %b %d %H:%M:%S %Y]
    file = /etc/httpd/logs/ssl_access_log
    buffer_duration = 5000
    log_stream_name = {instance_id}
    initial_position = start_of_file
    log_group_name = AmazonLinux/etc/httpd/logs/ssl_access_log
    
    [/etc/httpd/logs/ssl_error_log]
    datetime_format = [%a %b %d %H:%M:%S %Y]
    file = /etc/httpd/logs/ssl_error_log
    buffer_duration = 5000
    log_stream_name = {instance_id}
    initial_position = start_of_file
    log_group_name = AmazonLinux/etc/httpd/logs/ssl_error_log
    
    [/etc/httpd/logs/ssl_request_log]
    datetime_format = [%a %b %d %H:%M:%S %Y]
    file = /etc/httpd/logs/ssl_request_log
    buffer_duration = 5000
    log_stream_name = {instance_id}
    initial_position = start_of_file
    log_group_name = AmazonLinux/etc/httpd/logs/ssl_request_log
    
    [/var/log/nginx/access.log]
    datetime_format = %Y/%m/%d %H:%M:%S
    file = /var/log/nginx/access.log
    buffer_duration = 5000
    log_stream_name = {instance_id}
    initial_position = start_of_file
    log_group_name = AmazonLinux/var/log/nginx/access.log
    
    [/var/log/nginx/backend.access.log]
    datetime_format = %Y/%m/%d %H:%M:%S
    file = /var/log/nginx/access.log
    buffer_duration = 5000
    log_stream_name = {instance_id}
    initial_position = start_of_file
    log_group_name = AmazonLinux/var/log/nginx/backend.access.log
    
    [/var/log/nginx/badactor.log]
    datetime_format = %Y/%m/%d %H:%M:%S
    file = /var/log/nginx/badactor.log
    buffer_duration = 5000
    log_stream_name = {instance_id}
    initial_position = start_of_file
    log_group_name = AmazonLinux/var/log/nginx/badactor.log
    
    [/var/log/nginx/error.log]
    datetime_format = %Y/%m/%d %H:%M:%S
    file = /var/log/nginx/error.log
    buffer_duration = 5000
    log_stream_name = {instance_id}
    initial_position = start_of_file
    log_group_name = AmazonLinux/var/log/nginx/error.log
    

  4. awslogs を起動します。

    $ sudo service awslogs start
    

  5. awslogs の自動起動の設定をします。

    $ sudo chkconfig awslogs on
    $ sudo chkconfig --list | grep awslogs
    
    awslogs            0:off    1:off    2:on    3:on    4:on    5:on    6:off
    

99.ハマりポイント

  • 今回は、凡ミスばかりで本当に自分が嫌になりました…。もう、毎回、何やってんだ…。

  • CloudWatch へのメトリクスデータの送信では、 CloudWatch のカスタム名前空間の「collectd」ではなく、AWS の EC2 のフィルタに表示されると勘違いして、全然ログが出てこないと悩んでいました…。もう、本当馬鹿…。
  • 後、/etc/collectd.conf の設定も結構悩みました。
  • CloudWatch Logs へのログデータの送信では、/etc/awslogs/awscli.conf の設定を /etc/awslogs/awslogs.conf にすると勘違いして、本当に無駄な時間を浪費しました…。

XX.まとめ

以下、参考にさせて頂いたサイトです。
ありがとうございました。

続きを読む

EC2(Amazon Linux)のWebLogicでログを管理する

このシリーズの流れ。

EC2のEBSに出力されたログをCloudWatch Logsから見る。

管理するログを決める

以下を参考にさせてもらいました。
WebLogic Serverを基礎から学ぶシリーズ第3弾 入門!WebLogic Serverの運用監視

これらのログを管理することに決定。

  • サーバーログ
  • ドメインログ
  • コンソールログ
  • GCログ
  • HTTPアクセスログ
  • アプリケーションログ

CloudWatch Logsの設定

出力されたログをCloudWatch Logsに送信するため、まずはAWSのドキュメント1に従ってEC2インスタンスへCloudWatch Logsエージェントをインストールする。ログは管理サーバーにも管理対象サーバーにも出力されるので両方へインストールを行う。

1. IAMロールをEC2インスタンスにアタッチ

EC2インスタンスにCloudWatch Logsへのアクセスを委任。

  1. IAMロールを作成
  2. 作成したロールへ、CloudWatch Logsの操作を許可するカスタムポリシーを追加
  3. EC2インスタンスへロールを割り当て

2. CloudWatch Logs エージェントをインストール

$ sudo yum update -y
$ sudo yum install -y awslogs

$ sudo sed 's/^region = .*/region = ap-northeast-1/' /etc/awslogs/awscli.conf > ~/awscli.conf.tmp
$ sudo chown root:root ~/awscli.conf.tmp
$ sudo chmod 600 ~/awscli.conf.tmp
$ sudo mv ~/awscli.conf.tmp /etc/awslogs/awscli.conf

IAMロールをアタッチしているので認証情報の設定は不要。ただ東京リージョンのCloudWatch Logsへ送信したかったのでそこだけは設定。

3. awslogsサービスを開始

初期設定で/var/log/messagesを送信するようになっているので、まずはどんな感じか体験してみる。

$ sudo service awslogs start

開始後、CloudWatchコンソールを見ると…「CloudWatch > ロググループ > /var/log/messages > [インスタンスID]」にログ出てるー:v::v::v:

4. 追跡するログの設定

ポイントになるのは対象ログの場所、名前、タイムスタンプのフォーマット。
管理すると決めたログについて上記を確認し設定していく。

サーバーログ

WebLogicサーバーのイベントが記録される。起動とか停止とかアプリケーションのデプロイとか。管理サーバーと管理対象サーバーの両方に存在する。

まずはファイルパス、ファイル名、およびタイムスタンプのフォーマットを確認。

すべて管理コンソールから確認できる。ドメイン構造から「環境 → サーバー → [サーバー名]」と選択し「ロギング」タブの「一般」タブにて。(タイムスタンプのフォーマットは実際のログを見た方が早いかな)

確認できたのでCloudWatch Logs エージェントの設定ファイルへ追跡したいログの情報を記述する。以下のようになった。(管理サーバーでの例)

/etc/awslogs/awslogs.conf
[serverlog]
log_group_name = ServerLog
log_stream_name = leo1(管理サーバー)
datetime_format = ####<%b %d, %Y %I:%M:%S %p %Z>
file = /home/oracle/user_projects/domains/zodiac/servers/leo1/logs/leo1.log
multi_line_start_pattern = {datetime_format}

awslogsサービスを再起動して設定を反映。

$ sudo service awslogs restart

ドメインログ

ドメイン全体のステータスを確認できるログ。各サーバーログの特定ログレベル以上のメッセージが記録される。管理サーバーにのみ存在。

まずはファイルパス、ファイル名、およびタイムスタンプのフォーマットを確認。

すべて管理コンソールから確認できる。ドメイン構造からドメイン名を選択し、「構成」タブの「ロギング」にて。

確認できたのでCloudWatch Logs エージェントの設定ファイルへ追跡したいログの情報を記述する。以下のようになった。

/etc/awslogs/awslogs.conf
[domainlog]
log_group_name = DomainLog
log_stream_name = zodiac
datetime_format = ####<%b %d, %Y %I:%M:%S %p %Z>
file = /home/oracle/user_projects/domains/zodiac/servers/leo1/logs/zodiac.log
multi_line_start_pattern = {datetime_format}

awslogsサービスを再起動して設定を反映。

$ sudo service awslogs restart

コンソールログ

標準出力、標準エラー出力のログ。管理サーバーと管理対象サーバーの両方で取得する。

まずはファイルパス、ファイル名を確認、というか設定する。WebLogicの起動スクリプトに変数名「WLS_REDIRECT_LOG」で出力ファイル名を記述できるが、今回は余すことなく取得できるようスクリプト実行時にリダイレクト先を指定する方向で設定。

管理サーバーの場合:

$ nohup /home/oracle/user_projects/domains/zodiac/startWebLogic.sh 1>/home/oracle/user_projects/domains/zodiac/servers/leo1/logs/console.log.`date +%Y%m%d%H%M%S`.$$ 2>&1 &

管理対象サーバーの場合:

$ nohup /home/oracle/user_projects/domains/zodiac/bin/startManagedWebLogic.sh leo2 t3://leo1.example.com:7001 1>/home/oracle/user_projects/domains/zodiac/servers/leo2/logs/console.log.`date +%Y%m%d%H%M%S`.$$ 2>&1 &

続いてタイムスタンプのフォーマット確認、だけど雑多な内容が出ると思われるので設定しようがない感。というわけでCloudWatch Logs エージェントの設定ファイルは以下のような記述になった。(管理サーバーでの例)

/etc/awslogs/awslogs.conf
[consolelog]
log_group_name = ConsoleLog
log_stream_name = leo1(管理サーバー)
file = /home/oracle/user_projects/domains/zodiac/servers/leo1/logs/console.log.*

awslogsサービスを再起動して設定を反映。

$ sudo service awslogs restart

ちなみにログローテーションについては、出力そんなにないだろうし内容の確認はCloudWatchコンソールから行うので今回はしなくていいんじゃないかなーって。:hamburger:

GCログ

ガベージコレクションのログ。アプリケーションがデプロイされる管理対象サーバーでのみ取得。

まずはファイルパス、ファイル名を確認、というか設定する。管理対象サーバーの起動スクリプトへGC関連のフラグを設定。

/home/oracle/user_projects/domains/zodiac/bin/startManagedWebLogic.sh
# JAVA_OPTIONS環境変数を定義する直前にGC関連のフラグを設定
JAVA_OPTIONS="-XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/var/log/logdemo/gc.log.%t -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=20M ${JAVA_OPTIONS}"

export JAVA_OPTIONS

設定したフラグは以下。

フラグ 意味
-XX:+PrintGC GCの基本的なログを出力する
-XX:+PrintGCDetails GCに関する詳細なログを記録する
-XX:+PrintGCDateStamps GCのログの各エントリで実際の日付を出力する
-Xloggc:[パス] GCのログを標準出力から別のファイルへリダイレクトする
-XX:+UseGCLogFileRotation GCのログのローテーションを行う
-XX:NumberOfGCLogFiles=[N] ログローテーションで保持するログファイルの数を指定する
-XX:GCLogFileSize=[N] ログファイルのサイズを指定する

タイムスタンプのフォーマットは実際の出力を見て確認。

2017-09-19T15:26:42.257+0900: 9.422: [Full GC (Metadata GC Threshold) 2017-09-19T15:26:42.257+0900: 9.422: [Tenured: 26081K->40434K(174784K), 0.1071922 secs] 94961K->40434K(253504K), [Metaspace: 58287K->58287K(1101824K)], 0.1072718 secs] [Times: user=0.10 sys=0.01, real=0.11 secs]
2017-09-19T15:26:43.770+0900: 10.934: [GC (Allocation Failure) 2017-09-19T15:26:43.770+0900: 10.934: [DefNew: 70016K->8704K(78720K), 0.0263706 secs] 110450K->50187K(253504K), 0.0264394 secs] [Times: user=0.03 sys=0.00, real=0.02 secs]
2017-09-19T15:26:45.177+0900: 12.342: [GC (Allocation Failure) 2017-09-19T15:26:45.177+0900: 12.342: [DefNew: 78720K->8704K(78720K), 0.0265826 secs] 120203K->58992K(253504K), 0.0266508 secs] [Times: user=0.02 sys=0.01, real=0.03 secs]
2017-09-19T15:26:45.673+0900: 12.837: [GC (Allocation Failure) 2017-09-19T15:26:45.673+0900: 12.837: [DefNew: 78720K->221K(78720K), 0.0097785 secs] 129008K->54214K(253504K), 0.0098368 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
2017-09-19T15:26:47.298+0900: 14.462: [GC (Allocation Failure) 2017-09-19T15:26:47.298+0900: 14.463: [DefNew: 70237K->7929K(78720K), 0.0133497 secs] 124230K->61922K(253504K), 0.0134268 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]

確認できたのでCloudWatch Logs エージェントの設定ファイルへ追跡したいログの情報を記述する。以下のようになった。

/etc/awslogs/awslogs.conf
[gclog]
log_group_name = GCLog
log_stream_name = leo2
datetime_format = %Y-%m-%dT%H:%M:%S.%f%z
file = /var/log/logdemo/gc.log.*
multi_line_start_pattern = {datetime_format}

awslogsサービスを再起動して設定を反映。

$ sudo service awslogs restart

GCログはCloudWatchコンソールからS3へ出力して別途ツールで眺める感じになるんじゃないかなー。

HTTPアクセスログ

その名の通りアクセスログ。アプリケーションがデプロイされる管理対象サーバーでのみ取得。

まずはファイルパス、ファイル名、およびタイムスタンプのフォーマットを確認。

すべて管理コンソールから確認できる。ドメイン構造から「環境 → サーバー → [サーバー名]」と選択し「ロギング」タブの「HTTP」タブにて。

確認できたのでCloudWatch Logs エージェントの設定ファイルへ追跡したいログの情報を記述する。以下のようになった。

/etc/awslogs/awslogs.conf
[accesslog]
log_group_name = AccessLog
log_stream_name = leo2
datetime_format = [%d/%b/%Y:%H:%M:%S %z]
file = /home/oracle/user_projects/domains/zodiac/servers/leo2/logs/access.log
multi_line_start_pattern = {datetime_format}

awslogsサービスを再起動して設定を反映。

$ sudo service awslogs restart

アプリケーションログ

log4j2を利用してログを出力。

ファイルパス、ファイル名、およびタイムスタンプのフォーマットは設定ファイルから確認。

src/main/resources/log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="off">
    <Properties>
        <Property name="loglayout">[%d{yyyy-MM-dd HH:mm:ss.SSS}] %-5p %t %c %m%n</Property>
    </Properties>
    <Appenders>
        <Console name="stdout" target="SYSTEM_OUT">
            <PatternLayout pattern="${loglayout}" />
        </Console>
        <RollingFile name="app" fileName="/var/log/logdemo/app.log" filePattern="/var/log/logdemo/app-%d{yyyy-MM-dd}-%i.log.gz">
            <PatternLayout pattern="${loglayout}" />
            <Policies>
                <OnStartupTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="20 MB" />
                <TimeBasedTriggeringPolicy />
            </Policies>
            <DefaultRolloverStrategy max="10" />
        </RollingFile>
    </Appenders>
    <Loggers>
        <Root level="debug">
            <AppenderRef ref="stdout" />
        </Root>
        <Logger name="com.mycompany" level="info" additivity="false">
            <AppenderRef ref="app" />
        </Logger>
    </Loggers>
</Configuration >

確認できたのでCloudWatch Logs エージェントの設定ファイルへ追跡したいログの情報を記述する。以下のようになった。

/etc/awslogs/awslogs.conf
[applicationlog]
log_group_name = ApplicationLog
log_stream_name = logdemo2
datetime_format = [%Y-%m-%d %H:%M:%S.%f]
file = /var/log/logdemo/app.log
multi_line_start_pattern = {datetime_format}

awslogsサービスを再起動して設定を反映。

$ sudo service awslogs restart

その他情報

CloudWatch Logs自体のログ

ログが追跡できていない時など、awslogsサービスでエラーがないか確認する際は/var/log/awslogs.logファイルを確認する。

$ cat /var/log/awslogs.log 

WebLogic + SLF4J + Log4j2

この組み合わせでログが出なさすぎたので解決方法をメモ。

ライブラリの設定:

pom.xml
<dependencies>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.8.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>2.8.2</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.21</version>
    </dependency>
</dependencies>
  • log4j-core(version:2.8.2) // Log4j2本体、version:2.9.0にすると何故かデプロイできない…
  • log4j-slf4j-impl // Log4j2へのバインディング
  • slf4j-api // ログファサード

weblogic.xmlでSLF4Jのリソース定義を行う:

weblogic.xml
<container-descriptor>
    <prefer-application-packages>
        <package-name>org.slf4j.*</package-name>
    </prefer-application-packages>
    <prefer-application-resources>
        <resource-name>org/slf4j/impl/StaticLoggerBinder.class</resource-name>
    </prefer-application-resources>
</container-descriptor>

StaticLoggerBinder.classを常にアプリケーションのリソースからロードされるよう設定しないといけないらしい2。わっかんねー:innocent:


続きを読む