Amazon Linux と Amazon Linux 2 の技術面の違い

Amazon Linux 向けに書いた Ansible Playbook を Amazon Linux 2 に対応させるときに気づいた点をまとめておきます。

個人ブログに書いた「Ansible で Amazon Linux と Amazon Linux 2 を見分ける」も参考にしてください。

TL;DR

Amazon Linux はもともと CentOS とよく似た構成なので、概ね CentOS 6 から 7 への変更点と同じです。

大きな変更点

init デーモン

init デーモンが Upstart から systemd に変更されています。 pstree コマンドで見ると PID 1 のデーモンが init から systemd に変わっていることがわかります。

Amazon_Linux_2
$ pstree -p --ascii
systemd(1)-+-agetty(3177)
           |-agetty(3178)
           |-amazon-ssm-agen(3204)-+-{amazon-ssm-agen}(3208)
           |                       |-{amazon-ssm-agen}(3209)
           |                       |-{amazon-ssm-agen}(3210)
           |                       |-{amazon-ssm-agen}(3211)
           |                       |-{amazon-ssm-agen}(3212)
           |                       |-{amazon-ssm-agen}(3213)
           |                       `-{amazon-ssm-agen}(3215)
           |-atd(3162)
           |-auditd(2567)---{auditd}(2568)
           |-chronyd(2630)
           |-crond(3164)
(snip)
Amazon_Linux
$ pstree -p --ascii
init(1)-+-acpid(2415)
        |-agetty(2605)
        |-amazon-ssm-agen(2250)-+-{amazon-ssm-agen}(2262)
        |                       |-{amazon-ssm-agen}(2263)
        |                       |-{amazon-ssm-agen}(2264)
        |                       |-{amazon-ssm-agen}(2265)
        |                       |-{amazon-ssm-agen}(2266)
        |                       |-{amazon-ssm-agen}(2271)
        |                       |-{amazon-ssm-agen}(2281)
        |                       |-{amazon-ssm-agen}(2282)
        |                       `-{amazon-ssm-agen}(2638)
        |-atd(2580)
        |-auditd(2258)---{auditd}(2259)
        |-crond(2566)
(snip)

ファイルシステム

ファイルシステムが ext4 から xfs に変更されています。

Amazon_Linux_2
$ df -T /dev/xvda1
Filesystem     Type 1K-blocks    Used Available Use% Mounted on
/dev/xvda1     xfs    8376300 1055844   7320456  13% /
Amazon_Linux
$ df -T /dev/xvda1
Filesystem     Type 1K-blocks    Used Available Use% Mounted on
/dev/xvda1     ext4   8123812 1072296   6951268  14% /

軽微な変更点

ユーザー

ec2-user の uid と gid が 500 から 1000 に変更されています。

Amazon_Linux_2
$ id
uid=1000(ec2-user) gid=1000(ec2-user) groups=1000(ec2-user),4(adm),10(wheel),190(systemd-journal)
Amazon_Linux
$ id
uid=500(ec2-user) gid=500(ec2-user) groups=500(ec2-user),10(wheel)

パッケージ管理

Yum リポジトリがひとつに集約されました。 /etc/yum.repos.d/ 以下を見ると、epel リポジトリが削除されたことがわかります。

Amazon_Linux_2
$ yum repolist
Loaded plugins: langpacks, update-motd
repo id                            repo name                              status
!amzn2-core/2017.12/x86_64         Amazon Linux 2 core repository         7,102
repolist: 7,102

$ ls -l /etc/yum.repos.d/
total 4
-rw-r--r-- 1 root root 1003 Dec 12 20:52 amzn2-core.repo
Amazon_Linux
$ yum repolist
Loaded plugins: priorities, update-motd, upgrade-helper
repo id                               repo name                           status
!amzn-main/latest                     amzn-main-Base                      5,883
!amzn-updates/latest                  amzn-updates-Base                     738
repolist: 6,621

$ ls -l /etc/yum.repos.d/
total 24
-rw-r--r-- 1 root root 1014 Nov  1 19:45 amzn-main.repo
-rw-r--r-- 1 root root  327 Nov  1 19:45 amzn-nosrc.repo
-rw-r--r-- 1 root root 1041 Nov  1 19:45 amzn-preview.repo
-rw-r--r-- 1 root root 1041 Nov  1 19:45 amzn-updates.repo
-rw-r--r-- 1 root root  957 Mar  1  2013 epel.repo
-rw-r--r-- 1 root root 1056 Mar  1  2013 epel-testing.repo

NTP クライアント

NTP クライアントが ntpd から chronyd に変更されています。

Amazon_Linux_2
$ ps aux | grep -e ntpd -e chronyd
chrony    2633  0.0  0.8 120480  4356 ?        S    22:53   0:00 /usr/sbin/chronyd
Amazon_Linux
$ ps aux | grep -e ntpd -e chronyd
ntp       2506  0.0  0.8  29772  4280 ?        Ss   22:53   0:00 ntpd -u ntp:ntp -p /var/run/ntpd.pid -g

MTA

MTA が Sendmail から Postfix に変更されています。

Amazon_Linux_2
$ alternatives --display mta
mta - status is auto.
 link currently points to /usr/sbin/sendmail.postfix
