ようへいの日々精進XP

よかろうもん

2020 年 02 月 01 日 (土)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 色が濃くなれば濃くなる程強度が高い (歩行, 走行距離が長い) ということで. 実装の詳細はこちら.

ジョギング

  • 山王公園を 20min くらい
  • 明日は別大なのに背中の痛みが酷すぎて辛い

ギョーム

  • お休み

別府移動

  • 別府に移動
  • とりあえず, 別府に行ったら背中の痛みが治まるんじゃないかと思って

明日は別大マラソン

  • 先述の通り, 言い訳がましいかもしれないけど, 背中に痛みがあって走れるが微妙
  • 出来る限り頑張る

夕食

別府駅前の居酒屋. 申し訳ないけど美味しくなかったけど, 明日の為にお腹いっぱい食べた. 夕食後, 再度お風呂に入って体をほぐす. お風呂上がりにお水とポカリと 2Run を飲んだ.

2020 年 01 月 31 日 (金)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 色が濃くなれば濃くなる程強度が高い (歩行, 走行距離が長い) ということで. 実装の詳細はこちら.

ジョギング

  • 山王公園を 60min で 12 キロ
  • 背中の痛みに耐えながら, マジで痛い
  • 右足太ももについては, 背中の痛みがあるからか気にならない... でも張りは強い

ギョーム

  • 社内全体会議
  • ウィークリーレポート
  • RDS の検証引き続き, インスタンスパラメータを操作するツールを引き続き

夕飯

  • 今日も鍋
  • やっぱり, 食べ過ぎた

2020 年 01 月 30 日 (木)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 色が濃くなれば濃くなる程強度が高い (歩行, 走行距離が長い) ということで. 実装の詳細はこちら.

ジョギング

  • 引き続き, お休み
  • 徒歩通勤往復
  • 鎮痛剤を飲んで背中や足の痛みを抑えている
  • 明日は軽く走ろうと思う

ギョーム

  • PostgreSQL と pgrouting (PostGIS) が動く Docker 環境を作ったり
  • PostgreSQLSSL 接続を有効にしたり (ちなみに, psql はデフォルトで SSL 接続する)
  • 本番環境でうっかり事故らないように検証して実装した

inokara.hateblo.jp

夕飯

  • 鍋, 今日のお品書きも秀逸だったけど, 鍋を作るのは自分
  • 食べ過ぎた

1 つの AWS アカウントで出来るだけうっかりミスを抑えつつ本番環境を運用する為にやったこと

tl;dr

先日, 完全に自分のうっかりで AWS リソースをオペミスで壊してしまいサービス障害を発生させてしまいました. 原因は, 何を隠そう自分の「うっかり」であり, 完全に人為的なミスです. 今後, このような事故を出来るだけ起こさないように対応策を施したので書ける範囲で共有させて頂きます.

原因

AWS アカウントを利用して検証中の事故でしたが, 以下のような幾つかの状況が重なった事故だったと考えています.

  • 検証環境のリソースと本番環境のリソースが混在している状況だった
  • 検証環境のリソースと本番環境のリソースで見分けがつけ辛い状況だった
  • 利用している IAM ユーザーについて, 全てのリソースを無条件で操作出来る権限が付与されているアカウントだった
  • オペレーター (自分) がボーッとしてしまい, 特になんの疑いも持たずに操作してしまった, しかも, 一人で操作していた

これらの原因を受けて, 以下のような対策を実装しました.

実装

2 つの実装

  1. IAM ユーザーの分割: 通常, 検証等で使う IAM ユーザーと本番環境を操作出来る IAM ユーザーを分ける (通常使うアカウントでは本番環境のリソースは操作出来ないようにする)
  2. Chrome Extension による IAM ユーザーの判別: 本番環境が操作可能な IAM ユーザーで操作する場合, 自身のアカウントが本番環境を操作可能な IAM ユーザーであることを意識付けるようにする

実装 (1) IAM ユーザーの分割 〜 本番環境のリソース操作を拒否する 〜

従来は個人用として 1 つの IAM ユーザーを作成し, これを利用していました. この IAM ユーザーには管理者権限 (IAM ロールの AdministratorAccess 相当) がアタッチされていましたが, 今後は, この IAM ユーザーについては, 本番環境のリソースについて, 再起動や停止, 編集等の権限については無効するようなポリシーを追加しました.

