cloudmapperに入門した
awsの構成変更を行う場合、Document更新を忘れるので良い方法がないか調査した。
本来なら構成変更を行ったタイミングで自動化してDocument更新をするのが良いが効果的な方法が見つからない。
cloudmapperを使用した場合、現時点での構成が図表されるので代替え案として検討した。
導入する為に行った時の勉強メモ。
- 以下構築要件
■下記に導入〜動作確認までを記載する
● OSに必要環境セットアップ
$sudo yum install autoconf automake libtool python3-devel.x86_64 python3-tkinter python34-devel awscli w3m jq $virtualenv venv $python --version $pip install -r requirements.txt
● cloudmapperインストール
$git clone https://github.com/duo-labs/cloudmapper.git
● ユーザーが未作成の場合、コンソールより作成
$aws --profile cloudmapper iam create-user --user-name cloudmapper
● accounts確認
[ec2-user@ip-172-31-xxx-xxx cloudmapper]$ cat config.json { "accounts": [ {"id": "123456789012", "name": "aws-account-1", "default": true} ], "cidrs": { "1.1.1.1/32": {"name": "SF Office"}, "2.2.2.2/28": {"name": "NY Office"} } }
● credentialsファイル確認
[ec2-user@ip-172-31-xxx-xxx cloudmapper]$ cat ~/.aws/credentials [default] aws_access_key_id = ********* aws_secret_access_key = ********* [cloudmapper] aws_access_key_id = ********* aws_secret_access_key = *********
● 起動
$cd /home/ec2-user/cloudmapper $./collect_data.sh --account aws-account-1 --profile cloudmapper $python cloudmapper.py prepare --account aws-account-1 $python cloudmapper.py webserver --public --port 8001
※ 一部起動パラメータが変更になっているので調整する
$ python cloudmapper.py webserver {args}
def run(arguments):
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument(
"--port",
help="Port to listen on",default=8000,type=int)
parser.add_argument(
"--public",
dest='is_public',help="Allow connections from 0.0.0.0 (or :: if --ipv6 was provided) as opposed to only localhost",action='store_true')
parser.add_argument(
"--ipv6",
dest='is_ipv6',help="Listen on IPv6",action='store_true')
● 動作確認
$curl http://localhost:8001/ $w3m http://localhost:8001/
以下のように、VPCやSubnetのレイアウトやSecurity Groupによるアクセス許可を可視化できる
(README.mdより引用)
Ansibleを使用した構成管理に入門した
ansibleを使用して構成管理をする場合の条件分岐方法の調査を行った時の勉強メモ。
- 以下構築要件
- Ansibleで構成管理を行う(冪等性の担保)
- Ansibleで各環境毎に設定内容を書き換える
- PRD(Production)/STG(Staging)/sandbox等
■下記に各設定サンプルのconfファイルを記載する
- template/prd.confの設定
<source> @id prd_src @type config_expander <config> @type tail @label @{{ td_agent_label }} read_from_head true path /home/prd/logs/*.log pos_file /var/log/td-agent/prd.pos format none message_key log_line tag {{ td_agent_tag }} </config> </source>
- template/sbx.confの設定
<source> @id sbx_src @type config_expander <config> @type tail @label @{{ td_agent_label }} read_from_head true path /home/sbx/logs/*.log pos_file /var/log/td-agent/sbx.pos format none message_key log_line tag {{ td_agent_tag }} </config> </source>
- template/td-agent.confの設定
{% if is_sandbox %} @include sbx.conf {% else %} @include prd.conf {% endif %}
- group_vars/servers.ymlの設定
is_sandbox: True tdagent_force_restart: False tdagent_conf_dir: "{{ inventory_dir }}/templates/td-agent" td_agent_label: test-pjt td_agent_tag: stage-src-tag td_agent_loginfo_group: test-grp tdagent_conf_files: - { src: "{{ tdagent_conf_dir }}/td-agent.conf.j2", dest: "td-agent.conf" } - { src: "{{ tdagent_conf_dir }}/in.www.nginx.access.conf.j2", dest: "in.www.nginx.access.conf" } - { src: "{{ tdagent_conf_dir }}/in.www.nginx.error.conf.j2", dest: "in.www.nginx.error.conf" } - { src: "{{ tdagent_conf_dir }}/out.conf.j2", dest: "out.conf" } tdagent_root_exec: True
- hostsの設定(inventory)
[all:vars] ansible_connection=ssh ansible_user=username ansible_ssh_pass=userpwd ansible_sudo_pass=rootpwd [servers] vm1234 ansible_host=172.31.100.1 newrelic_install=true
- servers.ymlの設定(playbook)
--- - hosts: servers become: yes strategy: free become_method: su become_user: root roles: - { role: newrelic, when: "newrelic_install == 'true'" }
- playbook実行
# ansible-playbook -i hosts -u username servers.yml -K -S --diff
Ansibleを使用した構成管理構成を構築した。
冪等性の担保、コンテナ化した構成管理時に効率的に運用管理が行う事が可能。
CI/CD、デプロイ等を絡めた構成管理が前提の状況な為、知識を確実に体系化する必要がある。
Amazon Kinesis Client Library (KCL)を使用したログ収集基盤構成
Amazon Kinesis Client Library (KCL)を使用したログファイル収集基盤構成を構築する必要があり、調査を行った時の勉強メモ。
以下構築要件
KCLの設定
[ec2-user@ip-172-xx-xx-xx aws-kinesis]$ cat agent.json { "awsAccessKeyId": "******", "awsSecretAccessKey": "******", "cloudwatch.endpoint": "monitoring.ap-northeast-1.amazonaws.com", "cloudwatch.emitMetrics": true, "kinesis.endpoint": "", "firehose.endpoint": "firehose.ap-northeast-1.amazonaws.com", "flows": [ { "filePattern": "/tmp/test.log", "deliveryStream": "teststream", "dataProcessingOptions": [ { "optionName": "LOGTOJSON", "logFormat": "COMMONAPACHELOG", "matchPattern": "^([\\d.]+) - - \\[([\\w:/]+).*\\] \"(\\w+) /(\\w+).*(\\d.+)\" (\\d{3}) (\\d+) \"(\\S+)\" \"(.*?)\" ([\\d.]+) \"(.*?)\" (\\d+);(\\d+)", "customFieldNames": ["client_ip", "time_stamp", "verb", "uri_path", "http_ver", "http_status", "bytes", "referrer", "agent", "response_time", "graphql", "company_id", "user_id"] } ] } ] }
- サンプルデータ作成スクリプト
[ec2-user@ip-172-xx-xx-xx ~]$ cat test.sh #!/bin/bash start=$(date) for i in $(seq 1 ${1}) do echo ${i} echo -e "$( echo $(cat sample.json))" >> /tmp/test.log sleep 0.01s done echo ${start} date
- サンプルデータのフォーマット確認
[ec2-user@ip-172-xx-xx-xx ~]$ cat sample.json 111.111.111.111 - - [02/Dec/2016:13:58:47 +0000] "POST /graphql HTTP/1.1" 200 1161 "https://www.myurl.com/endpoint/12345" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36" 0.172 "query user userMessages hasPermissions F0 F1" 11111;222222
KCL ライブラリを使用したログ収集基盤構成を構築した。
収集時、アグリゲーターでtd-agentを使用した環境と比較し、安易に送信及び構築が可能な為、今後は本環境を使用した基盤構成を行うケースが増えそうです。
aws cloud watchの各使用状況詳細
aws cloudwatchで各使用状況を確認出来るが、各コストに関して詳細に調査する必要があり、調査を行った時の勉強メモ。
・Daily total cost https://console.aws.amazon.com/cost-reports/home?#/custom?groupBy=Service&hasBlended=false&hasAmortized=false&excludeDiscounts=true&excludeTaggedResources=false&timeRangeOption=Custom&granularity=Daily&reportName=&reportType=CostUsage&isTemplate=true&filter=%5B%5D&chartStyle=Group&forecastTimeRangeOption=None&usageAs=usageQuantity&startDate=2018-12-24&endDate=2019-01-18
・有償メトリクス(s3/kinesis shard) https://console.aws.amazon.com/cost-reports/home?#/custom?groupBy=Operation&hasBlended=false&hasAmortized=false&excludeDiscounts=true&excludeTaggedResources=false&timeRangeOption=Custom&granularity=Daily&reportName=&reportType=CostUsage&isTemplate=true&filter=%5B%7B%22dimension%22:%22Service%22,%22values%22:%5B%22AmazonCloudWatch%22%5D,%22include%22:true,%22children%22:null%7D%5D&chartStyle=Stack&forecastTimeRangeOption=None&usageAs=usageQuantity&startDate=2018-12-30&endDate=2019-01-20 Gourp by : API Operation Filters > Service : CloudWatch PutMetricDataの詳細情報取得 -> CloudTrail logにてAPI Callが記録
・Kinesisデータ保持期間 https://console.aws.amazon.com/cost-reports/home?#/custom?groupBy=UsageType&hasBlended=false&hasAmortized=false&excludeDiscounts=true&excludeTaggedResources=false&timeRangeOption=Custom&granularity=Daily&reportName=&reportType=CostUsage&isTemplate=true&filter=%5B%7B%22dimension%22:%22Service%22,%22values%22:%5B%22Amazon%20Kinesis%22%5D,%22include%22:true,%22children%22:null%7D%5D&chartStyle=Stack&forecastTimeRangeOption=None&usageAs=usageQuantity&startDate=2018-12-25&endDate=2019-01-20 Group by : Usage Type Filters > Service : kinesis
cloud watchを使用したモニタリング環境での各値確認まで完了した。
サーバレスアーキテクチャ等でモニタリング監視を行うケースが増えそうなので確認方法を確立しておく必要ありそうです。
fluentdで送信recordに文字列を代入してから送信する
タイトル通り実装する要件があり、調査・設定行った時の勉強メモ。
fluentdを使用したログ集約環境で、送信データの特定フィールドの値をごにょごにょ加工したい(次工程に渡す)っていう要件があります。
調査の結果、fluentdのfilter_record_transformerプラグインで実装可能との事で設定してみた。
record_transformer Filter Plugin | Fluentd
- 構築手順
- td-agent-gem install fluentd -v 0.12.x
- ※今回はVersion
0.12.x
を使用 - ※fluentdに内包されているのでプラグインのインストールは必要ありません
- ※今回はVersion
- out.conf(送信設定conf)作成
- td-agent再起動(設定反映)
- td-agent-gem install fluentd -v 0.12.x
書き方は以下ようになります。
タイトルで代入と記載してますが、代入時に同名のフィールドがあればその値が代入項目にマップされる動作になっています。
<filter foo.bar> @type record_transformer <record> hostname "#{Socket.gethostname}" tag ${tag} </record> </filter>
また、enable_rubyオプションを有効にした場合、Ruby式の評価結果を値にする事が可能です。
計算処理や文字列操作なんかで使えそうで便利です。
以下にサンプル処理を記載します。
特定recordに新規項目代入・含まれる特定の文字列削除(gsubメソッド使用)・更新等で使用可能です。
# ### sample log scrubbing filters # #replace social security numbers # <filter reform.**> # @type record_transformer # enable_ruby true # <record> # log ${record["log"].gsub(/[0-9]{3}-*[0-9]{2}-*[0-9]{4}/,"xxx-xx-xxxx")} # </record> # </filter> # # replace credit card numbers that appear in the logs # <filter reform.**> # @type record_transformer # enable_ruby true # <record> # log ${record["log"].gsub(/[0-9]{4} *[0-9]{4} *[0-9]{4} *[0-9]{4}/,"xxxx xxxx xxxx xxxx")} # </record> # </filter> # # replace email addresses that appear in the logs # <filter reform.**> # @type record_transformer # enable_ruby true # <record> # log ${record["log"].gsub(/[\w+\-]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+/i,"user@email.tld")} # </record> # </filter> # # replace url addresses that appear in the logs # <filter reform.**> # @type record_transformer # enable_ruby true # <record> # log ${record["log"].gsub(/\.sub\.test\.com|\.sub\.test\.co\.jp/,"")}} # </record> # </filter> # ### end sample log scrubbing filters
これでログ集約時、送信前に加工処理し送信可能です。
amazon linux2でのpython3環境構築
Lambdaをpython3で書く必要があり、まずは環境構築を行った時の勉強メモ。
- 構築手順
- python3 install
- pip3 install
- reqest package作成
- boto3 package作成
- Token取得
- ※取得したTokenが正常か確認
・python3 install $ sudo yum install python36 python36-virtualenv python36-pip $ python3 -V Python 3.6.5 ・pip3 install install python3-pip ・reqest package pip3 install requests -t ./ rm -rf *.dist-info bin pip3 install pipdeptree sudo pip3 install pipdeptree zip -r reqest.zip ./* ・boto3 package pip install -t ./python boto3 zip -r boto3-1.9.67.zip python cp boto3-1.9.67.zip /home/ec2-user/ [2019.02.14 add] aws linux(ec2/旧環境)で「No package」対応 ># yum install python3 >Loaded plugins: priorities, update-motd, upgrade-helper >amzn-main/latest | 2.1 kB 00:00 >amzn-updates/latest | 2.5 kB 00:00 >21 packages excluded due to repository priority protections >No package python3 available. >Error: Nothing to do ・現環境確認 pip --version ・Repository確認 yum list available | grep "python" | grep "libs" ・python3インストール yum install python36 python36-virtualenv python36-pip pip-3.6 -V ・必要パケージ収集 mkdir lambda_test/ cd lambda_test/ pip install --upgrade pip pip-3.6 install requests bs4 slackweb -t . rm -rf *.dist-info *.egg-info bin ・パケージ化 zip -r scraping_pkg.zip ./*
・Token取得について
https://api.slack.com/apps/AE******/oauth? ->[OAuth&Permission] ->「Bot User OAuth Access Token」
Tokenが正常認証許可するか確認
https://slack.com/api/chat.postMessage?token=xoxb-xxxxxx-xxxxxx-xxxxxx&channel=test&text=%22Hello%22
↓結果
{"ok":true,"channel":"CERG265JT","ts":"1545287527.000100","message":{"type":"message","subtype":"bot_message","text":"\"Hello\"","ts":"1545287527.000100","username":"slack-test-func","bot_id":"BE9TMPEUQ"}}
まず、python3→Token取得まで確認した。
サーバレスアーキテクチャでLambdaを選択する場合に使えそう。
ref)
https://goodbyegangster.hatenablog.com/entry/2018/05/22/024513
https://qiita.com/SHASE03/items/16fd31d3698f207b42c9
https://qiita.com/hayao_k/items/b9750cc8fa69d0ce91b0
https://qiita.com/ykhirao/items/3b19ee6a1458cfb4ba21
aws cuiを使用してKinesis streamデータ登録・確認
Kinesisはライブラリとして使用する事が多い為、実際の挙動を把握せず使ってるので調査した時の勉強メモ。
実際の挙動を把握する事で障害対応等で効率的に行動出来るようにする。
■ストリーム作成
aws kinesis create-stream --stream-name <ストリーム名> --shard-count <シャード数>
■レコード登録
# "ShardId": "shardId-000000000000" と出力されればOK aws kinesis put-record --stream-name <ストリーム名> --partition-key 123 --data <レコードに保存したい文字列>
■レコード確認
aws kinesis get-shard-iterator --shard-id shardId-000000000000 --shard-iterator-type TRIM_HORIZON --stream-name <ストリーム名> --query 'ShardIterator' { "ShardIterator": "AAAAAAAAAAE2R*******************==" } aws kinesis get-records --shard-iterator "AAAAAAAAAAE2R*******************==" { "Records": [ { "Data": "aG9nZWhvZ2U=", "PartitionKey": "123", "ApproximateArrivalTimestamp": 1546849899.19, "SequenceNumber": "49591791737946085028906975044094438871988285374419959810" }, { "Data": "aG9nZTE=", "PartitionKey": "123", "ApproximateArrivalTimestamp": 1546851156.579, "SequenceNumber": "49591791737946085028906975051711880461380150184625831938" } ], "NextShardIterator": "AAAAAAAAAAFQkY****************==", "MillisBehindLatest": 0 }
■簡易確認の為、上記手順をスクリプト化
$ cat chk-kinesis-record.sh #!/bin/bash KINESIS_NAME=<ストリーム名> # 引数チェック #echo "args = "$# ARGS1=${1:?} #echo $ARGS1 # レコード登録 aws kinesis put-record --stream-name $KINESIS_NAME --partition-key 123 --data $ARGS1 # shardIdからiterator値取得 SHARD_ITERATOR=$(aws kinesis get-shard-iterator --shard-id shardId-000000000000 --shard-iterator-type TRIM_HORIZON --stream-name $KINESIS_NAME --query 'ShardIterator') # レコード取得 aws kinesis get-records --shard-iterator $SHARD_ITERATOR
■kinesis→レコード登録・確認
- スクリプト引数として、登録レコード文字列指定
$ ./chk-kinesis-record.sh hoge1 { "ShardId": "shardId-000000000000", "SequenceNumber": "49591791737946085028906975051711880461380150184625831938" } { "Records": [ { "Data": "aG9nZWhvZ2U=", "PartitionKey": "123", "ApproximateArrivalTimestamp": 1546849899.19, "SequenceNumber": "49591791737946085028906975044094438871988285374419959810" }, { "Data": "aG9nZTE=", "PartitionKey": "123", "ApproximateArrivalTimestamp": 1546851156.579, "SequenceNumber": "49591791737946085028906975051711880461380150184625831938" } ], "NextShardIterator": "AAAAAAAAAAFQkY****************==", "MillisBehindLatest": 0 }
指定データをKinesisがBase64 エンコーディング後、Dataに文字列が格納される。
Base64 デコーディングする事により元データ参照可能。
Base64 エンコーディング・デコーディングサイト:
Base64 Decode and Encode - Online
また、時刻に関してはtimestamp形式で格納される。
UNIX時間(UNIX時刻)から日付に変換サイト:
UNIX時間⇒日付変換 - 高精度計算サイト
■ストリーム削除
aws kinesis delete-stream --stream-name <ストリーム名>
■AWS WEBコンソールからKinesisのData Streamの挙動モニタリング
AWS Kinesis → Data Stream → ストリーム名 → モニタリングへ移動
- 下記図を確認
- GetRecords.Bytes
- GetRecords.Records
- PutRecord.Bytes
- PutRecords.Records
図の中に青い丸(単一データ)、又は青い線(複数データ)でグラフ化されているば正常
- ※ 上部赤い線は制限値(Maxの値)なので無視で問題ない