Foreverly

メモ帳

シェルスクリプトでのリトライ処理とロック処理

サーバ運用で手動でApache再起動のような対応は辛いので アラートを検知したら自動でApache再起動を実施し、 メールで知らせてくれるスクリプトを書きたいと思い、 リトライ処理やロック処理をシェルスクリプトでどうやるか調べたのでまとめます。

リトライ処理

変数でリトライ回数とリトライ間隔を決めて whileループでカウントを1ずつ増やし、 sleepコマンドの引数にリトライ間隔の変数を与えることで リトライ処理を実装できた。

## リトライ処理
RETRY_COUNT=1    # リトライ回数
RETRY_INTERVAL=1 # リトライ間隔1秒

while [[ $COUNT -ne $RETRY_COUNT ]]
do
    COUNT=`expr $COUNT + 1`
    sleep $RETRY_INTERVAL
done

ロック処理

こちらの記事が参考になりました。https://heartbeats.jp/hbblog/2013/10/atomic03.html#more

シンボリックリンクを作成するときに、作成先にすでにファイルが存在するとエラーとなります。そのため、ロックファイルをシンボリックリンクとして作成を試みれば、ロックファイルが存在すればエラーが発生するため、ロックファイルが存在すると判断し処理を中断できます。ロックファイルが存在しなければ、ロックファイルがシンボリックリンクとして作成されます。「ロックファイルの確認」と「ロックファイルの作成」が同時に行われるため、安全にロックすることができるのです。普通のファイルとしてロックファイルを作成する方法での問題はシンボリックリンクの場合は起きません。

以下のようにシンボリックリンクを作成することでアトミックにロックファイルを作成することができます。

#!/bin/bash
LOCK_FILE=$HOME/tmp/file.lock

## ロックファイルの確認と作成
if ! ln -s $$ $LOCK_FILE; then
    echo "LOCKED"
    exit 0

このようにロックファイルの確認と作成を別々に行うとアトミックなファイルの扱いにはならないので要注意です。

## ロックファイルの確認
if [ -f $LOCK_FILE ]; then
    echo "LOCKED"
    exit 1
fi

それでは実際にリトライ処理とロック処理を使ってシェルスクリプトを書いてみましょう。 Nagios監視でcheck_httpが何度か失敗し、check_loadでも失敗したら Apache再起動を実行し、1分間はApache再起動が実行されないスクリプトを書いてみます。 これをCronなどで3分毎に実行させればWEBサーバで応答に時間がかかっている時の障害対応を自動化できますね。 ロックファイルを設置して排他制御を行うことで、Apache再起動が何度も実行されないように実装ができます。

#!/bin/bash

set -uo pipefail

HOSTNAME=$(uname -n)
MAIL_ADDRESS_TO="メールアドレス"
LOCK_FILE="$HOME/restart.lock"

RETRY_COUNT=5    # リトライ回数
RETRY_INTERVAL=5 # リトライ間隔5秒
COUNT=0

## ロックファイルの確認
## なければロックファイルの作成
if ! ln -s $$ $LOCK_FILE; then
    echo "LOCKED"
    exit 0
fi

/usr/lib64/nagios/plugins/check_http -w 5 -c 7 -H localhost -u "/" -s "</html>"
RETURN_HTTP=$?

if [[ ${RETURN_HTTP} -ne 0 ]]; then

    ## check_httpの応答判断のリトライ処理
    while [[ $COUNT -ne $RETRY_COUNT ]]
    do
        COUNT=`expr $COUNT + 1`
        sleep $RETRY_INTERVAL
        /usr/lib64/nagios/plugins/check_http -w 5 -c 7 -H localhost -u "/" -s "</html>"
        RETURN_HTTP=$?
        if [[ ${RETURN_HTTP} -eq 0 ]]; then
            exit 0
        else
            continue
        fi
    done

    ## リトライ5回繰り返してもcheck_http監視がOKでないなら以下の再起動処理に進む
    if [[ ${RETURN_HTTP} -ne 0 ]]; then
        /usr/lib64/nagios/plugins/check_load -w 2,2,2 -c 3,3,3
        RETURN_LOAD=$?
        if [[ ${RETURN_LOAD} -ne 0 ]]; then

            echo "/etc/init.d/httpd restart"
            RETURN=$?

            if [[ ${RETURN} -ne -0 ]]; then
                RESULT="Failed"
            else
                RESULT="Success"
            fi

            SUBJECT="${HOSTNAME} httpd restart ${RESULT}"
            BODY="${HOSTNAME} restart apache ${RESULT}"
            echo "${BODY}" | mail -s "${SUBJECT}" ${MAIL_ADDRESS_TO}

            ## 再起動後は1分スリープ後にロックファイルの削除
            sleep 60
            rm -f $LOCK_FILE
        fi
    fi
fi

障害対応の自動化で他によいものがあれば教えて下さい。 また、今回のアトミックなファイルの取扱いの考え方は自分ひとりではなかなか気づかなかったです。

Linuxサーバをセキュアな環境にする

Linuxサーバでセキュアな設定についてまとめてみました。 OSはCentOS6なので古いですが。。 Wordpress周りはまだ調べられてないので どこかでまとめたい。

アドレススキャン対策

ブロードキャスト宛のICMP Echo Requestに対して回答しない

vim /etc/sysctl.conf
net.ipv4.icmp_echo_ignore_broadcasts=1

OSやバージョンの確認

# yum -y install nmap
# nmap -O example.com

telnet example.com 80

まずはこれぐらいはやっておきたいセキュアな設定

  • OSはminimalで必要最小限でインストールする
  • システム管理者用のユーザを作成して利用する
  • yum -y update でパッケージを最新のものを利用する
  • 不要なサービスは停止する
    • audit(コマンドの監査をしない場合)
    • ip6tables(IPv6を使用しない場合)
    • netfs(NFSクライアントを使用しない場合)
    • postfix(SMTPサーバを使用しない場合)
  • rootユーザのログインを禁止する
    • コンソールからのrootログイン禁止
  # echo > /etc/securetty
  • SSHでのrootログイン禁止
  # vim /etc/ssh/ssh_config
  #PermitRootLogin yes

  PermitRootLogin no 
  • SSHを受け付けるPort番号を変更する
  # vim /etc/ssh/ssh_config
  Ports 20022
  • SSHサーバを再起動して設定を反映させる
  • ポートやファイアウォールの設定を確認する
    • netstat -atnp iptables -Ln

OSのセキュリティ

  • GRUBのパスワード設定
    • grub-md5-crypt を実行して出力内容を /boot/grub/grub.conf に書くコム
    • title で始まる行よりも前に password --md5 パスワード の書式で記述する
  • 一般ユーザのログイン管理
    • 不要なユーザのロック usermod -L hoge
    • 不要なユーザのロック解除 usermod -U hoge
    • シェルログインが不要なユーザの作成 useradd -s /sbin/nologon hoge
    • hogeユーザのログインシェルを /sbin/nologin に設定 usermod -s /sbin/nologin hoge
  • コンソールからのrootログイン禁止
    • echo > /etc/securetty
  • su コマンドを使えるユーザを制限
    • /etc/pam.d/su ファイルをrootユーザで開き、 「auth required pam_wheel.so use_uid」という行を追加する
    • これでwheelグループに追加されたユーザのみがsuコマンドを利用できるようになる
    • usermod -G wheel hoge でグループに所属させることが可能
  • sudoコマンドの利用設定
    • visudo を実行し /etc/sudoers を開く
    • hoge ALL=(ALL) ALL ですべてのroot権限が必要なコマンドの実行を許可する
  • Clam AntiVirusのインストール
    • yum install clamav
    • freshclam でウィルスデータベースのアップデート
    • ウィルススキャンはスキャンしたいディレクトリに移動し、clamscanコマンドを実行
    • cd /home して clamscan -r再帰的にディレクトリをスキャンする
    • スキャンしかしないので clamscan --remove で実行時にウィルスの自動削除もしてくれる

メールサーバのセキュリティ

  • ユーザログインの禁止
    • メールサーバを利用するだけのユーザならログインする必要ないのでデフォルトシェルを無効にしておく
    • useradd -s /sbin/nologin newuser

main.cfの主な設定

  • myhostname
    • ホスト名をFQDNで指定
    • myhostname = windsor.example.com
  • mydomain
    • メールサーバのドメイン名を指定
    • mydomain = example.com
  • myorigin
    • メールアドレスの[@]以降が指定されなかった時、デフォルトで保管する値を指定する
    • myorigin = $mydomain
  • inet_interfaces
  • mydestination
    • ローカル配送を行うドメイン名、つまりメールを受け取るドメイン名を指定
    • mydestination = $myhostname, localhost.$mydomain, localhost
  • mynetworks
    • 中継を許可するホストの存在する内部ネットワークアドレスを指定
    • ここに指定したアドレスからのメールは無条件で中継される
    • mynetworks = 192.168.11.0/24, 127.0.0.1/8
  • smtpd_banner
    • SMTPの応答コードに続いて出力されるバナー情報を指定
    • できるだけ情報は少ないほうがいいが、 $myhostname は削除しないようにすること
  • disabled_vrfy_command
    • STMPのVRFYコマンドを禁止にする
    • VRFYコマンドはメールサーバにどのようなアカウントがあるのかを知られる可能性がある
    • disable_vrfy_command = yes
  • smtpd_helo_required
    • SMTP開始時のHELO/EHLOコマンドを必須とするかどうかを指定
    • yesとするとスパムメールの抑制となる
    • smtpd_helo_required = yes
  • smtpd_recipient_restrictions
    • 通常は末尾にrejectを指定する
  • smtpd_sender_restictions
    • メールの送信元アドレスをチェックし、受信を拒否するかどうかを判断

設定の反映

service postfix reload

デフォルト値から変更されている項目のみを表示

postconf -n

FTPサーバのセキュリティ

CentOSではセキュアなvsftpdを使う