具体的には, 以下のような IAM ポリシーを付与しました. 以下は, Environment タグ名に Production という値が設定されている EC2 インスタンスの再起動をはじめタグ操作を Deny しています.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": [
        "ec2:RebootInstances",
        "ec2:StartInstances",
        "ec2:StopInstances",
        "ec2:CreateTags",
        "ec2:DeleteTags",
        "ec2:Terminate*"
      ],
      "Resource": "arn:aws:ec2:*:*:instance/*",
      "Condition": {
        "StringEquals": {
          "ec2:ResourceTag/Environment": "Production"
        }
      }
    }
  ]
}

また, 今回の事故は具体的に申し上げると, 本番環境の RDS をフェイルオーバーさせてしまいました. ということで, RDS についても同様に Environment タグ名に Production という値が設定されている RDS クラスタインスタンスについても構成変更等が行えないように設定しました.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Action": [
                "rds:Modify*",
                "rds:Start*",
                "rds:Stop*",
                "rds:Reboot*",
                "rds:AddTagsToResource",
                "rds:RemoveTagsFromResource",
                "rds:FailoverDBCluster"
            ],
            "Resource": "arn:*:rds:*:*:cluster:*",
            "Condition": {
                "StringEquals": {
                    "rds:cluster-tag/Environment": "Production"
                }
            }
        },
        {
            "Effect": "Deny",
            "Action": [
                "rds:Modify*",
                "rds:Start*",
                "rds:Stop*",
                "rds:Reboot*",
                "rds:AddTagsToResource",
                "rds:RemoveTagsFromResource",
                "rds:FailoverDBCluster"
            ],
            "Resource": "arn:*:rds:*:*:db:*",
            "Condition": {
                "StringEquals": {
                    "rds:db-tag/Environment": "Production"
                }
            }
        }
    ]
}

これらの拒否ポリシーは, 先述の Administrator Access 相当のロールが付与されていても, それを上書きするように作用する為, 当該 IAM ユーザーアカウントについては, 従来どおり検証用で作成したリソースを自由に操作しつつ, うっかり本番環境 (Environment:Production が付与された) リソースを操作してしまうようなことを防ぐことが可能になります.

ただ, 立場上, 本番環境を操作する必要がある為, これに対応する為に本当に全てのリソースを操作可能な IAM ユーザーアカウントを作成しました. 本番環境を操作するような場合にはアカウントを切り替えて (もしくは, ブラウザを切り替えて) 操作することになります. 多少の運用負担にはなってしまいますが, うっかり操作で障害を発生させてしまった際の影響と比較すると大したことではないと考えています.

実際に拒否ポリシーが適用された IAM ユーザーで EC2 を停止しようとすると, 下図のようにエラーとなります.

f:id:inokara:20200131002140p:plain

以下, IAM ポリシーで利用可能な, アクションやリソース, 条件コンテキストキーのリンクです. これらの条件を利用することで, タグ以外の条件でもリソース操作を制限することが可能かと思われます.

実装 (2) Chrome Extension による IAM ユーザーの判別

先述の通り, 立場上, 全てのリソースに対する権限が付与された IAM ユーザーアカウントも運用することになりますが, この IAM ユーザーアカウントでマネジメントコンソールにログインした際には, 下図のようにヘッダ付近に現在のユーザーが管理者ユーザーである旨のメッセージが出力されるようにしました.

f:id:inokara:20200130234935p:plain

これは, 以下の記事を参考にさせて頂き, オレオレ Chrome Extension を作りました.

qiita.com

コード自体は以下のように数行レベルのものです.

$(function() {
    console.log($(".nav-elt-label").text());
    var sp = /super|administrator|admin/;
    if($(".nav-elt-label").text().match(sp)) {
        $("#h").after('<div style="background-color:#FF0000;text-align:center;"><h3>全てのリソースを操作出来る IAM ユーザーでアクセスしています.  Production 環境のリソースの取り扱いに注意しましょう.</h3></div>');
    }
});

