ラズベリーパイで Zabbix を構築しようと思ったんですが、CentOS7 用のパッケージがなかったんですよね…
なんで、ソースからインストールしなきゃ、ってことで備忘録です。
ついでに Nginx と php-fpm もソースから最新版を導入してみます。
【Lambda】CloudWatch の通知を Lambda で Chatwork に飛ばしてみる【Python】
こんにちは。
表題の通り、CloudWatch の Alarm 通知を Chatwork に通知してみます。
ランタイムは前回と同じく python 3.7 です。
ROOMNO にメッセージを通知するルームナンバ、 TOKEN に ChatWorkToken を定義すれば動きます。
import boto3 import json import logging import os import urllib from base64 import b64decode from urllib.request import Request, urlopen from urllib.error import URLError, HTTPError # Chatwork のルームナンバ定義 ROOMNO = 'xxxxxxxxxxxxxxxx' # WEB_HOOKURL URL = f'https://api.chatwork.com/v2/rooms/{ROOMNO}/messages' # ChatWorkToken 定義 TOKEN = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' 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'] new_state = message['NewStateValue'] reason = message['NewStateReason'] # ヘッダ情報 headers = { 'X-ChatWorkToken': TOKEN, } # 通知内容 sns_message = { 'body': "%s state is now %s: %s" % (alarm_name, new_state, reason), } # エンコード msns_message = urllib.parse.urlencode(sns_message) msns_message = msns_message.encode('utf-8') # リクエスト発行 req = Request(URL, data=msns_message, headers=headers) with urlopen(req) as res: result = json.loads(res.read().decode("utf-8"))
【Python】JMeter の実行結果をスプレッドシートに出力するスクリプトを書いてみた【gspread】
こんにちは。
JMeter が出力する結果を Google のスプレッドシートに出力してみようと考えまして、調べてみると Python に便利なライブラリがあったんで作ってみました。
※ 下記の JMeter デプロイ用 Playbook にも入れているのでよければご利用くださいませ。
https://github.com/keisukesanuki/jmeter-MS
Python スクリプト
#!/usr/bin/python3 import gspread import json import csv import sys import itertools # シークレットキーを絶対パスで指定 SECRETJSON = "/usr/local/jmeter/bin/sacred-drive.json" # スプレッドシートキーを定義 SPREADSHEET_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' ############################################################################ ## 関数 # 数字と文字コンバーター def num2alpha(num): if num<=26: return chr(64+num) elif num%26==0: return num2alpha(num//26-1)+chr(90) else: return num2alpha(num//26)+chr(64+num%26) ############################################################################# ## 認証 # お約束 from oauth2client.service_account import ServiceAccountCredentials scope = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive'] # ダウンロードした json ファイルを定義 credentials = ServiceAccountCredentials.from_json_keyfile_name(SECRETJSON, scope) # Google API にログイン gc = gspread.authorize(credentials) # スプレッドシートのシート1を開く worksheet = gc.open_by_key(SPREADSHEET_KEY).sheet1 ############################################################################## ## 処理 # コマンドライン引数を取得 args = sys.argv csvfile = args[1] # CSVファイルの内容を配列に代入 with open(csvfile) as fp: results_list_ex = list(csv.reader(fp)) # 2次元配列を1次元配列に変換 results_list = list(itertools.chain.from_iterable(results_list_ex)) # カウント変数初期化 COUNT_NUM = 1 # 空白行探索 while str(len(worksheet.cell(COUNT_NUM, 1).value)) != "0": COUNT_NUM += 1 # 編集する範囲を指定 cell_list = worksheet.range('A'+str(COUNT_NUM)+':'+num2alpha(len(results_list))+str(COUNT_NUM)) # cell_listにresults_listの配列を代入 for i,cell in enumerate(cell_list): cell.value = results_list[i] # 結果の保存 worksheet.update_cells(cell_list)
第一引数に csv ファイルを指定することで、結果をスプレッドシートに出力するスクリプトです。
このスクリプトを後述の JMeter 起動用スクリプトで利用します。
シェルスクリプト
#!/bin/sh DATE=$(date +"%Y%m%d") OPTIME=$(date +"%Y%m%d-%H%M%S") # 結果の出力先ディレクトリを指定 LOGDIR=/var/www/html/${DATE} # JMXファイルを指定 FILE_JMX=/usr/local/jmeter/bin/templates/build-web-test-plan.jmx # 日付ディレクトリの作成 mkdir -p ${LOGDIR} # JMeter 起動 /usr/local/jmeter/bin/jmeter -Dsun.net.inetaddr.ttl=0 -n -t ${FILE_JMX} -j ${LOGDIR}/${OPTIME}.log -l ${LOGDIR}/${OPTIME}.jtl -e -o ${LOGDIR}/${OPTIME}_th${JMETER_THREAD}${2}/ -r # CSV ファイルの作成 cat ${LOGDIR}/${OPTIME}_th${JMETER_THREAD}${2}/statistics.json | jq -r ". [] | [.transaction,.sampleCount,.errorCount,.errorPct,.meanResTime,.minResTime,.maxResTime,.pct1ResTime,.pct2ResTime,.pct3ResTime,.throughput,.receivedKBytesPerSec,.sentKBytesPerSec] | @csv" | grep "Total" > ${LOGDIR}/${OPTIME}_th${JMETER_THREAD}${2}/statistics.csv # スプレッドシートに結果を出力 /usr/local/bin/main.py ${LOGDIR}/${OPTIME}_th/statistics.csv
JMeter は json で結果を出力するので jq で無理やり csv に変換してます。
Python だと簡単に実装できて楽ですね。
補足
スクリプトの実行に下記のパッケージ導入が必要です。
yum install python3 python-devel jq pip3 install gspread pip3 install oauth2client
【Ansible】Ansible で AWS の3層ネットワークを構築する【IaC】
こんにちは。
表題の通り AWS の 3層ネットワークを構築する playbook を用意してみます。
※ 詳細は README を参照ください。
https://github.com/keisukesanuki/aws-vpc-3layer
作るもの
・VPC
・SUBNET
・INTERNETGATEWAY
・NATGATEWAY
・ROUTETABLE
ディレクトリ構造
. ├── README.md ├── ansible.cfg ├── hosts ├── roles │ └── aws_vpc │ ├── tasks │ │ └── main.yml │ └── vars │ └── main.yml └── vpc_create.yml
playbook
--- # tasks file for aws_vpc - name: create_vpc ec2_vpc_net: name: "{{ vpc_name }}" cidr_block: "{{ vpc_cidr }}" region: "{{ region }}" profile: "{{ profile }}" dns_hostnames: yes dns_support: yes register: vpc_info # PUBLIC_SUBNET 作成 - name: create_public_subnet ec2_vpc_subnet: vpc_id: "{{ vpc_info.vpc.id }}" cidr: "{{ item.pub_subnet_cidr }}" az: "{{ item.subnet_az }}" region: "{{ region }}" resource_tags: { "Name":"{{ item.pub_subnet_name }}" } profile: "{{ profile }}" register: pubsub_info with_items: - "{{ pub_subnet }}" # DMZ_SUBNET 作成 - name: create_dmz_subnet ec2_vpc_subnet: vpc_id: "{{ vpc_info.vpc.id }}" cidr: "{{ item.dmz_subnet_cidr }}" az: "{{ item.subnet_az }}" region: "{{ region }}" resource_tags: { "Name":"{{ item.dmz_subnet_name }}" } profile: "{{ profile }}" register: pubsub_info with_items: - "{{ dmz_subnet }}" # PRIVATE_SUBNET 作成 - name: create_private_subnet ec2_vpc_subnet: vpc_id: "{{ vpc_info.vpc.id }}" cidr: "{{ item.pri_subnet_cidr }}" az: "{{ item.subnet_az }}" region: "{{ region }}" resource_tags: { "Name":"{{ item.pri_subnet_name }}" } profile: "{{ profile }}" register: prisub_info with_items: - "{{ pri_subnet }}" # IGW 作成 - name: create_igw ec2_vpc_igw: vpc_id: "{{ vpc_info.vpc.id }}" region: "{{ region }}" tags: { "Name":"{{ igw_name }}" } profile: "{{ profile }}" register: igw_info # ROUTETABLE 作成(IGW) - name: create_route_table ec2_vpc_route_table: vpc_id: "{{ vpc_info.vpc.id }}" subnets: "{{ atache_igw_subnet }}" routes: - dest: 0.0.0.0/0 gateway_id: "{{ igw_info.gateway_id }}" region: "{{ region }}" profile: "{{ profile }}" resource_tags: { "Name":"{{ rttable_pub_name }}" } # NGW の ID を取得 - name: get_subnet_id shell: aws ec2 describe-subnets --region {{ region }} --profile {{ profile }} --output text | grep -B 1 {{ ngw_subnet_name }} | awk 'NR==1 {print $12}' register: ngw_subnet_id #- name: show # debug: # msg: "{{ ngw_subnet_id.stdout }}" # NGW 作成 - name: create_ngw ec2_vpc_nat_gateway: subnet_id: "{{ ngw_subnet_id.stdout }}" region: "{{ region }}" profile: "{{ profile }}" register: ngw_info #- name: show # debug: # msg: "{{ ngw_info.nat_gateway_id }}" # NGW 作成まで待つ - name: wait_for_ngw pause: minutes: 5 # ROUTETABLEの作成(NGW) - name: create_route_table2 ec2_vpc_route_table: vpc_id: "{{ vpc_info.vpc.id }}" subnets: "{{ atache_ngw_subnet }}" routes: - dest: 0.0.0.0/0 gateway_id: "{{ ngw_info.nat_gateway_id }}" region: "{{ region }}" profile: "{{ profile }}" resource_tags: { "Name":"{{ rttable_dmz_name }}" }
NATGATEWAY の ID が上手く取得できなかったので awscli の結果をパースして ngw_subnet_id に渡しています。
変数定義
--- # vars file for aws_vpc # REGION region: "ap-northeast-1" # PROFILE profile: "default" # VPC vpc_name: "sanuki-wd-vpc2" vpc_cidr: "10.10.0.0/16" # IGW igw_name: "sanuki-igw2" # NGW ngw_name: "sanuki-ngw2" # NGWを作成するサブネット名 ngw_subnet_name: "sanuki-wd-public-subnet2-a" # ROUTETABLE(PUBLIC) rttable_pub_name: "sanuki-pub-rt2" # ROUTETABLE(DMZ) rttable_dmz_name: "sanuki-dmz-rt2" # PUBLIC_SUBNET pub_subnet: - { pub_subnet_cidr: "10.10.10.0/24" ,subnet_az: "ap-northeast-1a" ,pub_subnet_name: "sanuki-wd-public-subnet2-a" } - { pub_subnet_cidr: "10.10.20.0/24" ,subnet_az: "ap-northeast-1c" ,pub_subnet_name: "sanuki-wd-public-subnet2-c" } # DMZ_SUBNET dmz_subnet: - { dmz_subnet_cidr: "10.10.30.0/24" ,subnet_az: "ap-northeast-1a" ,dmz_subnet_name: "sanuki-wd-dmz-subnet2-a" } - { dmz_subnet_cidr: "10.10.40.0/24" ,subnet_az: "ap-northeast-1c" ,dmz_subnet_name: "sanuki-wd-dmz-subnet2-c" } # PRIVATE_SUBNET pri_subnet: - { pri_subnet_cidr: "10.10.50.0/24" ,subnet_az: "ap-northeast-1a" ,pri_subnet_name: "sanuki-wd-private-subnet2-a" } - { pri_subnet_cidr: "10.10.60.0/24" ,subnet_az: "ap-northeast-1c" ,pri_subnet_name: "sanuki-wd-private-subnet2-c" } # IGWに紐付けるサブネット atache_igw_subnet: - "10.10.10.0/24" - "10.10.20.0/24" # NGWに紐付けるサブネット atache_ngw_subnet: - "10.10.30.0/24" - "10.10.40.0/24"
NatGateway が片方の AZ にしかないため、冗長性の観点からは ? となりますが、まぁいいでしょう。
↓ 2層の playbook はこちら
【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
【シェルスクリプト】だいたいのサーバ情報を取得する便利スクリプト【サーバ移設】
取り敢えずこのスクリプトを実行すれば、ある程度のサーバ情報を取得できるよ、ってだけのスクリプトです。
#!/bin/sh # 情報取得関数 function addinfo(){ # 情報を出力するファイル名を定義 OUTPUT=serverinfo-`hostname`.txt # 情報内容を出力 echo "####### $1 #########" >> $OUTPUT # コマンド結果を出力 $2 >> $OUTPUT return 0 } # ホストネーム addinfo hostname "hostname" # プロセス一覧 addinfo process-list "ps auxwwf" # Listenポート一覧 addinfo listen-port "sudo netstat -lntp" # ルートテーブル addinfo route-table "sudo netstat -rn" # rpmパッケージ addinfo rpm-package "sudo rpm -qa | sort" # 自動起動リスト addinfo chkconfig "sudo chkconfig --list" # OSバージョン addinfo os-version "cat /etc/redhat-release" # CPU addinfo cpu-info "cat /proc/cpuinfo" # メモリ addinfo memory-info "free -m" # ディスク addinfo disk-info "df -hT" # fstab addinfo fstab "cat /etc/fstab" # iptables addinfo iptables "sudo service iptables status" # ifconfig addinfo ifconfig "ifconfig"
【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 もありますが、こちらではグループメトリクスは取得できないようです。