vsftpd.confの設定

  • バナーの表示
  • FTP接続確立時のバナーメッセージはftpd_bannerディレクティブで設定
    • ftpd_banner='FTP Login
    • バナーメッセージを格納したファイルを指定するbanner_fileによって無視せれるので注意
  • TCP Wrapperの利用有無
    • tcp_wraller=Yes
    • tcp_wraller=No
  • ユーザリストファイル
  userlist_file=/etc/vsftpd/user_list
  userlist_enable=YES
  userlist_deny=YES
  userlist_file=/etc/vsftpd/user_list
  userlist_enable=YES
  userlist_deny=NO
  • /etc/vsftpd/user_list にはFTP接続にかかわるユーザを登録。
  • userlist_enable=NO となっている場合 /etc/vsftpd/user_list 内に指定されたユーザのみFTP許可されるが、 /etc/vsftpd/ftpusers にユーザ名が指定されている場合はFTPログインを禁止されてしまう
  • ファイルのアップロード
    • FTPサーバをファイル配布用にするならアップロードは不要
    • write_enable=NO でアップロードが禁止になる
  • ユーザの設定
    • Linuxユーザのログインを許可するには local_enable=YES と設定するとLinuxシステムのユーザ名とパスワードを使ってFTPログインが可能になる
  • ホームディレクトリ以外に移動できないように設定
chroot_local_user=YES
#chroot_list_enable=YES
# (default follows)
chroot_list_file=/etc/vsftpd/chroot_list
  • 一部のユーザにはホームディレクトリ以外に移動できないように設定
    • chroot_list_enable=YES と設定して、chroot_list にユーザを列挙する
chroot_local_user=YES
chroot_list_enable=YES
# (default follows)
chroot_list_file=/etc/vsftpd/chroot_list
  • ホームディレクトリ配下のFTPログイン用のサブディレクトリにログインするようにする
  • 匿名FTPを許可の有無
    • デフォルトでは有効になっている
    • anonymous_enable=YES
    • 匿名FTPを使ってファイル配布したい場合は、匿名アカウントでのファイルアップロードを禁止しておく
    • anon_upload_enable=NO
    • write_enbale=NO なら anon_upload_enable=YES でもファイルのアップロードはできない
  • FTPSを使う
    • 証明書と秘密鍵をまとめてpemファイルを作る
cd /etc/pki/tls/certs
cp mycerts.crt mycerts.pem
cat mycerts.key >> mycerts.pem
  • vsftpd.confに以下の行を追加
ssl_enable=YES #SSLの有効化
rsa_cert_file=/etc/pki/tls/certs/mycerts.pem #サーバ証明書秘密鍵のパス
  • 通常のFTP接続も許可するなら以下の設定もする
  • SSL非対応のFTPクライアントからの利用も想定するときは必要
force_local_logins_ssl=NO #FTPログイン時にSSL接続を強制しないように設定
force_local_date_ssl=NO   #FTP転送時にSSL接続を強制しないように設定
  • vsftpdのログ
    • デフォルトでは/var/log/xferlog にファイル転送に関するログが記録される
xferlog_enable=YES
xferlog_std_format=YES
  • ファイル転送のログに加えて、サーバへの接続に関するログも出力されるようにする
xferlog_std_format=NO
vsftpd_log_file=/var/log/vsftpd.log
  • syslogへ出力するようにもできる
syslog_enable=YES

安全なSSHサーバの設定

/etc/ssh/sshd_config の設定

  • Portの変更
    • Port 20022 #portの待受けを22番以外にする
  • Protocolのバージョンを2にする
    • Protocol 2
  • rootログインを許可しない
    • PermitRootLogin no
  • パスワード認証を許可しない
    • PasswordAuthentication no
  • ログイン認証認証の失敗を許容できる回数を変更
    • MaxAuthTries 3

pythonでしたいと思ったことまとめ①

print()でカンマ区切りで表示したい

print(a, b, c, sep=',')

行末の改行を削除したい

string.rstrip()

文字列の末尾部分を除去したコピーを返す。引数 chars は除去される文字集合を指定する文字列。

特定の文字を除去したい

文字列.replace() メソッドを利用します。

以下で改行を除去できる。

remove_enter = jugemu.replace('\n', '')

csvファイルなどのカンマで文字列を分割したい

string.strip(',')

ファイルの中身に追記していきたい

a を使う、 w だと上書きしてしまう。

with open('output/hoge.log', 'a', encoding='utf-8') as f:

現在の時刻を取得する

datetimeモジュールを使う

from datetime import datetime

now = datetime.now()

日時.yearで日時の年の値を数値として取得できる。

print(str(now.year) + '年')

日時.monthで日時の月の値を数値として取得できる。

print(str(now.month) + '月')

日時.dayで日時の日の値を数値として取得できる。

print(str(now.day) + '日')

日時.hourで日時の時の値を数値として取得できる。

print(str(now.hour) + '時')

日時.minuteで日時の分の値を数値として取得できる。

print(str(now.minute) + '分')

日時.secondで日時の秒の値を数値として取得できる。

print(str(now.second) + '秒')

日時のオブジェクトを作成したい

datetime(年, 月, 日, 時, 分, 秒)と指定可能で時分秒を省略すると00:00:00になる。

one_day = datetime(2016, 1, 31, 10, 20, 30)

日時を文字列に変換したい

print(now.strftime('%Y/%m/%d'))  # -> 2016/01/10
print(now.strftime('%Y-%m-%d'))  # -> 2016-01-10
print(now.strftime('%Y年%m月%d日'))  # -> 2016年01月10日

strftime (フォーマット)を利用して変換できる

  • %Y: 西暦(4桁)の10進表記を表します。
  • %m: 0埋めした10進数で表記した月。
  • %d: 0埋めした10進数で表記した月中の日にち。
  • %H: 0埋めした10進数で表記した時 (24時間表記)。
  • %M: 0埋めした10進数で表記した分。
  • %S: 0埋めした10進数で表記した秒。

文字列を日付にしたい

strptime を使う。

from datetime import datetime

day_str = '2018/3/14 12:30:00'
dt = datetime.strptime(day_str, '%Y/%m/%d %H:%M:%S') # 第二引数には変換したい文字列に一致したフォーマットを渡す
print(dt) # 2018-03-14 12:30:00

X日前(後)の日付を表示したい

timedelta を使う

from datetime import datetime
from datetime import timedelta

olympic_day = datetime(2020, 7, 24)
before_3days = now - timedelta(days=3) # 3日前
after_3days = now + timedelta(days=3) # 3日後

Pathを結合したい

os.path.join(a, b, ...) で指定可能

Pathが存在するか確認したい

os.path.exists(path) で指定したpathが存在するか確認できる。

指定したpathがファイルかディレクトリか確認したい

ファイルなら

os.path.isfile(path)

ディレクトリなら

os.path.isdir(path)

指定されたディレクトリー内のファイル名と子ディレクトリー名をリストで返したい

os.walk(top) で返せる。

for文に引数root, dirs, filesを指定すると、そこに各ディレクトリーごとのデータが代入されていく。

import os

def directory_tree(target_path):
    for root, dirs, files in os.walk(target_path) :
        print(root)
        for dir in dirs:
            print('\t', dir)
        for file in files:
            print('\t', file)
  • root には、 ディレクトリのパス が代入。
  • dirs には、 root内に存在するサブディレクトリーのリスト が代入。
  • files には、 root内に存在するファイルのリスト が代入。

AWS Summit Tokyo 2018の聴いたセッションのメモ

聞いたセッションのメモ セッションだけ聞くなら会場ではなくストリーミング配信をみるのが快適ということに気がついてしまった。

オペレーションの最適化

  • ベストプラクティスに基づく準備
  • 適切なモニタリング
  • 適切な運用

  • Well-Architected framework

  • 課題
  • AWS Trusterd Advisor

  • Well-Architected framework クラウドアーキテクチャ設計と運用の考え方とベストプラクティス

  • 運用上の優秀正
  • 実現のための大原則
  • 確認のための質問

  • Operation as codeの実践

  • config,cloudwatc→lambdaで対処するオペレーションの自動化
  • 注釈でドキュメンテーションをする.デプロイしたらplaybookなりが更新される
  • 頻繁に小さく可逆な変更を加える。ワークロード側も変えられる設計にすべき
  • 頻繁に運用手順を見直そう。定期的にGamedayを実施して手順をレビューする。効果があるか、効率化できるポイントを探す。
  • 障害を予想する。机上演習Pre-mortemを実施する。障害シナリオとそのインパクトを理解。対応手順が効果的であることぉ確認、チームがそれらに詳しくなる。
  • イベントと障害対応から学ぶ。うまくいった対応も塩お愛した対応も振り返る。イベントから学んだことをチームで共有する。ログを集めて、可視化しておこう。athenaとか 確認のための質問 運用がビジネスにどんな影響をあたえるのか、運用が客観的に回るっているのか。
  • 運用における優先度を決める要因はなにか
  • どのようにアプリケーション

  • 実際のお客様環境によくある課題

    • タグを管理・活用しているか
    • デプロイ時に強制 tagつけ忘れないようにCloudformationその他のデプロイツールやiAMポリシーで縛る。AWS Service Catalogを利用
    • AWS Configで必須タグが付いているかをチェック。事前定義済ルールのrequired-tagsを利用。対象となるリソースタイプやタグを編集。
    • タグをキーにAWS Sytem Managerを使ってタグを使った管理もできる。リソースグループ化して管理。グループ化したリソースに対して一括処理も可能。
    • タグで頑張りすぎないことも大事。
    • タグの設定指針 awS Tagging Strategyをもよう。
  • メンテナンスの通知は受け取れているのか
    • メールを見逃す。特定の担当者にしか行かない。社内のチャット
    • aWS Personal Health Dashboard
    • リソースに対するメンテやissueが表示されるダッシュボード
    • CloudWatch Eventsと連携してイベントに対するアクションを実行
  • awS HEalth API & AWS Heallth Github repository
    • aws-health-tools を使えばチャットツールやsNS通知に自動化できる
    • 大体の連絡先の活用
      • 合うぃ急の連絡先、操作の連絡先、セキュリティの連絡先
  • 複数のアカウントをまとめて管理する
    • 部門ごとやアプリケーションごとにアカウントを作っているけど、ガバナンスを聞かせられない。
    • 請求統合をおこなっているけど、各アカウンとの利用状況が把握できない
    • 請求統合されたアカウント感でRIを管理はいや
    • AWS Oraganizationによえう請求統合がソリューション
    • Masterアカウントにまとめて一括請求、ボリュームディスカウントもこれに適用
  • AWS Organization
  • 一括請求のみを有効化
  • 複数のAWSアカウントに適用するポリシーを集中管理できる
  • AWSのサービスへのアクセス制御
  • AWSアカウントんお作成と管理の自動化
  • AWS Config連携、AWSFirewall Manager連携、SingleSignOn連携
  • Cost Explorer API
  • Cost Explorer API, CustomReport
  • csvだけでなく、jsonでも取れる
  • aws-cost-explorer-report
  • api使うとお金がかかる
  • Reservide Instanceの共有拒否設定
    • 本当は複数のアカウントでサイズ関係なくうまくばらすこともできるので、共有してほしい。
    • それでも共有したくないなら、RI割引共有の設定で共有したくないなら設定できる
  • AWSサポートは活用できているか
    • 複数のアカウント感でナレッジが共有されず、何度もの同じことを聞く
    • 社内で使っている課題管理システムと連携したい
    • サポートの調査が思うように進まない
  • AWSサポートAPI

    • サポート問い合わせの自動化や問題管理ツールとの連携
    • サポート問い合わせのエクスポート
    • Trusted Advisortとの自動連系
    • case_life_cycle.html, trustedadvisor.html
    • ビジネス以上でないと古ファンクションは使えない
  • サポート問い合わせのベストプラクティス

    • 一つのお問い合わせで関連性のない複数の質問をしない
    • 問い合わせ対象リソースの所有者が起票していることを確認する
    • 適切な緊急度を設定
    • 問いあわせ時には以下の内容を添付