マネジメントコンソールのヘッダ部分を解析して, 特定の文字列が含まれていたらヘッダ部分に HTML を差し込みます. 上記の例だと, IAM ユーザーに superAdministrator という文字列が含まれている状態を想定しています. 当初は, リソース名に production という文字列が含まれていたら, 何か警告を出すような仕込みを入れてみようと頑張ってみましたが, マネジメントコンソールの処理を解析出来る程の能力があるわけもなく, 上記のような対応にしました.

まずは, この対応で頑張ってみたいと思います.

最後に

このような場合, そもそも検証環境と本番環境で AWS アカウントを分けるというのが常套手段なのかもしれませんが, こういう対応も可能ということを共有させて頂ければ思います.また, この対応で完全にミスが防げるというわけではありません. あくまでも, ミスによる障害を抑制する為の保険の一つでしかありません.

以上, 事故の起きないインフラ環境を目指して精進したいと思います.

2020 年 01 月 29 日 (水)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 色が濃くなれば濃くなる程強度が高い (歩行, 走行距離が長い) ということで. 実装の詳細はこちら.

ジョギング

  • 引き続き, お休み
  • 徒歩通勤往復
  • もう色々と諦めた, 足よりも背中が非常に辛い

ギョーム

  • Elasticsearch で壊れたインデックスが原因でデータインスタンスのディスク使用量に偏りが出来ていてアラートが発生, 壊れたインデックスを削除したら復旧, ガラクタを溜め込んではいけないなと思った次第
  • RDS メンテの検証, ツール書いたりしてた...ら, プロダクション環境を操作してしまってサービスに障害を発生させてしまった...めちゃくちゃ恥ずかしい...大変申し訳ございません
  • 障害をうけてエンジニアリングで解決出来ないか試行錯誤してた

夕飯

  • 手羽中のソテー, お刺身, 今日もお品書きが良かった

2020 年 01 月 28 日 (火)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 色が濃くなれば濃くなる程強度が高い (歩行, 走行距離が長い) ということで. 実装の詳細はこちら.

ジョギング

  • 引き続き, お休み
  • 徒歩通勤往復
  • 背筋痛は奥さんのサロメチールマッサージ落ち着いてきた感じ
  • 夕方, 鍼治療

ギョーム

  • Aurora のチューニング検証
  • 検証とか実際のメンテでも利用するパラメータグループを更新するツールを Go で書き始めたけど, RDS の API ってパラメータは存在しているけど, 「現在はサポートされていない」系があってフムってなった
  • でも, Example をコピペでだいたいのものが作れるのは嬉しい

docs.aws.amazon.com

夕飯

今日は洋食ということで, ビストロひろみだった. お得意のハンバーグがいつものように美味しかった.

【俺の一行チップス】docker-compose の Extension fields を使って DRY な YAML にする(docker-compose 3.4 以降, docker-compose 2.1 以降編)

やりたいこと

docker-compose.yml を書いていて, 同じ内容を何度も何度も書いていて, 令和の時代にこれはアカンということで Anchor, Alias で少しでも DRY にしたい. DRY とは, アサヒスーパードライではなく, Don't Repeat Yourself のことなので酔っ払わないように.

諸注意

動作確認環境は以下の通り.

$  docker-compose version
docker-compose version 1.24.1, build 4667896b
docker-py version: 3.7.3
CPython version: 3.6.8
OpenSSL version: OpenSSL 1.1.0j  20 Nov 2018

やったこと

これまでの docker-compose.yml

version: '3.4'

services:
  postgresql_server:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        DB_PASSWORD: "posgre"
    container_name: postgresql
    ports:
      - "5432:5432"
    networks:
      my_net:
        ipv4_address: 10.0.101.10

  psql:
    image: postgres:9
    container_name: psql
    networks:
      my_net:
    environment:
      PGAPPNAME: pgbench
      PGHOST: 10.0.101.10
      PGUSER: pgadmin
      PGPASSWORD: posgre
      PGDATABASE: pgbench

  pgbench-prepare:
    image: postgres:9
    container_name: pgbench-prepare
    networks:
      my_net:
    environment:
      PGAPPNAME: pgbench
      PGHOST: 10.0.101.10
      PGUSER: pgadmin
      PGPASSWORD: posgre
      PGDATABASE: pgbench
    command: bash -c "dropdb pgbench ; createdb --owner=pgadmin pgbench && pgbench --initialize --scale=5"
