【AWS】Data Lifecycle Manager を CloudFormation で設定してみた【dlm】

EBS のスナップショットを取得する Data Lifecycle Manager というマネージドサービスがございます。
こちらを一括で設定する CloudFormation のテンプレートを作成しました。

AWSTemplateFormatVersion: "2010-09-09"
Description: "DLM Configuration YAML"

# パラメータセッティング
Parameters:
  ProjectName:
    Type: String
  LotateNum:
    Type: Number
    Default: 3
  GetTime:
    Type: String
    Default: "18:00"

Resources:
  
  # DLM IAM ロール作成
  CreateDlmRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: 'AWSDataLifecycleManagerDefaultRole'
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - dlm.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /service-role/
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSDataLifecycleManagerServiceRole
        
  # DLM 作成
  BasicLifecyclePolicy:
    Type: "AWS::DLM::LifecyclePolicy"
    Properties:
      Description: !Join [ "-", [ !Ref ProjectName, dlm ] ]
      State: "ENABLED"
      ExecutionRoleArn: !Sub "arn:aws:iam::${AWS::AccountId}:role/service-role/AWSDataLifecycleManagerDefaultRole"
      PolicyDetails:
        ResourceTypes:
          - "VOLUME"
        TargetTags:
          -
            Key: "dlmtarget"
            Value: "true"

        Schedules:
          -
            Name: !Join [ "-", [ !Ref ProjectName, daily-schedule ] ]
            TagsToAdd:
              -
                Key: "type"
                Value: !Join [ "-", [ !Ref ProjectName, scheduled-snapshot ] ]

            CreateRule:
              Interval: 24
              IntervalUnit: "HOURS"
              Times:
                - !Ref GetTime

            RetainRule:
              Count: !Ref LotateNum
            CopyTags: true

各種パラメータは下記の通りに設定して下さい。
・ProjectName ⇒ DLM リソース の prefix
・LotateNum ⇒ スナップショットの保持期間を指定
・GetTime ⇒ スナップショットの取得時間を UTCで指定 ( 例:10:00、08:35、02:48 )

【AWS】EBS のスナップショットを取得して世代管理してみる【シェルスクリプト】

こんにちは。
表題の通りです。
DLM でもよいのですが、最長のインターバルが 24 時間なので、要件が合わない時のために。

#!/bin/sh

# スナップショットの保持世代数を定義
LOTATE_NUM=3
# ホストネームを定義
HOSTNAME=
# スナップショットを取得するボリュームIDを定義
VOLID=

# スナップショットを取得
aws ec2 create-snapshot --volume-id $VOLID --tag-specification 'ResourceType="snapshot",Tags=[{Key="Name",Value="script-create"}]' --description "$HOSTNAME snapshot"

# 指定した世代数分になるようにスナップショットを削除
SNAPSHOTS_NUM=`aws ec2 describe-snapshots --output text | grep $VOLID | grep "$HOSTNAME snapshot" | wc -l`
while [ ${SNAPSHOTS_NUM} -gt ${LOTATE_NUM} ]
do
        aws ec2 delete-snapshot --snapshot-id `aws ec2 describe-snapshots --output text | grep $VOLID | grep "$HOSTNAME snapshot" | sort -k 8 | awk 'NR==1 {print $7}'`
        SNAPSHOTS_NUM=`aws ec2 describe-snapshots --output text | grep $VOLID | grep "$HOSTNAME snapshot" | wc -l`
done

# awscli の導入

curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
sudo python get-pip.py
sudo pip install awscli
aws configure

【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)を指定して実行してください。

【C言語】単純なTCPサーバをdemontoolsでデーモン化する【demontools】

C 言語で単純な TCP サーバを作って demontools でデーモン化してみます。
※ demontools を使う機会があったので備忘録を兼ねています。

TCPサーバ

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(){
        int sockfd, sock_size, sock;
        struct sockaddr_in server;
        struct sockaddr_in client;

        /* ソケット作成 */
        sockfd = socket(AF_INET, SOCK_STREAM, 0);

        server.sin_family = AF_INET;
        server.sin_port = htons(8888);
        server.sin_addr.s_addr = INADDR_ANY;

        /* ソケットにポート番号割り当て */
        bind(sockfd, (struct sockaddr *)&server, sizeof(server));

        /* 割り当てたポート番号へ接続が作成できることをシステムに伝える */
        listen(sockfd, 5);

        /* 接続要求を受ける度にソケットを新しく取得 */
        while(1){
                sock_size = sizeof(client);
                sock = accept(sockfd, (struct sockaddr *)&client, &sock_size);
                write(sock, "TEST\n", 5);
                /* クライアントとの接続をクローズ */
                close(sock);
        }
        close(sockfd);
        return 0;
}

エラー処理は省いています。
適当なディレクトリにコンパイルしてください。
# ディレクトリ移動
cd /usr/local/bin
vi main.c
===================
*上記コード
===================
# コンパイル
gcc main.c -o simple-server

demontools

demontools の設定です。

# demontoolsの導入
mkdir -p /package
chmod 1755 /package
cd /package
wget http://cr.yp.to/daemontools/daemontools-0.76.tar.gz
gunzip daemontools-0.76.tar
tar -xpf daemontools-0.76.tar
rm -f daemontools-0.76.tar
cd admin/daemontools-0.76
cd src/

# ヘッダファイル修正
vi error.h
=======================
extern int errno;

↓

#include <errno.h>
=======================

# インストール
cd ..
package/install

# centos7 では使用しないのでコメントアウト
vi /etc/inittab
=======================
#SV:123456:respawn:/command/svscanboot
=======================

# サービスファイル作成
vi /etc/systemd/system/demontools.service
======================================================
[Unit]
Description=run demontools during boot
After=network.target

