Introducing ds-operator, the ForgeRock Directory Services Operator for Kubernetes



ForgeRock Directory Services 7.0 was a big achievement for the Grenoble Directory team.  It is the only "Kubernetes native" directory where you can add a new replica using kubectl:

kubectl scale sts/ds-idrepo --replicas=3

The 7.0 deployment is assembled using standard Kubernetes primitives such as StatefulSets, Persistent Volume Claims, and Services.  This is all built and orchestrated using Skaffold and Kustomize

An emerging pattern in the Kubernetes world is the use of Custom Resources and Operators.  Broadly speaking, a custom resource is the declaration of the desired system state, and the operator's job is to observe the current state and bring the system into alignment with the declared state:

source: https://blog.container-solutions.com/kubernetes-operators-explained

The Kubernetes API server (the thing that responds to your kubectl commands) can be extended to handle new custom types.  A custom resource definition (CRD) describes to the API server the syntax and schema for the new custom type.  A custom resource (CR) is an instance of a custom type. There is one CRD for a type, but many possible CR definitions.

By creating a CRD, you make it possible to describe your system to Kubernetes at a higher level than is possible using the underlying primitives. At the end of the day,  users want to focus on running a Directory Service, not StatefulSets or Pods.

Introducing the ds-operator

 The ds-operator is a Kubernetes operator that deploys a ForgeRock Directory Service described by a Custom Resource. The operator enables us to focus on the higher level details of the directory service, and takes care of housekeeping details such as backup and restore. 

Here is a simple example:

# ds.yaml 
# Sample DirectoryService deployment
apiVersion: directory.forgerock.io/v1alpha1
kind: DirectoryService
metadata:
  name: ds-idrepo
  labels:
    app.kubernetes.io/name: ds
    app.kubernetes.io/part-of: forgerock
spec:
  image: gcr.io/forgeops-public/ds-idrepo:7.1-dev
  replicas: 2
  resources:
    requests:
      memory: 900Mi
      cpu: 250m
    limits:
      memory: 1024Mi
  storage: 5Gi
If you have the ds-operator installed on your cluster, deploying two replicated instances is as a simple as:

kubectl apply -f ds.yaml 

Because the API server is aware of our custom type, we can query the server for status:

kubectl describe directoryservice

Or even change the number of directory replicas.

kubectl scale directoryservice/ds-idrepo --replicas=3

If you try this out you will see that the operator creates the underlying Kubernetes StatefulSets, Services, and so on. What then is the benefit of the operator besides a more compact definition of the directory service?

The key difference is that an operator can be extended with special knowledge of the underlying system. A Kubernetes StatefulSet knows nothing about the LDAP protocol, or the replication state of the directory, but the operator does. For example, the operator can connect to the directory using LDAP or HTTP, and query the status of cn=monitor.

The ds-operator currently implements two new features that take advantage of direct LDAP protocol support.

The first is to synchronize Kubernetes secrets to directory service accounts. This can include the uid=admin root user, or the service account that ForgeRock Access Manager uses to connect to the CTS directory. Here is a snippet from the directory spec:

 passwords:
    uid=admin:
      secretName: ds-passwords
      key: dirmanager.pw
    uid=monitor:
      secretName: ds-passwords
      key: monitor.pw
      secretName: ds-env-secrets
      key: AM_STORES_CTS_PASSWORD
    uid=am-identity-bind-account,ou=admins,ou=identities:
      secretName: ds-env-secrets
      key: AM_STORES_USER_PASSWORD
    uid=am-config,ou=admins,ou=am-config:
      secretName: ds-env-secrets
      key: AM_STORES_APPLICATION_PASSWORD
The above definition maps the value of a Kubernetes secret to a directory account password. The operator will change the passwords of the account to match the secret value. It supports a "bring your own secrets" model where you create the referenced secrets, or alternatively the operator will generate random secrets for you.

Aside: Check out the ForgeRock Secret Agent Operator to generate deployment secrets and keystores. The operator also implements a new backup and restore feature that is more flexible and easier to use than the existing mechanism. For example, the backup parameters can be changed while the directory is running, without redeploying or rolling the StatefulSet.

Here is an example from the spec:
  backup:
    enabled: true
    # Path starts with s3://, gs:// , az:// or a path to the filesystem
    #path: /var/tmp/backup
    path: gs://ds-operator-engineering-devops/ds-backup-test
    # Crontab(5) format for the schedule
    cron: "35 * * * *"
    secretName: cloud-storage-credentials
    # purgeHours - backups older than this many hours will be purged. Defaults to 100 days (2400 hours)
    purgeHours: 500
    # purgeCron - how often to run the purge task to purge old backups. Defaults to "40 0 * * *"
    purgeCron: "40 0 * * *"
  # Restore from the last backup if the data directory is empty
  restore:
    enabled: true
    path: gs://ds-operator-engineering-devops/ds-backup-test
    secretName: cloud-storage-credentials
The above example will backup the directory to cloud storage (GCP, AWS and Azure are supported), and will recover the directory if a peristent volume is lost. For fun, you can run:

kubectl edit directoryservice/ds-idrepo

And enable/disable the backup, or change the cron schedule. If you query the directory cn=Task backend, observe that changes takes place within a minute or two.

Next Steps

We invite you to try the operator and give us feedback.  You can grab pre-built binaries or build the operator yourself.  The project and installation instructions can be found at  https://github.com/ForgeRock/ds-operator 

Do not use this in production yet! We need to test this thoroughly before we consider it ready. 

The operator is not a supported ForgeRock product, but we are very receptive to bug reports and pull requests.  The operator is currently offered under an open source license, but, as a reminder, the ForgeRock Directory Server must be licensed. 

Comments

Popular posts from this blog

Automating OpenDJ backups on Kubernetes

Deploying the ForgeRock platform on Kubernetes using Skaffold and Kustomize