/usr/sbin/sendmail.postfix - priority 30
 slave mta-mailq: /usr/bin/mailq.postfix
 slave mta-newaliases: /usr/bin/newaliases.postfix
 slave mta-pam: /etc/pam.d/smtp.postfix
 slave mta-rmail: /usr/bin/rmail.postfix
 slave mta-sendmail: /usr/lib/sendmail.postfix
 slave mta-mailqman: /usr/share/man/man1/mailq.postfix.1.gz
 slave mta-newaliasesman: /usr/share/man/man1/newaliases.postfix.1.gz
 slave mta-sendmailman: /usr/share/man/man1/sendmail.postfix.1.gz
 slave mta-aliasesman: /usr/share/man/man5/aliases.postfix.5.gz
Current `best' version is /usr/sbin/sendmail.postfix.
Amazon_Linux
$ alternatives --display mta
mta - status is auto.
 link currently points to /usr/sbin/sendmail.sendmail
/usr/sbin/sendmail.sendmail - priority 90
 slave mta-mailq: /usr/bin/mailq.sendmail
 slave mta-newaliases: /usr/bin/newaliases.sendmail
 slave mta-rmail: /usr/bin/rmail.sendmail
 slave mta-sendmail: /usr/lib/sendmail.sendmail
 slave mta-pam: /etc/pam.d/smtp.sendmail
 slave mta-sendmailman: /usr/share/man/man8/sendmail.sendmail.8.gz
 slave mta-mailqman: /usr/share/man/man1/mailq.sendmail.1.gz
 slave mta-newaliasesman: /usr/share/man/man1/newaliases.sendmail.1.gz
 slave mta-aliasesman: /usr/share/man/man5/aliases.sendmail.5.gz
Current `best' version is /usr/sbin/sendmail.sendmail.

まとめ

ひとつの Playbook の中で Amazon Linux と Amazon Linux 2 に対応するのはなかなか大変なので、fork して別の Playbook を書いたほうが楽かもしれませんね。

続きを読む

SSL証明書の有効期限監視をLambda+CloudWatchで実装する

SSL証明書の有効期限をLambdaで取得し、CloudWatchにカスタムメトリクスを送り、CloudWatch Alarmで通知する

AWS上のEC2インスタンスや各種サービスの監視を行う際、CloudWatch Alarmを活用しているケースは多いと思います。
このような場面を想定し、Lambdaで毎日SSL証明書の有効期限チェックを行い、CloudWatchに各ドメインの残日数を送り、その日数をターゲットとしたCloudWatch Alarmを設定することができるようにしたいと思います。

環境

ランタイム:node.js 6.10
開発環境:AWS Cloud9

監視対象の管理

監視対象のドメインは適宜増減することが想定されます。
これらを簡単に管理するために、今回はAWS Systems Manager のパラメータストアにて管理を行います。

パラメータストアに、下記のようなパラメータを登録します。

項目 内容
キー名 /monitor/certificate/domains
タイプ 文字列
[ “hogehoge.com”, “example.com” ]

上記のようにチェックを行うドメインをJSON配列形式で設置します。

Lambdaコード

下記ので実装できます。
※child-process-promise を使用していますが、モジュールのインストールを別途行わなくてもよい
 child_processを使っても良いと思います。(全てをPromiseで統一したかったのであえてchild-process-promiseを使っています)

index.js
const AWS = require('aws-sdk');
var SSM;
var CW;

exports.handler = (event, context, callback) => {
  if(SSM===undefined){
    SSM = new AWS.SSM({region: 'ap-northeast-1'});
  }
  if(CW===undefined){
    CW = new AWS.CloudWatch({region: 'ap-northeast-1'});
  }

  Promise.resolve()
  .then(()=>{
    return new Promise((resolve)=>{
      let ssm_params = {
        Name: "/monitor/certificate/domains"
      };
      let ssm_parameter = SSM.getParameter(ssm_params).promise();
      ssm_parameter.then((data)=>{
        resolve(JSON.parse(data.Parameter.Value));
      });
    });
  })
  .then((domains)=>{
    return new Promise((resolve)=>{
      let check_expire_list = [];
      domains.forEach((domain)=>{
        check_expire_list.push(checkExpire(domain));
      });
      Promise.all(check_expire_list)
      .then((result_valid)=>{
        resolve(result_valid);
      });
    });
  })
  .then((valid_list)=>{
    return new Promise((resolve)=>{
      let metric_list = [];
      valid_list.forEach((result)=>{
        var params = {
          MetricData: [
            {
              MetricName: 'valid_days',
              Dimensions: [
                {
                  Name: 'domain',
                  Value: result.domain
                }
              ],
              Unit: 'None',
              Value: result.valid_days
            }
          ],
          Namespace: 'SSLCertificate'
        };
        metric_list.push(CW.putMetricData(params).promise());
      });
      Promise.all(metric_list)
      .then((data)=>{
        resolve();
      });
    });
  })
  .then(()=>{
    callback();
  });
};

var checkExpire = (domain)=>{
  return new Promise((resolve)=>{
    let exec = require('child-process-promise').exec;
    let cmd = "openssl s_client -connect " + domain + ":443 -servername " + domain + " < /dev/null 2> /dev/null | openssl x509 -text | grep Not | sed -e 's/^  *//g' | sed -e 's/Not.*: //g'";
    let now = new Date();
    exec(cmd)
    .then((result)=>{
      let not = result.stdout.split("n");
      let expire_date = new Date(not[1]);
      let valid_days = Math.floor((expire_date - now) / 1000 / 3600 / 24);
      console.log(domain+" の残り日数は "+valid_days + " です");
      resolve({'domain': domain,'valid_days': valid_days});
    });
  });
};

