Skip to main content

Elastic Load Balancing to VPC instances on a private subnet

Generally, when creating an elastic load balancer inside a VPC you are load balancing to a set of servers that are inside a public subnet (which routes through the IGW device). Each of these instances has it’s own elastic IP and while elastic IPs are free you may want to move your web servers inside a private subnet to avoid placing a public IP on them.

I have had discussions with amazon support and generally gotten mixed responses. The documentation is not exactly clear in the required configuration. First, the important thing to understand is that when you create a load balancer you are essentially creating hidden instances inside that subnet which have two IPs (a public and a private). If we wanted to have our public load balancer able to serve traffic from a set of servers on a private subnet then we need to create public subnets for the hidden elastic load balancer instances to live in.

Let’s say we have three webservers. Each of these are in a different availability zone and existing inside a private subnet which routes traffic through a NAT device. These instances do NOT have public IPs.

Hostname IP Address
www-1.example.com 10.200.21.21
www-2.example.com 10.200.22.21
www-3.example.com 10.200.23.21

We need to create three public subnets with the following address spacing

10.200.11.0/24
10.200.12.0/24
10.200.13.0/24

The subnets we just created are associated with our public routing table which will route traffic through the Internet Gateway Device. We can now create an Elastic Load Balancer using the documentation link above. When you get to the page to select the subnets you want to make sure you select the subnets we just created. You then want to select the instances that you wish to load balance traffic to. You should make sure you configure your health checks correct and assuming your security groups allow traffic from the Elastic Load balancers subnet or security group to the webservers your instances will soon report healthy and you will be able to access your content using the new load balancer URL (assuming your configuration permits this).

Akismet: Simple Comment Spam Filtering

So I have developed a few websites in the past year that included blogs. One of the big issues is comment spam. Normally the standard procedure has been to implement reCaptcha. While I do love helping to digitze books recently several methods have come to light forbypassing reCaptcha. The amount of Viagra comments started to get to an extreme. There are certainly some less creative solutions such as automatically dropping comments with certain keywords, or blocking comments from outside of the country. You could also simply block all comments by default and approve comments as they come but that inhibits active discussion on posts, and frankly is kind of crappy.

I did some research and happened upon Akismet. This service offers a pay as much as you want model which I love. You can pay as little as nothing or as much as 120/yr. Now that I found a service the question came down to implementation. I found this fantastic gem called rakismet which offers easy integration and provides helper methods for checking if a message is spam, and best of all, letting them know if a comment was truly spam or not via api calls.

I wont dive into the setup of the Gem because the instructions are really fantastic. I do want to briefly talk a bit about a great way to implement this functionality to place comments marked as spam into a queue for approval or deletion.

My Comment Model includes:

The important thing here is really the approved bit, as by default, comments are approved. When you iterate of your comments you can check to see if approved is true before displaying the comment in your view.

Our comment controller might look something like…

The important thing to note in the exampe above is the spam method. When we call it on comment this reaches out to the Akismet API and checks the comment to see if its considered spam. The API will return either true or false, which if true means the comment is spam and thus sets its approved status to false. You can now leverage this data in your admin panel or whever to see your comments that are pending approval.

So the best thing about this service, is that you get to help improve it. You can use something like the below to help Akismet learn which comments are spam and which arent.

 

Overall my experience with the service so far has been excellent. Integration is easy with any rails app, documentation is excellent, and you cant beat the pricing model of pay whatever you want. You’re users are happy because they dont have to try to guess the hard to read words, solve a math problem, orselect the cats.

TL;DR: Captcha’s are dead. Get rid of them, and start effortlessly filtering comments with Akismet.

Multi SSH (MuSSH)

Recently I ran into a situation where I needed to run a command on a large number of servers. There are existing libraries out there, but I found that they wouldnt run under OS X for one reason or another, or they didnt handle a large number of servers very well. Normally I do this with something along the lines of

And while the above does work it suffers from being a big loop. It connects to a server, runs the command, disconnects, and connects to the next and so on.

 

I ended up putting something together in ruby which can either take a comma delimited list on the command line or read from a file if you have a large number of hosts or happen to use the same hosts often