()

environment の値が 2 箇所, 省略している部分を含めると 4 箇所に同じ内容が書かれているのでなんだか長くてダサい. けど, 一応, 構文的には問題ない.

$ docker-compose --file docker-compose.before.yml config --quiet; echo $status
0

ちなみに, docker-compose config という docker-compose.yml の内容をチェックしているコマンドがあったのは知らなかった.

令和の docker-compose.yml

以下のように, docker-compose 3.4 から (docker-compose 2.1 以降も) サポートされている, Extension fields を利用することで, docker-compose.yml のトップレベルである services と同じルートレベルに特殊フィールド (キーの頭に x- を付ける) として書くことが出来る. 尚, docker-compose 3.4 以前も Anchor と Alias を使うことが出来たが, services 内に Anchor を書く必要があった.

# ドキュメントより引用
version: '3.4'
x-logging:
  &default-logging
  options:
    max-size: '12m'
    max-file: '5'
  driver: json-file

services:
  web:
    image: myapp/web:latest
    logging: *default-logging
  db:
    image: mysql:latest
    logging: *default-logging

とのことなので, 先程の docker-compose.yml を書き直してみると以下のような感じ.

version: '3.4'

x-common_environment: &common_environment
  PGAPPNAME: pgbench
  PGHOST: 10.0.101.10
  PGUSER: pgadmin
  PGPASSWORD: posgre
  PGDATABASE: pgbench
x-networks: &common_networks
  networks:
    my_net:

services:
  postgresql_server:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        DB_PASSWORD: "posgre"
    container_name: postgresql
    ports:
      - "5432:5432"
    networks:
      my_net:
        ipv4_address: 10.0.101.10

  psql:
    image: postgres:9
    container_name: psql
    environment: *common_environment
    <<: *common_networks

  pgbench-prepare:
    image: postgres:9
    container_name: pgbench-prepare
    environment: *common_environment
    command: bash -c "dropdb pgbench ; createdb --owner=pgadmin pgbench && pgbench --initialize --scale=5"
    <<: *common_networks
 (略)

こんな感じになった. Anchor, Alias を使えば, 当然, 同じ記述を繰り返し書かなくてすむし, Extension fields でよりスッキリした感じ.

$ docker-compose --file docker-compose.yml config --quiet; echo $status
0

構文チェックも OK.

以上

メモでした.

参考

docs.docker.com

circleci.com

(完)

2020 年 01 月 27 日 (月)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 色が濃くなれば濃くなる程強度が高い (歩行, 走行距離が長い) ということで. 実装の詳細はこちら.

ジョギング

  • お休み
  • 徒歩通勤往復

ギョーム

  • 課題の整理等
  • JavaScript なプロジェクトで git commit をフックして eslint を走らせるようにしてみた
  • PostgreSQL の shared_buffers の検証

shared_buffer を調整することでバッファーキャッシュの使われ方が変わるのを確認出来て勉強になった.

夕飯

最近, 奥さんが夕飯のお品書きを書いてくれるのでテンション上がる. 久しぶりに生姜ご飯で美味しかった.

【俺の一行チップス】PostgreSQL 9.x で localhost 以外からデータベース接続する (ことを Go の testing パッケージで検証する)

やりたいこと

PostgreSQL 9.x において, localhost 以外からデータベース接続を設定についてまとめたのは前回. 今回は, これを検証するにあたって Go の testing パッケージでテストコードを書いて検証したお話を少し.

inokara.hateblo.jp

諸注意

動作確認環境は以下の通り.

# PostgreSQL サーバー側 (Ubuntu 上にパッケージで PostgreSQL をインストール)
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.3 LTS"

$ /usr/lib/postgresql/9.6/bin/postgres --version
postgres (PostgreSQL) 9.6.16

# psql 側
$ docker-compose exec postgresql_client psql --version
psql (PostgreSQL) 9.6.16

# Go
$ docker-compose exec go_test go version
go version go1.13.6 linux/amd64

やったこと

環境構築とか