事象の発生時間(タイムゾーン)
事象が発生したリソースの詳細(リージョン・リソースID・名前)
発生した事象の詳細:
SdKやCLIのエラ=であればそのエラー出力
可能であればAWSのCLIのの場合は--debug
  • AWS Trusted Advisor
    • リアルタイムガイダンスを提供してくれる
    • AWS Trusted AdvisorとCloudWatchの連携
    • AWS Limit Monitor 

Well-Architectを使って準備し、Trusted Advisorを使って環境を見直しておこう

Fargate

コンテナのメリット - パッケージング - 配布 - イミュータブルインフラストラクチャ

アプリケーション開発に集中

1台のサーバでDockerコンテナを使うのは簡単だが、サーバが増えると大変

  • ECS
    • コンテナはタスクという単位でタスクの配置やスケールのマネージド 動作イメージ ECS EC2インスタンスとタスクがある。これを提供してくれる ECSアーキテクチャの整理 Taskアプリケーションを構成する1つ以上のコンテナ(群)実行単位 Container Instance Taskが起動するEC2インスタンス Service ロングランニングアプリ用スケジューラTaskの数 Cluster

Fatgateはインスタンス管理不要  Fargateの上にTaskが起動。EC2インスタンスを増やすことなく仮想サーバー側の管理が不要 Taskだけがスケールされる

Codecommit codebuld ECR Fargate ECK

コンテナ管理にひつようなもの サービスディスカバリ Route53,ALB ロギング、モニタにリング CloudWatch セキュリティ IAM VPC パラメータストア スケジューリング タスクプレースメント

サービスディスカバリ サービス同士が疎結合になるように構成するのがベストプラクティス、生存時間が短いので各サービスが自身が接続する先を見つける必要がある ECSではALBと連携 ALBをエンドポイントとしてつかう ECAサービスディスカバリの利用 名前解決で、ALBを使わずRoute53のDNA名で自動的に登録することができる

ロギングとモニタにリング コンテナのアプリは外でSTDOUTに出力する コンテナインスタンスとかリソースよりサービスを管理するのがよい

CloudWatch awslogsでCloudWathLogsに送信される 1つのTask内に2種類のコンテナを定義する アプリケーションコンテナ ロギング用のコンテナ 一次共有ボリュームにログを出力しロギングコンテナがcloudwatch logsに転送 ロギング処理を別コンテナにまかせる サイドカー構成

Fargateはコンテナにインスタンスの管理は不要でタスクのみ。

Fargateより、より細やかなECSクラスタ管理をつげんできる ECSクラスタの状態変化をリアルタイムに検出する 監視システムにEventログを保存してくらすたの 状態を可視化する 特定のタスクが落ちたときに気づける状態変化に気づける

EventStreamによるリアルタイムなイベント検知 ECSクラスタの状態変化を通知する Evento通知の到達性は少なくとも1回

セキュリティ アクセス権限の考え方 IAMロールポリシーを使ってクラスターに対する権限や アプリケーションの権限、どのタスクがどのAWSリスースにアクセスできるか タスク管理に関する権限 ECRからのイメージのpull Clone

Taskに関するセキュリティ Task単位でIAMロールを割り当て Task単位でSecurity Groupを割り当て

Taskでどのようにパスワードをわたすのか Parameter Store,Secrets Managerを使ってKMSに置いてTaskに設定されたIAMロールの権限に応じて秘密情報を取得

スケジューリングとタスクプレースメント 管理が必要となる2つのレイヤー - CountainerInstanceのスケーリング Fargateは考慮不要。 - Taskのスケーリング  アプリケーションオートスケーリングを利用することでTaskのオートスケーリングを実現可能

EC2インスタンス使うときのスケールイン タスクの数が減る。→コンテナインスタンスを削除

Fargateのスケールイン

タスクのみがスケールインすればよい。

Target Trackingを利用したアプリケーションオートスケーリング メトリクスに対してターゲット値を設定 その値に近づくようにアプリケーションオートスケーリングが自動的にTaskを調整

Taksの配置を管理するには Taskga可動するために必要な条件は 必要なCPU、メモリ、ポートが割り当て可能化

どのようにTaskを配置したいのか 特定のAZに置く 特定のインスタンスタイプのみ

Task配置に関するロジック CPUメモリーポートとAZ、インスタンスタイプ、AMI ID 配置戦略を満たすか 最終的なTaskの配置場所を決定

タスク配置例

コンテナインスタンスのroll out タスクdefinitionの更新時に新しいAMI IDを利用してコンテナインスタンスに配置する制約をつける 1ホスト1コンテナ distinctinstqnce constaraint + event stream + lambda

# 202-service-mesh

Istioも0.8がリリースされたので、Istioの公式ドキュメントからサンプルアプリケーションを動かしたほうがよいです。 それでは続きをしていきます。

Service Mesh integration with Kubernetes

Service MeshコンポーネントをKubernetesクラスタに統合する方法を示します。 Service Meshは、マイクロサービス間の通信を管理するレイヤーで、クラウドネイティブアプリケーションにとって普及している サービス検出、負荷分散、自動再試行、回路遮断器、収集要求/応答メトリック、トレース情報などの重要な機能があります。

2つのよく知られているサービスメッシュ統合について検討します。

  • Linkerd
  • Istio

こちらもあわせて読みたいです。 Service meshとは何か

LinkerdとKubernetesの使用

Linkerdは、HTTP、Thrift、Mux、HTTP/2、およびgRPC経由でトラフィックをルーティングおよびロードバランスするレイヤ5/7のプロキシです。 それはFinagle(Twitterで構築)に基づいており、2017年1月にlinkerdがKubernetesとともにCNCFのメンバーになりました。

Linkerdは、回路破壊、待ち時間を考慮したロードバランシング、最終的に一貫した(「アドバイザリ」)サービス発見、デッドライン伝播、トレーシングと計測など、幅広い強力なテクニックを使用して、可視性、制御、および信頼性をアプリケーションに追加します。 今回Kubernetesクラスターで実行されているサービスの可視性に焦点を当てます。 k8sクラスタにlinkerdをインストールし、いくつかの簡単なマイクロサービスを実行し、linkerdが成功率、要求量、待ち時間などのトップラインサービスメトリクスをどのように取得するかを行います。 Linkerdの次のような機能をいくつか見ていきます。

  1. Service Mesh内のトラフィックの監視
  2. リクエストごとのルーティング

Kubernetesクラスタを作成する

3つのマスターノードと5つのワーカーノードを持つクラスタを用意

Linkerdをインストールする

kubectl でインストールします。 デフォルトのKubernetes名前空間で動作するDaemonSet(つまり、ホストごとに1つのインスタンス)としてlinkerdがインストールされます。

kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/\
k8s-daemonset/k8s/linkerd.yml
configmap "l5d-config" created
daemonset "l5d" created
service "l5d" created

linkerd(l5dという名前の)ポッドが実行されていることを確認します。

$ kubectl get pods
NAME        READY     STATUS    RESTARTS   AGE
l5d-b8pht   2/2       Running   0          48s
l5d-jlpcl   2/2       Running   0          48s
l5d-kl98n   2/2       Running   0          48s
l5d-mp4vn   2/2       Running   0          48s
l5d-nnxqz   2/2       Running   0          48s

これは、5ワーカーノードクラスタからの出力です。 linkerdサービスが実行されていることを確認します。

$ kubectl get svc
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP        PORT(S)                                        AGE
kubernetes   ClusterIP      100.64.0.1      <none>             443/TCP                                        5m
l5d          LoadBalancer   100.67.155.17   a8ac6926260d4...   4140:32573/TCP,4141:31565/TCP,9990:30298/TCP   2m

linkerdサービスの詳細もみてみます。

