Example Kubernetes Projects

Two example Kubernetes projects that demonstrate the use and capabilities of the DirX Directory container images are delivered in the same archive as two separate folders: standalone and scalable. The standalone example project runs a full DirX Directory installation in a single pod using the dxd container image. The scalable example project demonstrates a horizontally scalable deployment using the per-server container images and the dirxcontroller image. The next sections describe both example projects and how to use them.

Restrictions

This section describes restrictions that apply to the example DirX Directory Kubernetes projects.

Distribution

The example DirX Directory Kubernetes projects are supported on Kubernetes certified distributions. The example projects only use the default set of Kubernetes resources, so any certified distribution should work. However, certain distributions may have platform-specific behavior or limitations that could cause issues. Currently, minikube and Rancher are actively tested. If you encounter problems with a different certified distribution, the configuration may need to be adapted to accommodate its specifics.

Artifacts

The example DirX Directory Kubernetes projects are delivered and tested as reference deployments. Any modifications to the Kubernetes configuration beyond the procedures described in this document are the responsibility of the customer and are outside the scope of DirX Directory support.

Scalable Example Project

Due to the scalable nature of the scalable example project, where DirX Directory processes run in separate containers, certain features behave differently or are not available compared to a traditional installation.

Extended Operations

Extended operations issued over the load balancer are routed to any one of the load-balanced servers. Therefore, extended operations that must target a particular server instance should be executed from debug containers attached to the chosen server pod instead of through the load balancer. For example:

kubectl debug -n dxd -it dirxldap-abcd --image=dxd --target=dirxdsa --profile=general -- /bin/bash

RPC Ports

RPC ports are not exposed by default, because load balancing would route RPC requests to arbitrary servers. If you still need to expose RPC ports externally, you must create a more specific service that targets a particular pod. The following example service definition exposes the RPC ports for the master DSA:

apiVersion: v1
kind: Service
metadata:
  name: dirxdsa-0-rpc
  labels:
    app: dirxdsa-rpc
spec:
  type: LoadBalancer
  selector:
    statefulset.kubernetes.io/pod-name: dirxdsa-0
  ports:
    - name: rpc-5999
      port: 5999
      targetPort: 5999
      protocol: TCP
    - name: rpc-6000
      port: 6000
      targetPort: 6000
      protocol: TCP
    - name: rpc-6001
      port: 6001
      targetPort: 6001
      protocol: TCP
    - name: rpc-6002
      port: 6002
      targetPort: 6002
      protocol: TCP
    - name: rpc-6003
      port: 6003
      targetPort: 6003
      protocol: TCP
    - name: rpc-6004
      port: 6004
      targetPort: 6004
      protocol: TCP

RPC Authentication in LDAP Server

RPC authentication in the LDAP server relies on a shared file between the DSA and the LDAP server. Since in the scalable example project these processes run in separate containers, this shared file is not available. Therefore, the LDAP RPC interface will not require authentication.

dirxprogsvr

The dirxprogsvr is not implemented in the scalable container images. Prog policies are executed directly by the DSA.

LDAP Cache

LDAP cache is not supported in the scalable example project. Cache invalidation relies on watchdog functionality that is not used in the per-server container images.

Prerequisites

Deploying and running the example DirX Directory Kubernetes projects has the following prerequisites.

System Requirements

The host machine requires at least 8 GB RAM and 40 GB free disk space to deploy the DirX Directory Kubernetes example projects.

Kubernetes Distribution

Deploying the example DirX Directory Kubernetes projects requires a certified Kubernetes distribution.

Standalone Example Project

The standalone example project runs the DirX Directory service using the dxd container image in a single stateful set pod.

Architecture

The standalone example project runs the DirX Directory service in a single stateful set pod. The pod contains the dxd container image with all server and client binaries. The stateful set is connected to persistent volume claims for database files, log files, and other persistent data. A set of Kubernetes services expose the DSA, LDAP, and HTTP ports via LoadBalancer resources. Configuration files are provided through ConfigMaps and Secrets that are mounted into the container as read-only volumes.

Configuration

The root of the standalone example project contains a set of folders that are similar to a normal DirX Directory installation: client, conf, dsa, http, ldap, progsvr, tools and several other configuration files.

The content of these folders corresponds to a normal DirX Directory installation and contains several types of configuration files. The next sections describe these files in more detail.

init_scripts_config_map.yaml

