Share
Embed
Amazon ECSで好きなだけ検証環境を起動できるOSSの設計・実装・運用 / YAPC::Hiroshima 2024
FUJIWARA Shunichiro
February 09, 2024
Transcript
50 slides
-
ࣗݾհ @fujiwara ໘ന๏ਓΧϠοΫSREνʔϜ ISUCON 1,2,5,11 ! ༏উ4ճ ISUCON 3,8,12,13 ӡӦ(ग़)
4ճ github.com/kayac/ecspresso Amazon ECS σϓϩΠπʔϧ github.com/fujiwara/lambroll AWS Lambda σϓϩΠπʔϧ -
࣮ݱํ๏(1) ʮࣄલʹෳڥΛ࡞͍ͯ͠ճ͢ʯ ͋Β͔͡ΊɺڥΛෳ༻ҙ͓ͯ͘͠ ڥҙͷϒϥϯνʹΓସ͑ͯىಈͰ͖ ΔΑ͏ʹ͓ͯ͘͠ ͍͍ͨਓ͕ۭ͍͍ͯΔڥΛ ҙͷϒϥϯνͰىಈͯ͠͏ - ୭͕Ͳ͜Λ͍ͬͯΔ͔Λཧ͢Δඞཁ
- ͍ऴΘͬͨΒ͔ʹ։์͠ͳ͍ͱଞͷਓ ͕͑ͳ͍ - ͔ͱ͍ͬͯશһ༻ҙ͢Δͱߴίετ -
࣮ݱํ๏(2) ʮඞཁͳ࣌ʹIaCͰશ෦࡞Δʯ ͍͍ͨλΠϛϯάͰඞཁͳαʔόʔϦιʔεΛҰࣜ·Δͬͱ࡞ ྫ: AWSͰALB + ECS + RDS +
Elas0Cache ALB, ECSαʔϏε/λεΫ, RDS, ElastCache Λ࡞Ͱ͖Δίʔυ (Terraformͱ͔CFnͱ͔CDKͱ͔)Λ࡞͓͍ͬͯͯόʔϯ -
ʮඞཁͳ࣌ʹIaCͰશ෦࡞Δʯ ํ๏ͷ ࡞Δͷʹֻ͕͔࣌ؒΔ(͕ͭ͋Δ) - ৽نͷRDSElas*CacheΛىಈ͢Δͱ20ʙͱ͔ Ұؙࣜ͝ͱ༻ҙ͢Δͱͱʹֻ͔͓͕͔ۚ͘Δ - ফ͠ΕΔͱ… ! ڞ༻Ϧιʔεͱಈతͳ࡞/আͱIaCͷ૬ੑ͕ඍົ(ͳ͜ͱ͕͋Δ)
- ίετݮͷͨΊʹҰ෦ͷϦιʔε(LBͳͲ)Λڞ༻͢Δͱى͖͕ͪ - ڥAͷ࡞ͱBͷআฏߦͰͰ͖ͳ͍ɺͱ͔ -
mirage-ecs ʮϒϥϯνผ։ൃɾݕূڥʯΛߴʹىಈͰ͖Δ ίετͰ࣮ݱ͢ΔιϑτΣΞ(OSS) github.com/acidlemon/mirage-ecs mirage-ecs is a reverse proxy for
ECS tasks and a manager for the tasks. ECSλεΫͷϚωʔδϟʔ݉ϦόʔεϓϩΩγ -
֓೦ਤ ALBʹ *.example.com ΛׂΓͯΔ mirage-ecsʹશͯͷϦΫΤετΛసૹ - foo.example.com ڥ foo ʹproxy
- bar.example.com ڥ bar ʹproxy mirage.example.com Ͱ WebUI / API Λఏ ڙ - ڥىಈ → ECS RunTask - ڥআ → ECS StopTask mirage-ecs ͱ 1.ʮڥʯΛ ECS ͷλεΫͱͯ͠ىಈ/ఀࢭ 2.ʮڥʯͷϦΫΤετΛλεΫʹ Reverse Proxy͢ΔιϑτΣΞ -
mirage-ecsΛ͏ͱͳʹ͕خ͍͔͠ ͍͍ͨڥΛԿݸͰɺ͙͢ʹ༻ҙͰ͖Δ - ECSλεΫΛFargateͰىಈ͢Ε͍ͭ͘Ͱ - ىಈ࣌ؒ࠷1ʙͯ͘10ఔ ίετ - 1ڥ =
ECSλεΫ1ݸ(1ʙ2vCPU, Memory 4GBʙ) - ECS on EC2Ͱಈ͔͢͜ͱՄೳ ڥͷىಈআ͕WebUIͱAPIͰૢ࡞Ͱ͖Δ - WebUI: ඇΤϯδχΞʹ༏͍͠ - API: ىಈ/আΛSlack botͳͲͰ࣮Ͱ͖Δ -
WebΞϓϦέʔγϣϯΛmirage-ecsͰىಈ͢Δ ඞཁͳͷͱϦϙδτϦ͕ೖͬͨΠϝʔδͱECSλεΫఆٛΛ༻ҙ - GitϦϙδτϦΛΠϝʔδʹম͖ࠐΜͰ͓͘(େ͖ͳϦϙδτϦͷ߹) - খ͍͞߹ىಈ࣌ʹશ෦cloneͯ͠Α͍ mirage-ecs͕ఆٛ͢Δڥม ىಈ࣌ʹڥ໊ͱϒϥϯνΛࢦఆ͢ΔͱɺڥมΛઃఆ͢Δ - SUBDOMAIN
: ڥ໊ fujiwara, event-111, ……ͳͲαϒυϝΠϯ - GIT_BRANCH : main, feature/some-x, …… Gitͷϒϥϯν໊ - ΄͔ʹઃఆͰҙͷڥมΛఆٛͰ͖Δ ↑ WebUI/API͔Βىಈ࣌ʹࢦఆՄೳ -
WebΞϓϦέʔγϣϯΛmirage-ecsͰىಈ͢Δ ίϯςφͷentrypointͰ… ϒϥϯνΛΓସ͑Δ - git (clone|fetch) && switch Ͱ͍͍ͨϒϥϯνʹΓସ͑Δ -
git switch origin/$GIT_BRANCH ← ىಈ࣌ʹࢦఆͨ͠ϒϥϯν DBͳͲͷ֎෦ϦιʔεΛ༻ҙ͢Δ - ࡞ʹֻ͕͔࣌ؒΒͳ͍ɺैྔ՝ۚͳϦιʔεͦͷͰ࡞ - $SUBDOMAIN Λ໊લʹؚΊͯผͷͷͱͯ͠࡞Δ - DynamoDB ͷςʔϒϧͱ͔SQS queueͱ͔ -
WebΞϓϦέʔγϣϯΛmirage-ecsͰىಈ͢Δ ىಈʹֻ͕͔࣌ؒΔɺ࠷՝ֹ͕ۚେ͖͍Ϧιʔεڞ༻͢Δ ྫ: RDS (MySQL) - σʔλϕʔεΛ$SUBDOMAINΛݩʹͯ͠࡞Δ - DBNAME=$(echo $SUBDOMAIN
| tr - _) mysql -e "CREATE DATABASE IF NOT EXISTS $DBNAME ..." ྫ: Elas'Cache Redis - key_prefix Λ ${SUBDOMAIN}: ʹͯ͠ཧతʹ (ΫϥΠΞϯτϥΠϒϥϦͷػೳ) -
WebΞϓϦέʔγϣϯΛ mirage-ecsͰىಈ ֎෦Ϧιʔεͷ४උ͕ऴΘͬͨΒىಈ - DB migra*onॳظσʔλͷimport - ϥΠϒϥϦͷߋ৽ (CPAN, Gem...)ɺϏϧυ
- αʔόʔىಈ (plackup, rails s...) ىಈͨ͠ڥͷReverse Proxymirage-ecs ͕ࣗಈͰఆٛͯ͘͠Ε·͢ -
mirageͷݶք - γϯάϧϗετߏ େྔͷڥΛىಈ͢Δʹେ͖ͳ1ͷΠϯελϯε͕ඞཁ → CPU͋ΔఔΦʔόʔίϛοτͰ͖Δ͕ϝϞϦඞཁ ىಈ࣌ϚΠάϨʔγϣϯ࣌ʹϗετͷετϨʔδΛࠅ͢Δ → IO͕͍ΠϯελϯεͰಈ͔͍ͨ͠ EC2ͳΒi3ΠϯελϯεͷΤϑΣϝϥϧSSDͱ͔
εέʔϧ͍ͨ͠ͱ͖=ಈ͍͍ͯΔϗετ͕ݶքʹୡͨ͠ͱ͖ ҰڥΛશ෦མͱͯ͠ىಈ͔͢͠͠ͳ͍ -
mirageͷ՝ - αΠυΧʔΛ࣋ͯͳ͍ ڥͱͯ͠ىಈ͢Δ୯Ґ = ίϯςφ ඞཁͳαʔόʔɺϛυϧΣΞΛશͯ٧ΊࠐΜͰsupervisorͰىಈ foreman (Ruby) /
kazeburo͞ΜͷProclet (Perl) / ma;n͞Μͷgoreman (Go) ͋ΒΏΔͷ͕શ෦ೖΓͷಛΓίϯςφʹ -
mirage → mirage-ecs LevelDB → ετϨʔδϨε - ReverseProxyͷͨΊʹʮڥ໊ʯ->ʮIPΞυϨεʯͷϚοϐϯά͕ඞཁ - ECSλεΫʹλά͕࣋ͯΔ
- ڥ໊ͳͲͷϝλσʔλλάʹೖΕΔɺIPΞυϨεECS͕͍ͬͯ Δ - ఆظతʹECS APIͰλεΫͱIPΞυϨεΛऔಘͯ͠ReverseProxyఆٛΛ ߋ৽ αΠυΧʔΛ࣋ͯΔ - ʮڥ=ίϯςφʯ→ʮڥ=ECSλεΫ(ίϯςφ࠷େ10ݸ)ʯ -
mirage → mirage-ecs γϯάϧϗετߏ → ෳߏʹͰ͖Δ - ڥmirage͕ಈ࡞͢Δϗετ্Ͱͳ͘ಠཱͯ͠ىಈ - mirage-ecsࣗମετϨʔδϨεͳͷͰෳͰಈ࡞Ͱ͖Δ
ͱ͍͑Proxy͔͠͠ͳ͍ͷͰ100ڥ͋ͬͯ1Ͱे σϓϩΠrollingͰOK - ڥͱVPCͰ௨৴͢ΔͷͰෳͰಈ࡞Ͱ͖Δ -
mirage → mirage-ecs 1ͷΠϯελϯε+mirage(ϓϩηε)+ෳͷDockerίϯςφ(ϓϩηε) ͔Β ෳͷΠϯελϯε(ECSΫϥελ) + mirage-ecs(ECSαʔϏε) + ෳͷڥ(ECSλεΫ)
Πϯελϯε → Ϋϥελ / ϓϩηε → λεΫ εέʔϥϏϦςΟΛ֫ಘ͢ΔͨΊͷίϯςφٕज़ʹͬͨਖ਼౷ਐԽ -
mirage-ecs = GoͷWeb APIαʔόʔ݉reverse proxy ϝΠϯͷHTTPαʔόʔ: ϦΫΤετΛશ෦ड͚ͯHostϔομΛΈΔ - mirage.* →
ΞϓϦέʔγϣϯϋϯυϥΛ࣮ߦ - ͦΕҎ֎ → HostʹରԠͨ͠ڥѼͯͷReverseProxyΛ࣮ߦ ͦͷଞͷgorou%ne worker - ECS APIΛୟ͍ͯReverseProxyΛߋ৽͢Δworker ʮڥ=λεΫʯ͕૿͑ͨΒReveseProxyΛ࡞ͯ͠mapʹՃ ݮͬͨΒReveseProxyΛmap͔Βআ - ϦΫΤετूܭΛCloudWatchʹ͛Δworker -
ίϯϑΟάϨε ॳmirageͰඞཁͩͬͨઃఆ͜Ε͚ͩ host: webapi: mirage.example.com reverse_proxy_suffix: ".example.com" listen: http: -
listen: 80 target: 80 ͜Ε͙Β͍ͳΒखͰॻ͍ͯͳ͍͕… -
ECSͰλεΫΛىಈ͢ΔͨΊͷઃఆ͕(Ͳ͏ͯ͠)ඞཁ ecs: region: "ap-northeast-1" cluster: mycluster default_task_definition: myapp enable_execute_command: true
launch_type: FARGATE network_configuration: awsvpc_configuration: subnets: - subnet-aaaa0000 - subnet-bbbb1111 - subnet-cccc2222 security_groups: - sg-11112222 - sg-aaaagggg assign_public_ip: ENABLED -
mirage link ECSλεΫʹ10ίϯςφ·ͰؚΊΒΕΔ͕Γͳ͘ͳͬͯࠔͬͨͷͰ… 1. ىಈ࣌ʹෳͷλεΫఆٛ(A,B)Λ͢(Ϣʔβʔ) 2. ͦΕͧΕͷλεΫఆ͔ٛΒλεΫa,bΛىಈ͢Δ (mirage-ecs) 3. ίϯςφ໊ͱλεΫͷIPΞυϨεͰRoute53ʹ໊લΛఆٛ(mirage-ecs)
nginx.foo.example.com λεΫaͷIPΞυϨε webapp.foo.example.com λεΫaͷIPΞυϨε backend.foo.example.com λεΫbͷIPΞυϨε sidecar.foo.example.com λεΫbͷIPΞυϨε ෳͷλεΫΛ1ͭͷʮڥʯͱͯ͠ѻ͑Δ -
POST /api/purge { "excludes": ["foo", "bar"], "exclude_tags": ["branch:preview"], "duration": 86400
} excludes: ಛఆͷڥ໊আ֎ exclude_tags: ࢦఆͨ͠λά͕͍͍ͯΔڥআ֎ duration: աڈࢦఆͨ͠ඵʹΞΫηε͕ͳ͍ڥΛআ͢Δ ࢭΊͨ͘ͳ͍ڥ͋ΔͷͰআ֎݅ΛࢦఆՄೳ(ސ٬͚ͱ͔) -
ڥ͕ىಈͰ͖ͳ͍ཧ༝ΛΓ͍ͨ ECSλεΫɺཱͨͳ͍ͱ͖ࠔΓ·͢ΑͶ… github.com/fujiwara/tracer "Amazon ECS λεΫͷΠϕϯτͱϩάΛ࣌ܥྻͰग़͢ tracer Λ࡞ͬͨ"4 - λεΫʹؔ࿈͢ΔΠϕϯτ(࡞ɺىಈ։࢝ɺpull։࢝ͱఀࢭɺఀࢭ։
࢝ɺఀࢭྃͳͲ) - λεΫͷίϯςφ͕ CloudWatch Logs ʹग़ྗͨ͠ϩά - (ECS αʔϏε͔Βىಈ͞ΕͨλεΫͷ߹) αʔϏεͷΠϕϯτϩά ͜ΕΛmirage-ecsͷWebUI͔Β͙͢ݟΒΕΔΑ͏ʹ 4 h$ps:/ /techblog.kayac.com/ecs-task-tracer -
tracerͷग़ྗྫ (ىಈ→ఀࢭ) 2024-01-31T07:05:17.529Z TASK Created 2024-01-31T07:05:32.718Z CONTAINER:nginx LastStatus:PENDING HealthStatus:UNKNOWN 2024-01-31T07:05:32.718Z
TASK LastStatus:PENDING 2024-01-31T07:05:22.775Z TASK Connected 2024-01-31T07:05:32.391Z TASK Pull started 2024-01-31T07:05:39.561Z TASK Pull stopped 2024-01-31T07:05:39.590Z TASK Started 2024-01-31T07:05:40.070Z CONTAINER:nginx LastStatus:PENDING HealthStatus:UNKNOWN 2024-01-31T07:05:40.070Z TASK LastStatus:PENDING 2024-01-31T07:05:40.070Z CONTAINER:nginx LastStatus:RUNNING HealthStatus:UNKNOWN 2024-01-31T07:05:40.070Z TASK LastStatus:RUNNING 2024-01-31T07:05:39.573Z CONTAINER:nginx /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration 2024-01-31T07:05:39.573Z CONTAINER:nginx /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ 2024-01-31T07:05:39.576Z CONTAINER:nginx /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh -- (ུ) -- 2024-02-04T01:03:04.797Z TASK LastStatus:STOPPED 2024-02-04T01:02:50.022Z TASK Stopping 2024-02-04T01:02:50.022Z TASK StoppedReason:Terminate requested by Mirage 2024-02-04T01:02:50.022Z TASK StoppedCode:UserInitiated 2024-02-04T01:02:52.015Z CONTAINER:nginx 2024/02/04 01:02:52 [notice] 1#1: signal 15 (SIGTERM) received, exiting 2024-02-04T01:02:52.018Z CONTAINER:nginx 2024/02/04 01:02:52 [notice] 34#34: exiting 2024-02-04T01:02:52.018Z CONTAINER:nginx 2024/02/04 01:02:52 [notice] 35#35: exiting 2024-02-04T01:02:52.018Z CONTAINER:nginx 2024/02/04 01:02:52 [notice] 34#34: exit -
tracerͷग़ྗྫ (ىಈࣦഊ) 2024-02-04T01:09:02.676Z TASK Created 2024-02-04T01:09:08.180Z TASK LastStatus:STOPPED 2024-02-04T01:09:08.180Z TASK
LastStatus:DEPROVISIONING 2024-02-04T01:09:08.180Z TASK LastStatus:PROVISIONING 2024-02-04T01:09:06.503Z TASK Connected 2024-02-04T01:09:21.109Z TASK Execution stopped 2024-02-04T01:09:31.147Z TASK Stopping 2024-02-04T01:09:31.147Z TASK StoppedReason:CannotPullContainerError: pull image manifest has been retried 1 time(s): failed to resolve ref docker.io/library/nginx:lates: docker.io/library/nginx:lates: not found 2024-02-04T01:09:31.147Z TASK StoppedCode:TaskFailedToStart imageΛpullͰ͖͍ͯͳ͍ͨΊ StoppedCode:TaskFailedToStart ͳͷ͕͙͔͢Δ