TECH PLAY

電通総研

電通総研 の技術ブログ

å…š843ä»¶

はじめに こんにちは。X むノベヌション 本郚の藀川です。 私は「aiuolaアむりォヌラ」ずいう ゚ンタヌプラむズ アプリケヌションプラットフォヌムの開発においお、プロダクトマネヌゞャヌをしおいたす。たれにアヌキテクト、 デベロッパ ヌなど別の垜子を被っお 開発プロセス に参加しおいたす。 今回の蚘事では、aiuolaが採甚しおいる アゞャむル 開発プロセス に぀いお私たちの珟圚の着地点をスプリントむベントを䞭心に玹介したす。 ちなみにaiuolaずは「 ゚ンタヌプラむズ アプリケヌションでお客様に感動を」ずいうキャッチフレヌズで立ち䞊げた開発プロゞェクトです。゚ンプラ系アプリっおなんかあれじゃん、結局倧したこずないでしょずいう眉唟100%の皆様、ご安心ください。 私たちの想いを䜓珟した ゚ンタヌプラむズ アプリケヌションは「Ci*Xサむクロス」ずいうブランドでリリヌスしおおりたす。 ご利甚䞭のお客様からは「マニュアルを参照せずに䜿える業務アプリっお初めお」「 経理 郚門に配属以来最も倧きな感動䜓隓です」ず評刀です。 䌚蚈プロダクトの怜蚎をされおいる方はぜひこちらをご芧ください。 グルヌプ経営管理゜リュヌション サむクロスシリヌズ aiuolaの取り組み aiuola ずは aiuolaは圓瀟の ゚ンタヌプラむズ アプリケヌションの共通プラットフォヌムです。 ゚ンタヌプラむズ アプリで求められる認蚌・認可やUIラむブラリを提䟛しおいたす。 2023幎珟圚、aiuolaを掻甚したいく぀かのプロダクト矀をリリヌスしご奜評をいただいおおりたす。 䜓制 aiuolaの開発䜓制は初期からの倉遷を経お、以䞋のような䜓制ずなっおいたす。 本チヌムではサヌビス運甚のミッションを持っおいないためむンフラチヌムは有しおいたせん。 各プロダクト偎にむンフラチヌムがいお、我々ず協力しおお客様のサクセスを支えおいたす 初期の頃はフロント゚ンゞニア4名、専任デザむナヌが1名ずいう䜓制でしたが、デザむンシステムが固たっおからは抂ね䞊蚘の䜓制で掻動しおいたす。 圓チヌムのバック゚ンド゚ンゞニアは単䞀の ナヌスケヌス 機胜の開発を担圓し、機胜単䜍のフロント実装も行いたす。 䞀方でフロント゚ンゞニアはUI コンポヌネント の開発やフロント゚ンド実装指針にフォヌカスを圓おお掻動しおいたす。 スプリントむベント aiuolaの開発は2週間のスプリントで実斜しおいたす。 スプリント期間の過ごし方をスプリントむベントを䞭心に図にしおみたした。 ご芧いただくずお分かりかず思いたすが、すごくオヌ゜ドックスな スクラム 開発プロセス を採甚しおいたす。 なお、2020幎以降、aiuolaの開発はリモヌトスタむルでの開発ずなっおいたす。 スプリントむベントを含めお、すべおの掻動をリモヌト環境で実斜しおいたす。飲み䌚以倖はね😉。 デむリヌミヌティング 䞻に前日タスクでの課題ずその日の掻動予定を共有したすが、slackで簡単なワヌクレポヌトを投皿するルヌルにしおいるので、困りごずぞの察応、レビュヌ担圓者ぞの アサむ ン、QAメンバヌぞのテスト䟝頌などが目的になりたす。 倧䜓、15分〜20分ぐらいの時間でその名の通り、毎日実斜しおいたす。 スプリントプランニング スプリントで実斜するタスクを バックログ から決定したす。 スプリントチヌムはQAチヌムを含めお4぀のサブチヌムが存圚するので、3段階のスプリントプランニングステヌゞを蚭けおいたす。 プレスプリントプランニング 各サブチヌムにお次スプリントタスクの遞定ずポヌカヌ サブリヌダヌによるスプリントプランニング サブチヌム間の䜜業すり合わせ 党員でのスプリントプランニング スプリントタスクの共有 埓来は3だけですべおを実斜しおいたのですが、チヌム䜓制が倧きくなるに぀れ、党員を拘束しおしたう時間が増えおしたいたした。 貎重な゚ンゞニアリング時間を十分に確保するこずを目的に3段階のフェヌズを蚭けるこずにしたした。 プロダクトリヌダヌ䌚 プロダクトファミリヌで玹介した通り、aiuolaを掻甚するプロダクトは耇数ありたす。 各プロダクトも日々開発を進めおいたす。プロダクト間で期埅する芁望、察応スケゞュヌルのすり合わせは重芁です。 プロダクトリヌダヌ䌚ではそのようなプロダクトをたたがった調敎を行いたす。 リリヌス内容発衚䌚 リリヌス内容発衚䌚ではスプリントにおいおリリヌスできる機胜をチヌム内で共有し、玹介し、功瞟を称える䌚ずなりたす。 私たちの開発察象は ゚ンタヌプラむズ アプリケヌションのため、単䞀の機胜が有するフィヌチャヌは比范的倧芏暡になりたす。そのためスプリントの䞭で1぀の機胜を完党に䜜り䞊げるこずができたせん。 リリヌス内容発衚䌚ではそのリリヌスに含めるこずができた機胜を察象ずしたす。 それ以倖にもQAチヌムから品質の取り組みに関する発衚も含たれるこずがありたす。 スプリントリリヌス スプリントリリヌスはミヌティングではなく、前スプリントの成果をリリヌスするタスクずなりたす。 aiuolaずしおのリリヌスはスプリントの成果物を各プロダクトチヌムに提䟛する䜜業です。 プロダクトファミリヌの垂堎投入サむクルはaioulaを含めおすべお6ヶ月単䜍ずなりたす。そのため、スプリントリリヌスは開発ベヌタ版ずしおプロダクトチヌムに成果物を提䟛するこずを指したす。 レトロスペクティブ レトロスペクティブはその名の通り、スプリントの最埌に行う振り返り䌚です。 開発の改善に圹立぀ア むデア や課題を議論し、スプリントの䞭で挑戊すべきこずを議論したす。 埓来はオフラむンで実斜しおいたしたが、オンラむン䞻䜓の 開発プロセス に倉わっおからはMiroを掻甚しおおりたす。 終わりに 今回の蚘事では私たちが開発しおいる ゚ンタヌプラむズ アプリケヌションプラットフォヌム「aiuola」の 開発プロセス に぀いお非垞に簡単ですがその䞀端をご玹介したした。 プロダクトファミリヌにお玹介したaiuolaプラットフォヌムを掻甚した各プロダクトも積極的な機胜匷化を行っおいたす。 それぞれのプロダクトはここで玹介したプロセスをコピヌしお適甚しおいるわけではなく、プロダクト特性やチヌム䜓制に応じた開発スタむルを採甚し、独自に発展を遂げおいたす。もちろん私たちaiuolaチヌムも珟状に満足しおいるわけではなく、より効果的な取り組みにチャレンゞしおいたす。 いずれのプロダクトでも、共に新たなチャレンゞに挑んでくれる仲間を探しおいたすので、ご興味を持っおいただいた方は是非ずも採甚ペヌゞをご芧ください。 たた、本チヌムの開発メンバヌがアプリケヌション アヌキテクチャ をテヌマずしおTech Playに登壇したす。 こちらも是非ご参加いただけるず幞いです。 Tech Play URL 私たちは䞀緒に働いおくれる仲間を募集しおいたす プロダクトプラットフォヌム開発゚ンゞニア/新芏プロダクト開発゚ンゞニア 次䞖代䌚蚈プロダクト開発ITアヌキテクトCi*Xシリヌズ 次䞖代䌚蚈プロダクトDevOps゚ンゞニアCi*Xシリヌズ 執筆 @fujikawa.kenji 、レビュヌ @wakamoto.ryosuke  Shodo で執筆されたした 
こんにちは。Xクロス むノベヌション 本郚 クラりド むノベヌション センタヌの柎田です。 本蚘事ではTerraformでコヌドを倉曎しおいないリ゜ヌスが known after apply ずなっおしたう堎合の回避策をご玹介したす。 前提 問題ずなるコヌドの䟋 原因 回避策 おわりに 参考 前提 この蚘事は以䞋のTerraformのバヌゞョンを前提ずしたす。 新しいバヌゞョンのTerraformでは本蚘事ず異なる挙動をする可胜性がありたす。 $ terraform version Terraform v1.5.3 on linux_amd64 + provider registry.terraform.io/hashicorp/aws v5.7.0 問題ずなるコヌドの䟋 以䞋のTerraformコヌドを䟋に考えおみたしょう。 resource "aws_s3_bucket" "sample" { bucket_prefix = "sample-" tags = { Project = "My Project A" } } data "aws_iam_policy_document" "sample" { statement { effect = "Allow" actions = [ "s3:*" ] resources = [ aws_s3_bucket.sample.arn ] } } resource "aws_iam_policy" "sample" { name = "SampleBucketFullAccess" path = "/" policy = data.aws_iam_policy_document.sample.json } このTerraformコヌドを terraform apply したす。 $ terraform apply Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create <= read (data resources) Terraform will perform the following actions: # data.aws_iam_policy_document.sample will be read during apply # (config refers to values not yet known) <= data "aws_iam_policy_document" "sample" { + id = (known after apply) + json = (known after apply) + statement { + actions = [ + "s3:*", ] + effect = "Allow" + resources = [ + (known after apply), ] } } # aws_iam_policy.sample will be created + resource "aws_iam_policy" "sample" { + arn = (known after apply) + id = (known after apply) + name = "SampleBucketFullAccess" + name_prefix = (known after apply) + path = "/" + policy = (known after apply) + policy_id = (known after apply) + tags_all = (known after apply) } # aws_s3_bucket.sample will be created + resource "aws_s3_bucket" "sample" { + acceleration_status = (known after apply) + acl = (known after apply) + arn = (known after apply) + bucket = (known after apply) + bucket_domain_name = (known after apply) + bucket_prefix = "sample-" + bucket_regional_domain_name = (known after apply) + force_destroy = false + hosted_zone_id = (known after apply) + id = (known after apply) + object_lock_enabled = (known after apply) + policy = (known after apply) + region = (known after apply) + request_payer = (known after apply) + tags = { + "Project" = "My Project A" } + tags_all = { + "Project" = "My Project A" } + website_domain = (known after apply) + website_endpoint = (known after apply) } Plan: 2 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes aws_s3_bucket.sample: Creating... aws_s3_bucket.sample: Creation complete after 1s [id=sample-20230713121614963200000001] data.aws_iam_policy_document.sample: Reading... data.aws_iam_policy_document.sample: Read complete after 0s [id=55239551] aws_iam_policy.sample: Creating... aws_iam_policy.sample: Creation complete after 1s [id=arn:aws:iam::************:policy/SampleBucketFullAccess] Apply complete! Resources: 2 added, 0 changed, 0 destroyed. 次にS3 バケット aws_s3_bucket.sample の Project タグの倀を倉曎したす。 resource "aws_s3_bucket" "sample" { bucket_prefix = "sample-" tags = { - Project = "My Project A" + Project = "My Project B" } } 倉曎埌のTerraformコヌドに察しお terraform plan を実行したす。 $ terraform plan aws_s3_bucket.sample: Refreshing state... [id=sample-20230713121614963200000001] aws_iam_policy.sample: Refreshing state... [id=arn:aws:iam::************:policy/SampleBucketFullAccess] Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: ~ update in-place <= read (data resources) Terraform will perform the following actions: # data.aws_iam_policy_document.sample will be read during apply # (depends on a resource or a module with changes pending) <= data "aws_iam_policy_document" "sample" { + id = (known after apply) + json = (known after apply) + statement { + actions = [ + "s3:*", ] + effect = "Allow" + resources = [ + "arn:aws:s3:::sample-20230713121614963200000001", ] } } # aws_iam_policy.sample will be updated in-place ~ resource "aws_iam_policy" "sample" { id = "arn:aws:iam::************:policy/SampleBucketFullAccess" name = "SampleBucketFullAccess" ~ policy = jsonencode( { - Statement = [ - { - Action = "s3:*" - Effect = "Allow" - Resource = "arn:aws:s3:::sample-20230713121614963200000001" }, ] - Version = "2012-10-17" } ) -> (known after apply) tags = {} # (4 unchanged attributes hidden) } # aws_s3_bucket.sample will be updated in-place ~ resource "aws_s3_bucket" "sample" { id = "sample-20230713121614963200000001" ~ tags = { ~ "Project" = "My Project A" -> "My Project B" } ~ tags_all = { ~ "Project" = "My Project A" -> "My Project B" } # (10 unchanged attributes hidden) # (3 unchanged blocks hidden) } Plan: 0 to add, 2 to change, 0 to destroy. するず、倉曎がないはずのIAM policy aws_iam_policy.sample の policy が known after apply ずなっおしたいたした。 原因 これはData Sourceの仕様によるものです。 Data Resource Dependencies には以䞋のように蚘述されおいたす。 Data resources have the same dependency resolution behavior as defined for managed resources . Setting the depends_on meta-argument within data blocks defers reading of the data source until after all changes to the dependencies have been applied. In order to ensure that data sources are accessing the most up to date information possible in a wide variety of use cases, arguments directly referencing managed resources are treated the same as if the resource was listed in depends_on . 芁玄するず以䞋のずおりです。 Data Sourceでは depends_on に蚘茉されたリ゜ヌスのすべおの倉曎が適甚されるたで読み取りは延期される。 Data Sourceの匕数が他のリ゜ヌスを盎接参照しおいる堎合、参照先のリ゜ヌスがData Sourceの depends_on に含たれおいる堎合ず同じように扱われる。 ぀たり Data Sourceが盎接参照しおいるリ゜ヌスに倉曎がある堎合、それらの倉曎が適甚されたあず、Data Sourceの読み取りが再実行される ずいうこずです。 改めお先ほどの䟋を考えおみたしょう。Terraformが以䞋のように刀断しおいたこずがわかりたす。 aws_s3_bucket.sample のコヌドの倉曎が怜出される。 data.aws_iam_policy_document.sample は aws_s3_bucket.sample を盎接参照しおいるため、 depends_on に aws_s3_bucket.sample が含たれおいる堎合ず同じように扱われる。 depends_on に含たれる aws_s3_bucket.sample の倉曎が怜出されたため、その倉曎が適甚されたあずで data.aws_iam_policy_document.sample の再読み取りを行う必芁があるず刀断される。 3をうけお aws_iam_policy.sample の policy が曎新されるず刀断される。 回避策 Data Resource Dependencies には以䞋のように蚘述されおいたす。 This behavior can be avoided when desired by indirectly referencing the managed resource values through a local value , unless the data resource itself has custom conditions . どうやら Local Value を間に挟むこずで先ほどの事象を回避できるようです。 詊しおみたしょう。先ほどのTerraformコヌドを以䞋のように倉曎したす。 provider "aws" { region = "ap-northeast-1" } resource "aws_s3_bucket" "sample" { bucket_prefix = "sample-" tags = { Project = "My Project B" } } locals { s3_bucket_arn = aws_s3_bucket.sample.arn } data "aws_iam_policy_document" "sample" { statement { effect = "Allow" actions = [ "s3:*" ] resources = [ local.s3_bucket_arn ] } } resource "aws_iam_policy" "sample" { name = "SampleBucketFullAccess" path = "/" policy = data.aws_iam_policy_document.sample.json } 倉曎埌のTerraformコヌドに察しお terraform plan を実行したす。 $ terraform plan aws_s3_bucket.sample: Refreshing state... [id=sample-20230713121614963200000001] data.aws_iam_policy_document.sample: Reading... data.aws_iam_policy_document.sample: Read complete after 0s [id=55239551] aws_iam_policy.sample: Refreshing state... [id=arn:aws:iam::************:policy/SampleBucketFullAccess] Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: ~ update in-place Terraform will perform the following actions: # aws_s3_bucket.sample will be updated in-place ~ resource "aws_s3_bucket" "sample" { id = "sample-20230713121614963200000001" ~ tags = { ~ "Project" = "My Project A" -> "My Project B" } ~ tags_all = { ~ "Project" = "My Project A" -> "My Project B" } # (10 unchanged attributes hidden) # (3 unchanged blocks hidden) } Plan: 0 to add, 1 to change, 0 to destroy. S3 バケット aws_s3_bucket.sample 以倖の倉曎が衚瀺されないこずを確認できたした。 おわりに 本蚘事ではTerraformでコヌドを倉曎しおいないリ゜ヌスが known after apply ずなっおしたう堎合の回避策をご玹介したした。 この蚘事がこの問題に悩んでいる方のお圹に立おば幞いです。 最埌たでお読みいただき、ありがずうございたした。 参考 Data Sources - Configuration Language | Terraform | HashiCorp Developer date source referencing managed resource proposes unnecessary changes under 0.14 · Issue #27171 · hashicorp/terraform 私たちは䞀緒に働いおくれる仲間を募集しおいたす クラりドアヌキテクト 執筆 @shibata.takao 、レビュヌ 寺山 茝 (@terayama.akira)  Shodo で執筆されたした 
こんにちは。Xクロス むノベヌション 本郚 クラりド むノベヌション センタヌの柎田です。 本蚘事ではTerraformでコヌドを倉曎しおいないリ゜ヌスが known after apply ずなっおしたう堎合の回避策をご玹介したす。 前提 問題ずなるコヌドの䟋 原因 回避策 おわりに 参考 前提 この蚘事は以䞋のTerraformのバヌゞョンを前提ずしたす。 新しいバヌゞョンのTerraformでは本蚘事ず異なる挙動をする可胜性がありたす。 $ terraform version Terraform v1.5.3 on linux_amd64 + provider registry.terraform.io/hashicorp/aws v5.7.0 問題ずなるコヌドの䟋 以䞋のTerraformコヌドを䟋に考えおみたしょう。 resource "aws_s3_bucket" "sample" { bucket_prefix = "sample-" tags = { Project = "My Project A" } } data "aws_iam_policy_document" "sample" { statement { effect = "Allow" actions = [ "s3:*" ] resources = [ aws_s3_bucket.sample.arn ] } } resource "aws_iam_policy" "sample" { name = "SampleBucketFullAccess" path = "/" policy = data.aws_iam_policy_document.sample.json } このTerraformコヌドを terraform apply したす。 $ terraform apply Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create <= read (data resources) Terraform will perform the following actions: # data.aws_iam_policy_document.sample will be read during apply # (config refers to values not yet known) <= data "aws_iam_policy_document" "sample" { + id = (known after apply) + json = (known after apply) + statement { + actions = [ + "s3:*", ] + effect = "Allow" + resources = [ + (known after apply), ] } } # aws_iam_policy.sample will be created + resource "aws_iam_policy" "sample" { + arn = (known after apply) + id = (known after apply) + name = "SampleBucketFullAccess" + name_prefix = (known after apply) + path = "/" + policy = (known after apply) + policy_id = (known after apply) + tags_all = (known after apply) } # aws_s3_bucket.sample will be created + resource "aws_s3_bucket" "sample" { + acceleration_status = (known after apply) + acl = (known after apply) + arn = (known after apply) + bucket = (known after apply) + bucket_domain_name = (known after apply) + bucket_prefix = "sample-" + bucket_regional_domain_name = (known after apply) + force_destroy = false + hosted_zone_id = (known after apply) + id = (known after apply) + object_lock_enabled = (known after apply) + policy = (known after apply) + region = (known after apply) + request_payer = (known after apply) + tags = { + "Project" = "My Project A" } + tags_all = { + "Project" = "My Project A" } + website_domain = (known after apply) + website_endpoint = (known after apply) } Plan: 2 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes aws_s3_bucket.sample: Creating... aws_s3_bucket.sample: Creation complete after 1s [id=sample-20230713121614963200000001] data.aws_iam_policy_document.sample: Reading... data.aws_iam_policy_document.sample: Read complete after 0s [id=55239551] aws_iam_policy.sample: Creating... aws_iam_policy.sample: Creation complete after 1s [id=arn:aws:iam::************:policy/SampleBucketFullAccess] Apply complete! Resources: 2 added, 0 changed, 0 destroyed. 次にS3 バケット aws_s3_bucket.sample の Project タグの倀を倉曎したす。 resource "aws_s3_bucket" "sample" { bucket_prefix = "sample-" tags = { - Project = "My Project A" + Project = "My Project B" } } 倉曎埌のTerraformコヌドに察しお terraform plan を実行したす。 $ terraform plan aws_s3_bucket.sample: Refreshing state... [id=sample-20230713121614963200000001] aws_iam_policy.sample: Refreshing state... [id=arn:aws:iam::************:policy/SampleBucketFullAccess] Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: ~ update in-place <= read (data resources) Terraform will perform the following actions: # data.aws_iam_policy_document.sample will be read during apply # (depends on a resource or a module with changes pending) <= data "aws_iam_policy_document" "sample" { + id = (known after apply) + json = (known after apply) + statement { + actions = [ + "s3:*", ] + effect = "Allow" + resources = [ + "arn:aws:s3:::sample-20230713121614963200000001", ] } } # aws_iam_policy.sample will be updated in-place ~ resource "aws_iam_policy" "sample" { id = "arn:aws:iam::************:policy/SampleBucketFullAccess" name = "SampleBucketFullAccess" ~ policy = jsonencode( { - Statement = [ - { - Action = "s3:*" - Effect = "Allow" - Resource = "arn:aws:s3:::sample-20230713121614963200000001" }, ] - Version = "2012-10-17" } ) -> (known after apply) tags = {} # (4 unchanged attributes hidden) } # aws_s3_bucket.sample will be updated in-place ~ resource "aws_s3_bucket" "sample" { id = "sample-20230713121614963200000001" ~ tags = { ~ "Project" = "My Project A" -> "My Project B" } ~ tags_all = { ~ "Project" = "My Project A" -> "My Project B" } # (10 unchanged attributes hidden) # (3 unchanged blocks hidden) } Plan: 0 to add, 2 to change, 0 to destroy. するず、倉曎がないはずのIAM policy aws_iam_policy.sample の policy が known after apply ずなっおしたいたした。 原因 これはData Sourceの仕様によるものです。 Data Resource Dependencies には以䞋のように蚘述されおいたす。 Data resources have the same dependency resolution behavior as defined for managed resources . Setting the depends_on meta-argument within data blocks defers reading of the data source until after all changes to the dependencies have been applied. In order to ensure that data sources are accessing the most up to date information possible in a wide variety of use cases, arguments directly referencing managed resources are treated the same as if the resource was listed in depends_on . 芁玄するず以䞋のずおりです。 Data Sourceでは depends_on に蚘茉されたリ゜ヌスのすべおの倉曎が適甚されるたで読み取りは延期される。 Data Sourceの匕数が他のリ゜ヌスを盎接参照しおいる堎合、参照先のリ゜ヌスがData Sourceの depends_on に含たれおいる堎合ず同じように扱われる。 ぀たり Data Sourceが盎接参照しおいるリ゜ヌスに倉曎がある堎合、それらの倉曎が適甚されたあず、Data Sourceの読み取りが再実行される ずいうこずです。 改めお先ほどの䟋を考えおみたしょう。Terraformが以䞋のように刀断しおいたこずがわかりたす。 aws_s3_bucket.sample のコヌドの倉曎が怜出される。 data.aws_iam_policy_document.sample は aws_s3_bucket.sample を盎接参照しおいるため、 depends_on に aws_s3_bucket.sample が含たれおいる堎合ず同じように扱われる。 depends_on に含たれる aws_s3_bucket.sample の倉曎が怜出されたため、その倉曎が適甚されたあずで data.aws_iam_policy_document.sample の再読み取りを行う必芁があるず刀断される。 3をうけお aws_iam_policy.sample の policy が曎新されるず刀断される。 回避策 Data Resource Dependencies には以䞋のように蚘述されおいたす。 This behavior can be avoided when desired by indirectly referencing the managed resource values through a local value , unless the data resource itself has custom conditions . どうやら Local Value を間に挟むこずで先ほどの事象を回避できるようです。 詊しおみたしょう。先ほどのTerraformコヌドを以䞋のように倉曎したす。 provider "aws" { region = "ap-northeast-1" } resource "aws_s3_bucket" "sample" { bucket_prefix = "sample-" tags = { Project = "My Project B" } } locals { s3_bucket_arn = aws_s3_bucket.sample.arn } data "aws_iam_policy_document" "sample" { statement { effect = "Allow" actions = [ "s3:*" ] resources = [ local.s3_bucket_arn ] } } resource "aws_iam_policy" "sample" { name = "SampleBucketFullAccess" path = "/" policy = data.aws_iam_policy_document.sample.json } 倉曎埌のTerraformコヌドに察しお terraform plan を実行したす。 $ terraform plan aws_s3_bucket.sample: Refreshing state... [id=sample-20230713121614963200000001] data.aws_iam_policy_document.sample: Reading... data.aws_iam_policy_document.sample: Read complete after 0s [id=55239551] aws_iam_policy.sample: Refreshing state... [id=arn:aws:iam::************:policy/SampleBucketFullAccess] Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: ~ update in-place Terraform will perform the following actions: # aws_s3_bucket.sample will be updated in-place ~ resource "aws_s3_bucket" "sample" { id = "sample-20230713121614963200000001" ~ tags = { ~ "Project" = "My Project A" -> "My Project B" } ~ tags_all = { ~ "Project" = "My Project A" -> "My Project B" } # (10 unchanged attributes hidden) # (3 unchanged blocks hidden) } Plan: 0 to add, 1 to change, 0 to destroy. S3 バケット aws_s3_bucket.sample 以倖の倉曎が衚瀺されないこずを確認できたした。 おわりに 本蚘事ではTerraformでコヌドを倉曎しおいないリ゜ヌスが known after apply ずなっおしたう堎合の回避策をご玹介したした。 この蚘事がこの問題に悩んでいる方のお圹に立おば幞いです。 最埌たでお読みいただき、ありがずうございたした。 参考 Data Sources - Configuration Language | Terraform | HashiCorp Developer date source referencing managed resource proposes unnecessary changes under 0.14 · Issue #27171 · hashicorp/terraform 私たちは䞀緒に働いおくれる仲間を募集しおいたす クラりドアヌキテクト 執筆 @shibata.takao 、レビュヌ 寺山 茝 (@terayama.akira)  Shodo で執筆されたした 
こんにちは、Xクロス むノベヌション 本郚 クラりド むノベヌション センタヌの田村です。 2023 幎 5 月の Microsoft Build にお統合分析プラットフォヌム Microsoft Fabric が発衚されたした。 Microsoft Fabric は珟圚プレビュヌ䞭ですが、既存のサヌビスにはない機胜远加や倚くのアップデヌトが予定されおおり、 Microsoft のデヌタ領域ビゞネスにおいお今埌泚目すべきサヌビスです。 本蚘事では、 Microsoft Fabric の抂芁ずサヌビス怜蚌ずしお実斜した勀怠デヌタ分析の内容をご玹介したす。 Microsoft Fabric の抂芁 One Lake Synapse Data Engineering Data Factory Power BI サヌビス怜蚌勀怠デヌタの分析 抂芁 怜蚌シナリオ勀怠デヌタ分析 怜蚌アヌキテクチャ Microsoft Fabric サブスクリプションの賌入 Microsoft Fabric ワヌクスペヌスの䜜成 レむクハりスの䜜成 勀怠デヌタの栌玍 ノヌトブックによるデヌタの敎圢 デヌタフロヌによるデヌタの倉換・加工 SQL ゚ンドポむントによる分析 Power BI レポヌトの䜜成 サヌビス怜蚌結果 䞀気通貫のデヌタ分析 デヌタ分析の経隓が浅いナヌザヌぞのサポヌト 各機胜の操䜜感 たずめ Microsoft Fabric の抂芁 Microsoft Fabric は、デヌタ分析に必芁な芁玠を 1 ぀の統合環境で提䟛する SaaS 圢匏の゜リュヌションです。 埓来 Microsoft の クラりド サヌビスでデヌタ分析をする堎合は、Azure Data Factory や Azure Synapse Analytics ずいった PaaS を組み合わせた アヌキテクチャ を蚭蚈する手法が䞀般的でした。 Microsoft Fabric では、デヌタの蓄積/加工/倉換/分析/可芖化を単䞀の基盀䞊で実珟できるため、ナヌザヌは統䞀された UI 䞊でシヌムレスな分析を実斜できるず謳われおいたす。 これにより、ナヌザヌは 1 ぀のサヌビス内でデヌタ分析やデヌタ管理に関する䜜業をすべお完結でき、分析リ゜ヌスのサむゞングずいった管理負担の軜枛が期埅できたす。 Microsoft Fabric の䞻芁な構成芁玠に぀いお述べたす。 蚘事のボリュヌムを考慮し、今回は技術怜蚌にお扱った芁玠に぀いお簡朔に説明したすので、他にも興味がある方は こちら のリンクをご参照ください。 出兞 Microsoft Fabric ずは One Lake Microsoft Fabric の環境に 1 ぀䜜成される SaaS 圢匏のデヌタレむクです。 Microsoft Fabric の各機胜で利甚されるデヌタを䞀元的に管理する基盀であり、ショヌトカットず呌ばれる機胜を利甚するずさたざたなサヌビスから手軜にデヌタを移動できたす。 珟時点では Microsoft Fabric 内郚/ Amazon S3 /Azure Data Lake Storage ずの連携が実装されおおり、今埌も拡倧されおいくず思われたす。 OneLake のショヌトカット Synapse Data Engineering レむクハりスず呌ばれる構造化/非構造化デヌタを管理・分析できるデヌタストアに栌玍されたデヌタに察する凊理を行う機胜です。 具䜓的には Apache Spark クラスタ による分析やノヌトブックによる察話的な分析 Python /R/ Scala 、デヌタパむプラむンによるデヌタの移動/倉換/結合等が実斜できたす。 Microsoft Fabric のデヌタ ゚ンゞニアリングずは Data Factory 既存のデヌタ統合サヌビスである Azure Data Factory ず、 Excel や Power BI 等に搭茉されおいる Power Query を組み合わせたデヌタ統合機胜です。 さたざたなデヌタ゜ヌスからデヌタを取り蟌み、柔軟な凊理が可胜です。 Microsoft Fabric の Data Factory ずは Power BI Microsoft Power Platform にお提䟛されおいる BI ツヌルです。 Microsoft Fabric に可芖化 コンポヌネント ずしお統合されおいたす。 Power BI ずは サヌビス怜蚌勀怠デヌタの分析 抂芁 7 月䞊旬あたりで Microsoft Fabric のキャッチアップず チュヌトリアル の実斜がある皋床進んだので、手持ちのデヌタを䜿甚しお Microsoft Fabric での分析に着手したした。 分析䜜業を通じお、䞋蚘の項目に぀いお怜蚌するこずを目的ずしたす。 Microsoft Fabric のみでデヌタ分析を 䞀気通貫 で実斜できるか デヌタ分析の経隓があたりないナヌザヌをサポヌトする機胜が珟時点でどの皋床実装されおいるか Microsoft Fabric の操䜜感Power BI や Data Factory など統合されたサヌビスがこれたで通り利甚できるか 怜蚌シナリオ勀怠デヌタ分析 ISID では日々の勀怠入力を自瀟゜リュヌションである POSITIVE で実斜しおいたす。 POSITIVE - 人事絊䞎、勀怠システム ISID 瀟内で利甚しおいる POSITIVE では、入力した勀怠情報を Excel 圢匏でダりンロヌドできたす。 そこで、自分の勀怠デヌタが蚘録された Excel ファむルを Microsoft Fabric で分析し、可芖化たでの工皋を 䞀気通貫 で怜蚌しおみるこずにしたした。 怜蚌 アヌキテクチャ アヌキテクチャ ず怜蚌手順は䞋蚘の通りです。 Microsoft Fabric サブスクリプション を賌入する Microsoft Fabric ワヌクスペヌス を䜜成する Synapse Data Engineering におデヌタストアずなるレむクハりスを䜜成する ロヌカルから Excel 圢匏の勀怠デヌタをレむクハりスぞ栌玍する ノヌトブック を䜜成し、 Excel 圢匏の勀怠デヌタを敎圢しお再床レむクハりスぞ栌玍する 敎圢された勀怠デヌタをデヌタフロヌにお倉換・加工し、再床レむクハりスぞ栌玍する レむクハりスから SQL ゚ンドポむントを䜜成し分析を実斜する 倉換埌のデヌタおよび分析結果を Power BI にお可芖化する Microsoft Fabric サブスクリプション の賌入 Microsoft 365 もしくは Azure 䞊から賌入できたす。 今回は Azure 䞊から賌入したした。 手順は簡単か぀ドキュメントの内容をなぞるだけですので、本蚘事では割愛したす。 Microsoft Fabric サブスクリプションを賌入する Microsoft Fabric ワヌクスペヌス の䜜成 ワヌクスペヌス ずは、 Microsoft Fabric で䜜成したさたざたなコレクションレむクハりス、デヌタフロヌ、BI レポヌト etc...をたずめお管理するものです。 Microsoft Fabric で䜜業を開始する際には、内容を問わずはじめに実斜する工皋ずなりたす。 手順ずしおは ワヌクスペヌス 名を入力しお保存するだけですので、こちらに぀いおも詳现は割愛したす。 厳密には ワヌクスペヌス に察する暩限蚭定などもありたすが、今回は怜蚌甚 ワヌクスペヌス のため実斜しおいたせん。 ワヌクスペヌスの䜜成 レむクハりスの䜜成 レむクハりスは、倧容量のデヌタを蓄積するデヌタレむクずデヌタの取り蟌みや分析に特化したデヌタりェアハりスを統合したものです。 䞀般的に構造化/半構造化/非構造化デヌタを 1 箇所で管理・分析するこずが可胜で、 Microsoft Fabric では倚様なデヌタ゜ヌスからのデヌタ栌玍ずデヌタに察するさたざたな倉換・統合凊理や SQL や Spark ゚ンゞンを利甚した分析をサポヌトしおいたす。 たた Microsoft Fabric におけるレむクハりスの特城ずしお、栌玍されたデヌタを自動で怜出し、分析に適した圢匏でテヌブルずしお登録する機胜も甚意されおいたす。 䜜成自䜓は非垞に簡単で、 Microsoft Fabric ワヌクスペヌス の+ 新芏よりレむクハりスを遞択し任意の名前を蚭定しお完了です。 勀怠デヌタの栌玍 怜蚌に必芁なデヌタを䜜成したレむクハりスぞ栌玍したす。 察象ずなるのは、私の 2023 幎 6 月分の勀怠実瞟を蚘録した Excel デヌタファむル名Attendance_202306.xlsxです。 䜜成盎埌のレむクハりスには 構造化デヌタが管理される Tables ずデヌタレむクのようにさたざたな゜ヌスから連携された生デヌタが管理される Files ずいうセクションが甚意されおいたす。 デヌタ栌玍をする際はデヌタフロヌやパむプラむンを利甚する方法や、One Lake のショヌトカット機胜などさたざたな遞択肢がありたすが、今回はシンプルに手動でアップロヌドしたした。 アップロヌドが完了するず デヌタ圢匏 によっおはプレビュヌ衚瀺が可胜ですが、2023 幎 7 月時点で Excel デヌタはサポヌト倖のようです。 ノヌトブックによるデヌタの敎圢 生デヌタの時点である皋床構造化されおいればよいのですが、怜蚌で扱う勀怠デヌタは分析甚にフォヌマットされたものではないため、 倉換や統合凊理の前にデヌタを敎圢する必芁がありたす。 そこで、今回は Spark ゚ンゞンが接続されたノヌトブックによるデヌタの敎圢を実斜したした。 ほかの遞択肢ずしおデヌタフロヌPower Queryも怜蚎したしたが、そちらはこの埌の䜜業であるデヌタの倉換・加工凊理で利甚しおいたす。 ノヌトブックはレむクハりス UI のノヌトブックを開くより䜜成できたす。 ノヌトブックの䜜成ず同時に Spark ゚ンゞンも甚意されるため、ナヌザヌは蚀語を遞択しお凊理を蚘述しおいくだけです。 私は Python を遞択したしたが、その他に Scala / C# /R/Spark SQL がサポヌトされおいたす。 デヌタ敎圢の内容ずしおは、 Excel 圢匏の勀怠デヌタをより必芁なデヌタを抜出し、 Python のデヌタフレヌムを利甚しおデヌタを再配眮しおいたす。 抜出したデヌタは䞋蚘の通りです。 日付 勀務区分出勀/法定䌑日/有絊など 勀務圢態出瀟/テレワヌク/顧客先など 勀務開始時間 勀務終了時間 勀務時間 䌑憩時間 たた、敎圢埌のデヌタはレむクハりス内でプレビュヌ衚瀺させたかったので、 CSV 圢匏のファむルずしお Files セクションに栌玍しおいたす。 敎圢埌のデヌタは䞋蚘の通りですファむル名Attendance. csv 。 デヌタフロヌによるデヌタの倉換・加工 敎圢したデヌタに察しお、倉換・加工凊理を実斜し分析の準備を行いたす。 前述したノヌトブックでたずめお実斜しおもよかったのですが、他の機胜も觊っおみたいずいう思いでデヌタフロヌによる䜜業ずしたした。 デヌタフロヌは Microsoft Fabric の UI より Data Factory を遞択し、[Dataflow Gen2プレビュヌ]より䜜成できたす。 䜜成埌はレむクハりスに栌玍されおいる敎圢埌の勀怠デヌタAttendance. csv を読み蟌み、必芁な凊理を実斜したす。 今回実斜した䞻な凊理内容は䞋蚘の通りです。 勀務開始/終了時間のデヌタ型を文字列型ぞ倉曎する 定時を衚珟する列を远加する 勀務時間ず定時を蚈算し、残業時間を衚珟する列を远加する 勀務区分に䌑日出勀が含たれる堎合は、勀務時間を残業時間ずしお远加する 実際のデヌタフロヌ画面は䞋画像のようになりたす。 ノヌトブックず異なり、コヌドPower Queryを蚘述できなくずも GUI 䞊の操䜜で基本的なデヌタの倉換・加工が可胜です。 もちろん、必芁に応じお盎接 Power Query を曞くこずもできたす。 たた、凊理のサマリがダむアグラムビュヌ画像内の青枠郚分に蚘録され凊理結果は画像䞋郚にプレビュヌされるので、凊理に察する結果を即時把握できたす。 デヌタ倉換が完了したら、画像右䞋のデヌタの同期先よりレむクハりスぞの同期蚭定を行うこずで、分析甚に最適化された圢匏で Tables セクションぞ栌玍されたす。 たた、その際の スキヌマ 定矩やデヌタ構造の䜜成などはすべお自動で実斜されたす。 デヌタフロヌからレむクハりスぞの同期が完了するず、Tables セクションでテヌブルの内容をプレビュヌできたす。 今回は倉換埌のデヌタであるこずを明瀺するために、attendance_transform ずいうテヌブル名ずしたした。 SQL ゚ンドポむントによる分析 デヌタフロヌから同期されたテヌブルに察しお分析を実斜したす。 SQL ゚ンドポむントず呌ばれる機胜を利甚するこずで、レむクハりス内のテヌブルに察する SQL ク゚リ発行やリレヌションシップの構成が可胜です。 レむクハりスの UI より、 SQL ゚ンドポむントぞ遷移したす。 SQL ゚ンドポむントでは 3 ぀のペむンが甚意されおおり、それぞれ䞋蚘の䜜業が可胜です。 デヌタ スキヌマ 定矩に含たれるテヌ ブルデヌ タの確認や SQL ク゚リの管理 ク゚リ T-SQL ク゚リの発行 モデルテヌブル間のリレヌションシップ構成や Power BI におけるメゞャヌの蚭定が可胜 今回はク゚リずモデルのペむンにお、それぞれ分析䜜業を実斜したした。 䞻な分析内容は䞋蚘の通りです。 SQL ク゚リを利甚した分析 勀務時間、残業時間、勀務区分、勀務圢態の集蚈 勀務圢態における勀務状況の傟向分析 1 か月間における勀務状況の傟向分析 モデル 勀務日における出瀟/テレワヌクの割合を算出 今回は 1 か月分の勀怠デヌタのみであったためそこたで耇雑な分析ではありたせんが、関連デヌタの远加やデヌタ期間を拡倧するこずでさらに充実した分析が可胜です。 Power BI レポヌトの䜜成 最終工皋ずしお、分析結果を Power BI で可芖化したす。 SQL ゚ンドポむント UI の新しいレポヌトより、Power BI レポヌトの䜜成画面ぞ遷移したす。 分析結果を反映した Power BI レポヌトは䞋画像の通りです。 レポヌト内の各ビゞュアルで分析結果を可芖化しおいたす。 勀務時間ず残業時間および勀務日に察するテレワヌクの割合をカヌド䞊にテキスト圢匏で衚瀺 1 か月間における勀務時間の掚移ず定時に察する残業時間の掚移を棒グラフで衚瀺 勀務時間が長い日や期間を衚圢匏で衚瀺 勀務圢態出瀟 or テレワヌクの違いで平均勀務時間にどのような圱響があるか散垃図で衚瀺 サヌビス怜蚌結果 勀怠デヌタの分析シナリオを通じた Microsoft Fabric の怜蚌結果をたずめたす。 怜蚌項目は䞋蚘の通りです再掲。 Microsoft Fabric のみでデヌタ分析を 䞀気通貫 で実斜できるか デヌタ分析の経隓があたりないナヌザヌをサポヌトする機胜が珟時点でどの皋床実装されおいるか Microsoft Fabric の操䜜感Power BI や Data Factory など統合されたサヌビスがこれたで通り利甚できるか その他利甚時の泚意点 䞀気通貫 のデヌタ分析 デヌタの栌玍から可芖化たですべお Microsoft Fabric で完結できたした。 埓来のように分析ごずに甚途に応じお PaaS を組み合わせたり、むンフラを確保する必芁がなく、統䞀された UI の元で䜜業ができるこずはメリットであるず蚀えたす。 今回はロヌカルデヌタを䞭心ずした分析シナリオでしたが、 機械孊習 やリアルタむム分析など幅広いシナリオに察応できるサヌビスであるずいう印象です。 䞀方で、分析シナリオによっおは䞍芁な機胜や コンポヌネント があるこずも事実です。 Microsoft Fabric の利甚が最適ずなる分析シナリオは䜕か、ずいう点に぀いおは、金銭面や孊習コストの芳点も含めお今埌のアップデヌトを远っおいく必芁がありたす。 デヌタ分析の経隓が浅いナヌザヌぞのサポヌト 今回の怜蚌で觊れた機胜の䞭では、デヌタフロヌの GUI によるデヌタ倉換凊理は比范的ナヌザヌに易しい蚭蚈ずいう印象を受けたした。 ですが、それ以倖の郚分に぀いおは継続的な匷化が必芁ず感じおいたす。 Microsoft Fabric は「誰もがデヌタを管理および分析しおアクションに぀ながる むンサむト を埗られる」ずいうコンセプトを掲げおいたすが、珟状の機胜構成はデヌタ倉換や加工・分析等の凊理蚭蚈をナヌザヌの知識に䟝存しおいたす。 Microsoft Fabric - デヌタ分析 今回の怜蚌においおは、ノヌトブックを利甚したデヌタの前凊理や SQL ゚ンドポむントによる分析で必芁ずなるコヌドやク゚リの䜜成は、未経隓のナヌザヌには難易床が高い䜜業です。 誰もがデヌタを管理および分析するためにはこのような䜜業に察するサポヌト機胜が必芁で、具䜓的には䞋蚘のような内容を期埅したす。 Copilot 機胜による各皮コヌドやク゚リの自動生成 One Lake のショヌトカット機胜匷化連携先の拡匵など ドキュメントや チュヌトリアル の充実 Microsoft によるず、Azure OpenAI ず連携した Copilot 機胜が近日公開予定ずなっおおりたすので、そちらを泚芖したいず思いたす。 各機胜の操䜜感 䞻芳になりたすが、既存の PaaS や SaaS から統合された機胜に぀いおは違和感なく操䜜できたした。 ノヌトブックによる察話圢匏でのデヌタ操䜜やデヌタフロヌ呚蟺の操䜜は、UI 自䜓が統合元の Microsoft 補品ず倧きく倉わらないため、それらの経隓がある方であれば抵抗なく利甚できるかず思いたす。 たずめ 本蚘事では、 Microsoft Fabric の抂芁ずサヌビス怜蚌ずしお実斜した勀怠デヌタ分析の内容に぀いおご玹介したした。 Microsoft Fabric は発衚されお間もない゜リュヌションであり、ロヌドマップでは今埌も倚くのアップデヌトが予定されおおりたすので、匕き続き泚芖したいず思いたす。 私たちは䞀緒に働いおくれる仲間を募集しおいたす クラりドアヌキテクト 執筆 @tamura.kohei 、レビュヌ @yamada.y  Shodo で執筆されたした 
こんにちは、Xクロス むノベヌション 本郚 クラりド むノベヌション センタヌの田村です。 2023 幎 5 月の Microsoft Build にお統合分析プラットフォヌム Microsoft Fabric が発衚されたした。 Microsoft Fabric は珟圚プレビュヌ䞭ですが、既存のサヌビスにはない機胜远加や倚くのアップデヌトが予定されおおり、 Microsoft のデヌタ領域ビゞネスにおいお今埌泚目すべきサヌビスです。 本蚘事では、 Microsoft Fabric の抂芁ずサヌビス怜蚌ずしお実斜した勀怠デヌタ分析の内容をご玹介したす。 Microsoft Fabric の抂芁 One Lake Synapse Data Engineering Data Factory Power BI サヌビス怜蚌勀怠デヌタの分析 抂芁 怜蚌シナリオ勀怠デヌタ分析 怜蚌アヌキテクチャ Microsoft Fabric サブスクリプションの賌入 Microsoft Fabric ワヌクスペヌスの䜜成 レむクハりスの䜜成 勀怠デヌタの栌玍 ノヌトブックによるデヌタの敎圢 デヌタフロヌによるデヌタの倉換・加工 SQL ゚ンドポむントによる分析 Power BI レポヌトの䜜成 サヌビス怜蚌結果 䞀気通貫のデヌタ分析 デヌタ分析の経隓が浅いナヌザヌぞのサポヌト 各機胜の操䜜感 たずめ Microsoft Fabric の抂芁 Microsoft Fabric は、デヌタ分析に必芁な芁玠を 1 ぀の統合環境で提䟛する SaaS 圢匏の゜リュヌションです。 埓来 Microsoft の クラりド サヌビスでデヌタ分析をする堎合は、Azure Data Factory や Azure Synapse Analytics ずいった PaaS を組み合わせた アヌキテクチャ を蚭蚈する手法が䞀般的でした。 Microsoft Fabric では、デヌタの蓄積/加工/倉換/分析/可芖化を単䞀の基盀䞊で実珟できるため、ナヌザヌは統䞀された UI 䞊でシヌムレスな分析を実斜できるず謳われおいたす。 これにより、ナヌザヌは 1 ぀のサヌビス内でデヌタ分析やデヌタ管理に関する䜜業をすべお完結でき、分析リ゜ヌスのサむゞングずいった管理負担の軜枛が期埅できたす。 Microsoft Fabric の䞻芁な構成芁玠に぀いお述べたす。 蚘事のボリュヌムを考慮し、今回は技術怜蚌にお扱った芁玠に぀いお簡朔に説明したすので、他にも興味がある方は こちら のリンクをご参照ください。 出兞 Microsoft Fabric ずは One Lake Microsoft Fabric の環境に 1 ぀䜜成される SaaS 圢匏のデヌタレむクです。 Microsoft Fabric の各機胜で利甚されるデヌタを䞀元的に管理する基盀であり、ショヌトカットず呌ばれる機胜を利甚するずさたざたなサヌビスから手軜にデヌタを移動できたす。 珟時点では Microsoft Fabric 内郚/ Amazon S3 /Azure Data Lake Storage ずの連携が実装されおおり、今埌も拡倧されおいくず思われたす。 OneLake のショヌトカット Synapse Data Engineering レむクハりスず呌ばれる構造化/非構造化デヌタを管理・分析できるデヌタストアに栌玍されたデヌタに察する凊理を行う機胜です。 具䜓的には Apache Spark クラスタ による分析やノヌトブックによる察話的な分析 Python /R/ Scala 、デヌタパむプラむンによるデヌタの移動/倉換/結合等が実斜できたす。 Microsoft Fabric のデヌタ ゚ンゞニアリングずは Data Factory 既存のデヌタ統合サヌビスである Azure Data Factory ず、 Excel や Power BI 等に搭茉されおいる Power Query を組み合わせたデヌタ統合機胜です。 さたざたなデヌタ゜ヌスからデヌタを取り蟌み、柔軟な凊理が可胜です。 Microsoft Fabric の Data Factory ずは Power BI Microsoft Power Platform にお提䟛されおいる BI ツヌルです。 Microsoft Fabric に可芖化 コンポヌネント ずしお統合されおいたす。 Power BI ずは サヌビス怜蚌勀怠デヌタの分析 抂芁 7 月䞊旬あたりで Microsoft Fabric のキャッチアップず チュヌトリアル の実斜がある皋床進んだので、手持ちのデヌタを䜿甚しお Microsoft Fabric での分析に着手したした。 分析䜜業を通じお、䞋蚘の項目に぀いお怜蚌するこずを目的ずしたす。 Microsoft Fabric のみでデヌタ分析を 䞀気通貫 で実斜できるか デヌタ分析の経隓があたりないナヌザヌをサポヌトする機胜が珟時点でどの皋床実装されおいるか Microsoft Fabric の操䜜感Power BI や Data Factory など統合されたサヌビスがこれたで通り利甚できるか 怜蚌シナリオ勀怠デヌタ分析 ISID では日々の勀怠入力を自瀟゜リュヌションである POSITIVE で実斜しおいたす。 POSITIVE - 人事絊䞎、勀怠システム ISID 瀟内で利甚しおいる POSITIVE では、入力した勀怠情報を Excel 圢匏でダりンロヌドできたす。 そこで、自分の勀怠デヌタが蚘録された Excel ファむルを Microsoft Fabric で分析し、可芖化たでの工皋を 䞀気通貫 で怜蚌しおみるこずにしたした。 怜蚌 アヌキテクチャ アヌキテクチャ ず怜蚌手順は䞋蚘の通りです。 Microsoft Fabric サブスクリプション を賌入する Microsoft Fabric ワヌクスペヌス を䜜成する Synapse Data Engineering におデヌタストアずなるレむクハりスを䜜成する ロヌカルから Excel 圢匏の勀怠デヌタをレむクハりスぞ栌玍する ノヌトブック を䜜成し、 Excel 圢匏の勀怠デヌタを敎圢しお再床レむクハりスぞ栌玍する 敎圢された勀怠デヌタをデヌタフロヌにお倉換・加工し、再床レむクハりスぞ栌玍する レむクハりスから SQL ゚ンドポむントを䜜成し分析を実斜する 倉換埌のデヌタおよび分析結果を Power BI にお可芖化する Microsoft Fabric サブスクリプション の賌入 Microsoft 365 もしくは Azure 䞊から賌入できたす。 今回は Azure 䞊から賌入したした。 手順は簡単か぀ドキュメントの内容をなぞるだけですので、本蚘事では割愛したす。 Microsoft Fabric サブスクリプションを賌入する Microsoft Fabric ワヌクスペヌス の䜜成 ワヌクスペヌス ずは、 Microsoft Fabric で䜜成したさたざたなコレクションレむクハりス、デヌタフロヌ、BI レポヌト etc...をたずめお管理するものです。 Microsoft Fabric で䜜業を開始する際には、内容を問わずはじめに実斜する工皋ずなりたす。 手順ずしおは ワヌクスペヌス 名を入力しお保存するだけですので、こちらに぀いおも詳现は割愛したす。 厳密には ワヌクスペヌス に察する暩限蚭定などもありたすが、今回は怜蚌甚 ワヌクスペヌス のため実斜しおいたせん。 ワヌクスペヌスの䜜成 レむクハりスの䜜成 レむクハりスは、倧容量のデヌタを蓄積するデヌタレむクずデヌタの取り蟌みや分析に特化したデヌタりェアハりスを統合したものです。 䞀般的に構造化/半構造化/非構造化デヌタを 1 箇所で管理・分析するこずが可胜で、 Microsoft Fabric では倚様なデヌタ゜ヌスからのデヌタ栌玍ずデヌタに察するさたざたな倉換・統合凊理や SQL や Spark ゚ンゞンを利甚した分析をサポヌトしおいたす。 たた Microsoft Fabric におけるレむクハりスの特城ずしお、栌玍されたデヌタを自動で怜出し、分析に適した圢匏でテヌブルずしお登録する機胜も甚意されおいたす。 䜜成自䜓は非垞に簡単で、 Microsoft Fabric ワヌクスペヌス の+ 新芏よりレむクハりスを遞択し任意の名前を蚭定しお完了です。 勀怠デヌタの栌玍 怜蚌に必芁なデヌタを䜜成したレむクハりスぞ栌玍したす。 察象ずなるのは、私の 2023 幎 6 月分の勀怠実瞟を蚘録した Excel デヌタファむル名Attendance_202306.xlsxです。 䜜成盎埌のレむクハりスには 構造化デヌタが管理される Tables ずデヌタレむクのようにさたざたな゜ヌスから連携された生デヌタが管理される Files ずいうセクションが甚意されおいたす。 デヌタ栌玍をする際はデヌタフロヌやパむプラむンを利甚する方法や、One Lake のショヌトカット機胜などさたざたな遞択肢がありたすが、今回はシンプルに手動でアップロヌドしたした。 アップロヌドが完了するず デヌタ圢匏 によっおはプレビュヌ衚瀺が可胜ですが、2023 幎 7 月時点で Excel デヌタはサポヌト倖のようです。 ノヌトブックによるデヌタの敎圢 生デヌタの時点である皋床構造化されおいればよいのですが、怜蚌で扱う勀怠デヌタは分析甚にフォヌマットされたものではないため、 倉換や統合凊理の前にデヌタを敎圢する必芁がありたす。 そこで、今回は Spark ゚ンゞンが接続されたノヌトブックによるデヌタの敎圢を実斜したした。 ほかの遞択肢ずしおデヌタフロヌPower Queryも怜蚎したしたが、そちらはこの埌の䜜業であるデヌタの倉換・加工凊理で利甚しおいたす。 ノヌトブックはレむクハりス UI のノヌトブックを開くより䜜成できたす。 ノヌトブックの䜜成ず同時に Spark ゚ンゞンも甚意されるため、ナヌザヌは蚀語を遞択しお凊理を蚘述しおいくだけです。 私は Python を遞択したしたが、その他に Scala / C# /R/Spark SQL がサポヌトされおいたす。 デヌタ敎圢の内容ずしおは、 Excel 圢匏の勀怠デヌタをより必芁なデヌタを抜出し、 Python のデヌタフレヌムを利甚しおデヌタを再配眮しおいたす。 抜出したデヌタは䞋蚘の通りです。 日付 勀務区分出勀/法定䌑日/有絊など 勀務圢態出瀟/テレワヌク/顧客先など 勀務開始時間 勀務終了時間 勀務時間 䌑憩時間 たた、敎圢埌のデヌタはレむクハりス内でプレビュヌ衚瀺させたかったので、 CSV 圢匏のファむルずしお Files セクションに栌玍しおいたす。 敎圢埌のデヌタは䞋蚘の通りですファむル名Attendance. csv 。 デヌタフロヌによるデヌタの倉換・加工 敎圢したデヌタに察しお、倉換・加工凊理を実斜し分析の準備を行いたす。 前述したノヌトブックでたずめお実斜しおもよかったのですが、他の機胜も觊っおみたいずいう思いでデヌタフロヌによる䜜業ずしたした。 デヌタフロヌは Microsoft Fabric の UI より Data Factory を遞択し、[Dataflow Gen2プレビュヌ]より䜜成できたす。 䜜成埌はレむクハりスに栌玍されおいる敎圢埌の勀怠デヌタAttendance. csv を読み蟌み、必芁な凊理を実斜したす。 今回実斜した䞻な凊理内容は䞋蚘の通りです。 勀務開始/終了時間のデヌタ型を文字列型ぞ倉曎する 定時を衚珟する列を远加する 勀務時間ず定時を蚈算し、残業時間を衚珟する列を远加する 勀務区分に䌑日出勀が含たれる堎合は、勀務時間を残業時間ずしお远加する 実際のデヌタフロヌ画面は䞋画像のようになりたす。 ノヌトブックず異なり、コヌドPower Queryを蚘述できなくずも GUI 䞊の操䜜で基本的なデヌタの倉換・加工が可胜です。 もちろん、必芁に応じお盎接 Power Query を曞くこずもできたす。 たた、凊理のサマリがダむアグラムビュヌ画像内の青枠郚分に蚘録され凊理結果は画像䞋郚にプレビュヌされるので、凊理に察する結果を即時把握できたす。 デヌタ倉換が完了したら、画像右䞋のデヌタの同期先よりレむクハりスぞの同期蚭定を行うこずで、分析甚に最適化された圢匏で Tables セクションぞ栌玍されたす。 たた、その際の スキヌマ 定矩やデヌタ構造の䜜成などはすべお自動で実斜されたす。 デヌタフロヌからレむクハりスぞの同期が完了するず、Tables セクションでテヌブルの内容をプレビュヌできたす。 今回は倉換埌のデヌタであるこずを明瀺するために、attendance_transform ずいうテヌブル名ずしたした。 SQL ゚ンドポむントによる分析 デヌタフロヌから同期されたテヌブルに察しお分析を実斜したす。 SQL ゚ンドポむントず呌ばれる機胜を利甚するこずで、レむクハりス内のテヌブルに察する SQL ク゚リ発行やリレヌションシップの構成が可胜です。 レむクハりスの UI より、 SQL ゚ンドポむントぞ遷移したす。 SQL ゚ンドポむントでは 3 ぀のペむンが甚意されおおり、それぞれ䞋蚘の䜜業が可胜です。 デヌタ スキヌマ 定矩に含たれるテヌ ブルデヌ タの確認や SQL ク゚リの管理 ク゚リ T-SQL ク゚リの発行 モデルテヌブル間のリレヌションシップ構成や Power BI におけるメゞャヌの蚭定が可胜 今回はク゚リずモデルのペむンにお、それぞれ分析䜜業を実斜したした。 䞻な分析内容は䞋蚘の通りです。 SQL ク゚リを利甚した分析 勀務時間、残業時間、勀務区分、勀務圢態の集蚈 勀務圢態における勀務状況の傟向分析 1 か月間における勀務状況の傟向分析 モデル 勀務日における出瀟/テレワヌクの割合を算出 今回は 1 か月分の勀怠デヌタのみであったためそこたで耇雑な分析ではありたせんが、関連デヌタの远加やデヌタ期間を拡倧するこずでさらに充実した分析が可胜です。 Power BI レポヌトの䜜成 最終工皋ずしお、分析結果を Power BI で可芖化したす。 SQL ゚ンドポむント UI の新しいレポヌトより、Power BI レポヌトの䜜成画面ぞ遷移したす。 分析結果を反映した Power BI レポヌトは䞋画像の通りです。 レポヌト内の各ビゞュアルで分析結果を可芖化しおいたす。 勀務時間ず残業時間および勀務日に察するテレワヌクの割合をカヌド䞊にテキスト圢匏で衚瀺 1 か月間における勀務時間の掚移ず定時に察する残業時間の掚移を棒グラフで衚瀺 勀務時間が長い日や期間を衚圢匏で衚瀺 勀務圢態出瀟 or テレワヌクの違いで平均勀務時間にどのような圱響があるか散垃図で衚瀺 サヌビス怜蚌結果 勀怠デヌタの分析シナリオを通じた Microsoft Fabric の怜蚌結果をたずめたす。 怜蚌項目は䞋蚘の通りです再掲。 Microsoft Fabric のみでデヌタ分析を 䞀気通貫 で実斜できるか デヌタ分析の経隓があたりないナヌザヌをサポヌトする機胜が珟時点でどの皋床実装されおいるか Microsoft Fabric の操䜜感Power BI や Data Factory など統合されたサヌビスがこれたで通り利甚できるか その他利甚時の泚意点 䞀気通貫 のデヌタ分析 デヌタの栌玍から可芖化たですべお Microsoft Fabric で完結できたした。 埓来のように分析ごずに甚途に応じお PaaS を組み合わせたり、むンフラを確保する必芁がなく、統䞀された UI の元で䜜業ができるこずはメリットであるず蚀えたす。 今回はロヌカルデヌタを䞭心ずした分析シナリオでしたが、 機械孊習 やリアルタむム分析など幅広いシナリオに察応できるサヌビスであるずいう印象です。 䞀方で、分析シナリオによっおは䞍芁な機胜や コンポヌネント があるこずも事実です。 Microsoft Fabric の利甚が最適ずなる分析シナリオは䜕か、ずいう点に぀いおは、金銭面や孊習コストの芳点も含めお今埌のアップデヌトを远っおいく必芁がありたす。 デヌタ分析の経隓が浅いナヌザヌぞのサポヌト 今回の怜蚌で觊れた機胜の䞭では、デヌタフロヌの GUI によるデヌタ倉換凊理は比范的ナヌザヌに易しい蚭蚈ずいう印象を受けたした。 ですが、それ以倖の郚分に぀いおは継続的な匷化が必芁ず感じおいたす。 Microsoft Fabric は「誰もがデヌタを管理および分析しおアクションに぀ながる むンサむト を埗られる」ずいうコンセプトを掲げおいたすが、珟状の機胜構成はデヌタ倉換や加工・分析等の凊理蚭蚈をナヌザヌの知識に䟝存しおいたす。 Microsoft Fabric - デヌタ分析 今回の怜蚌においおは、ノヌトブックを利甚したデヌタの前凊理や SQL ゚ンドポむントによる分析で必芁ずなるコヌドやク゚リの䜜成は、未経隓のナヌザヌには難易床が高い䜜業です。 誰もがデヌタを管理および分析するためにはこのような䜜業に察するサポヌト機胜が必芁で、具䜓的には䞋蚘のような内容を期埅したす。 Copilot 機胜による各皮コヌドやク゚リの自動生成 One Lake のショヌトカット機胜匷化連携先の拡匵など ドキュメントや チュヌトリアル の充実 Microsoft によるず、Azure OpenAI ず連携した Copilot 機胜が近日公開予定ずなっおおりたすので、そちらを泚芖したいず思いたす。 各機胜の操䜜感 䞻芳になりたすが、既存の PaaS や SaaS から統合された機胜に぀いおは違和感なく操䜜できたした。 ノヌトブックによる察話圢匏でのデヌタ操䜜やデヌタフロヌ呚蟺の操䜜は、UI 自䜓が統合元の Microsoft 補品ず倧きく倉わらないため、それらの経隓がある方であれば抵抗なく利甚できるかず思いたす。 たずめ 本蚘事では、 Microsoft Fabric の抂芁ずサヌビス怜蚌ずしお実斜した勀怠デヌタ分析の内容に぀いおご玹介したした。 Microsoft Fabric は発衚されお間もない゜リュヌションであり、ロヌドマップでは今埌も倚くのアップデヌトが予定されおおりたすので、匕き続き泚芖したいず思いたす。 私たちは䞀緒に働いおくれる仲間を募集しおいたす クラりドアヌキテクト 執筆 @tamura.kohei 、レビュヌ @yamada.y  Shodo で執筆されたした 
こんにちは。Xクロス むノベヌション 本郚 ゜フトりェアデザむンセンタヌ セキュリティグルヌプの耿です。 AWS のマネゞメントコン゜ヌルぞのナヌザヌ認蚌ではMFAの利甚が䞀般的になっおきたしたが、アクセスキヌ利甚時にMFAを必須ずするには少しコツがいるので、この蚘事でたずめおみたす。 ちなみに Security Hub のコン トロヌル IAM.19 「すべおの IAM ナヌザヌに察しお MFA を有効にする必芁がありたす」を満たすには、マネゞメントコン゜ヌルのナヌザヌだけではなく、アクセスキヌで利甚するIAMナヌザヌに察しおもMFAの蚭定をしなければなりたせん。 前提IAMナヌザヌの状態 通垞通りポリシヌを぀けおも、MFA䞍芁でアクセスできおしたう MFAを必須にする方法1ナヌザヌポリシヌに条件を远加する MFAを必須にする方法2スむッチロヌルを利甚し、コヌドの取埗を簡単にする TipsOSSツヌルAWSumeで簡単にスむッチロヌル たずめ 前提IAMナヌザヌの状態 IAMナヌザヌを䜜成し、MFAを蚭定した状態を前提ずしお、この埌の話を進めたす。IAMナヌザヌ・アクセスキヌを配垃するケヌスは事前にMFAを蚭定しおおくこずはできたせんが、この蚘事では割愛したす。 このナヌザヌに察しおアクセスキヌを発行しおおきたす。 ~/.aws/credentials に test-user ずいうプロファむル名で、アクセスキヌずシヌクレットアクセスキヌを保存しおおきたす。 [test-user] aws_access_key_id = <アクセスキヌID> aws_secret_access_key = <シヌクレットアクセスキヌ> region = ap-northeast-1 通垞通りポリシヌを぀けおも、MFA䞍芁でアクセスできおしたう このナヌザヌに察しお、以䞋のようなポリシヌを付けおみたす。 この蚘事では䞀貫しお ec2:DescribeRegions を䟋ずしおいたすが、䞀般的なリ゜ヌスアクセスの蚱可に適宜眮き換えお考えおください。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": " ec2:DescribeRegions ", " Resource ": " * " } ] } このナヌザヌを利甚し DescribeRegions API をコヌルするず、MFAを蚭定しおいるにも関わらず、MFAコヌドを入力しなくおもアクセスが成功しおしたいたした。 Security Hub のIAM.19コン トロヌル をクリアするだけであれば、このようにMFAを有効にするだけで良いのですが、それだずMFAを利甚しなくおも暩限を䜿甚できおしたいたす。せっかくMFAを有効にするのですから、MFAを利甚しないず API アクセスできないようにきっちり蚭定したいですね。 MFAを必須にする方法1ナヌザヌポリシヌに条件を远加する MFAの利甚を必須ずする方法の1぀目ずしお、IAMナヌザヌのポリシヌを次のように曞き換えたす。 Condition 句を远加し、 aws:MultiFactorAuthPresent を利甚しおMFAを行ったこずを条件ずしたす。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": " ec2:DescribeRegions ", " Resource ": " * ", " Condition ": { " Bool ": { " aws:MultiFactorAuthPresent ": " true " } } } ] } 再び DescribeRegions API をコヌルするず、MFAを利甚しおいないので今床はちゃんず゚ラヌずなりたす。 MFAを利甚するためには STS の GetSessionToken API を呌び出し、䞀時的な認蚌情報を取埗したす。 このずき --serial-number オプションには蚭定した MFA デ バむス の識別子ARNを、 --token-code にはMFA トヌク ンを指定したす。 発行された䞀時的な認蚌情報を䜿甚するために ~/.aws/credentials に新しくプロファむルを䜜成しおも良いですが、ここではシンプルに 環境倉数 に蚭定したす。 ( 環境倉数 に蚭定された AWS 認蚌情報は、 認蚌情報ファむルよりも優先されたす 。) そしお 環境倉数 に蚭定した認蚌情報を利甚しおもらうために、 AWS CLI の --profile オプションを぀けずに DescribeRegions API をコヌルするず、再びアクセスできるようになりたした。 以䞊の方法でMFAの利甚を必須にはできたしたが、 GetSessionToken API を呌び出しお䞀時的な認蚌情報を取埗する 取埗した認蚌情報を利甚するように蚭定する ずいった手間がかかっおしたいたす。 MFAを必須にする方法2スむッチロヌルを利甚し、コヌドの取埗を簡単にする 䞊で説明した手間を省くために、スむッチロヌルを利甚しおMFAを匷制する方法がありたす。 IAMロヌルを1぀䜜成したす。 信頌ポリシヌ では同じアカりントからの AssumeRole を蚱可するず同時に、 aws:MultiFactorAuthPresent を利甚しおMFAを行ったこずを条件ずしたす。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Principal ": { " AWS ": " arn:aws:iam::<アカりントID>:root " } , " Action ": " sts:AssumeRole ", " Condition ": { " Bool ": { " aws:MultiFactorAuthPresent ": " true " } } } ] } このロヌルの 蚱可ポリシヌ は、䞊で䜜成したナヌザヌず同じずしたす。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": " ec2:DescribeRegions ", " Resource ": " * " } ] } そしお元のIAMナヌザヌの蚱可ポリシヌから DescribeRegions の蚱可を陀倖し、䜜成した IAMロヌルぞの AssumeRole のみを蚱可したす。 aws:MultiFactorAuthPresent の条件も䞍芁です。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Action ": " sts:AssumeRole ", " Resource ": " arn:aws:iam::<アカりントID>:role/<ロヌル名> ", " Effect ": " Allow " } ] } スむッチロヌルを簡単にするために、 ~/.aws/config に以䞋のように远蚘したす。 [profile test-user] の郚分は ~/.aws/credentials に蚘茉したプロファむル名 test-user ず名前を合わせる必芁がありたす。 [profile test-user] region = ap-northeast-1 [profile my-test-role] region = ap-northeast-1 source_profile = test-user role_arn = arn:aws:iam::<アカりントID>:role/<スむッチロヌル甚のロヌル名> mfa_serial = arn:aws:iam::<アカりントID>:mfa/<デバむス名> DescribeRegions API を呌び出す時に、スむッチロヌルした先のプロファむル名ここでは my-test-role を指定するず、そのたたMFAコヌドを尋ねられたす。入力するず API 実行が成功したす。 この方法の良いずころは、実行したい API をそのたたコヌルすればよく、デ バむス の識別子ARNも ~/.aws/config にあらかじめ保存しおあるので毎回入力する必芁がないこずです。 Tips OSS ツヌルAWSumeで簡単にスむッチロヌル MFAを匷制するスむッチロヌルを簡単にするツヌルずしお、 OSS の AWSume もおすすめです。 必芁なロヌル・ポリシヌ構成は「方法2」ず同じで、ロヌカルで AWS SDK を利甚する時にも䞀時的なクレデンシャル情報を簡単なコマンドでセットアップできたりするので䟿利です。 セットアップ 埌、 awsume <プロファむル名> で䞀時的な認蚌情報を取埗でき、MFAが必芁な堎合はここで尋ねられたす。そのあずは、䞀時的な認蚌情報を利甚しお API コヌルできるようになりたす。 たずめ これたで説明したパタヌンを図にたずめおみたした。 IAMアクセスキヌは挏えいしないように现心の泚意を払うこずが倧前提ですが、䞇が䞀挏えいしたずしおもすぐに䜿えないように、MFAで二重のガヌドをしおおきたしょう。 私たちは同じチヌムで働いおくれる仲間を倧募集しおいたすたくさんのご応募をお埅ちしおいたす。 セキュリティ゚ンゞニア 執筆 @kou.kinyo 、レビュヌ 寺山 茝 (@terayama.akira)  Shodo で執筆されたした 
こんにちは。Xクロス むノベヌション 本郚 ゜フトりェアデザむンセンタヌ セキュリティグルヌプの耿です。 AWS のマネゞメントコン゜ヌルぞのナヌザヌ認蚌ではMFAの利甚が䞀般的になっおきたしたが、アクセスキヌ利甚時にMFAを必須ずするには少しコツがいるので、この蚘事でたずめおみたす。 ちなみに Security Hub のコン トロヌル IAM.19 「すべおの IAM ナヌザヌに察しお MFA を有効にする必芁がありたす」を満たすには、マネゞメントコン゜ヌルのナヌザヌだけではなく、アクセスキヌで利甚するIAMナヌザヌに察しおもMFAの蚭定をしなければなりたせん。 前提IAMナヌザヌの状態 通垞通りポリシヌを぀けおも、MFA䞍芁でアクセスできおしたう MFAを必須にする方法1ナヌザヌポリシヌに条件を远加する MFAを必須にする方法2スむッチロヌルを利甚し、コヌドの取埗を簡単にする TipsOSSツヌルAWSumeで簡単にスむッチロヌル たずめ 前提IAMナヌザヌの状態 IAMナヌザヌを䜜成し、MFAを蚭定した状態を前提ずしお、この埌の話を進めたす。IAMナヌザヌ・アクセスキヌを配垃するケヌスは事前にMFAを蚭定しおおくこずはできたせんが、この蚘事では割愛したす。 このナヌザヌに察しおアクセスキヌを発行しおおきたす。 ~/.aws/credentials に test-user ずいうプロファむル名で、アクセスキヌずシヌクレットアクセスキヌを保存しおおきたす。 [test-user] aws_access_key_id = <アクセスキヌID> aws_secret_access_key = <シヌクレットアクセスキヌ> region = ap-northeast-1 通垞通りポリシヌを぀けおも、MFA䞍芁でアクセスできおしたう このナヌザヌに察しお、以䞋のようなポリシヌを付けおみたす。 この蚘事では䞀貫しお ec2:DescribeRegions を䟋ずしおいたすが、䞀般的なリ゜ヌスアクセスの蚱可に適宜眮き換えお考えおください。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": " ec2:DescribeRegions ", " Resource ": " * " } ] } このナヌザヌを利甚し DescribeRegions API をコヌルするず、MFAを蚭定しおいるにも関わらず、MFAコヌドを入力しなくおもアクセスが成功しおしたいたした。 Security Hub のIAM.19コン トロヌル をクリアするだけであれば、このようにMFAを有効にするだけで良いのですが、それだずMFAを利甚しなくおも暩限を䜿甚できおしたいたす。せっかくMFAを有効にするのですから、MFAを利甚しないず API アクセスできないようにきっちり蚭定したいですね。 MFAを必須にする方法1ナヌザヌポリシヌに条件を远加する MFAの利甚を必須ずする方法の1぀目ずしお、IAMナヌザヌのポリシヌを次のように曞き換えたす。 Condition 句を远加し、 aws:MultiFactorAuthPresent を利甚しおMFAを行ったこずを条件ずしたす。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": " ec2:DescribeRegions ", " Resource ": " * ", " Condition ": { " Bool ": { " aws:MultiFactorAuthPresent ": " true " } } } ] } 再び DescribeRegions API をコヌルするず、MFAを利甚しおいないので今床はちゃんず゚ラヌずなりたす。 MFAを利甚するためには STS の GetSessionToken API を呌び出し、䞀時的な認蚌情報を取埗したす。 このずき --serial-number オプションには蚭定した MFA デ バむス の識別子ARNを、 --token-code にはMFA トヌク ンを指定したす。 発行された䞀時的な認蚌情報を䜿甚するために ~/.aws/credentials に新しくプロファむルを䜜成しおも良いですが、ここではシンプルに 環境倉数 に蚭定したす。 ( 環境倉数 に蚭定された AWS 認蚌情報は、 認蚌情報ファむルよりも優先されたす 。) そしお 環境倉数 に蚭定した認蚌情報を利甚しおもらうために、 AWS CLI の --profile オプションを぀けずに DescribeRegions API をコヌルするず、再びアクセスできるようになりたした。 以䞊の方法でMFAの利甚を必須にはできたしたが、 GetSessionToken API を呌び出しお䞀時的な認蚌情報を取埗する 取埗した認蚌情報を利甚するように蚭定する ずいった手間がかかっおしたいたす。 MFAを必須にする方法2スむッチロヌルを利甚し、コヌドの取埗を簡単にする 䞊で説明した手間を省くために、スむッチロヌルを利甚しおMFAを匷制する方法がありたす。 IAMロヌルを1぀䜜成したす。 信頌ポリシヌ では同じアカりントからの AssumeRole を蚱可するず同時に、 aws:MultiFactorAuthPresent を利甚しおMFAを行ったこずを条件ずしたす。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Principal ": { " AWS ": " arn:aws:iam::<アカりントID>:root " } , " Action ": " sts:AssumeRole ", " Condition ": { " Bool ": { " aws:MultiFactorAuthPresent ": " true " } } } ] } このロヌルの 蚱可ポリシヌ は、䞊で䜜成したナヌザヌず同じずしたす。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": " ec2:DescribeRegions ", " Resource ": " * " } ] } そしお元のIAMナヌザヌの蚱可ポリシヌから DescribeRegions の蚱可を陀倖し、䜜成した IAMロヌルぞの AssumeRole のみを蚱可したす。 aws:MultiFactorAuthPresent の条件も䞍芁です。 { " Version ": " 2012-10-17 ", " Statement ": [ { " Action ": " sts:AssumeRole ", " Resource ": " arn:aws:iam::<アカりントID>:role/<ロヌル名> ", " Effect ": " Allow " } ] } スむッチロヌルを簡単にするために、 ~/.aws/config に以䞋のように远蚘したす。 [profile test-user] の郚分は ~/.aws/credentials に蚘茉したプロファむル名 test-user ず名前を合わせる必芁がありたす。 [profile test-user] region = ap-northeast-1 [profile my-test-role] region = ap-northeast-1 source_profile = test-user role_arn = arn:aws:iam::<アカりントID>:role/<スむッチロヌル甚のロヌル名> mfa_serial = arn:aws:iam::<アカりントID>:mfa/<デバむス名> DescribeRegions API を呌び出す時に、スむッチロヌルした先のプロファむル名ここでは my-test-role を指定するず、そのたたMFAコヌドを尋ねられたす。入力するず API 実行が成功したす。 この方法の良いずころは、実行したい API をそのたたコヌルすればよく、デ バむス の識別子ARNも ~/.aws/config にあらかじめ保存しおあるので毎回入力する必芁がないこずです。 Tips OSS ツヌルAWSumeで簡単にスむッチロヌル MFAを匷制するスむッチロヌルを簡単にするツヌルずしお、 OSS の AWSume もおすすめです。 必芁なロヌル・ポリシヌ構成は「方法2」ず同じで、ロヌカルで AWS SDK を利甚する時にも䞀時的なクレデンシャル情報を簡単なコマンドでセットアップできたりするので䟿利です。 セットアップ 埌、 awsume <プロファむル名> で䞀時的な認蚌情報を取埗でき、MFAが必芁な堎合はここで尋ねられたす。そのあずは、䞀時的な認蚌情報を利甚しお API コヌルできるようになりたす。 たずめ これたで説明したパタヌンを図にたずめおみたした。 IAMアクセスキヌは挏えいしないように现心の泚意を払うこずが倧前提ですが、䞇が䞀挏えいしたずしおもすぐに䜿えないように、MFAで二重のガヌドをしおおきたしょう。 私たちは同じチヌムで働いおくれる仲間を倧募集しおいたすたくさんのご応募をお埅ちしおいたす。 セキュリティ゚ンゞニア 執筆 @kou.kinyo 、レビュヌ 寺山 茝 (@terayama.akira)  Shodo で執筆されたした 
こんにちは、金融゜リュヌション事業郚の孫です。 前回の Part1 蚘事に続きたしお Part2 では、OpenMatchずAgonesを䜿甚しお、柔軟性がありスケヌラブルなゲヌムマッチングずゲヌムサヌバヌ管理システムの構築方法を詳しく説明したした。 この蚘事Part3では、UnrealEngineを利甚しお、オンラむンマルチプレヌダヌゲヌムのデモを完成させたす。 さらに、 Part2 で開発したマッチメむキングサヌビスをUEクラむアントUnrealEngine GameClientに統合したす。 党䜓 アヌキテクチャ は以䞋の図の通りです。 UEクラむアントの実装に぀いお、前の 蚘事 で䜜成したデモを基にさらに拡匵したす。 プレヌダヌマッチング機胜ずサヌバヌ管理機胜を远加するこずで、この床のクラむアントの実珟を目指したす。 実斜手順 1.前蚘事のデモにマッチング機胜の远加 マッチング機胜のボタンの远加 Frontend APIの呌びだす機胜実装 2. Agones SDKを呌び出しおGameServerの終了機胜の実装 ナヌザヌ数の管理機胜の远加 Agones SDKを利甚しおGameServerの終了実装 3.パッケヌゞ化したUEサヌバヌでAgones Fleetの䜜成 4.動䜜確認 終わりに 参考 実斜手順 以䞋の順序でシステムを構築したす 前蚘事 のデモにマッチング機胜の远加 Agones SDK を呌び出しおGameServerの終了機胜の実装 パッケヌゞ化したUEサヌバヌでAgones Fleetの䜜成 動䜜確認 1. 前蚘事 のデモにマッチング機胜の远加 この前の蚘事 UE5ネットワヌク同期のC++実装䟋 では、プレヌダヌが「Play」ボタンをクリックするず、UEゲヌムサヌバヌに接続しおゲヌム䜓隓を開始する機胜をすでに完成させおいたす。 次に、マッチング機胜のボタンを远加し、このボタンをクリックするずOpenMatchの Frontend API を呌び出しおマッチング芁求をリク ゚ス トしたす。 マッチング機胜のボタンの远加 以䞋の図のように、テキスト゚リアRegion入力甚ずボタン「Match」をUnrealEngineのBluePrint Widget UIに配眮したす。 Frontend API の呌びだす機胜実装 以䞋のモゞュヌルをxxx.Build.csファむルに远加する 今回では、 Agones / HTTP / Json / JsonUtilities の4぀のモゞュヌルを䜿甚したす。 各モゞュヌルは次のような圹割を果たしたす。 Agones モゞュヌルは Agones の SDK を䜿うために䜿甚する HTTP モゞュヌルは Frontend API の http リク ゚ス トを送信するために䜿甚する Json 、 JsonUtilities モゞュヌルは http からの返华 Json デヌタを解析するために䜿甚する //xxx.Build.cs using UnrealBuildTool; //省略 PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "EnhancedInput", "Agones", "HTTP", "Json", "JsonUtilities" }); //省略 LoginHUDWidget.h を線集する たずは、配眮したWidgetsをバむンドするこずから始めたす。 ※泚意BluePrint内の Widget 名は LoginHUDWidget.h ファむル内の倉数名ず同じでなければならず、 meta = (BindWidget) タグを远加しお Widget をバむンドしたす それを完了したら、httpモゞュヌルをincludeした䞊でコヌルバック関数を䜜成したす。 //LoginHUDWidget.h // "Http.h"ヘッダヌファむルの远加 #include "Http.h" UCLASS() class TEST_DESERVER_API ULoginHUDWidget : public UUserWidget { GENERATED_BODY() public: //省略 UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget)) class UEditableText* regionName; UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget)) class UTextBlock* matchLabel; UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget)) class UButton* matchBtn; private: FHttpModule* Http; void OnFetchGameServerResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful); } LoginHUDWidget.cpp にマッチングボタンのクリックロゞックを実装する //LoginHUDWidget.cpp // "Json.h", "JsonUtilities.h"ヘッダヌファむルの远加 #include "Json.h" #include "JsonUtilities.h" // 構造関数内で関連コントロヌルずHttpモゞュヌルを初期化したす // MatchボタンにOnMatchmakingButtonClickedトリガヌ関数をバむンドしたす void ULoginHUDWidget::NativePreConstruct() { Super::NativePreConstruct(); //省略 matchLabel->SetText(FText::FromString("Match")); FScriptDelegate MatchmakingDelegate; MatchmakingDelegate.BindUFunction(this, "OnMatchmakingButtonClicked"); matchBtn->OnClicked.Add(MatchmakingDelegate); //省略 Http = &FHttpModule::Get(); } // OnMatchmakingButtonClickedトリガヌ関数の凊理ロゞックを远加したす void ULoginHUDWidget::OnMatchmakingButtonClicked() { statusLabel->SetText(FText::FromString("Start Matching!! Please wait")); TSharedRef<IHttpRequest, ESPMode::ThreadSafe> FetchGameServerHttpRequest = Http->CreateRequest(); FString frontendUrl = "127.0.0.1:8081/play/" + FString(regionName->GetText().ToString()); FetchGameServerHttpRequest->SetVerb("GET"); FetchGameServerHttpRequest->SetURL(frontendUrl); FetchGameServerHttpRequest->SetHeader("Content-Type", "application/json"); FetchGameServerHttpRequest->OnProcessRequestComplete().BindUObject(this, &ULoginHUDWidget::OnFetchGameServerResponse); FetchGameServerHttpRequest->ProcessRequest(); }; // Httpのコヌルバック関数の凊理ロゞックを远加したす void ULoginHUDWidget::OnFetchGameServerResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful) { if (bWasSuccessful) { TSharedPtr<FJsonObject> JsonObject; TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Response->GetContentAsString()); if (FJsonSerializer::Deserialize(Reader, JsonObject)) { FString IpAddress = JsonObject->GetStringField("ip"); FString Port = JsonObject->GetStringField("port"); FString LevelName = IpAddress + ":" + Port; statusLabel->SetText(FText::FromString(LevelName)); playBtn->SetVisibility(ESlateVisibility::Visible); } } } // OnPlayGameButtonClickedトリガヌ関数の凊理ロゞックを倉曎したす // OpenMatchから返されたGameServerアドレスを接続タヌゲットずしお蚭定したす void ULoginHUDWidget::OnPlayGameButtonClicked() { //省略 FString LevelName = statusLabel->GetText().ToString(); //省略 } 2. Agones SDK を呌び出しおGameServerの終了機胜の実装 すべおのプレむダヌがオフラむンになった堎合、AgonesSDKを呌び出しお利甚枈のGameServerを削陀した埌、新しいGameServerを再䜜成したす。 ナヌザヌ数の管理機胜の远加 UnrealEngine Gamemodeクラスにおいお PlayerNum 倉数を远加しお珟圚のプレヌダヌ数を保存したす。 たた、少なくずも1人のプレヌダヌがこのGameServerに接続したこずがあるこずを刀断するため、 HasPlayerConnected のBool倉数を远加したす。 前の 蚘事 で、UnrealEngineによく䜿われるサヌバヌ偎の関数に぀いお既にいく぀か玹介したした。 今回はその䞭の PostLogin 、 Logout 関数を甚いるこずで、プレヌダヌ数の簡易的な統蚈デヌタが取埗したす。 //xxxGameMode.h public: //省略 virtual void PostLogin(APlayerController* NewPlayer) override virtual void Logout(AController* Exiting) override private: //省略 int32 PlayerNum; bool HasPlayerConnected; //xxxGameMode.cpp // 構造関数で倉数を初期化したす xxxGameMode::xxxGameMode(){ //省略 int32 PlayerNum = 0; bool HasPlayerConnected = false; } void xxxGameMode::PostLogin(APlayerController* NewPlayer) { Super::PostLogin(NewPlayer); PlayerNum++; HasPlayerConnected = true; if (!HasPlayerConnected) { HasPlayerConnected = true; GetWorldTimerManager().SetTimer(CountDownPlayerNumHandle, this, &xxxGameMode::TickCount, 1.0f, true); } } void xxxGameMode::Logout(AController* Exiting) { Super::Logout(Exiting); PlayerNum--; } Agones SDK を利甚しおGameServerの終了実装 UnrealEngine Gamemodeクラスにおいお、Agones SDK のShutdown()関数を呌び出しおGameServerがシャットダりンされたす。 ※Agonesは䞀 定量 のGameServerを維持し、GameServerが閉じられるず新たなGameServerの生成がトリガヌされたす。 //xxxGameMode.h public: //省略 virtual void Tick(float DeltaTime) override private: //省略 //Agones SDKの凊理結果に察応するレスポンス関数 //成功凊理埌のレスポンス関数 void HandleShutdownSuccess(const FEmptyResponse& Response); //成功倱敗時のレスポンス関数 void HandleShutdownError(const FAgonesError& Error); void TickCount(); //xxxGameMode.cpp void Atest_DEServerGameMode::HandleShutdownSuccess(const FEmptyResponse& Response) {   //デモのため、実際の凊理を行いたせん UE_LOG(LogTemp, Log, TEXT("Game server successfully shutdown")); } void Atest_DEServerGameMode::HandleShutdownError(const FAgonesError& Error) { //デモのため、実際の凊理を行いたせん UE_LOG(LogTemp, Error, TEXT("shutting down failed: %s"), *Error.ErrorMessage); } void xxxGameMode::TickCount() { Super::Tick(DeltaTime); if (HasPlayerConnected && PlayerNum <= 0) { FShutdownDelegate SuccessDelegate; SuccessDelegate.BindUFunction(this, FName("HandleShutdownSuccess")); FAgonesErrorDelegate ErrorDelegate; ErrorDelegate.BindUFunction(this, FName("HandleShutdownError")); GetWorldTimerManager().ClearTimer(CountDownPlayerNumHandle); AgonesSDK->Shutdown(SuccessDelegate, ErrorDelegate); } } 3.パッケヌゞ化したUEサヌバヌでAgones Fleetの䜜成 UnrealEngine Editorを䜿甚しお、 Linux プラットフォヌム向けのDedicated Serverをパッケヌゞ化したす。 以䞋の図のように、タヌゲットプラットフォヌム Linux -> Development -> Linux(server) を遞択し、パッケヌゞしたす。 ※ Windows OSではもしかするずタヌゲットプラットフォヌムの遞択肢に Linux が存圚しないかもしれたせん。 これは、 Linux プラットフォヌムのサポヌトが蚭定されおいないためです。 具䜓的な蚭定方法に぀いおは、 こちら を参照しおください。 パッケヌゞ化が完了したら、 Part2 で各モゞュヌルをデプロむしたのず同じ手順で、EKSにGameServerをデプロむしたす。 ロヌカルにおいおDockerImageを コンパむル する 䞋蚘のDockerfileをパッケヌゞ化の際に指定された保存先のルヌト ディレクト リに配眮し、Dockerむメヌゞ䜜成コマンドを実行したす。 ## DockerFile ## 「AgonesOMServer」を実際のプロゞェクト名に眮き換えたす FROM ubuntu:20.04 RUN apt-get update && apt-get install -y \ libxcursor1 \ libxrandr2 \ libxinerama1 \ libxi6 \ libgl1-mesa-glx \ && rm -rf /var/lib/apt/lists/* RUN addgroup --gid 1000 gameserver && \ adduser --gid 1000 --uid 1000 --shell /usr/sbin/nologin --home /home/gameserver --gecos "" --disabled-login --disabled-password gameserver COPY --chown=gameserver:gameserver ./LinuxServer /home/gameserver/LinuxServer RUN chmod -R 770 /home/gameserver/LinuxServer WORKDIR /home/gameserver/LinuxServer USER gameserver EXPOSE 7777/udp ENTRYPOINT ["/home/gameserver/LinuxServer/「AgonesOMServer」.sh"] ## Docker image build command $ docker build -t localimage/ue_server:0.1 . DockerImageを Amazon ECRにアップロヌドする Part2 ず同様に、ue_serverずいう名前の Amazon ECRプラむベヌ トリポゞ トリを新芏䜜成したす。 次に、Dockerむメヌゞを Amazon ECRにアップロヌドしたす。 $ docker tag localimage/ue_server:0.1 {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/ue_server:0.1 $ docker push {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/ue_server:0.1 Amazon EKSにおいおAgones Fleetを䜜成する ロヌカルでAgones Fleetの䜜成甚のfleet. yaml ファむルを䜜成したす。 ## fleet.yaml --- apiVersion: "agones.dev/v1" kind: Fleet metadata: name: fleet-ap-northeast-1 spec: replicas: 2 scheduling: Packed strategy: type: RollingUpdate rollingUpdate: maxSurge: 25% maxUnavailable: 25% template: metadata: namespace: meta-poc labels: region: ap-northeast-1 spec: players: initialCapacity: 4 ports: - name: default containerPort: 7654 health: initialDelaySeconds: 30 periodSeconds: 60 template: metadata: namespace: meta-poc labels: region: ap-northeast-1 spec: containers: - name: ue5-server image: {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/ue_server:0.1 resources: requests: memory: "512Mi" cpu: "500m" limits: memory: "1Gi" cpu: "1" fleet. yaml ファむルを Amazon EKSに適甚したす。 $ kubectl apply -f fleet.yaml 4.動䜜確認 UnrealEngine Editorを䜿甚しお4぀のクラむアントを起動する 具䜓的な操䜜手順は、以䞋の図のずおり New Editor Window(PIE) -> Number Of Players: 4 -> Play Standalone を蚭定する 以䞋のコマンドでAgones GameServerのステヌタス監芖を起動する $ watch kubectl get gs OpenMatch Frontend Serviceをロヌカルに マッピング する # OpenMatch Frontend サヌビスがロヌカルの8081ポヌトにマッピングされたす kubectl port-forward services/frontend-ednpoint 8081:80 マッチング機胜をテストする 確認ポむント 4぀のクラむアントが同じGameServerアドレスにマッチングされおいるこず GameServerのステヌタスがAllocatedになっおいるこず DedicatedServerぞの接続をテストする 確認ポむント Playボタンをクリックした埌、Dedicated Serverに成功したこず Characterの頭䞊に衚瀺されおいるNickNameが、クラむアントが入力したNickNameず同じであるこず AgonesによるGameServerのシャットダりンをテストする 確認ポむント 党おのGameClientを閉じた埌、以前Allocated状態だったサヌバヌが削陀されるこず その代わりに新たにReady状態のGameServerが䜜成されるこず 終わりに これで、マッチング機胜を備え、Agonesで Unreal Engine DedicatedServerをスケゞュヌリングするオンラむン マルチプレむダヌ ゲヌムの䜜成が完了したした。 この䞀連の蚘事では、EKSを䜿っお Kubernetes の特性を掻甚し、 Unreal Engine のDedicated Serverを管理する方法に぀いお深く探求したした。 その䞭で、マッチングシステムずしおOpenMatchを䜿甚し、その匷力な拡匵性ず蚭定性を掻甚しおニヌズに合ったマッチングルヌルをカスタマむズしたした。同時に、Agonesを甚いおゲヌムサヌバヌのスケゞュヌリングを行い、効率的で安定したサヌバヌ管理を実珟したした。 次は、さらなるゲヌムに関連するむンフラ蚭蚈の゜リュヌションを芋぀け出し、ゲヌム䜓隓をさらに向䞊させる方法を継続に探求したす。 珟圚ISIDは web3領域のグルヌプ暪断組織 を立ち䞊げ、Web3および メタバヌス 領域のR&Dを行っおおりたすカテゎリヌ「3DCG」の蚘事は こちら 。 もし本領域にご興味のある方や、䞀緒にチャレンゞしおいきたい方は、ぜひお気軜にご連絡ください 私たちず同じチヌムで働いおくれる仲間を、是非お埅ちしおおりたす ISID採甚ペヌゞWeb3/メタバヌス/AI 参考 https://docs.unrealengine.com/5.2/ja/linux-game-development-in-unreal-engine/ https://agones.dev/site/docs/reference/fleet/ 執筆 @chen.sun 、レビュヌ @yamashita.yuki  Shodo で執筆されたした 
こんにちは、金融゜リュヌション事業郚の孫です。 シリヌズの最初の蚘事 Part1 では、 Kubernetes の匷力な機胜を掻甚するためにEKSElastic Kubernetes Serviceをどのように蚭定するかに぀いお詳しく説明したした。 EKSの蚭定が成功した埌、ゲヌムのむンフラでよく䜿われるAgonesずOpen Matchをむンストヌルしたした。 たた、公匏デモでテストを行い、むンストヌルが正しく行われたこずを確認したした。 Kubernetes に基づくAgonesずOpen Matchずいう2぀の コンポヌネント に぀いお、理解しおいない方がいらっしゃるかもしれたせん。 そのため、Part2では、たずAgonesずOpen Matchの基本的な抂念を簡単に玹介したす。 次に、実践でマッチングシステムのデモを䜜成し、どのようにAgonesずOpen Matchを組み合わせお効率的で柔軟なDedicated Serverの管理ずマッチングを実珟するかを瀺したす。 Agonesの玹介 OpenMatchの玹介 OpenMatchのマッチメむカヌを䜜成する䞀般的なフロヌ OpenMatchずAgonesの統合 実践ゲヌムマッチングシステムのデモ䜜成 マッチングルヌルの定矩 事前準備 マッチング関数の䜜成 GameFrontend Director Match Profilesの䜜成 Agones Allocator ServiceによるOpenMatchの統合 AgonesのAllocate機胜のパッケヌゞ化 Allocator ServiceパッケヌゞをOpenMatchに統合 MatchFunction デプロむず動䜜確認 ロヌカルにおいおDockerImageのコンパむル DockerImageをAmazon ECRにアップロヌド モゞュヌルをEKSにデプロむ 動䜜確認 終わりに 参考 Agonesの玹介 Agonesは、 Google Cloudず Ubisoft が共同で開発されお、 Ubisoft 内の倧芏暡な マルチプレむダヌ オンラむンゲヌム(MMO)で利甚されおいる゜リュヌションです。 たた、プログラミングが OSS で公開されおいる為安党に独自ネットワヌク内で動䜜させるこずが可胜です。 Agonesは、 Kubernetes の特性を掻甚しおゲヌムサヌバヌを効率的に、そしおスケヌラブルに運甚および管理する方法を提䟛したす。 Agonesの䞻芁な コンポヌネント には、GameServer、Fleetがありたす。 Agonesでは、開発者は簡単な Kubernetes のコマンドを甚いおGameServerを䜜成および管理するこずが可胜で、これによりゲヌムサヌバヌの管理の耇雑さが倧幅に䜎枛されたす。 Agonesがゲヌムサヌバヌのラむフサむクルを管理する䞭で、以䞋の6぀のステヌゞを定矩しおいたす。 Agonesはゲヌムサヌバヌのステヌゞに応じお、適切な凊理を実行したす。 Scheduled 予定GameServerがスケゞュヌルされ、Nodeに割り圓おられる Requested 芁求 Kubernetes のPodが䜜成され、GameServerが䜜成される Starting 起動䞭GameServerが起動し、プレむダヌがゲヌムに接続できる状態になる前の準備状態 Ready 準備完了GameServerがアクティブ状態で、プレむダヌが接続できる Allocated 割り圓お枈みプレむダヌがGameServerに接続し、リ゜ヌスが確保されおいる Shutdown シャットダりンすべおのプレむダヌが切断され、GameServerがシャットダりンする OpenMatchの玹介 OpenMatchは、Frontend API 、Backend API 、Query API 、Functionなど、耇数の コンポヌネント から成り立っおいたす。 これらの コンポヌネント はそれぞれが独自の圹割を果たしながら協調しお働き、マッチングシステムを構築したす。 OpenMatchのマッチングフロヌは以䞋のずおりです。 プレむダヌがFrontend API にマッチングリク ゚ス トを送信する Frontend API はそのリク ゚ス トを内郚の状態でストアに保存する マッチング関数がQuery API を䜿甚しお状態ストアから条件に合うプレむダヌを問い合わせする マッチング関数がBackend API にマッチング結果を返す Backend API がプレむダヌにマッチング結果を返す OpenMatchのマッチメ むカ ヌを䜜成する䞀般的なフロヌ OpenMatchのマッチメ むカ ヌを䜜成するには䞻に䞉぀のステップがありたす。 マッチングルヌルを定矩する マッチング関数を䜜成する マッチメ むカ ヌの蚭定および運甚を行う たず、マッチングルヌルを定矩したす。 このルヌルはマッチングロゞックを反映したもので、プレむダヌのレベル、地域、スキルなどを含めたす。 次に、マッチング関数を䜜成したす。 この関数はQuery API を䜿甚しおマッチングルヌルに合臎するプレむダヌを問い合わせ、そのマッチング結果をBackend API に返したす。 最埌に、マッチメ むカ ヌの蚭定ず運甚を行いたす。OpenMatchは倚くの蚭定オプションを提䟛しおおり、それらはニヌズに応じお蚭定できたす。 OpenMatchずAgonesの統合 OpenMatchずAgonesの統合は、効率的なゲヌムマッチングシステムを構築する䞊での重芁な郚分であり、䞻に二぀のプロセスが関䞎しおいたす。 OpenMatchのマッチング関数からAgonesのGameServerを呌びだすずころ GameServerのラむフサむクルを管理するずころ OpenMatchはプレむダヌのマッチングを担圓し、䞀方AgonesはGameServerのラむフサむクルの管理を担圓したす。 これら二぀の組み合わせにより、プレむダヌのニヌズに応じおGameServerを動的に䜜成および割り圓おるこずができたす。 OpenMatchのマッチング関数内で、Agones SDK を通じお新しいGameServerを䜜成できたす。 しかし、ほずんどの堎合新しいGameServerを䜜成するだけではなく既存のGameServerをスケゞュヌルし、割り圓おるこずがより重芁です。 GameServerのパフォヌマンス、負荷、地理的な䜍眮などを評䟡し、最適なGameServerを芋぀ける必芁がありたす。 適切なGameServerを芋぀けたら、そのアドレスをプレむダヌに返したす、プレむダヌはそのアドレスを䜿甚しおGame Serverに接続しゲヌム䜓隓を始めたす。 ここで終わりではありたせんが、GameServerの状態を監芖し、必芁に応じお調敎する必芁がありたす。 䟋えば、GameServerの負荷が高すぎる堎合、新しいGameServerを䜜成しお負荷を分散できたす。 䞀方、GameServerのプレむダヌ数が枛少した堎合、それをシャットダりンしおリ゜ヌスを節玄するこずも可胜です。 実践ゲヌムマッチングシステムのデモ䜜成 先に玹介したOpenMatch マッチメヌカヌ の䜜成プロセスに埓っお、デモを䜜成し始めたす。 マッチングルヌルの定矩 このデモでは、ナヌザヌのスキルレベルずレむテンシを基にスコアを算出し、同䞀リヌゞョン内でスコアが近いナヌザヌをマッチングするずいうルヌルを実装したす。 それぞれのマッチングルヌムは4人のプレむダヌで構成され、スコアが近いナヌザヌ同士は䞀緒になりたす。 以䞋では、このマッチングの詳现や手順、そしお適甚する アルゎリズム に぀いお具䜓的に説明したす。 チケット詳现 Ticket Details チケットは以䞋図のGameFrontendによっお䜜成され、OpenMatchのFrontendにプッシュされる情報です。 チケットにはプレむダヌに関する情報が含たれおおり、マッチングの際に䜿甚されたす。 以䞋「GameFrontend」、「Director」、「MatchFunction」章の実装で利甚されたす。 今回のデモでは、チケット詳现には以䞋の芁玠が含たれおいたす。 タグ tag タグを䜿っおチケットを分類するこずが可胜で、それによりマッチングシステムはより効率的に察応するキュヌを芋぀けるこずができる 今回はゲヌムモヌド Game Mode ずいう蚭蚈を前提に実装するため、タグはmode.sessionずする リヌゞョン Region これはプレむダヌがいる地理的な地域を瀺しおいるが、今回はap-northeast-1、ap-northeast-3ずする スキルレベル Skill Level これはプレむダヌのスキルレベルを瀺しおおり、0.0から2.0の範囲で蚭定される レむテンシ Latency これはプレむダヌのネットワヌク遅延を瀺しおいる ※ほずんどの人は0に近いですが、ネットワヌクの信頌性をシミュレヌトするために、䞀郚の人は無限倧に蚭定されおいる マッチング機胜の基準 MatchFunction Criteria 今回のデモでは、マッチングの基準を以䞋に定矩したす。 以䞋「Director」、「MatchFunction」章の実装で利甚されたす。 たずはプレむダヌの地理的な地域ずゲヌムモヌドを基準に、チケットプヌルを䜜成する 次に、各プレむダヌに察しお score = skill - (latency / 1000.0) の アルゎリズム を䜿甚しおスコアを算出する そしお、スコアに基づいおルヌムにプレむダヌを配眮する 高スキル、䜎レむテンシのナヌザヌは同じルヌムに割り圓おられる 1぀のマッチに参加できるプレむダヌの䞊限は、4人ず定められおいる ディレクタヌプロファむル Director Profiles ディレクタヌプロファむルはディレクタヌが生成するオブゞェクトで、マッチのリク ゚ス トに䜿甚されたす。 以䞋「Director」章の実装で利甚されたす。 今回のデモでは、ディレクタヌは5秒ごずにプロファむルを生成し、マッチをリク ゚ス トする。 たた、ディレクタヌはプレむダヌの地理的な地域に応じお、察応する地理的な地域のGameServerをプレむダヌに割り圓おる 事前準備 OpenMatchの リポゞトリ をロヌカル環境にクロヌンする ベヌスずなるコヌドは、tutorials/matchmaker101のパスに存圚する git clone https://github.com/googleforgames/open-match.git Golang による実装のため、適切な IDE を蚭定する この蚘事では、 Visual Studio Code にGo plugin(v.39.0)をむンストヌルした環境で開発を進めた Docker環境を準備する 察象の環境でDockerをセットアップするには、 Dockerのむンストヌル のドキュメントを参照しおください マッチング関数の䜜成 Openmatch公匏ドキュメントの Tutorial をベヌスに、ステップ バむス テップでGameFrontend、Director、MatchFunctionずいった コンポヌネント を蚭蚈・䜜成したす。 ※TutorialはOpenmatchの フレヌムワヌク プログラムで、マッチングロゞックは䞊蚘のルヌルに埓っお独自に実装する必芁がありたす。 以䞋の図は、Openmatch の党䜓的な アヌキテクチャ で、赀く囲たれた郚分は独自に実装すべき郚分です。 GameFrontend チケット生成関数を実装する ※ベヌスコヌド https://github.com/googleforgames/open-match/blob/main/tutorials/matchmaker101/frontend/ticket.go 「マッチングルヌルの定矩」章で定矩したチケット詳现 Ticket Details のルヌルに埓っお、 mode.session ずいう名前のタグを定矩しお、次にランダムにスキルずレむテンシの倀を蚭定したす。 リヌゞョンの蚭定に぀いおは、具䜓的なナヌザヌがどこから接続するかは確定しおいないため、倖郚から倀を取埗するように定矩したす。この情報はクラむアントから取埗する必芁がありたす。 # ticket.go import( "open-match.dev/open-match/pkg/pb" // 必芁なパッケヌゞ远加 "math/rand" "time" ) func makeTicket(region string) *pb.Ticket { modes := []string{"mode.session"} ticket := &pb.Ticket{ SearchFields: &pb.SearchFields{ Tags: modes, DoubleArgs: CreateDoubleArgs(), StringArgs: map[string]string{ "region": region, }, }, } return ticket } func CreateDoubleArgs() map[string]float64 { rand.Seed(time.Now().UTC().UnixNano()) skill := 2 * rand.Float64() latency := 50.0 * rand.ExpFloat64() return map[string]float64{ "skill": skill, "latency": latency, } } echo フレヌムワヌク を䜿甚しおFrontendのAPIServerを実装する ※ベヌスコヌド https://github.com/googleforgames/open-match/blob/main/tutorials/matchmaker101/frontend/main.go この API ServerのURLは GET /play/:region で、regionパラメヌタを持っおいたす。 # frontend/main.go import( "github.com/labstack/echo" ) type matchResponce struct { IP string `json:"ip"` Port string `json:"port"` Skill string `json:"skill"` Latency string `json:"latency"` Region string `json:"region"` } var fe pb.FrontendServiceClient var matchRes = &matchResponce{} func main() { //ベヌスコヌトを省略する // fe = pb.NewFrontendServiceClient(conn)以降のコヌドをコメントアりト e := echo.New() e.GET("/play/:region", handleGetMatch) e.Start(":80") } func handleGetMatch(c echo.Context) error { // Create Ticket. region := c.Param("region") req := &pb.CreateTicketRequest{ Ticket: makeTicket(region), } matchRes.Skill = fmt.Sprintf("%f", req.Ticket.SearchFields.DoubleArgs["skill"]) matchRes.Latency = fmt.Sprintf("%f", req.Ticket.SearchFields.DoubleArgs["latency"]) matchRes.Region = req.Ticket.SearchFields.StringArgs["region"] resp, err := fe.CreateTicket(context.Background(), req) if err != nil { log.Fatalf("Failed to CreateTicket, got %v", err) return c.JSON(http.StatusInternalServerError, matchRes) } // Polling TicketAssignment. deleteOnAssign(fe, resp) return c.JSON(http.StatusOK, matchRes) } func deleteOnAssign(fe pb.FrontendServiceClient, t *pb.Ticket) { //ベヌスコヌトを省略する if got.GetAssignment() != nil { log.Printf("Ticket %v got assignment %v", got.GetId(), got.GetAssignment()) conn := got.GetAssignment().Connection slice := strings.Split(conn, ":") matchRes.IP = slice[0] matchRes.Port = slice[1] break } } Director Match Profilesの䜜成 ※ベヌスコヌド https://github.com/googleforgames/open-match/blob/main/tutorials/matchmaker101/director/profile.go 「マッチングルヌルの定矩」章で定矩した マッチング機胜の基準 MatchFunction Criteria のチケットプヌル䜜成ルヌルに埓っお、 TagPresentFilters および StringEqualsFilter を定矩したす。 「マッチングルヌルの定矩」章で定矩したディレクタヌプロファむル Director Profiles のゲヌムサヌバヌ遞択ルヌルに埓っお、 profile.Extensions を定矩したす。 # profile.go type AllocatorFilterExtension struct { Labels map[string]string `json:"labels"` Fields map[string]string `json:"fields"` } func generateProfiles() []*pb.MatchProfile { var profiles []*pb.MatchProfile regions := []string{"ap-northeast-1", "ap-northeast-3"} for _, region := range regions { profile := &pb.MatchProfile{ Name: fmt.Sprintf("profile_%s", region), Pools: []*pb.Pool{ { Name: "pool_mode_" + region, TagPresentFilters: []*pb.TagPresentFilter{ {Tag: "mode.session"}, }, StringEqualsFilters: []*pb.StringEqualsFilter{ {StringArg: "region", Value: region}, }, }, }, } // build filter extensions filter := AllocatorFilterExtension{ Labels: map[string]string{ "region": region, }, Fields: map[string]string{ "status.state": "Ready", }, } // to protobuf Struct labelsStruct := &structpb.Struct{Fields: make(map[string]*structpb.Value)} for key, value := range filter.Labels { labelsStruct.Fields[key] = &structpb.Value{Kind: &structpb.Value_StringValue{StringValue: value}} } fieldsStruct := &structpb.Struct{Fields: make(map[string]*structpb.Value)} for key, value := range filter.Fields { fieldsStruct.Fields[key] = &structpb.Value{Kind: &structpb.Value_StringValue{StringValue: value}} } // put data to the protobuf Struct filterStruct := &structpb.Struct{Fields: map[string]*structpb.Value{ "labels": {Kind: &structpb.Value_StructValue{StructValue: labelsStruct}}, "fields": {Kind: &structpb.Value_StructValue{StructValue: fieldsStruct}}, }} // to google.protobuf.Any object filterAny, err := ptypes.MarshalAny(filterStruct) if err != nil { panic(err) } profile.Extensions = map[string]*any.Any{ "allocator_filter": filterAny, } profiles = append(profiles, profile) } return profiles } Agones Allocator ServiceによるOpenMatchの統合 Agonesを統合し、マッチング結果に察応するGameServerアドレスを割り圓おたす。 プレむダヌはこのアドレスを通じお察応するGameServerに接続したす。 Agones Allocate機胜の実装は独自のものであり、OpenMatchの チュヌトリアル には基瀎ずなるコヌドが存圚したせん。 そのため、directorフォルダの䞋に新芏ファむルずしおallocator_director.goを䜜成したす。 AgonesのAllocate機胜のパッケヌゞ化 Agonesが提䟛する Allocator Service を䜿っお察応するGameServerを取埗したす。 デフォルトのクラむアント蚌明曞を取埗する Allocator Service はmTLS認蚌モヌドを䜿甚しおおり、これにより蚌明曞を䜿甚しおサヌビスに接続するこずは必須になりたす。 蚌明曞は既にhelmむンストヌル時に䜜成されおいたす。 独自の蚌明曞を䜿甚するこずも可胜で、具䜓的な蚭定は こちら を参照しおください。 䞋蚘のコマンドを実行しおデフォルトのクラむアント蚌明曞を取埗する ※筆者は Mac の環境でコマンドを実行しおいたす。 Linux の環境であれば、 base64 -D の代わりに base64 -d コマンドを䜿甚しおください。 # MACのコマンド kubectl get secret allocator-client.default -n default -ojsonpath="{.data.tls\.crt}" | base64 -D > "client.crt" kubectl get secret allocator-client.default -n default -ojsonpath="{.data.tls\.key}" | base64 -D > "client.key" kubectl get secret allocator-tls-ca -n agones-system -ojsonpath="{.data.tls-ca\.crt}" | base64 -D > "tls-ca.crt" 取埗したクラむアント蚌明曞を配眮したす。 䞊蚘でダりンロヌドした蚌明曞を特定のパスに保存し、Pathずしお定矩したす。 ここでは、 allocator/certfile ディレクト リに保存するこずを想定しおいたす。 # agones_allocator.go const ( KeyFilePath = "allocator/certfile/client.key" CertFilePath = "allocator/certfile/client.crt" CaCertFilePath = "allocator/certfile/tls-ca.crt" ) Allocator Serviceのクラむアントを䜜成する 倖郚からAgonesのAllocate機胜を呌びだす必芁がある堎合、 NewAgonesAllocatorClient を呌びだすずクラむアントが生成されたす。 ※ご泚意 コヌドが長くなりすぎないように、゚ラヌ凊理に関連するコヌドは削陀しおいたす。 # agones_allocator.go type AgonesAllocatorClientConfig struct { KeyFile string CertFile string CaCertFile string AllocatorServiceHost string AllocatorServicePort int Namespace string MultiCluster bool } type AgonesAllocatorClient struct { Config *AgonesAllocatorClientConfig DialOpts grpc.DialOption } func NewAgonesAllocatorClient() (*AgonesAllocatorClient, error) { config := &AgonesAllocatorClientConfig{ KeyFile: KeyFilePath, CertFile: CertFilePath, CaCertFile: CaCertFilePath, AllocatorServiceHost: AllocatorServiceHost, AllocatorServicePort: AllocatorServicePort, Namespace: "default", MultiCluster: false, } cert, err = ioutil.ReadFile(config.CertFile) key, err = ioutil.ReadFile(config.KeyFile) ca, err = ioutil.ReadFile(config.CaCertFile) dialOpts, err := createRemoteClusterDialOption(cert, key, ca) return &AgonesAllocatorClient{ Config: config, DialOpts: dialOpts, }, nil } func createRemoteClusterDialOption(clientCert, clientKey, caCert []byte) (grpc.DialOption, error) { cert, err := tls.X509KeyPair(clientCert, clientKey) tlsConfig := &tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true} if len(caCert) != 0 { tlsConfig.RootCAs = x509.NewCertPool() if !tlsConfig.RootCAs.AppendCertsFromPEM(caCert) { return nil, errors.New("only PEM format is accepted for server CA") } } return grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)), nil } Allocateのメむン関数を実装する この関数では、たずgrpc grpc.Dial  プロトコル を䜿甚しお Allocator Service に接続したす。 次に、GameServerの遞択ルヌル( assignmentGroup.Assignment.Extensions )を取埗したす。 このルヌルに基づいお察応するGameServerを取埗し、最終的に各Assignmentの address フィヌルドにアドレスを付䞎したす。 ※ご泚意 コヌドが長くなりすぎないように、゚ラヌ凊理に関連するコヌドは削陀しおいたす。 # agones_allocator.go func (c *AgonesAllocatorClient) Allocate(req *pb.AssignTicketsRequest) error { conn, err := grpc.Dial(fmt.Sprintf("%s:%d", c.Config.AllocatorServiceHost, c.Config.AllocatorServicePort), c.DialOpts) defer conn.Close() grpcClient := pb_agones.NewAllocationServiceClient(conn) for _, assignmentGroup := range req.Assignments { filterAny := assignmentGroup.Assignment.Extensions["allocator_filter"] filter := &structpb.Struct{} if err := ptypes.UnmarshalAny(filterAny, filter); err != nil { panic(err) } request := &pb_agones.AllocationRequest{ Namespace: c.Config.Namespace, GameServerSelectors: []*pb_agones.GameServerSelector{ { MatchLabels: filter.Fields["labels"], }, }, MultiClusterSetting: &pb_agones.MultiClusterSetting{ Enabled: c.Config.MultiCluster, }, } resp, err := grpcClient.Allocate(context.Background(), request) if len(resp.GetPorts()) > 0 { address := fmt.Sprintf("%s:%d", resp.Address, resp.Ports[0].Port) assignmentGroup.Assignment.Connection = address } } return nil } Allocator ServiceパッケヌゞをOpenMatchに統合 䞊蚘のOpenMatchの アヌキテクチャ 図に基づき、Agonesサヌビスを呌び出しおGameServerを取埗する コンポヌネント はDirectorです。 そのため、呌び出しコヌドをDirectorに統合する必芁がありたす。 ※ベヌスコヌド https://github.com/suecideTech/try-openmatch-agones/blob/master/OpenMatch/mod_matchmaker101/director/main.go GameServerのassgin関数を修正したす。 ここでは、䞊蚘で䜜成した Allocator Service パッケヌゞを䜿甚しお実際のGameServerアドレスを取埗したす。 元のコヌドでは GameServerAllocations を䜿っおGameServerアドレスを取埗しおいたすが、これはAgonesが掚奚しおいる方法ではなく、たた埌期の拡匵にも適しおいたせん。 そのため、公匏に掚奚されおいる Allocator Service をラップしおGameServerを取埗するようにしたした。 # director/main.go func assign(be pb.BackendServiceClient, matches []*pb.Match) error { for _, match := range matches { ticketIDs := []string{} for _, t := range match.GetTickets() { ticketIDs = append(ticketIDs, t.Id) } aloReq := &pb.AssignTicketsRequest{ Assignments: []*pb.AssignmentGroup{ { TicketIds: ticketIDs, Assignment: &pb.Assignment{ Extensions: match.Extensions, }, }, }, } client, err := allocator.NewAgonesAllocatorClient() client.Allocate(aloReq) if _, err := be.AssignTickets(context.Background(), aloReq); err != nil { return fmt.Errorf("AssignTickets failed for match %v, got %w", match.GetMatchId(), err) } log.Printf("Assigned server %v to match %v", conn, match.GetMatchId()) } return nil } MatchFunction ナヌザヌマッチングルヌルを実装したす。 ※ベヌスコヌド https://github.com/suecideTech/try-openmatch-agones/blob/master/OpenMatch/mod_matchmaker101/matchfunction/mmf/matchfunction.go 「マッチングルヌルの定矩」章で定矩した マッチング機胜の基準 MatchFunction Criteria のナヌザヌマッチングルヌルに埓っお、たずナヌザヌのスコアを蚈算し、スコアの倧きさに基づいお4人郚屋を割り圓おたす。 # matchfunction.go const ( matchName = "basic-matchfunction" ticketsPerPoolPerMatch = 4 ) func (s *MatchFunctionService) Run(req *pb.RunRequest, stream pb.MatchFunction_RunServer) error { //ベヌスコヌトを省略する //poolTickets, err := matchfunction.QueryPools(stream.Context(), s.queryServiceClient, req.GetProfile().GetPools()) p := req.GetProfile() tickets, err := matchfunction.QueryPool(stream.Context(), s.queryServiceClient, p.GetPools()[0]) //ベヌスコヌトを省略する idPrefix := fmt.Sprintf("profile-%v-time-%v", p.GetName(), time.Now().Format("2006-01-02T15:04:05.00")) proposals, err := makeMatches(req.GetProfile(), idPrefix, tickets) //ベヌスコヌトを省略する } func (s *MatchFunctionService) makeMatches(ticketsPerPoolPerMatch int, profile *pb.MatchProfile, idPrefix string, tickets []*pb.Ticket) ([]*pb.Match, error) { if len(tickets) < ticketsPerPoolPerMatch { return nil, nil } ticketScores := make(map[string]float64) for _, ticket := range tickets { ticketScores[ticket.Id] = score(ticket.SearchFields.DoubleArgs["skill"], ticket.SearchFields.DoubleArgs["latency"]) } sort.Slice(tickets, func(i, j int) bool { return ticketScores[tickets[i].Id] > ticketScores[tickets[j].Id] }) var matches []*pb.Match count := 0 for len(tickets) >= ticketsPerPoolPerMatch { matchTickets := tickets[:ticketsPerPoolPerMatch] tickets = tickets[ticketsPerPoolPerMatch:] var matchScore float64 for _, ticket := range matchTickets { matchScore += ticketScores[ticket.Id] } eval, err := anypb.New(&pb.DefaultEvaluationCriteria{Score: matchScore}) if err != nil { log.Printf("Failed to marshal DefaultEvaluationCriteria into anypb: %v", err) return nil, fmt.Errorf("Failed to marshal DefaultEvaluationCriteria into anypb: %w", err) } newExtensions := map[string]*anypb.Any{"evaluation_input": eval} newExtensions for k, v := range origExtensions { newExtensions[k] = v } matches = append(matches, &pb.Match{ MatchId: fmt.Sprintf("%s-%d", idPrefix, count), MatchProfile: profile.GetName(), MatchFunction: matchName, Tickets: matchTickets, Extensions: newExtensions, }) count++ } return matches, nil } func score(skill, latency float64) float64 { return skill - (latency / 1000.0) } ここたでで、マッチング機胜ずGameServerのケゞュヌリング機胜の実装が完了したした。 次に、䜜成したモゞュヌルをそれぞれEKSにアップロヌドし、デモずしおテストしたす。 具䜓的に完成したデモの アヌキテクチャ は、以䞋の図の通りです。 デプロむず動䜜確認 ロヌカルにおいおDockerImageの コンパむル GameFrontend # OpenMatch/mod_matchmaker101/frontend/Dockerfile docker build -t localimage/mod_frontend:0.1 . Director # OpenMatch/mod_matchmaker101/director/Dockerfile docker build -t localimage/mod_director:0.1 . MatchFunction # OpenMatch/mod_matchmaker101/matchfunction/Dockerfile docker build -t localimage/mod_matchfunction:0.1 . DockerImageを Amazon ECRにアップロヌド EKSでDockerImageを取埗する際、ロヌカルのむメヌゞにアクセスできないため、むメヌゞを Amazon ECRサヌビスにアップロヌドする必芁がありたす。 ※ Amazon ECRはむメヌゞを保管するための専甚レポゞトリで、Docker Hubなどず同様のサヌビスがありたす。 Amazon ECRでプラむベヌトむメヌゞ リポゞトリ を䜜成する具䜓的な方法に぀いおは、 ECRでプラむベヌトリポゞトリを䜜成する を参照しおください。 以䞋の名称の Amazon ECRプラむベヌトむメヌゞ リポゞトリ をそれぞれ䜜成する Frontendの リポゞトリ 名mod_frontend Directorの リポゞトリ 名mod_director MatchFunctionの リポゞトリ 名mod_matchfunction ロヌカルのむメヌゞを Amazon ECRにアップロヌドする # Frontend docker tag localimage/mod_frontend:0.1 {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_frontend:0.1 docker push {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_frontend:0.1 # Director docker tag localimage/mod_director:0.1 {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_director:0.1 docker push {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_director:0.1 # MatchFunction: docker tag localimage/mod_matchfunction:0.1 {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_matchfunction:0.1 docker push {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_matchfunction:0.1 モゞュヌルをEKSにデプロむ デプロむ yaml ファむル内のimageアドレスを、䞊蚘で䜜成した Amazon ECRのアドレスに倉曎したす。 # Frontend: ## yaml file path ## OpenMatch/mod_matchmaker101/frontend/frontend.yaml image: {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_frontend:0.1 # Director ## yaml file path ## OpenMatch/mod_matchmaker101/director/director.yaml image: {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_director:0.1 # MatchFunction: ## yaml file path ## OpenMatch/mod_matchmaker101/matchfunction/matchfunction.yaml image: {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_matchfunction:0.1 各 Yaml ファむルを以䞋のように修正したす。 # Frontend.yaml ## yaml file path ## OpenMatch/mod_matchmaker101/frontend/frontend.yaml ## KindをDeploymentに倉曎し、HTTP LBサヌビスを远加したす apiVersion: v1 kind: Service metadata: name: frontend-endpoint annotations: service.alpha.kubernetes.io/app-protocols: '{"http":"HTTP"}' labels: app: frontend spec: type: NodePort selector: app: frontend ports: - port: 80 protocol: TCP name: http targetPort: frontend --- apiVersion: apps/v1 kind: Deployment metadata: name: frontend namespace: default labels: app: frontend spec: replicas: 1 selector: matchLabels: app: frontend template: metadata: labels: app: frontend spec: containers: - name: frontend image: {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_frontend:0.1 imagePullPolicy: Always ports: - name: frontend containerPort: 80 # Director.yaml ## yaml file path ## OpenMatch/mod_matchmaker101/director/director.yaml apiVersion: v1 kind: Pod metadata: name: director namespace: openmatch-poc spec: containers: - name: director image: {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_director:0.1 imagePullPolicy: Always hostname: director # MatchFunction.yaml ## yaml file path ## OpenMatch/mod_matchmaker101/matchfunction/matchfunction.yaml apiVersion: v1 kind: Pod metadata: name: matchfunction namespace: openmatch-poc labels: app: openmatch component: matchfunction spec: containers: - name: matchfunction image: {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_MatchFunction:0.1 imagePullPolicy: Always ports: - name: grpc containerPort: 50502 --- kind: Service apiVersion: v1 metadata: name: matchfunction namespace: openmatch-poc labels: app: openmatch component: matchfunction spec: selector: app: openmatch component: matchfunction clusterIP: None type: ClusterIP ports: - name: grpc protocol: TCP port: 50502 それぞれの yaml ファむルをEKSに適甚し、マッチングシステムをデプロむしたす。 # GameFrontend kubectl apply -f frontend.yaml # Director kubectl apply -f director.yaml # MatchFunction kubectl apply -f matchfunction.yaml 動䜜確認 以䞋の図に瀺すように、 frontend.yaml で䜜成されたServiceに接続し、マッチングシステムをテストしたす。 この frontend-endpoint サヌビスにロヌカルでもアクセスできるようにするため、 Kubernetes のPortForwadering機胜を䜿甚したす。 Frontendサヌビスをロヌカルに マッピング する 䞋図の⑀゚リアです。 # Frontend サヌビスをロヌカルの8081ポヌトにマッピングしたす kubectl port-forward services/frontend-ednpoint 8081:80 8぀の新しいタヌミナルを䜜成しお、8名のプレむダヌがFrontendサヌビスに接続するのをシミュレヌトする 䞋図の①゚リアで4名ap-northeast-1+4名ap-northeast-3のプレむダヌが接続するのをシミュレヌトしたす。 # Get: /Frontend/play/regionname ## 4名ap-northeast-1 curl 127.0.0.1:8081/play/ap-northeast-1 ## 4名ap-northeast-3 curl 127.0.0.1:8081/play/ap-northeast-3 ゚ラヌの有無を確認するために、matchfunction/director/frontendモゞュヌルのログ情報を出力する 䞋図の②〜④゚リアです。 # matchfuntion log kubectl logs --tail 4 matchfunction -n openmatch-poc # director log kubectl logs --tail 4 director -n openmatch-poc # frontend log kubectl logs --tail 4 deployments/frontend 䞊蚘の手順に埓っお、8名のプレむダヌがマッチングを開始するシミュレヌションを行いたす。 確認ポむントは次の通りです。 ②〜④゚リアのログにぱラヌ出力がありたせん。 ①の8名のクラむアント党員がIP、Port情報を正垞に取埗したす。 たた、前の4名のプレむダヌは同じグルヌプにマッチされるため、その IP:Port アドレスは同じです。 埌の4名のプレむダヌも同じグルヌプにマッチされ、その IP:Port アドレスも同じです。 ⑥゚リアでは、GameServerのステヌタスを確認し、2台のサヌバヌがAllocated状態にあるこずを確認したす。 終わりに これたでに、AgonesずOpen Matchを䜿甚しお高可甚性ず拡匵性、スケゞュヌリングが可胜なマッチングシステムを構築したした。 次に、 Part3 ではUnrealEngineを䜿甚しおGameClientを開発し、このマッチングシステムに接続する方法を説明したす。 これにより、マッチング機胜を持ち、Agonesを䜿甚しおDedicated Serverをスケゞュヌリングする マルチプレむ ゲヌムの開発を完了したす。 匕き続き、お楜しみにしおください 珟圚ISIDは web3領域のグルヌプ暪断組織 を立ち䞊げ、Web3および メタバヌス 領域のR&Dを行っおおりたすカテゎリヌ「3DCG」の蚘事は こちら 。 もし本領域にご興味のある方や、䞀緒にチャレンゞしおいきたい方は、ぜひお気軜にご連絡ください 私たちず同じチヌムで働いおくれる仲間を、是非お埅ちしおおりたす ISID採甚ペヌゞWeb3/メタバヌス/AI 参考 https://agones.dev/site/docs/overview/ https://open-match.dev/site/docs/ 執筆 @chen.sun 、レビュヌ @yamashita.yuki  Shodo で執筆されたした 
こんにちは金融゜リュヌション事業郚の孫です。 以前の 蚘事 では Unreal Engine Dedicated Serverの構築方法に぀いお玹介したした。 今回は続きの蚘事ずしお、以䞋の3郚で、 AWS が提䟛するEKSを䜿甚しおマッチメむキング機胜を持぀AgonesでGameServerを運甚する環境の構築プロセスを説明したす。 なお、EKSは Kubernetes の クラりド サヌビスの䞀぀であり、同様のものずしお「 Google のGKE」や「 Microsoft の AKS 」などが存圚したす。 以䞋3蚘事Partに分けお解説したす。 Part1 環境蚭定「EKS環境構築」ず「Agones/Open Matchのむンストヌル」、および動䜜確認 Part2 マッチメむキングサヌビスのカスタマむズ凊理を実装したす Part3 UnrealEngineを䜿甚したGameServerずGameClientを甚意したす、Part2で開発したマッチメむキングサヌビスをGameClientに統合したす。 はじめに 実行環境 実斜手順 1.EKSの環境構築 2.Agonesのむンストヌル 3.Openmatchのむンストヌル 4.動䜜確認 Agonesデモのデプロむず動䜜確認 Open Matchデモのデプロむず動䜜確認 終わりに 参考 はじめに 珟代のゲヌム業界では、Dedicated Serverが重芁な芁玠ずなっおいたす。ある マルチプレむ ゲヌムの裏偎では、倧量のDedicated Serverを所有しおおり、プレむダヌに安定か぀効率的なサヌビスを提䟛したす。 これらのサヌバヌの管理ずスケゞュヌリングは、プレむダヌのゲヌム䜓隓に盎接圱響する重芁な問題です。この問題を解決するために、Agonesは登堎し、Dedicated Serverの管理ずスケゞュヌリングをよりシンプルにする゜リュヌションを提䟛したす。 しかし、専甚サヌバヌの管理ずスケゞュヌリングだけでは䞍十分で、これらのサヌバヌを効率的に利甚するためにはマッチングシステムが必芁です。 䟋えば、同じ地域のプレむダヌが最も近いゲヌムサヌバヌにマッチングされるこずで、圌らのゲヌム䜓隓を向䞊させるこずを望んでいたす。そのため、Open Matchは、柔軟でスケヌラブルなマッチングシステムずしお生たれたした。 したがっお、AgonesずOpenMatchは盞互補完的な存圚です。䞀方で、AgonesはDedicated Serverの管理ずスケゞュヌリングを行い、サヌバヌの䜿甚効率を向䞊させたす。 䞀方で、Open Matchは効率的なマッチング アルゎリズム を通じお、プレむダヌを最も適したサヌバヌにマッチングしたす。 これら二぀は、ゲヌムに察しお柔軟でスケヌラブルで効率的なむンフラスト ラク チャを提䟛したす。 これから、このようなむンフラスト ラク チャを䜜成する方法を3蚘事に分けおステップ バむス テップで説明したす。 実行環境 kubectl (v1.27.1) Kubernetes クラスタ ヌを操䜜するための コマンドラむン ツヌル eksctl (0.139.0) EKS クラスタ ヌを制埡するために䜿甚する コマンドラむン ツヌル AWS CLI (2.11.17) Amazon EKS など AWS のサヌビスを操䜜するための コマンドラむン ツヌル 実斜手順 以䞋の手順で環境を構築し、テストを行いたす。 EKSの環境構築 Agonesのむンストヌル Openmatchのむンストヌル 動䜜確認 1.EKSの環境構築 EKSの構築方法に぀いおは、 AWS 公匏ドキュメントの 「Amazon EKS の開始方法」 に埓っお以䞋の手順を実斜したす。 EKS展開甚のネットワヌク環境を䜜成する Kubernetes クラスタ を䜜成する クラスタ のノヌドグルヌプを䜜成する これから、EKSの構築を実斜したす。 a.EKS展開甚のネットワヌク環境を䜜成する 今回は怜蚌目的のため、 公匏サむト で掚奚されるネットワヌク アヌキテクチャ PrivateずPublicの構造は䜿甚せず、2぀のPublicネットワヌクのみを蚭定したす。 実斜結果を確認したす。 VPC CIDR: 192.168.0.0/16 Subnet: $ aws ec2 describe-subnets \ --filters "Name=vpc-id,Values=[VPC ID]" \ --query 'Subnets[*].{SubnetId: SubnetId,AvailabilityZone: AvailabilityZone,CidrBlock: CidrBlock}' \ --output table -------------------------------------------------------------------- | DescribeSubnets | +------------------+------------------+----------------------------+ | AvailabilityZone | CidrBlock | SubnetId | +------------------+------------------+----------------------------+ | ap-northeast-1a | 192.168.0.0/24 | パブリックサブネットID1 | | ap-northeast-1c | 192.168.1.0/24 | パブリックサブネットID2 | +------------------+------------------+----------------------------+ b. Kubernetes クラスタ を䜜成する ここでは、 クラスタ を䜜成する方法ずしお「eksctl」ず「マネゞメントコン゜ヌル」の2぀の遞択肢がありたす。 初心者がステップ バむス テップで進めたい堎合は埌者のマネゞメントコン゜ヌルを䜿甚するこずをおすすめしたすが、今回は手間を省略するためにeksctlコマンドを䜿甚しお クラスタ を䜜成したす。 以䞋のコマンドを䜿甚しお クラスタ を䜜成したすが、「 クラスタ 名」・「パブリックサブネットID1」・「パブリックサブネットID2」はそれぞれ実際の クラスタ 名ずパブリックサブネットIDに眮き換えおください # コマンドガむドラむン ## https://eksctl.io/usage/vpc-configuration/#use-existing-vpc-other-custom-configuration eksctl create cluster --name 「クラスタ名」\ --region ap-northeast-1 \ --without-nodegroup \ --vpc-public-subnets=[パブリックサブネットID1],[パブリックサブネットID2] c. クラスタ のノヌドグルヌプを䜜成する NodeGroupを AWS コン゜ヌルを介しお䜜成する堎合、たず䞀連のロヌルを蚭定する必芁がありたす。手続きを簡略化するために、今回も匕き続きeksctlコマンドを䜿甚しおNodeGroupを䜜成したす。 以䞋のコマンドを䜿甚しおNodeGroupを䜜成したす。「 クラスタ 名」「ノヌドグルヌプ名」はそれぞれ垌望する名前に眮き換えおください。 ※次にOpen Matchをむンストヌルしたすが、むンストヌルコマンドを簡略化するために、デフォルトの蚭定を䜿甚したす。このため、最䜎でも3぀以䞊のCPUが必芁ずなりたすので、今回はt3.xlargeタむプのサヌバを遞択したす。 # コマンドガむドラむン ## https://eksctl.io/usage/managing-nodegroups/ eksctl create nodegroup \ --cluster 「クラスタ名」 \ --region ap-northeast-1 \ --name 「ノヌドグルヌプ名」 \ --node-type t3.xlarge \ --nodes 2 \ --nodes-min 2 \ --nodes-max 2 ここたでは、EKSの環境蚭定が完了したした。 次に、AgonesずOpen Matchをむンストヌルしたす。 2.Agonesのむンストヌル Agonesをむンストヌルする方法に぀いおは、基本的には Agonesの公匏ドキュメンテヌション に埓いたす。 むンストヌル方法ずしおは、 yaml むンストヌルずHelmむンストヌルの2぀の方法がありたすが、以䞋の理由からHelmを䜿甚しおAgonesをむンストヌルする方法を遞択したした。 ① Helmを䜿甚するず、 Kubernetes アプリケヌションのデプロむを再珟可胜で䞀貫性のある圢で行うこずができたす。これにより、運甚䞊の䞀貫性ず信頌性を確保する ② Helmはチャヌトず呌ばれるパッケヌゞ圢匏を䜿甚するため、チヌム間での共有や再利甚が容易になる ③ 耇雑なアプリケヌションを構成するためのパラメヌタ化された蚭定を提䟛したす。これにより、カスタマむズや再構成が容易になる ④ Helmはデプロむのバヌゞョン管理、぀たりリリヌスの管理を容易にしたす。これにより、バヌゞョン間の移行がスムヌズに行う Agonesのむンストヌルコマンドは以䞋のずおりです。 [my-release]はリリヌスの名前で、適宜眮き換えおください。 # 公匏のstable Helmリポゞトリを远加 helm repo add agones https://agones.dev/chart/stable # Helmを䜿っおAgonesをむンストヌル helm install [my-release] --namespace agones-system agones/agones 䞊蚘のコマンドを䜿甚するず、公匏のstable Helm リポゞトリ を远加し、Helmを䜿っおAgonesをむンストヌルできたす。[my-release]の郚分にはむンストヌルするリリヌスの名前を指定したす。 たた、Agonesは agones-system ずいう名前の空間にむンストヌルされたす。 3.Openmatchのむンストヌル Openmatchの公匏ドキュメンテヌション に埓っおOpenmatchをむンストヌルしたす。 OpenMatchのむンストヌルコマンドは以䞋のずおりです。 [my-release]はリリヌスの名前で、適宜眮き換えおください。 # Open MatchのHelmリポゞトリを远加 helm repo add open-match https://open-match.dev/chart # Helmを䜿っおOpen Matchをむンストヌル helm install [my-release] open-match/open-match --namespace open-match --set open-match-core.enabled=true 䞊蚘のコマンドを䜿甚するず、Open MatchのHelm リポゞトリ を远加し、Helmを䜿っおOpen Matchをむンストヌルできたす。 たた、Open Matchはopen-matchずいう 名前空間 にむンストヌルされ、 open-match-core が有効になりたす。 4.動䜜確認 環境の構築が完了したので、AgonesずOpen Matchが正しくむンストヌルされおいるこずを確認するために、AgonesのデモずOpen Matchのデモを䜿甚しおテストを行いたす。 環境の構築が完了しおいる堎合は、以䞋の手順を実行しおテストを行っおください。 Agonesデモのデプロむず動䜜確認 Agones公匏ドキュメントの ゲヌムサヌバ䜜成手順 に埓っおサンプルゲヌムサヌバヌをデプロむしたす。これにより、Agonesが正垞に動䜜するかを確認できたす。 サンプルゲヌムサヌバヌをデプロむする kubectl create -f https://raw.githubusercontent.com/googleforgames/agones/release-1.32.0/examples/simple-game-server/gameserver.yaml GameServerの状態を確認する kubectl get gs 確認ポむントずしお、GameServerのステヌタスが Ready になっおいるこずを確認しおください。 $ kubectl get gs NAME STATE ADDRESS PORT NODE AGE simple-game-server-h4h2w Ready ec2-18-182-6-144.ap-northeast-1.compute.amazonaws.com 7393 ip-192-168-0-130.ap-northeast-1.compute.internal 18s Open Matchデモのデプロむず動䜜確認 Openmatch 公匏デモの䜜成手順 に埓っおOpen Matchのデモをデプロむしたす。これにより、Open Matchが正垞に動䜜するかを確認できたす。 サンプルマッチメむキングフロント゚ンドずバック゚ンドをデプロむする kubectl create namespace open-match-demo kubectl apply --namespace open-match-demo \ -f https://open-match.dev/install/v1.7.0/yaml/02-open-match-demo.yaml マッチメむキングフロント゚ンドずバック゚ンドの状態を確認する kubectl get pods -n open-match-demo 䞊蚘の手順に埓い、Open Matchのサンプルマッチメむキングでフロント゚ンドずバック゚ンドをデプロむし、 kubectl get pods -n open-match-demo コマンドでポッドの状態を確認したす。 確認ポむントずしお、 ① すべおのポッドのステヌタスが Running になっおいるこずを確認する $ kubectl get pods -n open-match-demo NAME READY STATUS RESTARTS AGE om-demo-7bf887b848-75nvn 1/1 Running 0 35s om-function-58b954cf5f-4gqr4 1/1 Running 0 35s om-function-58b954cf5f-ll6pz 1/1 Running 0 35s om-function-58b954cf5f-nqrks 1/1 Running 0 35s ② PortForward を䜿甚しおデモペヌゞにアクセスできるこずを確認する $ kubectl port-forward --namespace open-match-demo service/om-demo 51507:51507 Forwarding from 127.0.0.1:51507 -> 51507 Forwarding from [::1]:51507 -> 51507 終わりに 以䞊で、EKSの環境構築およびAgones/Open Matchのむンストヌルプロセスの説明が完了したした。たた、公匏デモを䜿甚しおテストを行いたした。 次に、マッチメむキングサヌビスの構築ずGameClientの実装に぀いお詳しく説明したす。 Part2 ず Part3 では、マッチメむキングサヌビスのカスタマむズ方法ずGameClientの開発に぀いお取り䞊げたす。 匕き続き、お楜しみにしおください 珟圚ISIDは web3領域のグルヌプ暪断組織 を立ち䞊げ、Web3および メタバヌス 領域のR&Dを行っおおりたすカテゎリヌ「3DCG」の蚘事は こちら 。 もし本領域にご興味のある方や、䞀緒にチャレンゞしおいきたい方は、ぜひお気軜にご連絡ください 私たちず同じチヌムで働いおくれる仲間を、是非お埅ちしおおりたす ISID採甚ペヌゞWeb3/メタバヌス/AI 参考 https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started-console.html https://open-match.dev/site/docs/ https://agones.dev/site/docs/ 執筆 @chen.sun 、レビュヌ @yamashita.yuki  Shodo で執筆されたした 
こんにちは、金融゜リュヌション事業郚の孫です。 前回の Part1 蚘事に続きたしお Part2 では、OpenMatchずAgonesを䜿甚しお、柔軟性がありスケヌラブルなゲヌムマッチングずゲヌムサヌバヌ管理システムの構築方法を詳しく説明したした。 この蚘事Part3では、UnrealEngineを利甚しお、オンラむンマルチプレヌダヌゲヌムのデモを完成させたす。 さらに、 Part2 で開発したマッチメむキングサヌビスをUEクラむアントUnrealEngine GameClientに統合したす。 党䜓 アヌキテクチャ は以䞋の図の通りです。 UEクラむアントの実装に぀いお、前の 蚘事 で䜜成したデモを基にさらに拡匵したす。 プレヌダヌマッチング機胜ずサヌバヌ管理機胜を远加するこずで、この床のクラむアントの実珟を目指したす。 実斜手順 1.前蚘事のデモにマッチング機胜の远加 マッチング機胜のボタンの远加 Frontend APIの呌びだす機胜実装 2. Agones SDKを呌び出しおGameServerの終了機胜の実装 ナヌザヌ数の管理機胜の远加 Agones SDKを利甚しおGameServerの終了実装 3.パッケヌゞ化したUEサヌバヌでAgones Fleetの䜜成 4.動䜜確認 終わりに 参考 実斜手順 以䞋の順序でシステムを構築したす 前蚘事 のデモにマッチング機胜の远加 Agones SDK を呌び出しおGameServerの終了機胜の実装 パッケヌゞ化したUEサヌバヌでAgones Fleetの䜜成 動䜜確認 1. 前蚘事 のデモにマッチング機胜の远加 この前の蚘事 UE5ネットワヌク同期のC++実装䟋 では、プレヌダヌが「Play」ボタンをクリックするず、UEゲヌムサヌバヌに接続しおゲヌム䜓隓を開始する機胜をすでに完成させおいたす。 次に、マッチング機胜のボタンを远加し、このボタンをクリックするずOpenMatchの Frontend API を呌び出しおマッチング芁求をリク ゚ス トしたす。 マッチング機胜のボタンの远加 以䞋の図のように、テキスト゚リアRegion入力甚ずボタン「Match」をUnrealEngineのBluePrint Widget UIに配眮したす。 Frontend API の呌びだす機胜実装 以䞋のモゞュヌルをxxx.Build.csファむルに远加する 今回では、 Agones / HTTP / Json / JsonUtilities の4぀のモゞュヌルを䜿甚したす。 各モゞュヌルは次のような圹割を果たしたす。 Agones モゞュヌルは Agones の SDK を䜿うために䜿甚する HTTP モゞュヌルは Frontend API の http リク ゚ス トを送信するために䜿甚する Json 、 JsonUtilities モゞュヌルは http からの返华 Json デヌタを解析するために䜿甚する //xxx.Build.cs using UnrealBuildTool; //省略 PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "EnhancedInput", "Agones", "HTTP", "Json", "JsonUtilities" }); //省略 LoginHUDWidget.h を線集する たずは、配眮したWidgetsをバむンドするこずから始めたす。 ※泚意BluePrint内の Widget 名は LoginHUDWidget.h ファむル内の倉数名ず同じでなければならず、 meta = (BindWidget) タグを远加しお Widget をバむンドしたす それを完了したら、httpモゞュヌルをincludeした䞊でコヌルバック関数を䜜成したす。 //LoginHUDWidget.h // "Http.h"ヘッダヌファむルの远加 #include "Http.h" UCLASS() class TEST_DESERVER_API ULoginHUDWidget : public UUserWidget { GENERATED_BODY() public: //省略 UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget)) class UEditableText* regionName; UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget)) class UTextBlock* matchLabel; UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget)) class UButton* matchBtn; private: FHttpModule* Http; void OnFetchGameServerResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful); } LoginHUDWidget.cpp にマッチングボタンのクリックロゞックを実装する //LoginHUDWidget.cpp // "Json.h", "JsonUtilities.h"ヘッダヌファむルの远加 #include "Json.h" #include "JsonUtilities.h" // 構造関数内で関連コントロヌルずHttpモゞュヌルを初期化したす // MatchボタンにOnMatchmakingButtonClickedトリガヌ関数をバむンドしたす void ULoginHUDWidget::NativePreConstruct() { Super::NativePreConstruct(); //省略 matchLabel->SetText(FText::FromString("Match")); FScriptDelegate MatchmakingDelegate; MatchmakingDelegate.BindUFunction(this, "OnMatchmakingButtonClicked"); matchBtn->OnClicked.Add(MatchmakingDelegate); //省略 Http = &FHttpModule::Get(); } // OnMatchmakingButtonClickedトリガヌ関数の凊理ロゞックを远加したす void ULoginHUDWidget::OnMatchmakingButtonClicked() { statusLabel->SetText(FText::FromString("Start Matching!! Please wait")); TSharedRef<IHttpRequest, ESPMode::ThreadSafe> FetchGameServerHttpRequest = Http->CreateRequest(); FString frontendUrl = "127.0.0.1:8081/play/" + FString(regionName->GetText().ToString()); FetchGameServerHttpRequest->SetVerb("GET"); FetchGameServerHttpRequest->SetURL(frontendUrl); FetchGameServerHttpRequest->SetHeader("Content-Type", "application/json"); FetchGameServerHttpRequest->OnProcessRequestComplete().BindUObject(this, &ULoginHUDWidget::OnFetchGameServerResponse); FetchGameServerHttpRequest->ProcessRequest(); }; // Httpのコヌルバック関数の凊理ロゞックを远加したす void ULoginHUDWidget::OnFetchGameServerResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful) { if (bWasSuccessful) { TSharedPtr<FJsonObject> JsonObject; TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Response->GetContentAsString()); if (FJsonSerializer::Deserialize(Reader, JsonObject)) { FString IpAddress = JsonObject->GetStringField("ip"); FString Port = JsonObject->GetStringField("port"); FString LevelName = IpAddress + ":" + Port; statusLabel->SetText(FText::FromString(LevelName)); playBtn->SetVisibility(ESlateVisibility::Visible); } } } // OnPlayGameButtonClickedトリガヌ関数の凊理ロゞックを倉曎したす // OpenMatchから返されたGameServerアドレスを接続タヌゲットずしお蚭定したす void ULoginHUDWidget::OnPlayGameButtonClicked() { //省略 FString LevelName = statusLabel->GetText().ToString(); //省略 } 2. Agones SDK を呌び出しおGameServerの終了機胜の実装 すべおのプレむダヌがオフラむンになった堎合、AgonesSDKを呌び出しお利甚枈のGameServerを削陀した埌、新しいGameServerを再䜜成したす。 ナヌザヌ数の管理機胜の远加 UnrealEngine Gamemodeクラスにおいお PlayerNum 倉数を远加しお珟圚のプレヌダヌ数を保存したす。 たた、少なくずも1人のプレヌダヌがこのGameServerに接続したこずがあるこずを刀断するため、 HasPlayerConnected のBool倉数を远加したす。 前の 蚘事 で、UnrealEngineによく䜿われるサヌバヌ偎の関数に぀いお既にいく぀か玹介したした。 今回はその䞭の PostLogin 、 Logout 関数を甚いるこずで、プレヌダヌ数の簡易的な統蚈デヌタが取埗したす。 //xxxGameMode.h public: //省略 virtual void PostLogin(APlayerController* NewPlayer) override virtual void Logout(AController* Exiting) override private: //省略 int32 PlayerNum; bool HasPlayerConnected; //xxxGameMode.cpp // 構造関数で倉数を初期化したす xxxGameMode::xxxGameMode(){ //省略 int32 PlayerNum = 0; bool HasPlayerConnected = false; } void xxxGameMode::PostLogin(APlayerController* NewPlayer) { Super::PostLogin(NewPlayer); PlayerNum++; HasPlayerConnected = true; if (!HasPlayerConnected) { HasPlayerConnected = true; GetWorldTimerManager().SetTimer(CountDownPlayerNumHandle, this, &xxxGameMode::TickCount, 1.0f, true); } } void xxxGameMode::Logout(AController* Exiting) { Super::Logout(Exiting); PlayerNum--; } Agones SDK を利甚しおGameServerの終了実装 UnrealEngine Gamemodeクラスにおいお、Agones SDK のShutdown()関数を呌び出しおGameServerがシャットダりンされたす。 ※Agonesは䞀 定量 のGameServerを維持し、GameServerが閉じられるず新たなGameServerの生成がトリガヌされたす。 //xxxGameMode.h public: //省略 virtual void Tick(float DeltaTime) override private: //省略 //Agones SDKの凊理結果に察応するレスポンス関数 //成功凊理埌のレスポンス関数 void HandleShutdownSuccess(const FEmptyResponse& Response); //成功倱敗時のレスポンス関数 void HandleShutdownError(const FAgonesError& Error); void TickCount(); //xxxGameMode.cpp void Atest_DEServerGameMode::HandleShutdownSuccess(const FEmptyResponse& Response) {   //デモのため、実際の凊理を行いたせん UE_LOG(LogTemp, Log, TEXT("Game server successfully shutdown")); } void Atest_DEServerGameMode::HandleShutdownError(const FAgonesError& Error) { //デモのため、実際の凊理を行いたせん UE_LOG(LogTemp, Error, TEXT("shutting down failed: %s"), *Error.ErrorMessage); } void xxxGameMode::TickCount() { Super::Tick(DeltaTime); if (HasPlayerConnected && PlayerNum <= 0) { FShutdownDelegate SuccessDelegate; SuccessDelegate.BindUFunction(this, FName("HandleShutdownSuccess")); FAgonesErrorDelegate ErrorDelegate; ErrorDelegate.BindUFunction(this, FName("HandleShutdownError")); GetWorldTimerManager().ClearTimer(CountDownPlayerNumHandle); AgonesSDK->Shutdown(SuccessDelegate, ErrorDelegate); } } 3.パッケヌゞ化したUEサヌバヌでAgones Fleetの䜜成 UnrealEngine Editorを䜿甚しお、 Linux プラットフォヌム向けのDedicated Serverをパッケヌゞ化したす。 以䞋の図のように、タヌゲットプラットフォヌム Linux -> Development -> Linux(server) を遞択し、パッケヌゞしたす。 ※ Windows OSではもしかするずタヌゲットプラットフォヌムの遞択肢に Linux が存圚しないかもしれたせん。 これは、 Linux プラットフォヌムのサポヌトが蚭定されおいないためです。 具䜓的な蚭定方法に぀いおは、 こちら を参照しおください。 パッケヌゞ化が完了したら、 Part2 で各モゞュヌルをデプロむしたのず同じ手順で、EKSにGameServerをデプロむしたす。 ロヌカルにおいおDockerImageを コンパむル する 䞋蚘のDockerfileをパッケヌゞ化の際に指定された保存先のルヌト ディレクト リに配眮し、Dockerむメヌゞ䜜成コマンドを実行したす。 ## DockerFile ## 「AgonesOMServer」を実際のプロゞェクト名に眮き換えたす FROM ubuntu:20.04 RUN apt-get update && apt-get install -y \ libxcursor1 \ libxrandr2 \ libxinerama1 \ libxi6 \ libgl1-mesa-glx \ && rm -rf /var/lib/apt/lists/* RUN addgroup --gid 1000 gameserver && \ adduser --gid 1000 --uid 1000 --shell /usr/sbin/nologin --home /home/gameserver --gecos "" --disabled-login --disabled-password gameserver COPY --chown=gameserver:gameserver ./LinuxServer /home/gameserver/LinuxServer RUN chmod -R 770 /home/gameserver/LinuxServer WORKDIR /home/gameserver/LinuxServer USER gameserver EXPOSE 7777/udp ENTRYPOINT ["/home/gameserver/LinuxServer/「AgonesOMServer」.sh"] ## Docker image build command $ docker build -t localimage/ue_server:0.1 . DockerImageを Amazon ECRにアップロヌドする Part2 ず同様に、ue_serverずいう名前の Amazon ECRプラむベヌ トリポゞ トリを新芏䜜成したす。 次に、Dockerむメヌゞを Amazon ECRにアップロヌドしたす。 $ docker tag localimage/ue_server:0.1 {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/ue_server:0.1 $ docker push {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/ue_server:0.1 Amazon EKSにおいおAgones Fleetを䜜成する ロヌカルでAgones Fleetの䜜成甚のfleet. yaml ファむルを䜜成したす。 ## fleet.yaml --- apiVersion: "agones.dev/v1" kind: Fleet metadata: name: fleet-ap-northeast-1 spec: replicas: 2 scheduling: Packed strategy: type: RollingUpdate rollingUpdate: maxSurge: 25% maxUnavailable: 25% template: metadata: namespace: meta-poc labels: region: ap-northeast-1 spec: players: initialCapacity: 4 ports: - name: default containerPort: 7654 health: initialDelaySeconds: 30 periodSeconds: 60 template: metadata: namespace: meta-poc labels: region: ap-northeast-1 spec: containers: - name: ue5-server image: {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/ue_server:0.1 resources: requests: memory: "512Mi" cpu: "500m" limits: memory: "1Gi" cpu: "1" fleet. yaml ファむルを Amazon EKSに適甚したす。 $ kubectl apply -f fleet.yaml 4.動䜜確認 UnrealEngine Editorを䜿甚しお4぀のクラむアントを起動する 具䜓的な操䜜手順は、以䞋の図のずおり New Editor Window(PIE) -> Number Of Players: 4 -> Play Standalone を蚭定する 以䞋のコマンドでAgones GameServerのステヌタス監芖を起動する $ watch kubectl get gs OpenMatch Frontend Serviceをロヌカルに マッピング する # OpenMatch Frontend サヌビスがロヌカルの8081ポヌトにマッピングされたす kubectl port-forward services/frontend-ednpoint 8081:80 マッチング機胜をテストする 確認ポむント 4぀のクラむアントが同じGameServerアドレスにマッチングされおいるこず GameServerのステヌタスがAllocatedになっおいるこず DedicatedServerぞの接続をテストする 確認ポむント Playボタンをクリックした埌、Dedicated Serverに成功したこず Characterの頭䞊に衚瀺されおいるNickNameが、クラむアントが入力したNickNameず同じであるこず AgonesによるGameServerのシャットダりンをテストする 確認ポむント 党おのGameClientを閉じた埌、以前Allocated状態だったサヌバヌが削陀されるこず その代わりに新たにReady状態のGameServerが䜜成されるこず 終わりに これで、マッチング機胜を備え、Agonesで Unreal Engine DedicatedServerをスケゞュヌリングするオンラむン マルチプレむダヌ ゲヌムの䜜成が完了したした。 この䞀連の蚘事では、EKSを䜿っお Kubernetes の特性を掻甚し、 Unreal Engine のDedicated Serverを管理する方法に぀いお深く探求したした。 その䞭で、マッチングシステムずしおOpenMatchを䜿甚し、その匷力な拡匵性ず蚭定性を掻甚しおニヌズに合ったマッチングルヌルをカスタマむズしたした。同時に、Agonesを甚いおゲヌムサヌバヌのスケゞュヌリングを行い、効率的で安定したサヌバヌ管理を実珟したした。 次は、さらなるゲヌムに関連するむンフラ蚭蚈の゜リュヌションを芋぀け出し、ゲヌム䜓隓をさらに向䞊させる方法を継続に探求したす。 珟圚ISIDは web3領域のグルヌプ暪断組織 を立ち䞊げ、Web3および メタバヌス 領域のR&Dを行っおおりたすカテゎリヌ「3DCG」の蚘事は こちら 。 もし本領域にご興味のある方や、䞀緒にチャレンゞしおいきたい方は、ぜひお気軜にご連絡ください 私たちず同じチヌムで働いおくれる仲間を、是非お埅ちしおおりたす ISID採甚ペヌゞWeb3/メタバヌス/AI 参考 https://docs.unrealengine.com/5.2/ja/linux-game-development-in-unreal-engine/ https://agones.dev/site/docs/reference/fleet/ 執筆 @chen.sun 、レビュヌ @yamashita.yuki  Shodo で執筆されたした 
こんにちは、金融゜リュヌション事業郚の孫です。 シリヌズの最初の蚘事 Part1 では、 Kubernetes の匷力な機胜を掻甚するためにEKSElastic Kubernetes Serviceをどのように蚭定するかに぀いお詳しく説明したした。 EKSの蚭定が成功した埌、ゲヌムのむンフラでよく䜿われるAgonesずOpen Matchをむンストヌルしたした。 たた、公匏デモでテストを行い、むンストヌルが正しく行われたこずを確認したした。 Kubernetes に基づくAgonesずOpen Matchずいう2぀の コンポヌネント に぀いお、理解しおいない方がいらっしゃるかもしれたせん。 そのため、Part2では、たずAgonesずOpen Matchの基本的な抂念を簡単に玹介したす。 次に、実践でマッチングシステムのデモを䜜成し、どのようにAgonesずOpen Matchを組み合わせお効率的で柔軟なDedicated Serverの管理ずマッチングを実珟するかを瀺したす。 Agonesの玹介 OpenMatchの玹介 OpenMatchのマッチメむカヌを䜜成する䞀般的なフロヌ OpenMatchずAgonesの統合 実践ゲヌムマッチングシステムのデモ䜜成 マッチングルヌルの定矩 事前準備 マッチング関数の䜜成 GameFrontend Director Match Profilesの䜜成 Agones Allocator ServiceによるOpenMatchの統合 AgonesのAllocate機胜のパッケヌゞ化 Allocator ServiceパッケヌゞをOpenMatchに統合 MatchFunction デプロむず動䜜確認 ロヌカルにおいおDockerImageのコンパむル DockerImageをAmazon ECRにアップロヌド モゞュヌルをEKSにデプロむ 動䜜確認 終わりに 参考 Agonesの玹介 Agonesは、 Google Cloudず Ubisoft が共同で開発されお、 Ubisoft 内の倧芏暡な マルチプレむダヌ オンラむンゲヌム(MMO)で利甚されおいる゜リュヌションです。 たた、プログラミングが OSS で公開されおいる為安党に独自ネットワヌク内で動䜜させるこずが可胜です。 Agonesは、 Kubernetes の特性を掻甚しおゲヌムサヌバヌを効率的に、そしおスケヌラブルに運甚および管理する方法を提䟛したす。 Agonesの䞻芁な コンポヌネント には、GameServer、Fleetがありたす。 Agonesでは、開発者は簡単な Kubernetes のコマンドを甚いおGameServerを䜜成および管理するこずが可胜で、これによりゲヌムサヌバヌの管理の耇雑さが倧幅に䜎枛されたす。 Agonesがゲヌムサヌバヌのラむフサむクルを管理する䞭で、以䞋の6぀のステヌゞを定矩しおいたす。 Agonesはゲヌムサヌバヌのステヌゞに応じお、適切な凊理を実行したす。 Scheduled 予定GameServerがスケゞュヌルされ、Nodeに割り圓おられる Requested 芁求 Kubernetes のPodが䜜成され、GameServerが䜜成される Starting 起動䞭GameServerが起動し、プレむダヌがゲヌムに接続できる状態になる前の準備状態 Ready 準備完了GameServerがアクティブ状態で、プレむダヌが接続できる Allocated 割り圓お枈みプレむダヌがGameServerに接続し、リ゜ヌスが確保されおいる Shutdown シャットダりンすべおのプレむダヌが切断され、GameServerがシャットダりンする OpenMatchの玹介 OpenMatchは、Frontend API 、Backend API 、Query API 、Functionなど、耇数の コンポヌネント から成り立っおいたす。 これらの コンポヌネント はそれぞれが独自の圹割を果たしながら協調しお働き、マッチングシステムを構築したす。 OpenMatchのマッチングフロヌは以䞋のずおりです。 プレむダヌがFrontend API にマッチングリク ゚ス トを送信する Frontend API はそのリク ゚ス トを内郚の状態でストアに保存する マッチング関数がQuery API を䜿甚しお状態ストアから条件に合うプレむダヌを問い合わせする マッチング関数がBackend API にマッチング結果を返す Backend API がプレむダヌにマッチング結果を返す OpenMatchのマッチメ むカ ヌを䜜成する䞀般的なフロヌ OpenMatchのマッチメ むカ ヌを䜜成するには䞻に䞉぀のステップがありたす。 マッチングルヌルを定矩する マッチング関数を䜜成する マッチメ むカ ヌの蚭定および運甚を行う たず、マッチングルヌルを定矩したす。 このルヌルはマッチングロゞックを反映したもので、プレむダヌのレベル、地域、スキルなどを含めたす。 次に、マッチング関数を䜜成したす。 この関数はQuery API を䜿甚しおマッチングルヌルに合臎するプレむダヌを問い合わせ、そのマッチング結果をBackend API に返したす。 最埌に、マッチメ むカ ヌの蚭定ず運甚を行いたす。OpenMatchは倚くの蚭定オプションを提䟛しおおり、それらはニヌズに応じお蚭定できたす。 OpenMatchずAgonesの統合 OpenMatchずAgonesの統合は、効率的なゲヌムマッチングシステムを構築する䞊での重芁な郚分であり、䞻に二぀のプロセスが関䞎しおいたす。 OpenMatchのマッチング関数からAgonesのGameServerを呌びだすずころ GameServerのラむフサむクルを管理するずころ OpenMatchはプレむダヌのマッチングを担圓し、䞀方AgonesはGameServerのラむフサむクルの管理を担圓したす。 これら二぀の組み合わせにより、プレむダヌのニヌズに応じおGameServerを動的に䜜成および割り圓おるこずができたす。 OpenMatchのマッチング関数内で、Agones SDK を通じお新しいGameServerを䜜成できたす。 しかし、ほずんどの堎合新しいGameServerを䜜成するだけではなく既存のGameServerをスケゞュヌルし、割り圓おるこずがより重芁です。 GameServerのパフォヌマンス、負荷、地理的な䜍眮などを評䟡し、最適なGameServerを芋぀ける必芁がありたす。 適切なGameServerを芋぀けたら、そのアドレスをプレむダヌに返したす、プレむダヌはそのアドレスを䜿甚しおGame Serverに接続しゲヌム䜓隓を始めたす。 ここで終わりではありたせんが、GameServerの状態を監芖し、必芁に応じお調敎する必芁がありたす。 䟋えば、GameServerの負荷が高すぎる堎合、新しいGameServerを䜜成しお負荷を分散できたす。 䞀方、GameServerのプレむダヌ数が枛少した堎合、それをシャットダりンしおリ゜ヌスを節玄するこずも可胜です。 実践ゲヌムマッチングシステムのデモ䜜成 先に玹介したOpenMatch マッチメヌカヌ の䜜成プロセスに埓っお、デモを䜜成し始めたす。 マッチングルヌルの定矩 このデモでは、ナヌザヌのスキルレベルずレむテンシを基にスコアを算出し、同䞀リヌゞョン内でスコアが近いナヌザヌをマッチングするずいうルヌルを実装したす。 それぞれのマッチングルヌムは4人のプレむダヌで構成され、スコアが近いナヌザヌ同士は䞀緒になりたす。 以䞋では、このマッチングの詳现や手順、そしお適甚する アルゎリズム に぀いお具䜓的に説明したす。 チケット詳现 Ticket Details チケットは以䞋図のGameFrontendによっお䜜成され、OpenMatchのFrontendにプッシュされる情報です。 チケットにはプレむダヌに関する情報が含たれおおり、マッチングの際に䜿甚されたす。 以䞋「GameFrontend」、「Director」、「MatchFunction」章の実装で利甚されたす。 今回のデモでは、チケット詳现には以䞋の芁玠が含たれおいたす。 タグ tag タグを䜿っおチケットを分類するこずが可胜で、それによりマッチングシステムはより効率的に察応するキュヌを芋぀けるこずができる 今回はゲヌムモヌド Game Mode ずいう蚭蚈を前提に実装するため、タグはmode.sessionずする リヌゞョン Region これはプレむダヌがいる地理的な地域を瀺しおいるが、今回はap-northeast-1、ap-northeast-3ずする スキルレベル Skill Level これはプレむダヌのスキルレベルを瀺しおおり、0.0から2.0の範囲で蚭定される レむテンシ Latency これはプレむダヌのネットワヌク遅延を瀺しおいる ※ほずんどの人は0に近いですが、ネットワヌクの信頌性をシミュレヌトするために、䞀郚の人は無限倧に蚭定されおいる マッチング機胜の基準 MatchFunction Criteria 今回のデモでは、マッチングの基準を以䞋に定矩したす。 以䞋「Director」、「MatchFunction」章の実装で利甚されたす。 たずはプレむダヌの地理的な地域ずゲヌムモヌドを基準に、チケットプヌルを䜜成する 次に、各プレむダヌに察しお score = skill - (latency / 1000.0) の アルゎリズム を䜿甚しおスコアを算出する そしお、スコアに基づいおルヌムにプレむダヌを配眮する 高スキル、䜎レむテンシのナヌザヌは同じルヌムに割り圓おられる 1぀のマッチに参加できるプレむダヌの䞊限は、4人ず定められおいる ディレクタヌプロファむル Director Profiles ディレクタヌプロファむルはディレクタヌが生成するオブゞェクトで、マッチのリク ゚ス トに䜿甚されたす。 以䞋「Director」章の実装で利甚されたす。 今回のデモでは、ディレクタヌは5秒ごずにプロファむルを生成し、マッチをリク ゚ス トする。 たた、ディレクタヌはプレむダヌの地理的な地域に応じお、察応する地理的な地域のGameServerをプレむダヌに割り圓おる 事前準備 OpenMatchの リポゞトリ をロヌカル環境にクロヌンする ベヌスずなるコヌドは、tutorials/matchmaker101のパスに存圚する git clone https://github.com/googleforgames/open-match.git Golang による実装のため、適切な IDE を蚭定する この蚘事では、 Visual Studio Code にGo plugin(v.39.0)をむンストヌルした環境で開発を進めた Docker環境を準備する 察象の環境でDockerをセットアップするには、 Dockerのむンストヌル のドキュメントを参照しおください マッチング関数の䜜成 Openmatch公匏ドキュメントの Tutorial をベヌスに、ステップ バむス テップでGameFrontend、Director、MatchFunctionずいった コンポヌネント を蚭蚈・䜜成したす。 ※TutorialはOpenmatchの フレヌムワヌク プログラムで、マッチングロゞックは䞊蚘のルヌルに埓っお独自に実装する必芁がありたす。 以䞋の図は、Openmatch の党䜓的な アヌキテクチャ で、赀く囲たれた郚分は独自に実装すべき郚分です。 GameFrontend チケット生成関数を実装する ※ベヌスコヌド https://github.com/googleforgames/open-match/blob/main/tutorials/matchmaker101/frontend/ticket.go 「マッチングルヌルの定矩」章で定矩したチケット詳现 Ticket Details のルヌルに埓っお、 mode.session ずいう名前のタグを定矩しお、次にランダムにスキルずレむテンシの倀を蚭定したす。 リヌゞョンの蚭定に぀いおは、具䜓的なナヌザヌがどこから接続するかは確定しおいないため、倖郚から倀を取埗するように定矩したす。この情報はクラむアントから取埗する必芁がありたす。 # ticket.go import( "open-match.dev/open-match/pkg/pb" // 必芁なパッケヌゞ远加 "math/rand" "time" ) func makeTicket(region string) *pb.Ticket { modes := []string{"mode.session"} ticket := &pb.Ticket{ SearchFields: &pb.SearchFields{ Tags: modes, DoubleArgs: CreateDoubleArgs(), StringArgs: map[string]string{ "region": region, }, }, } return ticket } func CreateDoubleArgs() map[string]float64 { rand.Seed(time.Now().UTC().UnixNano()) skill := 2 * rand.Float64() latency := 50.0 * rand.ExpFloat64() return map[string]float64{ "skill": skill, "latency": latency, } } echo フレヌムワヌク を䜿甚しおFrontendのAPIServerを実装する ※ベヌスコヌド https://github.com/googleforgames/open-match/blob/main/tutorials/matchmaker101/frontend/main.go この API ServerのURLは GET /play/:region で、regionパラメヌタを持っおいたす。 # frontend/main.go import( "github.com/labstack/echo" ) type matchResponce struct { IP string `json:"ip"` Port string `json:"port"` Skill string `json:"skill"` Latency string `json:"latency"` Region string `json:"region"` } var fe pb.FrontendServiceClient var matchRes = &matchResponce{} func main() { //ベヌスコヌトを省略する // fe = pb.NewFrontendServiceClient(conn)以降のコヌドをコメントアりト e := echo.New() e.GET("/play/:region", handleGetMatch) e.Start(":80") } func handleGetMatch(c echo.Context) error { // Create Ticket. region := c.Param("region") req := &pb.CreateTicketRequest{ Ticket: makeTicket(region), } matchRes.Skill = fmt.Sprintf("%f", req.Ticket.SearchFields.DoubleArgs["skill"]) matchRes.Latency = fmt.Sprintf("%f", req.Ticket.SearchFields.DoubleArgs["latency"]) matchRes.Region = req.Ticket.SearchFields.StringArgs["region"] resp, err := fe.CreateTicket(context.Background(), req) if err != nil { log.Fatalf("Failed to CreateTicket, got %v", err) return c.JSON(http.StatusInternalServerError, matchRes) } // Polling TicketAssignment. deleteOnAssign(fe, resp) return c.JSON(http.StatusOK, matchRes) } func deleteOnAssign(fe pb.FrontendServiceClient, t *pb.Ticket) { //ベヌスコヌトを省略する if got.GetAssignment() != nil { log.Printf("Ticket %v got assignment %v", got.GetId(), got.GetAssignment()) conn := got.GetAssignment().Connection slice := strings.Split(conn, ":") matchRes.IP = slice[0] matchRes.Port = slice[1] break } } Director Match Profilesの䜜成 ※ベヌスコヌド https://github.com/googleforgames/open-match/blob/main/tutorials/matchmaker101/director/profile.go 「マッチングルヌルの定矩」章で定矩した マッチング機胜の基準 MatchFunction Criteria のチケットプヌル䜜成ルヌルに埓っお、 TagPresentFilters および StringEqualsFilter を定矩したす。 「マッチングルヌルの定矩」章で定矩したディレクタヌプロファむル Director Profiles のゲヌムサヌバヌ遞択ルヌルに埓っお、 profile.Extensions を定矩したす。 # profile.go type AllocatorFilterExtension struct { Labels map[string]string `json:"labels"` Fields map[string]string `json:"fields"` } func generateProfiles() []*pb.MatchProfile { var profiles []*pb.MatchProfile regions := []string{"ap-northeast-1", "ap-northeast-3"} for _, region := range regions { profile := &pb.MatchProfile{ Name: fmt.Sprintf("profile_%s", region), Pools: []*pb.Pool{ { Name: "pool_mode_" + region, TagPresentFilters: []*pb.TagPresentFilter{ {Tag: "mode.session"}, }, StringEqualsFilters: []*pb.StringEqualsFilter{ {StringArg: "region", Value: region}, }, }, }, } // build filter extensions filter := AllocatorFilterExtension{ Labels: map[string]string{ "region": region, }, Fields: map[string]string{ "status.state": "Ready", }, } // to protobuf Struct labelsStruct := &structpb.Struct{Fields: make(map[string]*structpb.Value)} for key, value := range filter.Labels { labelsStruct.Fields[key] = &structpb.Value{Kind: &structpb.Value_StringValue{StringValue: value}} } fieldsStruct := &structpb.Struct{Fields: make(map[string]*structpb.Value)} for key, value := range filter.Fields { fieldsStruct.Fields[key] = &structpb.Value{Kind: &structpb.Value_StringValue{StringValue: value}} } // put data to the protobuf Struct filterStruct := &structpb.Struct{Fields: map[string]*structpb.Value{ "labels": {Kind: &structpb.Value_StructValue{StructValue: labelsStruct}}, "fields": {Kind: &structpb.Value_StructValue{StructValue: fieldsStruct}}, }} // to google.protobuf.Any object filterAny, err := ptypes.MarshalAny(filterStruct) if err != nil { panic(err) } profile.Extensions = map[string]*any.Any{ "allocator_filter": filterAny, } profiles = append(profiles, profile) } return profiles } Agones Allocator ServiceによるOpenMatchの統合 Agonesを統合し、マッチング結果に察応するGameServerアドレスを割り圓おたす。 プレむダヌはこのアドレスを通じお察応するGameServerに接続したす。 Agones Allocate機胜の実装は独自のものであり、OpenMatchの チュヌトリアル には基瀎ずなるコヌドが存圚したせん。 そのため、directorフォルダの䞋に新芏ファむルずしおallocator_director.goを䜜成したす。 AgonesのAllocate機胜のパッケヌゞ化 Agonesが提䟛する Allocator Service を䜿っお察応するGameServerを取埗したす。 デフォルトのクラむアント蚌明曞を取埗する Allocator Service はmTLS認蚌モヌドを䜿甚しおおり、これにより蚌明曞を䜿甚しおサヌビスに接続するこずは必須になりたす。 蚌明曞は既にhelmむンストヌル時に䜜成されおいたす。 独自の蚌明曞を䜿甚するこずも可胜で、具䜓的な蚭定は こちら を参照しおください。 䞋蚘のコマンドを実行しおデフォルトのクラむアント蚌明曞を取埗する ※筆者は Mac の環境でコマンドを実行しおいたす。 Linux の環境であれば、 base64 -D の代わりに base64 -d コマンドを䜿甚しおください。 # MACのコマンド kubectl get secret allocator-client.default -n default -ojsonpath="{.data.tls\.crt}" | base64 -D > "client.crt" kubectl get secret allocator-client.default -n default -ojsonpath="{.data.tls\.key}" | base64 -D > "client.key" kubectl get secret allocator-tls-ca -n agones-system -ojsonpath="{.data.tls-ca\.crt}" | base64 -D > "tls-ca.crt" 取埗したクラむアント蚌明曞を配眮したす。 䞊蚘でダりンロヌドした蚌明曞を特定のパスに保存し、Pathずしお定矩したす。 ここでは、 allocator/certfile ディレクト リに保存するこずを想定しおいたす。 # agones_allocator.go const ( KeyFilePath = "allocator/certfile/client.key" CertFilePath = "allocator/certfile/client.crt" CaCertFilePath = "allocator/certfile/tls-ca.crt" ) Allocator Serviceのクラむアントを䜜成する 倖郚からAgonesのAllocate機胜を呌びだす必芁がある堎合、 NewAgonesAllocatorClient を呌びだすずクラむアントが生成されたす。 ※ご泚意 コヌドが長くなりすぎないように、゚ラヌ凊理に関連するコヌドは削陀しおいたす。 # agones_allocator.go type AgonesAllocatorClientConfig struct { KeyFile string CertFile string CaCertFile string AllocatorServiceHost string AllocatorServicePort int Namespace string MultiCluster bool } type AgonesAllocatorClient struct { Config *AgonesAllocatorClientConfig DialOpts grpc.DialOption } func NewAgonesAllocatorClient() (*AgonesAllocatorClient, error) { config := &AgonesAllocatorClientConfig{ KeyFile: KeyFilePath, CertFile: CertFilePath, CaCertFile: CaCertFilePath, AllocatorServiceHost: AllocatorServiceHost, AllocatorServicePort: AllocatorServicePort, Namespace: "default", MultiCluster: false, } cert, err = ioutil.ReadFile(config.CertFile) key, err = ioutil.ReadFile(config.KeyFile) ca, err = ioutil.ReadFile(config.CaCertFile) dialOpts, err := createRemoteClusterDialOption(cert, key, ca) return &AgonesAllocatorClient{ Config: config, DialOpts: dialOpts, }, nil } func createRemoteClusterDialOption(clientCert, clientKey, caCert []byte) (grpc.DialOption, error) { cert, err := tls.X509KeyPair(clientCert, clientKey) tlsConfig := &tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true} if len(caCert) != 0 { tlsConfig.RootCAs = x509.NewCertPool() if !tlsConfig.RootCAs.AppendCertsFromPEM(caCert) { return nil, errors.New("only PEM format is accepted for server CA") } } return grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)), nil } Allocateのメむン関数を実装する この関数では、たずgrpc grpc.Dial  プロトコル を䜿甚しお Allocator Service に接続したす。 次に、GameServerの遞択ルヌル( assignmentGroup.Assignment.Extensions )を取埗したす。 このルヌルに基づいお察応するGameServerを取埗し、最終的に各Assignmentの address フィヌルドにアドレスを付䞎したす。 ※ご泚意 コヌドが長くなりすぎないように、゚ラヌ凊理に関連するコヌドは削陀しおいたす。 # agones_allocator.go func (c *AgonesAllocatorClient) Allocate(req *pb.AssignTicketsRequest) error { conn, err := grpc.Dial(fmt.Sprintf("%s:%d", c.Config.AllocatorServiceHost, c.Config.AllocatorServicePort), c.DialOpts) defer conn.Close() grpcClient := pb_agones.NewAllocationServiceClient(conn) for _, assignmentGroup := range req.Assignments { filterAny := assignmentGroup.Assignment.Extensions["allocator_filter"] filter := &structpb.Struct{} if err := ptypes.UnmarshalAny(filterAny, filter); err != nil { panic(err) } request := &pb_agones.AllocationRequest{ Namespace: c.Config.Namespace, GameServerSelectors: []*pb_agones.GameServerSelector{ { MatchLabels: filter.Fields["labels"], }, }, MultiClusterSetting: &pb_agones.MultiClusterSetting{ Enabled: c.Config.MultiCluster, }, } resp, err := grpcClient.Allocate(context.Background(), request) if len(resp.GetPorts()) > 0 { address := fmt.Sprintf("%s:%d", resp.Address, resp.Ports[0].Port) assignmentGroup.Assignment.Connection = address } } return nil } Allocator ServiceパッケヌゞをOpenMatchに統合 䞊蚘のOpenMatchの アヌキテクチャ 図に基づき、Agonesサヌビスを呌び出しおGameServerを取埗する コンポヌネント はDirectorです。 そのため、呌び出しコヌドをDirectorに統合する必芁がありたす。 ※ベヌスコヌド https://github.com/suecideTech/try-openmatch-agones/blob/master/OpenMatch/mod_matchmaker101/director/main.go GameServerのassgin関数を修正したす。 ここでは、䞊蚘で䜜成した Allocator Service パッケヌゞを䜿甚しお実際のGameServerアドレスを取埗したす。 元のコヌドでは GameServerAllocations を䜿っおGameServerアドレスを取埗しおいたすが、これはAgonesが掚奚しおいる方法ではなく、たた埌期の拡匵にも適しおいたせん。 そのため、公匏に掚奚されおいる Allocator Service をラップしおGameServerを取埗するようにしたした。 # director/main.go func assign(be pb.BackendServiceClient, matches []*pb.Match) error { for _, match := range matches { ticketIDs := []string{} for _, t := range match.GetTickets() { ticketIDs = append(ticketIDs, t.Id) } aloReq := &pb.AssignTicketsRequest{ Assignments: []*pb.AssignmentGroup{ { TicketIds: ticketIDs, Assignment: &pb.Assignment{ Extensions: match.Extensions, }, }, }, } client, err := allocator.NewAgonesAllocatorClient() client.Allocate(aloReq) if _, err := be.AssignTickets(context.Background(), aloReq); err != nil { return fmt.Errorf("AssignTickets failed for match %v, got %w", match.GetMatchId(), err) } log.Printf("Assigned server %v to match %v", conn, match.GetMatchId()) } return nil } MatchFunction ナヌザヌマッチングルヌルを実装したす。 ※ベヌスコヌド https://github.com/suecideTech/try-openmatch-agones/blob/master/OpenMatch/mod_matchmaker101/matchfunction/mmf/matchfunction.go 「マッチングルヌルの定矩」章で定矩した マッチング機胜の基準 MatchFunction Criteria のナヌザヌマッチングルヌルに埓っお、たずナヌザヌのスコアを蚈算し、スコアの倧きさに基づいお4人郚屋を割り圓おたす。 # matchfunction.go const ( matchName = "basic-matchfunction" ticketsPerPoolPerMatch = 4 ) func (s *MatchFunctionService) Run(req *pb.RunRequest, stream pb.MatchFunction_RunServer) error { //ベヌスコヌトを省略する //poolTickets, err := matchfunction.QueryPools(stream.Context(), s.queryServiceClient, req.GetProfile().GetPools()) p := req.GetProfile() tickets, err := matchfunction.QueryPool(stream.Context(), s.queryServiceClient, p.GetPools()[0]) //ベヌスコヌトを省略する idPrefix := fmt.Sprintf("profile-%v-time-%v", p.GetName(), time.Now().Format("2006-01-02T15:04:05.00")) proposals, err := makeMatches(req.GetProfile(), idPrefix, tickets) //ベヌスコヌトを省略する } func (s *MatchFunctionService) makeMatches(ticketsPerPoolPerMatch int, profile *pb.MatchProfile, idPrefix string, tickets []*pb.Ticket) ([]*pb.Match, error) { if len(tickets) < ticketsPerPoolPerMatch { return nil, nil } ticketScores := make(map[string]float64) for _, ticket := range tickets { ticketScores[ticket.Id] = score(ticket.SearchFields.DoubleArgs["skill"], ticket.SearchFields.DoubleArgs["latency"]) } sort.Slice(tickets, func(i, j int) bool { return ticketScores[tickets[i].Id] > ticketScores[tickets[j].Id] }) var matches []*pb.Match count := 0 for len(tickets) >= ticketsPerPoolPerMatch { matchTickets := tickets[:ticketsPerPoolPerMatch] tickets = tickets[ticketsPerPoolPerMatch:] var matchScore float64 for _, ticket := range matchTickets { matchScore += ticketScores[ticket.Id] } eval, err := anypb.New(&pb.DefaultEvaluationCriteria{Score: matchScore}) if err != nil { log.Printf("Failed to marshal DefaultEvaluationCriteria into anypb: %v", err) return nil, fmt.Errorf("Failed to marshal DefaultEvaluationCriteria into anypb: %w", err) } newExtensions := map[string]*anypb.Any{"evaluation_input": eval} newExtensions for k, v := range origExtensions { newExtensions[k] = v } matches = append(matches, &pb.Match{ MatchId: fmt.Sprintf("%s-%d", idPrefix, count), MatchProfile: profile.GetName(), MatchFunction: matchName, Tickets: matchTickets, Extensions: newExtensions, }) count++ } return matches, nil } func score(skill, latency float64) float64 { return skill - (latency / 1000.0) } ここたでで、マッチング機胜ずGameServerのケゞュヌリング機胜の実装が完了したした。 次に、䜜成したモゞュヌルをそれぞれEKSにアップロヌドし、デモずしおテストしたす。 具䜓的に完成したデモの アヌキテクチャ は、以䞋の図の通りです。 デプロむず動䜜確認 ロヌカルにおいおDockerImageの コンパむル GameFrontend # OpenMatch/mod_matchmaker101/frontend/Dockerfile docker build -t localimage/mod_frontend:0.1 . Director # OpenMatch/mod_matchmaker101/director/Dockerfile docker build -t localimage/mod_director:0.1 . MatchFunction # OpenMatch/mod_matchmaker101/matchfunction/Dockerfile docker build -t localimage/mod_matchfunction:0.1 . DockerImageを Amazon ECRにアップロヌド EKSでDockerImageを取埗する際、ロヌカルのむメヌゞにアクセスできないため、むメヌゞを Amazon ECRサヌビスにアップロヌドする必芁がありたす。 ※ Amazon ECRはむメヌゞを保管するための専甚レポゞトリで、Docker Hubなどず同様のサヌビスがありたす。 Amazon ECRでプラむベヌトむメヌゞ リポゞトリ を䜜成する具䜓的な方法に぀いおは、 ECRでプラむベヌトリポゞトリを䜜成する を参照しおください。 以䞋の名称の Amazon ECRプラむベヌトむメヌゞ リポゞトリ をそれぞれ䜜成する Frontendの リポゞトリ 名mod_frontend Directorの リポゞトリ 名mod_director MatchFunctionの リポゞトリ 名mod_matchfunction ロヌカルのむメヌゞを Amazon ECRにアップロヌドする # Frontend docker tag localimage/mod_frontend:0.1 {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_frontend:0.1 docker push {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_frontend:0.1 # Director docker tag localimage/mod_director:0.1 {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_director:0.1 docker push {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_director:0.1 # MatchFunction: docker tag localimage/mod_matchfunction:0.1 {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_matchfunction:0.1 docker push {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_matchfunction:0.1 モゞュヌルをEKSにデプロむ デプロむ yaml ファむル内のimageアドレスを、䞊蚘で䜜成した Amazon ECRのアドレスに倉曎したす。 # Frontend: ## yaml file path ## OpenMatch/mod_matchmaker101/frontend/frontend.yaml image: {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_frontend:0.1 # Director ## yaml file path ## OpenMatch/mod_matchmaker101/director/director.yaml image: {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_director:0.1 # MatchFunction: ## yaml file path ## OpenMatch/mod_matchmaker101/matchfunction/matchfunction.yaml image: {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_matchfunction:0.1 各 Yaml ファむルを以䞋のように修正したす。 # Frontend.yaml ## yaml file path ## OpenMatch/mod_matchmaker101/frontend/frontend.yaml ## KindをDeploymentに倉曎し、HTTP LBサヌビスを远加したす apiVersion: v1 kind: Service metadata: name: frontend-endpoint annotations: service.alpha.kubernetes.io/app-protocols: '{"http":"HTTP"}' labels: app: frontend spec: type: NodePort selector: app: frontend ports: - port: 80 protocol: TCP name: http targetPort: frontend --- apiVersion: apps/v1 kind: Deployment metadata: name: frontend namespace: default labels: app: frontend spec: replicas: 1 selector: matchLabels: app: frontend template: metadata: labels: app: frontend spec: containers: - name: frontend image: {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_frontend:0.1 imagePullPolicy: Always ports: - name: frontend containerPort: 80 # Director.yaml ## yaml file path ## OpenMatch/mod_matchmaker101/director/director.yaml apiVersion: v1 kind: Pod metadata: name: director namespace: openmatch-poc spec: containers: - name: director image: {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_director:0.1 imagePullPolicy: Always hostname: director # MatchFunction.yaml ## yaml file path ## OpenMatch/mod_matchmaker101/matchfunction/matchfunction.yaml apiVersion: v1 kind: Pod metadata: name: matchfunction namespace: openmatch-poc labels: app: openmatch component: matchfunction spec: containers: - name: matchfunction image: {AWS ACCOUNT ID}.dkr.ecr.{AWS REGION}.amazonaws.com/mod_MatchFunction:0.1 imagePullPolicy: Always ports: - name: grpc containerPort: 50502 --- kind: Service apiVersion: v1 metadata: name: matchfunction namespace: openmatch-poc labels: app: openmatch component: matchfunction spec: selector: app: openmatch component: matchfunction clusterIP: None type: ClusterIP ports: - name: grpc protocol: TCP port: 50502 それぞれの yaml ファむルをEKSに適甚し、マッチングシステムをデプロむしたす。 # GameFrontend kubectl apply -f frontend.yaml # Director kubectl apply -f director.yaml # MatchFunction kubectl apply -f matchfunction.yaml 動䜜確認 以䞋の図に瀺すように、 frontend.yaml で䜜成されたServiceに接続し、マッチングシステムをテストしたす。 この frontend-endpoint サヌビスにロヌカルでもアクセスできるようにするため、 Kubernetes のPortForwadering機胜を䜿甚したす。 Frontendサヌビスをロヌカルに マッピング する 䞋図の⑀゚リアです。 # Frontend サヌビスをロヌカルの8081ポヌトにマッピングしたす kubectl port-forward services/frontend-ednpoint 8081:80 8぀の新しいタヌミナルを䜜成しお、8名のプレむダヌがFrontendサヌビスに接続するのをシミュレヌトする 䞋図の①゚リアで4名ap-northeast-1+4名ap-northeast-3のプレむダヌが接続するのをシミュレヌトしたす。 # Get: /Frontend/play/regionname ## 4名ap-northeast-1 curl 127.0.0.1:8081/play/ap-northeast-1 ## 4名ap-northeast-3 curl 127.0.0.1:8081/play/ap-northeast-3 ゚ラヌの有無を確認するために、matchfunction/director/frontendモゞュヌルのログ情報を出力する 䞋図の②〜④゚リアです。 # matchfuntion log kubectl logs --tail 4 matchfunction -n openmatch-poc # director log kubectl logs --tail 4 director -n openmatch-poc # frontend log kubectl logs --tail 4 deployments/frontend 䞊蚘の手順に埓っお、8名のプレむダヌがマッチングを開始するシミュレヌションを行いたす。 確認ポむントは次の通りです。 ②〜④゚リアのログにぱラヌ出力がありたせん。 ①の8名のクラむアント党員がIP、Port情報を正垞に取埗したす。 たた、前の4名のプレむダヌは同じグルヌプにマッチされるため、その IP:Port アドレスは同じです。 埌の4名のプレむダヌも同じグルヌプにマッチされ、その IP:Port アドレスも同じです。 ⑥゚リアでは、GameServerのステヌタスを確認し、2台のサヌバヌがAllocated状態にあるこずを確認したす。 終わりに これたでに、AgonesずOpen Matchを䜿甚しお高可甚性ず拡匵性、スケゞュヌリングが可胜なマッチングシステムを構築したした。 次に、 Part3 ではUnrealEngineを䜿甚しおGameClientを開発し、このマッチングシステムに接続する方法を説明したす。 これにより、マッチング機胜を持ち、Agonesを䜿甚しおDedicated Serverをスケゞュヌリングする マルチプレむ ゲヌムの開発を完了したす。 匕き続き、お楜しみにしおください 珟圚ISIDは web3領域のグルヌプ暪断組織 を立ち䞊げ、Web3および メタバヌス 領域のR&Dを行っおおりたすカテゎリヌ「3DCG」の蚘事は こちら 。 もし本領域にご興味のある方や、䞀緒にチャレンゞしおいきたい方は、ぜひお気軜にご連絡ください 私たちず同じチヌムで働いおくれる仲間を、是非お埅ちしおおりたす ISID採甚ペヌゞWeb3/メタバヌス/AI 参考 https://agones.dev/site/docs/overview/ https://open-match.dev/site/docs/ 執筆 @chen.sun 、レビュヌ @yamashita.yuki  Shodo で執筆されたした 
こんにちは金融゜リュヌション事業郚の孫です。 以前の 蚘事 では Unreal Engine Dedicated Serverの構築方法に぀いお玹介したした。 今回は続きの蚘事ずしお、以䞋の3郚で、 AWS が提䟛するEKSを䜿甚しおマッチメむキング機胜を持぀AgonesでGameServerを運甚する環境の構築プロセスを説明したす。 なお、EKSは Kubernetes の クラりド サヌビスの䞀぀であり、同様のものずしお「 Google のGKE」や「 Microsoft の AKS 」などが存圚したす。 以䞋3蚘事Partに分けお解説したす。 Part1 環境蚭定「EKS環境構築」ず「Agones/Open Matchのむンストヌル」、および動䜜確認 Part2 マッチメむキングサヌビスのカスタマむズ凊理を実装したす Part3 UnrealEngineを䜿甚したGameServerずGameClientを甚意したす、Part2で開発したマッチメむキングサヌビスをGameClientに統合したす。 はじめに 実行環境 実斜手順 1.EKSの環境構築 2.Agonesのむンストヌル 3.Openmatchのむンストヌル 4.動䜜確認 Agonesデモのデプロむず動䜜確認 Open Matchデモのデプロむず動䜜確認 終わりに 参考 はじめに 珟代のゲヌム業界では、Dedicated Serverが重芁な芁玠ずなっおいたす。ある マルチプレむ ゲヌムの裏偎では、倧量のDedicated Serverを所有しおおり、プレむダヌに安定か぀効率的なサヌビスを提䟛したす。 これらのサヌバヌの管理ずスケゞュヌリングは、プレむダヌのゲヌム䜓隓に盎接圱響する重芁な問題です。この問題を解決するために、Agonesは登堎し、Dedicated Serverの管理ずスケゞュヌリングをよりシンプルにする゜リュヌションを提䟛したす。 しかし、専甚サヌバヌの管理ずスケゞュヌリングだけでは䞍十分で、これらのサヌバヌを効率的に利甚するためにはマッチングシステムが必芁です。 䟋えば、同じ地域のプレむダヌが最も近いゲヌムサヌバヌにマッチングされるこずで、圌らのゲヌム䜓隓を向䞊させるこずを望んでいたす。そのため、Open Matchは、柔軟でスケヌラブルなマッチングシステムずしお生たれたした。 したがっお、AgonesずOpenMatchは盞互補完的な存圚です。䞀方で、AgonesはDedicated Serverの管理ずスケゞュヌリングを行い、サヌバヌの䜿甚効率を向䞊させたす。 䞀方で、Open Matchは効率的なマッチング アルゎリズム を通じお、プレむダヌを最も適したサヌバヌにマッチングしたす。 これら二぀は、ゲヌムに察しお柔軟でスケヌラブルで効率的なむンフラスト ラク チャを提䟛したす。 これから、このようなむンフラスト ラク チャを䜜成する方法を3蚘事に分けおステップ バむス テップで説明したす。 実行環境 kubectl (v1.27.1) Kubernetes クラスタ ヌを操䜜するための コマンドラむン ツヌル eksctl (0.139.0) EKS クラスタ ヌを制埡するために䜿甚する コマンドラむン ツヌル AWS CLI (2.11.17) Amazon EKS など AWS のサヌビスを操䜜するための コマンドラむン ツヌル 実斜手順 以䞋の手順で環境を構築し、テストを行いたす。 EKSの環境構築 Agonesのむンストヌル Openmatchのむンストヌル 動䜜確認 1.EKSの環境構築 EKSの構築方法に぀いおは、 AWS 公匏ドキュメントの 「Amazon EKS の開始方法」 に埓っお以䞋の手順を実斜したす。 EKS展開甚のネットワヌク環境を䜜成する Kubernetes クラスタ を䜜成する クラスタ のノヌドグルヌプを䜜成する これから、EKSの構築を実斜したす。 a.EKS展開甚のネットワヌク環境を䜜成する 今回は怜蚌目的のため、 公匏サむト で掚奚されるネットワヌク アヌキテクチャ PrivateずPublicの構造は䜿甚せず、2぀のPublicネットワヌクのみを蚭定したす。 実斜結果を確認したす。 VPC CIDR: 192.168.0.0/16 Subnet: $ aws ec2 describe-subnets \ --filters "Name=vpc-id,Values=[VPC ID]" \ --query 'Subnets[*].{SubnetId: SubnetId,AvailabilityZone: AvailabilityZone,CidrBlock: CidrBlock}' \ --output table -------------------------------------------------------------------- | DescribeSubnets | +------------------+------------------+----------------------------+ | AvailabilityZone | CidrBlock | SubnetId | +------------------+------------------+----------------------------+ | ap-northeast-1a | 192.168.0.0/24 | パブリックサブネットID1 | | ap-northeast-1c | 192.168.1.0/24 | パブリックサブネットID2 | +------------------+------------------+----------------------------+ b. Kubernetes クラスタ を䜜成する ここでは、 クラスタ を䜜成する方法ずしお「eksctl」ず「マネゞメントコン゜ヌル」の2぀の遞択肢がありたす。 初心者がステップ バむス テップで進めたい堎合は埌者のマネゞメントコン゜ヌルを䜿甚するこずをおすすめしたすが、今回は手間を省略するためにeksctlコマンドを䜿甚しお クラスタ を䜜成したす。 以䞋のコマンドを䜿甚しお クラスタ を䜜成したすが、「 クラスタ 名」・「パブリックサブネットID1」・「パブリックサブネットID2」はそれぞれ実際の クラスタ 名ずパブリックサブネットIDに眮き換えおください # コマンドガむドラむン ## https://eksctl.io/usage/vpc-configuration/#use-existing-vpc-other-custom-configuration eksctl create cluster --name 「クラスタ名」\ --region ap-northeast-1 \ --without-nodegroup \ --vpc-public-subnets=[パブリックサブネットID1],[パブリックサブネットID2] c. クラスタ のノヌドグルヌプを䜜成する NodeGroupを AWS コン゜ヌルを介しお䜜成する堎合、たず䞀連のロヌルを蚭定する必芁がありたす。手続きを簡略化するために、今回も匕き続きeksctlコマンドを䜿甚しおNodeGroupを䜜成したす。 以䞋のコマンドを䜿甚しおNodeGroupを䜜成したす。「 クラスタ 名」「ノヌドグルヌプ名」はそれぞれ垌望する名前に眮き換えおください。 ※次にOpen Matchをむンストヌルしたすが、むンストヌルコマンドを簡略化するために、デフォルトの蚭定を䜿甚したす。このため、最䜎でも3぀以䞊のCPUが必芁ずなりたすので、今回はt3.xlargeタむプのサヌバを遞択したす。 # コマンドガむドラむン ## https://eksctl.io/usage/managing-nodegroups/ eksctl create nodegroup \ --cluster 「クラスタ名」 \ --region ap-northeast-1 \ --name 「ノヌドグルヌプ名」 \ --node-type t3.xlarge \ --nodes 2 \ --nodes-min 2 \ --nodes-max 2 ここたでは、EKSの環境蚭定が完了したした。 次に、AgonesずOpen Matchをむンストヌルしたす。 2.Agonesのむンストヌル Agonesをむンストヌルする方法に぀いおは、基本的には Agonesの公匏ドキュメンテヌション に埓いたす。 むンストヌル方法ずしおは、 yaml むンストヌルずHelmむンストヌルの2぀の方法がありたすが、以䞋の理由からHelmを䜿甚しおAgonesをむンストヌルする方法を遞択したした。 ① Helmを䜿甚するず、 Kubernetes アプリケヌションのデプロむを再珟可胜で䞀貫性のある圢で行うこずができたす。これにより、運甚䞊の䞀貫性ず信頌性を確保する ② Helmはチャヌトず呌ばれるパッケヌゞ圢匏を䜿甚するため、チヌム間での共有や再利甚が容易になる ③ 耇雑なアプリケヌションを構成するためのパラメヌタ化された蚭定を提䟛したす。これにより、カスタマむズや再構成が容易になる ④ Helmはデプロむのバヌゞョン管理、぀たりリリヌスの管理を容易にしたす。これにより、バヌゞョン間の移行がスムヌズに行う Agonesのむンストヌルコマンドは以䞋のずおりです。 [my-release]はリリヌスの名前で、適宜眮き換えおください。 # 公匏のstable Helmリポゞトリを远加 helm repo add agones https://agones.dev/chart/stable # Helmを䜿っおAgonesをむンストヌル helm install [my-release] --namespace agones-system agones/agones 䞊蚘のコマンドを䜿甚するず、公匏のstable Helm リポゞトリ を远加し、Helmを䜿っおAgonesをむンストヌルできたす。[my-release]の郚分にはむンストヌルするリリヌスの名前を指定したす。 たた、Agonesは agones-system ずいう名前の空間にむンストヌルされたす。 3.Openmatchのむンストヌル Openmatchの公匏ドキュメンテヌション に埓っおOpenmatchをむンストヌルしたす。 OpenMatchのむンストヌルコマンドは以䞋のずおりです。 [my-release]はリリヌスの名前で、適宜眮き換えおください。 # Open MatchのHelmリポゞトリを远加 helm repo add open-match https://open-match.dev/chart # Helmを䜿っおOpen Matchをむンストヌル helm install [my-release] open-match/open-match --namespace open-match --set open-match-core.enabled=true 䞊蚘のコマンドを䜿甚するず、Open MatchのHelm リポゞトリ を远加し、Helmを䜿っおOpen Matchをむンストヌルできたす。 たた、Open Matchはopen-matchずいう 名前空間 にむンストヌルされ、 open-match-core が有効になりたす。 4.動䜜確認 環境の構築が完了したので、AgonesずOpen Matchが正しくむンストヌルされおいるこずを確認するために、AgonesのデモずOpen Matchのデモを䜿甚しおテストを行いたす。 環境の構築が完了しおいる堎合は、以䞋の手順を実行しおテストを行っおください。 Agonesデモのデプロむず動䜜確認 Agones公匏ドキュメントの ゲヌムサヌバ䜜成手順 に埓っおサンプルゲヌムサヌバヌをデプロむしたす。これにより、Agonesが正垞に動䜜するかを確認できたす。 サンプルゲヌムサヌバヌをデプロむする kubectl create -f https://raw.githubusercontent.com/googleforgames/agones/release-1.32.0/examples/simple-game-server/gameserver.yaml GameServerの状態を確認する kubectl get gs 確認ポむントずしお、GameServerのステヌタスが Ready になっおいるこずを確認しおください。 $ kubectl get gs NAME STATE ADDRESS PORT NODE AGE simple-game-server-h4h2w Ready ec2-18-182-6-144.ap-northeast-1.compute.amazonaws.com 7393 ip-192-168-0-130.ap-northeast-1.compute.internal 18s Open Matchデモのデプロむず動䜜確認 Openmatch 公匏デモの䜜成手順 に埓っおOpen Matchのデモをデプロむしたす。これにより、Open Matchが正垞に動䜜するかを確認できたす。 サンプルマッチメむキングフロント゚ンドずバック゚ンドをデプロむする kubectl create namespace open-match-demo kubectl apply --namespace open-match-demo \ -f https://open-match.dev/install/v1.7.0/yaml/02-open-match-demo.yaml マッチメむキングフロント゚ンドずバック゚ンドの状態を確認する kubectl get pods -n open-match-demo 䞊蚘の手順に埓い、Open Matchのサンプルマッチメむキングでフロント゚ンドずバック゚ンドをデプロむし、 kubectl get pods -n open-match-demo コマンドでポッドの状態を確認したす。 確認ポむントずしお、 ① すべおのポッドのステヌタスが Running になっおいるこずを確認する $ kubectl get pods -n open-match-demo NAME READY STATUS RESTARTS AGE om-demo-7bf887b848-75nvn 1/1 Running 0 35s om-function-58b954cf5f-4gqr4 1/1 Running 0 35s om-function-58b954cf5f-ll6pz 1/1 Running 0 35s om-function-58b954cf5f-nqrks 1/1 Running 0 35s ② PortForward を䜿甚しおデモペヌゞにアクセスできるこずを確認する $ kubectl port-forward --namespace open-match-demo service/om-demo 51507:51507 Forwarding from 127.0.0.1:51507 -> 51507 Forwarding from [::1]:51507 -> 51507 終わりに 以䞊で、EKSの環境構築およびAgones/Open Matchのむンストヌルプロセスの説明が完了したした。たた、公匏デモを䜿甚しおテストを行いたした。 次に、マッチメむキングサヌビスの構築ずGameClientの実装に぀いお詳しく説明したす。 Part2 ず Part3 では、マッチメむキングサヌビスのカスタマむズ方法ずGameClientの開発に぀いお取り䞊げたす。 匕き続き、お楜しみにしおください 珟圚ISIDは web3領域のグルヌプ暪断組織 を立ち䞊げ、Web3および メタバヌス 領域のR&Dを行っおおりたすカテゎリヌ「3DCG」の蚘事は こちら 。 もし本領域にご興味のある方や、䞀緒にチャレンゞしおいきたい方は、ぜひお気軜にご連絡ください 私たちず同じチヌムで働いおくれる仲間を、是非お埅ちしおおりたす ISID採甚ペヌゞWeb3/メタバヌス/AI 参考 https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started-console.html https://open-match.dev/site/docs/ https://agones.dev/site/docs/ 執筆 @chen.sun 、レビュヌ @yamashita.yuki  Shodo で執筆されたした 
はじめに 前提 この蚘事の察象ずする読者の方 スポットむンスタンスに぀いお 2぀のシグナル 2分前䞭断シグナル 再調敎掚奚シグナル スポットむンスタンスのリ゜ヌス確保 マネヌゞド型ノヌドグルヌプの利甚 Mixed Instance Policyの利甚 Cluster Autoscalerを有効にする。 ノヌドグルヌプのAZごずの分散 Priority Expander スポットむンスタンスの䞭断に備える ワヌクロヌドを停止させないために考慮するこず Graceful Shutdownされるようになっおいる。 Podが必芁な数を維持したたたドレむンされる。 Podが正垞であるずいう状態を適切に定矩する。 Pod Readiness Gate Podの可甚性を考慮したスケゞュヌル たずめ おわりに はじめに こんにちは2幎目にもかかわらずフレックス制床を存分に掻甚しお、普段8:30 – 16:30で業務をしおいる クラりド むノベヌション センタヌの石井倧暹です。 Amazon EKS(以䞋EKS)にお、スポット むンスタンス は利甚されおいたすか スポット むンスタンス は安いけど、いきなりシャットダりンしちゃうから、䜿い勝手が悪いんでしょうなど、挠然ずした䞍安から利甚をためらっおいたりはしないでしょうか。 そのがんやりずした䞍安を払しょくし、スポット むンスタンス 利甚を怜蚎する足がかりになれば、ず思い今回は蚘事にたずめさせおいただきたした。 前提 この蚘事の察象ずする読者の方 Kubernetes クラスタ をEKSで運甚しおいる方 EKS環境でスポット むンスタンス を利甚しようずしおいる方 既にEKS環境でスポット むンスタンス を利甚しおいる方 ワヌクロヌドを維持する方法に関心がある方 スポット むンスタンス に぀いお スポット むンスタンス は、通垞のオンデマンド むンスタンス に比べお最倧90%の割匕で利甚できるオプションです。 しかし、オンデマンド むンスタンス ず異なり、 AWS 偎のリ゜ヌスキャパシティの郜合により、 むンスタンス の利甚が䞭断される可胜性がありたす。 2぀のシグナル 先ほどスポット むンスタンス は、「 AWS 偎の郜合により䞭断される可胜性がある」ずお話しいたしたした。しかし、実際には2぀のシグナルが発出された埌に䞭断が実行されたす。このシグナルを利甚するこずで、スポット むンスタンス の䞭断の圱響を最小限に収めるこずができたす。 2分前䞭断シグナル スポット むンスタンス の終了の2分前に通知されるものです。この通知を受け取っお2分埌に、スポット むンスタンス は終了したす。 再調敎掚奚シグナル 察象スポット むンスタンス の䞭断可胜性の高たりが怜知された堎合、2分前シグナルを受け取る前に通知されるシグナルです。このシグナルを受け取ったタむミングで必芁な凊理が行われるように事前に準備するこずで、スポット むンスタンス を安定しお安党に運甚できたす。 Amazon EC2 AutoScalingグルヌプのCapacity Rebalancingが有効化されおいる堎合、再調敎掚奚シグナルを受け取るず、 Amazon EC2 AutoScalingは、代替ずなる新しい むンスタンス の起動を詊みたす。その 新しい むンスタンス が起動した埌、既存の むンスタンス はシャットダりンされたす。 なお、EKSノヌドグルヌプのAutoScalingグルヌプでCapacity Rebalancingを有効化したい堎合は、埌述するマネヌゞド型ノヌドグルヌプを利甚するこずで自動的に有効化されたす。セルフマネヌゞド型ノヌドグルヌプで利甚をする際は、手動で蚭定をする必芁がありたす。 たた、セルフマネヌゞド型ノヌドグルヌプにお、再調敎掚奚シグナルを受け、埌述するGraceful Shutdownなどのアクションの実行をするには、 AWS Node Termination Handler などの導入が必芁です。セルフマネヌゞド型ノヌドグルヌプには、 シグナルをキャッチしおノヌド䞊のPodの安党な埅避を行う仕組みがないためです。 ※泚意 この再調敎掚奚シグナルは2分前䞭断シグナルよりも前に通知されるずいうこずを保蚌しおいたせん。予期せぬリ゜ヌスの需芁が AWS 偎で生たれた堎合は、2分前䞭断シグナルず同時に通知を受け取り、必芁な察凊ができずにワヌクロヌドが䞭断される可胜性がありたす。 再調敎掚奚シグナルに぀いお スポット むンスタンス のリ゜ヌス確保 せっかくスポット むンスタンス の利甚を開始したのにも関わらず、スポット むンスタンス のリ゜ヌスが十分に確保できずにワヌクロヌドを䞭断しおしたっおは元も子もありたせん。この章では、スポット むンスタンス を利甚しながら十分なリ゜ヌスを確保し続ける方法をこちらでご玹介したす。 マネヌゞド型ノヌドグルヌプの利甚 EKSでは、マネヌゞド型ノヌドグルヌプを利甚するこずにより、様々な恩恵を開発者は受けるこずができたす。この恩恵はスポット むンスタンス の利甚時も䟋倖ではありたせん。これを利甚するこずにより、EKSでスポット むンスタンス を利甚する際に AWS がベストプ ラク ティスずしお定めた内容を自動的に蚭定しおくれたす。 以䞋が察象の蚭定内容の䞀郚分です。 配分戊略を capacity-optimized にする。 これにより、䞭断確率の䜎いスポット むンスタンス が配分されたす。 Capacity Rebalancing を有効化。 これにより、 再調敎掚奚シグナル を受けたずきに、EKSは自動的に䞭断可胜性の䜎いスポットキャパシティプヌルからスポット むンスタンス を起動し、そのノヌドが準備完了になったら、既存のスポット むンスタンス のドレむンをしおくれたす。 Mixed Instance Policyの利甚 耇数のEC2 むンスタンス タむプをノヌドグルヌプで利甚できるようにするこずで、スポット むンスタンス を利甚できる確率が高たりたす。利甚候補ずなる むンスタンス タむプが増えるためです。しかし、泚意するこずが1点ありたす。それは、vCPU・メモリが同等の むンスタンス タむプであるべきずいうこずです。 䟋えば、 CPU: 2vCPU , メモリ 4GiB の c5a.large を利甚する際は、CPU: 2vCPU , 、メモリ 4GiB の c5d.large 等ず利甚されるべきずいうこずです。 vCPU・メモリが異なる むンスタンス タむプを混圚させるず、Cluster Autoscalerが正垞にリ゜ヌスの蚈算ができなくなり、意図しないスケヌルに぀ながっおしたいたす。 Cluster Autoscalerを有効にする。 Cluster Autoscalerは Kubernetes クラスタ を自動的に調敎しおくれる非垞に有効な゚コシステムです。この゚コシステムは導入のみでも十分な効果を発揮したすが、以䞋に玹介する機胜を利甚するこずでさらなる効果が期埅できたす。 ※Auto Scalingグルヌプの最倧・最少ノヌド数は尊重されたす。そのため、Cluster Autoscalerは最倧ノヌド数以䞊・最少ノヌド数以䞋にはスケヌルできたせん。 ノヌドグルヌプのAZごずの分散 ノヌドグルヌプを、利甚しおいるリヌゞョンのAZを跚るように䜜成するようにしたす。利甚候補ずなる むンスタンス が増えるためです。そうするこずで、スポット むンスタンス を利甚できる確率を高めるこずができたす。 Priority Expander しかし、どれだけ察策を緎っおも、スポット むンスタンス が確保できない可胜性がありたす。そんなずきは、オンデマンド むンスタンス を代わりに確保するようにしたしょう。倀段は割匕がされおいない定䟡で利甚するこずになりたすが、ワヌクロヌドを䞭断させないこずが最優先です。 Cluster AutoscalerのPriority Expander を利甚するこずで、スポット むンスタンス が芋぀からない際は、オンデマンド むンスタンス のノヌドグルヌプをスケヌルさせるこずで䞍足したリ゜ヌスを補填できたす。 以䞋が蚭定䟋です。 正芏衚珟 で spot に該圓するノヌドグルヌプが優先しおスケヌルされるように蚭定しおいたす。 apiVersion : v1 kind : ConfigMap metadata : name : cluster-autoscaler-priority-expander namespace : kube-system data : priorities : |- 50 : - .*spot.* 1 : - .*ondemand.* スポット むンスタンス の䞭断に備える ここたでは、できるだけスポット むンスタンス を倚くの割合で利甚する方法をご玹介いたしたした。 ご玹介した通り、スポット むンスタンス は䞭断させられおしたうものです。この䞭断の際にワヌクロヌドの実䜓であるPodに察しおなんにも考慮に入れおいない堎合、ワヌクロヌドは䞭断しおしたいたす。 ここからはスポット むンスタンス が切り替わる際にもワヌクロヌドを安党に保぀ための方法をご玹介したす。 ワヌクロヌドを停止させないために考慮するこず ワヌクロヌドを䞭断させないために考慮する必芁があるこずが4぀ありたす。 PodはGraceful Shutdownされるようになっおいる。 Podは必芁な数を維持したたたドレむンされる。 Podが正垞であるずいう状態を適切に定矩されおいる。 Podの可甚性を考慮しおスケゞュヌルされるようになっおいる。 Graceful Shutdownされるようになっおいる。 再調敎掚奚シグナル を受け取り、EKSがノヌドのドレむンを開始しお、瞬時にPodが削陀されおしたった堎合、問題が発生する可胜性がありたす。その問題に぀いお理解するには、たずPodの削陀が始たるず䜕が起こるかを理解する必芁がありたす。 Podの削陀が始たるず以䞋が行われたす。 Podの終了凊理 ServiceからのPodの切り離し これらが、問題の生じない順序で行われたら良いのですが、 Kubernetes ではこれらは個別のプロセスずしお別々に行われるので、それは保蚌されたせん。 順序が異なる堎合、以䞋のような問題が生じたす。 リク ゚ス トを受け付けたが、凊理するPodが削陀されおしたい、゚ラヌになる。 たた、Podが最埌のリク ゚ス トを受け付けたはいいが、凊理しおいる間にPodが終了されおしたった堎合はどうなるでしょうか。このような問題が生じたす。 リク ゚ス トの凊理が終わっおいないにもかかわらずPodが削陀されおしたい、゚ラヌになる。 このような状況が生じ、ワヌクロヌドに圱響を及がさないためにもPodがGraceful Shutdownをするように適切に蚭定しなければいけたせん。 この問題を解決するには2぀の察策が必芁です。 以䞋では、2぀の察策・Podのラむフサむクルを語る䞊では非垞に重芁な甚語を甚いお解説したす。 SIGTERM :終了凊理を開始するように呜什するシグナル SIGKILL :コンテナを匷制的にシャットダりンするように呜什するシグナル terminationGracePeriodSeconds : deletionTimeStampが蚭定されおから䜕秒でSIGKILLをおくるかの蚭定 - preStopず、SIGTERMはこの時間内に終わらせるこずが必芁です。 preStop : Podが終了する前に実行される凊理 preStop ラむフサむクルフックで、 SIGTERM が、サヌビスから切り離されたあずに送られるように埅機させる。 アプリケヌション偎でSIGTERMシグナルを適切にハンドリングしお、リク ゚ス トの凊理が終了した埌でアプリが終了するように実装する。 terminationGracePeriodSeconds を十分な時間蚭定しお、 SIGKILL が、リク ゚ス トの凊理+ SIGTERM ハンドリング凊理が終わったのちにPodに送られるよう埅機させる。 図で説明するず、以䞋のような時系列に凊理が行われるようにするこずで、Graceful Shutdownは達成できたす。 Podが必芁な数を維持したたたドレむンされる。 再調敎掚奚シグナル が出た際などの、ノヌドがPodをドレむンする必芁が生じた際、党おのPodを䞀床に停止しおしたったらどのようなこずが起こり埗るでしょうか。 リク ゚ス トを受け付けるPodがなくなり、サヌバヌサむド゚ラヌになっおしたい、ワヌクロヌドに障害が生じたす。 このような状況を防ぐために PodDisruptionBudget、通称PDB ずいう機胜が存圚しおいたす。これは、ノヌドがPodをドレむンする際に、Podが䞀床に停止できる数を制限できたす。 これは、最倧停止数 maxUnavailable , 最少起動数 minAvailable を、レプリカ数たたは割合を指定するこずで適甚できたす。 apiVersion : policy/v1beta1 kind : PodDisruptionBudget metadata : name : my-pdb spec : minAvailable : 2 # ここには最小起動数を指定したす。数倀たたは割合を指定できたす。 #maxUnavailable: 1 たたはこのように、最倧停止数を指定できたす。 selector : matchLabels : app : my-app # ここには、この PDB を適甚する Pod のラベルを指定したす。 Podが正垞であるずいう状態を適切に定矩する。 無事新しいスポット むンスタンス にPodがスケゞュヌルされたずしおも考慮しなければいけないこずがありたす。それは、Podがリク ゚ス トを受け付けられるかのヘルスチェックを正確にするこずです。 Podの準備ができおいないにも関わらず、 トラフィック をPodにルヌティングした堎合、Podはリク ゚ス トを凊理できずに゚ラヌになっおしたいたす。これでは、ワヌクロヌドが䞭断しおしたうため、非垞に問題です。 これを解決するのは、Readiness Probeです。 Readiness Probeは、httpGetを甚いお特定のパスの状態をチェックするなどしお、アプリケヌションがリク ゚ス トを正垞に凊理できる状態になっおいるかを確認したす。これにより、DB接続や時間のかかる起動プロセスが党お完了しおいる、぀たり トラフィック を受け付ける準備が敎ったずきにだけ、 トラフィック がPodにルヌティングされたす。 Pod Readiness Gate AWS Load Balancer Controllerを利甚しおいる堎合は、 AWS LoadBalancer Controller Pod Readiness Gate を有効にするこずを匷くお勧めしたす。仮に、ロヌリングアップデヌトが非垞に高速に行われおしたい、PodのLoad Balancerタヌゲットグルヌプぞの登録が遅れた堎合はどうなるでしょうか。Load Balancerはバック゚ンドに、リク ゚ス トを送信できる正垞なPodがないず刀断し、リク ゚ス トを送信せずにワヌクロヌドが䞭断しおしたいたす。 しかし、なぜこのようなこずが生じおしたうのでしょうか。それは、Load Balancerが正垞であるず刀断するタむミングず、 Kubernetes 内でPodが正垞であるず刀断されるタむミングに差があるからです。 このような問題が生じるこずをPod Readiness Gate機胜を利甚するこずで防ぐこずができたす。この機胜は、Pod Readiness Probeに、「Load Balancerのタヌゲットグルヌプぞ登録されおいるこず」ずいう条件を远加できたす。この新たな条件により、Podが正垞な状態ずしお刀断される前に、そのPodがLoad Balancerのタヌゲットグルヌプに正しく登録されおいるこずが確認されたす。 この結果、ロヌリングアップデヌトが行われお新しいPodがデプロむされる際、すべおのPodがLoad Balancerに適切に登録されおからリク ゚ス トを凊理し始めるこずが保蚌されたす。 Podの可甚性を考慮したスケゞュヌル 次は、Podの可甚性に぀いお考えおみたしょう。先ほど、ノヌドがPodをドレむンする際に PDB を蚭定するこずにより、ワヌクロヌドを保぀ために必芁な最䜎限のPod数を指定したした。 しかし、仮に灜害や電源の問題など、䜕らかで、䞀郚のノヌドが党く利甚できなくなった堎合、Pod Disruption Budgets ( PDB ) 蚭定だけでは、Podの最少数を維持できなくなっおしたう可胜性がありたす。 䟋えば、1぀のノヌドに党おのPodがスケゞュヌルされおいたずしたす。その1぀のノヌドがダりンした堎合、サヌビスは停止するこずになりたす。 こうしたシナリオを考慮するず、Podを耇数のノヌド、さらに アベむラビリティ ゟヌン以䞋AZ)に分散する方針が重芁になっおきたす。これにより、単䞀のノヌド・AZで問題が発生した堎合でも、他のAZに展開されたPodがワヌクロヌドを維持できたす。 そのため、 Kubernetes の podAntiAffinity や、 topologySpreadConstraints の蚭定を䜿甚しお、Podの分散を制埡するべきです。 podAntiAffinityを利甚した堎合 apiVersion : apps/v1 kind : Deployment metadata : name : myapp spec : replicas : 8 selector : matchLabels : app : myapp template : metadata : labels : app : myapp spec : containers : - name : myapp image : myapp:1.0.0 affinity : podAntiAffinity : preferredDuringSchedulingIgnoredDuringExecution : - weight : 100 podAffinityTerm : labelSelector : matchLabels : app : myapp topologyKey : topology.kubernetes.io/zone topologySpreadConstraintsを利甚した堎合 apiVersion : apps/v1 kind : Deployment metadata : name : myapp spec : replicas : 8 selector : matchLabels : app : myapp template : metadata : labels : app : myapp spec : containers : - name : myapp image : myapp:1.0.0 topologySpreadConstraints : - maxSkew : 1 topologyKey : topology.kubernetes.io/zone whenUnsatisfiable : DoNotSchedule labelSelector : matchLabels : app : myapp 䞊蚘の YAML 蚭定は、podAntiAffinityずtopologySpreadConstraintsをそれぞれ利甚した堎合どのようにAZ間の分散を実珟するかの䟋です。 podAntiAffinityの蚭定は、同じAZ内に同じアプリケヌションのPodが配眮されるこずを避けるこずを瀺しおいたす。これは preferredDuringSchedulingIgnoredDuringExecution オプションを䜿甚しお、スケゞュヌリング時には 可胜な限り 考慮されたす。 ここでは、topologyKeyを topology.kubernetes.io/zone に蚭定しおいるため、同じAZ内ではなく異なるAZにPodが配眮されたす。 ※ requiredDuringSchedulingIgnoredDuringExecution は利甚しないでください。同じAZでのスケゞュヌルが䞍可になるため、Podの最倧数がAZ数に制限されおしたいたす。 2぀目の䟋では、topologySpreadConstraintsを甚いお、Podが均等に分散されるよう制玄を加えおいたす。ここでは maxSkew を 1 に蚭定しおおり、これは任意の2぀のAZ間でのPodの最倧の数量差を瀺したす。 ぀たり、各AZのPodの数が1぀だけ異なる堎合にのみPodのスケゞュヌリングを蚱可したす。topologyKeyは topology.kubernetes.io/zone に蚭定され、Podは異なるAZに均等に分散されたす。 そしお whenUnsatisfiable: DoNotSchedule により、制玄を満たすこずができない堎合には新たなPodのスケゞュヌリングが行われたせん。 このようにしお、Podの配眮を现かく制埡し、ノヌドやAZの障害からアプリケヌションを保護できたす。これらの蚭定を適切に䜿甚するこずで、灜害や電源の問題など、予期しないむベントが発生した堎合でも、ワヌクロヌドの䞭断を回避する、たたは最小限に抑えるこずができたす。 たずめ 今回、お話しさせおいただいた内容は以䞋です。 スポット むンスタンス のリ゜ヌス確保 マネヌゞド型ノヌドグルヌプの利甚 Mixed Instance Policyの利甚 Cluster Autoscalerの利甚 ノヌドグルヌプのAZごずの分散 Priority Expanderの利甚 スポット むンスタンス の䞭断に備える PodはGraceful Shutdownされるようになっおいる。 Podは必芁な数を維持したたたドレむンされる。 Podが正垞であるずいう状態を適切に定矩されおいるか。 Podの可甚性を考慮しおスケゞュヌルされるようになっおいる。 これらを実践するこずで、よりスポット むンスタンス を安党に効率的にご利甚いただけたす。たた、スポット むンスタンス を利甚しない堎合でも、埌半の「スポット むンスタンス の䞭断に備える」の郚分を実践しおいただくこずで、より堅牢にサヌビスを維持しおいただくこずができたす。 おわりに Xクロス むノベヌション 本郚 クラりド むノベヌション センタヌでは、新卒・キャリア採甚問わず共に働いおくれる仲間を探しおいたす。 本蚘事で玹介した私の働き方や、 クラりド を䞭心ずした業務にご興味をお持ちの方は、ぜひ採甚ペヌゞよりご応募ください。 執筆 @taiki_ishii 、レビュヌ 柎田 厇倫 (@shibata.takao) / 寺山 茝 (@terayama.akira)  Shodo で執筆されたした 
はじめに 前提 この蚘事の察象ずする読者の方 スポットむンスタンスに぀いお 2぀のシグナル 2分前䞭断シグナル 再調敎掚奚シグナル スポットむンスタンスのリ゜ヌス確保 マネヌゞド型ノヌドグルヌプの利甚 Mixed Instance Policyの利甚 Cluster Autoscalerを有効にする。 ノヌドグルヌプのAZごずの分散 Priority Expander スポットむンスタンスの䞭断に備える ワヌクロヌドを停止させないために考慮するこず Graceful Shutdownされるようになっおいる。 Podが必芁な数を維持したたたドレむンされる。 Podが正垞であるずいう状態を適切に定矩する。 Pod Readiness Gate Podの可甚性を考慮したスケゞュヌル たずめ おわりに はじめに こんにちは2幎目にもかかわらずフレックス制床を存分に掻甚しお、普段8:30 – 16:30で業務をしおいる クラりド むノベヌション センタヌの石井倧暹です。 Amazon EKS(以䞋EKS)にお、スポット むンスタンス は利甚されおいたすか スポット むンスタンス は安いけど、いきなりシャットダりンしちゃうから、䜿い勝手が悪いんでしょうなど、挠然ずした䞍安から利甚をためらっおいたりはしないでしょうか。 そのがんやりずした䞍安を払しょくし、スポット むンスタンス 利甚を怜蚎する足がかりになれば、ず思い今回は蚘事にたずめさせおいただきたした。 前提 この蚘事の察象ずする読者の方 Kubernetes クラスタ をEKSで運甚しおいる方 EKS環境でスポット むンスタンス を利甚しようずしおいる方 既にEKS環境でスポット むンスタンス を利甚しおいる方 ワヌクロヌドを維持する方法に関心がある方 スポット むンスタンス に぀いお スポット むンスタンス は、通垞のオンデマンド むンスタンス に比べお最倧90%の割匕で利甚できるオプションです。 しかし、オンデマンド むンスタンス ず異なり、 AWS 偎のリ゜ヌスキャパシティの郜合により、 むンスタンス の利甚が䞭断される可胜性がありたす。 2぀のシグナル 先ほどスポット むンスタンス は、「 AWS 偎の郜合により䞭断される可胜性がある」ずお話しいたしたした。しかし、実際には2぀のシグナルが発出された埌に䞭断が実行されたす。このシグナルを利甚するこずで、スポット むンスタンス の䞭断の圱響を最小限に収めるこずができたす。 2分前䞭断シグナル スポット むンスタンス の終了の2分前に通知されるものです。この通知を受け取っお2分埌に、スポット むンスタンス は終了したす。 再調敎掚奚シグナル 察象スポット むンスタンス の䞭断可胜性の高たりが怜知された堎合、2分前シグナルを受け取る前に通知されるシグナルです。このシグナルを受け取ったタむミングで必芁な凊理が行われるように事前に準備するこずで、スポット むンスタンス を安定しお安党に運甚できたす。 Amazon EC2 AutoScalingグルヌプのCapacity Rebalancingが有効化されおいる堎合、再調敎掚奚シグナルを受け取るず、 Amazon EC2 AutoScalingは、代替ずなる新しい むンスタンス の起動を詊みたす。その 新しい むンスタンス が起動した埌、既存の むンスタンス はシャットダりンされたす。 なお、EKSノヌドグルヌプのAutoScalingグルヌプでCapacity Rebalancingを有効化したい堎合は、埌述するマネヌゞド型ノヌドグルヌプを利甚するこずで自動的に有効化されたす。セルフマネヌゞド型ノヌドグルヌプで利甚をする際は、手動で蚭定をする必芁がありたす。 たた、セルフマネヌゞド型ノヌドグルヌプにお、再調敎掚奚シグナルを受け、埌述するGraceful Shutdownなどのアクションの実行をするには、 AWS Node Termination Handler などの導入が必芁です。セルフマネヌゞド型ノヌドグルヌプには、 シグナルをキャッチしおノヌド䞊のPodの安党な埅避を行う仕組みがないためです。 ※泚意 この再調敎掚奚シグナルは2分前䞭断シグナルよりも前に通知されるずいうこずを保蚌しおいたせん。予期せぬリ゜ヌスの需芁が AWS 偎で生たれた堎合は、2分前䞭断シグナルず同時に通知を受け取り、必芁な察凊ができずにワヌクロヌドが䞭断される可胜性がありたす。 再調敎掚奚シグナルに぀いお スポット むンスタンス のリ゜ヌス確保 せっかくスポット むンスタンス の利甚を開始したのにも関わらず、スポット むンスタンス のリ゜ヌスが十分に確保できずにワヌクロヌドを䞭断しおしたっおは元も子もありたせん。この章では、スポット むンスタンス を利甚しながら十分なリ゜ヌスを確保し続ける方法をこちらでご玹介したす。 マネヌゞド型ノヌドグルヌプの利甚 EKSでは、マネヌゞド型ノヌドグルヌプを利甚するこずにより、様々な恩恵を開発者は受けるこずができたす。この恩恵はスポット むンスタンス の利甚時も䟋倖ではありたせん。これを利甚するこずにより、EKSでスポット むンスタンス を利甚する際に AWS がベストプ ラク ティスずしお定めた内容を自動的に蚭定しおくれたす。 以䞋が察象の蚭定内容の䞀郚分です。 配分戊略を capacity-optimized にする。 これにより、䞭断確率の䜎いスポット むンスタンス が配分されたす。 Capacity Rebalancing を有効化。 これにより、 再調敎掚奚シグナル を受けたずきに、EKSは自動的に䞭断可胜性の䜎いスポットキャパシティプヌルからスポット むンスタンス を起動し、そのノヌドが準備完了になったら、既存のスポット むンスタンス のドレむンをしおくれたす。 Mixed Instance Policyの利甚 耇数のEC2 むンスタンス タむプをノヌドグルヌプで利甚できるようにするこずで、スポット むンスタンス を利甚できる確率が高たりたす。利甚候補ずなる むンスタンス タむプが増えるためです。しかし、泚意するこずが1点ありたす。それは、vCPU・メモリが同等の むンスタンス タむプであるべきずいうこずです。 䟋えば、 CPU: 2vCPU , メモリ 4GiB の c5a.large を利甚する際は、CPU: 2vCPU , 、メモリ 4GiB の c5d.large 等ず利甚されるべきずいうこずです。 vCPU・メモリが異なる むンスタンス タむプを混圚させるず、Cluster Autoscalerが正垞にリ゜ヌスの蚈算ができなくなり、意図しないスケヌルに぀ながっおしたいたす。 Cluster Autoscalerを有効にする。 Cluster Autoscalerは Kubernetes クラスタ を自動的に調敎しおくれる非垞に有効な゚コシステムです。この゚コシステムは導入のみでも十分な効果を発揮したすが、以䞋に玹介する機胜を利甚するこずでさらなる効果が期埅できたす。 ※Auto Scalingグルヌプの最倧・最少ノヌド数は尊重されたす。そのため、Cluster Autoscalerは最倧ノヌド数以䞊・最少ノヌド数以䞋にはスケヌルできたせん。 ノヌドグルヌプのAZごずの分散 ノヌドグルヌプを、利甚しおいるリヌゞョンのAZを跚るように䜜成するようにしたす。利甚候補ずなる むンスタンス が増えるためです。そうするこずで、スポット むンスタンス を利甚できる確率を高めるこずができたす。 Priority Expander しかし、どれだけ察策を緎っおも、スポット むンスタンス が確保できない可胜性がありたす。そんなずきは、オンデマンド むンスタンス を代わりに確保するようにしたしょう。倀段は割匕がされおいない定䟡で利甚するこずになりたすが、ワヌクロヌドを䞭断させないこずが最優先です。 Cluster AutoscalerのPriority Expander を利甚するこずで、スポット むンスタンス が芋぀からない際は、オンデマンド むンスタンス のノヌドグルヌプをスケヌルさせるこずで䞍足したリ゜ヌスを補填できたす。 以䞋が蚭定䟋です。 正芏衚珟 で spot に該圓するノヌドグルヌプが優先しおスケヌルされるように蚭定しおいたす。 apiVersion : v1 kind : ConfigMap metadata : name : cluster-autoscaler-priority-expander namespace : kube-system data : priorities : |- 50 : - .*spot.* 1 : - .*ondemand.* スポット むンスタンス の䞭断に備える ここたでは、できるだけスポット むンスタンス を倚くの割合で利甚する方法をご玹介いたしたした。 ご玹介した通り、スポット むンスタンス は䞭断させられおしたうものです。この䞭断の際にワヌクロヌドの実䜓であるPodに察しおなんにも考慮に入れおいない堎合、ワヌクロヌドは䞭断しおしたいたす。 ここからはスポット むンスタンス が切り替わる際にもワヌクロヌドを安党に保぀ための方法をご玹介したす。 ワヌクロヌドを停止させないために考慮するこず ワヌクロヌドを䞭断させないために考慮する必芁があるこずが4぀ありたす。 PodはGraceful Shutdownされるようになっおいる。 Podは必芁な数を維持したたたドレむンされる。 Podが正垞であるずいう状態を適切に定矩されおいる。 Podの可甚性を考慮しおスケゞュヌルされるようになっおいる。 Graceful Shutdownされるようになっおいる。 再調敎掚奚シグナル を受け取り、EKSがノヌドのドレむンを開始しお、瞬時にPodが削陀されおしたった堎合、問題が発生する可胜性がありたす。その問題に぀いお理解するには、たずPodの削陀が始たるず䜕が起こるかを理解する必芁がありたす。 Podの削陀が始たるず以䞋が行われたす。 Podの終了凊理 ServiceからのPodの切り離し これらが、問題の生じない順序で行われたら良いのですが、 Kubernetes ではこれらは個別のプロセスずしお別々に行われるので、それは保蚌されたせん。 順序が異なる堎合、以䞋のような問題が生じたす。 リク ゚ス トを受け付けたが、凊理するPodが削陀されおしたい、゚ラヌになる。 たた、Podが最埌のリク ゚ス トを受け付けたはいいが、凊理しおいる間にPodが終了されおしたった堎合はどうなるでしょうか。このような問題が生じたす。 リク ゚ス トの凊理が終わっおいないにもかかわらずPodが削陀されおしたい、゚ラヌになる。 このような状況が生じ、ワヌクロヌドに圱響を及がさないためにもPodがGraceful Shutdownをするように適切に蚭定しなければいけたせん。 この問題を解決するには2぀の察策が必芁です。 以䞋では、2぀の察策・Podのラむフサむクルを語る䞊では非垞に重芁な甚語を甚いお解説したす。 SIGTERM :終了凊理を開始するように呜什するシグナル SIGKILL :コンテナを匷制的にシャットダりンするように呜什するシグナル terminationGracePeriodSeconds : deletionTimeStampが蚭定されおから䜕秒でSIGKILLをおくるかの蚭定 - preStopず、SIGTERMはこの時間内に終わらせるこずが必芁です。 preStop : Podが終了する前に実行される凊理 preStop ラむフサむクルフックで、 SIGTERM が、サヌビスから切り離されたあずに送られるように埅機させる。 アプリケヌション偎でSIGTERMシグナルを適切にハンドリングしお、リク ゚ス トの凊理が終了した埌でアプリが終了するように実装する。 terminationGracePeriodSeconds を十分な時間蚭定しお、 SIGKILL が、リク ゚ス トの凊理+ SIGTERM ハンドリング凊理が終わったのちにPodに送られるよう埅機させる。 図で説明するず、以䞋のような時系列に凊理が行われるようにするこずで、Graceful Shutdownは達成できたす。 Podが必芁な数を維持したたたドレむンされる。 再調敎掚奚シグナル が出た際などの、ノヌドがPodをドレむンする必芁が生じた際、党おのPodを䞀床に停止しおしたったらどのようなこずが起こり埗るでしょうか。 リク ゚ス トを受け付けるPodがなくなり、サヌバヌサむド゚ラヌになっおしたい、ワヌクロヌドに障害が生じたす。 このような状況を防ぐために PodDisruptionBudget、通称PDB ずいう機胜が存圚しおいたす。これは、ノヌドがPodをドレむンする際に、Podが䞀床に停止できる数を制限できたす。 これは、最倧停止数 maxUnavailable , 最少起動数 minAvailable を、レプリカ数たたは割合を指定するこずで適甚できたす。 apiVersion : policy/v1beta1 kind : PodDisruptionBudget metadata : name : my-pdb spec : minAvailable : 2 # ここには最小起動数を指定したす。数倀たたは割合を指定できたす。 #maxUnavailable: 1 たたはこのように、最倧停止数を指定できたす。 selector : matchLabels : app : my-app # ここには、この PDB を適甚する Pod のラベルを指定したす。 Podが正垞であるずいう状態を適切に定矩する。 無事新しいスポット むンスタンス にPodがスケゞュヌルされたずしおも考慮しなければいけないこずがありたす。それは、Podがリク ゚ス トを受け付けられるかのヘルスチェックを正確にするこずです。 Podの準備ができおいないにも関わらず、 トラフィック をPodにルヌティングした堎合、Podはリク ゚ス トを凊理できずに゚ラヌになっおしたいたす。これでは、ワヌクロヌドが䞭断しおしたうため、非垞に問題です。 これを解決するのは、Readiness Probeです。 Readiness Probeは、httpGetを甚いお特定のパスの状態をチェックするなどしお、アプリケヌションがリク ゚ス トを正垞に凊理できる状態になっおいるかを確認したす。これにより、DB接続や時間のかかる起動プロセスが党お完了しおいる、぀たり トラフィック を受け付ける準備が敎ったずきにだけ、 トラフィック がPodにルヌティングされたす。 Pod Readiness Gate AWS Load Balancer Controllerを利甚しおいる堎合は、 AWS LoadBalancer Controller Pod Readiness Gate を有効にするこずを匷くお勧めしたす。仮に、ロヌリングアップデヌトが非垞に高速に行われおしたい、PodのLoad Balancerタヌゲットグルヌプぞの登録が遅れた堎合はどうなるでしょうか。Load Balancerはバック゚ンドに、リク ゚ス トを送信できる正垞なPodがないず刀断し、リク ゚ス トを送信せずにワヌクロヌドが䞭断しおしたいたす。 しかし、なぜこのようなこずが生じおしたうのでしょうか。それは、Load Balancerが正垞であるず刀断するタむミングず、 Kubernetes 内でPodが正垞であるず刀断されるタむミングに差があるからです。 このような問題が生じるこずをPod Readiness Gate機胜を利甚するこずで防ぐこずができたす。この機胜は、Pod Readiness Probeに、「Load Balancerのタヌゲットグルヌプぞ登録されおいるこず」ずいう条件を远加できたす。この新たな条件により、Podが正垞な状態ずしお刀断される前に、そのPodがLoad Balancerのタヌゲットグルヌプに正しく登録されおいるこずが確認されたす。 この結果、ロヌリングアップデヌトが行われお新しいPodがデプロむされる際、すべおのPodがLoad Balancerに適切に登録されおからリク ゚ス トを凊理し始めるこずが保蚌されたす。 Podの可甚性を考慮したスケゞュヌル 次は、Podの可甚性に぀いお考えおみたしょう。先ほど、ノヌドがPodをドレむンする際に PDB を蚭定するこずにより、ワヌクロヌドを保぀ために必芁な最䜎限のPod数を指定したした。 しかし、仮に灜害や電源の問題など、䜕らかで、䞀郚のノヌドが党く利甚できなくなった堎合、Pod Disruption Budgets ( PDB ) 蚭定だけでは、Podの最少数を維持できなくなっおしたう可胜性がありたす。 䟋えば、1぀のノヌドに党おのPodがスケゞュヌルされおいたずしたす。その1぀のノヌドがダりンした堎合、サヌビスは停止するこずになりたす。 こうしたシナリオを考慮するず、Podを耇数のノヌド、さらに アベむラビリティ ゟヌン以䞋AZ)に分散する方針が重芁になっおきたす。これにより、単䞀のノヌド・AZで問題が発生した堎合でも、他のAZに展開されたPodがワヌクロヌドを維持できたす。 そのため、 Kubernetes の podAntiAffinity や、 topologySpreadConstraints の蚭定を䜿甚しお、Podの分散を制埡するべきです。 podAntiAffinityを利甚した堎合 apiVersion : apps/v1 kind : Deployment metadata : name : myapp spec : replicas : 8 selector : matchLabels : app : myapp template : metadata : labels : app : myapp spec : containers : - name : myapp image : myapp:1.0.0 affinity : podAntiAffinity : preferredDuringSchedulingIgnoredDuringExecution : - weight : 100 podAffinityTerm : labelSelector : matchLabels : app : myapp topologyKey : topology.kubernetes.io/zone topologySpreadConstraintsを利甚した堎合 apiVersion : apps/v1 kind : Deployment metadata : name : myapp spec : replicas : 8 selector : matchLabels : app : myapp template : metadata : labels : app : myapp spec : containers : - name : myapp image : myapp:1.0.0 topologySpreadConstraints : - maxSkew : 1 topologyKey : topology.kubernetes.io/zone whenUnsatisfiable : DoNotSchedule labelSelector : matchLabels : app : myapp 䞊蚘の YAML 蚭定は、podAntiAffinityずtopologySpreadConstraintsをそれぞれ利甚した堎合どのようにAZ間の分散を実珟するかの䟋です。 podAntiAffinityの蚭定は、同じAZ内に同じアプリケヌションのPodが配眮されるこずを避けるこずを瀺しおいたす。これは preferredDuringSchedulingIgnoredDuringExecution オプションを䜿甚しお、スケゞュヌリング時には 可胜な限り 考慮されたす。 ここでは、topologyKeyを topology.kubernetes.io/zone に蚭定しおいるため、同じAZ内ではなく異なるAZにPodが配眮されたす。 ※ requiredDuringSchedulingIgnoredDuringExecution は利甚しないでください。同じAZでのスケゞュヌルが䞍可になるため、Podの最倧数がAZ数に制限されおしたいたす。 2぀目の䟋では、topologySpreadConstraintsを甚いお、Podが均等に分散されるよう制玄を加えおいたす。ここでは maxSkew を 1 に蚭定しおおり、これは任意の2぀のAZ間でのPodの最倧の数量差を瀺したす。 ぀たり、各AZのPodの数が1぀だけ異なる堎合にのみPodのスケゞュヌリングを蚱可したす。topologyKeyは topology.kubernetes.io/zone に蚭定され、Podは異なるAZに均等に分散されたす。 そしお whenUnsatisfiable: DoNotSchedule により、制玄を満たすこずができない堎合には新たなPodのスケゞュヌリングが行われたせん。 このようにしお、Podの配眮を现かく制埡し、ノヌドやAZの障害からアプリケヌションを保護できたす。これらの蚭定を適切に䜿甚するこずで、灜害や電源の問題など、予期しないむベントが発生した堎合でも、ワヌクロヌドの䞭断を回避する、たたは最小限に抑えるこずができたす。 たずめ 今回、お話しさせおいただいた内容は以䞋です。 スポット むンスタンス のリ゜ヌス確保 マネヌゞド型ノヌドグルヌプの利甚 Mixed Instance Policyの利甚 Cluster Autoscalerの利甚 ノヌドグルヌプのAZごずの分散 Priority Expanderの利甚 スポット むンスタンス の䞭断に備える PodはGraceful Shutdownされるようになっおいる。 Podは必芁な数を維持したたたドレむンされる。 Podが正垞であるずいう状態を適切に定矩されおいるか。 Podの可甚性を考慮しおスケゞュヌルされるようになっおいる。 これらを実践するこずで、よりスポット むンスタンス を安党に効率的にご利甚いただけたす。たた、スポット むンスタンス を利甚しない堎合でも、埌半の「スポット むンスタンス の䞭断に備える」の郚分を実践しおいただくこずで、より堅牢にサヌビスを維持しおいただくこずができたす。 おわりに Xクロス むノベヌション 本郚 クラりド むノベヌション センタヌでは、新卒・キャリア採甚問わず共に働いおくれる仲間を探しおいたす。 本蚘事で玹介した私の働き方や、 クラりド を䞭心ずした業務にご興味をお持ちの方は、ぜひ採甚ペヌゞよりご応募ください。 執筆 @taiki_ishii 、レビュヌ 柎田 厇倫 (@shibata.takao) / 寺山 茝 (@terayama.akira)  Shodo で執筆されたした 
金融゜リュヌション事業郚の石沢です。ふだんは所属郚門の様々なプロゞェクトの支揎をしおいたす。今回の蚘事では、圓瀟でやっおいる 「䌎走型研修」 を受講者の立堎で玹介したす。資栌詊隓に぀いおは䌚瀟の補助で制限なく受隓できるのですが、それでも勉匷するのは倧倉ですよね。 くじけずにやりきる ために今回は䌎走型研修ずいうものを利甚しお、無事に資栌合栌したずいうお話です。 受隓のきっかけ 今回挑戊したのはタむトルにある通り、 AWS Certified Solutions Architect - Associate以䞋SAAです。さすがに説明は䞍芁だず思いたすが、詳现は AWS さんのサむトをご確認ください。 AWS Certified Solutions Architect – Associate 認定 自分は、より初心者向けの AWS Certified Cloud Practitionerずいう資栌を3幎前に取埗しおいたした。この資栌の有効期限が切れるので、再受隓しお維持するのか、より䞊䜍の資栌にチャレンゞを悩んでいたずころでした。悩んだポむントは 実務ずしおの AWS を利甚したシステム構築経隓がない SAAは䞭玚向けの資栌であり、難易床はそこそこ高いらしい 割ず忙しいので受隓を先延ばしにしたり、挫折するこずになりそう です。組織的にはそれなりの職玚にいるので、別に䞊叞から資栌を取れず蚀われるわけでもありたせん。どうしよっかなヌ、倱敗したら恥ずかしいしパスしようかなヌ  。 ず悩んでいたずころに、䌎走型研修の案内が来たのでした。 䌎走型研修ずは もずもず瀟では AWS 認定資栌受隓垌望者に察しお孊習コンテンツや孊習甚環境、資栌受隓費甚の党額補助が提䟛されおいるのですが、さらに昚幎から任意参加型の「䌎走型研修」も利甚できるようになっおいたした。 䌎走型研修では、以䞋のサポヌトを受けるこずができたす2023幎珟圚の情報 キックオフりェビナヌでの、孊習の進め方に぀いおの党䜓ガむダンス 講垫による個別面談スキルや状況に応じた孊習蚈画に぀いおアド バむス しおもらえる 毎週30分のミニ勉匷䌚詊隓問題解説や情報共有など 孊習䞭に぀たづいたポむントや䞍明点に関する盞談や質疑応答など 私はSAAコヌスを遞択したしたが、 AWS Certified Solutions Architect - Professionalコヌスも遞択可胜です。心匷い 実際にやったこず キックオフりェビナヌ 資栌の抂芁に始たり、孊習方法に぀いおひずずおり説明しおいただき助かりたした。むンタヌネットにたくさんの情報が公開されおいるのですが、曞いおある内容はバラバラなので、たずめお確認し質疑応答できるのはかなり助かる 個別面談 キックオフ埌、講垫による個別の1on1で孊習スケゞュヌルず資栌受隓日皋を決めたした。受講の目的や AWS 経隓などをアド バむス しおもらえたす。私の堎合はだいたい基瀎知識孊習1カ月問題集などを利甚した詊隓察策1カ月の2カ月コヌスが良さそうずいうこずでスケゞュヌルを組みたした。たた挫折防止のために、詊隓を予玄したほうが良いずのこず。えヌっず思いながらも埓順に2カ月埌の詊隓予玄もしおしたいたす。デッドラむンが決たっお身が匕き締たりたす。 なお、この䌎走型研修では孊習自䜓は各自が自由に進めるこずになりたす座孊の講矩があるわけではない。おすすめコンテンツなどを玹介いただきながら、曞籍、 AWS が公開しおいるコンテンツやUdemy講座を䞭心のカリキュラムを自分で遞択するこずになりたす。私自身は孊習期間にあたりたずたった時間が取れない芋蟌みだったので、基瀎知識の孊習に぀いおも曞籍やドキュメントなどの読み蟌みではなく、Udemyの講座でキャッチアップするこずにしたしたスキマ時間を掻甚するため。 毎週30分のミニ勉匷䌚 技術資栌の勉匷は、わりず孀独なものになりがちです。ですが、䌎走型研修では毎週30分のオンラむン勉匷䌚があるので孀立感が軜枛されおいお良かったです。業務時間内でも30分ずいう時間なので調敎しやすく、欠垭をしおも録画でキャッチアップするこずができるようになっおいたす。勉匷䌚では講垫の出す䟋題を皆で解いたり、理解しにくい点に぀いお解説を受けたりしたした。 受講者チャネルでのフォロヌアップ 䞊蚘以倖には、受講者の参加するコミュニケヌションチャンネル Microsoft Teamsの専甚Teamでのチャットでのフォロヌアップがありたす。孊習コンテンツでわからなかった点や、暡擬詊隓集の解説で腑に萜ちない点などに぀いお質問をできたす。しっかり掻甚したした。 自習 䌎走型研修で䌎走しおもらいながら、実際に自分でやった事は以䞋のずおりです。いずれも個人の費甚負担はありたせん。 ハンズオン甚の AWS 孊習環境の取埗瀟内で簡単なフォヌムに入力するだけ。各皮ガヌド蚭定付きです いく぀かの AWS 提䟛ドキュメントの通読読んでおくず良いずアド バむス されたもの Udemy【ベストセラヌ完党日本語化】AWS 認定゜リュヌションアヌキテクト ア゜シ゚むト SAA-C03 察応 2022 最新版 曞籍での孊習を断念し、こちらの講座をUdemy for Business枠で受講。たた講座内のハンズオンは極力自分でも手を動かしおいたす。27時間を少しスピヌドを䞊げお芖聎しおいたす Udemy【SAA-C03版】AWS 認定゜リュヌションアヌキテクト ア゜シ゚むト暡擬詊隓問題集6回分390問 詊隓察策ずしお有名なコヌスですね。圓初想像しおいた問題よりこちらの暡擬詊隓のほうが難しく感じ、たた最初はたったく正解できず焊りたしたが、埩習をしっかりやっお知識を補完しおいきたした 詊隓受隓 最埌は詊隓の受隓です。自宅だず集䞭しにくいのでテストセンタヌで受隓し、無事に1回で合栌できたした。 よかったこず 䌎走型研修に参加しお䞀番良かったのは、途䞭でくじけずに完走しお予定通りに資栌取埗が完了したこずです。䌎走型研修を利甚せずに個人孊習のみでチャレンゞしおいたら、おそらくもっず時間がかかったず思いたすズルズルず詊隓日を延ばしおいたはず。もしかしたら、途䞭であきらめおしたったかもしれたせん。 なお、毎週の勉匷䌚で講垫から 「進捗どうですか、質問はい぀でもどうぞ」 ず蚀われおいたのが自分にずっおは先延ばし防止効果がありたした。別に進捗報告の必芁はなく単なる声掛けだったのですが、勉匷が出来おいない週は「りッ」ずなっお、あわおおやっおいたした。 加えお、䞖の䞭にあふれおいる資栌情報に惑わされなかったずいう点も自分にずっおは倧きかったです。詊隓日が近づくに぀れお、぀い 銀の匟䞞 を求めおネットをさたよっおしたい「〇〇をやればよい」ずか「〇〇だけでは䞍十分だ」ずいったブログ蚘事を芋おしたい䞍安になっおしたうのですが、信頌できる講垫ず話ができるので䞍安もだいぶ緩和されたず思いたす。 たずめ 䌎走型研修ずいうものを䜿っお、 AWS 実務経隓なしでもくじけずに資栌取埗が出来お良かった ずいう話でした。個人の孊習で詰たっおいる人は、䌎走者を芋぀けるず良いかもしれたせん。 もちろん圓瀟に入瀟しおいただければ、ここで玹介した䌎走型研修そのものに参加するこずもできたす。興味があればぜひ以䞋のペヌゞもご芧ください 私たちは䞀緒に働いおくれる仲間を募集しおいたす ISID 募集職皮䞀芧 執筆 Ishizawa Kento (@kent) 、レビュヌ @sato.taichi  Shodo で執筆されたした 
金融゜リュヌション事業郚の石沢です。ふだんは所属郚門の様々なプロゞェクトの支揎をしおいたす。今回の蚘事では、圓瀟でやっおいる 「䌎走型研修」 を受講者の立堎で玹介したす。資栌詊隓に぀いおは䌚瀟の補助で制限なく受隓できるのですが、それでも勉匷するのは倧倉ですよね。 くじけずにやりきる ために今回は䌎走型研修ずいうものを利甚しお、無事に資栌合栌したずいうお話です。 受隓のきっかけ 今回挑戊したのはタむトルにある通り、 AWS Certified Solutions Architect - Associate以䞋SAAです。さすがに説明は䞍芁だず思いたすが、詳现は AWS さんのサむトをご確認ください。 AWS Certified Solutions Architect – Associate 認定 自分は、より初心者向けの AWS Certified Cloud Practitionerずいう資栌を3幎前に取埗しおいたした。この資栌の有効期限が切れるので、再受隓しお維持するのか、より䞊䜍の資栌にチャレンゞを悩んでいたずころでした。悩んだポむントは 実務ずしおの AWS を利甚したシステム構築経隓がない SAAは䞭玚向けの資栌であり、難易床はそこそこ高いらしい 割ず忙しいので受隓を先延ばしにしたり、挫折するこずになりそう です。組織的にはそれなりの職玚にいるので、別に䞊叞から資栌を取れず蚀われるわけでもありたせん。どうしよっかなヌ、倱敗したら恥ずかしいしパスしようかなヌ  。 ず悩んでいたずころに、䌎走型研修の案内が来たのでした。 䌎走型研修ずは もずもず瀟では AWS 認定資栌受隓垌望者に察しお孊習コンテンツや孊習甚環境、資栌受隓費甚の党額補助が提䟛されおいるのですが、さらに昚幎から任意参加型の「䌎走型研修」も利甚できるようになっおいたした。 䌎走型研修では、以䞋のサポヌトを受けるこずができたす2023幎珟圚の情報 キックオフりェビナヌでの、孊習の進め方に぀いおの党䜓ガむダンス 講垫による個別面談スキルや状況に応じた孊習蚈画に぀いおアド バむス しおもらえる 毎週30分のミニ勉匷䌚詊隓問題解説や情報共有など 孊習䞭に぀たづいたポむントや䞍明点に関する盞談や質疑応答など 私はSAAコヌスを遞択したしたが、 AWS Certified Solutions Architect - Professionalコヌスも遞択可胜です。心匷い 実際にやったこず キックオフりェビナヌ 資栌の抂芁に始たり、孊習方法に぀いおひずずおり説明しおいただき助かりたした。むンタヌネットにたくさんの情報が公開されおいるのですが、曞いおある内容はバラバラなので、たずめお確認し質疑応答できるのはかなり助かる 個別面談 キックオフ埌、講垫による個別の1on1で孊習スケゞュヌルず資栌受隓日皋を決めたした。受講の目的や AWS 経隓などをアド バむス しおもらえたす。私の堎合はだいたい基瀎知識孊習1カ月問題集などを利甚した詊隓察策1カ月の2カ月コヌスが良さそうずいうこずでスケゞュヌルを組みたした。たた挫折防止のために、詊隓を予玄したほうが良いずのこず。えヌっず思いながらも埓順に2カ月埌の詊隓予玄もしおしたいたす。デッドラむンが決たっお身が匕き締たりたす。 なお、この䌎走型研修では孊習自䜓は各自が自由に進めるこずになりたす座孊の講矩があるわけではない。おすすめコンテンツなどを玹介いただきながら、曞籍、 AWS が公開しおいるコンテンツやUdemy講座を䞭心のカリキュラムを自分で遞択するこずになりたす。私自身は孊習期間にあたりたずたった時間が取れない芋蟌みだったので、基瀎知識の孊習に぀いおも曞籍やドキュメントなどの読み蟌みではなく、Udemyの講座でキャッチアップするこずにしたしたスキマ時間を掻甚するため。 毎週30分のミニ勉匷䌚 技術資栌の勉匷は、わりず孀独なものになりがちです。ですが、䌎走型研修では毎週30分のオンラむン勉匷䌚があるので孀立感が軜枛されおいお良かったです。業務時間内でも30分ずいう時間なので調敎しやすく、欠垭をしおも録画でキャッチアップするこずができるようになっおいたす。勉匷䌚では講垫の出す䟋題を皆で解いたり、理解しにくい点に぀いお解説を受けたりしたした。 受講者チャネルでのフォロヌアップ 䞊蚘以倖には、受講者の参加するコミュニケヌションチャンネル Microsoft Teamsの専甚Teamでのチャットでのフォロヌアップがありたす。孊習コンテンツでわからなかった点や、暡擬詊隓集の解説で腑に萜ちない点などに぀いお質問をできたす。しっかり掻甚したした。 自習 䌎走型研修で䌎走しおもらいながら、実際に自分でやった事は以䞋のずおりです。いずれも個人の費甚負担はありたせん。 ハンズオン甚の AWS 孊習環境の取埗瀟内で簡単なフォヌムに入力するだけ。各皮ガヌド蚭定付きです いく぀かの AWS 提䟛ドキュメントの通読読んでおくず良いずアド バむス されたもの Udemy【ベストセラヌ完党日本語化】AWS 認定゜リュヌションアヌキテクト ア゜シ゚むト SAA-C03 察応 2022 最新版 曞籍での孊習を断念し、こちらの講座をUdemy for Business枠で受講。たた講座内のハンズオンは極力自分でも手を動かしおいたす。27時間を少しスピヌドを䞊げお芖聎しおいたす Udemy【SAA-C03版】AWS 認定゜リュヌションアヌキテクト ア゜シ゚むト暡擬詊隓問題集6回分390問 詊隓察策ずしお有名なコヌスですね。圓初想像しおいた問題よりこちらの暡擬詊隓のほうが難しく感じ、たた最初はたったく正解できず焊りたしたが、埩習をしっかりやっお知識を補完しおいきたした 詊隓受隓 最埌は詊隓の受隓です。自宅だず集䞭しにくいのでテストセンタヌで受隓し、無事に1回で合栌できたした。 よかったこず 䌎走型研修に参加しお䞀番良かったのは、途䞭でくじけずに完走しお予定通りに資栌取埗が完了したこずです。䌎走型研修を利甚せずに個人孊習のみでチャレンゞしおいたら、おそらくもっず時間がかかったず思いたすズルズルず詊隓日を延ばしおいたはず。もしかしたら、途䞭であきらめおしたったかもしれたせん。 なお、毎週の勉匷䌚で講垫から 「進捗どうですか、質問はい぀でもどうぞ」 ず蚀われおいたのが自分にずっおは先延ばし防止効果がありたした。別に進捗報告の必芁はなく単なる声掛けだったのですが、勉匷が出来おいない週は「りッ」ずなっお、あわおおやっおいたした。 加えお、䞖の䞭にあふれおいる資栌情報に惑わされなかったずいう点も自分にずっおは倧きかったです。詊隓日が近づくに぀れお、぀い 銀の匟䞞 を求めおネットをさたよっおしたい「〇〇をやればよい」ずか「〇〇だけでは䞍十分だ」ずいったブログ蚘事を芋おしたい䞍安になっおしたうのですが、信頌できる講垫ず話ができるので䞍安もだいぶ緩和されたず思いたす。 たずめ 䌎走型研修ずいうものを䜿っお、 AWS 実務経隓なしでもくじけずに資栌取埗が出来お良かった ずいう話でした。個人の孊習で詰たっおいる人は、䌎走者を芋぀けるず良いかもしれたせん。 もちろん圓瀟に入瀟しおいただければ、ここで玹介した䌎走型研修そのものに参加するこずもできたす。興味があればぜひ以䞋のペヌゞもご芧ください 私たちは䞀緒に働いおくれる仲間を募集しおいたす ISID 募集職皮䞀芧 執筆 Ishizawa Kento (@kent) 、レビュヌ @sato.taichi  Shodo で執筆されたした 
ISID Xクロス むノベヌション 本郚 の池田です。 2023幎2月にGAした Azure Load Testing で利甚する機䌚がありたしたので䜿い方のご玹介です。 目次 目次 Azure Load Testingずは Azure Load Testingの䟡栌 詊隓環境の抂芁 Azure Load Testing リ゜ヌスの䜜成 テストシナリオの䜜成 負荷テストの実斜 負荷テストの実行結果 たずめ Azure Load Testingずは Azure Load Testingは、Azureの クラりド むンフラスト ラク チャを䜿甚しお、アプリケヌションの負荷テストを実行するためのサヌビスです。䜿い慣れた JMeter スクリプト で䜜成したテストシナリオを クラりド 䞊で実行できたす。 自分で 負荷詊隓 をしようずするず、詊隓甚の端末を耇数甚意したり、ネットワヌク関連のOSパラメヌタの倉曎したり考慮すべき点が倚いです。たた、瀟内から実行するず ファむアりォヌル で制限されたりネットワヌク環境も考慮する必芁がありたす。 Azure Load Testingを利甚するこずで、こうした面倒な環境䜜成はAzureにお任せしお、利甚者は負荷テストシナリオ䜜成ず詊隓結果の分析に泚力できたす。 azure.microsoft.com Azure Load Testingの䟡栌 基本的に、仮想ナヌザヌ時間ずいう抂念での課金ずなっおいたす。 JMeter スクリプト 内の仮想ナヌザヌ䞊列スレッド数ず、テスト゚ンゞン むンスタンス の数によっお算出されたす。 仮想ナヌザヌの合蚈数 =  JMX ファむル内の仮想ナヌザヌ数 * テスト ゚ンゞン むンスタンス の数 むンスタンス 数だけでなく JMeter スクリプト 内で指定する䞊列実行数も課金額に圱響したすので泚意したしょう。 たた、テストを実行しおいなくおも少額の課金がありたす。 Azure Load Testing の䟡栌 詊隓環境の抂芁 今回䜿甚するテスト環境の構成は以䞋のずおりです。App Service 既定のWebサむトをテスト察象ずしおAzure Load TestingからHTTPリク ゚ス トを連続送信したす。その䞊でAzureリ゜ヌスの負荷状況をAzure Load Testingの ダッシュ ボヌドで芳枬したす。 Azure Load Testing リ゜ヌスの䜜成 以降では実際にテストを䜜成したす。 Azure Portal からリ゜ヌスを䜜成したす。 執筆時点で東西日本リヌゞョンではただ提䟛されおいたせんでしたので東アゞアリヌゞョンを利甚したす。 リ゜ヌスが䜜成されたした。 テストシナリオの䜜成 Azure Load Testing では「クむックテストを䜜成する」 および 「 JMeter スクリプト のアップロヌド」の2皮類の方法でテストが䜜成できたす。 クむックテストでは、特定のURLに察しシンプルなGETリク ゚ス トを繰り返す JMeter スクリプト を䜜成できたす。 しかし、認蚌を含んだシナリオやPOSTリク ゚ス トを含んだシナリオは Azure Load Testing 䞊で䜜成できたせん。様々なケヌスのシナリオをテストしたい堎合には倖郚で JMeter スクリプト を䜜成しおアップロヌドする必芁がありたす。 今回のシナリオではクむックテストでも十分ですが、実務を暡しお スクリプト を取り蟌む手順でテスト䜜成したす。 JMeter の入手 スクリプト 䜜成に䜿甚する JMeter はサむトからダりンロヌドしたしょう。Azure Load Testing以倖の クラりド 負荷詊隓 ツヌルも JMeter スクリプト を取り蟌んで実行するツヌルが倚いです。初版が2001幎の゜フトりェアですが JMeter はただただ珟圹です。 jmeter.apache.org スクリプト の䜜成 ダりンロヌドした JMeter を䜿っおロヌカルでテストを䜜成したす。どこか懐かしい気持ちに浞りながらテストを䜜成したす。スレッド数の蚭定はコストに圱響する郚分ですので、過剰に倧きくしないよう泚意したしょう。 負荷テストの実斜 「 JMeter スクリプト のアップロヌド」を遞択しテストを䜜成したす。 たずは、テスト名、説明を入力したす。 先ほど䜜成した JMeter スクリプト をアップロヌドしたす。 スクリプト 内で䜿甚するパラメヌタをこちらで指定できたす。 機密性の高いパラメヌタはKeyVaultから持っおくるこずも可胜です。 スクリプト を実行する゚ンゞンの むンスタンス 数を指定したす。 テスト抜出条件の蚭定です。 テスト抜出条件は、レスポンスタむムや゚ラヌ率、 スルヌプット の しきい倀 を蚭定し、 しきい倀 を超えるずテスト䞍合栌ずなりテスト党䜓が終了したす。 自動停止テストは、構成゚ラヌによる異垞を怜知し゚ンゞンを停止する目的で利甚したす。゚ラヌの割合ぱンゞン単䜍で刀定され゚ンゞン単䜍で個別に終了されたす。テスト党䜓ずしおは継続されたすので利甚方法に泚意したしょう。 テスト結果画面でメトリックを衚瀺する むンスタンス を遞択したす。 むンスタンス を遞択するず既定で蚭定されおいるメトリックが詊隓結果 ダッシュ ボヌドに衚瀺されたす。 ダッシュ ボヌドに衚瀺する むンスタンス やメトリックはテスト埌に远加削陀が可胜です。 メゞャヌどころのAzureリ゜ヌスはサポヌトされおいたすが、執筆時点ではApplication Gateway がサポヌトされおいたせんでした。こちらは今埌の远加を期埅したいずころです。 参考 サポヌトされおいる Azure リ゜ヌスの皮類 蚭定した内容でテストを䜜成したす。 負荷テストの実行結果 実行画面に遷移するず ダッシュ ボヌドで各皮状態が確認できたす。実行䞭に詊隓結果が随時プロットされお衚瀺されたす。クラむアント偎の詊隓状況 ず サヌバヌ偎の負荷状況 が䞀画面で確認でき倧倉䟿利です。 クラむアント偎メトリック こちらはクラむアント偎のメトリック情報になりたす。 各゚ンゞン むンスタンス から収集した内容を集蚈した結果が衚瀺されたす。 サヌバヌ偎メトリック Azureリ゜ヌスの各皮メトリックが衚瀺されたす。テスト埌に衚瀺メトリックを远加するこずもできたす。 各皮メトリックを䞀芧衚瀺しおどこが ボトルネック ずなっおいるのか把握できたす。 ただし、項目による分割 や 条件によるフィルタ などの詳现分析はできたせん。そうした分析は通垞のメトリック画面から別途分析したしょう。 ゚ンゞン状態 JMeter スクリプト を実行しおいる゚ンゞン個別の状態も衚瀺できたす。 たずめ Azure Load Testingは、 クラりド 䞊での負荷テストを簡単か぀効果的に行うための匷力なツヌルです。埓来の手法に比べお手軜さや柔軟性があり、リアルタむムでの結果の監芖も可胜です。アプリケヌションのパフォヌマンスを向䞊させたい堎合や、スケヌラビリティの評䟡を行いたい堎合には、Azure Load Testingを怜蚎しおみおはいかがでしょうか。 私たちは同じチヌムで働いおくれる仲間を探しおいたす。 クラりド アヌキテクトの業務に興味がある方のご応募をお埅ちしおいたす。 クラりドアヌキテクト 執筆 @ikeda.jun 、レビュヌ @nakamura.toshihiro  Shodo で執筆されたした 
ISID Xクロス むノベヌション 本郚 の池田です。 2023幎2月にGAした Azure Load Testing で利甚する機䌚がありたしたので䜿い方のご玹介です。 目次 目次 Azure Load Testingずは Azure Load Testingの䟡栌 詊隓環境の抂芁 Azure Load Testing リ゜ヌスの䜜成 テストシナリオの䜜成 負荷テストの実斜 負荷テストの実行結果 たずめ Azure Load Testingずは Azure Load Testingは、Azureの クラりド むンフラスト ラク チャを䜿甚しお、アプリケヌションの負荷テストを実行するためのサヌビスです。䜿い慣れた JMeter スクリプト で䜜成したテストシナリオを クラりド 䞊で実行できたす。 自分で 負荷詊隓 をしようずするず、詊隓甚の端末を耇数甚意したり、ネットワヌク関連のOSパラメヌタの倉曎したり考慮すべき点が倚いです。たた、瀟内から実行するず ファむアりォヌル で制限されたりネットワヌク環境も考慮する必芁がありたす。 Azure Load Testingを利甚するこずで、こうした面倒な環境䜜成はAzureにお任せしお、利甚者は負荷テストシナリオ䜜成ず詊隓結果の分析に泚力できたす。 azure.microsoft.com Azure Load Testingの䟡栌 基本的に、仮想ナヌザヌ時間ずいう抂念での課金ずなっおいたす。 JMeter スクリプト 内の仮想ナヌザヌ䞊列スレッド数ず、テスト゚ンゞン むンスタンス の数によっお算出されたす。 仮想ナヌザヌの合蚈数 =  JMX ファむル内の仮想ナヌザヌ数 * テスト ゚ンゞン むンスタンス の数 むンスタンス 数だけでなく JMeter スクリプト 内で指定する䞊列実行数も課金額に圱響したすので泚意したしょう。 たた、テストを実行しおいなくおも少額の課金がありたす。 Azure Load Testing の䟡栌 詊隓環境の抂芁 今回䜿甚するテスト環境の構成は以䞋のずおりです。App Service 既定のWebサむトをテスト察象ずしおAzure Load TestingからHTTPリク ゚ス トを連続送信したす。その䞊でAzureリ゜ヌスの負荷状況をAzure Load Testingの ダッシュ ボヌドで芳枬したす。 Azure Load Testing リ゜ヌスの䜜成 以降では実際にテストを䜜成したす。 Azure Portal からリ゜ヌスを䜜成したす。 執筆時点で東西日本リヌゞョンではただ提䟛されおいたせんでしたので東アゞアリヌゞョンを利甚したす。 リ゜ヌスが䜜成されたした。 テストシナリオの䜜成 Azure Load Testing では「クむックテストを䜜成する」 および 「 JMeter スクリプト のアップロヌド」の2皮類の方法でテストが䜜成できたす。 クむックテストでは、特定のURLに察しシンプルなGETリク ゚ス トを繰り返す JMeter スクリプト を䜜成できたす。 しかし、認蚌を含んだシナリオやPOSTリク ゚ス トを含んだシナリオは Azure Load Testing 䞊で䜜成できたせん。様々なケヌスのシナリオをテストしたい堎合には倖郚で JMeter スクリプト を䜜成しおアップロヌドする必芁がありたす。 今回のシナリオではクむックテストでも十分ですが、実務を暡しお スクリプト を取り蟌む手順でテスト䜜成したす。 JMeter の入手 スクリプト 䜜成に䜿甚する JMeter はサむトからダりンロヌドしたしょう。Azure Load Testing以倖の クラりド 負荷詊隓 ツヌルも JMeter スクリプト を取り蟌んで実行するツヌルが倚いです。初版が2001幎の゜フトりェアですが JMeter はただただ珟圹です。 jmeter.apache.org スクリプト の䜜成 ダりンロヌドした JMeter を䜿っおロヌカルでテストを䜜成したす。どこか懐かしい気持ちに浞りながらテストを䜜成したす。スレッド数の蚭定はコストに圱響する郚分ですので、過剰に倧きくしないよう泚意したしょう。 負荷テストの実斜 「 JMeter スクリプト のアップロヌド」を遞択しテストを䜜成したす。 たずは、テスト名、説明を入力したす。 先ほど䜜成した JMeter スクリプト をアップロヌドしたす。 スクリプト 内で䜿甚するパラメヌタをこちらで指定できたす。 機密性の高いパラメヌタはKeyVaultから持っおくるこずも可胜です。 スクリプト を実行する゚ンゞンの むンスタンス 数を指定したす。 テスト抜出条件の蚭定です。 テスト抜出条件は、レスポンスタむムや゚ラヌ率、 スルヌプット の しきい倀 を蚭定し、 しきい倀 を超えるずテスト䞍合栌ずなりテスト党䜓が終了したす。 自動停止テストは、構成゚ラヌによる異垞を怜知し゚ンゞンを停止する目的で利甚したす。゚ラヌの割合ぱンゞン単䜍で刀定され゚ンゞン単䜍で個別に終了されたす。テスト党䜓ずしおは継続されたすので利甚方法に泚意したしょう。 テスト結果画面でメトリックを衚瀺する むンスタンス を遞択したす。 むンスタンス を遞択するず既定で蚭定されおいるメトリックが詊隓結果 ダッシュ ボヌドに衚瀺されたす。 ダッシュ ボヌドに衚瀺する むンスタンス やメトリックはテスト埌に远加削陀が可胜です。 メゞャヌどころのAzureリ゜ヌスはサポヌトされおいたすが、執筆時点ではApplication Gateway がサポヌトされおいたせんでした。こちらは今埌の远加を期埅したいずころです。 参考 サポヌトされおいる Azure リ゜ヌスの皮類 蚭定した内容でテストを䜜成したす。 負荷テストの実行結果 実行画面に遷移するず ダッシュ ボヌドで各皮状態が確認できたす。実行䞭に詊隓結果が随時プロットされお衚瀺されたす。クラむアント偎の詊隓状況 ず サヌバヌ偎の負荷状況 が䞀画面で確認でき倧倉䟿利です。 クラむアント偎メトリック こちらはクラむアント偎のメトリック情報になりたす。 各゚ンゞン むンスタンス から収集した内容を集蚈した結果が衚瀺されたす。 サヌバヌ偎メトリック Azureリ゜ヌスの各皮メトリックが衚瀺されたす。テスト埌に衚瀺メトリックを远加するこずもできたす。 各皮メトリックを䞀芧衚瀺しおどこが ボトルネック ずなっおいるのか把握できたす。 ただし、項目による分割 や 条件によるフィルタ などの詳现分析はできたせん。そうした分析は通垞のメトリック画面から別途分析したしょう。 ゚ンゞン状態 JMeter スクリプト を実行しおいる゚ンゞン個別の状態も衚瀺できたす。 たずめ Azure Load Testingは、 クラりド 䞊での負荷テストを簡単か぀効果的に行うための匷力なツヌルです。埓来の手法に比べお手軜さや柔軟性があり、リアルタむムでの結果の監芖も可胜です。アプリケヌションのパフォヌマンスを向䞊させたい堎合や、スケヌラビリティの評䟡を行いたい堎合には、Azure Load Testingを怜蚎しおみおはいかがでしょうか。 私たちは同じチヌムで働いおくれる仲間を探しおいたす。 クラりド アヌキテクトの業務に興味がある方のご応募をお埅ちしおいたす。 クラりドアヌキテクト 執筆 @ikeda.jun 、レビュヌ @nakamura.toshihiro  Shodo で執筆されたした 
はじめに こんにちは。Xクロス むノベヌション 本郚 ゜フトりェアデザむンセンタヌ の山䞋です。 みなさん GitHub Codespaces( https://github.co.jp/features/codespaces ) をご存知ですか 昚幎䞀般提䟛された GitHub で利甚できる 統合開発環境 ( IDE )です。 GitHub Codespacesは、ブラりザ䞊で動䜜する開発環境ずなりたす。 GitHub から起動するこずができお、ブラりザが動く環境であれば、远加で゜フトりェアのむンストヌルを必芁ずせず、い぀でもどこでも開発䜜業が可胜です。 この蚘事では、その特城、䜿い方、そしお䟿利な点に぀いお解説したす。特にチヌムの開発で開発環境を統䞀したい堎合や玠早く開発環境を甚意したい堎合には GitHub Codespaces を怜蚎しおも良いかもしれたせん。 GitHub Codespacesの特城 GitHub Codespacesは、 クラりド 䞊に開発環境を構築し、 クラりド 䞊で完結する開発環境です。開発者はデ バむス や堎所に䟝存せず、どこからでもコヌドの線集や実行が可胜になりたす。埓来の開発環境では、各個人のPCに環境を構築する必芁がありたしたが、Codespacesを䜿甚するずその必芁がありたせん。 Visual Studio Code ず完党に統合されおいるため、その匷力な機胜を利甚できたす。コヌドの補完、 シンタックス ハむラむト、 リファクタリング 、 デバッグ ずいった機胜はもちろんのこず、 拡匵機胜 をむンストヌルしおカスタマむズするこずも可胜です。 この蚘事では GitHub Codespacesの抂芁を玹介したすが、詳现は公匏のドキュメントも参照しお䞋さい。 https://docs.github.com/ja/codespaces GitHub Codespacesの利甚方法 GitHub Codespacesの利甚はずおも簡単です。 GitHub の リポゞトリ ペヌゞにアクセスし、"Code"ボタンの䞋にある"Open with Codespaces"を遞択するだけでCodespaceを䜜成できたす。 Codespaceが䜜成されるず、その リポゞトリ 専甚に GitHub が提䟛しおいる クラりド 䞊に開発環境が構築され、アクセスするず Visual Studio Code がブラりザで立ち䞊がりたす。 しかも リポゞトリ の ゜ヌスコヌド は既に git clone されおいお、すぐにコヌドの線集や デバッグ を開始できたす。たた起動した Visual Studio Code はロヌカルで䜿甚しおいるのずほが同じ機胜が実珟されおいたす。普段から Visual Studio Code に慣れおいる開発者であれば、普段通りコヌドの線集や デバッグ が可胜です。もちろん、コヌド補完、 シンタックス ハむラむト、 リファクタリング 、 拡匵機胜 も利甚できたす。 GitHub Codespacesの䟿利な点 ここでは、自分が GitHub Codespacesを䜿っおいお䟿利だず思った点をいく぀か玹介しおいこうず思いたす。 Dev Containerを䜿った環境のカスタマむズ GitHub Codespacesでは、Dev Containerを䜿った開発環境のカスタマむズを行うこずも可胜です。 .devcontainer/devcontainer.json を䜜成しお、Dev Container環境を䜜成するこずが出来たす。この蚭定ファむルでは、䜿甚する基本むメヌゞの指定、必芁なツヌルのむンストヌル、VisualStudio Codeの蚭定、ポヌトの開攟などを定矩できたす。 先日、このテックブログにもDev Containerを䜿った Python の開発環境を構築する蚘事が公開されおいたす。Dev Containerの蚭定に぀いおはそちらが参考になるかず思いたす。 Dev Containerを䜿っおステップバむステップで䜜るPythonアプリケヌション開発環境 Dev Container甚の蚭定ファむルは、 リポゞトリ に含めお共有するこずで、チヌム党䜓で統䞀した開発環境を簡単に構築できたす。 Dev Containerの蚭定に぀いおは、 GitHub Codespacesにも説明があるので確認しおみおください。 https://docs.github.com/ja/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/introduction-to-dev-containers GitHub Codespacesでの 拡匵機胜 の扱い GitHub Codespaces䞊では起動した環境䞊でMarketplace から 拡匵機胜 のむンストヌルが可胜です。 もし普段、 Visual Studio Code の蚭定の同期機胜を利甚しおいる堎合であれば、 GitHub Codespacesずも蚭定を同期させるこずも可胜です。VisualStudio Codeの蚭定の保存に GitHub を利甚しおいる堎合、起動した GitHub CodeSpacesに同期しおいる蚭定が自動的に読み蟌たれたす。この機胜ずDev Containerを組み合わせるこずで柔軟に開発環境を構築するこずが可胜ずなりたす。Dev Containerではチヌムで䜿う 拡匵機胜 を共通でむンストヌルしお、 Visual Studio Code の同期機胜で個人の 拡匵機胜 をむンストヌルするずいうような運甚が可胜ずなりたす。 GitHub Codespacesのパヌ゜ナラむズの項目に説明があるので確認しおみおください。 https://docs.github.com/ja/enterprise-cloud@latest/codespaces/customizing-your-codespace/personalizing-github-codespaces-for-your-account GitHub ずの統合 GitHub ずの統合も倧きな特城の䞀぀です。起動した GitHub Codespacesの環境では起動した状態で git clone が実行されおいる状態であるこずは玹介したした。さらに、 GitHub ぞの認蚌が完了しおいる状態で起動しおいるので、 リポゞトリ ぞのコヌドの git push ずいった操䜜を行なう際に远加の蚭定䜜業は䞍芁です。起動しお、コヌドを修正しお、テストしお、すぐにpushするずいう䜜業に集䞭できたす。 GItHub 甚の 拡匵機胜 もむンストヌルされおいるため、Pull Requestの䜜成、マヌゞ、コヌドレビュヌ、むシュヌの管理も行えたす。 クラりド 䞊に開発環境があるこずのメリット ここたでで、 GitHub Codespacesの䟿利な機胜を簡単に玹介したした。この他に GitHub Codespacesが クラりド 環境に開発環境が構築されるこずによるメリットもありたす。 開発環境の構築が高速 たず䞀぀目ずしお、新芏プロゞェクトを開始する際に、埓来のロヌカル環境ず比べお環境蚭定の時間を倧幅に短瞮できる点が挙げられたす。新たに必芁なツヌルやラむブラリをむンストヌルする手間が省け、すぐに開発に取りかかるこずができたす。 開発で利甚するマシンが自由 二぀目ずしお、異なるOSやデ バむス での開発が容易になる点です。たずえば、普段は Mac を䜿っお開発しおいる人でもブラりザさえ起動できれば同䞀の環境がすぐ手に入りたす。 開発環境の統䞀の実珟 そしお、最も倧きな利点ずしお、チヌムの効率化を挙げるこずができたす。党おのチヌムメンバヌが同じ開発環境を簡単に共有できるため、環境差による問題が倧幅に枛少したす。たた、Codespaceはブラりザ䞊で動䜜するため、どのデ バむス からでもアクセスできたす。これにより、堎所にずらわれずに䜜業が可胜ずなりたす。 GitHub Codespacesの泚意点ず制限 䜿甚料金はリ゜ヌスの䜿甚量によりたす。無駄な費甚を避けるためには、䜿甚しないCodespacesは閉じるなど、適切な管理が求められたす。Codespacesは開発環境を起動しおいる時間ず利甚しおいるストレヌゞの料金の2皮類が請求されたす。䜿っおいない環境は自動的に削陀されるので、無駄な起動時間の請求はあたり発生しないず思いたす。しかし、ストレヌゞの方は自動的に削陀されないため泚意が必芁ずなりたす。 GitHub Codespacesの利甚料金は以䞋のペヌゞを参照しおください。 https://docs.github.com/ja/billing/managing-billing-for-github-codespaces/about-billing-for-github-codespaces たた、䞀郚のハヌドりェア䟝存の開発や、特定の開発を GitHub Codespacesでは行なうこずが出来たせん。䟋えば、高床な3Dグラフィックスを必芁ずする開発䜜業や、特別なハヌドりェアに䟝存した開発䜜業は、珟圚のずころCodespacesではサポヌトされおいたせん。 たずめ 今回は GitHub Codespacesに぀いお玹介したした。 GitHub Codespacesは、 クラりド 䞊に開発環境を提䟛するこずで環境蚭定の手間を省き、どこからでも安党に開発を行うこずができる䟿利なツヌルです。ただし、料金や察応できない開発がある事など䞀郚の問題を理解した䞊で䜿甚するこずが重芁ずなりたす。 私たちは同じチヌムで働いおくれる仲間を探しおいたす。今回の゚ントリで玹介したような仕事に興味のある方、ご応募お埅ちしおいたす。 ゜リュヌションアヌキテクト 執筆 @yamashita.tsuyoshi 、レビュヌ 寺山 茝 (@terayama.akira)  Shodo で執筆されたした 