信頼はずっと、挑戦はもっと。

お問い合わせ
TEL:03-3496-3888

BLOG コアテックの社員ブログ (毎週月曜~金曜更新中)

LIST OF ARTICLES

記事一覧

  • テクログ

    410からの〜お知らせページ表示〜

    内部的に「Lambdaとはなにか会」をやったり「単体テストを普及させて幸せになりたい」なって思っていろいろやったりしてる昨今、いかがおすごしですか。さて、突然ですがステータスコード404ってのはよく見かけますが、410ってあんまりピンと来ないですよね。簡単に言うと404は意図的なのか、単に今みれないのかわからないけど、なんかページがない、410は意図的になくなりました!という、みたいな違いらしいです。参考ページ:https://www.seo-ch.jp/news/470で、特集ページなどをhttps:/サイトドメイン/hogehoge/などで作っていて、特集が終わったりして、『無くなったよ!』と伝えたい気持ちが高まった場合、どうするんでしょうか。(+で、このページはなくなったんです、というお知らせも表示したい気持ちもあります)こうします!ErrorDocument 410 /hogehoge/index.html <IfModule mod_rewrite.c>   RewriteEngine On   RewriteCond %{REQUEST_URI} ^/hogehoge/index.html$   RewriteRule ^.*$ index.html [L]   RewriteCond %{REQUEST_URI} ^/hogehoge/$   RewriteRule ^.*$ index.html [L]   RewriteRule .* - [G] </IfModule> /hogehoge/index.htmlが告知ページです。ルートの場合/またはindex.htmlへのアクセス以外は、一番下の  RewriteRule .* - [G] で410へ飛ばします。それだけだと410エラーが表示されますので、もしも410エラーのときにはindex.htmlを出す、ということを1行目でかいています。これで410を出したい気持ちを解消することができましたね!めでたしめでたし。以下は開催したLambdaとはなにか会のスライドの端っこです。見栄えのためです。
  • テクログ

    コスト配分タグを自動でチェックしたい!

    恒例のしたいシリーズです。いまつくりました。●なにがしたいの?AWSアカウント内に複数の媒体があって、どの媒体にどれだけお金がかかっているかをチェックするために、リソースにProjectタグをつけると簡単に集計できます。でも、リソースは随時増えるし、ちゃんとProjectタグついているのかわからない。なんとかしたいという気持ち。●どうやるの?LambdaでリソースにProjectタグがついているかをチェック。+Projectタグの値もチェック(ちがうのがついてたらこまるからね)チェックしない、というのも設定したい。あと、結果はSlackに通知したりしたい。●具体的には?ソースをはりますんで見てね!EC2のタグチェックの例です。サンプルですよ。・追加ライブラリslackwebいれてください。・使っている環境変数ACCOUNT_NAME AWSアカウントの名前とかをいれます。通知用です。CHECK_TAG_NAME チェックしたいタグをいれます。今回はProjectです。CHECK_TAG_VALUES カンマ区切りで、入っていていほしいタグの値をいれます。aaa.jp,bbb.jp  みたいなのですSLACK_URL SlackのWebhookURLです。・ソース(Pythonらしさはかけらもありませんがゆるしてください# -*- coding: utf-8 -*- # EC2のタグ設定チェック import boto3 import os import slackweb import sys # アカウント名 ACCOUNT_NAME   = os.environ['ACCOUNT_NAME'] # チェックするタグ名 CHECK_TAG_NAME  = os.environ['CHECK_TAG_NAME'] # ついていてほしいタグの内容(どれかならOK) CHECK_TAG_VALUES = os.environ['CHECK_TAG_VALUES'].split(",") #slackurl SLACK_URL    = os.environ['SLACK_URL'] REGION_NAME = 'ap-northeast-1' ##################################################### #本体 ##################################################### def lambda_handler(event, context):   #タグチェック   results = checkTags()   print('checkTags results:')   print(results)   checkResult_AND_Notify(results) ##################################################### # インスタンスID一覧を取得 ##################################################### def checkTags():   instance_list = []   #ページャーで全て取得   client  = boto3.client('ec2', region_name=REGION_NAME)   paginator = client.get_paginator('describe_instances')   # Filterで止まっているものは除外   page_iterator = paginator.paginate(     Filters=[     {       'Name': 'instance-state-name',       'Values': [         'running',       ]     }   ],)   #チェックしていく   for page in page_iterator:     for reservation in page["Reservations"]:       for instance in reservation["Instances"]:         instance_id = instance["InstanceId"]         #Tagsを見て、CheckProjectSettingがNOならば除外(存在しない、またはYESなら追加         check_flag       = True         project_tag_exist_flag = False         project_tag_value   = ""         name_tag_value     = ""         Tags = instance["Tags"]         for tag in Tags:           if tag['Key'] == 'CheckProjectSetting':             if tag['Value'] == 'NO':               print('CheckProjectSetting,NO:' + instance_id)               check_flag = False           if tag['Key'] == 'Project':             project_tag_exist_flag = True             project_tag_value = tag['Value']             print('Project tag_value:' + project_tag_value)           #Nameはわかりやすさのため取ります           if tag['Key'] == 'Name':             name_tag_value = tag['Value']             print('Project tag_value:' + name_tag_value)         if check_flag == True:           print('CheckProjectSetting,YES:' + instance_id)           if project_tag_exist_flag == False:             #タグ自体がない場合は即追加             instance_id_dict = {               "instance_id"    : instance_id,               "name_tag_value"  : name_tag_value,               "project_tag_value" : project_tag_value,               "reason"      : "no_project_tag"             }             instance_list.append(instance_id_dict)           else:             #タグはあった場合、中身を確認し、なかったら一覧追加             if project_tag_value not in CHECK_TAG_VALUES:               instance_id_dict = {                 "instance_id"    : instance_id,                 "name_tag_value"  : name_tag_value,                 "project_tag_value" : project_tag_value,                 "reason"      : "project_tag_not_match"               }               instance_list.append(instance_id_dict)   return instance_list ##################################################### # 漏れがあるものを通知 ##################################################### def checkResult_AND_Notify(results):   print('checkResult_AND_Notify')   exist_no_Tag_Flag = False   res_str = ''   for result in results:     exist_no_Tag_Flag = True     res_str += '&gt;  Name:' + result['name_tag_value'] + ' ID:' + result['instance_id'] + ' 理由:' + result['reason'] +'\n'   if exist_no_Tag_Flag:     title_str = "ProjectタグをつけてないEC2インスタンスがあったよ!付けてね!\n"     slack = slackweb.Slack(url=SLACK_URL)     slack.notify(text=ACCOUNT_NAME + "のProjectタグチェックをしたよ!\n\n" + title_str + res_str)   else:     print("ProjectタグをつけてないEC2インスタンスはなかったよ!") ※Tagsを見て、CheckProjectSettingがNOならば除外やったね!もうタグがあるかどうかをチェックしなくていいよ!肝心のタグ設定は場合によりますので、手動で付けてくださいね。以上!(見栄え用の画像↓)
  • テクログ

    古いGitレポなんかにいられるか!私はCodeCommitにさせてもらう!

    この後すぐ、もしくは後半で藪の中とかで死んでるのが見つかるパターン。 …で、CodeCommitにしたいんです。CodeCommitじゃなくてもいいですが、旧Gitから新Gitへ変えたい。…だけどスパッと切り替えられないんだよねーなかなかねー。 …というときのために。新・旧Git両方にpush。です。 ひとことでいうなら『いま使っているレポジトリのリモートレポジトリ設定に新のURLを増やせばいい』ということです。 丁度使ってたSourceTreeの手順を書いてみますね。(1)旧レポジトリで、右上の「設定」を押します。(2)origin を選択して 「設定ファイルを編集」を押します。開くエディタを聞かれるので、開きます。 これが開いたファイルのイメージです。サンプルです。このファイルの、「pushurl」を2行にします(下に一緒にpushしたいレポジトリ指定を追加します)↓こんな感じになります。    編集後、保存してSourceTreeに戻って、pushテストをしてみましょう。新・旧両方に反映されていればOKです! スムーズに移行したい~
  • テクログ

    vpc内でのRedis使用によって、冪等性を担保したくない?

    キャー!ちょう冪等性担保したいー! Lambdaの冪等性をvpc外で担保する場合、 Dynamoでやっていることが多いですよね。なぜLambdaの冪等性を担保しないといけないかというと、最低1回は実行されるけど、複数回実行されることもあるからです。vpc内でなにかをしたい。外との通信は別にいいかー、じゃあvpc内で担保したいな。ってなるよね。なるなるー。よくあるー。 となると、DynamoはつかえないのでRedisですね。はい、こうなりますよ。いかにもサンプル、なので利用はご自身の責任で。redisはpipでいれてね。import boto3 import redis import logging logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context):     print('start!')     #1分に1回走るとして、その重複を検知するキー     testkey = 'testdesu_2017-10-26_18-00'     redis_host = "lambda-redis-test.hostwo.irete.ne"     ttl = 900#10分強あれば十分すぎる     try:         redis_client = redis.StrictRedis(host=redis_host, port=6379, db=0)         #キーの存在を確認。あるならダブルでやられてるのでダーメ         key_exists = redis_client.exists(testkey)         #print(key_exists)         if key_exists == False:             logger.info('key:' + testkey + ' is not exists.')             redis_client.set(testkey, 'executed')             redis_client.expire(testkey, ttl)             #ここに独自にやりたい処理を入れるよ         else:             #キーがあっても別にエラーではないのでwarn程度             logger.warn('key:' + testkey + ' is already exists.so do nothing.')         logger.info('success')     except Exception as e:         #その他の例外時         logger.error(e)         logger.error('Exception')     print('end!') こんな感じです。 いやーRedisっていいなあ。 
  • テクログ

    (Lambdaで)S3の間違って消しちゃったファイルを元に戻そうのコーナー

    はい、私が消したわけじゃないですよ!わたしたちが消したわけでもございません。ご安心ください。 さーて、時間もないので概要から! こんなことをしたい人にオススメのコーナーです。コーナーですが全1回です。  ・間違ってS3からファイルを消しちゃっても戻せるよ!ってことにしたい。 ・手動だとつらいので自動でしたい。 ・CLIでもできるけどCLIすら打ちたくない。(CLIだとみんなが使えないし打ち間違えとか嫌だし。油断してるとシステムダウンとかするんですよCLIとかコマンドってやつはね…信用できn(ry) さて、ご用意いただくものは以下の通りです。分量をお守りください。  ・バージョニングを有効にしたS3バケット 料理には構想が大事です。どんな感じがいいですかねー、そうですねー、  ・戻したいバケットを指定できる。 ・戻したいパス以下を指定できる。 ・どの時間以降に消しちゃったものを戻すかが指定できる。 こんな感じでどうでしょう。全部戻せる!とか言われてもそんなね、全部戻されても困りますしね。時間指定が今回のワンポイントですよ。betweenはいいでしょう。やっちまったのにbetweenとかそれどころじゃないですよね。強いて言うならば章末の発展課題、Betweenを指定できるように改造してみよう、ということで。 さて、LambdaでPython3.6を選んで作りましょう。消しちゃうってことはイレギュラーなのでトリガーはいらないですね。一回なんでもいいからトリガーを付けて作成し、あとで消しましょうね。 さて、シンプルに味付けをし、一晩寝かせたものがこちらのコードです。環境変数もありますよ。テキストp19をごらんください。…じゃなくて下に書きますね。 # -*- coding: utf-8 -*- #s3で指定したバケット・パス、指定時間(以降)で一気に戻す from __future__ import print_function, unicode_literals import boto3 import os from datetime import datetime,timedelta import time Bucket = os.environ['Bucket'] Prefix = os.environ['Prefix'] #削除フラグを戻す時間(削除フラグがこの時間以降のものなら消す) 2012/12/29 13:49 の形式を受けることにする OR_Lator_RestoreTime_JST = os.environ['OR_Lator_RestoreTime_JST'] def lambda_handler(event, context):     #をUnixtimeに変換     tdatetime = datetime.strptime(OR_Lator_RestoreTime_JST, '%Y/%m/%d %H:%M')     print("入力されたリストア基準時間(JST):" + str(tdatetime))     utc_OR_Lator_RestoreTime = tdatetime + timedelta(hours=-9)     print("入力されたリストア基準時間(UTC):" + str(utc_OR_Lator_RestoreTime))     utc_OR_Lator_RestoreTime_unixtime= time.mktime(utc_OR_Lator_RestoreTime.timetuple())     print("↑のunixtime:" + str(utc_OR_Lator_RestoreTime_unixtime))     client = boto3.client('s3')     paginator = client.get_paginator('list_object_versions')     page_iterator = paginator.paginate(         Bucket=Bucket,         Prefix=Prefix     )     for page in page_iterator:         if 'DeleteMarkers' in page:             print('削除オブジェクトあり')         else:             return '指定した場所に削除されたオブジェクトはありませんでした'         for DeleteMarker in page['DeleteMarkers']:             LastModified_unixtime = time.mktime(DeleteMarker['LastModified'].timetuple())             if LastModified_unixtime > utc_OR_Lator_RestoreTime_unixtime and DeleteMarker['IsLatest'] == True:                 print('判定結果:戻し対象:')                 printKeyInfo(DeleteMarker)                 #戻し処理                 response = client.delete_object(                     Bucket=Bucket,                     Key=DeleteMarker['Key'],                     VersionId=DeleteMarker['VersionId']                 )                 print(response)             else:                 print('判定結果:戻し対象ではない:')                 printKeyInfo(DeleteMarker)     return 'END!' ### #情報ログprint ### def printKeyInfo(DeleteMarker):     print("Key:"          + str(DeleteMarker['Key']))     print("IsLatest:"     + str(DeleteMarker['IsLatest']))     #print(DeleteMarker['VersionId'])     print("LastModified:" + str(DeleteMarker['LastModified']))#UTC  ・使う環境変数Bucket 戻したいバケット名です。Prefix 戻したいパスです。このパス以下が戻す判定対象となります。OR_Lator_RestoreTime_JST 名前わかりづらくてすみません。この時間以降に削除されたものを戻します。指定は 2017/08/10 16:00 みたいなかんじです。 大量に戻したいからLambdaではできないんだ!というあなたのために、実はこれをちょっといじればPythonでのCLI版もできるんですねー。お手軽ですのでそちらも夏の工作としてお子さんと作成して召し上がってみてはいかがでしょう。 では、よい夏を!はーコミケ行きたかったな! 
  • テクログ

    AWSの監視を監視したくありませんか?

    AWSのCloudWatch監視、便利ですよね。でもね、監視が漏れてたりとかしますよね。しない人なんかいない。 監視漏れの確認とかちょう疲れるんですよ。しかも終わりがない。…ということで面倒なことは自動化しましょう。 ●やりたいことAWSのあるリソースについて、[期待している監視]がついているかを自動で確認して、確認結果をSlackとかに通知したい。(とりあえずEC2を対象) ●どうやって?Lambdaで。Pythonでいいかな。3.6です。 ●具体的にはまず[期待している監視]を定義します。MetricName と Alarmのアクション(通知先) が期待しているものだったらOKとします。あと、開発環境や一時的に作成したものなのでアラームチェックから外したい場合もあるので、タグを付けて識別することとします。+漏れたら困るので、タグがついていない場合も監視対象とします。タグは CheckAlarmSetting って名前にして、NOなら監視しない。それ以外なら監視する。です。 流れは(1)インスタンス一覧を取得(現在動いているものに絞る + タグで絞り込み)(2)CloudWatchのアラーム一覧を取得して、(1)で取得したインスタンス一覧に該当するものについて、 期待しているアラームが付いているかを確認。(3)結果をみてわかりやすい感じにしてSlackへ通知。(てっくんに喋らせてます) です。 ●使うものLambdaの環境変数に以下を設定: ACCOUNT_NAME → 複数のAWSアカウントがあると、どれをチェックしたのかわかんないので動的になるため。CHECK_METRIC_NAMES → 監視したいメトリック名 これらがついてない場合にはちゃんとついてない!って言われる。               複数あると思うので、カンマ区切りで設定します。CHECK_ALARM_ACTION → アラームについていてほしいARN。監視してても通知先がなかったり違ったら意味ないですから。               複数あると思うので、カンマ区切りで設定します。ARNはWebコンソールで見てください。SLACK_URL → SlackのWebhookのURLです。 詳細はこちらなどをご参照ください。  ライブラリ:slackwebslackwebpipしましょう。 ロール:EC2とLambdaが使える感じのを作って付けましょう。 ●ソース # -*- coding: utf-8 -*- # EC2のアラーム設定チェック import boto3 import os import slackweb ##################################################### #設定 ##################################################### # アカウント名 ACCOUNT_NAME       = os.environ['ACCOUNT_NAME'] # ついていてほしいCloudWatchのMetricName CHECK_METRIC_NAMES = os.environ['CHECK_METRIC_NAMES'].split(",") #slackurl(あれならKMSで暗号化もしてください) SLACK_URL          = os.environ['SLACK_URL'] # ついていてほしいAlarmのアクション CHECK_ALARM_ACTION = os.environ['CHECK_ALARM_ACTION'].split(",") REGION_NAME = 'ap-northeast-1' ##################################################### #本体 ##################################################### def lambda_handler(event, context):     #まずインスタンスIDの一覧を取得する(今動いているもの)     instance_lists = get_InstanceList()     print('CheckInstanceList:')     print(instance_lists)     #アラームをチェック     instance_list_results = check_CloudWatchAlarmList(instance_lists)     print('CheckInstanceResult:')     print(instance_list_results)     #チェック結果を確認して、通知     checkResult_AND_Notify(instance_list_results) ##################################################### # インスタンスID一覧を取得 ##################################################### def get_InstanceList():     instance_list = []     #ページャーで全て取得     client    = boto3.client('ec2', region_name=REGION_NAME)     paginator = client.get_paginator('describe_instances')     # Filterで動いているものだけにする     page_iterator = paginator.paginate(         Filters=[         {             'Name': 'instance-state-name',             'Values': [                 'running',             ]         }     ],)     #instanceIDを取得     for page in page_iterator:         for reservation in page["Reservations"]:             for instance in reservation["Instances"]:                 instance_id  = instance["InstanceId"]                 #Tagsを見て、CheckAlarmSettingがNOならば除外(NOではない、またはタグが存在しないなら追加                 check_flag = True                 Tags = instance["Tags"]                 for tag in Tags:                     if tag['Key'] == 'CheckAlarmSetting':                         if tag['Value'] == 'NO':                             print('CheckAlarmSetting,NO:' + instance_id)                             check_flag = False                 if check_flag == True:                     print('CheckAlarmSetting,YES:' + instance_id)                     instance_id_dict = {instance_id : list(CHECK_METRIC_NAMES)}                     instance_list.append(instance_id_dict)     return instance_list ##################################################### # CloudWatchのアラーム一覧を取得し、チェック ##################################################### def check_CloudWatchAlarmList(instance_lists):     cloud_watch_client    = boto3.client('cloudwatch', region_name=REGION_NAME)     cloud_watch_paginator = cloud_watch_client.get_paginator('describe_alarms')     page_iterator = cloud_watch_paginator.paginate()     for page in page_iterator:         alarms = page['MetricAlarms']         for alarm in alarms:             # それぞれのアラームについて、期待した宛先があるかを確認             # +ついてないものがチェック対象のものならば通知             checkAction = False             for AlarmAction in alarm['AlarmActions']:                 if AlarmAction in CHECK_ALARM_ACTION:                     checkAction = True             if alarm['Namespace'] == 'AWS/EC2':                 i = 0                 for instance_list in instance_lists:                     instance_id = alarm['Dimensions'][0]['Value']                     if instance_id in instance_list:                         if checkAction == False:                             slack = slackweb.Slack(url=SLACK_URL)                             slack.notify(text=ACCOUNT_NAME + "のEC2アラームチェック途中だけど、\n" + alarm['AlarmName'] + "\nのアラームの宛先にxxxx@xxxxxxがないよ!つけてね!")                         #元の一覧からアラームを取り除いていって、残ったらそれが付いていない、ということなので警告をだす。                         if alarm['MetricName'] in instance_lists[i][instance_id]:#必要なもの以外のアラームが付いていてもエラーとはしない                             instance_lists[i][instance_id].remove(alarm['MetricName'])                     i += 1     return instance_lists ##################################################### # 結果を確認し、漏れがあるかどうかを通知 ##################################################### def checkResult_AND_Notify(instance_list_results):     print('checkResult_AND_Notify')     client    = boto3.client('ec2', region_name=REGION_NAME)     exist_no_Alarm_Flag = False     res_str = ''     for instance_list_result in instance_list_results:         for result in instance_list_result.items():             if len(result[1]) != 0:                 exist_no_Alarm_Flag = True                 no_Alarm_instance_id = result[0]                 print('no_Alarm_instance_id:' + no_Alarm_instance_id)                 res = client.describe_instances(                     InstanceIds=[                         no_Alarm_instance_id                     ]                 )                 for tag in res['Reservations'][0]['Instances'][0]['Tags']:                     if tag['Key'] == 'Name':                         res_str += '>    Name:' + tag['Value'] + '    インスタンスID:' + no_Alarm_instance_id + '\n'     if exist_no_Alarm_Flag:         title_str = "アラームをつけてないEC2インスタンスがあったよ! アラームを付けてね!\n"     else:         title_str = "アラームをつけてないEC2インスタンスはなかったよ!\n"     slack = slackweb.Slack(url=SLACK_URL)     slack.notify(text=ACCOUNT_NAME + "のEC2アラームチェックをしたよ!\n\n" + title_str + res_str)  …という感じです。 コアテックでは他にもRDS,ElastiCache,DynamoDB,Lambdaのアラーム監視もやってます。結構返り値とか呼び方が違ってたりして、EC2のをそのまま利用できる!って感じではなかったですが、一度作ればもう手動チェックはいらなくなるのでおためしください!