SAM Template(CloudFormation)

上記のコードをデプロイするためのSAMテンプレートとして、下記のテンプレートでデプロイすることで、CloudWatchEventsにて毎日実行する設定を同時に行われます。

template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: SSL certificate monitoring function.
Resources:
  monitorCertExpire:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: monitorCertExpire/index.handler
      Runtime: nodejs6.10
      Description: ''
      MemorySize: 256
      Timeout: 300
      Events:
        CheckExpire:
          Type: Schedule
          Properties:
            Schedule: rate(1 day)
            Input: "{}"

CloudWatch

上記をデプロイすることで、CloudWatchメトリクスに 名前空間:SSLCertificate メトリック:valid_days で有効期限切れまでの残り日数が毎日送信されます。

このメトリックデータを使用し、間隔:1日 統計:最小 期間:1中1のデータポイント にて、アラートさせたい日数をしきい値としてアラームを設定することでこれまで通り他の監視と同様に扱うことができます。

参考にさせていただきました

https://qiita.com/zwirky/items/25b1a66dac534f67ca03
https://blog.manabusakai.com/2016/07/lambda-cert-expire/

続きを読む

Go – AWS SSM Parameter Storeのデータを復号化とmockテストの書き方

SSMとは? SSM ParameterStoreとは? 実際にやってみよう 1. ParameterStoreの登録 2. aws-cliで試してみる 3. Goで動かす 4. テストを書く SSMとは? インフラ運用を便利にするサービス SSM ParameterStoreとは? パスワードなど値を管理 KMSを使… 続きを読む

カテゴリー 未分類 | タグ

t2.microインスタンスでWindowsは使い物になるのか?

ICDP(田舎クラウドデザインパターン)的なネタ再び。

概要

AWS EC2 t2.micro インスタンスのシステム資源は非常に乏しい。
AWS無料利用枠でウィンドウズも対象だけど、本当に使い物になるのか?

目的

t2.microインスタンスへWindows Server 2008R2をインストールしてソフトウェアを起動しようとしたところ、 Out of Memory で起動不能であった。
メモリ1GB、連続して演算できない制限付きのCPU能力で、ウィンドウズを使用するには厳しい。
動作させたいソフトウェアは必要メモリ500MBのため、なんとか使えるようにすることを目的とする。

要件

  • AMI
    Windows_Server-2008-R2_SP1-Japanese-64Bit-Base-2017.11.29 – ami-95d06bf3

  • ページファイル(スワップ)無しで使う。
    スワップが発生したら実用にならないためページファイルは無しとする。
    これはスワップ処理にはCPU時間を消費するため、CPU時間に制限があるt2系インスタンスでは動作が間欠的に停止したり、操作不能に陥ったりするからである。

現状

Windows Server 2008R2 をインストールして起動した状態はこのようになっている。
t2a.jpg

消費メモリは959MB。
メモリ1GBしか無いのに消費メモリがこの状況では無理もない。殆ど空きがない。
40MBではメモリ不足で起動不能となるのは当然であろう。

対処

タスクマネージャでメモリ使用状況を見て削減できそうなプロセスを調べる。
t2b.jpg

TrustedInstaller.exe が460MBも使用している。
これは何かと調べると、Windows Modules Installerサービスのようだ。
Windows Update関連のプログラムで、停止させると更新に失敗するが通常は問題無いので停止させてみた。

無効に設定したサービス

先の大物を含め、無効に設定したサービスは以下の通り。
ただしこれを行うとWindows Updateが失敗するので行う場合は手動で起動し対処すること。

  • Windows Modules Installer
  • Windows Update
  • WinHttp Web proxy Auto-Discovery Service

また、AWSオリジナルの制御機能を使わないのであれば以下も無効にできる。
こちらは計20MB程度の削減にしかならないのでお好みで。

  • Amazon SSM Agent
  • AWS Lite Guest Agent
  • Ec2Config

対処した結果

t2c.JPG

消費メモリが400MB程度となり、600MBの空きを確保できた。

結論

かろうじて要件を満たし動作可能な環境を構築できた。
しかし、リソースには余裕が無いためMackerel等で常時監視した方が良いと思われる。

続きを読む

GitHub上のAnsiblePlaybookをSystems Managerで実行する

おさらい. “AWS-RunRemoteScript”でやっていることは、以下の2つです。 コンテンツ(スクリプトなど)のダウンロード. https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-plugins.html#aws-downloadContent. コマンドの実行. (Windows) … 続きを読む

AWS Parameter Storeから取得したパラメータを環境変数に設定するgemを作った

AWS Parameter Storeから取得したパラメータを環境変数に設定するgemを作った – エムスリーテックブログ. おはこんにちばんわ。エムスリーエンジニアの園田です。 先日 aws-ssm-env というRubyのgemを公開しまし… 続きを表示 おはこんにちばんわ。エムスリーエンジニアの園田です。 先日 aws-ssm-env というRuby … 続きを読む