[Service]
User=root
Group=root
Type=simple
RemainAfterExit=yes
ExecStart=/command/svscanboot
Restart=always
LimitNOFILE=20480

[Install]
WantedBy=multi-user.target
======================================================


# プロセスのデーモン化
mkdir /service/simple-server/
vi /service/simple-server/run
======================================================
#!/bin/sh

exec /usr/local/bin/simple-server
======================================================

# ログ出力設定
mkdir /service/simple-server/log/
mkdir /var/log/simple-server
vi /service/simple-server/log/run
==============================================
#!/bin/sh

exec /usr/local/bin/multilog t /var/log/simple-server
==============================================

# 権限変更
chmod 755 /service/simple-server/run
chmod 755 /service/simple-server/log/run

# demontools 起動/自動起動設定
systemctl start demontools
systemctl enable demontools

【シェルスクリプト】apacheのrotatelogsとシェルスクリプトでログ管理をする【運用】

お疲れ様です。
rotatelogsでapacheのログを出力している環境でログを管理する必要があったので、忘備録として残しておきます。

背景

CustomLog "|/usr/local/apache2/bin/rotatelogs /usr/local/apache2/logs/access_log.%Y%m%d%H 14400 540" combined  env=!no_log
ErrorLog "|/usr/local/apache2/bin/rotatelogs /usr/local/apache2/logs/error_log.%Y%m%d 86400 540"

apacheに標準でついてくるrotatelogsでログが世代管理されている前提でですね、
2週間経過したログは削除、1日経過したログは圧縮するスクリプトを作ってcronに登録してみます。

スクリプトの作成

vi /usr/local/bin/apache_accesslog_compress.sh
====================================================================
#!/bin/sh
#ディレクトリを移動する
cd /usr/local/apache2/logs
#14日経過したログを削除する
find ./ -name 'access_log.*' -mtime +13 -daystart -exec rm {} \;
#1日経過したログを圧縮する
find ./ -name 'access_log.*' -mtime +0 -daystart  -exec gzip {} \;
====================================================================

findコマンドの-daystartは
コマンドを実行した日の00:00を-mtimeの基準とするオプションです。

cronへの登録

crontab -e
=======================================================
00 04 * * * /usr/local/bin/apache_accesslog_compress.sh
=======================================================

古い MySQL インストール方法

こんにちは。
古いバージョンの MySQL をインストールする際に少し躓いたので備忘録を残しておきます。

手順

wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
tar -xvf mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar

yum localinstall mysql-community-server-5.7.24-1.el7.x86_64.rpm \
mysql-community-client-5.7.24-1.el7.x86_64.rpm \
mysql-community-common-5.7.24-1.el7.x86_64.rpm \
mysql-community-devel-5.7.24-1.el7.x86_64.rpm \
mysql-community-libs-5.7.24-1.el7.x86_64.rpm \
mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm

MySQL が停止して困った話

こんにちは。
メモリが枯渇して MySQL が起動しなくなったので、SWAP を追加したお話です。

背景

最近、メモリ不足で MySQL が勝手に停止する事象が発生してました。
取り急ぎ、下記のようなスクリプトを cron に登録してたのですが、さらに SWAP 領域を作成しておきます。

#!/bin/bash
ProcessName=mysqld
count=`ps aux | grep $ProcessName | grep -v grep | wc -l`
if [ $count = 0 ]; then
sudo systemctl restart $ProcessName
echo "$(date)_$ProcessName is dead" >> /var/log/mysqld/statu_log.txt
else
echo "$(date)_$ProcessName is alive" >> /var/log/mysqld/statu_log.txt
fi

dd if=/dev/zero of=/swap.img bs=1M count=500
chmod 600 /swap.img
mkswap /swap.img
swapon /swap.img
cp -p /etc/fstab /etc/fstab_20181118
vim /etc/fstab
================================
/swap.img swap swap defaults 0 0
================================
systemctl status mysqld

Let’s Encrypt で証明書を取得する

こんにちは。
急に寒くなってきましたね。
ところで Let’s Encrypt でサイトを SSL化しました。
その際の備忘録になります。

certbotのインストール

epel から certbot のパッケージを落とします。

yum install epel-release
yum install certbot

証明書の取得

certbot certonly --webroot \
-w 【ドキュメントルート】 \
-d 【ドメイン名】 \
-m 【メールアドレス】 \
--agree-tos -n

※ 下記ディレクトリに証明書が生成されます。

# サーバ証明書
/etc/letsencrypt/live/【ドメイン名】/cert.pem
# 秘密鍵
/etc/letsencrypt/live/【ドメイン名】/privkey.pem
# 中間証明書
/etc/letsencrypt/live/【ドメイン名】/chain.pem

あとは、WEBサーバに設定すればOK

<VirtualHost *:443>
   ServerAdmin n41210guitar@gmail.com
   ServerName fingerease.work
   DocumentRoot "/var/www/vhosts/fingerease.work/public_html"
   DirectoryIndex wordpress index.php index.html index.xml
   <Directory /var/www/vhosts/fingerease.work/public_html>
           Options FollowSymLinks
           AllowOverride all
   </Directory>
   
   SSLEngine on
   SSLProtocol             all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
   SSLCipherSuite          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
   SSLHonorCipherOrder     off

   SSLCertificateFile /etc/letsencrypt/live/fingerease.work/cert.pem
   SSLCertificateKeyFile /etc/letsencrypt/live/fingerease.work/privkey.pem
   SSLCertificateChainFile /etc/letsencrypt/live/fingerease.work/chain.pem

   CustomLog "/var/log/httpd/fingerease.work-ssl-access_log" combined
   ErrorLog  "/var/log/httpd/fingerease.work-ssl-error_log"
</VirtualHost>