You can see the latest code here on github.

Resolving a large list of domains from CSV

This script is pretty simple, I was tasked with taking a CSV file that had about 5000 domains and seeing if any resolved to a particular IP address.

Straightforward and does the trick

Installing PG gem under OS X when Bundle install fails

The other day a coworker ran into an issue installing the postgres gem on her laptop while doing a bundle install. I have ran into the issue a couple of times myself and its a quick fix however the first time I encountered it it took a few minutes longer than it probably should to figure out.


 

This is a pretty simple fix, first we need to ensure that you have postgres installed. You can download and install postgres here: http://www.postgresql.org/download/

After that is installed, simple locate your pg_config file (an alernative would be to do a (find / -type d -name “pg_config”) although this may take a while. You could also do which psql91 (or whatever version you have installed) and look at the symlink in that directory. Generally your install should be in /opt/local/lib/.

What we are looking for is the pg_config directory we simply install the gem manually by running the below.

And there we go installed and a bundle install should now complete without issue.

Mass Updating Amazon Web Services S3 Permissions

Recently I ran into an issue where I needed to update the Access Control Lists(ACLs) for about 1.5 Million pictures. Amazon currently doesnt provide an easy way to do this and current tools such as 3Hub and such cant handle such a large volume.

By far the biggest flaw when it comes to mass updating in current S3 utilities is the lack of threading. With 3Hub I was able to update the permissions on around 400k images in a 30 hour period. I did not want to leave my laptop at work yet again so I decided to just write a script that could do this quicker and run on a server.
Here is the code that I used to accomplish this.
The config file is pretty straightforward and goes into a directory called config
Now obviously the script above would need to be adapted, in my case I had a list of ids from 1 to 9999. My method above is just a quick and dirty way to thread the application without having to pull a list of the IDs and feed it out. In our development environment which contains about 300,000 images I was able to update all of the permissions in about an hour.
Something to note –  If you run this script and update the ACLs it replaces your ACls with the above. So if have 5 different ACLs be sure to set them all above so that they are applied. If you need to only change a specific ACL and not the others then this script would need to be adapted to do that.

Sticky Session Load Balancing with mod_balancer

When load balancing across multiple application servers that are cache dependent you can use sticky sessions to easily ensure a browser request is routed to the same applicaton server each time. To do this we use the mod_headers module along with mod_balancer and mod_proxy.
When a request comes in the BALANCER_SESSION_ROUTE is checked (this is set as “route” in your site cookie). If this is unset then your request is assigned a new route id and your request is routed on its merry way. If your BALANCER_SESSION_ROUTE does not match the BALANCER_WORKER_ROUTE then you are assigned a new route id. This can happen if a server is removed from the pool.
Implementing this is into an existing setup is actually pretty simple. Lets use an example configuration.
We append the routeid to the end of each of our routes. We then must insert this route into the site cookie using mod_headers
Next we make ProxyPass follow the route using sticky sessions.
Here is an example of a full configuration.
And thats it, now you need to restart apache and run a quick test using wget.
Here we can see that the routeID is properly being stored in the cookie. An alternative method for checking would be to use firebug or developer tools in chrome and checking the contents of your site cookie. Using this method you should see the same routeID as well and can see that it does not change as you flip through pages.

Using tmux for collaboration

Summary
An old coworker of mine recently showed me the wonders of using tmux when pairing up. Using tmux you can easily share your screen with multiple people and both observe and make changes. Rather than pull a coworker from across the call or use a join.me session you can easily show them something with just a couple of quick commands.
Setup
Copy the below to your .bash_profile and then source that file (source ~/.bash_profile).
Usage
Creating
To start a session that someone can join, simply type tmux-start and a session name.
The way tmux works is it drops a pid file in /tmp with your session name. Normally this pid is readable by the user that created it. The chmod 777 changes the file permissions to allow this to be readable by all.
Listing
You can list the current sessions by typing tmux-list. This will spit out a list of the users and the name of the session for which you can join.
Joining
You can join a session by typing tmux-join and the session name.