2

I am having a very difficult time trying to launch a sample Rails 6 application to Elastic Beanstalk. For context, I am following these instructions

ADD RDS to Ruby Application

ADD an RDS to Beanstalk

I have followed these instructions to a tee and am still unable to connect to the rds database that I have provisioned. I keep receiving the following error:

PG::ConnectionBad: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

Whenever I try to run RAILS_ENV=production rails db:migrate or any other rake task, I keep getting that error.

On my AWS console, under Configuration and Software, I have the following environment variables:

enter image description here

Also in my database.yml file I have the rds configured variables listed as such.

production:
 adapter: postgresql
  database: <%= ENV['RDS_DB_NAME'] %>
  username: <%= ENV['RDS_USERNAME'] %>
  password: <%= ENV['RDS_PASSWORD'] %>
  host: <%= ENV['RDS_HOSTNAME'] %>
  port: <%= ENV['RDS_PORT'] %>

I have mapped my values as instructed in the documentation and am certain that they are correct.

Finally, I have sshed into my beanstalk provisioned ec2 instance and have executed the following command:

psql -U username -p 5432 -h examplehost.rds.amazonaws.com -d ebdb

provided the password and am able to connect. I am really at my wits end, I've spent too much time trying to diagnose this and am running out of ideas. I don't know where to look too next for ideas on how to trouble shoot this. I've read so many stack overflow questions and blogs that my head is spinning. If anyone has any ideas on how to resolve this, I would greatly appreciate it.

---Update---- I have created a new environment variable on the elastic beanstalk console.

ENV['DATABASE_URL'] = postgres://YourUserName:YourPassword@YourHostname:5432/YourDatabaseName

I made the necessary configurations, uploaded my .zip file and the connection to the database failed.

---- UPDATE-----

printenv does not show the varialbes provided by beanstalk, however this command does sudo /opt/elasticbeanstalk/bin/get-config environment.

Dan Rubio
  • 3,965
  • 5
  • 34
  • 74
  • Can you start the rails console from within your app? `cd /var/app/current` and then start the console? – littleforest Nov 09 '20 at 23:24
  • Is the rails server and rack env set to production mode? – 3DPrintScanner Nov 09 '20 at 23:56
  • Thank you guys for responding. Yes both variables are set to production and I am able to access the rails console. However if I try to make any kind of query or active record statement I recieve `no implicit conversion of nil into String (TypeError)`. I was able to make it work temporarily by just hard coding the production values on my deployed rails app in `database.yml`. This makes me think that the app cannot read the RDS environment variables somehow despite placing them in the console.. – Dan Rubio Nov 10 '20 at 02:54
  • Oh good detective work, but weird that the environment variables aren't getting picked up. In the console, can you double check to see if they are getting set? – littleforest Nov 10 '20 at 04:07
  • I'm not exactly sure how to do that at this point. From what I can tell, it is picking up all the other variables. So what I'm going to try tomorrow is create a new env variable called `DATABASE_URL` and have it set to this postgresql connection string. `postgres://YourUserName:YourPassword@YourHostname:5432/YourDatabaseName`. I'll configure my `database.yml` to use it and then I'll see if that did the trick. – Dan Rubio Nov 10 '20 at 04:32
  • Let us know how it goes. In the console you can just enter `ENV["RDS_DB_NAME"]` at the prompt and see if it outputs anything. – littleforest Nov 10 '20 at 15:22
  • It turns out that none of the variables are being read. Only `nil` is being outputted. It looks like for the time being I'll have to just hardcode the rds ENV variables, which is annoying. – Dan Rubio Nov 10 '20 at 21:04
  • Huh, that's not great for security. It looks like you've set everything up correctly as far as you've noted here. It might be worth it to pay for AWS support and see if they have any ideas. They can't help you with your code, but maybe they can identify something else that isn't set up correctly. – littleforest Nov 10 '20 at 23:26

1 Answers1

2

My first advice is that, in my opinion, it is a much better option to create an Amazon RDS on their own, and not tied to Beanstalk.

As the AWS documentation indicates (emphasis mine):

