Direct Kubernetes installation

Obtaining the images

Containerized masking utilizes three integrated containers to deliver, in essence, the same masking experience as provided on a Continuous Compliance Engine deployed on a VM. The containerized form allows for rapid spin up/tear down of ephemeral engines to handle automated workflow deployments. These three containers are delivered in a compressed archive (.tar.gz) for convenience.

Licensed versions of these bundles are available for download from the download.delphix.com site. In the folder for each version are two files. One file is HTML instructions similar to this page that can be downloaded for an offline copy of the installation instructions. The second file is the masking_docker_images.tar.gz bundle with the container images.

As an alternative to loading images from the tarball, users following the Direct Kubernetes Installation path can pull the same images from Amazon ECR (or a mirrored internal registry) by updating image references for delphix-masking-database, delphix-masking-app, and delphix-masking-proxy, and configuring registry access (for example, imagePullSecrets) in the pod spec.

Docker is employed to build the container images, which produces a set of OCI-compliant (Open Container Initiative) images for each container. The intention is to make the containers as vendor independent as possible.

The following examples show one way to configure registry access and image references in a direct Kubernetes deployment. Create an image pull secret (if your cluster does not already have pull access):

Copy
kubectl create secret docker-registry delphix-masking-image-pull-secret \ 
  --namespace delphix-masking \ 
  --docker-server=<registry> \ 
  --docker-username=<username> \ 
  --docker-password=<password>

Use the secret and set image references in the pod template:

Copy
imagePullSecrets: 
  - name: delphix-masking-image-pull-secret 
containers: 
  - name: mds 
    image: <registry>/delphix-masking-database:<version> 
    imagePullPolicy: IfNotPresent 
  - name: app 
    image: <registry>/delphix-masking-app:<version> 
    imagePullPolicy: IfNotPresent 
  - name: proxy 
    image: <registry>/delphix-masking-proxy:<version> 
    imagePullPolicy: IfNotPresent
The mds, app, and proxy containers run with readOnlyRootFilesystem: true. Writable paths required at runtime are supplied by the emptyDir volumes shown below; their contents do not persist across pod restarts.

Sample configuration

The following configuration file shows an example of how Containerized masking might be deployed. Details will vary based on the use case, environment, and product version.

Copy

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv2
spec:
  capacity:
    storage: 500Mi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  storageClassName: nfs-storage2
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    server: {}
    path: {}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc2
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  storageClassName: nfs-storage2
  resources:
    requests:
      storage: 500Mi
---
apiVersion: v1
kind: Service
metadata:
  name: delphix-masking
spec:
  type: NodePort
  selector:
    app: masking
  ports:
    - name: http
      port: 8080
      nodePort: 30080
    - name: https
      port: 8443
      nodePort: 30443
---
apiVersion: v1
kind: Service
metadata:
  name: delphix-masking-debugging