カテゴリー 未分類 | タグ

AWS re:Invent 2017 DevOps関連セッションまとめ

まとめについて

re:Invent 2017 で行われたBreak Out Session から DevOps に関するオススメセッションを独断と偏見でピックアップしました。AWSだけに限った内容ではありませんので、DevOps開発プロセス、マネジメント、アーキテクチャ一般の勉強にもどうぞ。
なお、本投稿は個人の見解であり、所属企業とは関係がありません。

セッション動画(英語)のリンクをつけました。Slideshareもできるだけ拾いましたが資料が公開されていないものもあります。
できるだけYouTubeの動画を見ることをおすすめします。米国のカンファレンスは資料より話がメインです。多くは資料なんか見ないで話します。デモも多くあります。
英語が苦手な方はYouTubeの各種機能(英語字幕、自動翻訳による日本語字幕、文字起こし、スピード調整など)を使ってご覧になってください。英語字幕を見ながら聞くのはリスニングの勉強にもなります。

カテゴリは以下のとおり:

  • DevOps全般
  • Chaos Engineering
  • DevOpsを実現するためのアーキテクチャ
  • CI/CDパイプライン
  • CloudFormation
  • CLI
  • Management & Governance & Monitoring
  • DevOps ワークショップ

DevOps全般

Life of a Code Change to a Tier 1 Service (DEV206)

Launch Applications the Amazon Way (DEV203)

  • Amazonにおけるアプリケーション開発スタイルを紹介した後、Code Starのデモを中心にCode*サービス、プロビジョン、デプロイ系サービスの全体像を解説。
  • https://www.youtube.com/watch?v=ITNorHA9m6Q

Tools Won’t Fix Your Broken DevOps (DEV345) by DevOps Research and Assessment

Chaos Engineering

Performing Chaos at Netflix Scale (DEV334) by Netflix

DevOpsを実現するためのアーキテクチャ

Cisco’s Journey from Monolith to Microservices (DEV329)

  • 前半はAWSのSAがマイクロサービスにおける永続的データの管理方法について解説。これはいい内容。後半はCiscoが社内の既存データをマイクロサービスとして提供するためのアーキテクチャについて解説。
  • https://www.youtube.com/watch?v=Qv7iRDbxS6A

Embracing Change without Breaking the World (DEV319)

CI/CDパイプライン

Continuous Integration Best Practices for Software Development Teams (DEV322)

  • 効果的なCI実施のための3つ施策について解説。Nighty Check, Branch Check, PullRequest Check。ツールとしてCodeBuildの活用をベースに。登壇者はWarnerのKeynoteに出てきたClare。彼女はCodeBuildの開発チームの一員。
  • https://www.youtube.com/watch?v=GEPJ7Lo346A

Deep Dive on Advanced Continuous Delivery Techniques Using AWS DevOps Tools (DEV324)

  • 昨年もあったContinuous DeliveryのDeep Diveセッション。「CDパイプラインが本番環境を壊すことが怖いですか?」怖い人はこのセッションを。
  • https://www.youtube.com/watch?v=Lrrgd0Kemhw

Use Amazon EC2 Systems Manager to Perform Automated Resilience Testing in Your CI/CD Pipeline (DEV338) by Expedia

Manage Your Applications with AWS Elastic Beanstalk (DEV305)

CloudFormation

CFn関連セッションはこちらのブログにもまとめて紹介されています
https://aws.amazon.com/jp/blogs/mt/your-aws-cloudformation-guide-to-reinvent-2017/

Deep Dive on AWS CloudFormation (DEV317)

  • CFnのプロダクトマネージャAnilによるDeep Dive Session。中ほどにStackと実環境との違いを検知するDrift Detection (commin soon) について解説があります。
  • https://www.youtube.com/watch?v=01hy48R9Kr8

Learn How Intuit Built a Frictionless Infrastructure Management System Using AWS CloudFormation (DEV318)

Build Once, Deploy Many: Architecting and Building Automate (GPSTEC319)

CLI

Introduction to the AWS CLI (DEV323)

AWS CLI: 2017 and Beyond (DEV307)

Management & Governance & Monitoring

How Amazon.com Uses AWS Management Tools (DEV340)

Using AWS Management Tools to Enable Governance, Compliance, Operational, and Risk Auditing (DEV339)

NEW LAUNCH! Gain Operational Insights and Take Action on AWS Resources with AWS Systems Manager (DEV346)

Embrace DevOps and Learn How to Automate Operations (DEV306)

Using Amazon CloudWatch for Amazon ECS Resource Monitoring at Scale (DEV333)

DevOps ワークショップ

Advanced DevOps Practices for AWS(DEV401)

DevOps Essentials An Introductory Workshop on CICD Practices

続きを読む

AWS System Manager Parameter StoreからパラメータをYAMLにいい感じに展開する

AWS上でアプリケーションを動作させる際、みなさん秘匿情報はどう扱っていますか?

  • KMSをつかう
  • Parameter Storeをつかう
  • Privateな設定管理ツールで管理する

あたりが一般的かなと思います。

開発リポジトリには秘匿情報をいれないポリシーで開発している場合、設定用のリポジトリを分けたり、別のコードとして管理する必要があるなど、ややまどろっこしいなあと思っていました。

