Seamless deployment of Django to single server

2019-03-29 11:29发布

问题:

I have a new website built on Django and Python 2.6 which I've deployed to the cloud (buzzword compliant AND the Amazon micro EC2 instance is free!).
Here are my detailed notes: https://docs.google.com/document/d/1qcZ_SqxNcFlGKNyp-CXqcFxXXsKs26Avv3mytXGCedA/edit?hl=en_US

As this is a new site (and wanting to play with the latest and greatest) I used Nginx and Gunicorn on top of Supervisor.
All software installed from trunk using YUM / easy_install.
My database is Sqlite (for now - not sure of where to go next, but that is not the question). Also on the todo list: virtualenv + pip.
So far so good.
My code in in SVN. I wrote a simple fabfile to deploy - checks out the latest code and restarts Gunicorn via Supervisor. I hooked my DNS name to an Elastic IP.
It works.

My question is, how do I update the site without a disruption of service? Users of the site get 404s / 500s when I run my little update script.

Is there a way to do this without adding another server (price is key)?

I would love to have a staging system (on a different port?) and a seamless switch between Staging and Production. On the same (free) server. Via Fabric.
How do I do that? Is it the same Nginx running both sites? Can I upgrade Staging without hurting Production? What would the fabfile look like? What would the directory tree look like?

Thanks!

Tal.

Related:

  • Seamless deployment in Rails
  • -

回答1:

Nginx allows you to setup failover for your reverse proxies you can put one gunicorn instance as the primary and as long as that version is running it will never look at the failover.

If you configure your site so that your new version is in the failover instance you just need to write your fab file to update the failure instance with the new version of the site and then when ready, turn off primary instance. Nginx will seamlessly failover to second instance and bam you are running on new version with no downtime.

You can then update the primary version and then turn it back on and your primary is now live. At this point you can keep the failover instance running just in case, or turn it off.

Some things to consider. You have to be careful with databases, if you are using sqllite make sure both gunicorn instances can accesss the sqllite file.

If you have a normal database this is less of a problem, you just need to make sure you apply any database migrations that the new version needs before you switch to it.

If they are backwards compatible changes then it isn't a big deal. If they aren't backwards compatible then be careful, you could break the old version of the site before you switch over to new version.

To make things easier I would run the versions on different virtual environments.

If you use supervisord to control gunicorn, then you can use the supervisorctl commands to reload/restart which ever instance you want to deploy without affecting the other one.

Hope that helps

Here is an example of and nginx config (not a full config file, removed the unimportant parts)

This assumes the primary gunicorn instance is running on port 9005 and the other is running on port 9006

upstream service-backend {
    server localhost:9005;        # primary
    server localhost:9006 backup; # only used when primary is down
}

server {
    listen 80;
    root /opt/htdocs;
    server_name localhost;

    access_log /var/logs/nginx/access.log;
    error_log  /var/logs/nginx/error.log;

    location / {
        proxy_pass http://service-backend;
    }
}


回答2:

Sounds like you need to figure out how to tell gunicorn to gracefully restart. It seems like all you have to do is issue a HUP to the gunicorn process when to notify to reload the app. As describe in the link about, the gunicorn docs explain how to do it.