As in Kubernetes, the standalone example project has a resource called an init container. The init_scripts_config_map.yaml configuration file contains the initialization scripts to be executed before the DirX Directory container starts up. It handles initializing a database file and loading the o=My-Company example database. You can customize the initialize_db.sh script to set the DBAM profile to your requirements.

stateful_set.yaml

This configuration file contains the definition of the main stateful set resource. It defines the init container, the container, the container ports used and the mounted volumes. As the stateful set contains the definition of the container in use, the dxd container image version to be used can be specified here. For this, the image property should be set in both the container and the init container definition.

service.yaml

The service.yaml configuration files define the service resources that are used to expose ports. There are multiple service.yaml files, one for each DirX Directory server. You can modify the exposed port numbers in these files.

*_pvc.yaml

These configuration files define the persistent volume claims that are used to persist the files used by the DirX Directory service. These files include the database files, log files, audit files, etc. You can adjust the size of the persistent volume claims by setting the storage parameter.

*config_map.yaml

Config maps are used to store the configuration files used by the DirX Directory service. There are several files with this naming structure, containing all configuration files used in a normal DirX Directory installation. You can modify these configuration files according to your requirements.

secret.yaml

Kubernetes secrets are used to store sensitive or binary data. In the standalone example project, they are used to store encrypted password files, client certificates, user certificates, license files, etc. These secrets can be updated according to your requirements.

Scalable Example Project

The scalable example project demonstrates a horizontally scalable DirX Directory deployment. Instead of running all servers in a single pod, it uses the per-server container images to run each server type as a separate Kubernetes resource. Replication between DSA instances is managed automatically by the dirxcontroller image.

Architecture

The scalable example project deploys the following components:

  • A DSA stateful set running multiple replicas of the dirxdsa image. Each replica holds a copy of the directory database. The first replica (dirxdsa-0) acts as the master, and the remaining replicas are consumers that receive data through synchronous shadowing agreements.

  • An LDAP server replica set running multiple replicas of the dirxldapv3 image. These stateless pods provide LDAP access to the DSAs.

  • An HTTP server replica set running multiple replicas of the dirxhttp image. These stateless pods provide HTTP/HTTPS access to the LDAP servers.

  • A controller CronJob running the dirxcontroller image. The controller periodically reconciles the desired number of DSA replicas with the actual state by creating or removing shadowing agreements and managing readiness gates.

  • Network policies that restrict traffic between components to only the required ports.

  • Services that expose the DSA, LDAP, and HTTP ports via LoadBalancer resources and provide internal headless service for DSA-to-DSA communication.

Configuration

The root of the scalable example project contains four folders: controller, dsa, http, and ldap. Each folder contains the Kubernetes resource definitions for the respective component.

controller/

The controller folder contains the configuration for the dirxcontroller CronJob:

  • config_map.yaml - contains the reconciliation script that manages shadowing agreements, scales the DSA stateful set, and maintains readiness gates on DSA pods.

  • cronjob.yaml - defines the CronJob that runs the controller every minute.

  • log_pvc.yaml - defines the persistent volume claim for controller logs.

dsa/

The dsa folder contains the configuration for the DSA stateful set:

  • stateful_set.yaml - defines the DSA stateful set using the dirxdsa image. It uses the dxd image as an init container for database initialization. The dirxdsa/desired-replicas annotation controls the desired number of DSA replicas.

  • internal_service.yaml - defines a headless service for inter-DSA communication using RPC ports.

  • loadbalancer_service.yaml - defines a LoadBalancer service to expose DSA ports externally.

  • config_map.yaml and conf_config_map.yaml - contain the DSA configuration files.

  • secret.yaml and conf_secret.yaml - contain sensitive data such as encrypted password files, certificates, and license files.

  • init_script_config_map.yaml - contains the initialization scripts for database setup.

ldap/

The ldap folder contains the configuration for the LDAP server replica set:

  • replica_set.yaml - defines a replica set using the dirxldapv3 image.

  • service.yaml - defines a LoadBalancer service to expose LDAP and LDAPS ports.

  • config_map.yaml and conf_config_map.yaml - contain the LDAP server configuration files.

  • secret.yaml and conf_secret.yaml - contain sensitive data such as encrypted password files, certificates, and license files.

  • log_pvc.yaml and audit_pvc.yaml - define persistent volume claims for logs and audit files.

http/

The http folder contains the configuration for the HTTP server replica set:

  • replica_set.yaml - defines a replica set using the dirxhttp image.

  • service.yaml - defines a LoadBalancer service to expose HTTP and HTTPS ports.

  • config_map.yaml - contains the HTTP server configuration files.

  • secret.yaml - contains sensitive data such as encrypted password files and certificates.

  • log_pvc.yaml and audit_pvc.yaml - define persistent volume claims for logs and audit files.

