diff options
Diffstat (limited to 'contrib/demos/magnum/redis-kube/README.rst')
| -rw-r--r-- | contrib/demos/magnum/redis-kube/README.rst | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/contrib/demos/magnum/redis-kube/README.rst b/contrib/demos/magnum/redis-kube/README.rst new file mode 100644 index 000000000..0a0ede6ab --- /dev/null +++ b/contrib/demos/magnum/redis-kube/README.rst @@ -0,0 +1,197 @@ +Reliable, Scalable Redis on Kubernetes +-------------------------------------- + +The following document describes the deployment of a reliable, +multi-node Redis on Kubernetes. It deploys a master with replicated +slaves, as well as replicated redis sentinels which are use for health +checking and failover. + +Prerequisites +~~~~~~~~~~~~~ + +This example assumes that you have a Kubernetes cluster installed and +running, and that you have installed the ``kubectl`` command line tool +somewhere in your path. Please see the `getting +started <https://github.com/GoogleCloudPlatform/kubernetes/tree/master/docs/getting-started-guides>`__ +for installation instructions for your platform. + +A note for the impatient +~~~~~~~~~~~~~~~~~~~~~~~~ + +This is a somewhat long tutorial. If you want to jump straight to the +"do it now" commands, please see the `tl; dr <#tl-dr>`__ at the end. + +Turning up an initial master/sentinel pod. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +is a +`*Pod* <https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/user-guide/pods.md>`__. +A Pod is one or more containers that *must* be scheduled onto the same +host. All containers in a pod share a network namespace, and may +optionally share mounted volumes. + +We will used the shared network namespace to bootstrap our Redis +cluster. In particular, the very first sentinel needs to know how to +find the master (subsequent sentinels just ask the first sentinel). +Because all containers in a Pod share a network namespace, the sentinel +can simply look at ``$(hostname -i):6379``. + +Here is the config for the initial master and sentinel pod: +`redis-master.yaml <redis-master.yaml>`__ + +Create this master as follows: + +.. code:: sh + + kubectl create -f examples/redis/v1beta3/redis-master.yaml + +Turning up a sentinel service +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In Kubernetes a *Service* describes a set of Pods that perform the same +task. For example, the set of nodes in a Cassandra cluster, or even the +single node we created above. An important use for a Service is to +create a load balancer which distributes traffic across members of the +set. But a *Service* can also be used as a standing query which makes a +dynamically changing set of Pods (or the single Pod we've already +created) available via the Kubernetes API. + +In Redis, we will use a Kubernetes Service to provide a discoverable +endpoints for the Redis sentinels in the cluster. From the sentinels +Redis clients can find the master, and then the slaves and other +relevant info for the cluster. This enables new members to join the +cluster when failures occur. + +Here is the definition of the sentinel +service:\ `redis-sentinel-service.yaml <redis-sentinel-service.yaml>`__ + +Create this service: + +.. code:: sh + + kubectl create -f examples/redis/v1beta3/redis-sentinel-service.yaml + +Turning up replicated redis servers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +So far, what we have done is pretty manual, and not very fault-tolerant. +If the ``redis-master`` pod that we previously created is destroyed for +some reason (e.g. a machine dying) our Redis service goes away with it. + +In Kubernetes a *Replication Controller* is responsible for replicating +sets of identical pods. Like a *Service* it has a selector query which +identifies the members of it's set. Unlike a *Service* it also has a +desired number of replicas, and it will create or delete *Pods* to +ensure that the number of *Pods* matches up with it's desired state. + +Replication Controllers will "adopt" existing pods that match their +selector query, so let's create a Replication Controller with a single +replica to adopt our existing Redis server. +`redis-controller.yaml <redis-controller.yaml>`__ + +The bulk of this controller config is actually identical to the +redis-master pod definition above. It forms the template or "cookie +cutter" that defines what it means to be a member of this set. + +Create this controller: + +.. code:: sh + + kubectl create -f examples/redis/v1beta3/redis-controller.yaml + +We'll do the same thing for the sentinel. Here is the controller +config:\ `redis-sentinel-controller.yaml <redis-sentinel-controller.yaml>`__ + +We create it as follows: + +.. code:: sh + + kubectl create -f examples/redis/v1beta3/redis-sentinel-controller.yaml + +Resize our replicated pods +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Initially creating those pods didn't actually do anything, since we only +asked for one sentinel and one redis server, and they already existed, +nothing changed. Now we will add more replicas: + +.. code:: sh + + kubectl resize rc redis --replicas=3 + +.. code:: sh + + kubectl resize rc redis-sentinel --replicas=3 + +This will create two additional replicas of the redis server and two +additional replicas of the redis sentinel. + +Unlike our original redis-master pod, these pods exist independently, +and they use the ``redis-sentinel-service`` that we defined above to +discover and join the cluster. + +Delete our manual pod +~~~~~~~~~~~~~~~~~~~~~ + +The final step in the cluster turn up is to delete the original +redis-master pod that we created manually. While it was useful for +bootstrapping discovery in the cluster, we really don't want the +lifespan of our sentinel to be tied to the lifespan of one of our redis +servers, and now that we have a successful, replicated redis sentinel +service up and running, the binding is unnecessary. + +Delete the master as follows: + +.. code:: sh + + kubectl delete pods redis-master + +Now let's take a close look at what happens after this pod is deleted. +There are three things that happen: + +1. The redis replication controller notices that its desired state is 3 + replicas, but there are currently only 2 replicas, and so it creates + a new redis server to bring the replica count back up to 3 +2. The redis-sentinel replication controller likewise notices the + missing sentinel, and also creates a new sentinel. +3. The redis sentinels themselves, realize that the master has + disappeared from the cluster, and begin the election procedure for + selecting a new master. They perform this election and selection, and + chose one of the existing redis server replicas to be the new master. + +Conclusion +~~~~~~~~~~ + +At this point we now have a reliable, scalable Redis installation. By +resizing the replication controller for redis servers, we can increase +or decrease the number of read-slaves in our cluster. Likewise, if +failures occur, the redis-sentinels will perform master election and +select a new master. + +tl; dr +~~~~~~ + +For those of you who are impatient, here is the summary of commands we +ran in this tutorial + +.. code:: sh + + # Create a bootstrap master + kubectl create -f examples/redis/v1beta3/redis-master.yaml + + # Create a service to track the sentinels + kubectl create -f examples/redis/v1beta3/redis-sentinel-service.yaml + + # Create a replication controller for redis servers + kubectl create -f examples/redis/v1beta3/redis-controller.yaml + + # Create a replication controller for redis sentinels + kubectl create -f examples/redis/v1beta3/redis-sentinel-controller.yaml + + # Resize both replication controllers + kubectl resize rc redis --replicas=3 + kubectl resize rc redis-sentinel --replicas=3 + + # Delete the original master pod + kubectl delete pods redis-master + |
