Hey. If you want to know what to do after you set the server up, visit my blog here. Cameron's Blog
Thursday, February 21, 2013
Sunday, January 13, 2013
Solving the ssh connection timeout problem
As I mentioned in my first post about setting up a Minecraft server in ec2, one of the main annoyances for my son with the original setup was that unless someone was constantly typing commands into the server, eventually the ssh connection would be closed due to inactivity and the server along with it. I want to solve that problem now.
The specific problem that we're trying to solve reveals itself when the Minecraft server stops responding to the minecraft clients. When we flip to the terminal window where we have the ssh connection to the EC2 instance, we see something like:
Due to the interactive nature of the Minecraft server's console, what we really want is to be able to start up the server; enter a few commands; shut down the ssh client, while keeping the server alive; reconnect to the instance and server console to enter some more commands; repeat. This is exactly the functionality provided by a terminal multiplexer. There a couple of different choices, but I have found that I like tmux. It's not installed in the image that we used to create our EC2 instance, so we have to install it ourselves. Ssh into the EC2 instance and execute the following command:
sudo yum install tmux.x86_64
After it's completed, the tmux command will be available. Now, when we first connect to the EC2 instance, before we start the Minecraft server, I run:
tmux new-session -s minecraft -n minecraft
This command creates a new tmux session with the name minecraft that will own the Minecraft server process. I see this screen:
It looks just like a normal terminal, except for the green bar at the bottom - which is how I know that I'm running inside of tmux. I execute the commands for starting up the Minecraft server and the console starts printing out information as normal. The difference is that now I can detach from this session - even terminate the ssh connection - and the server will continue running. To detach, I have to enter the keyboard combination of <CTRL-b> d. If you're not familiar with that notation, this means:
We can now exit from the ssh session; wait the few minutes for the server to start; go to a different computer, ssh to the EC2 instance and reconnect to the tmux session which contains the running Minecraft server process:
tmux attach -t minecraft
No more Connection reset by peer error messages and the sudden death of your Minecraft server!
The specific problem that we're trying to solve reveals itself when the Minecraft server stops responding to the minecraft clients. When we flip to the terminal window where we have the ssh connection to the EC2 instance, we see something like:
Read from remote host mctesting.no-ip.org: Connection reset by peerWhat has happened is that there hasn't been any activity on the ssh connection for some period of time, so it's terminated. When that occurs, any processes on the EC2 instance that were owned by the ssh client are also killed. In this case, that includes the java process that is our Minecraft server.
Connection to mctesting.no-ip.org closed.
Due to the interactive nature of the Minecraft server's console, what we really want is to be able to start up the server; enter a few commands; shut down the ssh client, while keeping the server alive; reconnect to the instance and server console to enter some more commands; repeat. This is exactly the functionality provided by a terminal multiplexer. There a couple of different choices, but I have found that I like tmux. It's not installed in the image that we used to create our EC2 instance, so we have to install it ourselves. Ssh into the EC2 instance and execute the following command:
sudo yum install tmux.x86_64
After it's completed, the tmux command will be available. Now, when we first connect to the EC2 instance, before we start the Minecraft server, I run:
tmux new-session -s minecraft -n minecraft
This command creates a new tmux session with the name minecraft that will own the Minecraft server process. I see this screen:
It looks just like a normal terminal, except for the green bar at the bottom - which is how I know that I'm running inside of tmux. I execute the commands for starting up the Minecraft server and the console starts printing out information as normal. The difference is that now I can detach from this session - even terminate the ssh connection - and the server will continue running. To detach, I have to enter the keyboard combination of <CTRL-b> d. If you're not familiar with that notation, this means:
- press-and-hold the control key
- press-and release the b key
- release the control key
- press-and-release the d key
We can now exit from the ssh session; wait the few minutes for the server to start; go to a different computer, ssh to the EC2 instance and reconnect to the tmux session which contains the running Minecraft server process:
tmux attach -t minecraft
No more Connection reset by peer error messages and the sudden death of your Minecraft server!
Friday, January 11, 2013
Automating a Minecraft server in EC2 - part 2
In part one of the automating a minecraft server in EC2 series, I got the environment set up for using the AWS command line program. Now, I will create, start and stop the server using it.
To start the server, I need to determine a few things:
- Region : I'll use us-east-1. You should use whichever one is closest to you
- Key-name: This is the name of the key pair that will be used to authenticate ssh connections. In my first post describing how to set up a minecraft server manually, I created the EC2Minecraftserver key pair.
- Security-Group: This is the name of the security group that determines what ports are available for communication on the server. In my first post, I created a Minecraft security group which opened port 25565.
- Instance-type: I still want to run as close to free as possible, so I'm using the micro instance (t1.micro).
- Image: This is the machine image that will be instantiated for our server. I'm going to stick with the relatively vanilla Amazon Linux AMI (ami-1624987f) that we used in the first post.
These choices yield the following command:
aws --region us-east-1 ec2 run-instances --image-id ami-1624987f --min-count 1 --max-count 1 --key-name EC2Minecraftserver --security-groups Minecraft --instance-type t1.micro
When this is executed, I receive a JSON result, which includes all of the settings for that instance. The most important one is the instance-id. In my case, that looked like:
"instanceId": "i-d37885a2",
Another key value is the state of the instance. On executing the command it should be pending, which will look like:
"instanceState": {
"code": 0,
"name": "pending"
},
Within a short period of time (a minute or so), the instance should be running. You can confirm this by executing the following command and looking for the instanceState:
aws --region us-east-1 ec2 describe-instances --instance-ids i-d37885a2
If the instance is running, it will look like:
"instanceState": {
"code": 16,
"name": "running"
},
In order to actually connect to the instance, I need to know the DNS name for the instance. This is also returned by the describe-instances call:
"dnsName": "ec2-174-129-160-109.compute-1.amazonaws.com"
At this point, though, I don't want to use that DNS name as we have not yet associated the instance with an Elastic IP address, so this DNS name is ephemeral. In other words, each time I stop and restart the instance, I may get a different DNS name. When I allocate an Elastic IP address, that DNS name/IP pair is mine to associate with any instance. Each time I stop and start an instance, it can retain the same external address. If I mess up and need to terminate the instance and start-over, I can still associate that same Elastic IP address to the brand-new server. This means I don't have to tell my son and his friends a new DNS name each time I stop/start/terminate the server instance. Right now, I can have up to three Elastic IP addresses as part of the first year Free Tier at Amazon.
I allocate an Elastic IP address:
aws ec2 --region us-east-1 allocate-address
and note the public IP address returned:
"publicIp": "54.235.205.83",
I associate the public IP address returned with the IP I started:
aws ec2 --region us-east-1 associate-address --instance-id i-d37885a2 --public-ip 54.235.205.83
A describe-instances call returns the Elastic IP address:
"dnsName": "ec2-54-235-205-83.compute-1.amazonaws.com",
As this was just a test , I don't want to keep that Elastic IP address (they are free as long as they are associated with a running instance, but they cost 1/2 cent per hour otherwise):
aws ec2 --region us-east-1 release-address --public-ip 54.235.205.83
The last three commands I need to know allow me to stop the instance when my son is finished with it for a while; start it up when he's ready to play minecraft again; terminate it when we get the system into an unrecoverable state and need to start-over.
Each time we stop and restart the instance, we need to re-associate the Elastic IP with the instance by re-executing the associate-address call above (when you see <IP address>, it means use the actual publicIP address returned when the address was allocated; similarly for <Instance ID>, use the instance ID that was returned when instance was originally created):
Create the instance
aws --region us-east-1 ec2 run-instances --image-id ami-1624987f --min-count 1 --max-count 1 --key-name EC2Minecraftserver --security-groups Minecraft --instance-type t1.micro
aws ec2 --region us-east-1 associate-address --instance-id <Instance ID> --public-ip <IP Address>
Stop the instance
aws --region us-east-1 ec2 stop-instances --instance-id <Instance ID>
Restart the instance
aws --region us-east-1 ec2 start-instances --instance-id <Instance ID>
aws ec2 --region us-east-1 associate-address --instance-id <Instance ID> --public-ip <IP Address>
Kill the instance if you can't get it to recover by just restarting it
aws --region us-east-1 ec2 terminate-instances --instance-id <Instance ID>
Automating a Minecraft server in EC2 - part 1
In my first post, I described how I set up a minecraft server in Amazon's Elastic Compute Cloud (EC2) by hand. In this post, I will begin exploring how to automate that process so that when I mess the server up, I can start over with very little effort.
The first thing I want to automate is all of the interactions with the web user interface required to create an instance, launch it and bind it to an elastic IP address. All of these interactions when moved to a command-line/API script require a different form of credential than the SSH key pairs I used in the last post, so the first step is to get those credentials.
Getting Credentials
This is done through Amazon's Identity and Access Management (IAM) system. I'll create a group whose members will be allowed to manage EC2, create a user and then add that user to the group. The command-line scripts will use that user's credentials to perform all EC2 operations. I start at the IAM console, where I select "Create a New Group of Users":
When the wizard launches, I give the group a meaningful name. I choose EC2Admins as all members of the group will be able to administer my EC2 instances.
I now apply a permissions policy to the group. This is where I indicate that all members of the group will have full access to EC2 by selecting the "Amazon EC2 Full Access" Policy Template.
This next step in the wizard shows what that policy template looks like in detail. I don't want to do any customization at this point, so I just continue past this step.
At this next step, I create a user and add it to the group. I chose "my_user_name" for this example, but you can pick any name you like. It is very important that you select "Generate an access key for each user" as this is the key that will be used to connect to authenticate with Amazon when we perform any operations on the instances.
I get a chance to confirm my choices. Everything looks good, so I click "Finish"
At this step, I get my only chance to download the credentials for the user.
I chose to open the Show/Hide Users Security Credentials so I could copy the credentials into a text file. I named the file aws.config.txt and placed the file in my ~/.ssh directory. I'll come back to this file in a moment, but be sure that you have copied your security credentials (not the ones from this blog post) before you close that window!
Setting up the Scripting Environment
I haven't done much with python, but I've wanted to learn it, so I'm going to use the python version of the AWS command line tools. I use three different environments (Mac, Linux and Windows) so I need to work out the set up for each operating system.The Mac and the Ubuntu Linux machines already had python and easy_install installed. For the Windows PC, I re-ran the cygwin setup program and added python. I also added easy_install there by opening http://peak.telecommunity.com/dist/ez_setup.py, saving the file to a temp directory, navigating to that directory and then executing the saved file with python
cd /cygdrive/c/temp
python ez_setup.py -U setuptools
I then followed Amazon's instructions for getting set up with the AWS Command Line Interface (CLI) on all three machines:
easy_install awscli
I could tell the installation was successful when I executed aws help and saw the associated help text.
The final preparatory step is to associate the credentials with the scripting environment. I modified the file that I saved above to match the structure required of the AWS configuration file.
[default]
aws_access_key_id = AKIAIQW7AJVBDDLBXDNQ
aws_secret_access_key = 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
By adding the following lines to my .bash_profile, I set the environment variable to point to that file each time I log in.
AWS_CONFIG_FILE=~/.ssh/aws.config.txt
export AWS_CONFIG_FILE
If everything is set up correctly, then I should get a JSON result back fully describing the instance I set up from the web console earlier when I run this command:
aws --region us-east-1 ec2 describe-instances
In the next post, I'll use this scripting environment to create, start and stop instances.
Troubleshooting
Some possible errors and how to deal with them:- 'NoneType' object has no attribute 'access_key'
export AWS_CONFIG_FILE=~/.ssh/aws.config.txt
Another possibility is that the first line of text in your configuration file has a word other than default between the square brackets. Make sure there are no spaces between the letters and the square brackets.
- The specified config file (/home/user_name/.ssh/aws.config.txt) could not be found.
- Unable to parse config file: /home/doug/.ssh/aws.config.txt
- A client error (AuthFailure) occurred: AWS was not able to validate the provided access credentials
- A client error (UnauthorizedOperation) occurred: You are not authorized to perform this operation.
- "reservationSet": [],
Subscribe to:
Posts (Atom)