Scaling

The scalable example project supports horizontal scaling of each server. The following sections describe how to scale the individual components.

DSA

The desired number of DSA replicas is controlled by the dirxdsa/desired-replicas annotation on the DSA stateful set. To scale the DSA, modify the annotation value in the dsa/stateful_set.yaml file and reapply the configuration:

kubectl apply -n namespace -f dsa/stateful_set.yaml

Do not specify the replicas field in the DSA stateful set. The controller manages the actual replica count based on the dirxdsa/desired-replicas annotation. Setting replicas directly will conflict with the controller’s scaling logic.

This is the recommended approach when using file-based deployments, as it keeps the desired state in version control and ensures consistency between the configuration files and the running cluster.

When scaling up, the controller CronJob will detect the change and automatically:

  1. Scale the stateful set to the desired number of replicas.

  2. Wait for new pods to be running.

  3. Create shadowing agreements between the master (dirxdsa-0) and the new consumer replicas.

  4. Wait until the database has been replicated to the new consumers.

  5. Mark the new pods as ready for the load balancer using readiness gates.

When scaling down, the controller will:

  1. Remove the pods to be deleted from the load balancer by clearing their readiness condition.

  2. Wait for endpoint updates to propagate.

  3. Delete the shadowing agreements for the removed replicas.

  4. Scale down the stateful set.

LDAP Server / HTTP Server

The LDAP server and HTTP server are deployed as replica sets. To scale them, modify the replicas field in the respective replica_set.yaml file and reapply the configuration:

kubectl apply -n namespace -f ldap/replica_set.yaml
kubectl apply -n namespace -f http/replica_set.yaml

Since these servers are stateless, Kubernetes handles scaling directly without additional coordination. New pods become available to the load balancer as soon as they are running and ready.

Using the Example Kubernetes Projects

This section describes example workflows for deploying and using the example DirX Directory Kubernetes projects. For these instructions, minikube is used as an example local Kubernetes environment. The same kubectl commands apply to any certified Kubernetes distribution.

Setting up Minikube

