クックパッドはなぜ開発しやすいのか
At AWS Summit Tokyo 2015 Developer Conference 2015/06/03
ΫοΫύουͳͥ։ൃ͍͢͠ͷ͔ΫοΫύουגࣜձࣾాҰੜ"844VNNJU5PLZP
View Slide
ాҰੜͳΔͨ ͍͍ͬͤ!NJSBLVJΫοΫύουגࣜձࣾΠϯϑϥετϥΫνϟʔ෦
ΫοΫύουʹ͍ͭͯ
.6#NP.14VTFST.DPPLJOHSFDJQFT˞݄ݱࡏ!"#!
'VMM"8420113݄ ౦ژϦʔδϣϯΦʔϓϯ20118݄ DC͔ΒAWSҠߦ✈
&$JOTUBODFT BUQFBL SFRTFD BUQFBL$
0QT%FWFMPQFST%FQMPZTEBZ⚒#
IUUQTTQFBLFSEFDLDPNB@NBUTVEBUIFSFDJQFGPSUIFXPSMETMBSHFTUSBJMTNPOPMJUIΫοΫύουੈքҰڊେͳϞϊϦγοΫ3BJMTΞϓϦέʔγϣϯʢ͔͠Ε·ͤΜʣ
ʮ։ൃ͍͢͠ʯͱԿ͔
%ʮ։ൃ͠ʹ͍͘ʯঢ়ଶͷྫٕज़తͳʹΑͬͯΠϊϕʔγϣϯ્͕͞Ε͍ͯΔঢ়ଶେྔͷϨΨγʔίʔυɺٕज़తෛ࠴ςετ͋Δ͚Ͳৗʹ͍͔ͭ͘ Fail ͍ͯͯ͠ɺ ์ஔ͞Ε͍ͯΔσϓϩΠ͕ଐਓతͰɺ͕͔͔࣌ؒΓ͗ͨ͢Γɺ ͨ·ʹࣦഊͨ͠Γ͢Δ
։ൃ͠ʹͯ͘͘Կ͕ѱ͍ʁݱָ͕Λ͍ͨ͠ૉૣ͘ՁΛఏڙ͍ͨ͠
⚒։ൃσϓϩΠ ςετ
։ൃ⚒
αʔϏε։ൃͱԿͳͷ͔࡞͍ͬͯΔͷʮػೳʯͰͳ͘ʮαʔϏεʯʮϢʔβମݧʯμϛʔσʔλͰͳ͘ຊ൪ͷσʔλΛͬͯ։ൃ͢Δ͖&
ຊ൪ͱಉظͨ͠%#Ͱ։ൃ͢ΔϝϦοτ• Ϣʔβʔͱಉͷମݧ• ༧ظͤ͵σʔλʹΑΔόάʹؾ͖͍ͮ͢• ॏ͍ΫΤϦʹؾ͖͍ͮ͢
'#ຊ൪%# ։ൃ%# ։ൃऀ.Z42- .Z42-NZTRMEVNQ(#։ൃऀͷ୭͔͕ؾ͕͍ͨ࣌ʹຊ൪μϯϓσʔλ͔Β։ൃ DB Λߋ৽ʢʹ1͘Β͍ʣd
खಈߋ৽ํࣜͷݱߦͷσʔλͷΈͰൃੜ͢ΔΑ͏ͳΤϥʔʹؾ͖ͮʹ͍͘৽ணίϯςϯπʹؔ࿈ͨ͠ಈ࡞֬ೝ͕͠ʹ͍͘ϢʔβͷମݧͱҟͳΔ
' ''###ຊ൪%# ։ൃ%#NBTUFS TMBWFSFBEXSJUF։ൃऀ.Z42- .Z42-ݱࡏ։ൃऀৗʹຊ൪ͷ࠷৽σʔλ͕ೖͬͨDBͰ։ൃ
Ͳ͏Δͷ͔ݒ೦slave ʹॻ͖ࠐΜͩΒΩʔিಥͰ ϨϓϦέʔγϣϯΤϥʔʹͳΔͷͰʁid ͕ຊ൪ͱͣΕͯ݁ہ͑ͳ͍σʔλʹͳΔͷͰʁ
JE OBNF ΧϨʔ ͔Β͋͛ ͡Ό͕JE OBNF ΧϨʔ ͔Β͋͛ ͡Ό͕ ͦ'# ຊ൪%# ։ൃ%#*/4&35ϨϓϦέʔγϣϯ ϥʔϝϯ௨ৗɺslave ʹॻ͖ࠐΜͰ͠·͏ͱAUTO_INCREMENT ͍ͯ͠Δ id ͕িಥ͢Δ
JE OBNF ΧϨʔ ͔Β͋͛ ͡Ό͕JE OBNF ΧϨʔ ͔Β͋͛ ͡Ό͕ ͦ ͏ͲΜ ੜᇙম͖'# ຊ൪%# ։ൃ%#*/4&35ϨϓϦέʔγϣϯAUTO_INCREMENT ʹڊେͳΦϑηοτΛઃఆ͢Δ͜ͱͰຊ൪ͱিಥ͠ʹ͘͘͢Δ ϥʔϝϯ
JE OBNF ΧϨʔ ͔Β͋͛ ͡Ό͕JE OBNF ΧϨʔ ͔Β͋͛ ͡Ό͕ ͦ ͏ͲΜ ੜᇙম͖ ຊ൪%# ։ൃ%#εςʔτϝϯτϕʔεϨϓϦέʔγϣϯ࠷৽ͷ݅ΛʮমʯʹมߋUPDATE recipes SET name=‘ম’ ORDER BY id DESC LIMIT 1মমεςʔτϝϯτϕʔεϨϓϦέʔγϣϯͰ։ൃ DB ͷσʔλ͕յΕ͍͢
JE OBNF ΧϨʔ ͔Β͋͛ ͡Ό͕JE OBNF ΧϨʔ ͔Β͋͛ ͡Ό͕ ͦ ͏ͲΜ ੜᇙম͖ ຊ൪%# ։ൃ%#ߦϕʔεϨϓϦέʔγϣϯ࠷৽ͷ݅ΛʮমʯʹมߋUPDATE recipes SET name=‘ম’ ORDER BY id DESC LIMIT 1ম মߦϕʔεϨϓϦέʔγϣϯʹ͢Δ͜ͱͰ։ൃ DB ͷσʔλ͕յΕʹ͘ͳΔ
ຊ൪%# ։ൃ%#ߦϕʔεϨϓϦέʔγϣϯεςʔτϝϯτϕʔεϨϓϦέʔγϣϯCJOMPHม༻%#ߦϕʔεϨϓϦέʔγϣϯͰɺόΠφϦϩάసૹྔ͕ڊେʹͳΓɺຊ൪ʹෛՙ͕͔͔ΔͨΊ࣮ࡍʹதؒ DB Λ༻ҙ͠όΠφϦϩάΛม͍ͯ͠Δ
ϨϓϦέʔγϣϯఀࢭରࡦඞཁෆ߹ى͖ʹ͘͘Ͱ͖Δ͕ɺܾͯ͠ᘳͰͳ͍ͷͰ ϨϓϦ͕ΤϥʔͰࢭ·Δ͜ͱ͋Δslave_skip_errors = ONΛઃఆͭͭ͠ɺఀࢭͨ͠Β skip ͯ͠࠶։͢ΔࢹεΫϦϓτΛӡ༻ʢslave_skip_errors͚ͩͰ skip ͞Εͳ͍Τϥʔ͕͋ΔͨΊ…ʣ
' ''###ຊ൪%# ։ൃ%#NBTUFS TMBWFSFBEXSJUF։ൃऀ.Z42- .Z42-։ൃऀৗʹຊ൪ͷ࠷৽σʔλ͕ೖͬͨDBͰ։ൃ
ຊ൪ڥͰ։ൃ͢Δw
&BUZPVSPXOEPHGPPEࣗͨͪͷαʔϏε͕ࣗͨͪϢʔβʹͳΔ͖♥
ඇϩάΠϯελοϑϢʔβͱͯ͠ϩάΠϯελοϑ͕ϩάΠϯ͢Δͱɺ։ൃதͷϕʔλػೳ͕͍ͭ͘༗ޮʹͳΔ
ϕʔλػೳϦϦʔεൣғΛࢦఆͯ͠ެ։ެ։ൣғͷྫελοϑͷΈʹެ։ςετࢀՃϢʔβʹͷΈެ։શମͷ10%ͷϢʔβʹެ։
αʔϏεͷՁΘͳ͍ͱ͔Βͳ͍ͦͷՁͷԾઆਖ਼͔ͬͨ͠ͷ͔ʁຊ൪ʹϦϦʔε͠ͳ͍ͱɺϢʔβʹͬͯΒ͏͜ͱ͕Ͱ͖ͳ͍ຊ൪ʹϦϦʔε͢Δʹຊ൪ͷ࣭ͷ ίʔυʢύϑΥʔϚϯεʣʹ্͛ͳ͚ΕͳΒͳ͍ʁˠඞཁͷͳ͍ػೳΛ࡞Γ͜ΜͰ͠·͏Մೳੑ͕͋Δ
ૣࣦ͘ഊΛ͢Δίʔυͷ࡞ΓࠐΈʹ࣌ؒΛ͔͚ΔΑΓɺૉૣ͘ެ։ͯ͠ԾઆΛݕূ͢ΔͨΊʹ࣌ؒΛ͏͖*
$IBOLPຊ൪ڥͰͷτϥΠˍΤϥʔΛࢧԉ͢Δ Rails ༻ gemUnit ͱ͍͏୯ҐͰطଘίʔυͷύονΛهड़࣭ͷ͍ίʔυΛຊ൪ʹ҆શʹग़ͤΔIUUQTHJUIVCDPNDPPLQBEDIBOLP+
" #طଘͷίʔυ A ΛɺελοϑϢʔβͷΈʹରͯ͠ϕʔλ൛ͷίʔυ B ʹஔ͖͍͑ͨͨͩ͠ɺB ݥతͳ࣮ͳͷͰɺྫ֎͕ൃੜ͢Δ͔͠Εͳ͍طଘͷ$POUSPMMFSͷίʔυ ϕʔλ൛ͷίʔυ
ελοϑͳΒ##Ͱྫ֎͕ى͖ͨΒ"ελοϑҎ֎ͳΒ"ϑϥάͰذ͍ͤͯ͘͞ͱίʔυ͕ԚΕ͍ͯ͘
ϕʔλػೳͷ6OJUطଘͷ$POUSPMMFSͷίʔυ"#Chanko ͰɺUnit ͱ͍͏ϑΝΠϧʹϕʔλػೳͷϩδοΫΛهड़͢Δinvoke ݅Λຬͨͨ͠߹ʹɺطଘϩδοΫ (A) ͷΘΓʹ Unit (B) ͕࣮ߦ͞ΕΔB ͕ྫ֎Λىͨ͜͠߹ɺݩͷ A ͕࣮ߦ͞ΕΔͨΊɺϢʔβʹΤϥʔ͕ฦΒͳ͍JOWPLF݅
ແࣄʹՁ͕ೝΊΒΕͨΒຊ൪ͷ࣭ͷίʔυʹ্͛ΔطଘίʔυΛॻ͖͑ɺUnit ϑΝΠϧΛফ͢ ʢ௨শ Un-chankoʣ
$IBOLPͷӡ༻ঢ়گ2011: Chanko ϦϦʔε + ಋೖ2015: 200+ Chanko Units• εςʔδϯά༻ͷαʔόଘࡏ͢Δ͕ɺར༻ස͍• ։ൃதͷͷΛຊ൪ʹग़͢จԽ͕Ͱ͖͍ͯΔ
ςετ
ΫοΫύουͱ34QFD1800+ files21000+ examples (test cases)7 min,
5FTUTNFMMT࣮ߦ͕͍࣌ؒյΕ͍͢ʢίʔυͷมߋʹऑ͍ʣFail ͍࣮͢͠ߦڥͷґଘ-
3334QFD
.3334QFDͯ͘ɾ҆ͯ͘ɾ҆ఆͨ͠$*ෳͷ Spot Instance Λͬͯ RSpec Λฒྻ࣮ߦڧྗͳϑΥʔϧττϨϥϯεIUUQTHJUIVCDPNDPPLQBESSSTQFD+
////TMBWFTMBWFXPSLFSXPSLFSXPSLFSʜ/ʜʜʜ////NBTUFS////ʜ
$*XPSLFSͷભҠۀ࣌ؒ֎ΛݮΒͯ͠ ίετݮ
&$4QPU*OTUBODFͳΔ͘ϋΠεϖοΫͳΠϯελϯεΛ͍͍͕ͨߴՁ→Spot Instance ͷར༻0
&$4QPU*OTUBODFʮ1࣌ؒ͋ͨΓͷ࠷େೖࡳՁ֨ʯΛࢦఆͯ͠ىಈ͢Δࢦఆͨ͠ʮ࠷େೖࡳՁ֨ʯΑΓ૬Ձ͕͚֨҆Εىಈىಈதʹ૬Ձ͕֨ʮ࠷େೖࡳՁ֨ʯΛ্ճͬͨ߹ɺ Πϯελϯεγϟοτμϯ͞ΕΔ૬Ձ֨ OnDemand Ձ֨ΑΓߴ͘ͳΔ͜ͱ͋Δ૬Ձ֨ AZ ͝ͱʹΑͬͯҟͳΔ
౦ژϦʔδϣϯͷͱ͋Δ";ʹ͓͚Δ4QPU1SJDF DYMBSHF0OEFNBOE I3*ZBMMVQGSPOU I
DYMBSHFDYMBSHFDYMBSHF˺ ˺DYMBSHFDYMBSHFDYMBSHF˺ ˺Ұ൪ίετύϑΥʔϚϯε͕͍͍ ΠϯελϯεΛࣗಈతʹબ
ϑΥʔϧττϨϥϯε͍͔ʹͯ͠GBJM͠ʹ͍͘$*ʹ͢Δ͔·Εʹࣦഊ͢ΔFYBNQMFʹରͯ͠ɿۭ͍͍ͯΔ worker Ͱࣗಈతʹ࠶࣮ߦ ҰͰ success ͢Ε success ͱͯ͠ѻ͏4QPU*OTUBODFͷࣗಈγϟοτμϯʹରͯ͠ɿଞͷ worker Ͱࣗಈతʹ࠶࣮ߦผλΠϓͷΠϯελϯεΛىಈ͠࠶࣮ߦ
ׂΕ૭ཧݐͷ૭ׂ͕Ε͍ͯΔ֗ɺ࣏͕҆ѱԽ͢Δܰඍͳ൜ࡑΛపఈతʹऔΓక·Δ͜ͱͰ ڟѱ൜ࡑΛࢭͰ͖Δͱ͢Δڥ൜ࡑ্ֶͷཧIUUQKBXJLJQFEJBPSHXJLJׂΕ૭ཧ-
$*͕ʮׂΕ૭ʯʹͳΒͳ͍Α͏ʹܰඍͳ͏ͪʹൃݟ͠ɺରॲ͢Δ• Ϗϧυ͕࣌ؒ͘ͳΔ• ͚ͯ͜Δςετͷ์ஔ• pending ঢ়ଶͳςετͷ์ஔ1
௨Fail ͨ͠ example ࡞ऀΛ blame ͯ͠νϟοτͰ௨Fail ͬ͠ͺͳ͠ʹͤ͞ͳ͍
·Εʹ'BJM͢ΔςετΛݟ͚ͭΔlBMMOJHIU$*zۀ࣌ؒ֎ʹͣͬͱճ͠ଓ͚Δ CIsuccess ͕͍ͱԿ͔͕͓͔͍͠
ඪ ҎҎ্͔͔ͬͨΒ௨$*ͷϏϧυ࣌ؒΛࢹ
QFOEJOHʹͤͬ͞ͺͳ͠ͷςετͷ࡞ऀʹࣗಈ௨IUUQTHJUIVCDPNDPPLQBEQFOEBYFT+
$*ӡ༻ͷ·ͱΊ• ༏Εͨ CI γεςϜΛ࡞Δ͜ͱΑΓɺ Ͳ͏ӡ༻͢Δ͔͕ॏཁ• Ϗϧυ࣌ؒɾ௨աɾίετͳͲͷ ࢦඪΛఆٛͯ͠ࢹ͠ɺ վળ͍ͯ͘͠• ׂΕ૭ʹ͠ͳ͍2
σϓϩΠ
+TVDDFTT-(5.QVMMSFRVFTUNFOUJPOEFQMPZ&$(JU)VC&OUFSQSJTF#EFWFMPQFS#SFWJFXFS$*+FOLJOTNFSHF
σϓϩΠϧʔϧʢҰ෦ʣ• CI Λύεͨ͠ϦϏδϣϯͷΈσϓϩΠͯ͠Α͍• σϓϩΠίʔυΛ push ͨ͠։ൃऀ͕ࣗߦ͏• Ӧۀ࣌ؒͷΈσϓϩΠՄೳ• σϓϩΠޙ։ൃऀ͕ಈ࡞֬ೝ͠ɺ ෆ۩߹Λݟ͚ͭͨΒ͙͢ʹϩʔϧόοΫ͢Δ
σϓϩΠʹॏཁͳ͜ͱ• ଐਓతͰͳ͍͜ͱ• ਖ਼֬Ͱ͋Δ͜ͱ• ϩʔϧόοΫͰ͖Δ͜ͱ• ेʹ͍͜ͱ 3
ۙिؒͷσϓϩΠʹ͔͔ͬͨ࣌ؒฏۉඵIPTUT
$BQJTUSBOP࣌ʢʙʣcapistrano2 + rsync_with_remote_cache
$BQJTUSBOPσϓϩΠͱ1͔Βશʹ ssh + rsyncσϓϩΠରϗετ͕૿͑Δͱ͘ͳ͍ͬͯ͘
σϓϩΠରϗετશʹTTISTZODˠσϓϩΠͷϘτϧωοΫʹ$BQJTUSBOP#///////STZOD
.BNJZB
.BNJZBϋΠεέʔϥϒϧͳߴσϓϩΠγεςϜσϓϩΠରϗετΛ serf ͰΫϥελϦϯάAmazon S3 ܦ༝ͰCapistrano ޓͷσΟϨΫτϦߏIUUQTHJUIVCDPNTPSBINBNJZB+
/$* UBSCBMM 4$*͕௨ͬͨϦϏδϣϯͷίʔυUBSCBMMͱͯ͠4ʹૹΒΕΔ
////////$*͕௨ͬͨϦϏδϣϯͷUBSCBMMશ͕ৗʹࣗಈͰQVMM͍ͯ͠Δʢ͜ͷ࣌Ͱ·ͩຊ൪ͷίʔυΓସΘ͍ͬͯͳ͍ʣ/
σϓϩΠͷࢦྩ4FSGΠϕϯτͱͯ͠(PTTJQϓϩτίϧͰ#!IVCPUEFQMPZQSPEVDUJPO
શͷϦϏδϣϯ͕ΓସΘΔʢϑΝΠϧ͋Β͔͡Ί͍ྃͯ͠ΔͨΊɺߴʹྃ͢Δʣ/ // // // // / / // // /#
.BNJZBͷεέʔϥϏϦςΟMamiya σϓϩΠରϗετ૿Ճʹରͯ͠εέʔϥϒϧϗετ͕૿Ճͯ͠ʢ΄ͱΜͲʣ͘ͳΒͳ͍ϑΝΠϧͷɿS3 ͷεέʔϥϏϦςΟΛར༻શͷϦϏδϣϯΓସ͑ࢦྩɿSerf ΠϕϯτΛར༻
.BNJZBʹΑΔσϓϩΠ࣌ؒॖޮՌˠඵDBQJTUSBOP NBNJZBDBQJTUSBOP NBNJZB
͓ΘΓʹ
։ൃͷ͢͠͞ΛอׂͭΕ૭Λ࡞Βͳ͍ͨΊʹɺऀͱࢦඪ͕ඞཁ4
ʮ։ൃ͢͠͞ʯͷՁ• ։ൃ͔ΒσϓϩΠ·ͰͷαΠΫϧ͕ेʹ͚Εɺ ʮຊ൪ڥΛͬͨ։ൃʯ͕࣮ݱͰ͖Δ→Ϣʔβͱಉ͡ମݧͷதͰ։ൃ͢Δ• ։ൃ͢͠͞ʹࢿ͢ΔՁेʹ͋Δ• ݁Ռͱͯ͠։ൃ৫αʔϏε݈શͳঢ়ଶΛอͯΔ'JO