そこで今回はYAMLにマクロ展開の機能を追加して、このあたりの管理を楽にできないかと思い、PoCしてみました。

Parameter Storeとは

Parameter Storeはキーと値を保存するシンプルな仕組みです。ざっくり紹介すると、以下が特徴です。

  • キーと値のペアを保存できる
  • 平文あるいは暗号化するか否かを選択可能
  • 暗号化のためのCMK(customer master key)を選択可能

aws-cliを利用した操作例は次のとおりです。

# 平文の場合
$ aws ssm put-parameter --name a_name --value "a value"
$ aws ssm get-parameter --name a_name --with-no-decryption

# 暗号化する場合
$ aws ssm put-parameter --name a_name --value "a value" --type SecureString
$ aws ssm get-parameter --name a_name --with-decryption

参考: http://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html

yaml.Unmarshal を拡張する

これらをアプリケーション実行時に環境変数になりに展開することもできます。ECSなどのコンテナ環境で環境変数に秘匿情報を平文でいれるのはセキュアではありません。

そこでYAMLファイルを読み取る際に値を展開すればよいのでは、と考えて実装してみました。

https://github.com/suzuken/yamlssm

機能はシンプルです。

  • yaml.Unmarshal と同様のインタフェースです。(import文を変えるだけで適用可能)
  • ssm:// から始まる場合のみParameter Storeから値を展開します。

コード例は次のとおりです。

type T struct {
    Foo string
    Bar string
}
var t T

if err := yamlssm.Unmarshal([]byte[`
foo: ssm://prod.database.name
bar: test
`], &t); err != nil {
    // ...
}

fmt.Print(t.Foo) // -> value of prod.database.name on your ssm

ひとまずデフォルトのCMSのみサポートしています。実行権限についてはaws-sdk-goの認証に準じます。

Parameter Storeにパラメータが存在しない場合にはUnmarshalがエラーになります。実際のアプリケーションでは初期化処理時にYAMLで設定を読み込むと思うので、エラーの場合にはpanicなりで起動させないようにするとよいです。

まとめ

Parameter Store便利なのでどんどんつかっていきましょう。

続きを読む

新しいCloudWatch AgentでEC2インスタンスのメモリ使用率を監視する

この記事は OpsJAWS Advent Calendar 2017 19日目の記事です。

はじめに

先日、新しいCloudWatch Agentが登場しました。
https://aws.amazon.com/jp/about-aws/whats-new/2017/12/amazon-cloudwatch-introduces-a-new-cloudwatch-agent-with-aws-systems-manager-integration-for-unified-metrics-and-logs-collection/

これまでディスク使用量やメモリ使用率といった仮想マシン上のメトリックについては
CloudWatch Monitoring Scripts 等 を設定してCloudWatchにデータを送信する必要がありました。
新しい Agent ではこれらのゲストOS上のメトリックについても収集できるようになっています。

収集可能なメトリックの一覧については以下のドキュメントを参照ください。
稼働対象(EC2 or On-premises)、OS、ログ取得レベルによっても取得出来る内容が異なります。
http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CW_Support_For_AWS.html#metrics-collected-by-CloudWatch-agent

やってみる

実際にAmazon Linuxサーバのメモリ使用率の監視設定を行ってみます。

IAMロールの作成

CloudWatch Agent を実行する EC2 インスタンスにアタッチする IAM ロールを事前に作成しておきます。

まず、以下の内容でポリシーを作成します。ポリシー名は任意に設定します。

CloudWatchAgentAdminPolicy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "CloudWatchAgentAdminPolicy",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "cloudwatch:PutMetricData",
                "ec2:DescribeTags",
                "logs:DescribeLogStreams",
                "logs:CreateLogGroup",
                "logs:PutLogEvents",
                "ssm:GetParameter",
                "ssm:PutParameter"
            ],
            "Resource": "*"
        }
    ]
}

新規のEC2用のIAMロールを作成し、上記のポリシーをアタッチします。
Agent の設定は AWS Systems Manager のパラメータストアに格納し、他サーバに展開させることが可能です。
上記例ではパラメータストアへの書き込みのため、ssm:PutParameter権限を付与しています。
通常、全てのインスタンスがパラメータストアへの書き込み権限を持つ必要はありませんので、
上記とは別に ssm:PutParameter を除いた一般用のIAMロールを別途作成することが望ましいです。

image.png

CloudWactch Agent のインストール

先ほど作成したIAMロールを、インストール対象のEC2インスタンスにアタッチします。

Agent のインストール方法は以下の2通りです。

  • AWS Systems Manager(ssm)によるインストール
  • CLI によるインストール

運用を考えると ssm でインストールを行うほうが楽ですが、
今回はAgentの基本的な操作を覚えるために、EC2インスタンスにログインし、CLIでインストールを行いました。

$ wget https://s3.amazonaws.com/amazoncloudwatch-agent/linux/amd64/latest/AmazonCloudWatchAgent.zip
$ unzip AmazonCloudWatchAgent.zip
$ sudo ./install.sh

プロキシを設定する必要がある環境の場合は、
/opt/aws/amazon-cloudwatch-agent/etc/common-config.tomlに設定します。

common-config.tml
[proxy]
http_proxy = "{http_url}"
https_proxy = "{https_url}"
no_proxy = "{domain}"

Agent 設定