$ kubectl describe svc/l5d
Name:                     l5d
Namespace:                default
Labels:                   <none>
Annotations:              kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"l5d","namespace":"default"},"spec":{"ports":[{"name":"outgoing","port":4140},{...
Selector:                 app=l5d
Type:                     LoadBalancer
IP:                       100.70.56.141
LoadBalancer Ingress:     abf44db7dbe1211e7a7d00220684043f-1319890531.eu-central-1.elb.amazonaws.com
Port:                     outgoing  4140/TCP
TargetPort:               4140/TCP
NodePort:                 outgoing  30108/TCP
Endpoints:                100.96.3.2:4140,100.96.4.2:4140,100.96.5.4:4140 + 2 more...
Port:                     incoming  4141/TCP
TargetPort:               4141/TCP
NodePort:                 incoming  31209/TCP
Endpoints:                100.96.3.2:4141,100.96.4.2:4141,100.96.5.4:4141 + 2 more...
Port:                     admin  9990/TCP
TargetPort:               9990/TCP
NodePort:                 admin  32117/TCP
Endpoints:                100.96.3.2:9990,100.96.4.2:9990,100.96.5.4:9990 + 2 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:
  Type    Reason                Age   From                Message
  ----    ------                ----  ----                -------
  Normal  CreatingLoadBalancer  3m    service-controller  Creating load balancer
  Normal  CreatedLoadBalancer   3m    service-controller  Created load balancer

Linkerdの管理ページ(ELB:9990)に行ってインストールを確認することができます。 ELB DNSが利用可能になるには、1〜2分かかります。 ロードバランサエンドポイントにアクセスする際に問題が発生した場合は、ファイアウォールまたはVPNがポート9990へのアクセスを妨げている可能性があります。

LINKERD_ELB=$(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}")
open http://$LINKERD_ELB:9990

openコマンドがだめだったらブラウザからURLを入力していけます。

ダッシュボードを確認しましょう。

サンプルのmicroservicesアプリケーションをインストールする

linkerd examplesリポジトリに「hello」と「world」という2つのマイクロサービスアプリがあります。 それらはお互いに通信してリクエストを完了します。このコマンドを実行すると、デフォルトの名前空間にこれらのアプリがインストールされます。

$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/\
k8s-daemonset/k8s/hello-world.yml
replicationcontroller "hello" created
service "hello" created
replicationcontroller "world-v1" created
service "world-v1" created

次のコマンドを実行してトラフィックを生成します。

http_proxy=$LINKERD_ELB:4140 curl -s http://hello

Linkerdは、提供されているリクエスト数、接続数、豊富なデータを表示します。

Install linkerd-viz

linkerd-vizは、PrometheusとGrafanaに基づく監視アプリケーションです。 k8sクラスタにインストールされているリンカーインスタンスとサービスを自動的に検索できます。

$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-viz/master/k8s/linkerd-viz.yml
replicationcontroller "linkerd-viz" created
service "linkerd-viz" created

linkerd-viz ELBを開いてダッシュボードを表示できます

LINKERD_VIZ_ELB=$(kubectl get svc linkerd-viz -o jsonpath="{.status.loadBalancer.ingress[0].*}")
open http://$LINKERD_VIZ_ELB

前の例と同様に、ELB DNSが利用可能になるには1〜2分かかることがあります。

リクエストごとのルーティング

上記の例で使用したのと同じ「hello-world」アプリケーションを使用しますが、今回は「world」マイクロサービスのバージョン2をデプロイし、要求ごとにリクエストでv1かv2を使用するかどうかを指定します 「hello-world」アプリケーションをまだ配備していない場合は、今すぐデプロイしてください。

kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/ \
k8s-daemonset / k8s / hello-world.yml

以前のリンカーのDaemonsetを削除してください。ConfigMapを更新して新しいものをインストールします

$ kubectl delete ds/l5d

アプリケーションに外部からアクセスできるようにlinkerd ingressをデプロイします。

$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/\
k8s-daemonset/k8s/linkerd-ingress.yml
configmap "l5d-config" configured
daemonset "l5d" configured
service "l5d" configured

今、バージョン2の「world」マイクロサービスを導入してください。

$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/\
k8s-daemonset/k8s/world-v2.yml
replicationcontroller "world-v2" created
service "world-v2" created

サービスのv1にリクエストを送信します。それは 'Hello world'と返信する必要があります。

INGRESS_LB=$(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}")
curl -H 'Host: www.hello.world' $INGRESS_LB

1〜2分後、次のHello worldように返信する必要があります。

Hello (100.96.1.12) world (100.96.1.14)

要求のヘッダーを変更して、サービスのv2に要求を送信します。

Hello (100.96.1.11) earth (100.96.2.14)

次のように「Hello Earth」と返信する必要があります

Hello (100.96.1.11) earth (100.96.2.14)

これは、worldサービスのv1とv2がクラスタ内で実行されていることを示しています。 また、要求ヘッダーに個々の要求をルーティングするサービスのバージョンを指定できます。 これでおしまい! linkerdの設定ファイルをlinkerdの例で見ることができます。

Cleanup

インストールしたコンポーネントの削除

kubectl delete -f install/kubernetes/addons/servicegraph.yaml
kubectl delete -f install/kubernetes/addons/prometheus.yaml
kubectl delete -f install/kubernetes/istio-auth.yaml
kubectl delete -f install/kubernetes/istio.yaml
./samples/bookinfo/kube/cleanup.sh
kubectl get all
kubectl get all --namespace istio-system

IstioとKubernetesの併用

Istioは、HTTP、WebSocket、HTTP/2、gRPC経由でトラフィックのルーティングとロードを行い、MongoDBやRedisなどのアプリケーションプロトコルをサポートするレイヤ4/7プロキシです。 IstioはEnvoyプロキシを使用して、サービスメッシュ内のすべての着信/発信トラフィックを管理します。 EnvoyはLyftによって建設され、2017年9月EnvoyはKubernetesと共にCNCFのメンバーになった。 Istioは、GoogleIBMLyftの共同開発です。

Istioには、A/Bテスト、段階的/カナリ・ロールアウト、障害回復、回路遮断器、レイヤー7ルーティング、ポリシー施行(すべてEnvoyプロキシによって提供される)など、アプリケーションコードの外にあるさまざまなトラフィック管理機能があります。 また、IstioはMixerコンポーネントを使用して、ACL、レート制限、クォータ、認証、要求トレース、テレメトリ収集をサポートしています。 Istioプロジェクトの目標は、アプリケーションの変更を必要とせずにトラフィック管理とマイクロサービスのセキュリティをサポートすることです。 これは、すべてのネットワーク通信を処理するside-carをポッドに注入することで行います。

この演習では、Istioが提供する次のような機能をいくつか見ていきます。

  • 加重ルーティング
  • 分散トレース
  • 相互TLS認証

Kubernetesクラスタを作成

3つのマスターノードと5つのワーカーノードを持つクラスタを使用

Istioをインストールする

Istioは、Envoy(side-car proxy)のサイドカーをポッドに挿入するためにマシンにバイナリをインストールする必要があります。 つまり、Istioをダウンロードする必要があります。Istioは自動的にside-carを注入することもできます。 詳細はIstioクイックスタートをご覧ください

curl -L  https://git.io/getLatestIstio | sh -
cd istio-*
export PATH=$PWD/bin:$PATH

これで、istioctl CLI を実行できるはずです

$ istioctl version
Version: 0.8.0
GitRevision: 6f9f420f0c7119ff4fa6a1966a6f6d89b1b4db84
User: root@48d5ddfd72da
Hub: docker.io/istio
GolangVersion: go1.10.1
BuildStatus: Clean

kubectlを使用してIstioをインストールします。 これにより、Istioが独自の名前空間 istio-system にインストールされます。 上記の手順でIstioをダウンロードしたディレクトリに移動します。 side-car 間の相互TLS認証を有効にせずにIstioをインストールします。 既存のアプリケーションを持つクラスタ、Istioside-carを持つサービスが他の非Istio Kubernetesサービスと通信できる必要があるアプリケーション、生存度と準備性のプローブ、ヘッドレスサービス、またはStatefulSet を使用するアプリケーションには、このオプションを選択します。

kubectl apply -f install/kubernetes/istio-demo.yaml

Istioがインストールされていることを確認します。 Istioは独自の名前空間にインストールされています。

$ kubectl get all --namespace istio-system
NAME                   DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/istio-ca        1         1         1            1           1m
deploy/istio-egress    1         1         1            1           1m
deploy/istio-ingress   1         1         1            1           1m
deploy/istio-mixer     1         1         1            1           2m
deploy/istio-pilot     1         1         1            1           1m

NAME                          DESIRED   CURRENT   READY     AGE
rs/istio-ca-2651333813        1         1         1         1m
rs/istio-egress-2836352731    1         1         1         1m
rs/istio-ingress-2873642151   1         1         1         1m
rs/istio-mixer-1999632368     1         1         1         2m
rs/istio-pilot-1811250569     1         1         1         1m

NAME                   DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/istio-ca        1         1         1            1           1m
deploy/istio-egress    1         1         1            1           1m
deploy/istio-ingress   1         1         1            1           1m
deploy/istio-mixer     1         1         1            1           2m
deploy/istio-pilot     1         1         1            1           1m

NAME                                READY     STATUS    RESTARTS   AGE
po/istio-ca-2651333813-pcr1f        1/1       Running   0          1m
po/istio-egress-2836352731-sfj7j    1/1       Running   0          1m
po/istio-ingress-2873642151-vzfxr   1/1       Running   0          1m
po/istio-mixer-1999632368-nz0mw     2/2       Running   0          2m
po/istio-pilot-1811250569-mmfdg     1/1       Running   0          1m

サンプルアプリケーションのデプロイ

私たちは、Istioチームが開発したサンプルアプリケーションを使用して、Istioの機能をチェックします。 Envoy(side-car proxy)をアプリケーションに手動で注入する方法を使用しているので、以下のように istioctl を使用する必要があります。

kubectl apply -f <(istioctl kube-inject -f samples/bookinfo/kube/bookinfo.yaml)

これによりBookInfoアプリケーションが展開されます。 これは4つのマイクロサービスで構成され、それぞれが異なる言語で書かれており、共同して書籍の製品情報、書籍の詳細、書籍のレビューを表示します。 各マイクロサービスは専用ポッドに配置され、エンボイプロキシはポッドに注入されます。 Envoyは、ポッド間のすべてのネットワーク通信を引き継ぐようになります。 すべてのコンポーネントがインストールされていることを確認しましょう

$ kubectl get all
NAME                    DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/details-v1       1         1         1            1           3h
deploy/productpage-v1   1         1         1            1           3h
deploy/ratings-v1       1         1         1            1           3h
deploy/reviews-v1       1         1         1            1           3h
deploy/reviews-v2       1         1         1            1           3h
deploy/reviews-v3       1         1         1            1           3h

NAME                           DESIRED   CURRENT   READY     AGE
rs/details-v1-39705650         1         1         1         3h
rs/productpage-v1-1382449686   1         1         1         3h
rs/ratings-v1-3906799406       1         1         1         3h
rs/reviews-v1-2953083044       1         1         1         3h
rs/reviews-v2-348355652        1         1         1         3h
rs/reviews-v3-4088116596       1         1         1         3h

NAME                    DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/details-v1       1         1         1            1           3h
deploy/productpage-v1   1         1         1            1           3h
deploy/ratings-v1       1         1         1            1           3h
deploy/reviews-v1       1         1         1            1           3h
deploy/reviews-v2       1         1         1            1           3h
deploy/reviews-v3       1         1         1            1           3h

NAME                                 READY     STATUS    RESTARTS   AGE
po/details-v1-39705650-vc2x0         2/2       Running   0          3h
po/productpage-v1-1382449686-b7frw   2/2       Running   0          3h
po/ratings-v1-3906799406-11pcn       2/2       Running   0          3h
po/reviews-v1-2953083044-sktvt       2/2       Running   0          3h
po/reviews-v2-348355652-xbbbv        2/2       Running   0          3h
po/reviews-v3-4088116596-pkkjk       2/2       Running   0          3h

すべてのコンポーネントが正常にインストールされている場合は、製品ページを表示できるはずです。 これには、最初にIngressが作成されるのに1〜2分かかる場合があります。 また、Ingressが公開するサービスに接続する場合もあります。 予約商品ページが表示されるまでブラウザを更新してください。

ISTIO_INGRESS=$(kubectl get -n istio-system svc istio-ingressgateway -o jsonpath="{.status.loadBalancer.ingress[0].*}")      
open http://$ISTIO_INGRESS/productpage

加重ルーティング

サンプルアプリケーションは非常に便利です。 上記のコマンドkubectl get all では、複数の「レビュー」マイクロサービスのバージョンが展開されていることがわかります。 重み付けされたルーティングを使用して、トラフィックの50%をレビューマイクロサービスのv3にルーティングします。 v3ではレビューごとに星が表示されますが、v1では表示されません。 次に、bookinfoの商品ページに数回問い合わせを行い、評価のために星を含むレビューページが表示された回数を数えます。 これは、レビューページのv3にルーティングされていることを示します。

$ kubectl create -f samples/bookinfo/kube/route-rule-all-v1.yaml
routerule "productpage-default" created
routerule "reviews-default" created
routerule "ratings-default" created
routerule "details-default" created
$ kubectl replace -f samples/bookinfo/kube/route-rule-reviews-50-v3.yaml
routerule "reviews-default" replaced

エンボイプロキシは、異なるバージョンのマイクロサービスへのルーティングをラウンドロビンしません。 したがって、製品ページに2回アクセスすると、1つのリクエストでレビューのv1が使用される可能性は低くなり、2回目のリクエストではv3が使用されます。 しかし、100件を超えるリクエストのうち50%はレビューページのv3にルーティングする必要があります。以下のスクリプトを使用してこれをテストできます。 mfileこれを実行する前に、現在のフォルダで呼び出されているファイルがないことを確認してください。 このスクリプトcurlはbookinfo製品ページに100回のリクエストを送信します。 約30秒かかる場合があり、レスポンスに星があるものを数えます。製品ページhtmlには2人のレビューアが含まれているため、2人で区切られています。 curlsレビューページで「完全な星」を返しました。100本のカールのうち、50本は「完全な星」を含むと予想しています。

ISTIO_INGRESS=$(kubectl get -n istio-system svc istio-ingressgateway -o jsonpath="{.status.loadBalancer.ingress[0].*}")   
for((i=1;i<=100;i+=1));do curl  -s http://$ISTIO_INGRESS/productpage >> mfile; done;
a=$(grep 'full stars' mfile | wc -l) && echo Number of calls to v3 of reviews service "$(($a / 2))"

出力は次のように表示されます。

Number of calls to v3 of reviews service 72

最後に、一時ファイルを削除します。

rm mfile

この重み付きルーティングは、Istioがバージョン間のトラフィックをルーティングし、トラフィックの負荷に対応するためにレビューマイクロサービスをスケーリングすることによって処理されました。

分散トレース

Istioは各サイドポッドにside-car proxyとして配備されています。 つまり、マイクロサービス間のすべてのトラフィックフローを表示および監視し、メッシュトラフィックのグラフィカルな表現を生成できます。 前の手順でデプロイしたbookinfoアプリケーションを使用してこれを実演します。

まず、Prometheusをインストールします。 これはIstioから必要なメトリクスを取得します

$ kubectl apply -f install/kubernetes/addons/prometheus.yaml
configmap "prometheus" created
service "prometheus" created
deployment "prometheus" created

Prometheusが動作していることを確認してください.

$ kubectl -n istio-system get svc prometheus
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
prometheus   ClusterIP   100.69.199.148   <none>        9090/TCP   47s

Servicegraphアドオンをインストールします。 Servicegraphは、Istioからのメッシュトラフィックフローの詳細を取得するPrometheusをクエリします。

$ kubectl apply -f install/kubernetes/addons/servicegraph.yaml
deployment "servicegraph" created
service "servicegraph" created

Servicegraphが展開されたことを確認します。

$ kubectl -n istio-system get svc servicegraph
NAME           TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
servicegraph   ClusterIP   100.65.77.1   <none>        8088/TCP   5m

bookinfoアプリケーションへのトラフィックを生成。

ISTIO_INGRESS=$(kubectl get ingress gateway -o jsonpath="{.status.loadBalancer.ingress[0].*}")
open http://$ISTIO_INGRESS/productpage

サービスグラフUIを表示する - ポートフォワーディングを使用してこれにアクセスします。

kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=servicegraph -o jsonpath='{.items[0].metadata.name}') 8088:8088 &
open http://localhost:8088/dotviz

このような形の分散トレースが表示されます。 Servicegraphが利用可能になるまで数秒かかる場合がありますので、応答がない場合はブラウザを更新してください。

side-car 間の相互TLS認証を有効にする

Istio-auth は、サイドキャストプロキシ間の相互TLS通信を強制することによって、マイクロサービス間の安全な通信を可能にします。 これを実装するのは簡単です。 相互TLSを有効にしてIstioをインストールするだけです。

上記の例を実行した場合は、Istioをアンインストールします。

kubectl delete -f install/kubernetes/istio.yaml

Authモジュールを有効にして再インストールする. デフォルトでは、Istioをインストールし、side-car 間で相互TLS認証を実施します。 このオプションは、新しく展開されたワークロードでIstio-side-car がインストールされていることが保証されている新しいkubernetesクラスタでのみ使用してください。

kubectl apply -f install/kubernetes/istio-demo-auth.yaml

マイクロサービス間のすべてのトラフィックが暗号化されます。

Cleanup

インストールされているコンポーネントを削除する

kubectl delete -f install/kubernetes/addons/servicegraph.yaml
kubectl delete -f install/kubernetes/addons/prometheus.yaml
kubectl delete -f install/kubernetes/istio-auth.yaml
kubectl delete -f install/kubernetes/istio.yaml
./samples/bookinfo/kube/cleanup.sh

default 上記のクリーンアップスクリプト名前空間を受け入れます。

Istioを削除すると、出力にエラーが表示されることがあります。 これらはインストールしていないIstioコンポーネントに関連しているので、これらについては心配する必要はありません。 すべてがアンインストールされたことを確認するには、次のようにします。 IstioまたはBookinfoのコンポーネントは残る必要はありません。

kubectl get all
kubectl get all --namespace istio-system

リソースグラフの見方

cactiとgrafanaのグラフの見方について調べました。

cactiグラフの見方

まずグラフを見るときは長いスパンでの確認と単位に気を付けること

サーバステータス・OS系

  • CPU Utilization
    • コアごとにCPU使用率を表示させる
  • Context Switches
    • サーバ側がカウンタなので、前回の処理からの差分を描画
    • 「Context Switches」はCPUでの処理対象プロセスなどの切り替え回数を示している。
    • プロセスの並列度が高く単位時間あたりの処理が多いシステムでは、値が大きくなる。
  • Forks
    • サーバ側がカウンタなので、前回の処理からの差分を描画
    • 「Forks」はプロセス処理であるForkの実行回数を示している。
    • プロセスの生成はCPUコストのかかる処理。
    • このグラフの値が常時大きい場合には、無駄なプロセス生成や外部プロセス呼び出しをしていないか、 必要だとしても、それをライブラリ呼び出しに変更できないか要検討
  • Interrupts
    • サーバ側がカウンタなので、前回の処理からの差分を描画
    • 「Interrupts」はネットワーク送受信などによる割り込みの数
    • ネットワーク送受信が多かったりすると増える。
  • Load Average
    • サーバ側の値をそのまま表示
    • 1 Minute Average:データ取得時点から直近1分間の実行街キュー数の平均値
    • 5 Minute Average:データ取得時点から直近5分間の実行街キュー数の平均値
    • ロードアベレージの値を読み解くのが難しいため、性能面の指標としては使うことができない。
    • 値の変化は状況の変化を表している。 負荷の指標としては、そのシステムが提供するサービス(HTTPなどの)応答時間をチェックする 性能の限界を越えると一気にロードアベレージの値が跳ね上がる。 急激な変化があった場合には、他の指標と見比べて、ボトルネックが発生していないか確認する。 ロードアベレージが高いから処理が遅くなることはありえず、処理がおそくなっていることがロードアベレージとして現れるという指標
  • Memory
    • Used Real:実メモリ使用量
    • Buffers:バッファとして利用中のメモリ容量
    • Cache:キャッシュとして利用中のメモリ容量
    • Unused Real:仮想メモリ使用量
    • Used Swap:Swapの読み書き量
    • Total Real:全メモリ容量
  • ディスク関連のグラフ
    • Disk Elapsed IO Time (ms)
    • サーバ側がカウンタになっているので、前回の処理からの差分を描画
    • IO Time:I/O時間
    • IO Time Weighted:I/O総所要時間
    • 「IO Time」に対して「IO Time Weighted」が大きい場合、ディスクI/Oに対して性能が不足している。
  • Disk Operations
    • サーバ側がカウンタになっているので、前回の処理からの差分を描画
    • Reads:ディスク読み込み要求数
    • Reads Merged:マージされたディスク読み込み要求数
    • Writes:ディスク書き込み要求数
    • Writes Merged:マージされたディスク書き込み要求数
    • 「Reads」+「Writes」=「Io Ops
    • 「Merged」はmergeされたI/O要求数
    • I/O処理を効率化するためにサーバがI/O要求をまとめることがある。
    • 基本的なI/O要求数は「Reads」と「Writes」で確認でき、「Merged」を見つけることで効率化の程度が確認できる
  • Disk Read/Write Time
    • サーバ側がカウンタになっているので、前回の処理からの差分を描画
    • Time Spent Reading 読み込みに要した時間
    • Time Spent Reading 書き込みに要した時間
    • Disk Sectors Read/Written
    • Sectors Read:読み込みセクタ数
    • Sectors Written:書き込みセクタ数
  • Disk Space
    • Used:利用中のディスク容量
    • Total:全容量
  • TCP Connection
    • サーバの値をそのまま表示
    • 「ESTABLISHED or CLOSE-WAIT」「ESTABLISHED」ステータスのソケット数、「CLOSE_WAIT」ステータスのソケット数
    • ESTABLISHED や CLOSE-WAITはプロセスがアタッチされた状態のため、
    • この数が大きいということはサーバ側の処理の並列数が高い
  • Network Traffic
    • サーバ側がカウンタで、前回の処理からの差分を描画
    • Inbound Inbound Traffic(受信)
    • Outbound Outbound Traffic(送信)
  • ネットワーク帯域利用量
    • 数値が頭うちになっていれば、ネットワーク帯域不足
  • APC cache purges
    • Alternative PHP Cache (APC) は、PHP の実行コードをキャッシュする仕組み
    • ファイルキャッシュと、ユーザのキャッシュでAPCがキャッシュを削除したサイズ
  • APC file cache hits and misses
    • Hits:ファイルキャッシュのヒット率
    • Misses:ファイルキャッシュのミス率 キャッシュヒットとは、命令処理に必要なデータがキャッシュメモリに存在し、キャッシュメモリからデータを読み込むことができることです。 またキャッシュミスとは、命令処理に必要なデータがキャッシュメモリに存在せず、キャッシュメモリからデータを読み込むことができないことです。 キャッシュミスの場合、メインメモリ等にデータを探しに行きます。
  • APC file cache memory
    • OP CODE Cache: opcodeキャッシュにキャッシュされたファイル
    • User Itmes Cache:ユーザーおよびアイテムがキャッシュ
    • Memory Limit:APCキャッシュメモリの上限
  • APC user cache hits and misses
    • Hits:ユーザキャッシュのヒット率
    • Misses:ユーザキャッシュのミス率
  • Apache Bytes
    • Bytes Sent:送信バイト数
    • Apacheが送信したバイト数
  • Apache CPU Load
  • Apache Requests
    • 発生したリクエスト数
  • Apache Scoreboard
    • Apacheリクエストの管理状態を表示 pacheで実際にHTTPリクエストを処理するエンティティを「スロット」と呼ぶ。そして、スロットを集めたApacheのリクエスト処理の管理状態の記録をスコアボードと呼ぶ。 スコアボードは、処理系にもよるが、大抵はOSの共有メモリを利用しており、リクエスト処理をするプロセス間で共有可能な記憶領域となっている。 共有メモリが利用できない一部の旧式な処理系では、ファイルで管理するらしい。 [Apacheスコアボードの監視とチューニング ](http://www.ginnokagi.com/2008/03/apache.html
  • Apache Workers
    • Idle workers:アイドルなプロセス数
    • Busy workers:ビジーなプロセス数 負荷が高い時間帯にIdleWorkersがゼロになる率が高い場合はMinSpareServersの値が小さいということになります。もっと大きい値にして、プロセス生成のオーバーヘッドを下げてやる必要があります。 負荷が高い時間帯にIdleWorkersが大きな値を示している場合はプロセス=メモリーが無駄使いされていることになりますから、MinSpareServersをもっと小さい値にします。その分のメモリーをバッファキャッシュ等に回してほうがよい。 mod_statusでapacheの稼働状況を記録する

MySQL

ステータス関連のグラフ

  • MySQL Command Counters※Max 500
    • Questions:総ステートメント実行回数
    • Com xxx :xxxステートメントを実行した回数 SELECT文が実行された場合は「Com Select」がカウントアップ。 ただし、クエリキャッシュにヒットした場合は「Questions」に計上されるが「Com Select」には計上されない このグラフからのSQLの量・内容・集中傾向を確認することで、チューニングの手がかりになる。
  • MySQL Connections※Max 120
    • サーバ側の値をそのまま表示しているもの
    • Max Connections:設定上の最大コネクション数
      • 起動して以来の最大同時コネクション数
    • Max Used Connections:最大同時接続コネクション数
    • Threads Connected:接続中のコネクション数
      • 同時接続数 コネクションプールを使うと「Threads Connected」は多いものの。Connections」は少なくなる。
    • サーバ側がカウンタになっていて、前回の処理からの差分を描画しているもの
    • Aborted Clients:接続できたが切断されたコネクションの数
      • 接続が正常にできていたものの、「WAIT_TIMEOUT」や「INTERACTIVE_TIMEOUT」などにより、
      • 切断されたコネクションの数
    • Aborted Connects:接続できなかったコネクションの数
    • Connections:接続されたコネクションの数
  • MySQL Files and Tables※Max 2.0k
    • サーバ側の値をそのまま表示
    • Table Cache:テーブルキャッシュサイズ
    • Open Tables:開いたことのあるテーブル数
    • Open File:開いたことのあるファイル数
    • Opend Tables:今開いているテーブル数
  • MySQL Handlers※Max 600k
    • サーバ側がカウンタになっているので、前回からの処理からの差分を描画
    • Handler Write:「INSERT」の要求回数
    • Handler Update:「UPDATE」の要求回数
    • Handler Delete:「DELETE」の要求回数
    • Handler Read First:最初のエントリがインデックスから読み込まれた回数
      • この項目が多いときは、フルスキャンが多いかもしれないので要確認
    • Handler Read Key:キー(インデックス)に基づく読み込み回数
      • この項目が多いときは、適切にインデックスが付与されている証拠なのでいい傾向
    • Handler Read Next:キー順序での次レコードの読み込み要求回数
    • Handler Read Prev:キー順序での前レコードの読み込み要求回数
      • NextとPrevは範囲指定をしてインデックスカラムをスキャンした場合に増える
    • Handler Read Rnd:固定位置に基づくレコードの読み込み要求回数
      • SQL結果をソートすることが多い場合に増える。テーブルスキャンが多いか、インデックスなしの「JOIN」が多く、インデックスが適切に付与できていない可能性がある。
    • Handler Read Rnd Next:データファイルでの次レコードの読み込み要求回数
      • この項目が多いときは、テーブルスキャンが多く、インデックスが適切に付与できていない可能性あり
  • MySQL Network Traffic※Max i.0M
    • サーバ側がカウンタになっているので、前回の処理からの差分が描画
    • Bytes Sent:MySQLからクライアントに送信したデータ量
    • Bytes Received:MySQLがクライアントから受信したデータ量。 単位がbytesなので注意(bitではない)通常はSentが圧倒的に多いが、SQLが長い、または投入データが大きい場合はReceivedも大きくなる。
  • MySQL Processlist※Max 4.0
    • サーバ側の値をそのまま表示
    • State Closing Tables:データをディスクにフラッシュしテーブルをクローズ中
    • State Copying To tmp Table:メモリ上の一時テーブルにデータをコピー中
    • State End:データ操作処理中
      • SQL文の「ALERT TABLE」、「CREATE VIEW」、「DELETE」、「INSERT」、「SELECT」、「UPDATE」の終了処理(クリーンアップ前)の状態
    • State Freeing Items:アイテム開放処理中
      • クリーンアップの次の工程で、クエリキャッシュを含めたいくつかのアイテムを開放している状態です。
    • State Init:SQL実行のための初期化中
      • SQL文の「ALERT TABLE」、「CREATE VIEW」、「DELETE」、「INSERT」、「SELECT」、「UPDATE」の実行準備中の状態
      • 具体的にはバイナリログやInnoDBログのフラッシュ、クエリキャッシュのクリーンアップ等を実行しています。
    • State Locked:ロックされている(ロック開放待ち)
      • 「State」が「Locked」、「Table lock」、「Waiting for .*lock」の合算。
      • ここでリストアップされていないものは「State Other」にすべて計上されている。
    • State Login:ログイン(認証処理など)処理中
    • State Preparing:クエリオプティマイザ実行中
    • State Reading From Net:ネットワークからSQLを読み込み中
    • State Sending Date:SELECTによるデータ読みこみ、またはクライアントへのデータ送信中
    • State Sorting Result:一時テーブルを利用しないsort処理中
    • State Statistics:SQL実行計画決定の為の統計処理中
    • State Updating:UPDATEのためのデータ探索中またはUPDATE処理中
    • State Writing To Net:ネットワークへデータを草子中
    • State None:Stateなし
      • 「State」に値が設定されていないスレッド。
      • 例えばSLEEP中のスレッド等が該当します。
      • トランザクション内でSQLSQLの間もSLEEPになるので「State None」に計上されます。
    • State Other:その他
  • MySQL Thread※Max 8
    • サーバ側の値をそのまま表示しているものと、サーバ側がカウンタとなっていて、前回の処理からの差分を描画しているものがある。
      • サーバ側の値をそのまま表示
      • Thread Cache Size:スレッドキャッシュのサイズ
      • Thread Connected:接続中(利用中)のスレッド数
      • Threads Running:実行中ステータスのスレッド数
      • Threads Cached:キャッシュされていたスレッド数
    • 前回からの差分を描画
      • Threads Created:生成されたスレッド数 「Threads Created」が高い値を示し続けるなら、 「Thread Cache Size」を増やすと処理が効率化できるかもしれない。
  • MySQL Transaction Handler※Max600
    • サーバ側がカウンタになっているので、前回の処理からの差分を描画
    • Handler Commit:コミット要求数
    • Handler Rollback:ロールバック要求数
    • Handler Savepoint:セーブポイント要求数
    • Handler Savepoint Rollback:セーブポイントロールバック要求数 どの数値が多いから異常ということはないが、想定範囲から大幅に外れていないか確認は必要

性能関連のグラフ

  • MySQL Query Cache※Max 10k
    • サーバ側の値をそのまま表示
      • Qcache Queries In Cache:キャッシュに格納されているSQL
    • サーバ側がカウンタになって、前回の処理からの差分を描画
      • Qcache Hits:キャッシュヒットしたSQL
      • Qcache Inserts:キャッシュに新しく登録されたSQL
      • Qcache Not Cached:キャッシュしないSQL
      • Qcache Lowmem Prunes:キャッシュ容量不足によりキャッシュから削除されたSQL数 「Qcache Lowmem Prunes」が発生しているようであれば、クエリキャッシュのサイズを調整することで処理が効率化できるかもしれない 合計SQL数は「Qcache Inserts」+「Qcache Hits」+「Qcache Not Cached」
  • MySQL Query Cache Memory
    • サーバ側がカウンタで前回の処理からの差分を描画
    • クエリキャッシュではブロック長は可変なので、「Qcache Free Memory」が多くも、
    • 「Qcache Free Blocks」が少ないと、キャッシュできるSQL数は少なくなる。
    • Qcache Cache Size:クエリキャッシュのサイズ
    • Qcache Free Memory:クエリキャッシュの空き容量
    • Qcahce Total Blocks:クエリキャッシュの総ブロック数
    • Qcache Free Blocks:クエリキャッシュの空きブロック数
  • My Select Types
    • サーバ側がカウンタで前回の処理からの差分を描画
    • Select Full Join:インデックスを利用しないJOINの数
    • Select Full Range Join:関連テーブルで範囲検索したJOINの数
    • Select Range:ファーストテーブルを範囲検索した部分を利用したJOINの数
    • Select Range Check:インデックスなしのJOINの数
    • Select Scan:ファーストテーブルでフルスキャンを実行したJOINの数 Select Full JoinとSelect Range Checkが0でない場合は、インデックスを見直す。
  • MySQL Sorts
    • サーバ側がカウンタで前回の処理からの差分を描画
    • Sort Rows:ソートしたレコード数
    • Sort Range:範囲指定ソートの回数
    • Sort Merge Passes:ソートで必要としたマージパスの回数
    • Sort Scan:テーブルスキャンでソートした回数
  • MySQL Table Locks
    • サーバ側がカウンタで前回の処理からの差分を描画
    • Table Locks Immediate:テーブルロックを直ちに実行した回数
    • Table Locks locks Waited:テーブルロックを実行するとき待ちが発生した回数
    • Slow Queries:スロークエリの数 テーブルロックが発生すると処理の並列度が著しく下がるため、「Table Locks Waited」が0になるようにする。
  • MySQL Temporary Objects
    • サーバ側がカウンタで前回の処理からの差分を描画
    • Created Tmp Tables:作成した一時テーブルの数
    • Created Tmp Disk Tables:ディスク上に作成した一時テーブルの数
    • Created Tmp File:作成した一時ファイルの数 「Created Tmp Disk Tables」に計上される一時テーブルは、 一時テーブルのサイズが「tmp_table_size」を越えた場合にディスクに書き出されるもの。 「Created Tmp File」に計上される一時ファイルは「sort_buffer_size」を 越える大きな「ORDER_BY」や「GROUP_BY」により作成されます。

InnoDB関連のグラフ

  • InnoDB Buffer Pool Activity
    • サーバ側がカウンタで前回の処理からの差分を描画
    • Pages Created:作成されたページの数
    • Pages Read:読み込まれたページの数
    • Pages Written:書き込まれたページの数
    • デフォルト1ページ16KB
  • InnoDB Buffer Pool
    • サーバ側の値をそのまま表示
    • Pool Size:バッファプールのサイズ(ページ数)
    • Database Pages:データがあるページ数
    • Free Pages:空きページ数
    • Modified Pages:書き換えが発生したダーティページ数
    • 単位がページ数で、デフォルトは1ページ16KB。
  • InnoDB I/O
    • サーバ側がカウンタで前回の処理からの差分を描画
    • Fire Reads:OSでの読み込みI/O実行回数
    • Fire Writes:OSでの書き込みI/O実行回数
    • Log Reads:log書き込みI/O実行回数
    • Fire Fsysncs:OSでのfsyncs実行回数
  • InnoDB I/O
    • サーバ側の値をそのまま表示
    • このグラフの数値すべてが0でない場合、ディスクI/Oがボトルネックになっている可能性がある。InnoDB I/Oグラフと併せて確認する
    • Pending Aio Log Ios:insert bufferの非同期ログでの待ちI/O数
    • Pending Aio Sync Ios:insert bufferの非同期syncでの待ちI/O数
    • Pending Chkp Writes:チェックポイントでの待ち
    • Pending Ibuf Aio Reads:insert bufferの非同期ログ読み込みでの待ちI/O数
    • Pending Log Flushes:ログフラッシュでの待ち
    • Pending Log Writes:ログ書き込みでの待ち
    • Pending Normal Aio Log Reads:通常の読み込み非同期I/Oでの待ち
    • Pending Normal Aio Log Writes:通常の書き込み非同期I/Oでの待ち
    • Pending Buf Pool Flushes:バッファプールフラッシュでの待ち
  • InnoDB Insert Buffer
    • サーバ側がカウンタで前回の処理からの差分を描画
    • Ibuf Inserts 実行した書き込み要求数
    • Ibuf Merged マージされたI/O要求数
    • Ibuf Merges マージ処理回数
  • InnoDB Lock
    • サーバ側がカウンタで前回の処理からの差分を描画とサーバ側の値をそのまま表示のものがある
    • サーバ側がカウンタで前回の処理からの差分を描画
      • Innodb Log Buffer Size:ログバッファのサイズ
      • Unflushed Log:ログから書き出されていないデータ量
    • サーバ側の値をそのまま表示のものがある
      • Log Bytes Written:ログに書き込まれたデータ量
      • Log Bytes Flushed:ログから書き出されたデータ量
  • InnoDB Row Operations
    • サーバ側がカウンタで前回の処理からの差分を描画
    • Row Read 読み込まれた行数
    • Rows Delete 削除された行数
    • Rows Updated 更新された行数
    • Rows Inserted 挿入された行数
  • InnoDB Semaphores
    • サーバ側がカウンタで前回の処理からの差分を描画
    • SQL文の「SHOW ENGINE INNNODB STATUS」で取得する「SEMAPHORES」の値
    • Spin Rounds スピンロック獲得のためのラウンド数
    • Spin Waits スピンロック獲得待ち
    • Os Waits OSロック獲得待ち数
  • InnoDB Transactions
    • サーバ側がカウンタで前回の処理からの差分を描画とサーバ側の値をそのまま表示のものがある
    • 前回からの差分を描画
  • MyISAM Indexes
    • サーバ側がカウンタで前回の処理からの差分を描画
    • Key Read Requests キャッシュからのキーブロックの読み込み要求数
    • Key Reads ディスクからのキーブロックの読み込み回数
    • Key Write Requests キャッシュにキーブロックを書き込んだ要求数
    • Key Writes ディスクへのキーブロックの書き込み回数
    • SQL文の「SHOW GLOBAL STATUS」で取得する値
    • キャッシュミス率は「Key Reads」/「Key Read Requests」で計算
    • 「Key Reads」がほぼ0になるよう調整する

Grafanaの見方

5.1.6 サーバーステータス変数

# iptablesについて

iptablesについてまとめてみました。 設定ミスすると思わぬサービス影響が出るのでちゃんと理解したいところです。

オプション

オプション 意味
-N 新規チェインの追加
-X ユーザチェインの削除
-A ルールの追加
-D ルールの削除
-L チェインにあるルールの一覧表示
-F チェイン内容の全消去
-P 各チェインのデフォルトルール(ポリシー)を記述することができる
-I 選択されたチェインにルール番号を指定して 1 つ以上のルールを挿入する
-R 選択されたチェインにあるルールを置き換える
-Z すべてのチェインのパケットカウンタとバイトカウンタをゼロにする
-E ユーザー定義チェインを指定した名前に変更する。
-h ヘルプ

パラメータ

以下のパラメータは (-A, -D, -I, -R,コマンドで用いられて) ルールの仕様を決める。

パラメータ名 説明
-p(--protocol) プロコトル ルールで使うプロトコルtcpudp、icmp、all)を指定
-s(--source) IPアドレス[/mask] 送信元アドレス。IPアドレスのほかにホスト名などでも指定できる
-d(--destinationIPアドレス[/mask] 接続先アドレス。IPアドレスのほかにホスト名などでも指定できる
-i(--in-interface) デバイス パケットが入ってくるインターフェイス(eth0、eth1など)を指定
-o(--out-interface) デバイス パケットが出ていくインターフェイスを指定
-j(--jump) ターゲット パケットがマッチしたときのアクション(ターゲット)を指定
-t(--table) テーブル テーブル(filter、nat、mangle)を指定
! -p、-s、-dなどで、条件を反転する。「! 192.168.0.1」とすると、「192.168.0.1以外」という意味になる
-c このオプションを使うと、 (insert, append, replace 操作において) 管理者はパケットカウンタとバイトカウンタを 初期化することができる。
-f このオプションは、分割されたパケット (fragmented packet) のうち 2 番目以降のパケットだけを参照するルールであることを意味する。
  • -p プロトコル all は全てのプロトコルとマッチし、 このオプションが省略された際のデフォルトである。

  • ! -pではプロトコルの前に "!" を置くと、そのプロトコルを除外するという意味になる。 -sではアドレス指定の前に "!" を置くと、そのアドレスを除外するという意味になる。 フラグ --src は、このオプションの別名である。 -dではアドレス指定の前に "!" を置くと、そのアドレスを除外するという意味になる。 -iではインターフェース名の前に "!" を置くと、 そのインターフェースを除外するという意味になる。 -oではインターフェース名の前に "!" を置くと、 そのインターフェースを除外するという意味になる。 -fでは"-f" フラグの前に "!"を置くと、 分割されたパケットのうち最初のものか、 分割されていないパケットだけにマッチする。

  • -d --dst は、このオプションの別名である。

  • -j このオプションがルールの中で省略された場合、 ルールに マッチしてもパケットの行方に何も影響しないが、 ルールのカウンタは 1 つ 加算される。

  • -i パケットを受信することになるインターフェース名 (INPUT, FORWARD, PREROUTING チェインに入るパケットのみ)。 インターフェース名が "+" で終っている場合、 その名前で始まる任意の インターフェース名にマッチする。 このオプションが省略された場合、 任意のインターフェース名にマッチする。

  • -o パケットを送信することになるインターフェース名 (FORWARD, OUTPUT, POSTROUTING チェインに入るパケットのみ)。 インターフェース名が "+" で終っている場合、 その名前で始まる任意のインターフェース名にマッチする。 このオプションが省略された場合、 任意のインターフェース名にマッチする。

テーブルとは

チェインをグループ化したもの

テーブル名 利用できるチェイン
filter INPUT,FORWARD,OUTPUT
nat PREROUTING,OUTPUT,POSTROUTING
mangle PREROUTING,OUTPUT,※POSTROUTING,INPUT,FORWARD 

※3つのチェインはカーネル2.4.18からサポートされている。

  • filter パケットのフィルタリングに使用する。 これがデフォルトのテーブルである。 (-t オプションが指定されていない場合)

  • nat このテーブルは新しい接続を開くようなパケットに対して参照される。 IPマスカレードの設定を行う。 アドレス変換に使用される。

  • mangle このテーブルは特別なパケット変換に使われる。
    パケットをNAT以外の目的で置き換えるときに使用される。 TOSフィールドの書き換えなどパケットの 書き換えルールを設定する。QoSをするのに使う。

チェインとは

チェインは入力、出力、転送するパケットに適用するルールのリスト デフォルトでINPUT, FORWARD, OUTPUT, PREROUTING, POSTROUTINGの 合計5つのチェインが定義されているが新しく作成したり、既存のチェインとリンクさせることが可能

チェイン チェインの意味
INPUT コンピュータに入ってくるパケットに適用するルール)
FORWARD あるネットワークインターフェースから、別のネットワークインターフェースに中継されるパケットに適用するルール)
OUTPUT コンピュータから出てゆくパケットに適用するルール)
PREROUTING パケットが入ってきた場合、すぐにそのパケットを変換するためのチェイン)
OUTPUT ローカルで生成されたパケットをルーティングの前に変換するためのチェイン)
POSTROUTING パケットが出て行くときに変換するためのチェイン)
  • FORWARD このチェインはコンピュータがルータもしくはゲートウェイとして構成された場合に使用される。

