Deploying Sync Gateway cluster

This guide demonstrates how to deploy a Sync Gateway cluster on Kubernetes.

Prerequisites

Before you begin, you must have the following:

  • A Couchbase Server cluster already running on Kubernetes. If you don’t already have one, you can refer to this guide for instructions.

  • A Couchbase Server RBAC user with application access privileges. Sync Gateway will connect to the Couchbase Server as this RBAC user. Refer to this section for instructions.

Deploying a Sync Gateway Cluster

The Sync Gateway nodes in a cluster have a homogeneous configuration with the exception of import node.

Import node

Under convergence/shared bucket access, it is recommended that one Sync Gateway node in a cluster be configured for handling document import processing. For high availability, you can configure more than one Sync Gateway node in your cluster to be the import node, although it is strongly discouraged for multiple Sync Gateway nodes in the cluster to be configured for import processing. The configuration of the Sync Gateway import node is slightly different than the "regular" or "non-import" Sync Gateway nodes (see databases.$db.import_docs).

The following sections cover the steps to deploy regular or import Sync Gateway nodes.

You will have to repeat the steps in this section once for the "regular" or non-import nodes and once for the "import" node. The difference is the Sync Gateway configuration file and the Kubernetes Deployment Controller config file.

Sync Gateway Configuration File

In this section, you will create a Kubernetes secret from a new or existing Sync Gateway configuration.

  1. Open the Sync Gateway configuration file corresponding to your deployment. If you don’t have a configuration file you may also use our sample configuration shown below as a starting point.

    Regular Node Import Node

    sgw-config.json

    sgw-config-import.json

  2. Replace the server key with the addressable Couchbase Server hostname. The following example shows the configuration file for a regular node.

    {
      "logging": {
        "console": {
          "log_file_path": "/var/tmp/sglogs",
          "console": {
            "log_level": "debug",
            "log_keys": ["*"]
          },
          "error": {
            "enabled": true,
            "rotation": {
              "max_size": 20,
              "max_age": 180
            }
          },
          "warn": {
            "enabled": true,
            "rotation": {
              "max_size": 20,
              "max_age": 90
            }
          },
          "info": {
            "enabled": false
          },
          "debug": {
            "enabled": false
          }
        }
      },
      "databases": {
        "db": {
          "server": "cb-example-0000.cb-example.default.svc:8091", (1)
          "bucket": "default",
          "username": "admin", (2)
          "password": "password",
          "users": { "GUEST": { "disabled": false, "admin_channels": ["*"] } },
          "allow_conflicts": false,
          "revs_limit": 20
        }
      }
    }
    1 The server key should point to any pod in the Couchbase Server cluster. This would typically be of the form CB_SERVER_POD.CB_SERVER_SERVICE_NAME.NAMESPACE.svc:8091.
    2 The username/password keys should match what was setup in the pre-requisites section when you configured the Sync Gateway RBAC user.
  3. You will use a Kubernetes Secret to pass the configuration file to Sync Gateway on launch. Alternatively, you could use a Kubernetes configMap if you are not concerned about security. However, since the Sync Gateway contains sensitive information, it is recommended that you create a secret from the config file and pass that to the Sync Gateway. Run the following command to create a secret called "sgw-config" or "sgw-config-import" corresponding to regular and import versions of Sync Gateway configuration file respectively

    • Regular node

    • Import node

    kubectl create secret generic sgw-config --from-file sgw-config.json
    kubectl create secret generic sgw-config-import --from-file sgw-config-import.json

    If successful, you will see the following.

    • Regular node

    • Import node

    secret "sgw-config" created
    secret "sgw-config-import" created

Deployment controller

In this section you will deploy the Sync Gateway cluster with the configuration file that you created above.