Agent 設定ファイルの作成

Agent の設定ファイルは、収集するメトリックやログファイルを指定したファイルです。
JSONで作成されたファイルをAgent 起動時にTOMLに変換する形になります。
手動で作成することもできますが、ここではウィザードを使用して作成します。

$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard

ウィザードでは以下を設定します。カッコ内は今回選択した内容です。
収集間隔は最短で1秒を指定できるようになっていますが、今回は60秒を選択しました。

  • インストール先のOS(Linux)
  • インストール先がEC2かオンプレミスか(EC2)
  • ホストのメトリクスを収集するか(yes)
  • CPUコア毎のメトリクスを収集するか(yes)
  • EC2ディメンションを全てのメトリクスに追加するか(yes)
  • メトリクスを収集する間隔(60s)
  • メトリクスの収集レベル(Standard)

ログファイル監視対象の設定

既にCloudWatch Logs を使用している環境の場合は、引き続きこのウィザードで設定を移行できます。
移行を行わない場合も監視対象のログファイルのパスを指定し、追加することができます。
ここでは デフォルト選択の syslog(/var/log/messages) を対象に指定し、ログの監視設定を完了します。

設定ファイルは /opt/aws/amazon-cloudwatch-agent/bin/config.json に保存されます。
今回、最終的な設定内容は以下のようになります。

config.json
{
    "logs": {
        "logs_collected": {
            "files": {
                "collect_list": [
                    {
                        "file_path": "/var/log/messages",
                        "log_group_name": "messages"
                    }
                ]
             }
         }
    },
    "metrics": {
        "append_dimensions": {
            "AutoScalingGroupName": "${aws:AutoScalingGroupName}",
            "ImageId": "${aws:ImageId}",
            "InstanceId": "${aws:InstanceId}",
            "InstanceType": "${aws:InstanceType}"
        },
        "metrics_collected": {
            "cpu": {
                "measurement": [
                    "cpu_usage_idle",
                    "cpu_usage_iowait",
                    "cpu_usage_user",
                    "cpu_usage_system"
                ],
                "metrics_collection_interval": 60,
                "resources": [
                    "*"
                ],
                "totalcpu": false
             },
            "disk": {
                "measurement": [
                    "used_percent",
                    "inodes_free"
                ],
                "metrics_collection_interval": 60,
                "resources": [
                    "*"
                ]
            },
            "diskio": {
                "measurement": [
                    "io_time"
                ],
                "metrics_collection_interval": 60,
                "resources": [
                    "*"
                ]
            },
            "mem": {
                "measurement": [
                    "mem_used_percent"
                ],
                "metrics_collection_interval": 60
            },
            "swap": {
                "measurement": [
                    "swap_used_percent"
                ],
                "metrics_collection_interval": 60
            }
        }
    }
}

パラメータストアへの保存

ウィザードの最後に設定ファイルをSSM パラメータストアに保存するかの確認があります。
選択肢は全てデフォルトで問題ありません。

  • 設定ファイルを SSM パラメータストアに保存するか(yes)
  • パラメータストア名(agent-config-linux)
  • 保存先リージョン(ap-northeast-1)
  • AWSクレデンシャルの選択(From SDK)

aws cliで手動アップロードすることも可能です。

$ cd /opt/aws/amazon-cloudwatch-agent/bin/
$ aws ssm put-parameter --name "agent-config-linux" --type "String" --value file://config.json

AWS Systems Manger のコンソールを確認すると、パラメータストアが保存されていることが確認できます。

image.png

Agentの起動

SSMパラメータストアに保存した設定ファイルでAgentを起動してみます。

$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c ssm:agent-config-linux -s
/opt/aws/amazon-cloudwatch-agent/bin/config-downloader --output-file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json --download-source ssm:agent-config-linux --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml
Successfully fetched the config from parameter store ssm:agent-config-linux and saved in /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
Start configuration validation...
/opt/aws/amazon-cloudwatch-agent/bin/config-translator --input /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json --output /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml
Valid Json input schema.
Configuration validation first phase succeeded
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent -schematest -config /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml
Configuration validation second phase succeeded
Configuration validation succeeded
amazon-cloudwatch-agent start/running, process 2811

メッセージの内容から、JSONの設定ファイルが
/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml として保存されていることがわかります。

ログファイルは /opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log に出力されています。
またAgentインストール時にサービス登録が行われていますが、

  • common-config.toml
  • amazon-cloudwatch-agent.toml

の2ファイルが存在しないと、OS起動時にAgentが正常に起動できないようです。

ステータス確認、および終了コマンドは以下のように行うことができます。
また amazon-cloudwatch-agent.toml が作成されている状態であれば、2回目以降の起動では
設定ファイルのフェッチは不要です。

# ステータス確認
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a status
{
  "status": "running",
  "starttime": "2017-12-19T01:43:56+0000",
  "version": "1.73.9"
}

# 停止
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a stop
amazon-cloudwatch-agent stop/waiting

# 起動
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a start
amazon-cloudwatch-agent start/running, process 3044

監視設定

コンソール上で取得したメトリックの確認および、アラームの設定を行います。

メトリックの確認

