Swift is the oldest and probably the mature project within OpenStack. It is the underlying technology that powers Rackspace’s Cloud Files™ service. While it only interacts tangentially with Nova (as shown in Chapter 3), it is still important in the overall scheme of understanding OpenStack.
Swift aims to provide a massively scalable and redundant object store conceptually similar to Amazon’s S3 service. To provide this scalability and redundancy, it writes multiple copies of each object to multiple storage servers within separate “zones.” Zones are a logical grouping of storage servers that have been isolated from each other to guard against failures. The level of isolation is up to the cloud operator; they can be isolated on differing servers (ability to lose individual servers), different racks (ability to lose entire rack), different sections of the data center, or even different data centers. Each choice provides a different level of isolation and cost.
Many beginners assume that Swift will take the place of their file server and that they will be able to easily mount volumes on their desktops to access their files. This is not the case. Swift is an object store, not a file server. While these sound similar, there are important differences. Object stores simply save files in logical groupings (called “containers” in Swift parlance) via a RESTful protocol. They do not provide a true filesystem, nor are they accessible through standard file sharing protocols like NFS (Network File System, the standard for UNIX), CIFS (Common Internet File System, the standard for Windows), or AFS (Appleshare Files System, the standard for Mac OS X). To access your files, you will need to use a the Swift API client. These are described later in this chapter.
Swift is configurable in terms of how many copies (called “replicas”) are written, as well as how many zones are configured. Current best practices call for three replicas written across five zones. As the number of replicas is less than or equal to the number of zones, Swift tries to balance the writing of objects to storage servers so that the write and read load is distributed. This is illustrated in Figure 2-1.
The logical view of Swift can be divided into two logical parts: presentation and resource. The major components, data stores, and interactions are illustrated in Figure 2-2.
Swift accepts end user requests via swift-proxy processes. swift-proxy accepts incoming end user requests; optionally authorizes and authenticates them; then passes them on to the appropriate object, account, or container processes for completion. It can optionally work with a cache (memcached[1]) to reduce authentication, container, and account calls. swift-proxy accepts requests via the OpenStack API on port 80. There is also an optional middleware to support the Amazon S3 protocol.
Swift handles authentication through a three-step process:
User authenticates through the authentication system (or middleware within swift-proxy) and receives a unique token (which is an operator-customizable string). This step is only required if the user doesn’t possess a valid token. Tokens are valid for an operator-configurable time limit (Rackspace Cloud Files™ uses a 24-hour timeout).
User issues a second request to Swift (directly to swift-proxy), passing the token along with the request in the HTTP headers.
swift-proxy validates the token and responds to user request with the help of swift-account, swift-container, and/or swift-object.
Swift authentication can be implemented through WSGI middleware or
as a separate system. For most installations, the WSGI middleware option
will be more straightforward. However, some enterprises might find the
separate system approach easier to integrate to their current
authentication scheme. Swift ships with sample authentication code
called swauth, which stores the
authentication database within Swift itself.
Swift manages a number of information sources through three processes that fulfill requests from swift-proxy. These three daemons are:
swift-account, which manages a sqlite3 database of accounts defined with the object storage service.
swift-container manages another sqlite3 database, but contains a mapping of containers (analogous to buckets in Amazon’s S3) within the object store service.
swift-object, a mapping of actual objects (i.e., Files) stored on the storage node.
Each of these processes are responsible for fulfilling requests from the proxy node, as well as auditing their own mappings (database consistency) and replicating any inconsistent information to other nodes in the ring.