_Editor’s note: Today’s guest post is by Jeff McCormick, a developer at Crunchy Data, showing how to build a PostgreSQL cluster using the new Kubernetes StatefulSet feature._
In an earlier [post](https://kubernetes.io/blog/2016/09/creating-postgresql-cluster-using-helm), I described how to deploy a PostgreSQL cluster using [Helm](https://github.com/kubernetes/helm), a Kubernetes package manager. The following example provides the steps for building a PostgreSQL cluster using the new Kubernetes [StatefulSets](/docs/concepts/abstractions/controllers/statefulsets/) feature.
StatefulSets is a new feature implemented in [Kubernetes 1.5](https://kubernetes.io/blog/2016/12/kubernetes-1-5-supporting-production-workloads/) (prior versions it was known as PetSets). As a result, running this example will require an environment based on Kubernetes 1.5.0 or above.
The example in this blog deploys on Centos7 using [kubeadm](/docs/admin/kubeadm/). Some instructions on what kubeadm provides and how to deploy a Kubernetes cluster is located [here](http://linoxide.com/containers/setup-kubernetes-kubeadm-centos).
The /etc/exports file should contain a line similar to this one except with the applicable IP address specified:
```
/nfsfileshare 192.168.122.9(rw,sync)
```
After these steps NFS should be running in the test environment.
**Step 3** - Clone the Crunchy PostgreSQL Container Suite
The example used in this blog is found at in the Crunchy Containers GitHub repo [here](https://github.com/CrunchyData/crunchy-containers.git). Clone the Crunchy Containers repository to your test Kubernertes host and go to the example:
This example will deploy a StatefulSet, which in turn creates two pods.
The containers in those two pods run the PostgreSQL database. For a PostgreSQL cluster, we need one of the containers to assume the master role and the other containers to assume the replica role.
So, how do the containers determine who will be the master, and who will be the replica?
This is where the new StateSet mechanics come into play. The StateSet mechanics assign a unique ordinal value to each pod in the set.
The StatefulSets provided unique ordinal value always start with 0. During the initialization of the container, each container examines its assigned ordinal value. An ordinal value of 0 causes the container to assume the master role within the PostgreSQL cluster. For all other ordinal values, the container assumes a replica role. This is a very simple form of discovery made possible by the StatefulSet mechanics.
PostgreSQL replicas are configured to connect to the master database via a Service dedicated to the master database. In order to support this replication, the example creates a separate Service for each of the master role and the replica role. Once the replica has connected, the replica will begin replicating state from the master.
During the container initialization, a master container will use a [Service Account](/docs/user-guide/service-accounts/) (pgset-sa) to change it’s container label value to match the master Service selector. Changing the label is important to enable traffic destined to the master database to reach the correct container within the Stateful Set. All other pods in the set assume the replica Service label by default.
In this deployment, there is a Service for the master and a separate Service for the replica. The replica is connected to the master and replication of state has started.
The Crunchy PostgreSQL container supports other forms of cluster deployment, the style of deployment is dictated by setting the PG\_MODE environment variable for the container. In the case of a StatefulSet deployment, that value is set to: PG\_MODE=set
This environment variable is a hint to the container initialization logic as to the style of deployment we intend.
The tests below assume that the psql client has been installed on the test system. If not, the psql client has been previously installed, it can be installed as follows:
In addition, the tests below assume that the tested environment DNS resolves to the Kube DNS and that the tested environment DNS search path is specified to match the applicable Kube namespace and domain. The master service is named pgset-master and the replica service is named pgset-replica.
Test the master as follows (the password is password):
Take a look at the persisted PostgreSQL data files on the resulting NFS mount path:
```
$ ls -l /nfsfileshare/
total 12
drwx------ 20 26 26 4096 Jan 17 16:35 pgset-0
drwx------ 20 26 26 4096 Jan 17 16:35 pgset-1
drwx------ 20 26 26 4096 Jan 17 16:48 pgset-2
```
Each container in the stateful set binds to the single NFS Persistent Volume Claim (pgset-pvc) created in the example script.
Since NFS and the PVC can be shared, each pod can write to this NFS path.
The container is designed to create a subdirectory on that path using the pod host name for uniqueness.
**Conclusion**
StatefulSets is an exciting feature added to Kubernetes for container builders that are implementing clustering. The ordinal values assigned to the set provide a very simple mechanism to make clustering decisions when deploying a PostgreSQL cluster.