ubuntu に vagrant 環境をつくる
余った PC に ubuntu-mate をインストールしたのでついでに vagrant 環境を作ってみました。
環境
PC | OS |
---|---|
thinkpad X1 | ubuntu 15.04 |
VT-X の有効化
BIOS から VT-X を有効化します。 thinkpad X1 の BIOS 起動手順はこちら
Security
-> Virtualization
-> Intel VT
に進み、Intel Virtualization
Technology
を Enabled
にして再起動します。
Virtual Box のインストール
普通に公式から deb パッケージをインストールしただけだと不足パッケージがあるようで、仮想マシンがうまく動作しませんでした。
冒頭で紹介させていただいたサイトに記載のリポジトリを追加して apt-get
します。
sudo echo "deb http://download.virtualbox.org/virtualbox/debian raring contrib" > /etc/apt/sources.list sudo wget -q http://download.virtualbox.org/virtualbox/debian/oracle_vbox.asc -O- | sudo apt-key add - sudo apt-get update sudo apt-get install virtualbox
vagrant のインストール
公式サイト から deb パッケージをダウンロードしてインストールします。
mkdir ~/src cd ~/src wget https://dl.bintray.com/mitchellh/vagrant/vagrant_1.7.2_i686.deb sudo dpkg --install vagrant_1.7.2_i686.deb
仮想環境を起動する
作業用ディレクトリを作成して、その中で作業します。 今回は公式の centos/7 を利用します。
mkdir -p ~/vagrant/centos7 cd ~/vagrant/centos7 vagrant init centos/7
init 完了後、作成された VagrantFile を1行だけ編集します。
# 29行目をコメントアウト config.vm.network "private_network", ip: "192.168.33.10"
新しめの vagrant コマンドでは公式の box ならば(?) vagrant up
のみでダウンロードから始まるので vagrant box add
しなくていいみたいです。
vagrant up --provier virtualbox
--provider virtualbox
はなくてもOKでした。
その後、vagrant 起動中に自動で yum update
が実行され、host / guest 間でのファイル共有のための rsync フォルダが作成され、そのまま centos が起動しました。
box にも追加されています。
$ vagrant box list centos/7 (virtualbox, 1509.01)
ssh ログインしてバージョンを確認してみます。
$ vagrant ssh [vagrant@localhost ~]$ cat /etc/centos-release CentOS Linux release 7.1.1503 (Core)
ログインできました^^
こちらを参考にさせていただきました。 Ubuntu 15.04にVirtualbox、Vagrantをインストール
postgresql で trigger とその trigger が動作するテーブルの一覧を取得する
SELECT event_object_schema, event_object_table, trigger_schema, trigger_name FROM information_schema.triggers
結果
event_object_schema | event_object_table | trigger_schema | trigger_name ---------------------+-----------------------------+----------------+------------------------------------------- schema | user_table | schema | user_trigger
*
だと action_timing
や event_manipulation
も取得できます。information_schema 便利です。
\d information_schema.triggers View "information_schema.triggers" Column | Type | Modifiers ----------------------------+------------------------------------+----------- trigger_catalog | information_schema.sql_identifier | trigger_schema | information_schema.sql_identifier | trigger_name | information_schema.sql_identifier | event_manipulation | information_schema.character_data | event_object_catalog | information_schema.sql_identifier | event_object_schema | information_schema.sql_identifier | event_object_table | information_schema.sql_identifier | action_order | information_schema.cardinal_number | action_condition | information_schema.character_data | action_statement | information_schema.character_data | action_orientation | information_schema.character_data | action_timing | information_schema.character_data | action_reference_old_table | information_schema.sql_identifier | action_reference_new_table | information_schema.sql_identifier | action_reference_old_row | information_schema.sql_identifier | action_reference_new_row | information_schema.sql_identifier | created | information_schema.time_stamp |
vpc endpoint から s3 へのアクセス制御 (bucket policy)
記載された vpce
と IPアドレスのみ許可する設定例です。
{ "Version": "2012-10-17", "Id": "vpce-restrict", "Statement": [{ "Sid": "Allow-VPCE", "Action": "s3:*", "Principal": { "AWS": "*" }, "Effect": "Allow", "Resource": [ "arn:aws:s3:::bucket-name*", "arn:aws:s3:::bucket-name/*", ], "Condition": { "StringEquals": { "aws:sourceVpce": [ "vpce-********" ] } } }, { "Sid": "IPAddress-restrict", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "s3:*", "Resource": [ "arn:aws:s3:::bucket-name*", "arn:aws:s3:::bucket-name/*", ], "Condition": { "IpAddress": { "aws:SourceIp": [ "***.***.***.***/**" ] } } }] }
この場合、StringEquals
だと許可、 StringNotEquals
だと拒否になりますので、うまいぐあいに使い分けができます。
というか、これに気づかなくてハマってしまった・・・
apache で URL を case insensitive にする
↓ の状態で
# ls /var/www/html/healthcheck.html /var/www/html/healthcheck.html
↓ のように 404 となったので
[Fri Oct 16 13:59:53 2015] [error] [client ***.***.***.***] File does not exist: /var/www/html/HealthCheck.html
産業追記して reload
LoadModule speling_module modules/mod_speling.so CheckSpelling on CheckCaseOnly on
そして HealthCheck.html でアクセスすると
***.***.***.*** - - [16/Oct/2015:13:58:47 +0900] "GET /healthcheck.html HTTP/1.1" 200
200 OK となりました
サポートケースを作成するための iam ポリシー
どうやって制御するんだろうと調べていたら iam policy の中にありました。
IAM > Policies > AWSSupportAccess
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "support:*" ], "Resource": "*" } ] }
というだけの記事でした。
redis-py で expire が付与されていない key を削除する
メモリが逼迫してきた redis で、本来存在しないはずの expire が付与されていない key を削除することになったので記録として。
key は session id として使われています。
環境
前提
- session id は英数小文字と数字が含まれていて、規則性がない
こんなの =>csodes5b5wenrvn0llbfcmme
使ったもの
インストールは pip で一発です。
スクリプトの概要
小文字と数字のランダムな文字列を生成してワイルドカードで keys をたたく
keys *
だと負荷がちょっとこわかったため、ちょっとずつやりたかったのです
*ランダム文字列の生成は こちら のものを使わせていただきました。
DELETE_COUNT の数だけ削除するが、keys コマンドでひっぱってくる数にバラつきがあるので、正確ではない
スクリプト
#!/usr/bin/env/python # -*- coding: utf-8 -*- import os, sys, string, random, time import redis from logging import getLogger import logging logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) logger = getLogger(os.path.basename(__file__)) # configration HOST = sys.argv[1] PORT = 6379 DB = 0 RANDOM_COUNT = 3 DELETE_COUNT = 200000 def connect_redis(h=HOST, p=PORT, d=DB): try: r = redis.StrictRedis(host=h, port=p, db=d) except redis.ConnectionError: logger.error("failed to connect %s" % HOST) logger.exception(e) sys.exit(1) except Exception, e: logger.exception(e) sys.exit(2) finally: return r def get_redis_info(arg): r = connect_redis() info = r.info(arg) return info def check_delete_limit(DB,DELETE_LIMIT): i = get_redis_info("keyspace") if i.has_key("db%s" % DB) == True: d = i.get("db%s" % DB) k = d.get("keys") - d.get("expires") if k <= DELETE_LIMIT: logger.info("limit arrived. stop process.") sys.exit(0) def get_delete_limit(DB,DELETE_COUNT): i = get_redis_info("keyspace") if i.has_key("db%s" % DB) == True: d = i.get("db%s" % DB) k = d.get("keys") - d.get("expires") if k >= DELETE_COUNT: k -= DELETE_COUNT return k elif k == DELETE_COUNT: return k else: logger.info("nothing to delete any more.") sys.exit(0) def gen_rand_str(length, chars=None): if chars is None: chars = string.digits + string.lowercase return ''.join([random.choice(chars) for i in range(length)]) def delete_session_keys(HOST,PORT,DB,RANDOM_COUNT,DELETE_LIMIT): sample_key = "*" + gen_rand_str(RANDOM_COUNT) + '*' # get sample keys r = connect_redis() keys = r.keys(sample_key) if keys is None: logger.info("not found expire keys from sample key.") for k in keys: # skip key "RedisSessionStateStore:LockedSessions" if "LockedSessions" in k: logger.debug("skip delete. key => %s" % k) continue # check ttl each key logger.debug("ttl start") ttl = r.ttl(k) logger.debug("ttl end") if ttl == -1: # delete key r.delete(k) logger.info("delete key => %s" % k) time.sleep(0.1) else: logger.debug("this key has ttl. key => %s , ttl => %s" % (k, ttl)) if __name__ == '__main__': DELETE_LIMIT = get_delete_limit(DB,DELETE_COUNT) while True: check_delete_limit(DB, DELETE_LIMIT) delete_session_keys(HOST,PORT,DB,RANDOM_COUNT,DELETE_LIMIT)
実行
$ python delete_session_keys.py redisのIPアドレスなど delete key => s5zhfytghgdq5bjmkaaqhkf2 delete key => sedhrhftw13jblpawgbvrh4k delete key => s4rewrbhex04fdujbytp3rw5 delete key => skwcm0jigx2arwqwf52sj21n this key has ttl. key => uxxprmpwyjpxqeots1q334lo , ttl => 10503 this key has ttl. key => djfw2py52croafz4gigun0l0 , ttl => 3606
以上です。
ELB に登録されているインスタンスを解除 & 指定したインスタンスを ELB に登録
ELB に登録されているインスタンスを全て解除する
#!/bin/bash aws="/usr/bin/aws --region ap-northeast-1" elb_names=("elb-1" "elb-2") deregister_instances_from_elb() { for elb_name in ${elb_names[@]} do # get registerd instance ids per elb deregister_instance_ids=$(${aws} elb describe-load-balancers \ --load-balancer-names ${elb_name} \ --query 'LoadBalancerDescriptions[].Instances[].InstanceId' \ --output text) # deregister instances from elb ${aws} elb deregister-instances-from-load-balancer \ --load-balancer-name ${elb_name} \ --instances ${deregister_instance_ids} \ || echo "ERROR. failed to deregistered ${deregister_instance_ids} from ${elb_name}" | exit 1 echo "OK. deregistered ${deregister_instance_ids} from ${elb_name}" done } deregister_instances_from_elb
指定したインスタンスを指定した ELB に登録
リストで持たせた NAME TAG から InstanceId を取得して一気に ELB に登録します。 また、登録した全てのインスタンスが InService になるまで待ちます。
#!/bin/bash aws="/usr/bin/aws --region ap-northeast-1" elb_names=("elb-1" "elb-2") regist_servers=("web-1" "web-2" "web-3" "web-4") register_instances_with_elb() { for elb_name in ${elb_names[@]} do # get instance ids from Name Tag for regist_server in ${regist_servers[@]} do regist_instance_id=$(${aws} ec2 describe-instances \ --filters Name=tag-value,Values=${regist_server} \ --query 'Reservations[].Instances[].[InstanceId]' \ --output text) regist_instance_ids+=("$regist_instance_id") done # register instance with elb ${aws} elb register-instances-with-load-balancer \ --load-balancer-name ${elb_name} \ --instances ${regist_instance_ids[@]} \ || echo "ERROR. failed to registered ${regist_instance_id[@]} with ${elb_name}" | exit 1 ## check in service regist_num=${#regist_instance_ids[@]} i=0 while true do in_service=$(${aws} elb describe-instance-health --load-balancer-name ${elb_name} \ --query 'length(InstanceStates[?State==`InService`].[State])') if [ ${in_service} = "${regist_num}" ]; then echo "OK. ${regist_servers[@]} is InService at ${elb_name}" unset regist_instance_ids break fi i=`expr $i + 1` sleep 5 done done } register_instances_with_elb
elb_names と attach_servers の持たせ方を工夫するとメンテナンスとかで使えそうな気がしたので晒してみました。