#347 Rubber and Amazon EC2
Deploying to Amazon EC2 allows you to scale an application quickly. Learn how to use Rubber to deploy to the cloud with just a few commands and monitor the cluster with various web tools.
- Download:
- source code
- mp4
- m4v
- webm
- ogv
Excellent episode, thank you
That was one of the best episodes yet. Thank you so much.
Nice episode, but I have a simple question. How can I add a Faye server (or any other independent server) to the application?
Thanks,
Andrei
The best way would be to add a rubber template to the mix. You can check out the existing templates here: https://github.com/wr0ngway/rubber/tree/master/templates
Another method would be to simply spin up a server with rubber, ssh in and setup faye manually.
Thanks for the reply. It might sound silly, but can you access the server via ssh? I haven't tried it yet, but I am considering moving my application to EC2.
Thanks again.
I haven't watched the episode yet but I wouldn't see why not. SSH is standard for any linux setup I've worked with. Also typically Capistrano uses it for tunneling.
Yea! That's my favorite part of rubber, it doesn't abstract anything away from you.
tunneling in, use your ec2 keypair and ssh root@name, i.e.: ssh -i ~/.ec2/gsg-keypair root@app01.foo.com
Once you're in, you can find all your config files where they're supposed to be or your app in the /mnt directory.
Hey, Ryan, thanks for the episode!
This may be a silly question, but does rubber also install all we need in the EC2 to deploy?
Thanks in advance.
Yes. Rubber hooks into capistrano and installs all the packages that are needed for the given template. Adding more aptitude packages is easy and all contained within the Rubber config files.
Wow, that's really sweet.
Thanks for the help.
Awesome!
Sorry if this is a noobish question, but why is the application being split into web, app, and db instances? I don't really understand that part. Is that just for Amazon or cloud-based load balancing, or is that something that I should be doing on a VPS? Thanks
splitting up the web app and db instances in rubber is more about how Rubber handles 'roles'. There can also be a redis role, a resque role, a sphinx role etc. It allows rubber to be very modular and scalable. You can place different roles on different hardware for instance.
Okay, thanks Scott.
Thanks Brian, for breaking the noobish question ice. Here's another one: Would anybody care to weigh in on the pros & cons of this EC2 service vs. using a VPS? Or maybe offer a link to an article that hits this question?
Thanks everybody and thanks again Ryan.
This is a big topic.
The simple aspect that my experience lends is just a very scalable system. With rubber, I have roles for each aspect of my application and spinning up a new server to handle more application resources takes minutes. Interfacing ec2's with other amazon services is ridiculously easy. Scaling horizontally and vertically is simplified especially with tools like Rubber.
I've been using Rubber for a bit over a year now and absolutely love it. Version 2.0 is a huge improvement as well.
Do you have experience with installing RMagick with Rubber on an instance? What is the best way to do it? I can simply ssh to the instance and install it manually, but it doesn't feel right.
There's a much better way.
First off, make sure you have rmagick in your gemfile.
Then in your rubber.yml file there should be a setting for 'packages'. Somewhere around line 189. You can simply add aptitude packages in this array.
Add to the array, 'imagemagick' and possibly libmagick9-dev. Simply cap rubber:bootstrap your instance and it will install these packages for you along with the new gem in your gemfile. Paperclip and other image processing should be good to go.
Also. There's a wealth of rubber information on the google discussion group from the last few years. http://groups.google.com/group/rubber-ec2
Note, you can also install packages on a template by template basis. Like only installing imagemagick when you are using passenger etc. The rubber.yml packages line will install it on all your severs.
Thank you very much, Scott!
I had to add "libmagickwand-dev" as well to make it work.
Rubber seems to be a really great tool :)
'libmagick9-dev' is no longer available, adding 'imagemagick, libmagickwand-dev' to packages: in rubber.yml is worked for me.
Ill add another new question re rubber.
If you start of with a small app so only one server required for all roles how well does rubber handle breaking this up once hopefully you start to get bigger. ie creating separate roes for App, Web & DB.
Would you have to convert your existing role to be just DB??
Also what about auto scaling. Is there a way to have rubber auto scale app and db slave servers if required?
And one more to chuck in what about setting up staging environment?
But like Alexander has said this seems a great tool.
I've done all these things in the past year so I'll pitch in.
The best part of using ec2's is you can get your servers to a stateless point. Where you can drop your existing servers at the drop of the hat if they have redundancies.
If you were to have a web, app, db server. to split that up you'd start by setting up a new db server where it's solely db and dump your current db over there. I personally love using RDS so I always have a separate db setup to host and I never have to worry about it. Alternatively, you could setup a slave on a separate server and then promote it later.
You can then set up more separate app servers, which become part of the network so they'll be managing some load but still working with the web role on the original server.
Finally, you can pull out the web role into it's own and the two web servers will work fine and you can drop one seamlessly.
Auto scaling is a bit different. Amazon does have ways of flashing your current image and they'll start up a new one if certain requirements are met. I haven't played with this as much. As long as you're paying attention, you can scale yourself really quickly in rubber without any new configuratio.
Staging environment is just like any rails env. set up a new staging.rb file in the environments and when you do cap rubber:create_staging, prefix it with RUBBER_ENV=staging cap rubber:create_staging so it setups up an entire rubber configuration within that environment. Separates out the instance yaml's and everything.
Thanks Scott, Going to give rubber a go I recon.
I'm just starting to look at rubber, but it looks like it's doing much of what I was building by hand. Can you share how you configured it to work with RDS?
Hi Scott.
I need to install Libsndfile as a binary instance... How is that done, do you know?
Thank you for this very nice cast. Rubber is impressive and makes great use of Capistrano's power. Can it handle non-rails applications and other cloud providers (I am guessing no and no)?
Hi. I'm one of the rubber devs. It can handle non-Rails applications just fine. I've personally deployed a couple Sinatra apps with in. And I even use Rubber to manage a few servers that just run Java apps and quite a few Windows machines on EC 2 (note that Rubber can only create/destroy/reboot Windows -- no app deploy).
It is currently EC 2 only. Part of the rubber 2 revamp was to base it on fog, which opens up the opportunity to run on a lot more providers. But, as of yet, we haven't done the work to finish this up. It's on the docket though.
Very nice! Looking forward to the upcoming releases.
NOOB - when I'm creating the EC2 instance, Amazon wants me to select a AMI (stack). Which one do you select?
Rubber should handle this for you. By default, the current version of rubber (2.0.1) uses ami-3c994355, which corresponds to the 64-bit instance-store Ubuntu 12.04 LTS image.
Feel free to hop onto #rubberec2 on Freenode and I'll try to help out.
AMI code for a kind of Image is different in each region, for example:
Ubuntu 12.04 LTS
Singapore:
64 bit: ami-a4ca8df6, 32 bit: ami-a6ca8df4
Northern Virginia:
64 bit: ami-a29943cb, 32 bit: ami-ac9943c5
I got the codes when i try to launch a new instance from AWS console and copy it. But maybe there's a better way to get it :)
NOOB - Getting error
* executing "sudo -p 'sudo password: ' bash -l -c 'cp /home/ubuntu/.ssh/authorized_keys /root/.ssh/'"
servers: ["50.17.145.140"]
.. ** Failed to connect to 50.17.145.140, retrying
* executing `rubber:_allow_root_ssh'
I believe my credentials are correct.
If I look at the EC2 console it says the private ip is 10.111.63.18
You'll get these for a bit. There's a delay between when Amazon indicates the machine is available and when we can actually SSH into it. If it doesn't resolve itself after a few minutes, then something is wrong. But if you only see them for a couple minutes, it's nothing to worry about. EC2 is pretty variable about instance startup time.
Yeah I have the same problem despite the instance being available. I'm able to ssh to it.
I was using a previous aws key-pair and for some reason creating one named gsg-keypair fixed the problem.
+1. Just hang in there. I was getting nervous because the server had actually been running (green light in the UI) on AWS for awhile. It did eventually kick in.
First check if your private key is in ~/.ec2 directory.
After, try to remove the .pem extension from your private key file.
+1
Once again, you read my mind with this week's episode topics! Thanks a ton Ryan, keep up the great work.
Thanks a lot Ryan! This episode is just amazing! I was looking for a tutorial like this for months!
Thank you, just what i was looking for.
Thanks, great cast, and just in time for me.
When I configure AMI for us-east-1 things seems to work. But if I change the aws: to region: eu-west-1 even the staging fails with a AMI ID '' does not exist. Any ideas how to solve this? Also what shall I specify for time zone instead of US/Eastern
The AMIs only work in the region they were created in. If you want to use us-west-1 with Ubuntu 12.04, the AMI you want is ami-e7712aa2.
Check out the sidebar on http://alestic.com/ to get a listing of Ubuntu AMIs by region and type.
The timezone setting is just the standard set of timezone mappings from Ubuntu. If you're on the west coast, I guess "America/Vancouver" would do what you want.
As I am in Europe! I would like to use eu-west-1. I can't get that to work. If I simply switch to us-east-1 it works. Why is that?
Please hop on the rubber user list [1] and I'll try to help you out there. Sorry, I misread what you typed earlier as us-west-1. The eu-west-1 AMI is ami-1de8d369 (again, taken from http://alestic.com/).
[1] -- http://groups.google.com/group/rubber-ec2
Kevin, the last time i checked, AMI for eu-west-1 for Ubuntu 12.04 LTS 64 bit is ami-e1e8d395 and 32 bit is ami-e7e8d393 :)
What kind of cost could I expect for a small site with say between 100 and 500 hits per day? Would it work out cheaper than a linode vps in this case?
I would like to know how to match my own domain name instead of foo.com.
Thanks.
Modify the "domain" setting in config/rubber/rubber.yml.
how do i point the domain to ec2?? just linking the ip or do i need to set up an extra dns server??
You don't need DNS out of the box since rubber will write your host entries to /etc/hosts. But if you do want DNS, rubber can manage that as well. Look at the config/rubber/rubber-dns.yml template to get started.
@robbied72, for the first year, it'd be much cheaper, since you can most likely get away with the Amazon free tier, which gives you a micro instance free for a year.
Thanks Brian, will give it a shot.
How to config rubber to utilize the free tier? In rubber.yml it seems you can only choose between m1.small not m1.micro
Sorry, that comment in config/rubber/rubber.yml is misleading. You can use any instance type. Although "m1.micro" doesn't exist -- it's "t1.micro".
sorry about the t :-)
When using m1.small things work great. But when using t1.micro the web role server fails miserably on bootstrap. Hangs while doing rubber config. Cant't go beyond the transforming collectd.conf. Any ideas?
No worries. It's kinda hard to really try to debug what's going on here. Mind joining the mailing list and asking there?
http://groups.google.com/group/rubber-ec2
Thanks.
I did, but I don't see my message there !?
msg below:
Hi I have been trying to use the t1.micro image_type on eu-west-1, using the ami-e1e8d395. I can create and bootstrap and even deploy app role servers and db role servers. But unable to even bootstrap the web role server.
It gets stuck while running ./script/rubber config is being run. If I ssh to the server the rvm process is a zombie. If I kill it and run locally I get the same result. Below is what I get when running:
FILTER=web01 cap rubber:booystrap
lots of stuff...
** [out :: web01.foo.com] Resolving deltas: 100% (58/58), done.
command finished in 200394ms
triggering after callbacks for
deploy:update_code'
rubber:passenger:remove_config_ru'* executing
** No servers for task remove_config_ru, skipping
* executing "sudo -p 'sudo password: ' bash -l -c 'cd /mnt/fz-
production/releases/20120508214814 && RUBBER_ENV=production RAILS_ENV=production ./script/rubber config --force --file=\"role/ collectd\"'"
servers: ["web01.foo.com"]
[web01.foo.com] executing command
** [out :: web01.foo.com] Rubber[INFO]: Transforming /mnt/foo- production/releases/20120508214814/config/rubber/role/collectd/
collectd-ping.conf
** [out :: web01.foo.com] Rubber[INFO]: Transforming /mnt/foo- production/releases/20120508214814/config/rubber/role/collectd/
collectd.conf
How to solve this?
I switched to us-east-1 and changed AMI accordingly. Guess what, It worked on the first attempt. I tried the eu-west-1 numerous times but always getting stuck at the above. Strange! The only explanation I can think of is that the AMIs aren't identical.
I used:
ami-a29943cb for us-east-1
ami-e1e8d395 for eu-west-1
In the EU setup all servers ended up in eu-west-1a (as there are 1a, 1b, 1c) so that cannot be the issue.
Sorry. The list is moderated because Google Groups is a spam haven. Your message has gone through now.
I've actually run into a similar problem. Rubber blows up toward the end, with:
So, now, I'm off to join the mailing list. ;-)
Hi!
Is haproxy required for the web role? Put another way, can I use nginx/apache + passenger for the web role skipping haproxy altogether?
Thx!
rb
Rubber generates config into your project. By default we set up HAProxy, but you're welcome to delete that and reconfigure the web server ports. I do that currently: I have apache listen on 80 & 443 and use mod_cluster to some TorqueBox servers.
Kevin, do you have anything you could point me to as far as blog posts or documentation on how you went about setting up torquebox on EC2? I've fallen in love with torquebox in the last couple days and I want my ultimate destination to be EC2. It would be nice to use Rubber to help manage this. I see you've created a torquebox template, I'm just wondering if you have any documentation on how you've used it and how well it has worked for you. Thanks!
EC2 comes with Elastic Load Balancing, it would be nice to use it instead of a web role.
Is it feasible ?
Noob getting this error
** [out :: production.genlink.com] rake aborted!
** [out :: production.genlink.com]
** [out :: production.genlink.com] FATAL: role "GenLink" does not exist
** [out :: production.genlink.com]
** [out :: production.genlink.com] Tasks: TOP => environment
** [out :: production.genlink.com]
** out :: production.genlink.com
** [out :: production.genlink.com]
command finished in 16651ms
failed: "/bin/bash -l -c 'cd /mnt/GenLink-production/releases/20120509093404 && bundle exec rake RAILS_ENV=production RAILS_GROUPS=assets assets:precompile'" on production.genlink.com
It's really hard to provide support here. If you wouldn't mind, please ask the question on the mailing list:
http://groups.google.com/group/rubber-ec2
It looks like your role configs might have gotten out of whack. But, hard to to say with just that snippet.
How does rubber handle adding an extra database instance? Does it automatically copy over the data and add itself as a slave?
Additionally, does the standard rubber config offer failover or would I need to add this in?
It's really up to you. But we handle the single master, multiple slave setup out of the box for both PostgreSQL and MySQL. All you need to do is add a machine with the appropriate slave role (e.g., postgresql_slave) and it'll auto-configure it for async streaming replication from your master. The config is all generated in your project though, so if you want to change to streaming replication, for instance, just modify the generated file and you're good to go.
Excellent episode. I'm looking forward a "part 2" where you would explain how to set up your own templates!
Thanks!
Is there a reason rubber uses haproxy and not the Amazon Load Balancer? Are there any benefits from using haproxy and is it possible to use the Amazon Load Balancer with rubber?
Very nice episode! But why does rubber upload code to all instance? I would expect it to upload the files only for the instance with the app role.
Awesome episode Ryan! You rocks! ... And awesome gem. Congrats!
this was a great episode. I'm going to give it a try. Two areas that i would be interested in knowing if rubber supports are integrating with ELB and AutoScaling. Any insights from smarter people on this?
thanks
Hey, thanks for the episode. After running the command below:
cap rubber:create_staging
I get the following error:
connection failed for: production.foo.com (Net::SSH::AuthenticationFailed: root)
Assuming that it has something to do with the fact that Ubuntu would not allow a root user to ssh by default I changed my config/deploy.rb file to use ubuntu as user. However, after that I get a similar error:
connection failed for: production.foo.com (Net::SSH::AuthenticationFailed: ubuntu)
Does someone have an idea about why this could be happening. I think it may be related to the ssh keys used but to me things seem ok with them.
In case someone is interested, the problem was due to Mac OS 10.7.3 in my case. They changed the DNS resolve order at some point and now at first place is not /etc/hosts but your local DNS server or something like that. So, production.foo.com is resolved as pointing to a real host using this domain name. I changed foo.com to something non-existent in several rubber config files to solve this problem. Also edited /etc/hosts to have the new domain name I am using.
Hi, could you write down more about how to
I changed foo.com to something non-existent in several rubber config files to solve this problem. Also edited /etc/hosts to have the new domain name I am using.
I am totally new to this stuff. thxHey great video really appreciate it - trying to figure out how to get past these two errors, wondering if you could point me in the right direction:
Rubber[INFO]: Transformation executing post config command: function error_exit { exit 99; }; trap error_exit ERR
config : 'option forwardfor' ignored for proxy 'passenger_proxy_ssl' as it requires HTTP mode.
Here is my deploy.rb
http://pastebin.com/6CdCP7DY
and here is my rubber.yml file
http://pastebin.com/7tUcrMqF
Let me know if you need any additional info...thanks!
I've been getting this error when trying to run the cap rubber:create_staging command. It runs for 20 minutes or so successfully, but breaks when it gets here:
executing "cd /mnt/EvrlistSite-production/releases/20120706050602 && bundle exec rake RAILS_ENV=production db:migrate"
servers: ["production.evrlist.com"]
[production.evrlist.com] executing command
** [out :: production.evrlist.com] rake aborted!
** [out :: production.evrlist.com]
** [out :: production.evrlist.com] FATAL: role "EvrlistSite" does not exist
** [out :: production.evrlist.com]
** [out :: production.evrlist.com] Tasks: TOP = > db:migrate
** [out :: production.evrlist.com]
Ryan, thanks for another excellent railscast!
Hi everyone.. I have to say, setting it up initially wasn't very easy. Turns out rubber is not very happy with "complex" database.yml (with conditional environment if's etc..) or with hyphens in the app name which, at least when using mysql templates, confuse rubber.
After having fixed a few annoying issues - and separating the credentials, I now have a weird issue (and a question below):
The problem I hope someone can shed some light on:
cap rubber:create_staging runs without errors. However, it ends with the same output as rubber:bootstrap does. i.e. the last command is:
* executing "sudo -p 'sudo password: ' bash -l /tmp/create_master_db"
and never actually fires up an apache/passenger to run my app.. and thus the link is not accessible.
Also, a bit above, collectd throws an error:
** [out :: production.foo.com] Starting statistics collection and monitoring daemon: collectd
** [out :: production.foo.com] configfile: stat (/etc/collectd/conf.d/*.conf) failed: No such file or directory
Can collectd be the reason why my app doesn't actually start? I'm using rubber 2.0.5 by the way. Or may it be that it requires me to run another command to get things started (even on staging)?
And the other question:
I'm using the complete_passenger_mysql template - which hopefully includes everything - but was tempted to use complete_passenger_nginx_mysql - any benefit in doing this instead??
Typo in ASCII-Cast
gsg-keypair.gem should be gsg-keypair.pem
I used this tutorial for the free tier, and didn't even finish it due to errors, but I was still charged $40 at the end of the month for barely a couple days of using this service. I terminated my instances within a few days of using rubber. Even the default small instances are only $0.08/hr.
Please can someone tell me what I am doing wrong here?
Thanks!
diglett,
Did you create your instances using the AMI-Type : m1.small or any other option other than t1.micro?
The t1.micro is the free ami-type
Anybody knows what this error is about?
happens on
cap rubber:create_staging
is this supposed to be filled in
fog:
credentials:
provider: rackspace
rackspace_api_key: 'XXX'
rackspace_username: 'YYY'
image_type: 123
image_id: 123
switched the secret access key and access key.... works
Anybody know why this happen ?
First check if your private key is in ~/.ec2 directory.
After, try to remove the .pem extension from your private key file.
Hi all,
Running cap rubber:create_staging
I get this error:
Missing rule, creating: {"source_group_name"=>"blog_production_default", "source_group_account"=>"1072835180", "protocol"=>"tcp", "from_port"=>"1", "to_port"=>"65535"}
[DEPRECATION] 'account:group' argument is deprecated. Use {account => group} or just group instead
/home/user/.rvm/gems/ruby-1.9.3-p194/gems/excon-0.16.4/lib/excon/connection.rb:290:in `request_kernel': The security group 'blog_production_default' does not exist (Fog::Compute::AWS::NotFound)
Does anybody know whats going on?
Thanks!.
@Sebastian its probably too late for you, but for anyone else with this problem, It happened to me and the reason was I was using my user name for the account field as opposed to my AWS account number. I'm assuming that if the account number is wrong, a similar error will ensue.
Minor not that may help folks if you aren't familiar with yml files (I am not) :
if you want to put your AWS account, access key, and secret access key in enviornment variables, you must use the <%= %> brackets to access them. For example :
access_key: <%= ENV["AWS_ACCESS_KEY"] %>
This is unlike other rails configuration files. I'm not quite sure why since yml files look ruby-ish.
Hello,
I followed all the steps, and when I visit the ip address ( or domain name set in hosts ) I get apache server's default page "It works". I did not get rails app.
I have an EC2 tiny instance with ubuntu 12.04 in it.
Please help.
HI Karthik,
I have the same issue, did you figure out why its happening ? when i put "production.foo.com" in url...it shows the same message as yours. Please help !
One thing that caused me some consternation: a misnamed keyfile.
When you create the keypair at Amazon, the name listed on amazon must match the filename locally.
Also, Ryan removes the .pem extension, from gsg-keypair...and Rubber does not tack .pem onto what you define in rubbery.yml.
So in short, make sure the key files names match everywhere.