カスタム名前空間の CWAgent を選択します。
少しわかりにくいですが、それぞれのメトリックを確認できます。

  • ImageId, InstanceId, InstanceType, device, fstype, path: Disk
  • ImageId, InstanceId, InstanceType, cpu: CPU
  • ImageId, InstanceId, InstanceType, name: Disk I/O
  • ImageId, InstanceId, InstanceType: Memory

image.png

ImageId, InstanceId, InstanceType を選択すると、mem_user_percent および swap_user_percent の値を確認することができました。

image.png

アラームの設定

特に変わった手順はありません。
グラフ化したメトリクスからアクションのアラームの作成を選択します。
image.png

アラーム名、閾値、間隔、通知先等を任意に設定し、アラームの作成を押下します。
image.png

以上でメモリ使用率の監視設定が完了しました。
参考になれば幸いです。

続きを読む

中途入社のAWSエンジニアが、稼働中サービスの運用状況をキャッチアップするために意識すること

Classiアドベントカレンダー11日目です。
今回は、AWSエンジニアが稼働中のAWSの管理アカウントを渡されて、ビクビクしながらキャッチアップを行っていったときのメモになります。

1.TL;DR

AWSアカウントのログイン前に準備できることもあるし、AWSアカウントにログインしてわかることもあるし、サーバーにログインしてわかることもある。それぞれのレイヤーでどういったことを確認するかを意識しながらキャッチアップを進めていきましょう。

2.AWSアカウントログイン前の事前準備

pre_aws.png

サービスが稼働しているのであれば、AWSアカウントにログインせずとも、たくさんの情報をキャッチアップすることができます。1日目から何らかの大きなアウトプットを出さないと解雇するような会社は、(おそらく)存在しない筈です。まずは落ち着きましょう^^;

2-1.ドキュメント読み込み

サービスのインフラにAWSが使われることが多くなったからといって、入社前に経験したAWS運用フローがそのまま活かせる訳ではありません。まずは、前任者や運用中のドキュメント管理ツールの中から、今までどのような運用を行っていたかを確認します。
ドキュメントを見たときに意識する観点としては、

  • フロー型:時間による鮮度の劣化があるドキュメント
  • ストック型:システム仕様など、メンテナンスが求められるドキュメント

どちらの情報であるかを意識して読むことが重要です。
フロー型の情報は、障害などで一時的な対応用にメモっていることもあり、運用の中で解決済みのことがあります。そのため、ストック型のドキュメントを中心に見ることが素早いキャッチアップになると思います。
とはいえ、ドキュメントの全てがメンテナンスされている会社というのは稀だと思いますので、各種ドキュメントを見ながら、仮説程度に自分なりのシステム構成図などを書いてみましょう。
要件定義書や各種構成図の変更履歴、課題管理表、リスクコントロール表といったドキュメント類があるのであれば、目を通しておきましょう。

2-2.運用フローを観察する

サービス側のドキュメントについては、まだ文書化されてることが多いですが、運用系ツールに関しては、ドキュメント化されていないことがあります。今の開発スタイルであれば、何らかのチャットツール(Slack,ChatWork,HipChat)上で、

  • デプロイ
  • 各種の通知
  • 運用Bot

の運用といったことが行われていると思います。また、チャットだけでなく、メールでの運用フローも存在しているかもしれません。
こうした運用系ツールの存在は、今後自分がリファクタするときに、「必須要件ではないが、重宝している」ということで、「リファクタ後にも、あの機能を実装して欲しい」といった声が社内から上がると思います。
そのため、このような運用フローがどこで実装されているかを見極めることが重要になってきます。

2-3.インフラ部分のコード読み

「俺はフルスタックエンジニアだ!」という強い意思がある方は、この時点で稼働中のアプリ側のコードまで読み込んでいただければよいですが、まずは入社前に期待されたであろう、インフラまわりのコード化部分を把握しておきましょう。どのみち、いずれはメンテナンスを任されたり、質問されることが増えてきますので、自分のメンテナンスする部分を優先的に確認しておきましょう。
実サーバーの運用はAWSに任せているので、ここで意識しておくことは、

  • Infrastructure Orchestration Tools:Terraform, CloudFormationなど
  • Server Configuration Tools:Chef,Ansible,Itamaeなど

あたりのコードがgithubなどに保存されているからといって、メンテナンスされていない可能性もあります。
コードの設計方針などを確認するのは当然必要なのですが、コードの変更履歴が年単位で放置されていないかどうかも見ておきましょう。特に、AWS関連のコードについては、担当する人がアプリ側よりも少ないので、構築当初のコードのままなのか、運用されているコードなのかはPRなどで確認しておいた方がよいです。

3.AWSのアカウント内を調査する

aws_kansatsu.png

実際にAWSアカウントにログインしたり、APIで各種設定を確認していきます。Web系サービスであれば、TCP/IPモデルやC/Sモデルを意識しながら、下層レイヤー回りから調査していき、ネットワークがどうせ設定されているかを確認していきます。
おそらく、ここで多くの疑問(場合によっては、絶望)が生まれる段階です。「あれ?ドキュメントにこう記述されているけど、設定上は違うような…」という沼にハマることがあるでしょう。負けないでください、一人で抱え込まずに闇を共有できる仲間を見つけましょう。

3-1.外部システム連携の確認

関連するAWSサービス

VPC関連のサービスを中心に、自AWSアカウント以外の連携がないかの確認を行います。

