To deploy CTP in Kubernetes, follow the process outlined below.
Deploying multiple CTP servers in Kubernetes is not supported with this version. Support is limited to a single instance of CTP running in a Kubernetes cluster.
Prerequisites
First, create a namespace for CTP to run in. For example:
kubectl create namespace parasoft-ctp-namespace
Note: The namespace name "parasoft-ctp-namespace" is used throughout this documentation in command and resource examples. If you use a different name for your namespace, be sure to change any instances of "parasoft-ctp-namespace" in those examples to your namespace name.
Once CTP has been licensed, deleting the namespace will invalidate machine-locked licenses, even if you recreate the same namespace.
Next, Persistent Volumes and Persistent Volume claims for database configuration and exports storage are needed. They should be provisioned with around 1GB (for the database configuration) to 10GB (for exports storage) of space (this can be increased or decreased according to your needs) and ReadWriteOnce access mode is recommended. This space will be used for the workspace of the CTP server.
You must have a well-formatted db_config.xml present in the volume you are mounting. See the db_config.xml below for an example of one that is well-formatted. You can copy the example below into the volume you are mounting if you prefer; whatever configuration you need to do will be done within the application itself. Note that if the URL JDBC string is for MariaDB, MySQL, or Oracle, then your CTP deployment/pod should be configured with the correct JDBC adapter; if the URL JDBC string is for HyperSQL, it should start up regardless of your CTP deployment/pod configuration.
<?xml version="1.0" encoding="UTF-8"?> <configuration> <db_config> <connection> <url>jdbc:hsqldb:file:/usr/local/parasoft/ctp/hsqldb/em;ifexists=true</url> <username>em</username> <password>em</password> </connection> </db_config> </configuration>
The default Persistent Volume Claim names are 'ctp-config-storage' and 'ctp-exports-storage' and these names can be customized by updating the yaml definition of the CTP server. The example shown below is a configuration to set up NFS Persistent Volumes and Persistent Volume Claims. While the example uses NFS, this is not required; use whatever persistent volume type fits your needs.
Warning: For NFS, the exported directory must have the same UID and GID as the Parasoft user that runs the container. For example, execute the command chown 1000:1000 <shared_path>
.
# ==== Persistent Volume to Mount db_config.xml ==== apiVersion: v1 kind: PersistentVolume metadata: name: ctp-config-storage namespace: parasoft-ctp-namespace spec: capacity: storage: 1Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: nfs nfs: path: <path> server: <ip_address> --- # ==== PersistentVolumeClaim for db_config.xml ==== apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ctp-config-pvc namespace: parasoft-ctp-namespace spec: accessModes: - ReadWriteOnce storageClassName: nfs resources: requests: storage: 1Gi volumeName: "ctp-config-storage" --- # ==== Persistent Volume for Export Storage ==== apiVersion: v1 kind: PersistentVolume metadata: name: ctp-exports-storage namespace: parasoft-ctp-namespace spec: capacity: storage: 10Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: nfs nfs: path: <path> server: <ip_address> --- # ==== PersistentVolumeClaim for CTP exports folder ==== apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ctp-exports-pvc namespace: parasoft-ctp-namespace spec: accessModes: - ReadWriteOnce storageClassName: nfs resources: requests: storage: 10Gi volumeName: "ctp-exports-storage"
Use the yaml file to create Persistent Volumes and a Persistent Volume claims:
kubectl create -f ctp-pv.yaml
A Persistent Volume and a Persistent Volume claim for the database are needed. It should be provisioned with around 50GB of space (this can be increased or decreased according to your needs) and ReadWriteOnce access mode is recommended.
The default Persistent Volume claim names in the examples below can be customized by updating the yaml definition of the CTP server. While the examples use NFS, this is not required; use whatever persistent volume type fits your needs. Be aware that for the external databases the Persistent Volume and Persistent Volume claim mounts are for the database JDBC adapters, not the databases themselves.
Different yaml examples are included for the embedded HyperSQL database and each of the supported external databases. Use the one that's right for your environment.
Warning: For NFS, the exported directory must have the same UID and GID as the Parasoft user that runs the container. For example, execute the command chown 1000:1000 <shared_path>
.
HyperSQL (Embedded)
apiVersion: v1 kind: PersistentVolume metadata: name: ctp-hsqldb-storage namespace: parasoft-ctp-namespace spec: capacity: storage: 50Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: nfs nfs: path: <path> server: <ip_address> --- # PersistentVolumeClaim for CTP HyperSQL DB apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ctp-hsqldb-pvc namespace: parasoft-ctp-namespace spec: accessModes: - ReadWriteOnce storageClassName: nfs resources: requests: storage: 50Gi
MariaDB
# ==== Persistent Volume for MariaDB JDBC Adapter apiVersion: v1 kind: PersistentVolume metadata: name: ctp-mariadbadapter-storage namespace: parasoft-ctp-namespace spec: capacity: storage: 1Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: nfs nfs: path: <path> server: <ip_address> --- # ==== PersistentVolumeClaim for MariaDB JDBC Adapter ==== apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ctp-mariadbadapter-pvc namespace: parasoft-ctp-namespace spec: accessModes: - ReadWriteOnce storageClassName: nfs resources: requests: storage: 1Gi volumeName: "ctp-mariadbadapter-storage"
MySQL
# ==== Persistent Volume for MySQL JDBC Adapter apiVersion: v1 kind: PersistentVolume metadata: name: ctp-mysqladapter-storage namespace: parasoft-ctp-namespace spec: capacity: storage: 1Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: nfs nfs: path: <path> server: <ip_address> --- # ==== PersistentVolumeClaim for MySQL JDBC Adapter ==== apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ctp-mysqladapter-pvc namespace: parasoft-ctp-namespace spec: accessModes: - ReadWriteOnce storageClassName: nfs resources: requests: storage: 1Gi volumeName: "ctp-mysqladapter-storage"
Oracle
# ==== Persistent Volume for OracleDB JDBC Adapter apiVersion: v1 kind: PersistentVolume metadata: name: ctp-oracleadapter-storage namespace: parasoft-ctp-namespace spec: capacity: storage: 1Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: nfs nfs: path: <path> server: <ip_address> --- # ==== PersistentVolumeClaim for OracleDB JDBC Adapter ==== apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ctp-oracleadapter-pvc namespace: parasoft-ctp-namespace spec: accessModes: - ReadWriteOnce storageClassName: nfs resources: requests: storage: 1Gi volumeName: "ctp-oracleadapter-storage"
Use the yaml file to create a Persistent Volume and a Persistent Volume claim:
kubectl create -f ctp-db.yaml
You also need to create the service account and required permissions.
apiVersion: v1 kind: ServiceAccount metadata: name: parasoft-account namespace: parasoft-ctp-namespace automountServiceAccountToken: true --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: parasoft-read namespace: parasoft-ctp-namespace rules: - apiGroups: - "*" resources: - "*" verbs: - get - read - list --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: parasoft-read-bind namespace: parasoft-ctp-namespace roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: parasoft-read subjects: - kind: ServiceAccount name: parasoft-account namespace: parasoft-ctp-namespace
Use your yaml file to create the service account and required permissions:
kubectl create -f parasoft-permissions.yaml
You should see something similar to the output below in your console:
serviceaccount/parasoft-account created role.rbac.authorization.k8s.io/parasoft-read created rolebinding.rbac.authorization.k8s.io/parasoft-read-bind created
CTP Deployment
Once the prerequisites have been met, you can deploy CTP in Kubernetes. If custom Persistent Volume Claim names were used in previous steps, make sure to update the appropriate 'volumeMounts:name' and 'claimName' fields to match the custom name. Uncomment the sections for the database you are using.
The server EULA must be accepted by setting the ACCEPT_EULA value to "true" in the -env specifier. Additionally, to opt-in to sending anonymous usage data to Parasoft to help improve the product, change the USAGE_DATA value to "true" in the -env specifier.
Note: kind: Deployment
is not supported. Use either kind: Pod
or kind: StatefulSet
, which are supported.
apiVersion: v1 kind: Pod metadata: name: ctp-pod namespace: parasoft-ctp-namespace labels: app: ctp spec: securityContext: runAsNonRoot: true serviceAccountName: parasoft-account automountServiceAccountToken: true containers: - name: ctp securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] seccompProfile: type: RuntimeDefault image: parasoft/ctp:latest ports: - containerPort: 8080 # Delete database.properties file to prevent overwriting of db_config.xml on pod startup command: [ "/bin/bash", "-c" ] args: - cd ctp/webapps/em/WEB-INF/classes/META-INF/spring/ && rm database.properties && cd /usr/local/parasoft && ./entrypoint.sh volumeMounts: - name: ctp-config-storage mountPath: /usr/local/parasoft/ctp/webapps/em/config/db_config.xml subPath: db_config.xml - name: ctp-exports-storage mountPath: /usr/local/parasoft/exports # - name: ctp-hsqldb-storage # mountPath: /usr/local/parasoft/ctp/hsqldb # === DB JDBC Adapter Volume Mounts === # - name: ctp-mariadbadapter-storage # mountPath: /usr/local/parasoft/ctp/webapps/em/WEB-INF/lib/mariadb-java-client-3.0.8.jar # subPath: mariadb-java-client-3.0.8.jar # - name: ctp-mysqladapter-storage # mountPath: /usr/local/parasoft/ctp/webapps/em/WEB-INF/lib/mysql-connector-java-8.0.30.jar # subPath: mysql-connector-java-8.0.30.jar # - name: ctp-oracleadapter-storage # mountPath: /usr/local/parasoft/ctp/webapps/em/WEB-INF/lib/ojdbc8.jar # subPath: ojdbc8.jar env: # === USE BELOW TO CONFIGURE ENVIRONMENT VARIABLES === # Configures CTP to connect to license server at the specified base URL - name: LICENSE_SERVER_URL value: https://licenseserver:8443 # Configures CTP to use basic authentication when connecting to license server - name: LICENSE_SERVER_AUTH_ENABLED value: "false" # Configures CTP to connect to license server as the specified user # - name: LICENSE_SERVER_USERNAME # value: admin # Configures CTP to connect to license server with the specified password # - name: LICENSE_SERVER_PASSWORD # value: admin # Set to true or false to opt-in or opt-out of sending anonymous usage data to Parasoft - name: USAGE_DATA value: "false" # Accepts the End User License Agreement if set to true - name: ACCEPT_EULA value: "false" - name: CATALINA_OPTS value: "-Dparasoft.cloudvm=true -Dparasoft.cloudvm.config=Kubernetes" - name: PARASOFT_POD_NAME #REQUIRED, DO NOT CHANGE valueFrom: fieldRef: fieldPath: metadata.name - name: PARASOFT_POD_NAMESPACE #REQUIRED, DO NOT CHANGE valueFrom: fieldRef: fieldPath: metadata.namespace # === PROBES === startupProbe: httpGet: path: /em/resources/favicon.ico port: 8080 initialDelaySeconds: 30 periodSeconds: 30 timeoutSeconds: 30 failureThreshold: 3 livenessProbe: httpGet: path: /em/resources/favicon.ico port: 8080 initialDelaySeconds: 30 periodSeconds: 30 timeoutSeconds: 30 readinessProbe: httpGet: path: /em/healthcheck port: 8080 initialDelaySeconds: 30 periodSeconds: 30 timeoutSeconds: 30 volumes: - name: ctp-config-storage persistentVolumeClaim: claimName: ctp-config-pvc - name: ctp-exports-storage persistentVolumeClaim: claimName: ctp-exports-pvc # - name: ctp-hsqldb-storage # persistentVolumeClaim: # claimName: ctp-hsqldb-pvc # === SQL JDBC Adapter Volumes === # - name: ctp-mariadbadapter-storage # persistentVolumeClaim: # claimName: ctp-mariadbadapter-pvc # - name: ctp-mysqladapter-storage # persistentVolumeClaim: # claimName: ctp-mysqladapter-pvc # - name: ctp-oracleadapter-storage # persistentVolumeClaim: # claimName: ctp-oracleadapter-pvc --- # ==== CTP Service Definition ==== apiVersion: v1 kind: Service metadata: name: ctp-service namespace: parasoft-ctp-namespace spec: selector: app: ctp type: NodePort ports: - protocol: TCP port: 8080 targetPort: 8080 nodePort: 30000
Use the yaml file to create service that can be used to access CTP in Kubernetes:
kubectl create -f ctp-pod.yaml
Required Settings for a Stable Machine ID
As you modify the ctp-pod.yaml shown above or craft your own yaml, be aware that the following fields need to be consistent across upgrades and redeployments in order to assure a stable machine ID:
- metadata: name
- metadata: namespace
- containers: name
In addition, the following environment variables are required:
- env: name: PARASOFT_POD_NAME
- env: name: PARASOFT_POD_NAMESPACE