spec:
  type: NodePort
  selector:
    app: masking
  ports:
    - port: 15213
      nodePort: 32213
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: delphix-masking
spec:
  selector:
    matchLabels:
      app: masking
  serviceName: delphix-masking
  template:
    metadata:
      labels:
        app: masking
    spec:
      securityContext:
        runAsUser: 65436
        runAsGroup: 50
        fsGroup: 50
        #
        # This is false so that we can run the initContainer as root, for
        # reasons explained below, but customers should be able to set this to
        # true in production.
        #
        runAsNonRoot: false
      initContainers:
        #
        # Ideally, we would rely on fsGroup to set ownership/permissions in the
        # mounted volumes such that they can be accessed by the containers.
        # However, some volume provisioners don't support fsGroup, including the
        # hostPath provisioner (https://github.com/kubernetes/minikube/issues/1990),
        # which is the default provisioner for Minikube and Microk8s, which we
        # use for development and testing. So that we can continue to use these
        # flavors of k8s, we run an initContainer that we set the ownership and
        # permissions to be the same as if the volume were created with
        # provisioner that honored the fsGroup setting.
        #
        - image: busybox
          name: initialize-volumes
          securityContext:
            runAsUser: 0  # Volumes are owned by root:root
          volumeMounts:
            - name: proxy-var-cache
              mountPath: /var/cache
            - name: proxy-var-run
              mountPath: /var/run
          command:
            - "/bin/sh"
            - "-c"
            - |
            set -e
            # Persistent volume ownership/permissions:
            chmod 2775 /var/delphix/masking && chgrp 50 /var/delphix/masking
            chmod 2775 /var/delphix/postgresql && chgrp 50 /var/delphix/postgresql
            # The proxy container requires these directories to exist before
            # nginx starts. emptyDir volumes shadow the directories that ship
            # in the container image, so anything nginx expects to find
            # pre-existing must be re-created here by the initContainer
            # (which runs as root):
            mkdir -p /var/cache/nginx/client_temp
            mkdir -p /var/cache/nginx/proxy_temp
            mkdir -p /var/cache/nginx/fastcgi_temp
            mkdir -p /var/cache/nginx/uwsgi_temp
            mkdir -p /var/cache/nginx/scgi_temp
            chgrp -R 50 /var/cache/nginx
            chmod -R 2775 /var/cache/nginx
            # Pre-create the nginx PID directory:
            mkdir -p /var/run
            chgrp 50 /var/run
            chmod 2775 /var/run
          volumeMounts:
            - name: masking-persistent-storage
              mountPath: /var/delphix/postgresql
              subPath: postgresql
            - name: masking-persistent-storage
              mountPath: /var/delphix/masking
              subPath: masking
          command:
            - "/bin/sh"
            - "-c"
                    - "chmod 2775 /var/delphix/masking && chgrp 50 /var/delphix/masking && chmod 2775 /var/delphix/postgresql && chgrp 50 /var/delphix/postgresql"
      volumes:
        - name: nfs-pv-storage
              persistentVolumeClaim:
              claimName: nfs-pvc
         #
        # Writable emptyDir volumes for readOnlyRootFilesystem support.
        # These provide writable scratch space at paths that the containers
        # need to write to at runtime (tmp files, PID files, caches, etc.)
        # without allowing writes to the rest of the root filesystem.
        # NOTE: emptyDir volumes are ephemeral — all data is lost on pod
        # restart. This is acceptable for temp files, caches, and PID files.
        #
        - name: mds-tmp
          emptyDir: {}
        - name: mds-var-tmp
          emptyDir: {}
        - name: mds-run-postgresql
          emptyDir: {}
        - name: app-tmp
          emptyDir: {}
        - name: app-var-tmp
          emptyDir: {}
        - name: app-ssl
          emptyDir: {}
        - name: app-dxrt
          emptyDir: {}
        - name: proxy-etc-config
          emptyDir: {}
        - name: proxy-var-cache
          emptyDir: {}
        - name: proxy-tmp
          emptyDir: {}
        - name: proxy-var-run
          emptyDir: {}  
      containers:
        - image: delphix-masking-database:{}
          imagePullPolicy: Never # This image has to be built locally
          name: mds
          securityContext:
            readOnlyRootFilesystem: true
          ports:
            - containerPort: 5432
              name: mds
          volumeMounts:
            - name: masking-persistent-storage
              mountPath: /var/delphix/postgresql
              subPath: postgresql
            - name: mds-tmp
              mountPath: /tmp
            - name: mds-var-tmp
              mountPath: /var/tmp
            - name: mds-run-postgresql
              mountPath: /var/run/postgresql
        - image: delphix-masking-app:{}
          imagePullPolicy: Never # This image has to be built locally
          name: app
          securityContext:
            readOnlyRootFilesystem: true
          ports:
            - containerPort: 8284
              name: http
          volumeMounts:
            - name: masking-persistent-storage
              mountPath: /var/delphix/masking
              subPath: masking
            - name: masking-persistent-storage
              mountPath: /var/delphix/postgresql
              subPath: postgresql
            - name: nfs-pv-storage2
              mountPath: /var/delphix/masking/remote-mounts/nfs_2
            - name: app-tmp
              mountPath: /tmp
            - name: app-var-tmp
              mountPath: /var/tmp
            - name: app-ssl
              mountPath: /var/delphix/ssl
            - name: app-dxrt
              mountPath: /var/delphix/sfdc/dxrt
          env:
            - name: MASK_DEBUG
              value: "true"
        - name: proxy
          image: delphix-masking-proxy:{}
          imagePullPolicy: Never # This image has to be built locally
          securityContext:
            readOnlyRootFilesystem: true
          ports:
          - containerPort: 8080
            name: http
          - containerPort: 8443
            name: https
          volumeMounts:
            - name: proxy-tmp
              mountPath: /tmp
            - name: proxy-etc-config
              mountPath: /etc/config
            - name: proxy-var-cache
              mountPath: /var/cache
            - name: proxy-var-run
              mountPath: /var/run
  volumeClaimTemplates:
    - metadata:
        name: masking-persistent-storage
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 4Gi

Deployment

Load the container images obtained from the download site into some Kubernetes container registry, then deploy the masking Pod using a config file similar to the example provided above.

Copy
kubectl apply -f <path-to-config-file>