関連しやすいAWSサービス例)

  • DirectConnect
  • NAT Gateway
  • Peering Connection
  • Customer Gateways
  • Virtual Private Gateways
  • VPN Connections
  • NetWorkACL
  • SecurityGroup
  • EIP

などに、何らかのインスタンスが稼働していて、productionやhonbanなどの文言がついたものがあれば、それはドキュメント上には存在しないが、サービス上何らかの理由で稼働しているものである可能性があります。
自社のサービスがAWSアカウント内だけで完結しているのであればよいのですが、誤ってここのインスタンスなどを削除すると、場合によってはシステム復旧できないぐらいの痛手になるので、慎重に確認していきましょう。
特に、SecurityGroupは、最近でこそInboundルールにDescriptionをつけられるようになりましたが、数年運用されているシステムには、何で利用しているIPアドレスなのかがわからないことがあるので、設定確認中に不明なIPアドレスを見つけたら社内で有識者に聞いてみましょう。

3-2.システム導線の確認

関連するAWSサービス

インスタンス障害があるとユーザー影響がありそうな、システム導線を追っていきます。

関連しやすいAWSサービス例)

  • ELB(CLB,ALB,NLB)
  • CloudFront
  • EC2
  • ElasticCache(redis,memcached)
  • RDS(Aurora,MySQL,PostgreSQL,SQLServer)
  • ElasticSearch
  • DynamoDB
  • S3

各種のインスタンスサイズが適切かを確認するのはもちろんですが、DB関連についてはバックアップ関連の設定がちゃんと行われているかどうかも確認しておきましょう。バックアップウィンドウの世代数やメンテナンスウィンドウの時間が営業時間内になっているとかは、結構ありがちな設定漏れケースになります。パラメータストアの設定については、本番で稼働している設定が正義なので、設計と違う場合は、社内で経緯を追ってみましょう。

3-3.運用導線の確認

関連するAWSサービス

直接のユーザー影響はないものの、バッチ系およびログインやログ連携など、システム運用で必要な運用導線を追っていきます。

関連しやすいAWSサービス例)

  • EC2
  • Lambda
  • ElasticSearch(& kibana)
  • IAM
  • CloudTrail
  • AWS Config
  • CloudWatch Logs
  • S3
  • Glacier

24224というポート開放を見れば、そのシステムはfluentd関連のフローがあるのはほぼ確定なので、ログの発生から可視化ツールおよびバックアップのフローまで追っていきましょう。また、バッチ系のEC2に関しては、最近のAWSだと、FargateやECS、Lambdaなどで定期バッチを行うことも可能なので、単一障害点をなくすことができないか、今後の計画のために、バッチ系が整理されているドキュメントなどを探してみましょう。

4.サーバー内の設定を確認する

server_chosa.png

最近だと、Server Configuration Toolsが大分普及していたり、コンテナ系の運用が発達してきているので、このあたりのキャッチアップ期間が少なくなるのかなと思います。とはいえ、SSH接続を頻繁に行うサーバーや起動時間が長いサーバーだと、コードの設定と異なる部分が出てきていることがあるかもしれません。
OSの設定やミドルウェアのバージョンなど、SSH接続すると確認した方がよいところは多々ありますが、Server Configuration Toolsの設定と異なっていたり、運用中のアラート設定などで差異がでやすそうな部分を以下に記載します。

4-1.各種メトリクス確認

メモリやプロセスの状況は、通常CloudWatchだけではわからないので、MackerelやZABBIXなどの監視ツールエージェントを入れているのであれば、各サーバーのメトリクスを確認しておきましょう。

4-2.稼働プロセスの確認

pstreeなどで、稼働しているプロセスを確認します。SSH接続が禁止されているのであれば、AWSのSSMエージェントなりで確認できないかを検討してみましょう。設計上のソフトウェアスタックに存在しないプロセスが常駐している場合は、何のエージェントが動いているかを追っておきましょう。

4-3.不要なファイルが出力されていないかの確認

ログレベルがデバッグのままだったり、ログファイルのローテートがなされていない場合があり、アラートは上がっていないけど、サーバー内のリソースを侵食しているときがあります。また、生成されるログファイルが小さすぎると、ディスクに余裕がありそうに見えても、inodeが先に枯渇するときもあります。lsofdf -iなどを可視化するなどして、サーバー内のディスク状況を確認しておきましょう。

4-4.同期処理と非同期処理のプロセス確認

同期処理のプロセスは意識しやすいので、監視対象に入っている可能性が高いです。ただ、非同期系プロセス(Rubyだとsidekiq,Pythonだとcelery,PHPだとphp-resqueなど)が監視対象に入っていないこともあるので、どのサーバーで非同期処理が行われているかを把握しておきましょう。

5.まとめ

AWSや他のパブリッククラウドが全盛になった今でも、3層アーキテクチャのシステム構成やOSI7階層などのレイヤーを意識しながらキャッチアップを行うと、システムを俯瞰しながらキャッチアップを進めることができるのではないかなと思います。とはいえ、前任者がコード化しきれなかった部分もある筈なので、そこは社内で過去経緯を知っている人に笑顔で質問をしてみましょう。技術が発達しても、人に蓄積されるノウハウはまだまだ多いので…
AWSエンジニアが転職する際などのご参考になれば。

続きを読む