環境も docker-compose で用意する前提.

version: '3'

services:
  postgresql_server:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        DB_PASSWORD: "posgre"
    container_name: postgresql-server
    ports:
      - "5432:5432"
    networks:
      my_net:
        ipv4_address: 10.0.101.10

  postgresql_client:
    image: postgres:9
    container_name: postgresql-client
    networks:
      my_net:
        ipv4_address: 10.0.101.11

  go_test:
    build:
      context: tests
      dockerfile: Dockerfile
    container_name: go-test
    environment:
      - DB_HOST=10.0.101.10
      - DB_PASSWORD=posgre
    networks:
      my_net:
        ipv4_address: 10.0.101.5
    command: tail -f /dev/null

networks:
  my_net:
    driver: bridge
    ipam:
     driver: default
     config:
       - subnet: 10.0.101.0/24

docker-compose up -d で全ての環境を起動した直後に, go test した図.

$ docker-compose exec go_test richgo test -v
START| PostgrePing
PASS | PostgrePing (0.01s)
PASS
PASS | postgresql_test 0.027s

いい感じでパスする.

次に, PostgreSQL の設定をデフォルトの状態に戻す. Dockerfile の以下の箇所をコメントアウトする.

# Enable Remote Access
RUN echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/9.6/main/pg_hba.conf # ここをコメントアウト
RUN echo "listen_addresses='*'" >> /etc/postgresql/9.6/main/postgresql.conf # ここをコメントアウト

コメントアウトすることで, 外部接続に必要な設定を無効化する.

改めて, 環境を作り直してテストを実行.

$ docker-compose build && docker-compose up -d && docker-compose exec go_test richgo test -v
()
START| PostgrePing
FAIL | PostgrePing (0.00s)
     |     postgresql_test.go:41: got error: dial tcp 10.0.101.10:5432: connect: connection refused
FAIL
     | exit status 1
FAIL |  postgresql_test 0.028s

テストが fail する.

テストコード全貌

ということで, 以下のようなテストを書いた.

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/lib/pq"
    "os"
    "testing"
)

const (
    user   = "pgadmin"
    dbname = "postgres"
)

var (
    host     = os.Getenv("DB_HOST")
    password = os.Getenv("DB_PASSWORD")
)

func TestPostgrePing(t *testing.T) {
    db, err := dbConnection()
    if err != nil {
        t.Errorf("got error: %v", err)
    }
    defer db.Close()

    err = db.Ping()
    if err != nil {
        t.Errorf("got error: %v", err)
    }
}

func dbConnection() (*sql.DB, error) {
    connInfo := fmt.Sprintf("host=%s "+
        "port=5432 "+
        "user=%s "+
        "password=%s "+
        "dbname=%s "+
        "sslmode=disable",
        host, user, password, dbname)
    db, err := sql.Open("postgres", connInfo)
    if err != nil {
        return nil, err
    }

    return db, nil
}

Ping を使って, データベースの死活をチェックしている.

作ったもの

github.com

参考

golang.org

godoc.org

github.com

(完)

2020 年 01 月 26 日 (日)

アクティビティ (今までの走行 (歩行) 距離)

https://pixe.la/v1/users/inokappa/graphs/fitbit-activity

Fitibit Charge2 のアクティビティから走行 (歩行) 距離を Fitbit Web API で取得して Pixela で草生やしている. 色が濃くなれば濃くなる程強度が高い (歩行, 走行距離が長い) ということで. 実装の詳細はこちら.

ジョギング

  • 山王公園を軽く歩いたり, 走ったり 30 分くらい
  • 走り始めから背中に突っ張るような激痛, 右足ハムストリングもそうだけど, 満身創痍感がある

ギョーム

  • もちろん, お休み
  • 素の PostgreSQLUbuntu にインストールしたりしつつガチャガチャしてた

大阪国際女子マラソン

最後の一枠をかけたレース. ダイハツ松田瑞生選手の攻めの走りが圧巻だった.

夕飯

  • 佐世保のおじさんからアジ (フライに出来る状態) とアラカブを頂いたので女将が調理
  • アジフライはジューシーだったし, アラカブはこんなにも出汁が出るのか!という感じで美味しゅうございました