doctorray117 / minecraft-ondemand

Templates to deploy a serverless Minecraft Server on demand in AWS
Apache License 2.0
1.72k stars 119 forks source link

Fix nodejs12 end of support on lambda + Improvement to the minecraft cloudwatch filter + 50% reducement in AWS cost #61

Open AndresArcones opened 1 year ago

AndresArcones commented 1 year ago
  1. https://github.com/doctorray117/minecraft-ondemand/pull/61/commits/7c0bd3843bf9ed9e6628ad6e4481d8f738188573 -> Fixed the nodejs12.x incompatibility on lambda runtime environment. This was caused by a peer dependency on aws-cdk-lib. Once updated this peer dependency the lambda now uses node14js.x which is supported by AWS. Amazon announcement about end of support for nodejs12

  2. https://github.com/doctorray117/minecraft-ondemand/pull/61/commits/00e78252e41320bace3888ecf7b1b939a5fd6d65 -> Updated the cloudWatch filter to be more specific. With this new filter only the DNS calls made by a minecraft client triggers the start of the minecraft server. This removes the problem of other agents pinging the DNS and activating the server incurring in a bigger operative cost

  3. https://github.com/doctorray117/minecraft-ondemand/pull/61/commits/aa57f4fd7f957b292d21ea68e9d5222f1b6d5159 -> Reduced to 50% the costs of AWS. Reduced the cost of the AWS bill by only using 1 hosted zone instead of 2. The cost is reduced from 1 eur month to 0.5 eur month with the same functionality and no regression:

image

Rithmatist commented 1 year ago

It's a nice push, only const dnsFilterPattern = _${config.subdomainPart}._tcp.${config.subdomainPart}.${config.domainName};`

will break it.

AndresArcones commented 1 year ago

Thank you!

The reason to that filter is to avoid DNS checkers, agents and other bots triggering the server. This causes the sever to be on most of the day, starting and stopping continuously. There is an issue of someone also noticing this: #45

In order to fix this, I changed this filter to a very particular filter that focus on filtering the SRV record, which usually is not used by bots but used by Minecraft when connecting or checking for the health of a server. This made that the run of the server was only being triggered by Minecraft clients and not other agents scanning the domain.

For me it has been working like a charm for more than 4 months, with 0 issues. Why do you say it will break things?

Example of what I am talking about, in the cloudwatch logs: image

Rithmatist commented 1 year ago

I tried it with minecraft java edition, and it doesn't seem to trigger the lambda function..

AndresArcones commented 1 year ago

If you have deploy this pull request you also need to perform a manual change on Route53.

Check that you have applied this: https://github.com/doctorray117/minecraft-ondemand/pull/61/commits/aa57f4fd7f957b292d21ea68e9d5222f1b6d5159#diff-b0b0aa5ef277f2eeabb6b5f834c43d21584c4deaa2f5fe02748cf2dd1a3025d0R66 and that you are receiving logs for that specific hosted zone.

Also check if you can see a log similar to this one on the log group (/aws/route53/[subdomain].[domain]), it should appear when you try to connect to the Minecraft server from the Minecraft client:

image

Rithmatist commented 1 year ago

I think the issue has to do with this: image

minecraft._tcp.(subdomain).(domain) your code does this: and this does work if your subdomain is minecraft, lol (subdomain)._tcp.(subdomain).(domain) only not with any other subdomain, guess its easy to fix to.

AndresArcones commented 1 year ago

Oooh, that makes a lot of sense, since the first part is the SRV Minecraft record. This means that it is even more robust, only accepting Minecraft SRV calls to boot the server up.

Thanks a lot for the investigation, I think your suggested fix will work. Going to fix it.

Rithmatist commented 1 year ago

@Colduck const dnsFilterPattern = _${'minecraft'}._tcp.${config.subdomainPart}.${config.domainName};

ah nvm, you pushed the fix it seems, lol

AndresArcones commented 1 year ago

Yes! thanks a lot for the help @Rithmatist!

Everything else worked fine? If you find any other suggestion please let me know!

Rithmatist commented 1 year ago

testing the fix image

edit: Well, it seems to work for java, only not for bedrock (will test few more times to confirm)

AndresArcones commented 1 year ago

hmmm, yeah... I just checked and Minecraft Bedrock does not support SRV records for now: source

I can make the change so this feature only applies to Minecraft Java servers then.

Rithmatist commented 1 year ago

hmmm, yeah... I just checked and Minecraft Bedrock does not support SRV records for now: source

I can make the change so this feature only applies to Minecraft Java servers then.

Yeah, the ones of bedrock are like this:

Untitled

I am using geyser mc ^^

AndresArcones commented 1 year ago

oh that is nice, I did not know about that tool. It will still perform the SRV call when connecting to a Minecraft Java server no? I want to make sure this change works even for those users.

Rithmatist commented 1 year ago

oh that is nice, I did not know about that tool. It will still perform the SRV call when connecting to a Minecraft Java server no? I want to make sure this change works even for those users.

to turn the server on, I think not.. :/

Rithmatist commented 1 year ago

@Colduck got discord?

atm I am rewriting some code so it will support multple servers. like different modpacks, but now it won't work as there can only be 1 log group for the route53 so I had to write a check for existing log group. (and use that one)

edit: will push this fix tomorrow..

Rithmatist commented 1 year ago

replace:

    const subdomain = `${config.subdomainPart}.${config.domainName}`;

    const queryLogGroup = new logs.LogGroup(this, 'LogGroup', {
      logGroupName: `/aws/route53/${subdomain}`,
      retention: RetentionDays.THREE_DAYS,
      removalPolicy: RemovalPolicy.DESTROY,
    });

with:

    const subdomain = `${config.subdomainPart}.${config.domainName}`;

    // Check if a CloudWatch Logs group already exists for the domain
    const existingLogGroup = logs.LogGroup.fromLogGroupName(
      this,
      'ExistingLogGroup',
      `/aws/route53/logs.${config.domainName}`
    );

    const queryLogGroup = existingLogGroup ?? new logs.LogGroup(this, 'LogGroup', {
      logGroupName: `/aws/route53/${subdomain}`,
      retention: RetentionDays.THREE_DAYS,
      removalPolicy: RemovalPolicy.DESTROY,
    });

Note, this would only work if your current log-group name is /aws/route53/logs.domainhere.com

Edit: This isn't the right approach, as it will only allow two subscription filters per log group. I am currently working on revamping the Lambda function and modifying the subscription filter to work with wildcards. This will enable the Lambda function to decode the logs and determine which server to turn on.

AndresArcones commented 1 year ago

hey! Were you able to add support also for bedrock servers? If not we can just keep this improvement for java servers, since it is a big improvement in cost and server usage.