iptableの起動確認

/etc/init.d/iptables status

  • 動いている場合
# /etc/init.d/iptables status
テーブル: filter
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
2    ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           
3    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
4    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:80
5    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:443
6    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22
7    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:3306
8    REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         
1    REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination         
  • 動いていない場合
# /etc/init.d/iptables status
bash: /etc/init.d/iptables: そのようなファイルやディレクトリはありません

natテーブルの状態

オプション-t natで natテーブルを指定することができる。

# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 211 packets, 8772 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

設定追加した後にサーバ再起動時の動き

saveする前に再起動をすると追加した設定は消える。

iptablesの再起動時にファイアウォールルールを消去中:と出力されるので、 保存しなければ再起動時に設定が反映されない。

# /etc/init.d/iptables restart
iptables: チェインをポリシー ACCEPT へ設定中filter         [  OK  ]
iptables: ファイアウォールルールを消去中:                  [  OK  ]
iptables: モジュールを取り外し中:                          [  OK  ]
iptables: ファイアウォールルールを適用中:                  [  OK  ]

INPUTチェイン一番上部に追加してiptables -nvLの結果をみてみる

iptables -I 1 -m state --state NEW -p tcp -s 123.456.789.111 --sport 80 -j ACCEPT

  • iptables -nvLの結果
# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     tcp  --  *      *       123.456.789.111      0.0.0.0/0           state NEW tcp spt:80
  404 33344 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:80
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:443
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22
    2   120 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:3306
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 13 packets, 2948 bytes)
 pkts bytes target     prot opt in     out     source               destination         

SMTP(25ポート)にアタックが来ていると仮定して、遮断手順作成してみる

  • IP:123.456.789.222
  • ポート:25
  • プロトコル:TCP
  • チェインはINPUT
  • アタックを /var/log/maillog で確認
# /etc/init.d/iptables status
# cp -a /etc/sysconfig/iptables{,.`date +%Y%m%d`_1}
# /etc/init.d/iptables save
# cp -a /etc/sysconfig/iptables{,.`date +%Y%m%d`_2}
# iptables -nvL (iptables -nL)
# iptables -I INPUT -s 123.456.789.111 -p tcp --dport 25 -j DROP
# iptables -nvL
# /etc/init.d/iptables save

以下は実行ログ

# cp -a /etc/sysconfig/iptables{,.`date +%Y%m%d`_1}
# /etc/init.d/iptables save
iptables: ファイアウォールのルールを /etc/sysconfig/iptable[  OK  ]中:
# cp -a /etc/sysconfig/iptables{,.`date +%Y%m%d`_2}
# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     tcp  --  *      *       123.456.789.111      0.0.0.0/0           state NEW tcp spt:80
  171 13020 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:80
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:443
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22
    4   240 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:3306
    1   229 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 107 packets, 15828 bytes)
 pkts bytes target     prot opt in     out     source               destination         
