月: 2018年9月

  • unsubscribeされてしまったcloudwatch (SNS)通知を検知する

    unsubscribeされてしまったcloudwatch (SNS)通知を検知する

    はじめに

    AWSでcloudwatchで監視し、異常があったらSNSで通知する事はあるが、SNSではデフォルトで「配信停止(unsubscribe)する場合は、ここクリックしてね」とありがたいことに(?)記載されてある。

    チーム開発しているとSNSの通知先がメーリングリストにしていると、誤って押されてしまうと、その後のメールが来なくなってしまう。

    配信停止(unsubscribe)を押された場合検知はさっくり作れたのでそれをまとめる

    手順

    awsコマンドとjqコマンドをうまく組み合わせる

    aws sns list-subscriptions | jq -r '.Subscriptions[] | select(.SubscriptionArn == "Deleted") '

    結果

    aws sns list-subscriptions | jq -r '.Subscriptions[] | select(.SubscriptionArn == "Deleted") '
    {
      "SubscriptionArn": "Deleted",
      "Owner": "xxxxxxxxxx",
      "Protocol": "email",
      "Endpoint": "sute@sumito.jp",
      "TopicArn": "arn:aws:sns:ap-northeast-1:xxxxxxx:xxxxxxxxx"
    }
    

    unsubscribeされたメールドレスや、TopicArn情報などを確認することができる。

    ちなみにチャットワークに通知する場合は以下の通りシェルでラップする

    #!/bin/bash
    aws --profile=$1 sns list-subscriptions | jq -r '.Subscriptions[] | select(.SubscriptionArn == "Deleted") ' > /tmp/check-unsubscribe.$1
    
    # 文字を整形する
    # headder
    cat << _EOT_ > /tmp/check-unsubscribe.$1.txt
    [info]
    [title]Someone clicked unsubscribe link
    [/title]
    _EOT_
    
    # contents
    cat  /tmp/check-unsubscribe.$1 >> /tmp/check-unsubscribe.$1.txt
    echo "[/info]"  >> /tmp/check-unsubscribe.$1.txt
    
    _roomid=xxxxxxxxxxxxx # (your chatroom id)
    _body=`cat /tmp/check-unsubscribe.$1.txt`
    
    # 1件以上あれば通知する
    if [ `wc -l /tmp/check-unsubscribe.$1 | awk '{print $1}'` -gt 0 ] ; then
        curl -X POST -H "X-ChatWorkToken: 123456789" -d "body=${_body}" "https://api.chatwork.com/v2/rooms/${_roomid}/messages"
    fi
    
    exit 0

     

  • ZipFile length cannot exceed 4096 characters. For larger source use S3Bucket/S3Key properties instead.

    ZipFile length cannot exceed 4096 characters. For larger source use S3Bucket/S3Key properties instead.

    はじめに

    ymlファイルをCloudFormationでデプロイした時、というエラーが出た。

    When yml file is deployed with CloudFormation, bellow error was happened.

    ZipFile length cannot exceed 4096 characters. For larger source use S3Bucket/S3Key properties instead.

     

    原因 reason

    zip化する際に含まれるコードが4096文字を越えると本エラーに陥る。

    This error occurs when the code included in zipping exceeds 4096 characters.

    対処 deal

    いらないところを削除するなどして、コードをコンパクトにする。

    Make the code more compact by deleting unnecessary parts.

  • mysqlのデータをembulkでBigQueryへ入れredashで確認する

    mysqlのデータをembulkでBigQueryへ入れredashで確認する

    はじめに

    データ解析するにあたり、BigQueryを使いたい事がある。mysqlからデータを取得するところをembulkを使う。embulkのインストール方法から簡単な使い方までまとめた。

    embulkのインストール

    embulkはJavaで作られており、一からinstallしようとすると、割と面倒。今回はDockerを使うこととする。

    BigQueryの設定

    APIs & Servicesでcredentialを作成する。

    jsonファイルダウンロードできるので、適宜保存する。

    Dockerfileを作成

    GCPにプロジェクトを作り、bigqueryに権限を付与。APIで操作できるようjsonファイルを取得する。

    FROM java:7
    MAINTAINER sumito.tsukada "tsukada@sumito.jp"
    
    ENV EMBULK_VERSION 0.8.39
    
    RUN curl -L https://bintray.com/artifact/download/embulk/maven/embulk-${EMBULK_VERSION}.jar -o /opt/embulk.jar
    RUN java -jar /opt/embulk.jar gem install embulk-input-mysql
    RUN java -jar /opt/embulk.jar gem install embulk-output-bigquery
    
    WORKDIR /work
    ENTRYPOINT ["java", "-jar", "/opt/embulk.jar"]
    CMD ["--help"]

    build

    # docker build -t tsukada/embulk .
    Sending build context to Docker daemon  2.048kB
    Step 1/9 : FROM java:7
     ---> 5dc48a6b75af
    Step 2/9 : MAINTAINER sumito.tsukada "tsukada@sumito.jp"
     ---> Using cache
     ---> bc78ed50d614
    Step 3/9 : ENV EMBULK_VERSION 0.8.39
     ---> Using cache
     ---> 266476a95a55
    Step 4/9 : RUN curl -L https://bintray.com/artifact/download/embulk/maven/embulk-${EMBULK_VERSION}.jar -o /opt/embulk.jar
     ---> Using cache
     ---> b21e71d6ce44
    Step 5/9 : RUN java -jar /opt/embulk.jar gem install embulk-input-mysql
     ---> Using cache
     ---> 2fb224b24c49
    Step 6/9 : RUN java -jar /opt/embulk.jar gem install embulk-output-bigquery
     ---> Running in b27f12583137
    2018-09-18 02:50:32.526 +0000: Embulk v0.8.39
    
    ********************************** INFORMATION **********************************
      Join us! Embulk-announce mailing list is up for IMPORTANT annoucement such as
        compatibility-breaking changes and key feature updates.
      https://groups.google.com/forum/#!forum/embulk-announce
    *********************************************************************************
    Gem plugin path is: /root/.embulk/jruby/2.3.0
    
    Successfully installed uber-0.1.0
    Successfully installed declarative-0.0.10
    Successfully installed declarative-option-0.1.0
    Successfully installed representable-3.0.4
    Successfully installed retriable-3.1.2
    Successfully installed public_suffix-3.0.3
    Successfully installed addressable-2.5.2
    Successfully installed mime-types-data-3.2018.0812
    Successfully installed mime-types-3.2.2
    Successfully installed multipart-post-2.0.0
    Successfully installed faraday-0.15.2
    Successfully installed multi_json-1.13.1
    Successfully installed jwt-2.1.0
    Successfully installed signet-0.9.2
    Successfully installed memoist-0.16.0
    Successfully installed os-1.0.0
    Successfully installed googleauth-0.6.6
    Successfully installed httpclient-2.8.3
    Successfully installed google-api-client-0.24.0
    Successfully installed thread_safe-0.3.6-java
    Successfully installed tzinfo-1.2.5
    Successfully installed time_with_zone-0.3.1
    Successfully installed embulk-output-bigquery-0.4.9
    23 gems installed
     ---> 74e55d0084d6
    Removing intermediate container b27f12583137
    Step 7/9 : WORKDIR /work
     ---> 19d9c56bf738
    Removing intermediate container c73ef21e7b6c
    Step 8/9 : ENTRYPOINT java -jar /opt/embulk.jar
     ---> Running in 4bca2f2ed68e
     ---> b4458584af6f
    Removing intermediate container 4bca2f2ed68e
    Step 9/9 : CMD --help
     ---> Running in 7fdbd68d5021
     ---> 0bfdab6b8d24
    Removing intermediate container 7fdbd68d5021
    Successfully built 0bfdab6b8d24
    Successfully tagged tsukada/embulk:latest

    embulkの設定

    今回はmysqlからデータを抜き、BigQueryに入れるとする。

    in:
      type: mysql
      user: redash
      password: passwd
      database: sample
      host: 127.0.0.1
      query: "select date, user from sampletable"
    out:
      type: bigquery
      auth_method: json_key
      json_keyfile: tsukada-bigquery.json
      path_prefix: /tmp/
      file_ext: .csv.gz
      source_format: CSV
      project: 12345679
      dataset: table123
      auto_create_table: true
      table: user_data
      formatter: {type: csv, charset: UTF-8, delimiter: ',', header_line: false}
      encoders:
      - {type: gzip}

    実行

    docker run -t -v ${PWD}:/work tsukada/embulk run sample.yml

    以下のようい表示されればOK

    [INFO] (main): Committed.

    BigQueryで確認

    データが入ったという事がわかった。
    また、

    #standardSQL

    と書いてあるが、これはコメントではなく、BigQueryが判断する重要な宣言になるので削除するとうまく動かないので注意。

     

    redashでBigQueryに接続

    先ほど使ったjsonファイルと接続先のプロジェクトIDを入力すると、redashからbigqueryへ接続する事ができる。

     

     

  • Linux/Macで好きな容量のファイルを作成する

    Linux/Macで好きな容量のファイルを作成する

    はじめに

    一定の容量のあるただのファイルを作成したいことがたまにある。例えばwordpressのupload容量を変更した際の動作テストを行ったりとかが一例。linuxのみならずmacでもddコマンドで簡単に作成することができるのでその方法を紹介。

    ddコマンド

    linuxもmacも共通の手順はこちら(macで実施した際のログ)

    $ dd if=/dev/zero of=~/80M bs=1 count=83886080
    83886080+0 records in
    83886080+0 records out
    83886080 bytes transferred in 189.533890 secs (442591 bytes/sec)
    $

    80Mの空ファイルが作成される。中身は/dev/zeroなので、からっぽ。

    上記例ではcountはバイト単位になる。

     * 1024 * 1024 * 80 = 83886080
    で80MByteという計算。

    ただし、189.533890 secs とあるように、3分以上かかっている。

    これは1回に読み書きするブロックサイズ(bsオプション)が1になっているため。

    この値を1 -> 1024に変更すれば理論上は1024倍高速になる。

    bsを1 -> 1024に変えてみた

    $ dd if=/dev/zero of=~/80M_1024 bs=1024 count=81920
    81920+0 records in
    81920+0 records out
    83886080 bytes transferred in 0.375389 secs (223464489 bytes/sec)
    $ 

    作成されたファイルは同じく80Mだが、0.375389 secsで完了した。

    bsが1の時と、1024の結果を比較した結果、504倍高速になったが、理論上の1024倍には届かなかった(残念だがそうゆうもんだ。。)。

    意外と知られていないddの使い方

    実はddで送った結果を直接他のサーバに送りつけることもできる。

    dd if=/dev/sda | ssh root@転送先サーバ " dd of=/転送先ディレクトリ/server.sda.img"

    DISKの中身を強制的にddコマンドで吸い上げ、他のサーバにイメージとして保存することもできる。今はDocker含むコンテナ全盛期の時代だが、KVMなどを使えば、吸い上げたイメージを元に仮想サーバとして動かすこともできる。

    参考記事

    https://qiita.com/S-T/items/8de3c150c7097bd021fa


  • docker版redash 運用でよく使うコマンドまとめ

    docker版redash 運用でよく使うコマンドまとめ

    はじめに

    データベースを可視化するのにredashはとても便利。

    しかし、運用を考えるといろいろ考えることがある。
    redashでよく使うオペレーションをまとめた。

    start redash

    cd ~/redash
    docker-compose -f docker-compose.production.yml up -d

    redashのuserを確認

    docker exec -it redash_server_1 ./manage.py users list

    create user

    docker exec -it redash_server_1 ./manage.py users create sumito.tsukada@sumito.jp sumito.tsukada

    change password

    docker exec -it redash_server_1 ./manage.py users password sumito.tsukada@sumito.jp password

    delete redash user

    docker exec -it redash_server_1 ./manage.py users deletesumito.tsukada@sumito.jp

    redash v5以前は、userをdisableする機能がなかったので削除するしかなかったが、一度クエリを作ったり、ダッシュボードを作ると削除できないという問題があった。v5以降は標準でdisableする機能が追加されたので今後使う頻度は減りそう。

    v4以前で上記コマンドでエラーになった場合、redash_postgres_1のレコードを強制的に削除することによって削除が可能になる(ことがある)

    docker ps
    (login to postgress)
    docker exec -it redash_postgres_1 /bin/bash
    psql -U postgres postgres
    SELECT * FROM events WHERE user_id = 6;
    DELETE FROM events WHERE user_id = 6;

    redashデータのexport

    docker ps
    docker exec -it redash_postgres_1 /bin/bash
    pg_dump -U postgres postgres | gzip > /tmp/redash_backup.gz
    exit
    docker cp redash_postgres_1:/tmp/redash_backup.gz .
    

    redashデータのimport

    本作業を行う前に、postgres以外のdockerコンテナを停止する

    docker cp /tmp/redash_backup.gz redash_postgres_1:/tmp/redash_backup.gz
    docker exec -it redash_postgres_1 /bin/bash
    
    psql -U postgres template1
    DROP DATABASE IF EXISTS postgres;
    CREATE DATABASE postgres;
    \q
    zcat /tmp/redash_backup.gz | psql -U postgres -d postgres
    

    Dockerのpostgresのデータをバックアップ

    cronなのに仕込み、定期的に取得する

    /bin/docker exec redash_postgres_1 pg_dump -U postgres postgres | /bin/gzip > /tmp/redash_backup.gz

    参考情報

    オライリー本より読みやすく、Dockerについて体系的に学ぶことができるのでおすすめ。

  • HAproxyでHR構成を組む on AWS

    HAproxyでHR構成を組む on AWS

    はじめに

    DBサーバへ接続する際、readレプリカを複数台作ることが一般的だが、readレプリカに対してバランシングはインフラの設計ポイントとなる。auroraであれば自動でreadレプリカを作ってくれるのでその考慮は要らないがレガシーなシステムを運用している場合それは使えない。今回はAWSで組むこととする。

    やりたいこと

    多くのプログラムはそうであろう構成。

    プログラムは更新用(write)と参照用(read)で接続先を変え、
    データベースはMasterとSlaveでレプリケーションをしている。

    Slaveは今後増える可能性もあるのに加え、Slaveが1台ダウンしてもサービスが稼働できるようにするには、クラスタリング構成をする必要がある。

    クラスタリングソフトの検討

    名前考察
    keepalived名前解決不可能。また、ググっても実績なし
    HAProxyAmazon linuxでyumでのversionが古い(1.5.2)。v1.6の resolvers オプションを使ってVPCのnameserverを参照するようにし、A Recordの変更に追従させる事が可能だが、ソースからのinstallになってしまう
    MySQL Routerアルファ版 本番利用 非推奨
    Consul by HashiCorpググっても出ない
    ProxySQLAmazonLinux非対応

    keppalivedはAWSでは難しいようだ。

    今回はHA proxyで実現することにした。

    対応

    Amazon linuxの上にHAproxyを使いクラスタリングを実現する。

     

    HAproxyのインストール

    amazon linuxの場合、yumでinstallしようとすると、versionが古い。

    そのため、sourceでインストールすることにした

    yum install -y gcc
    cd /usr/local/src/
    wget http://www.haproxy.org/download/1.8/src/haproxy-1.8.8.tar.gz
    pwd
    tar xvfz haproxy-1.8.8.tar.gz
    ls -ltr
    cd haproxy-1.8.8
    make TARGET=generic
    make install
    

    HAproxyの設定

    設定は以下の通り

    $ cat /etc/haproxy/haproxy.cfg 
    global
        log         tsukada01 local2
    
        chroot      /var/lib/haproxy
        pidfile     /var/run/haproxy.pid
        maxconn     4096
        user        haproxy
        group       haproxy
        daemon
        stats socket /var/lib/haproxy/stats
        stats maxconn 1
        stats timeout 120s
    
    resolvers awsvpc
        nameserver vpc 172.20.0.2:53
    
    defaults
        mode        tcp
        log         global
        retries     3
        timeout     connect 10s
        timeout     client 1m
        timeout     server 1m
        timeout     check 10s
        maxconn     512
    
    listen mysql
        bind tsukada01:3306
        mode tcp
        option mysql-check user haproxy_check
    
        balance roundrobin
    
        option          log-health-checks
    
        server read01 dbserver01:3306 check port 3306 resolvers awsvpc inter 2000 fall 3
        server read02 dbserver02:3306 check port 3306 resolvers awsvpc inter 2000 fall 3

    もう片方のサーバは今の通りに設定した

    $ cat /etc/haproxy/haproxy.cfg
    global
        log         tsukada02 local2
    
        chroot      /var/lib/haproxy
        pidfile     /var/run/haproxy.pid
        maxconn     4096
        user        haproxy
        group       haproxy
        daemon
        stats socket /var/lib/haproxy/stats
        stats maxconn 1
        stats timeout 120s
    
    resolvers awsvpc
        nameserver vpc 172.20.0.2:53
    
    defaults
        mode        tcp
        log         global
        retries     3
        timeout     connect 10s
        timeout     client 1m
        timeout     server 1m
        timeout     check 10s
        maxconn     512
    
    listen mysql
        bind tsukada02:3306
        mode tcp
        option mysql-check user haproxy_check
    
        balance roundrobin
    
        option          log-health-checks
    
        server read01 dbserver01:3306 check port 3306 resolvers awsvpc inter 2000 fall 3
        server read02 dbserver02:3306 check port 3306 resolvers awsvpc inter 2000 fall 3

    ほとんど同じように見えるので差分をまとめると、以下のような違いだ

    これで

    • tsukada001の3306ポート
    • tsukada002の3306ポート

      に接続すると、dbserver01,dbserver02へラウンドロビンで接続されるようになった

    しかし、これでは当然tsukada001、tsukada002自体で障害が起きる可能性もある。

    ALBでバランシング

    tsukada001:3306、tsukada002:3306をALBに登録しラウンドロビンで登録した。

    これによりALBのエンドポイントが払い出され、それを各プログラムが参照するような形にして可用性を担保した。

    振り返って見て思うこと

    レガシーなDBでこの構成を組もうとすると、できないことはないが、登場人物がやたら多い。一番なのはauroraなどに移行し、本当に必要なことのみに集中できれば最高だ。

     

     

  • SSL証明書の有効期限を外部から確認する

    SSL証明書の有効期限を外部から確認する

    はじめに

    近年SSL対応したページが当たり前になってきた。AWSであればAWS Certificate Manager (ACM)の機能で自動で証明書を更新してくれるが、念には念を期限くらいは監視しておきたい。また、Let’s encryptを使う環境だと3ヶ月ごとに期限切れになるので、有効期限を監視するのはとても重要だ。外部から証明書の有効期限を確認するコマンドを紹介。

    実施コマンド

    Linuxの場合

    実は非常に簡単に確認ができる

    Linuxの場合はだいたい標準でOpenSSLがインストールされているので、そのコマンドで確認ができる

    openssl s_client -connect tsukada.sumito.jp:443 < /dev/null 2> /dev/null | openssl x509 -text | grep "Not "
                Not Before: Mar 20 09:14:22 2018 GMT
                Not After : Mar 20 09:14:22 2019 GMT

    URLの部分を変えれば、どの環境でも対応できる

    Macの場合

    brewコマンドでインストール

    brew tap genkiroid/homebrew-cert
    brew install cert

    あとはcertコマンドで後ろに確認したいサイトのURLを記載するのみ。シンプル!

    cert tsukada.sumito.jp
    DomainName: tsukada.sumito.jp
    IP:         35.187.235.61
    Issuer:     Let's Encrypt Authority X3
    NotBefore:  2018-07-18 16:45:33 +0900 JST
    NotAfter:   2018-10-16 16:45:33 +0900 JST
    CommonName: tsukada.sumito.jp
    SANs:       [tsukada.sumito.jp]
    Error: