In this section:
Deploying License Server in Kubernetes with a Helm Chart
Parasoft has published an official Helm chart to Docker Hub for your convenience. Full installation instructions are included in the README there. See https://hub.docker.com/r/parasoft/lss-helm.
Deploying License Server in Kubernetes Manually
Prerequisites
First, create a namespace for License Server to run in. For example:
kubectl create namespace parasoft-lss-namespace
Note: The namespace name "parasoft-lss-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-lss-namespace" in those examples to your namespace name.
Once License Server has been licensed, deleting the namespace will invalidate machine-locked licenses, even if you recreate the same namespace.
Next, you will need a Kubernetes cluster. After starting the cluster, create the service account and permissions required by the License Server pod and related resources.
# Stable access for clients to license server apiVersion: v1 kind: ServiceAccount metadata: name: parasoft-account namespace: parasoft-lss-namespace automountServiceAccountToken: true --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: parasoft-read namespace: parasoft-lss-namespace rules: - apiGroups: - "*" resources: - "*" verbs: - get - read - list --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: parasoft-read-bind namespace: parasoft-lss-namespace roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: parasoft-read subjects: - kind: ServiceAccount name: parasoft-account namespace: parasoft-lss-namespace
Use your yaml file to create the required service account and permissions before creating the License Server environment:
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
Custom Keystore
If you want to set up a custom keystore, you will need to create a configuration map for the .keystore and server.xml files. The command below creates a configuration map called "keystore-cfgmap" with file mappings for the custom .keystore and server.xml files. In this example, each file mapping is given a key: "keystore" for the .keystore file and "server-config" for the server.xml file. While giving each file mapping a key is not necessary, it is useful when you don't want the key to be the file name.
~$ kubectl create configmap keystore-cfgmap --from-file=keystore=/path/to/.keystore --from-file=server-config=/path/to/server.xml configmap/keystore-cfgmap created
Create the License Server Environment
To create the License Server environment, you will first need a yaml file that defines a Secret (optional), a volume, a Pod or StatefulSet, and a Service (optional). The Secret is used to pull the License Server image from the repository. The Pod or StatefulSet creates a pod set up to run a License Server container configured with a volume to persist data and a liveness probe for the container health. The Service makes License Server accessible via external clients by allocating ports in the node and mapping them to ports in the pod. Example yaml files for a Pod or StatefulSet (both called "parasoft-lss.yaml") are shown below. These examples use an NFS volume, but that is not required; use the volume type that fits your needs best.
Note: kind: Deployment
is not supported. Use either kind: Pod
or kind: StatefulSet
, which are supported.
Once License Server has been deployed using Pod or StatefulSet, switching the Kind will invalidate machine-locked licenses.
Example yaml using 'kind: Pod'
apiVersion: v1 kind: Pod metadata: name: lss namespace: parasoft-lss-namespace labels: app: LSS spec: volumes: - name: lss-data nfs: server: NFS_SERVER_HOST path: /lss/ # Uncomment section below if you are setting up a custom keystore; you will also need to uncomment out the associated volumeMounts below # - name: keystore-cfgmap-volume # configMap: # name: keystore-cfgmap securityContext: runAsNonRoot: true containers: - name: lss-server securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] seccompProfile: type: RuntimeDefault image: LSS_DOCKER_IMAGE imagePullPolicy: Always env: - 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 # To inject JVM arguments into the container, specify the "env" property as in the example below, which injects LSS_JAVA_OPTS # - name: LSS_JAVA_OPTS # value: "-Dparasoft.use.license.v2=true" ports: - containerPort: 8080 name: "http-server" - containerPort: 8443 name: "https-server" volumeMounts: - mountPath: "/usr/local/parasoft/license-server/data" name: lss-data # Uncomment section below if you are setting up a custom keystore. Note that updates made to these files will not be reflected inside the container once it's been deployed; you will need to restart the container for it to contain any updates. # - name: keystore-cfgmap-volume # mountPath: "/usr/local/parasoft/license-server/app/tomcat/conf/.keystore" # subPath: keystore # - name: keystore-cfgmap-volume # mountPath: "/usr/local/parasoft/license-server/app/tomcat/conf/server.xml" # subPath: server-config # To prevent liveness probe failures on environments with low or overly taxed RAM/CPU, we recommend increasing the timeout seconds livenessProbe: exec: command: - healthcheck.sh initialDelaySeconds: 120 periodSeconds: 60 timeoutSeconds: 30 failureThreshold: 5 restartPolicy: Always serviceAccountName: parasoft-account automountServiceAccountToken: true imagePullSecrets: - name: YOUR_SECRET --- apiVersion: v1 kind: Service metadata: name: lss namespace: parasoft-lss-namespace spec: type: NodePort selector: app: LSS ports: - port: 8080 name: PORT_NAME_1 nodePort: XXXXX - port: 8443 name: PORT_NAME_2 nodePort: XXXXX # SERVICE CONFIG NOTES: # 'name' can be whatever you want # 'nodePort' must be between 30000-32768 # 'spec.selector' must match 'metadata.labels' in pod config
Example yaml using 'kind: StatefulSet'
apiVersion: apps/v1 kind: StatefulSet metadata: name: lss namespace: parasoft-lss-namespace labels: app: LSS spec: selector: matchLabels: app: LSS serviceName: lss-service replicas: 1 template: metadata: labels: app: LSS spec: volumes: - name: lss-data nfs: server: NFS_SERVER_HOST path: /lss/ # persistentVolumeClaim: # claimName: lss-pvc # Uncomment section below if you are setting up a custom keystore; you will also need to uncomment out the associated volumeMounts below # - name: keystore-cfgmap-volume # configMap: # name: keystore-cfgmap securityContext: runAsNonRoot: true containers: - name: lss-server securityContext: allowPrivilegeEscalation: false capabilities: drop: [ "ALL" ] seccompProfile: type: RuntimeDefault image: LSS_DOCKER_IMAGE imagePullPolicy: Always env: - 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 # To inject JVM arguments into the container, specify the "env" property as in the example below, which injects LSS_JAVA_OPTS # - name: LSS_JAVA_OPTS # value: "-Dparasoft.use.license.v2=true" ports: - containerPort: 8080 name: "http-server" - containerPort: 8443 name: "https-server" volumeMounts: - name: lss-data mountPath: "/usr/local/parasoft/license-server/data" # Uncomment section below if you are setting up a custom keystore. Note that updates made to these files will not be reflected inside the container once it's been deployed; you will need to restart the container for it to contain any updates. # - name: keystore-cfgmap-volume # mountPath: "/usr/local/parasoft/license-server/app/tomcat/conf/.keystore" # subPath: keystore # - name: keystore-cfgmap-volume # mountPath: "/usr/local/parasoft/license-server/app/tomcat/conf/server.xml" # subPath: server-config # To prevent liveness probe failures on environments with low or overly taxed RAM/CPU, we recommend increasing the timeout seconds livenessProbe: exec: command: - healthcheck.sh initialDelaySeconds: 120 periodSeconds: 60 timeoutSeconds: 30 failureThreshold: 5 restartPolicy: Always serviceAccountName: parasoft-account automountServiceAccountToken: true imagePullSecrets: - name: YOUR_SECRET --- apiVersion: v1 kind: Service metadata: name: lss namespace: parasoft-lss-namespace spec: type: NodePort selector: app: LSS ports: - port: 8080 name: PORT_NAME_1 nodePort: XXXXX - port: 8443 name: PORT_NAME_2 nodePort: XXXXX # SERVICE CONFIG NOTES: # 'name' can be whatever you want # 'nodePort' must be between 30000-32768 # 'spec.selector' must match 'metadata.labels' in pod config
Use the yaml file to create the LSS environment:
kubectl create -f parasoft-lss.yaml
To access the UI on a web browser, use the node ports allocated in the service definition as the address (for example, NODE_HOST:NODE_PORT).
If you injected JVM arguments into the container and want to verify their status, run the following command:
kubectl exec <POD_NAME> -c <CONTAINER_NAME> -- printenv
Required Settings for a Stable Machine ID
As you modify either of the parasoft-lss.yaml samples 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
Custom Truststore
Using a custom truststore in Kubernetes environments is similar to using a custom keystore as described above. Adjust the directions for using a custom keystore as appropriate. Note that the truststore location is /usr/local/parasoft/license-server/app/jre/lib/security/cacerts
.
Troubleshooting
Enabling Additional Logging
- Copy log4j.xml from the
<INSTALL_DIR>/app/
directory to<INSTALL_DIR>/data/
. Open the log4j.xml file in
<INSTALL_DIR>/data/
and add the following logger in Loggers element:<Logger name="com.parasoft.xtest" level="ALL"> <AppenderRef ref="CONSOLE" /> </Logger>
Find commented-out section for
LSS_JAVA_OPTS
in the yaml file, uncomment it, then add the following as the value forLSS_JAVA_OPTS
:-Dparasoft.cloudvm.verbose=true -Dparasoft.logging.config.file=/usr/local/parasoft/license-server/data/log4j.xml
- Restart the application.
Additional logging will go to catalina log file (stdout). You can run this command to get the log file to local file system (replace "lss-pod1-nfs" with your pod name and "parasoft-lss-namespace" with the namespace you used):
kubectl logs lss-pod1-nfs -n parasoft-lss-namespace > lss-debug.log
Troubleshooting
machineId is LINUX2-0
This issue can occur when there is an underlying permission issue. To resolve it, try the following options:
- Verify that you have created permissions required by License Server using parasoft-permissions.yaml.
- Note: if you are upgrading, make sure to use the parasoft-permissions.yaml for the version to which you are upgrading.
- Confirm that all Parasoft-required resources are using the same namespace.
machineId changes when pod restarts
This issue can occur if you are using an unsupported Kubernetes object. Make sure you are not using kind: Deployment
. Only kind: Pod
and kind: StatefulSet
are supported.