AWS Elastic Beanstalk provides support for running Amazon Relational Database Service (Amazon RDS) instances in your Elastic Beanstalk environment. To learn about that, see Adding a database to your Elastic Beanstalk environment. This works great for development and testing environments. However, it isn't ideal for a production environment because it ties the lifecycle of the database instance to the lifecycle of your application's environment.

And:

To decouple your database instance from your environment, you can run a database instance in Amazon RDS and configure your application to connect to it on launch. This enables you to connect multiple environments to a database, terminate an environment without affecting the database, and perform seamless updates with blue-green deployments.

In my opinion, even for testing or development, it is always advisable to configure a small database instance and give your application the ability of define the most appropriate mechanism for connecting to your database.

The only downside is that you will probably need to configure a VPC, although it should not be actually a problem and, in ay case, it is worth value.

If for any reason you need to use the Beanstalk provisioned RDS database perhaps you have some workarounds to your problem (it should be a workaround because your configuration looks fine - please, only, verify that the database configuration is defined for the right Beanstalk environment).

For instance, one thing you can try is to store the database connection configuration in a S3 bucket, as also suggested in the AWS documentation. The idea is basically create some configuration file with the necessary connectivity information, store it in S3, and read that configuration in your application, i.e., process that file, in order to initialize your database.

But maybe you can try another approach.

Please, consider this SO question, and the answer from Jon McAuliffe and others. As indicated, Beanstalk will provide your application with environment variables, but maybe this variables will not be exposed as shell variables, they will be exposed to your application in different ways depending on the runtime the application needs to be executed on.

In the case of Ruby, you are accessing these variables in the correct way but, for any reason, your program is not having access to that information.

This probably also explains why printenv does not print any if your variables but the get-config script does.

But maybe you can take advantage of the fact that get-config provides you the right information and, either define this variables in your ENV by executing the get-config script for every RDS* key, perhaps in your environment.rb - please, be aware that I programmed in Ruby when I was a student but there is a long time since that, do the task in the file you consider appropriate - or using .ebextensions and a custom configuration file. You can find several examples here.

For instance, consider the following (copy and paste, with minor modifications of this example configuration):

commands:
  01_update_env:
    command: "/tmp/update_environment_variables.sh"

files:
  "/tmp/update_environment_variables.sh":
      mode: "000755"
      content : |
        #!/bin/bash

        RDS_HOSTNAME=$(/opt/elasticbeanstalk/bin/get-config environment -k RDS_HOSTNAME)
        if [ -z "$RDS_HOSTNAME" ]; then
                echo "Could not determine RDS hostname"
                exit 1
        fi
        echo "RDS hostname $RDS_HOSTNAME..."
        # Just export the variable at OS level, or make it visible to
        # the rails env in some other way
        export RDS_HOSTNAME=$RDS_HOSTNAME

        # Process the rest of the variables...
        # Probably we should create a list and iterate through it

A similar approach could be the one exposed in this stackoverrun question, but restricted to the container that Beanstalk will use to encapsulate your app. AFAIK, the container should receive as env variables the different RDS* ones corresponding to the database configuration.

Dan, be aware that I have not tested these solutions, they are only ideas: please, be careful with that, I do not want to cause any damage to your system.

jccampanero
  • 21,211
  • 2
  • 2
  • 26
  • @DanRubio, were you able to try any of the proposed solutions? – jccampanero Dec 10 '20 at 18:35
  • Hey @jccampanero thanks for your reply, I gave you the bounty but the suggestions did not work after all. I have a decoupled rds database and have abandoned beanstalk entirely to simply move to a provisioned ec2 instance with the packages installed. I've found that beanstalk has too many problems with various steps in deployments and setup. It was simpler to just setup the ec2 instance itself at this point instead of bulldozing through. Thank you for your answer. – Dan Rubio Dec 15 '20 at 16:09
  • Hi @DanRubio. Thank you very much, I really appreciate that you gave me the bounty. I am sorry that none of the provided suggestions worked. I think you made a good decision to have the database separately. An ec2 instance provisioned with the correct packages is fine too. In any case, please, consider also other options like deploying your application in containers, directly or with Kubernetes. Thank you again Dan: please, if you think that I can be of any help, do not hesitate to contact me, I will be glad to help you. – jccampanero Dec 15 '20 at 22:28