# iptables -I INPUT -s 123.456.789.111 -p tcp --dport 25 -j DROP
# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       tcp  --  *      *       123.456.789.222      0.0.0.0/0           tcp dpt:25
    0     0 ACCEPT     tcp  --  *      *       123.456.789.111      0.0.0.0/0           state NEW tcp spt:80
  189 14412 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:80
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:443
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22
    5   300 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:3306
    1   229 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 4 packets, 576 bytes)
 pkts bytes target     prot opt in     out     source               destination         
# /etc/init.d/iptables save
iptables: ファイアウォールのルールを /etc/sysconfig/iptable[  OK  ]中:
# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       tcp  --  *      *       111.111.111.111      0.0.0.0/0           tcp dpt:25
    0     0 ACCEPT     tcp  --  *      *       111.111.111.111      0.0.0.0/0           state NEW tcp spt:80
  204 15448 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:80
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:443
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22
    5   300 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:3306
    1   229 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 15 packets, 3516 bytes)
 pkts bytes target     prot opt in     out     source               destination         
# /etc/init.d/iptables restart
iptables: チェインをポリシー ACCEPT へ設定中filter         [  OK  ]
iptables: ファイアウォールルールを消去中:                  [  OK  ]
iptables: モジュールを取り外し中:                          [  OK  ]
iptables: ファイアウォールルールを適用中:                  [  OK  ]
# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       tcp  --  *      *       111.111.111.111      0.0.0.0/0           tcp dpt:25
    0     0 ACCEPT     tcp  --  *      *       111.111.111.111      0.0.0.0/0           state NEW tcp spt:80
   16  1168 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:80
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:443
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:3306
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 9 packets, 1236 bytes)
 pkts bytes target     prot opt in     out     source               destination

