$30 off During Our Annual Pro Sale. View Details »

yapcasia2015

 yapcasia2015

我々はどのように冗長化を失敗したのか

kenjiskywalker

August 21, 2015
Tweet

More Decks by kenjiskywalker

Other Decks in Technology

Transcript

  1. 我々は  
    どのように  
    冗長化を失敗したのか
    YAPC::Asia  2015  
    2015/08/22  (Day  2)
    kenjiskywalker
    Photos : https://www.flickr.com/photos/gsfc 1

    View Slide

  2. ある思想を持って  
    システム構築を行い  
    失敗をした話をします
    よろしくお願いします
    2

    View Slide

  3. 話すこと
    挑戦したこと  
    冗長化について  
    Redis  +  Redis  Sentinel  
    Consul  
    MySQL  +  mysqlfailover  
    consul-template  
    hostsの順番  
    クラウドという名の混乱  
    対応  
    冗長化の終わり、そして
    3

    View Slide

  4. 挑戦したこと
    4

    View Slide

  5. 式年遷宮  
    インフラストラクチャ
    5

    View Slide

  6. 式年遷宮とは
    6

    View Slide

  7. ”神宮式年遷宮は、  
     神宮(伊勢神宮)において  
     行われる式年遷宮  
     (定期的に行われる遷宮)  
     である。”  
    Wikipedia調べ
    7

    View Slide

  8. 何故  
    式年遷宮を行うのか
    8

    View Slide

  9. 神道での清浄さの維持  
    技術の伝承という継続性
    Wikipedia調べ
    ”式年遷宮が20年ごとに行われる理由についても、  
     同じく確たる記録はないため不明である。  
     推測される主な理由としては、  
     以下の5点が挙げられる。”
    からの一部抜粋
    9

    View Slide

  10. 式年遷宮とは  
    長期的な品質の担保と  
    その概念自体の継続性の維持を  
    目的としたアーキテクチャ  
    ではなかったのだろうか(仮説)
    10

    View Slide

  11. Webサービスの運用と  
    式年遷宮
    11

    View Slide

  12. Kenji Naito a.k.a kenjiskywalker
    The world is not complete
    Photos : https://www.flickr.com/photos/gsfc
    YAPC::Asia 2014
    2014/08/29 (day 1)
    12

    View Slide

  13. 故障率曲線
    MTBF(平均故障間隔)  
    MTTR(平均修理時間)
    辛さの平均値
    13

    View Slide

  14. 「動くものは必ず壊れる」
    Webサービスの運用
    相反するふたつの価値観を  
    結びつけ成長させる必要がある
    14
    「24時間365日  
       正常に動き続けなけければ  
     ならない」

    View Slide

  15. 冗長化
    15

    View Slide

  16. ”冗長化(じょうちょうか)とは、  
     システムの一部に  
     何らかの障害が発生した場合に備えて、  
     障害発生後でも  
     システム全体の機能を維持し  
     続けられるように予備装置を  
     平常時からバックアップとして  
     配置し運用しておくこと。  
     冗長化によって得られる安全性は  
     冗長性と呼ばれる。”
    Wikipedia調べ
    16

    View Slide

  17. 異常が発生した際に  
    自動的にアクティブが  
    遷移する設定を  
    導入しているところは  
    結構あると思う
    17

    View Slide

  18. しかし
    18

    View Slide

  19. 障害発生時、  
    正常に  
    切り替わらないことが  
    ほとんどである
    (個人の感想であり効果・効能を示すものではありません)
    19

    View Slide

  20. そこで
    20

    View Slide

  21. 平常時であっても  
    常に冗長構成の  
    アクティブ/スタンバイを  
    切り替えることによって  
    異常時の正常動作を  
    担保できるのではないか
    Active/Standby Active/Standby
    21

    View Slide

  22. それって  
    式年遷宮では?
    22

    View Slide

  23. それって  
    式年遷宮では?
    23

    View Slide

  24. 式年遷宮  
    インフラストラクチャ
    思想
    (正常時も常に稼動系を切り替える)
    24

    View Slide

  25. 構成
    25

    View Slide

  26. 構成
    Public
    Web Server A 02
    Web Server A 01
    Web Sever B 02
    Web Server B 01
    26

    View Slide

  27. 構成
    MySQL A Slave
    MySQL A Master
    Private
    MySQL B Slave
    MySQL B Master
    27

    View Slide

  28. 構成
    Private
    Public
    VPN
    28

    View Slide

  29. nginx + Redis(Slave)
    Application A 02
    各ウェブサーバでは  
    nginxとRedis、  
    Web  Applicationが動いている
    nginx + Redis(Master)
    Application A 01
    29

    View Slide

  30. この構成で  
    式年遷宮を  
    実装する場合の課題
    30

    View Slide

  31. Master/Slave方式の  
    冗長化されたシステムを  
    どのように  
    式年遷宮に対応させるか
    31

    View Slide

  32. Redisの場合
    32

    View Slide

  33. Redis  Sentinel  
    Redis  Ver.  2.8.9
    33

    View Slide

  34. Redis  Sentinel?  
    基本スプリットブレインを  
    予防するためには  
    最低でも  
    サーバが3台必要なのでは?
    34

    View Slide

  35. 監視用のサーバを置いた場合  
    監視用のサーバも遷移させる?
    nginx + Redis
    Application A 01
    Sentinel x1
    nginx + Redis
    Application A 02
    Sentinel x1
    nginx + Redis
    Application A 03-01
    Sentinel x1
    nginx + Redis
    Application A 03-01
    Sentinel x1
    ?
    35

    View Slide

  36. 冗長化の為に  
    システム自体を  
    複雑化するのは避けたい
    36

    View Slide

  37. 台数をそのままに  
    Redis  Sentinelを導入
    37

    View Slide

  38. Master : Sentinel x1
    Slave : Sentinel x2
    Redis Master
    Sentinel x1
    Redis Master
    Sentinel x2
    38

    View Slide

  39. Masterが遷移した際に  
    Redis  Sentinelの数を  
    操作する(Master  x1/Slave  x2)に  
    する必要がある
    Redis (New) Slave
    Sentinel x1

    Sentinel x2
    Redis (New) Master
    Sentinel x2

    Sentinel x1
    39

    View Slide

  40. 詰めが甘いところはあるが  
    可能ではありそうだ
    40

    View Slide

  41. サーバに障害が発生した際に  
    アプリケーションをどのように  
    新しいMasterへ向き先を変えるか
    Redis Master
    Host 01
    Redis (New) Master
    Host 02
    41

    View Slide

  42. Consul  
    Consul  Ver.  0.5.0  
    42

    View Slide

  43. Consul  とは
    43

    View Slide

  44. 44

    View Slide

  45. Consulとは  
    いい感じに  
    DNSレコードを  
    返すもの
    45

    View Slide

  46. このConsulを利用して  
    RedisのMasterが  
    遷移したことを  
    アプリケーションへ  
    知らせたい
    46

    View Slide

  47. #!/usr/bin/env ruby
    redis_name = 'foo-redis'
    fqdn = 'service.dc1.consul'
    master_redis_name = "master.#{redis_name}.#{fqdn}"
    master_redis_hosts = `host -W 1 #{master_redis_name}| grep has`.split("\n")
    # マスターが複数台起動していたなら
    if master_redis_hosts.length > 1
    exit 2
    end
    redis_is_runnning = `netstat -l | grep -w 6379`
    # Redisが動いていなければfail
    if redis_is_runnning.nil?
    exit 2
    end
    # Roleがmasterであればtrue
    my_redis_role = `/usr/local/bin/redis-cli info | grep role`
    my_redis_role.chomp!
    if "#{my_redis_role}" == "role:master"
    exit 0
    else
    exit 2
    end 47

    View Slide

  48. #!/usr/bin/env ruby
    redis_name = 'foo-redis'
    fqdn = 'service.dc1.consul'
    master_redis_name = "master.#{redis_name}.#{fqdn}"
    master_redis_hosts = `host -W 1 #{master_redis_name}| grep has`.split("\n")
    # マスターが複数台起動していたなら
    if master_redis_hosts.length > 1
    exit 2
    end
    redis_is_runnning = `netstat -l | grep -w 6379`
    # Redisが動いていなければfail
    if redis_is_runnning.nil?
    exit 2
    end
    # Roleがmasterであればtrue
    my_redis_role = `/usr/local/bin/redis-cli info | grep role`
    my_redis_role.chomp!
    if "#{my_redis_role}" == "role:master"
    exit 0
    else
    exit 2
    end
    1、RedisのMasterのDNSが  
      複数のIPアドレスを返していない  
    2、自分のサーバでRedisが動いている  
    3、その動いているRedisはMasterである
    48

    View Slide

  49. #!/usr/bin/env ruby
    redis_name = 'foo-redis'
    fqdn = 'service.dc1.consul'
    master_redis_name = "master.#{redis_name}.#{fqdn}"
    master_redis_hosts = `host -W 1 #{master_redis_name}| grep has`.split("\n")
    # マスターが複数台起動していたなら
    if master_redis_hosts.length > 1
    exit 2
    end
    redis_is_runnning = `netstat -l | grep -w 6379`
    # Redisが動いていなければfail
    if redis_is_runnning.nil?
    exit 2
    end
    # Roleがmasterであればtrue
    my_redis_role = `/usr/local/bin/redis-cli info | grep role`
    my_redis_role.chomp!
    if "#{my_redis_role}" == "role:master"
    exit 0
    else
    exit 2
    end
    この3つの条件を  
    満たした時のみ
    RedisのMasterのDNSレコードを  
    Consulで返すようにした
    49

    View Slide

  50. {
    "service": {
    "id": "foo-redis master check in HOSTNAME",
    "tags": ["master"],
    "name": "foo-redis",
    "check": {
    "script": "/opt/consul/bin/redis-master-check.rb",
    "interval": "30s"
    }
    }
    }
    50

    View Slide

  51. 「master.foo-redis.service.dc1.consul」
    というRedisのMasterの  
    DNSレコードが利用できるようになる  
    51

    View Slide

  52. nothing
    Old Master fail
    master.foo-redis.service.dc1.consul
    52
    master.foo-redis.service.dc1.consul
    52
    192.0.2.11
    check ok

    View Slide

  53. nothing
    Old Master fail
    master.foo-redis.service.dc1.consul
    53
    master.foo-redis.service.dc1.consul
    53
    192.0.2.11
    check ok
    check ng
    nothing

    View Slide

  54. nothing
    Old Master fail
    Run Redis fail over
    nothing
    master.foo-redis.service.dc1.consul
    54
    master.foo-redis.service.dc1.consul
    54
    192.0.2.11
    check ok
    check ng
    failover
    nothing
    nothing

    View Slide

  55. master.foo-redis.service.dc1.consul
    55
    192.0.2.11
    check ok
    check ng
    failover complete
    failover
    nothing
    192.0.2.12(New)
    nothing

    View Slide

  56. 問題点
    このやり方だとConsul上で  
    常にSlave側がFailした  
    状態になってしまうので  
    Consulを利用した  
    ステートメント管理の  
    知見のある方、  
    教えてください&
    Master(OK)
    Slave(NG)
    56

    View Slide

  57. Consul  ポート8600問題
    57

    View Slide

  58. ConsulがDNSを返してくれるポートが  
    8600ポートなので、全サーバに  
    ConsulとDnsmasqを導入し、  
    「.consul」
    のドメインへのリクエストは  
    全て8600ポートに  
    問い合わせるようにした
    58

    View Slide

  59. conf-dir=/etc/dnsmasq.d
    server=/consul./127.0.0.1#8600
    /etc/dnsmasq.conf
    /etc/dnsmasq.d/10-consul
    設定例
    59

    View Slide

  60. Redisの冗長化完了
    60

    View Slide

  61. MySQLの場合
    61

    View Slide

  62. MySQL  5.6(GTID)  
    mysqlfailover  
    MySQL  Ver.  5.6.22-2  
    mysql-utilities  Ver.  1.5.4-1
    62

    View Slide

  63. mysqlfailoverとは
    63

    View Slide

  64. mysqlfailoverとは
    他にも一撃で  
    レプリケーション環境を構築できる
    mysqlreplicateなど  
    便利コマンドが内包されている
    MySQLが提供してくれている  
    MySQL  Utilitiesという  
    便利ツールの中のひとつのコマンド
    64

    View Slide

  65. mysqlfailoverを利用することで  
    障害時にMasterを  
    遷移することはできるが
    Redisと同様にどのように  
    MySQLを利用している  
    アプリケーションへ  
    稼動系の切り替えを伝達するか
    65

    View Slide

  66. Consul  
    Consul  Ver.0.5.0  
    66

    View Slide

  67. mysqlfailoverには
    遷移実行前(before_exec)と  
    遷移実行後(after_exec)で
    任意のコマンドが実行できる
    67

    View Slide

  68. この機能を利用して  
    Consulで  
    DNSレコードを  
    操作してみましょう
    68

    View Slide

  69. #!/bin/bash
    curl -X PUT -d '{"Node":"foo-db-master"}' localhost:8500/v1/catalog/deregister
    curl -X DELETE http://localhost:8500/v1/kv/foo-db-master
    遷移実行前(before_exec)
    deregister-master-db.sh
    遷移前にMasterのDNSレコードを削除し  
    接続できないようにする
    69

    View Slide

  70. #!/bin/bash
    curl -X PUT -d '{"Node":"foo-db-slave"}' localhost:8500/v1/catalog/deregister
    curl -X PUT -d '{"Node":"foo-db-master}", "Address":"192.0.2.110"}' \
    localhost:8500/v1/catalog/register
    curl -X PUT -d '192.0.2.110' http://localhost:8500/v1/kv/foo-db-master
    遷移実行後(after_exec)
    register-master-db.sh
    Masterの遷移が正常に完了した後  
    Masterのレコードを新MasterのIPアドレスで返す
    ※  kvは念のための設定
    70

    View Slide

  71. 192.0.2.111
    start failover
    foo-db-master.node.dc1.consul
    71

    View Slide

  72. 192.0.2.111
    start failover
    run before_exec
    deregister
    foo-db-master.node.dc1.consul
    72

    View Slide

  73. 192.0.2.111
    start failover
    run before_exec
    failover
    deregister
    nothing
    foo-db-master.node.dc1.consul
    73

    View Slide

  74. 192.0.2.111
    start failover
    run before_exec
    run after_exec
    failover
    deregister
    192.0.2.112(New)
    nothing
    foo-db-master.node.dc1.consul
    74

    View Slide

  75. MySQLの冗長化完了
    75

    View Slide

  76. しかし、ここで課題が
    内部の名前解決をすべて  
    Consulに委ねてしまうと、  
    Consulの死  =  サービスの死に  
    つながってしまう
    76

    View Slide

  77. これではせっかく  
    サービスの継続性を狙って  
    自動遷移する冗長構成を  
    構築したものの  
    Consulの存在自体が  
    リスクになる
    77

    View Slide

  78. あ、Consulが返してる  
    DNSレコードを  
    hostsに直接書いちゃお☺
    78

    View Slide

  79. hostsにDNSレコードを  
    書いておけば  
    万が一  
    Consulの応答がなくなっても  
    サービスへの影響はなくなる
    79

    View Slide

  80. consul-template  
    consul-template  Ver.  v0.7.0
    80

    View Slide

  81. consul-template  とは
    81

    View Slide

  82. consul-template  とは
    Consulの管理しているDNSレコードを  
    ファイルに書き出す
    Consulの管理してるDNSレコードに  
    変更があった際に任意のコマンドを  
    実行できる便利ツール
    82

    View Slide

  83. 変化があった場合に  
    /etc/hostsを書き換えて  
    Dnsmasqを再起動させるようにした
    consul = "127.0.0.1:8500"
    template {
    source = "/etc/hosts.ctmpl"
    destination = "/etc/hosts"
    command = "service dnsmasq restart"
    }
    /etc/consul.d/consul-template.cfg
    83

    View Slide

  84. # This file generated by consul-template
    127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
    # node{{ range nodes }}
    {{.Address}} {{.Node}}
    {{.Address}} {{.Node}}.node.dc1.consul{{end}}
    {{range services}}
    # service {{.Name}}{{range service .Name}}
    {{.Address}} {{.Name}}.service.dc1.consul{{end}}{{end}}
    /etc/hosts.ctmpl
    84

    View Slide

  85. 作成されるhostsファイル
    # This file generated by consul-template
    127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
    # node
    192.0.2.111 foo-db-master
    192.0.2.111 foo-db-master.node.dc1.consul
    192.0.2.112 foo-db-slave
    192.0.2.112 foo-db-slvave.node.dc1.consul
    ...
    # service bar-app
    192.0.2.11 bar-app.service.dc1.consul
    192.0.2.12 bar-app.service.dc1.consul
    85

    View Slide

  86. /usr/local/bin/consul-template \
    -config=/etc/consul.d/consul-template.cfg
    設定ファイルを指定し  
    DaemontoolsやSupervisorなどで  
    起動させておく
    86

    View Slide

  87. # node
    192.0.2.11 foo-app01
    192.0.2.11 foo-app01.node.dc1.consul
    192.0.2.12 foo-app02
    192.0.2.12 foo-app02.node.dc1.consul
    192.0.2.13 foo-app03
    192.0.2.13 foo-app03.node.dc1.consul
    # service foo-app
    192.0.2.11 foo-app.service.dc1.consul
    192.0.2.12 foo-app.service.dc1.consul
    192.0.2.13 foo-app.service.dc1.consul
    試しにfoo-app02を止めると
    87

    View Slide

  88. こうなる。便利
    こうなる
    # node
    192.0.2.11 foo-app01
    192.0.2.11 foo-app01.node.dc1.consul
    192.0.2.13 foo-app03
    192.0.2.13 foo-app03.node.dc1.consul
    # service foo-app
    192.0.2.11 foo-app.service.dc1.consul
    192.0.2.13 foo-app.service.dc1.consul
    88

    View Slide

  89. Redis Sentinel + Consul
    MySQL(GTID) + mysqlfailover + Consul
    Consul + consul-template
    89

    View Slide

  90. この時点で  
    解決できていない課題
    90

    View Slide

  91. MySQLおよびRedisの  
    遷移時のダウンタイム問題を  
    解決できていない  
    稼働系常時遷移を  
    実践している人いたら  
    知見を下さい。  
    よろしくお願いします&
    91

    View Slide

  92. 今考えていることメモ
    Web  API側、ネイティブアプリ側  
    それぞれでデータストアに  
    アクセスできない時に  
    即エラーを返さず、  
    バッファリング機能を搭載し  
    エラーまでのタイムアウト時間を  
    伸ばすか?しかしその影響は  
    どの範囲まで許容できる?
    92

    View Slide

  93. などなど考えていたが  
    いきなり100%を目指すのは難しい
    細かい機能リリース時に  
    念のためメンテナンスを実施する  
    昭和的運用だったので  
    一旦は都度メンテナンスの  
    タイミングで  
    正常系を遷移する予定だった
    93

    View Slide

  94. そして
    94

    View Slide

  95. この時構築中の  
    システムが乗る  
    アプリケーションは  
    リリースに追われ
    結合テストや負荷テストなど  
    十二分に行われてはいないまま  
    リリース日が刻々と迫っていた
    95

    View Slide

  96. 本題
    96

    View Slide

  97. 我々は  
    どのように  
    冗長化を失敗したのか
    97

    View Slide

  98. 問題  
    hostsの場合
    98

    View Slide

  99. 内部間の通信が01,  02とある内の  
    01のみにアクセスが集中していた 
    access no access
    01 02
    99

    View Slide

  100. 何が起こっていたのか
    100

    View Slide

  101. hostsに設定が書いてある場合  
    上から順に見ていき、  
    最初にヒットしたレコードを返す
    hosts
    ---
    # service foo-app
    192.0.2.11 foo-app.service.dc1.consul
    192.0.2.12 foo-app.service.dc1.consul
    ---
    101
    request
    response

    View Slide

  102. 01にしか処理が行かないのは  
    当然といえば当然だった  
    やる前に気付け問題
    102

    View Slide

  103. 解決作
    103

    View Slide

  104. Dnsmasq  
    nsswitch.conf  
    Dnsmasq  Ver.  2.48-14
    104

    View Slide

  105. 全サーバにDnsmasqが  
    稼働していたので  
    nsswitch.confで  
    hostsより先にDnsmasqを  
    先に見るようにした
    105

    View Slide

  106. nsswitch.conf  
    hostsの部分を書き換える
    hosts: files dns
    before:
    after: hosts: dns files
    106

    View Slide

  107. DNSラウンドロビン  
    されるようになった
    107

    View Slide

  108. 問題  
    mysqlfailoverの場合
    108

    View Slide

  109. mysqlfailoverのログを見ると  
    ちょくちょくhealth  checkに  
    失敗していた
    109

    View Slide

  110. mysqlfailoverの仕組み
    110

    View Slide

  111. def is_alive(self):
    """Determine if connection to server is still alive.
    Returns bool - True = alive, False = error or cannot connect.
    """
    res = True
    try:
    if self.db_conn is None:
    res = False
    else:
    # ping and is_connected only work partially, try exec_query
    # to make sure connection is really alive
    retval = self.db_conn.is_connected()
    if retval:
    self.exec_query("SHOW DATABASES")
    else:
    res = False
    except:
    res = False
    return res
    Health  Check時に  
    MySQLに接続し  
    SHOW  DATABASESを実行
    111

    View Slide

  112. def _reconnect_master(self, pingtime=3):
    """Tries to reconnect to the master
    This method tries to reconnect to the mast
    after 3 attemps, returns False.
    """
    if self.master and self.master.is_alive():
    return True
    is_connected = False
    i = 0
    while i < 3:
    try:
    self.master.connect()
    is_connected = True
    break
    except:
    pass
    time.sleep(pingtime)
    i += 1
    return is_connected
    失敗した場合は  
    ping(pingtime)  x3  試す
    x3はハードコードされている
    112

    View Slide

  113. どうにか3回のリトライ中に  
    成功はしているようだが、  
    そもそも  
    ステージングで検証した時は  
    Failは起こらなかった...
    113

    View Slide

  114. ping(pingtime)  x3の回数を  
    増やして様子を見る案もあったが  
    Failの原因が不明のまま  
    自動遷移の機構を  
    入れておくのは危険だった
    114

    View Slide

  115. 原因が不明なため、  
    Redisも含めた  
    自動遷移のシステムを停止した
    115

    View Slide

  116. 冗長化は幻しとなった
    116

    View Slide

  117. 原因について
    117

    View Slide

  118. 原因その1  
    VPNがおかしい
    118

    View Slide

  119. パブリック層から  
    プライベート層への接続が  
    日本中をめぐっていた
    119

    View Slide

  120. 不要なルーティングを  
    改修した
    120

    View Slide

  121. mysqladmin  ping
    121

    View Slide


  122. 122

    View Slide

  123. 原因その2  
    謎のスロークエリ
    123

    View Slide

  124. 時間によって  
    同じクエリでも  
    やたら遅いクエリが  
    存在していた
    124

    View Slide

  125. クラウド上のDBサーバが  
    乗っかっているホストの  
    I/Oが忙しいのでは?と  
    仮説を立て、DBサーバを  
    別のホストに移動してもらった
    125

    View Slide

  126. Slow  Queries
    126

    View Slide


  127. 127

    View Slide

  128. その3  
    根本的原因  
    そもそも利用していた  
    クラウドサービスが  
    はじまったばかりで  
    全然枯れていなかった
    128

    View Slide


  129. 129

    View Slide

  130. 不穏な動作の原因は  
    大体特定できたが  
    ネットワークの不調など  
    予期しないタイミングで  
    遷移されても困る
    130

    View Slide

  131. 自動遷移の利便性  
    -  MTTR(平均修理時間)の大幅な削減  
    - 復旧作業時のヒューマンエラー防止  
    - 圧倒的な満足感  
    - 人間がいない清らかな世界感
    131

    View Slide

  132. 手動遷移の優位性  
    -  意図したタイミングで遷移が可能  
    - 冗長監視システム誤動作の心配がない
    I'm fail over button
    Don't push me !!
    132

    View Slide

  133. 復旧時間を犠牲にして、  
    我々は自動遷移システムを止めた  
    その代わり  
    一撃で正確に遷移するような  
    ヒューマンエラーの起こらない  
    仕組みを入れることにした
    133

    View Slide

  134. そして
    134

    View Slide

  135. のっかるアプリケーションも  
    乗せるサーバ周りも  
    問題を抱えたまま  
    リリースを日を迎えた
    135

    View Slide

  136. 昼寝ができるぐらい遅い  
    レスポンスタイム
    繰り返されるN+1クエリ
    それが要件の結果の  
    動作だったのか  
    今となっては  
    誰もわからない各機能
    136





    View Slide

  137. 迫り来る  
    圧倒的成長機会に  
    感謝をしながら  
    改修対応を  
    行う日々が始まった
    ※もちろん若干盛っています
    137

    View Slide

  138. 138

    View Slide

  139. まとめ、学び
    139

    View Slide

  140. どれだけリリース直前まで  
    炎上していても  
    絶対に  
    本番環境と同等のシステム構成で  
    負荷テストをしよう
    実証
    140

    View Slide

  141. 結合テストが難しい場合は  
    各機能毎に負荷テストが  
    実施できるようにしよう  
    外部との依存部分を  
    最小限のモックにするなど  
    結合を待ってから試験をすることは  
    極力避けるようにしよう
    個別性能試験
    141

    View Slide

  142. 使う理由が良くわからなくても  
    自分が担当するところは  
    最終的に自分が  
    責任を持つことになるので  
    疑問点をなくすために  
    完全に検証をやりきろう
    道具への理解と責任
    142

    View Slide

  143. 期待するな、  
    計測しよう
    143

    View Slide

  144. 挑戦するなら  
    徹底的に検証しよう
    144

    View Slide

  145. 手に馴染んだ  
    道具を使おう
    145

    View Slide

  146. 当たり前のことを  
    当たり前に正しく行おう
    146

    View Slide

  147. Production  System  is  
    not  your  sandbox.
    147

    View Slide

  148. Webサービスが続く限り  
    顧客へ価値を  
    届け続けるために  
    我々の稼働率の戦いは  
    これからも続く
    148

    View Slide

  149. 149

    View Slide

  150. 次回予告
    150

    View Slide

  151. 式年遷宮  
    インフラストラクチャ  
    三部作最終章
    151

    View Slide

  152. クラウドの中心で  
    式年遷宮を叫んだ愚か者  
    Take  care  of  system.  
    鋭意製作中
    152

    View Slide

  153. To  be  continued
    153

    View Slide

  154. おわり
    ありがとう  
    ございました
    154

    View Slide

  155. Redis  
    http://redis.io/  
    Redis  Sentinel  
    http://redis.io/topics/sentinel  
    MySQL  
    https://www-jp.mysql.com/  
    MySQL  Utilities  
    https://dev.mysql.com/downloads/utilities/  
    Consul  by  HashiCorp  
    https://www.consul.io/  
    consul-template  
    https://github.com/hashicorp/consul-template  
    Dnsmasq  -  network  services  for  small  networks.  -  Simon  Kelley  
    http://www.thekelleys.org.uk/dnsmasq/doc.html  
    Consulと自作OSSを活用した100台規模のWebサービス運用  by  FUJIWARA  Shunichiro  
    https://speakerdeck.com/fujiwara3/consultozi-zuo-osswohuo-yong-sita100tai-gui-mo-
    falsewebsabisuyun-yong
    参考URL
    155

    View Slide

  156. 参考URL
    式年遷宮Infrastracture  /  さよならインターネット  
    http://blog.kenjiskywalker.org/blog/2013/08/11/shikinen-sengoo-infrastracture/  
    神宮式年遷宮  /  Wikipedia  
    https://ja.wikipedia.org/wiki/%E7%A5%9E%E5%AE%AE%E5%BC%8F
    %E5%B9%B4%E9%81%B7%E5%AE%AE  
    冗長化  /  Wikipedia  
    https://ja.wikipedia.org/wiki/%E5%86%97%E9%95%B7%E5%8C%96  
    完成されたシステムなどない。完成された人間もいない。あるのは成長し続ける未完成
    なシステムと、それを支える未完成な人間だけだ  /  YAPC::Asia  Tokyo  2014  
    http://yapcasia.org/2014/talk/show/4c7651e8-ed53-11e3-9faf-6ba36aeab6a4  
    156

    View Slide

  157. 「迷ったら健全な方」  
    Being  healthy  dev  and  ops  in  Cookpad  by  Issei  Naruta  /  Speaker  Deck  
    https://speakerdeck.com/mirakui/being-healthy-dev-and-ops-in-cookpad  
    「仕事道具に対しても責任を持ちたい」  
    監視ツールの話  by  @kazeburo  /  slideshare  
    http://www.slideshare.net/kazeburo/ss-13361002
    参考URL
    157
    ImmutableServer  /  Martin  Fowler  
    http://martinfowler.com/bliki/ImmutableServer.html  
    BlueGreenDeployment  /  Martin  Fowler  
    http://martinfowler.com/bliki/BlueGreenDeployment.html  
    Trash  Your  Servers  and  Burn  Your  Code:  Immutable  Infrastructure  and  Disposable  Components  /  Chad  Fowler
    http://chadfowler.com/blog/2013/06/23/immutable-deployments/  
    インフラ系技術の流れ  /  Gosuke  Miyashita  
    http://mizzy.org/blog/2013/10/29/1/  
    Rebuild.fm  25:  Immutable  Infrastructure  (Naoya  Ito,  Gosuke  Miyashita).  
    http://rebuild.fm/25/

    View Slide