【Python】Excel から Ansible のコードを自動生成する①【構築自動化】

Excel から必要な情報を抜き出して、Ansible の ini ファイルを置換する Python スクリプトを書いてみました。

#!/usr/bin/python3
# coding: UTF-8

import openpyxl
import sys

# Ansible の ini ファイルを定義(置換前)
org_file_name = "all.yml.org"
# Ansible の ini ファイルを定義(置換後)
file_name = "all.yml"

# コマンドライン引数の数を確認
if len(sys.argv) != 2:
    print("input error")
    sys.exit(1)

# Excel ファイル名を変数に代入
args = sys.argv
target = args[1]

# Excel データを取得
wb = openpyxl.load_workbook(target)
sheet = wb.get_sheet_by_name('Sheet1')

# セルデータの取得関数
def get_cell(x, y):
    param = sheet.cell(row=x,column=y).value
    return param

# 必要なセルの情報を取得
domain = get_cell(2, 2)
docroot = get_cell(3, 2)

# 置換前の ini ファイルを開く
with open(org_file_name, encoding="cp932") as f:
    data_lines = f.read()

# 置換
data_lines = data_lines.replace("xxx", domain)
data_lines = data_lines.replace("yyy", docroot)

# 置換後のiniファイルを作成
with open(file_name, 'w', encoding="cp932") as f:
    f.write(data_lines)

スクリプトのコマンドライン引数としてExcelファイル(.xlsx)を指定して実行してください。

【CloudWatch】AutoScaling のメモリ/ディスク使用率のグループメトリクスを取得する【AWS】

AutoScaling のグループメトリクスとして、メモリとディスク使用率を取得する必要がございました。
調べると AWS がメトリクス取得用のスクリプトを提供しているようです。
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/mon-scripts.html

# 必要なパッケージの導入
yum install -y perl-Switch perl-DateTime perl-Sys-Syslog perl-LWP-Protocol-https perl-Digest-SHA.x86_64
# ディレクトリ移動
cd /usr/local/src/
# スクリプトのインストール
curl https://aws-cloudwatch.s3.amazonaws.com/downloads/CloudWatchMonitoringScripts-1.2.2.zip -O
# スクリプトの解凍
unzip CloudWatchMonitoringScripts-1.2.2.zip && rm CloudWatchMonitoringScripts-1.2.2.zip && cd aws-scripts-mon
# テスト実行
./mon-put-instance-data.pl --mem-util --mem-used --mem-avail --disk-space-util --disk-path=/ --auto-scaling=only
# cronで5分毎に実行
crontab -e
=====================================================================================================================================================================
*/5 * * * * /usr/local/src/aws-scripts-mon/mon-put-instance-data.pl --mem-util --mem-used --mem-avail --disk-space-util --disk-path=/ --auto-scaling=only --from-cron