iptablesで遮断する手順も用意しました。

アタックがあった際iptablesにて遮断する手順

注意

  • どこのテーブルに設定を追加するか確認すること

アタックの判断基準

  • netstatの出力だけでアタックと判断しない
  • 海外IPだからという理由だけでアタックと判断しない
  • 必ず各ログを閲覧し、アタックと思われる出力を確認する

どこで遮断するか(サーバ、上流LB)

  • LBにぶら下がっているサーバに関しては、上流LBにて遮断を実施する。
  • その他については当該サーバにて遮断を実施する。

遮断手順

  1. root権限

      sudo su -
    
  2. 実施前に service iptables status で有効か確認する

     service iptables status
    
  3. 現在のiptablesの設定確認

     iptables -nvL --line
    
  4. ルールに差異がないかを確認

     diff /etc/sysconfig/iptables <(iptables-save)
    
  5. 設定ファイルをバックアップ

     cp -a /etc/sysconfig/iptables{,.`date +%Y%m%d`}
    
  6. 現在の設定を保存

     /etc/init.d/iptables save
    

    ※centos7系 iptables-save > /etc/sysconfig/iptables(wm_ml)

  7. 設定のバックアップ

     cp -a /etc/sysconfig/iptables{,.`date +%Y%m%d`_2}
    
  8. 対象のIPを遮断

     iptables -I <チェイン名> 1 -p tcp -m tcp --dport <ポート番号> -s <IPアドレス> -j DROP
    
     iptables -I INPUT 1 -p tcp -m tcp --dport 80 -s 123.456.789.111 -j DROP
     iptables -I INPUT 1 -p tcp -m tcp --dport 80 -s 123.456.789.222 -j DROP
    
  9. 追加されたか確認

     iptables -nvL --line
    
  10. 疎通確認

    1. 正常な(遮断されるべきでない)疎通が取れるか確認する
    2. 別窓で当該サーバの遮断したポートに対してtelnetを実行

       telnet <サーバ> <ポート>
      
    3. 正常に接続できることを確認

  11. 現在の設定を吐き出す

    /etc/init.d/iptables save
    

    ※centos7系 iptables-save > /etc/sysconfig/iptables

差し戻し手順

  1. 直前のバックアップファイルから復元

     iptables-restore < /etc/sysconfig/iptables{,.$(date +%Y%m%d)}
    
  2. 確認

     iptables -nvL
    
  3. 疎通確認

     telnet <サーバ> <ポート>
    
  4. save

     /etc/init.d/iptables save
    

    ※centos7系 iptables-save > /etc/sysconfig/iptables

削除手順

  1. root権限

     sudo su -
    
  2. 実施前に service iptables status で有効か確認する

     service iptables status
    
  3. 現在のiptablesの設定確認

     iptables -nvL --line
    
  4. 設定のバックアップ

     cp -a /etc/sysconfig/iptables{,.`date +%Y%m%d`}
    
  5. 現在の設定を保存

     /etc/init.d/iptables save
    
  6. 設定のバックアップ

     cp -a /etc/sysconfig/iptables{,.`date +%Y%m%d`_2}
    
  7. 対象のIPを遮断

     iptables -D <チェイン名> <行番号>
    
  8. 追加されたか確認

     iptables -nvL --line
    
  9. 現在の設定を吐き出す

     /etc/init.d/iptables save
    

    ※centos7系 iptables-save > /etc/sysconfig/iptables