Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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
  2. 話すこと 挑戦したこと   冗長化について   Redis  +  Redis  Sentinel  

    Consul   MySQL  +  mysqlfailover   consul-template   hostsの順番   クラウドという名の混乱   対応   冗長化の終わり、そして 3
  3. 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
  4. ”冗長化(じょうちょうか)とは、    システムの一部に    何らかの障害が発生した場合に備えて、    障害発生後でも    システム全体の機能を維持し  

     続けられるように予備装置を    平常時からバックアップとして    配置し運用しておくこと。    冗長化によって得られる安全性は    冗長性と呼ばれる。” Wikipedia調べ 16
  5. 構成 Public Web Server A 02 Web Server A 01

    Web Sever B 02 Web Server B 01 26
  6. nginx + Redis(Slave) Application A 02 各ウェブサーバでは   nginxとRedis、  

    Web  Applicationが動いている nginx + Redis(Master) Application A 01 29
  7. 監視用のサーバを置いた場合   監視用のサーバも遷移させる? 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
  8. Master : Sentinel x1 Slave : Sentinel x2 Redis Master

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

    Redis (New) Slave Sentinel x1 ⇣ Sentinel x2 Redis (New) Master Sentinel x2 ⇣ Sentinel x1 39
  10. 44

  11. #!/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
  12. #!/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
  13. #!/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
  14. { "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
  15. 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
  16. #!/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
  17. #!/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
  18. 変化があった場合に   /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
  19. # 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
  20. 作成される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
  21. # 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
  22. こうなる。便利 こうなる # 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
  23. 今考えていることメモ Web  API側、ネイティブアプリ側   それぞれでデータストアに   アクセスできない時に   即エラーを返さず、  

    バッファリング機能を搭載し   エラーまでのタイムアウト時間を   伸ばすか?しかしその影響は   どの範囲まで許容できる? 92
  24. 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
  25. 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
  26. 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
  27. 122

  28. 127

  29. 129

  30. 138

  31. 149

  32. 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
  33. 参考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
  34. 「迷ったら健全な方」   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/