Professional Documents
Culture Documents
INTRODUCTION
Building a Platform as a Service (PaaS) is rewarding work. We get to make the life of a developer easier.
PaaS helps developers deploy, scale, and manage their applications, without making developers hardcore systems
administrators themselves.
As with many problems, the toughest part about managing applications in the cloud is actually not the building of the
PaaS itself. The challenge lies in being able to scale the applications.
To give you a sense of the complexity, each minute, millions of HTTP requests are routed through the application.
Not only does our PaaS collect millions of metrics, we also aggregate, process, and analyze the metrics and look for
abnormal patterns. Apps are constantly deployed and migrated on our PaaS platform.
For economies of scale, virtually all PaaS providers pack density onto their physical machines. How does a PaaS
provider solve the following issues?
One key element is lightweight virtualization which is the use of virtual environments (called containers) to provide isolation
characteristics comparable to full-blown virtual machines, but with much less overhead. In this area, the dotCloud platform relies
on Linux Containers called LXCs.
In the following 5 episodes, we will dive into some of the internals of the dotCloud platform or more specifically, the
Linux kernel features used by dotCloud.
dotcloud.com
Episode 1: Namespaces
Each time a new Linux Container (LXC) is created, the name of the container is filed under the /cgroup directory. For
example, a new container named sanfrancisco is filed under the directory /cgroup/sanfrancisco. It is easy to think
that the container relies on the control groups. Although cgroups are useful to Linux Containers (we will cover cgroups
more thoroughly in Episode 2), Namespace provides an even more vital function to the Linux Containers.
Namespaces isolate the resources of processes. This isolation is the real magic behind Linux Containers! There are five
Namespaces, each covering a different resource: pid, net, ipc, mnt, and uts.
The pid namespace
The pid namespace is the most useful technology for basic isolation. Each pid namespace has it own numbering
process. Different pid namespaces form a hierarchy with the kernel which keeps track of all the namespace. A
parent namespace can see and implement actions on the child namespaces. A child namespace cannot perform
any actions on its parent.
There are some principles about the pid namespace as follows:
Each pid namespace has its own PID 1 init-like process
Processes residing in a namespace cannot affect processes residing in a parent or sibling namespace with system
calls like kill or ptrace because process ids are only meaningful inside a given namespace
If a pseudo-filesystem like proc is mounted by a process within a pid namespace, it will only show the processes
belonging to the namespace
Numbering is different in each namespace which means that a process in a child namespace can have multiple PIDs,
for example, one in its own namespace and a different PID in its parent namespace. Top-level pid namespace can see
all processes running in all namespaces with different PIDs. A process can have more than 2 PIDs if there are more than
two levels of hierarchy in the namespaces.
The net namespace
With the pid namespace, you can start processes in multiple isolated environments called containers. What if you
need to run separate instances of Apache webserver in each container? Generally only one process can listen to port
80/TCP at a time. To configure your instances of Apache webserver to listen on different ports, you could use the net
namespace, which has been designed for networking.
Each different net namespace can have different network interfaces. Even lo, the loopback interface supporting
127.0.0.1, can be different in each different net namespace. It is even possible to create a pair of special interfaces, which
will appear in two different net namespaces and allow one of the two net namespaces to talk to the outside world.
A typical container will have its own loopback interface (lo), as well as a special interface on one end, generally named
eth0. The other end of the special interface will be in the original namespace, and will bear a poetic name like
veth42xyz0. It is then possible to put those special interfaces together within an Ethernet bridge (to achieve switching
between containers), or route packets between them, etc. This is similar to the Xen networking model.
Each net namespace has its own local meaning for INADDR_ANY, a.k.a. 0.0.0.0. When your Apache webserver process
binds to INADDR_ANY and port 80 within its namespace *:80 within its namespace, it will only receive connections
directed to the IP addresses and interfaces of its namespace. That allows you to run multiple Apache instances, each
in their own pid and own net namespace, with their default configuration listening on port 80 and each will remain
individually addressable.
Each net namespace has its own routing table, and its own iptables chains and rules.
The ipc namespace
The ipc namespace wont appeal to many of you, unless youve passed UNIX 101 when engineering schools still taught
classes on IPC (InterProcess Communication).
IPC provides semaphores, message queues, and shared memory segments.
While still supported by virtually every UNIX flavors, those features are considered by many as obsolete, and
superseded by POSIX semaphores, POSIX message queues, and mmap. Nonetheless, some programs such as
PostgreSQL, for example, still use IPC.
Whats the connection with namespaces? Each IPC resource is accessed through a globally unique 32-bit ID. While IPC
implements permissions on the resource itself, an application could be surprised if it failed to access a given resource
because it has already been claimed by another process in a different container. The app doesnt know anything about
other containers!
Meet the ipc namespace. Processes within a given ipc namespace cannot access (or even see) the IPC resources living
in other ipc namespaces. And now you can safely run a PostgreSQL instance in each container without the fear of IPC
key collisions.
The mnt namespace
chroot is a mechanism to sandbox a process (and its children) within a given directory. The mnt namespace takes the
chroot concept even further.
As its name implies, the mnt namespace deals with mount points.
Processes living in different mnt namespaces can see different sets of mounted file systems and different root
directories. If a file system is mounted in an mnt namespace, it will be accessible only to those processes within that
namespace. It will not be visible for processes in other namespaces.
At first impression, it may sound useful, since the mnt namespace allows you to sandbox each container within its own
directory, hidden from other containers. However, is this really useful after all? If each container is chrooted in a different
directory, container C1 wont be able to access or see container C2s file system, right? There are downsides.
Inspecting /proc/mounts in a container will show the mount points of all containers. Also, those mountpoints will be
relative to the original namespace, which can give out some hints about the layout of your system. Seeing the path for
the global namespace may confuse some applications that rely on the paths in the local namespace /proc/mounts.
The mnt namespace makes the situation much cleaner, allowing each container to have its own mount points, and see
only those mount points, with their path correctly correlated to the actual root of the namespace.
The uts namespace
Finally, the uts namespace deals with one important detail in that the hostname can be seen by a group of processes.
The uts namespace addresses this issue by giving each uts namespace a different hostname, and changing the
hostname through the sethostname system call. Also, the uts namespace will only change the hostname for processes
running in the same namespace.
Creating namespaces
Namespace creation is achieved with the clone system call. This system call supports a number of flags, allowing you to
specify whether the new process should run within its own pid, net, ipc, mnt, and uts namespaces.
These are the series of steps that take place when creating a new container. A new process starts with new
namespaces created. Its network interfaces that include the special pair of interfaces to talk with the outside world are
configured. It then executes an init-like process.
When the last process within a namespace exits, the associated resources (IPC, network interfaces...) are automatically
reclaimed. If, for some reason, you want those resources to survive after the termination of the last process of the
namespace, you can use mount --bind to retain the namespace for future use, because each namespace is stored in a
special file in /proc/$PID/ns.
Not all namespaces can be retained, only for ones up to kernel 3.4 . There is support for ipc, net, and uts namespaces
but not for mnt and pid namespace. This presents a problem that we will address in the next paragraph.
Episode 2: Cgroups
Episode 2: cgroups
Control groups, or cgroups, are a set of mechanisms to measure
and limit resource usage for groups of processes.
Conceptually, it works somewhat like the ulimit shell command or
the setrlimit system call. ulimit and setrlimit set resource limits
for a single process. cgroups allow you to set resource limits for
groups of processes.
dotcloud.com
Episode 2: Cgroups
Pseudo-FS Interface
The easiest way to manipulate control groups is through the cgroup file system.
Assuming that it has been mounted on /cgroup, creating a new group named polkadot is as easy as mkdir /cgroup/
polkadot. When you create this (pseudo) directory, it instantly gets populated with many (pseudo) files to manipulate
the control group. You can then move one (or many) processes into the control group by writing their PID to the right
control file, for example, echo 4242 > /cgroup/polkadot/tasks.
When a process is created, it will be in the same group as its parent. If the init process of a container has been placed in
a control group, all the processes of the container will be also be in the same control group.
Destroying a control group is as easy as rmdir /cgroup/polkadot. However the processes within the cgroup have to be
moved to other groups first. Otherwise rmdir will fail since it is like trying to remove a non-empty directory.
Technically, control groups are split into many subsystems. Each subsystem is responsible for a set of files in /cgroup/
polkadot, and the file names are prefixed with the subsystem name.
For instance, the files cpuacct.stat, cpuacct.usage, cpuacct.usage_percpu are the interface for the cpuacct subsystem.
The available subsystems will be detailed in the next paragraph.
The subsystems can be used together, or independently. In other words, you can decide that each control group will
have limits and counters for all the subsystems. Alternatively, each subsystem can have different control groups.
To explain the latter case more fully, a subsystem can have a process in the polkadot control group for memory
control, a process in the bluesuedeshoe control group for CPU control such that polkadot and bluesuedeshoe are in
completely separated namespaces.
What can be Controlled?
Many things! Well highlight the most useful ones here, at least the ones we think are the most useful.
Memory
You can limit the amount of RAM and swap space that can be used by a group of processes. It accounts for the
memory used by the processes for their private use such as their Resident Set Size, or RSS, but also for the memory
used for caching purposes.
This is actually quite powerful, because traditional tools such as ps or analysis of /proc do not have a way to identify the
cache memory usage incurred by specific processes. This can make a big difference, for instance, with databases.
A database typically consumes very little memory for processing but consumes a large chunk of cache. Complex
queries would consume a lot of memory but, for this example, we are not performing complex queries.
To perform optimally, your whole database (or at least, your active set of data that you refer to the most often) should
fit into memory.
You can implement a memory limit for a process inside a cgroup that can easily be done by using echo 1000000000 >
/cgroup/polkadot/memory.limit_in_bytes (that will be rounded to a page size).
To check the current usage for a cgroup, inspect the pseudo-filememory.usage_in_bytes in the cgroup directory. You
can gather very detailed (and very useful) information using memory.stat.
Episode 2: Cgroups
CPU
You might already be familiar with scheduler priorities, and with the nice and renice commands. Once again, control
groups will let you define the amount of CPU that should be shared by a group of processes, instead of by a single
process. You can give each cgroup a relative number of CPU shares, and the kernel will make sure that each group of
processes gets access to the CPU in proportion of the number of shares you gave it.
Setting the number of shares is as simple as echo 250 > /cgroup/polkadot/cpu.shares.
Remember that those shares are just relative numbers. If you multiply everyones share by 10, the end result will be
exactly the same. This control group also gives statistics incpu.stat.
CPU Sets
This is different from the cpu controller. In systems with multiple CPUs (i.e., the vast majority of servers, desktop &
laptop computers, and even phones today!), the cpuset control group lets you define which processes can use which
CPU.
This can be useful to reserve a full CPU to a given process or group of processes. Those processes will receive a fixed
amount of CPU cycles, and they might also run faster because there will be less thrashing at the level of the CPU cache.
On systems with Non Uniform Memory Access (NUMA), the memory is split in multiple memory banks, and each bank
is tied to a specific CPU - or set of CPUs in a multi-core system. Binding a process (or group of processes) to a specific
CPU or to a specific group can also reduce the overhead when a process is scheduled to run on a CPU, while accessing
RAM tied to another CPU. There is a penalty to pay for accessing RAM that is tied to another CPU, so that you can use a
cpuset to bind a process and its memory to a specific CPU to avoid the penalty. This works for a group of processes or
CPUs too.
Block I/O
The blkio controller provides a lot of information about the disk accesses (or technically, block devices requests)
performed by a group of processes. This is a useful technology, because I/O resources are much harder to share than
CPU or RAM.
A system has a given, known, and fixed amount of RAM. It has a fixed number of CPU cycles every second. This is true
even on systems where the number of CPU cycles can change (such as tickless systems, or virtual machines). This
does not present an issue, because the kernel will slice the CPU time in shares of e.g. 1 millisecond, and there is a given,
known, and fixed number of milliseconds in every second obviously. However, I/O bandwidth can be unpredictable, or
the predictions arent very useful.
A hard disk with a 10ms average seek time will be able to process about 100 requests of 4 kB per second; but if the
requests are sequential, typical desktop hard drives can easily sustain 80 MB/s transfer rates which means 20000
requests of 4 kB per second.
The average throughput (measured in IOPS, I/O Operations Per Second) will be somewhere between those two
extremes. But as soon as the application performs a task that requires a lot of scattered, random I/O operations, the
performance will drop dramatically. The system can give you some guaranteed performance, but this guaranteed
performance is so low that it is not helpful. That is exactly the problem over at AWS EBS, by the way. Its like a highway
that offers a guarantee that you be able to go above a given speed, except that this speed is 5 mph. Not very helpful in
practicality, is it?
Episode 2: Cgroups
10
Thats why SSD storage is becoming increasingly popular. SSD has virtually no seek time, and can therefore sustain
random I/O as fast as sequential I/O. The available throughput is therefore predictably good, under any given load.
Actually, there are some workloads that can cause problems. For instance, writing and rewriting a whole disk will
cause performance to drop dramatically. This is because read and write operations are fast, but erase, which must be
performed at some point before write, is slow.
An example of this use case would be to use SSD to manage video on demand for hundreds of HD channels
simultaneously. The disk will sustain the write throughput until it has written every block once. When it needs to erase,
the performance will drop to below acceptable levels.
Going back to dotCloud, whats the purpose of the blkio controller in a PaaS environment?
The blkio controller metrics will help detect applications that are putting an excessive strain on the I/O subsystem. The
controller lets you set limits, which can be expressed in number of operations and/or bytes per second. It also allows for
different limits for read and write operations. It allows you to set some thresholds that no single app can significantly
degrade performance for other apps. Furthermore, once an I/O intensive app has been identified, its quota can be
adapted to reduce impact on other apps.
Its Not Only for Containers
As we mentioned, cgroups are convenient for containers, since it is very easy to map each container to a cgroup. But
there are many other uses for cgroups.
The systemd service manager is able to put each service in a different cgroup. This allows you to keep track of all the
subprocesses started by a given service, even when they use the double-fork technique to detach from their parent
and re-attach to init. It also allows fine-grained tracking and control of the resource used by each service.
It is also possible to run a system-wide daemon to automatically classify processes into cgroups. This can be particularly
useful on multi-user systems, to limit and/or meter appropriately the resources of each user, or to run some specific
programs in a special cgroupwhen you know that those programs are prone to excessive resource use.
dotCloud & Control Groups
Thanks to cgroups, we can meter very accurately the resource usage of each container, and therefore of each unit
of each service for each application. Our metrics collection system uses collectd, along with our in-house lxc plugin.
Metrics are streamed to a custom storage cluster, and can be queried and streamed by the rest of the platform using
our ZeroRPC protocol. We will be writing a more in-depth article on metrics collection system in the future.
We also use cgroups to allocate resource quotas for each container. For instance, when you use vertical scaling on
dotCloud, you are actually setting limits for memory, swap usage, and CPU shares.
Episode 3: AUFS
Episode 3: AUFS
AUFS (which initially stood for Another Union File System)
provides fast provisioning while retaining full flexibility and
ensuring disk and memory savings
dotcloud.com
11
Episode 3: AUFS
12
AUFS is a union file system, which merges two directory hierarchies together. On the dotCloud platform, we use AUFS
to combine a large, read-only file system containing a ready-to-run system image under a writeable layer. The resulting
file system looks like the large read-only one, except that you can now write on it anywhere and store just the changed
files. LiveCDs or bootable USBs are common examples of this use case. AUFS allows us to have a common base
image for all applications and a separate read-write layer, unique to each app.
Storage Savings
Lets assume that the base image takes up 1 GB of disk space. In reality, it is actually more than that, since were talking
about a full server file system, containing everything a dotCloud app could potentially need such as Python, Ruby,
Perl, Java, C compiler and libraries, and so on. If the entire image had to be cloned each time a dotCloud application
is deployed, it would use 1 GB of disk space for each new cloned deployment. AUFS therefore lets us save on storage
costs because it is typically using less than 1 MB of disk space.
Faster Deployments
Copying the whole base image would not only use up precious disk space, but it would also take time, up to a minute
or so depending on the disk speed. Also, the copy would put a significant I/O load on the disk. On the other hand,
creating a new pseudo-image using AUFS takes a fraction of a second, and virtually no I/O at all. AUFS offers a much
better solution when compared to copying an entire image every time.
Better Memory Usage
Virtually all operating systems use a feature called buffer cache to make disk access faster. Without it, your system
could run at least 10x, 100x or up to 1000x slower, because it has to access the disk even to run simple commands, for
example, when listing your files with ls! As we will see, AUFS also lets us rack in big savings on this buffer cache.
Every single application will load from disk a number of common files and components such as the libc standard
library, the /bin/sh standard shell... and a lot of common infrastructures, like crond, sshd, the local Mail Transfer Agent,
just to name a few. Additionally, all applications of the same type will load the same files. For example, Python
applications will load a copy of the Python interpreter every time.
If each app were running from its own copy, identical copies of those common files would be present multiple times in
memory, within the buffer cache. Using AUFS, those common files are in the base image, and the Linux kernel therefore
knows how to load them only once in memory. This will typically save tens of MB for each app.
Easier Upgrades
If you are familiar with storage technology, you might argue that snapshots, and copy-on-write devices already have
those advantages mentioned above.
Thats true. However, with those systems, it is not possible to update the base image, and have the changes reflected
in the lightweight clones such as in the snapshots. AUFS, on the other hand, lets you do whatever you want with the
base image. The changes will be immediately visible in the AUFS mount points using the base image. It means that it is
easy to do software upgrades, even while the applications are running, just like on a typical single server environment,
except that you can upgrade thousands of servers all at once.
Allows Arbitrary Changes
All those things can also be done without AUFS. For a decade, skilled UNIX systems administrators have been
deploying machines (workstations, X terminals, servers...) with a read-only root file system, allowing read-write access
through ad hoc mount points. After all, with some clever configuration and tuning, you dont need to write anywhere
else except places like /tmp, /var/run, /var/lock, and of course /home. The latter can be a traditional read-write file
system, and the formers can even use a tmpfs mount.
Episode 3: AUFS
13
Episode 4: GRSEC
Episode 4: GRSEC
GRSEC is a security patch to Linux kernel. Security features in
GRSEC help detect and deter malicious code.
dotcloud.com
14
Episode 4: GRSEC
15
GRSEC is a fairly large patch for the Linux kernel, providing strong security features that prevent many kinds of attacks
(or exploits), detect suspicious activity such as people looking for new exploits and/or known system vulnerabilities.
There are many features in GRSEC, so our goal is to provide an overview of the relevant features to dotCloud.
Randomize Address Space
Many exploits rely on the fact that the base address for the heap or the stack is always the same.
Consider the following example, this is a classic scenario for an attack on a remote service:
A bug is found in the service. Some index is not checked properly, and can be used to alter the stack, and cause a
jump to an arbitrary address (when a function returns)
The stack is altered to introduce some malicious code
A pointer to this malicious code is placed on the stack as well
The bug is triggered. The service jumps to the malicious code and executes it
If the address space of the stack is randomized, it would be much more difficult for an attacker to exploit the system.
The attacker would have to locate his malicious code before he can jump to the code in memory.
Prevent Execution of Arbitrary Code
There are two steps to make sure that arbitrary code cant make it inside a running program.
First, program code must be loaded in an area that is marked by the memory management unit as being read-only.
This prevents code from modifying itself. Self-modifying code is sometimes referred to as polymorphic code. There are
legitimate use cases for polymorphic code. However, it is more often associated with dubious intentions.
Second, the heap and the stack must be marked as non-executable. After all, theyre supposed to contain data
structures, function parameters, and return addresses but no opcode should be in there. On architectures supporting
it, the heap and the stack regions should be marked as non-executable at the hardware level, effectively preventing
accidental or intentional execution of code located in there.
At this point, there is no memory that is both executable and writable.
We mentioned that there were some legitimate uses for memory regions with both write and exec permissions. When
does that happen, and what can be done about it?
The most common case is on-the-fly code generation for optimization purposes. This use case is applicable to those
using Java and JIT (Just-In-Time) compiler.
The good news is that GRSEC lets you flag some specific executables and allows them to write to their code region or
execute their data region.
This reduces the security for those specific processes, but there are benefits. To exploit a bug, there has to be a bug in
e.g. the JVM itself, not in your program. Bugs in the JVM are likely to be found and fixed much faster than bugs in your
own program. This is not a comment about the quality of anyones code. Its more about the number of users in the
Java community and their scrutiny on the JVM.
Episode 4: GRSEC
16
Episode 4: GRSEC
17
In addition to GRSEC, dotCloud has built-in additional layers of security. Each service runs in its own container. The
benefits of container isolation were explained in Episode 2 on cgroups.
We do not allow dotCloud users to have root access. No root access means that users cannot SSH as root, cannot
login as root, and cannot get a root shell through sudo. All processes run under a regular, non-privileged UID.
Furthermore, SUID binaries are restricted to a set of well-known, well-audited programs, like ping.
Each of those security layers is strong. We believe that combining them together can provide a more than adequate
level of security for massively scaled, multi-tenant platforms.
18
dotcloud.com
19
All the HTTP traffic is bound to a group of special machines called the gateways. The gateways parse
HTTP requests, and route them to the appropriate backends. When there are multiple backends for a
single service, the gateways also deal with the load balancing and failover. Last but not least, the gateways
also forward HTTP l
visitors
(technically
HTTP clients)
dotCloud platform
This HTTP routing layer, as we call it, runs on an elastic number of dedicated machines. When the load is low, 3
machines are enough to deal with the traffic. When spikes or DoS attacks happen, we scale up to 6, 10, or even more
machines, to ensure optimal availability and latency.
All HTTP requests are bound to the HTTP routing layer, which is a cluster of identical HTTP load balancers. Each time
we create, update (e.g. scale), or delete an application on dotCloud, the configuration of those load balancers has to be
updated.
The master source for all the configuration is stored within a Riak cluster, working in tandem with a Redis cache. The
configuration is modified using basic commands:
Create a HTTP entry
Add/remove a frontend (virtual host)
Add/remove a backend (container)
The commands are passed through a ZeroRPC API. Each update done through the API propagates through the
platform; in the next sections, we will see which mechanisms are used.
Version 1: Nginx + ZeroRPC
As you probably know, a start-up must be lean, agile, and many other things. It also needs to be pragmatic, and the right
solution is not always the ideal one, but its the one that allowed us to ship on time. Thats why the first iteration of our routing
layer had some shortcomings, as we will see. But it has functioned properly up to support tens of thousands of apps.
Nginx powered the first version of dotClouds routing layer. Each modification to an app caused the central vhosts
service to push the full configuration to all the load balancers, using ZeroRPC.
Obviously, as the number of apps grew, the size of the configuration grew as well. Sending differential updates would
have been better. But at least, when a load balancer lost a few configuration messages, there was no special case to
handle. The next update would contain the full configuration, and provide all the necessary information.
The configuration was transmitted using a compressed, efficient format. Then, each load balancer would transform
this abstract configuration into the Nginx configuration file, and inform Nginx to reload this configuration. Nginx is well
designed, even when loading the new configurations, it can still serve requests along with the old one which meant that
no HTTP request is lost during the configuration update.
20
Nginx also handles load balancing and fail-over well. When a backend server dies, Nginx detects it, removes it from the
pool, periodically tries it again, and will re-add it to the pool once it has fixed itself.
This setup had two issues:
Nginx does not support the WebSocket protocol, which was one of the top features requested by our users at that
time
Nginx has no support for dynamic reconfiguration, which means that each configuration update requires the whole
configuration file to be regenerated and reloaded
At some point, the load balancers started to expend a significant amount of CPU time to reload Nginx configurations.
There was no significant impact on running applications, but it required deploying more and more powerful instances as
the number of apps increased.
Although Nginx was still fast and efficient, we had to find a more dynamic alternative.
Version 2: Node.js + Redis + WebSocket = Hipache
We spent some time digging through several kinds of languages and different technologies to solve this issue. We
needed the following features:
Ability to add, update, and remove virtual hosts dynamically, with a very low cost
Support for the WebSocket protocol
Great flexibility and control over the routed requests: we want to be able to trigger actions, log events, etc., during
different steps of the routing
After looking around, we finally decided to implement our own proxy solution. We did not implement everything from
scratch. We based our proxy on the node-http-proxy library developed by NodeJitsu. It included everything needed to
route a request efficiently with the appropriate level of control. The new routing layer would therefore be in JavaScript,
using Node.JS, leveraging on NodeJitsus library; we added several features such as the following:
21
22
CONCLUSION
As you can see, building a PaaS like dotCloud or Heroku involves specific knowledge about fundamental technologies.
Of course, you may not choose to implement any of the specific technologies that weve implemented in dotCloud.
We aim to expose the underlying technologies that weve implemented that provide isolation between apps, rapid
deployment, protection against security threats and distributed routing.
In other words, if you are serious about building a robust platform, you may want to become familiar with those types
of technologies. Or, alternatively, you could rely on an existing proven platform like dotCloud.
Join dotClouds Technical Community
Sign up for your own account
Join the technical discussions in our open forums
Read our blog
Have a technical question?
Email us: support@dotcloud.com
23
Authors Biography
Jrme Petazzoni, PaaS under the Hood, Episodes 1-4
Jrme is a senior engineer at dotCloud, where he rotates between Ops, Support and Evangelist duties and has earned
the nickname of master Yoda. In a previous life he built and operated large scale Xen hosting back when EC2 was just
the name of a plane, supervised the deployment of fiber interconnects through the French subway, built a specialized
GIS to visualize fiber infrastructure, specialized in commando deployments of large-scale computer systems in
bandwidth-constrained environments such as conference centers, and various other feats of technical wizardry. He cares
for the servers powering dotCloud, helps our users feel at home on the platform, and documents the many ways to use
dotCloud in articles, tutorials and sample applications. Hes also an avid dotCloud power user who has deployed just
about anything on dotCloud - look for one of his many custom services on our Github repository.
Connect with Jrme on Twitter! @jpetazzo
Sam Alba, PaaS Under the Hood, Episode 5
As dotClouds first engineering hire, Sam was part of the tiny team that shipped our first private beta in 2010. Since
then, he has been instrumental in scaling the platform to tens of millions of unique visitors for tens of thousands
of developers across the world, leaving his mark on every major feature and component along the way. Today, as
dotClouds first Director of Engineering, he manages our fast-growing engineering team, which is another way to
say he sits in meetings so that the other engineers dont have to. When not sitting in a meeting, he maintains several
popular open source projects, including Hipache and Cirruxcache and other projects also ending in -ache. In a
previous life, Sam supported Fortune 500s at Akamai, built the web infrastructure at several startups, and wrote
software for self-driving cars in a research lab at INRIA.
Follow Sam on Twitter @sam_alba