Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Created an EC2 Launch Template, supporting Role and Security Group for ad-hoc maintenance of the EFS. #33

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions cdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- AWS Account
- AWS CLI installed and configured
- Domain name with public DNS served from Route 53
- an EC2 Key pair (optional)

**Note:** Installing CDK globally is not required.

Expand Down Expand Up @@ -97,6 +98,55 @@ Alternatively, you can delete the `minecraft-server-stack` first, then the
`minecraft-domain-stack` from the [AWS Console](https://console.aws.amazon.com/cloudformation/).

## Advanced Usage
### EFS Maintenance
1. Log into your AWS console's EC2 section for your chosen region.
2. From the top right corner choose to launch an instance from a launch template ![Launch Instance](../docs/screenshots/efs1_launch_instance.png)
1. If you have more than one version, pick the highest revision.
3. Select the launch template created by your stack ![Select Template](../docs/screenshots/efs2_select_a_template.png)
4. Select the most recent x86 AMI ![Select AMI](../docs/screenshots/efs3_select_ami.png)
5. Select the cheapest instance type ![Instance Type](../docs/screenshots/efs4_select_instance_type.png)
6. Select your key pair to log in.
7. Select one of the public subnets created by your stack ![Network](../docs/screenshots/efs5_network.png)
8. Change anything else you want (though the defaults should _just work_) and launch the instance ![Launched](../docs/screenshots/efs6_launched.png)
9. Click the instance id to go to the lust of instances again and wait for your instance to show as running.
10. Once running clik the instance id to get the details of its external IP address ![IP](../docs/screenshots/efs7_ip.png)
11. Use ssh with your local key file to log in
```
ssh -i /path/to/key-file.pem ec2-user@YOUR_INSTANCE_IP
```
12. The FS should mount under `/mnt/efs/fs1/minecraft` after a minute or two ![Logged In](../docs/screenshots/efs8_logged_in.png)
13. When you are done shut down the instance to terminate it
```
sudo shutdown now
```

**Example Commands**
1. Back-up world to a local machine
```
# On ec2 instance
cd /mnt/efs/fs1/minecraft/
tar cjvf world.tar.bz2 world
# on local machine
scp -i /path/to/key-file.pem ec2-user@YOUR_INSTANCE_IP:/mnt/efs/fs1/minecraft/world.tar.bz2 .
```
2. Upload a world from a local machine
```
# on local machine
scp -i /path/to/key-file.pem world.tar.bz2 ec2-user@YOUR_INSTANCE_IP:/mnt/efs/fs1/minecraft/
# On ec2 instance
cd /mnt/efs/fs1/minecraft/
rm -rf world
tar xjvf world.tar.bz2
```
3. Remove everything but the world and backups (useful for modded server version changes).
```
# On ec2 instance
cd /mnt/efs/fs1/minecraft/
shopt -s extglob
rm -rfv !("backups"|"world")
rm .ftb-installed
shopt -u extglob
```

## FAQ

Expand Down
52 changes: 52 additions & 0 deletions cdk/lib/minecraft-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { constants } from './constants';
import { SSMParameterReader } from './ssm-parameter-reader';
import { StackConfig } from './types';
import { getMinecraftServerConfig, isDockerInstalled } from './util';
import { UserData } from 'aws-cdk-lib/lib/aws-ec2';

interface MinecraftStackProps extends StackProps {
config: Readonly<StackConfig>;
Expand Down Expand Up @@ -322,5 +323,56 @@ export class MinecraftStack extends Stack {
],
});
iamRoute53Policy.attachToRole(ecsTaskRole);

const efsMaintenanceInstanceRole = new iam.Role(this, 'EFSMaintenanceRole', {
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
description: 'Minecraft EC2 instance role',
});
efsReadWriteDataPolicy.attachToRole(efsMaintenanceInstanceRole);

const efsMaintenanceSecurityGroup = new ec2.SecurityGroup(
this,
'EfsMaintenanceSecurityGroup',
{
vpc,
description: 'Security group for Minecraft on-demand EFS Maintenance Instances',
}
);

efsMaintenanceSecurityGroup.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.tcp(22)
);

/* Allow access to EFS from Fargate service security group */
fileSystem.connections.allowDefaultPortFrom(
efsMaintenanceSecurityGroup
);

const efsMaintenanceLaunchTemplate = new ec2.LaunchTemplate(this, 'EFSMaintenanceLaunchTemplate', {
userData: UserData.custom(`#cloud-config
package_update: true
package_upgrade: true
runcmd:
- yum install -y amazon-efs-utils
- apt-get -y install amazon-efs-utils
- yum install -y nfs-utils
- apt-get -y install nfs-common
- file_system_id_1=${fileSystem.fileSystemId}
- efs_mount_point_1=/mnt/efs/fs1
- mkdir -p "\${efs_mount_point_1}"
- test -f "/sbin/mount.efs" && printf "\\n\${file_system_id_1}:/ \${efs_mount_point_1} efs iam,tls,_netdev\\n" >> /etc/fstab || printf "\\n\${file_system_id_1}.efs.${config.serverRegion}.amazonaws.com:/ \${efs_mount_point_1} nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport,_netdev 0 0\\n" >> /etc/fstab
- test -f "/sbin/mount.efs" && grep -ozP 'client-info]\\nsource' '/etc/amazon/efs/efs-utils.conf'; if [[ $? == 1 ]]; then printf "\\n[client-info]\\nsource=liw\\n" >> /etc/amazon/efs/efs-utils.conf; fi;
- retryCnt=15; waitTime=30; while true; do mount -a -t efs,nfs4 defaults; if [ $? = 0 ] || [ $retryCnt -lt 1 ]; then echo File system mounted successfully; break; fi; echo File system not available, retrying to mount.; ((retryCnt--)); sleep $waitTime; done;
`),
role: efsMaintenanceInstanceRole,
spotOptions: {
interruptionBehavior: ec2.SpotInstanceInterruption.TERMINATE,
requestType: ec2.SpotRequestType.ONE_TIME
},
securityGroup: efsMaintenanceSecurityGroup,
instanceInitiatedShutdownBehavior: ec2.InstanceInitiatedShutdownBehavior.TERMINATE
});

}
}
Binary file added docs/screenshots/efs1_launch_instance.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/efs2_select_a_template.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/efs3_select_ami.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/efs4_select_instance_type.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/efs5_network.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/efs6_launched.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/efs7_ip.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/efs8_logged_in.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.