root / doc / design-http-server.rst @ 33c730a2
History | View | Annotate | Download (5.4 kB)
1 |
========================================= |
---|---|
2 |
Design for replacing Ganeti's HTTP server |
3 |
========================================= |
4 |
|
5 |
.. contents:: :depth: 4 |
6 |
|
7 |
.. _http-srv-shortcomings: |
8 |
|
9 |
Current state and shortcomings |
10 |
------------------------------ |
11 |
|
12 |
The :doc:`new design for import/export <design-impexp2>` depends on an |
13 |
HTTP server. Ganeti includes a home-grown HTTP server based on Python's |
14 |
``BaseHTTPServer``. While it served us well so far, it only implements |
15 |
the very basics of the HTTP protocol. It is, for example, not structured |
16 |
well enough to support chunked transfers (:rfc:`2616`, section 3.6.1), |
17 |
which would have some advantages. In addition, it has not been designed |
18 |
for sending large responses. |
19 |
|
20 |
In the case of the node daemon the HTTP server can not easily be |
21 |
separated from the actual backend code and therefore must run as "root". |
22 |
The RAPI daemon does request parsing in the same process as talking to |
23 |
the master daemon via LUXI. |
24 |
|
25 |
|
26 |
Proposed changes |
27 |
---------------- |
28 |
|
29 |
The proposal is to start using a full-fledged HTTP server in Ganeti and |
30 |
to run Ganeti's code as `FastCGI <http://www.fastcgi.com/>`_ |
31 |
applications. Reasons: |
32 |
|
33 |
- Simplify Ganeti's code by delegating the details of HTTP and SSL to |
34 |
another piece of software |
35 |
- Run HTTP frontend and handler backend as separate processes and users |
36 |
(esp. useful for node daemon, but also import/export and Remote API) |
37 |
- Allows implementation of :ref:`rpc-feedback` |
38 |
|
39 |
|
40 |
Software choice |
41 |
+++++++++++++++ |
42 |
|
43 |
Theoretically any server able of speaking FastCGI to a backend process |
44 |
could be used. However, to keep the number of steps required for setting |
45 |
up a new cluster at roughly the same level, the implementation will be |
46 |
geared for one specific HTTP server at the beginning. Support for other |
47 |
HTTP servers can still be implemented. |
48 |
|
49 |
After a rough selection of available HTTP servers `lighttpd |
50 |
<http://www.lighttpd.net/>`_ and `nginx <http://www.nginx.org/>`_ were |
51 |
the most likely candidates. Both are `widely used`_ and tested. |
52 |
|
53 |
.. _widely used: http://news.netcraft.com/archives/2011/01/12/ |
54 |
january-2011-web-server-survey-4.html |
55 |
|
56 |
Nginx' `original documentation <http://sysoev.ru/nginx/docs/>`_ is in |
57 |
Russian, translations are `available in a Wiki |
58 |
<http://wiki.nginx.org/>`_. Nginx does not support old-style CGI |
59 |
programs. |
60 |
|
61 |
The author found `lighttpd's documentation |
62 |
<http://redmine.lighttpd.net/wiki/lighttpd>`_ easier to understand and |
63 |
was able to configure a test server quickly. This, together with the |
64 |
support for more technologies, made deciding easier. |
65 |
|
66 |
With its use as a public-facing web server on a large number of websites |
67 |
(and possibly more behind proxies), lighttpd should be a safe choice. |
68 |
Unlike other webservers, such as the Apache HTTP Server, lighttpd's |
69 |
codebase is of manageable size. |
70 |
|
71 |
Initially the HTTP server would only be used for import/export |
72 |
transfers, but its use can be expanded to the Remote API and node |
73 |
daemon (see :ref:`rpc-feedback`). |
74 |
|
75 |
To reduce the attack surface, an option will be provided to configure |
76 |
services (e.g. import/export) to only listen on certain network |
77 |
interfaces. |
78 |
|
79 |
|
80 |
.. _rpc-feedback: |
81 |
|
82 |
RPC feedback |
83 |
++++++++++++ |
84 |
|
85 |
HTTP/1.1 supports chunked transfers (:rfc:`2616`, section 3.6.1). They |
86 |
could be used to provide feedback from node daemons to the master, |
87 |
similar to the feedback from jobs. A good use would be to provide |
88 |
feedback to the user during long-running operations, e.g. downloading an |
89 |
instance's data from another cluster. |
90 |
|
91 |
.. _requirement: http://www.python.org/dev/peps/pep-0333/ |
92 |
#buffering-and-streaming |
93 |
|
94 |
WSGI 1.0 (:pep:`333`) includes the following `requirement`_: |
95 |
|
96 |
WSGI servers, gateways, and middleware **must not** delay the |
97 |
transmission of any block; they **must** either fully transmit the |
98 |
block to the client, or guarantee that they will continue transmission |
99 |
even while the application is producing its next block |
100 |
|
101 |
This behaviour was confirmed to work with lighttpd and the |
102 |
:ref:`flup <http-software-req>` library. FastCGI by itself has no such |
103 |
guarantee; webservers with buffering might require artificial padding to |
104 |
force the message to be transmitted. |
105 |
|
106 |
The node daemon can send JSON-encoded messages back to the master daemon |
107 |
by separating them using a predefined character (see :ref:`LUXI |
108 |
<luxi>`). The final message contains the method's result. pycURL passes |
109 |
each received chunk to the callback set as ``CURLOPT_WRITEFUNCTION``. |
110 |
Once a message is complete, the master daemon can pass it to a callback |
111 |
function inside the job, which then decides on what to do (e.g. forward |
112 |
it as job feedback to the user). |
113 |
|
114 |
A more detailed design may have to be written before deciding whether to |
115 |
implement RPC feedback. |
116 |
|
117 |
|
118 |
.. _http-software-req: |
119 |
|
120 |
Software requirements |
121 |
+++++++++++++++++++++ |
122 |
|
123 |
- lighttpd 1.4.24 or above built with OpenSSL support (earlier versions |
124 |
`don't support SSL client certificates |
125 |
<http://redmine.lighttpd.net/issues/1288>`_) |
126 |
- `flup <http://trac.saddi.com/flup>`_ for FastCGI |
127 |
|
128 |
|
129 |
Lighttpd SSL configuration |
130 |
++++++++++++++++++++++++++ |
131 |
|
132 |
.. highlight:: lighttpd |
133 |
|
134 |
The following sample shows how to configure SSL with client certificates |
135 |
in Lighttpd:: |
136 |
|
137 |
$SERVER["socket"] == ":443" { |
138 |
ssl.engine = "enable" |
139 |
ssl.pemfile = "server.pem" |
140 |
ssl.ca-file = "ca.pem" |
141 |
ssl.use-sslv2 = "disable" |
142 |
ssl.cipher-list = "HIGH:-DES:-3DES:-EXPORT:-ADH" |
143 |
ssl.verifyclient.activate = "enable" |
144 |
ssl.verifyclient.enforce = "enable" |
145 |
ssl.verifyclient.exportcert = "enable" |
146 |
ssl.verifyclient.username = "SSL_CLIENT_S_DN_CN" |
147 |
} |
148 |
|
149 |
|
150 |
.. vim: set textwidth=72 : |
151 |
.. Local Variables: |
152 |
.. mode: rst |
153 |
.. fill-column: 72 |
154 |
.. End: |