Follow the minikube installation instructions (see https://minikube.sigs.k8s.io/docs) and ensure the minikube instance is running. Use the following command to check it:

minikube status

The default-storageclass and storage-provisioner addons must be enabled. The status of the addons can be verified by executing the following command:

minikube addons list

Loading the Container Images

The first step of executing a containerized application is to get and load the container images. Load the DirX Directory container images to the local registry.

For minikube, use the command:

minikube image load dxd-k8s-9.7.138.tar

This command adds the container image to the local registry inside the minikube environment. DirX Directory delivers the container images with only a single label containing the full version.

However, the example projects use the default "latest" tag to refer to the container images in both the container and the init container definitions. After loading the images, you should either re-tag them to "latest" or update the image references in the yaml configuration files to use the specific version tag.

To use a specific image version, you can specify the tag in the image property of the containers and initContainers sections of the respective yaml configuration files. Alternatively, you can tag the image with the specific version tag to the default tag, as shown in the following command:

minikube image tag dxd:9.7.138 dxd

For the scalable example project, all images must be loaded: dxd, dirxdsa, dirxldapv3, dirxhttp, and dirxcontroller.

Tunneling the Ports

The example Kubernetes projects use LoadBalancer Kubernetes resources to expose their ports. In minikube, these ports are only available inside the minikube environment by default. To expose these ports to a specified bind address, use the command:

minikube tunnel --bind-address=target_IP

where target_IP is the IP address of the network interface to which the exposed ports should be bound. For example, to make the LDAP ports available outside minikube on the host’s loopback interface, use the command:

minikube tunnel --bind-address=127.0.0.1

Standalone

This section describes workflows specific to the standalone example project.

Starting the Standalone Example Project

The provided Kubernetes configuration files and the container image make it easy to run the DirX Directory service in the Kubernetes environment with the default My-Company configuration. To start the standalone project:

  • Get and load the dxd container image as described in the section "Loading the Container Images".

  • Extract the Kubernetes configuration files and then modify the parameters defined in the configuration section to your requirements; for example, DirX Directory version, port numbers, storage space, and so on. When preparing the configuration files, it is recommended to create a new namespace using the command:

    kubectl create ns namespace

  • Apply the configuration files with the command:

    kubectl apply -n namespace -Rf configuration_path

    where configuration_path is the folder to which you have extracted the provided Kubernetes configuration yaml files.

  • Check the status of the DirX Directory pod by running the command:

    kubectl get pods -n namespace

Here is an example startup command sequence for a DirX Directory service dxd-standalone:

kubectl create ns dxd-standalone
kubectl apply -n dxd-standalone -Rf standalone/
kubectl get pods -n dxd-standalone

Please note that starting up a pod takes time, so the last command may be repeated several times until the pod comes up, showing a Running status.

Setting up Shadowing

This section describes how to implement a simple supplier-consumer scenario using the standalone example project.

Create Master and Shadow Kubernetes Projects

As this shadowing scenario needs two DirX Directory instances with different configurations, the first step is to copy the standalone example project files into two different folders called dxd-master and dxd-shadow. These folders will contain the necessary configuration for the supplier and the consumer respectively. To perform this task, run the following commands:

cp -R standalone dxd-master
cp -R standalone dxd-shadow
Set Master and Shadow DSA Identifiers

Next, set the DIRX_HOST_NAME, DIRX_DSA_NAME and DIRX_OWN_PSAP environment variables. Open the dxd-master/conf/config_map.yaml file and append the following rows to dirxenv.ini:

set DIRX_DSA_NAME=CN=DirX-k8s-master
set DIRX_HOST_NAME=dxd-service.dxd-master.svc.cluster.local
set DIRX_OWN_PSAP=TS=DSA1,NA='TCP/IP_IDM!internet=1.2.3.4+port=1234',DNS='(HOST=dxd-service.dxd-master.svc.cluster.local,PLAINPORT=21200)'"

Now open the dxd-shadow/conf/config_map.yaml file and append the following rows to dirxenv.ini:

set DIRX_DSA_NAME=CN=DirX-k8s-shadow
set DIRX_HOST_NAME=dxd-service.dxd-shadow.svc.cluster.local
set DIRX_OWN_PSAP=TS=DSA2,NA='TCP/IP_IDM!internet=1.2.3.4+port=1234',DNS='(HOST=dxd-service.dxd-shadow.svc.cluster.local,PLAINPORT=21200)'"
Adjust Duplicate LoadBalancer Resources

As both dxd-master and dxd-shadow are copied from the same source, they contain the same definitions for the LoadBalancer service resources. If multiple LoadBalancer resources are started with the same port, it will result in port collisions when the traffic is tunneled to an IP address. So as the next step, you should delete or modify these resources. If you would like to access only one of the nodes from an external IP, you can delete the dsa/service.yaml, ldap/service.yaml, progsvr/service.yaml and http/service.yaml files from one of the copied folders. If you would like to access both, you can modify the port numbers in these files to avoid port collision.

Start Master and Shadow Instances

When the configuration is finished, start the dxd-master instance with the following commands:

kubectl create ns dxd-master
kubectl apply -n dxd-master -Rf dxd-master/
kubectl get pods -n dxd-master

Then start the dxd-shadow instance:

kubectl create ns dxd-shadow
kubectl apply -n dxd-shadow -Rf dxd-shadow/
kubectl get pods -n dxd-shadow
Create the Shadowing Agreement

After these commands are executed, there are two separate standalone DirX Directory instances running. Both are loaded with the o=My-Company example database. The next step is to create the shadowing agreement between the two standalone DSAs using the following commands:

kubectl exec -it -n dxd-master dxd-0 -- bash
dirxadm -c "defbind; sob create -consumer {/CN=DirX-k8s-shadow} \
    -agreementid 15 \
    -consumerpsap {TS=DSA2,NA='TCP/IP_IDM!internet=1.2.3.4+port=1234',DNS='(HOST=dxd-service.dxd-shadow.svc.cluster.local,PLAINPORT=21200)'} \
    -supplier {/CN=DirX-k8s-master} \
    -supplierpsap {TS=DSA1,NA='TCP/IP_IDM!internet=1.2.3.4+port=1234',DNS='(HOST=dxd-service.dxd-master.svc.cluster.local,PLAINPORT=21200)'} \
    -consumerkind CENTRALADMIN  \
    -status cooperative \
    -agreement {SS={AREA={CP={/o=My-Company},\
        RA={DEF=TRUE}},\
        ATT={DEF=TRUE}},\
        UM={SI={OC=TRUE}},CHANGEO=FALSE} \
    -pol {CONS={REPLS=TRUE}}"

Scalable

This section describes workflows specific to the scalable example project.

Starting the Scalable Example Project

To start the scalable example project:

  • Get and load all DirX Directory container images (dxd, dirxdsa, dirxldapv3, dirxhttp, dirxcontroller) as described in the section "Loading the Container Images".

  • Extract the Kubernetes configuration files and create a new namespace:

    kubectl create ns namespace

  • Apply the configuration files with the command:

    kubectl apply -n namespace -Rf configuration_path

    where configuration_path is the scalable folder.

  • Check the status of all pods by running the command:

    kubectl get pods -n namespace

Here is an example startup command sequence:

kubectl create ns dxd-scalable
kubectl apply -n dxd-scalable -Rf scalable/
kubectl get pods -n dxd-scalable

After startup, the controller CronJob will run within a minute and establish the shadowing agreements between the master DSA and the consumer replicas. You can monitor the controller’s progress by checking its logs.

Customizing the Initialization

You can customize the example Kubernetes projects by adjusting the delivered yaml configuration files and then applying the changes with the "apply" command described in the startup sections.

Please note that the Kubernetes example projects are delivered as reference deployments and a basis for developing custom containerized DirX Directory solutions. Any modifications to the Kubernetes configuration beyond the procedures described in this document are the responsibility of the customer and are outside the scope of DirX Directory support.

Executing Tools and Clients

The dxd container image contains all tools and clients as well as a bash shell. You can use these tools by using kubectl’s exec functionality. For example, you can open an interactive shell into the DirX Directory pod with the command:

kubectl exec -it -n namespace dxd-0 -- bash

In the interactive shell, you can manage the DirX Directory service as a normal Linux installation.

In the scalable example project, the per-server images do not contain a shell. To execute tools interactively, use a debug container with the dxd image:

kubectl debug -it -n namespace dirxdsa-0 --image=dxd -- bash

Deleting a Directory Instance

DirX Directory instances, if running in a separate namespace, can be deleted with the command:

kubectl delete ns namespace

Please note that this command will not clean up the persistent volumes. You should remove them manually.

Setting up Crash Handling

In the standalone example project, the DirX Directory watchdog (dirxdsas) handles all server crashes. However, some Kubernetes environments do not allow ptrace calls by default, so the watchdog procedure is not allowed to generate core dumps.

In the scalable example project, the per-server images do not include dirxdsas. Crash handling must be set up using systemd-coredump.

To activate automatic core dump collection, install the systemd-coredump package and then disable the watchdog’s core dump handling by setting DIRX_WDOG_CRASH_HANDLER=0 in dirxenv.ini. These settings enable systemd to collect the core dumps.

Troubleshooting

All files (including log, audit, ldif, and others) in the DirX Directory container images are written as they are in a normal Linux installation, so files required for troubleshooting are written as files. In the example Kubernetes projects, all paths used to store these files are mapped to persistent volume claims so that files needed for troubleshooting are persisted.

Log File Naming in Containerized Environments

In a containerized environment, multiple container instances may write to the same persistent volume over time. To ensure that log files from different container instances do not overwrite each other, the example Kubernetes projects use special dirxlog.cfg files that include the container ID in the log file name.

In a standard DirX Directory installation, the default dirxlog.cfg uses a simple naming pattern with only a sequence number:

dir:*.0:BINFILE.10.20000:%s/server/log/%sLOG%d
dba:*.0:GOESTO:dir
FATAL:TEXTFILE.10.20000:%s/server/log/%sEXC%d;GOESTO:dir
ERROR:TEXTFILE.10.20000:%s/server/log/%sUSR%d;GOESTO:FATAL

In the Kubernetes example projects, the dirxlog.cfg files use an additional %s format specifier that resolves to the container ID, making each container instance’s log files unique:

dir:*.0:BINFILE.10.20000:%s/server/log/%sLOG_%s_%d
dba:*.0:GOESTO:dir
FATAL:TEXTFILE.10.20000:%s/server/log/%sEXC_%s_%d;GOESTO:dir
ERROR:TEXTFILE.10.20000:%s/server/log/%sUSR_%s_%d;GOESTO:FATAL

The additional %s in the file name pattern inserts the container ID, so log files are named like LOG_abc123_1, LOG_abc123_2, etc. This ensures that when a container is restarted, the new instance writes to files with a different name and does not overwrite or interfere with logs from previous instances.

When deploying DirX Directory in Kubernetes, always use this container-ID-aware dirxlog.cfg pattern in your ConfigMaps to ensure proper log persistence across container restarts.