※ EC2 から CloudWatch を操作できる権限を持った IAM ロールを事前にアタッチしておく必要がございます。
※ インスタンス毎にキャッシュファイルが作成されるので、EC2 起動時にキャッシュファイルを削除するよう UserData を設定しておきます。
#!/bin/bash
rm -rf /var/tmp/aws-mon/*

※ cloudwatch-agent もありますが、こちらではグループメトリクスは取得できないようです。

【Lambda】CloudWatch の通知を Lambda で Slack に飛ばしてみる【Slack】

担当している案件で CloudWatch からの通知を Slackに飛ばす必要があったので、Lambda で実装してみます。

1.事前準備

■ 通知を飛ばす Slack に Incoming WebHooks を追加しておく
https://slack.com/services/new/incoming-webhook

■ 必要なポリシーを付与した IAM ロールを作成しておく
・CloudWatchReadOnlyAccess
・AWSLambdaBasicExecutionRole

■ CloudWatch + SNS の通知設定

2.Lambda設定

Lambda > 関数 > 関数の作成 > 一から作成

関数名:<>
ランタイム:python 3.7
実行ロールの選択: 事前準備で作成したIAMロール

> トリガーを追加

トリガーの設定:SNS
SNS トピック:「事前準備で作成したSNSトピック」
トリガーの有効化:有効

関数コード

import boto3
import json
import logging
import os

from base64 import b64decode
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError


# 通知を飛ばすチャンネルを定義
SLACK_CHANNEL = "#xxxxxx"

# WEB_HOOKURLを定義
HOOK_URL = "https://hooks.slack.com/services/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

logger = logging.getLogger()
logger.setLevel(logging.INFO)


def lambda_handler(event, context):
    logger.info("Event: " + str(event))
    message = json.loads(event['Records'][0]['Sns']['Message'])
    logger.info("Message: " + str(message))

    alarm_name = message['AlarmName']
    #old_state = message['OldStateValue']
    new_state = message['NewStateValue']
    reason = message['NewStateReason']

    slack_message = {
        'channel': SLACK_CHANNEL,
        'text': "%s state is now %s: %s" % (alarm_name, new_state, reason)
    }

    req = Request(HOOK_URL, json.dumps(slack_message).encode('utf-8'))
    try:
        response = urlopen(req)
        response.read()
        logger.info("Message posted to %s", slack_message['channel'])
    except HTTPError as e:
        logger.error("Request failed: %d %s", e.code, e.reason)
    except URLError as e:
        logger.error("Server connection failed: %s", e.reason)

⇒「SLACK_CHANNEL」「HOOK_URL」に通知を飛ばすチャンネル名とWebHookURLを定義してください。

【スパム対策】opendkim の設定【dkim】

opendkim を導入する機会があったので備忘録を残しておきます。
※ メール送信の際に利用するドメインを test.work とします。

# 必要なパッケージの導入
yum install epel-release
yum install opendkim
yum install mailx

# キーペア作成
mkdir -p /etc/opendkim/keys/test.work
opendkim-genkey -D /etc/opendkim/keys/test.work/ -d testdom.work -s test_work_20200315
chown opendkim:opendkim /etc/opendkim/keys/test.work -R

# KeyTable 追記
vi /etc/opendkim/KeyTable
===============================================================================================================================
test_work_20200315._domainkey.test.work test.work:test_work_20200315:/etc/opendkim/keys/test.work/test_work_20200315.private

# SigningTable 追記
vi /etc/opendkim/SigningTable
====================================================
*@test.work test_work_20200315._domainkey.test.work


# opendkim 設定ファイル調整
vi /etc/opendkim.conf
===========================================================
Mode    sv
KeyTable        /etc/opendkim/KeyTable
SigningTable    refile:/etc/opendkim/SigningTable
ExternalIgnoreList      refile:/etc/opendkim/TrustedHosts
InternalHosts   refile:/etc/opendkim/TrustedHosts

# opendkim 起動
systemctl start opendkim
systemctl enable opendkim

# opendkim 連携設定
vi /etc/postfix/main.cf
========================================
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
milter_default_action = accept

# postfix 設定反映
postfix check
systemctl reload postfix

# テストメール送信
echo "TEST MAIL" | mail -s "TEST" -r test@test.work xxx@xxx.com


# メールヘッダーに電子署名が追記されているか確認
less /var/log/maillog
========================================================================================================================
Mar 14 16:31:36 test-server1 opendkim[3193]: 0DD5D5B6A2: DKIM-Signature field added (s=test_work_20200315, d=test.work)

DNS サーバに登録するレコードと値はキーペアを作成した際の txt ファイルに情報が書いてます。

[root@test-server1 test.work]# cat /etc/opendkim/keys/test.work/test_work_20200315.txt
test_work_20200315._domainkey   IN      TXT     ( "v=DKIM1; k=rsa; "
          "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpgATXCFihKVnzn9BFZWqyGiFpzmkR5UMhdBz7Uqu+OnKN3+DYh47TSeKlj/4HIz/umGWJ/nAdDMLhkiaTtCfiEml/xxkzzsgwlOL9Iub/gigTaXcYbipAutSjtEoz8MTe+zeHGveLhcxwsEYxm9HQBXiTl6l1yzxqCdFAZes6uQIDAQAB" )  ; ----- DKIM key test_work_20200315 for testdom.work

「test_work_20200315._domainkey.test.work」の txt レコードとして下記を登録すれば OK です。

"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpgATXCFihKVnzn9BFZWqyGiFpzmkR5UMhdBz7Uqu+OnKN3+DYh47TSeKlj/4HIz/umGWJ/nAdDMLhkiaTtCfiEml/xxkzzsgwlOL9Iub/gigTaXcYbipAutSjtEoz8MTe+zeHGveLhcxwsEYxm9HQBXiTl6l1yzxqCdFAZes6uQIDAQAB"

【proxy】踏み台経由でデータを同期する【rsync】

こんにちは。
踏み台を経由して rsync でデータ同期する方法を、自分用の備忘録として残しておきます。

↓ 前提として同期先、及び、踏み台に root ユーザで接続できる必要があります。

【AWS】EC2 に root ユーザで接続する【サーバ移設】


# SSH 接続設定
vi ~/.ssh/config
============================================================
# 踏み台サーバ
Host mng-bastion01
    # IP アドレス ( 踏み台サーバ )
    HostName      111.111.111.111
    # 接続ユーザ ( 踏み台サーバ )
    User          root
    # 秘密鍵 ( 踏み台サーバ )
    IdentityFile  ~/.ssh/root_secretkey

# ステージングサーバ
Host stg-web01
    ProxyCommand  ssh -W %h:%p mng-bastion01
    # IP アドレス ( ステージングサーバ )
    HostName      222.222.222.222
    # 接続ユーザ ( ステージングサーバ )
    User          root
    # 秘密鍵 ( ステージングサーバ )
    IdentityFile  ~/.ssh/root_secretkey

# 本番サーバ
Host prod-web01
    ProxyCommand  ssh -W %h:%p mng-bastion01
    # IP アドレス ( 本番サーバ )
    HostName      333.333.333.333
    # 接続ユーザ ( 本番サーバ )
    User          root
    # 秘密鍵 ( 本番サーバ )
    IdentityFile  ~/.ssh/root_secretkey
============================================================
    
# パーミッションを調整
chmod 600 ~/.ssh/config

# 接続確認
ssh mng-bastion01
ssh stg-web01
ssh prod-web01

# /path/to/sync_dir を同期先の /path/to/ 配下に同期 ( ドライラン )
rsync -avzn --bwlimit=6400 -e 'ssh -i ~/.ssh/root_secretkey' /path/to/sync_dir stg-web01:/path/to/
rsync -avzn --bwlimit=6400 -e 'ssh -i ~/.ssh/root_secretkey' /path/to/sync_dir prod-web01:/path/to/

# /path/to/sync_dir を同期先の /path/to/ 配下に同期
rsync -avz --bwlimit=6400 -e 'ssh -i ~/.ssh/root_secretkey' /path/to/sync_dir stg-web01:/path/to/
rsync -avz --bwlimit=6400 -e 'ssh -i ~/.ssh/root_secretkey' /path/to/sync_dir prod-web01:/path/to/


# 同期元の /path/to/sync_dir を /path/to/ 配下に同期 ( ドライラン )
rsync -avzn --bwlimit=6400 -e 'ssh -i ~/.ssh/root_secretkey' stg-web01:/path/to/sync_dir /path/to/
rsync -avzn --bwlimit=6400 -e 'ssh -i ~/.ssh/root_secretkey' prod-web01:/path/to/sync_dir /path/to/

# 同期元の /path/to/sync_dir を/path/to/ 配下に同期
rsync -avz --bwlimit=6400 -e 'ssh -i ~/.ssh/root_secretkey' stg-web01:/path/to/sync_dir /path/to/
rsync -avz --bwlimit=6400 -e 'ssh -i ~/.ssh/root_secretkey' prod-web01:/path/to/sync_dir /path/to/

【AWS】EC2 に root ユーザで接続する【サーバ移設】

こんにちは。
rsync でデータ同期を行う際、一般ユーザを用いてしまうと owner と group が適切に設定されないケースがあるようです。
AWS EC2 ( AmazonLinux ) のデフォルト設定では root ユーザでの接続ができないので、後述のように設定を調整します。

# 設定ファイルをバックアップ
cp -p /etc/ssh/sshd_config /etc/ssh/sshd_config.org
diff /etc/ssh/sshd_config /etc/ssh/sshd_config.org

# sshd 設定ファイルの調整
vi /etc/ssh/sshd_config
======================================
#PermitRootLogin forced-commands-only
PermitRootLogin without-password
======================================
# sshd 設定ファイルの syntax チェック
sshd -t

# sshd 再読み込み
/etc/init.d/sshd reload

# sshd の起動を確認
netstat -lntp | grep sshd

# root ユーザの公開鍵追記
vi /root/.ssh/authorized_keys
=======================================
ssh-rsa xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
=======================================

※ 秘密鍵、公開鍵のキーペアは下記コマンドで作成できます。
ssh-keygen -b 2048 -t rsa -f ./key_name

【サーバ移設】Linux の OS ユーザ移設【Tips】

こんにちは。
Linux サーバを移設する際に OS ユーザを移設先サーバにも作成する必要があるんですが、大量に OS ユーザが存在すると面倒くさいですよね。
そんなときは /etc/passwd 関連ファイルをコピーするといいらしいです。
※ 普通に実施すると権限がないので下記の手順が必要です。

# /etc/passwdを編集
vipw
=======================================
user1:x:515:515::/home/user1:/bin/bash
user2:x:504:504::/home/user2:/bin/bash
=======================================
:wq!

# /etc/shadowを編集
vipw -s
=======================================================================================================================
user1:$6$43wzBE4t$XVEOEQpipC9FRocISuPMZ47qPIPwG70sjm2S7ADy4scuwtuBBSlA70q/w0nduW1A2dHUkpVqEW8KW8Ro0:17387:0:99999:7:::
user2:$6$G8m9jYDT$X53N71JCVXbbJnDLrvBED67ZrrwtL.hfJa.9sosksjwnaUtlLF/K0F2l9KvmsgrULgFQ/KahH6C.:17220:0:99999:7:::
=======================================================================================================================
# 保存できないので無理やり保存する
:w !sudo tee %
:q!

# /etc/groupを編集
vigr
=============
user1:x:515:
user2:x:504:
=============

# /etc/gshadowの編集
vigr -s
===========
user1:!::
user2:!::
===========
# 保存できないので無理やり保存する
:w !sudo tee %
:q!

【AWS】ダウンタイムなくルートパーティションを拡張してみる【ディスク拡張】

AWS の EC2 にアタッチしている EBS のボリュームサイズを変更してから、ファイルシステムの拡張を行う手順になります。
ダウンタイムなく実施してみます。

ボリュームサイズ変更

[root@ip-172-31-35-200 ~]# lsblk
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0  16G  0 disk
mqxvda1 202:1    0   8G  0 part /

ディスクが拡張された状態で認識されてますね。

パーティション拡張

[root@ip-172-31-35-200 ~]# growpart /dev/xvda 1
CHANGED: partition=1 start=4096 old: size=16773087 end=16777183 new: size=33550303 end=33554399

[root@ip-172-31-35-200 ~]# lsblk
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0  16G  0 disk
mqxvda1 202:1    0  16G  0 part /

[root@ip-172-31-35-200 ~]# df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        475M     0  475M   0% /dev
tmpfs           492M     0  492M   0% /dev/shm
tmpfs           492M  400K  492M   1% /run
tmpfs           492M     0  492M   0% /sys/fs/cgroup
/dev/xvda1      8.0G  1.3G  6.8G  16% /
tmpfs            99M     0   99M   0% /run/user/1000

まだファイルシステム上では認識されてないですね。

ファイルシステム拡張

[root@ip-172-31-35-200 ~]# xfs_growfs /dev/xvda1
meta-data=/dev/xvda1             isize=512    agcount=4, agsize=524159 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1 spinodes=0
data     =                       bsize=4096   blocks=2096635, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal               bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 2096635 to 4193787


[root@ip-172-31-35-200 ~]# df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        475M     0  475M   0% /dev
tmpfs           492M     0  492M   0% /dev/shm
tmpfs           492M  400K  492M   1% /run
tmpfs           492M     0  492M   0% /sys/fs/cgroup
/dev/xvda1       16G  1.3G   15G   8% /
tmpfs            99M     0   99M   0% /run/user/1000

拡張できましたね。
※ ファイルシステムが ext4 の時は resize2fs を使う。

【Docker】redashの構築【CentOS7】

担当した案件で CentOS7 に redash を導入したんでその時の備忘録になります。
なんか色々と嵌った気がします。

# 必要なパッケージの導入
yum install epel-release -y
yum install docker docker-compose -y

# docker操作用の権限を一般ユーザに追加
sudo groupadd docker
sudo gpasswd -a $USER docker
sudo systemctl restart docker


# docker-compose.ymlファイルを用意
cat <<EOF > docker-compose-redash.yml
version: '2'
services:
  redis:
    image: redis:3.0-alpine
    restart: always

  server:
    image: redash/redash:latest
    command: server
    depends_on:
      - postgres
      - redis
    ports:
      - "5000:5000"
    environment:
      PYTHONUNBUFFERED: 0
      REDASH_LOG_LEVEL: "INFO"
      REDASH_REDIS_URL: "redis://redis:6379/0"
      REDASH_DATABASE_URL: "postgresql://postgres@postgres/postgres"
      REDASH_COOKIE_SECRET: veryverysecret
      REDASH_WEB_WORKERS: 4
    restart: always

  worker:
    image: redash/redash:latest
    command: scheduler
    environment:
      PYTHONUNBUFFERED: 0
      REDASH_LOG_LEVEL: "INFO"
      REDASH_REDIS_URL: "redis://redis:6379/0"
      REDASH_DATABASE_URL: "postgresql://postgres@postgres/postgres"
      QUEUES: "queries,scheduled_queries,celery"
      WORKERS_COUNT: 2
    restart: always

  postgres:
    image: postgres:9.5.6-alpine
    volumes:
      - ~/postgres-data:/var/lib/postgresql/data
    restart: always
EOF

# docker上に環境構築
docker-compose -f docker-compose-redash.yml run --rm server create_db

# docker上のredash起動
docker-compose -f docker-compose-redash.yml up -d

5000ポートで listen するんで、フロントに Nginx を置いてリバプロするのがいいですね。

【rbenv】rubyの導入、操作方法【チラ裏】

よく忘れちゃうんで纏めておきます。

# 必要なパッケージ導入
yum install -y git gcc gcc-c++ openssl-devel readline-devel

# rbenvのインストール
cd /usr/local
git clone git://github.com/sstephenson/rbenv.git rbenv
git clone git://github.com/sstephenson/ruby-build.git rbenv/plugins/ruby-build

# 環境変数の設定
vi /etc/profile.d/rbenv.sh
=====================================
export RBENV_ROOT="/usr/local/rbenv"
export PATH="${RBENV_ROOT}/bin:${PATH}"
eval "$(rbenv init --no-rehash -)"
=====================================
# 設定の反映
source /etc/profile.d/rbenv.sh

# 導入できるバージョンを確認
rbenv install --list

# rubyのインストール
rbenv install 2.2.2
rbenv global 2.2.2
rbenv rehash

# インストールしているrubyの確認
rbenv versions

# rubyの切り替え
rbenv global 2.7.0

# bundlerのインストール(-vでバージョン指定)
gem install bundler -v 1.16.5