You will be using a Kubernetes deployment controller. A deployment controller allows you to define the number of Sync Gateway replicas and other parameters.

  1. Open the controller file corresponding to your deployment.

    Regular Node Import Node

    sgw-deployment.yaml

    sgw-deployment-import.yaml

    The following example shows the controller file for a regular node.

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: sync-gateway (1)
    spec:
      replicas: 2 (2)
      template:
        metadata:
          labels:
            app: sync-gateway
        spec:
          containers:
            - name: sync-gateway
              image: couchbase/sync-gateway:2.1.2-enterprise (3)
              args: ["/sync-gateway-config/sgw-config.json"] (4)
              volumeMounts: (5)
                - name: sgw-config-volume
                  mountPath: /sync-gateway-config
                  readOnly: true
              env:
                - name: GOMAXPROCS (6)
                  value: "2"
              resources:
                requests:
                  cpu: "2"
                limits:
                  cpu: "2" (7)
          volumes: (8)
            - name: sgw-config-volume
              secret:
                secretName: sgw-config
    1 metadata.name: The name of the deployment is "sync-gateway".
    2 spec.replicas: 2 Sync Gateway replicas that are deployed at most.
    • For import node deployment, this is recommended to be 1. If high availability is important, you may want at least 2 Sync Gateway import nodes. However, given the overhead of redundant import docs processing by multiple nodes, this is not typically recommended.

    3 containers[].image: Points to the docker image for Sync Gateway.
    4 containers[].args: Points to the Sync Gateway configuration file named "sgw-config-working.json" which is mounted at the path specified via the volumeMounts config. If you are using the sample config files, this would be "sgw-config-import.json" for the import node.
    5 volumeMounts: Specifies where to mount the volume into the container.
    6 GOMAXPROCS: This GO runtime environment variable is used to limit the number of system threads that are allocated to Sync Gateway.
    7 containers[].resources.limits.cpu: This is used to specify the CPU limit for the Sync Gateway pod. If you do not specify one, the Sync Gateway could spawn as many processes as CPU cores and potentially use up all CPU resources. You can learn more about CPU resource assignment here. We recommend a value of 2 but you should use what is suited for your environment.
    8 volumes: Specifies what to mount. In our case, the "secret" with name "sgw-config" corresponding to the Sync Gateway configuration that was created in the previous step is mounted. Learn more about Kubernetes volumes here.
  2. Deploy the Sync Gateway cluster from the specified deployment controller file.

    • Regular node

    • Import node

    kubectl create --from-file sgw-deployment.yaml
    kubectl create --from-file sgw-deployment-import.yaml

    If successful, you will see the following.

    • Import node

    • Regular node

    deployment.extensions "sync-gateway" created
    deployment.extensions "sync-gateway" created
  3. You can check the status of the deployment with the following command until all the pods corresponding to the Sync Gateway are in the "Ready" state and the status is "Running".

    kubectl get pods --watch

    The --watch option is optional but you use it to be asynchronously notified of updates to status of the pods instead of having to repeatedly run the command.

    If successful, you will see a listing of the Sync Gateway pods that were deployed. In the sample output below, we have Couchbase Server and Sync Gateway pods running in the same namespace. In a production deployment, you may have Couchbase Server deployed on a separate namespace.

    NAME                                 READY     STATUS    RESTARTS   AGE
    cb-example-0000                      1/1       Running   0          3d
    cb-example-0001                      1/1       Running   0          3d
    cb-example-0002                      1/1       Running   0          3d
    couchbase-operator-fd8db588b-9fzsw   1/1       Running   1          3d
    sync-gateway-7474f5df4b-c29xw        1/1       Running   2          18m
    sync-gateway-7474f5df4b-p98sq        1/1       Running   0          18m

    Make sure that you have sufficient CPU resources on the node on which the pods are being deployed. Failure to do so will result in an "insufficient resource" exception when attempting to deploy the pods.

Deploying a Load Balancer

In a production deployment, you will likely have one or more Sync Gateway nodes fronted by a load balancer.

You will deploy the load balancer using the Kubernetes Load Balancer service. The load balancer service provides an externally accessible IP address and routes traffic to the right ports in the cluster.

Load balancers only work on Cloud Environments (e.g. AWS, GCP etc). So if you are deploying on premise or using something like minikube for your test deployment, this option will not work. Please use a service such as NodePort or Ingress instead.

Follow these steps to deploy a load balancer in front of the Sync Gateway cluster.

  1. Create a new file called sgw-load-balancer.yaml with the following.

    kind: Service
    apiVersion: v1
    metadata:
      name: sgw-load-balancer (1)
    spec:
      selector:
        app: sync-gateway (2)
      ports:
      - protocol: TCP
        port: 4984 (3)
        targetPort: 4984
      type: LoadBalancer
    1 metadata.name: The name of the load balancer is "sgw-load-balancer".
    2 spec.selector.app: This value corresponds to the pods targeted by the load balancer. In this case, it targets any pods with the app=sync-gateway label which are the Sync Gateway nodes - this corresponds to what was specified in the deployment yaml file.
    3 spec.ports[].targetPort: The load balancer service targets port 4984 on the Sync Gateway cluster. This is the Sync Gateway port corresponding to the REST API. For security purposes, it is recommended that you do not expose the admin port (4985) over the Internet.
  2. Deploy the load balancer.

    kubectl create -f sgw-load-balancer.yaml

    If successful, you will see the following.

    service "sgw-load-balancer" created
  3. Verify the status of the service creation with the following.

    kubectl get services

    If successful, you will see a new service corresponding to the load balancer. In the sample output below, we have the sgw-load-balancer service.

    NAME                TYPE           CLUSTER-IP     EXTERNAL-IP
    cb-example          ClusterIP      None           <none>
    cb-example-srv      ClusterIP      None           <none>
    cb-example-ui       NodePort       10.3.246.239   <none>
    kubernetes          ClusterIP      10.3.240.1     <none>
    sgw-load-balancer   LoadBalancer   10.3.253.17    35.184.19.17

    The sgw-load-balancer's EXTERNAL-IP is the load balancer’s publicly accessible hostname.

  4. Verify the pods that the load balancer is targeting.

    kubectl describe service sgw-load-balancer

    You should see the equivalent of the following.

    Name:                     sgw-load-balancer
    Namespace:                default
    Labels:                   <none>
    Annotations:              <none>
    Selector:                 app=sync-gateway
    Type:                     LoadBalancer
    IP:                       10.3.253.17
    LoadBalancer Ingress:     35.184.19.17
    Port:                     <unset>  4984/TCP
    TargetPort:               4984/TCP
    NodePort:                 <unset>  32397/TCP
    Endpoints:                10.0.0.34:4984,10.0.0.35:4984
    Session Affinity:         None
    External Traffic Policy:  Cluster
    Events:

    Notice the "endpoints" field and confirm that it corresponds to the Sync Gateway nodes. In this example, we have 2 Sync Gateway nodes.

  5. Verify the Sync Gateway cluster is accessible with the following command; where EXTERNAL-IP is the IP that was copied in step 3.

    curl  http://EXTERNAL-IP:4984

    It should return the following.

    {"couchdb":"Welcome","vendor":{"name":"Couchbase Sync Gateway","version":"2.1"},"version":"Couchbase Sync Gateway/2.1.1(17;fea9947)"}

You have successfully deployed a Sync Gateway cluster on Kubernetes. The Manage a Cluster page contains additional details related to the management of the cluster.