Helm チャートを使用した Kubernetes での DTP のデプロイ

Docker Hub で Parasoft 公式の Helm チャートが提供されています。完全なインストール手順は readme に含まれています。https://hub.docker.com/r/parasoft/dtp-helm を参照してください。

手動による Kubernetes での DTP のデプロイ

要件

作業を開始する前に、DTP 用の外部データベースを用意します。新しい空のデータベースを作成することも、既存のデータベースを使用することもできます。いずれの場合も、データベース ユーザーには、データベースへのアクセスに必要な権限が設定されている必要があります。サポートされるデータベースは、MySQL、Oracle、および PostgreSQL です (サポートされるバージョンについては、「要件とサポート」を参照してください)。Docker Hub で入手可能な MySQL、Oracle、PostgreSQL Docker イメージのいずれかを使用できます。

次に、DTP を実行するための名前空間を作成します。例:

kubectl create namespace parasoft-dtp-namespace

注意: 名前空間名 parasoft-dtp-namespace は、このドキュメント全体のコマンドおよびリソースの例で使用されています。名前空間に別の名前を使用している場合は、parasoft-dtp-namespace をすべて実際の名前空間名に変更してください。

DTP のライセンスが取得されると、たとえ同じ名前空間を再作成した場合でも、名前空間を削除するとマシンロック ライセンスが無効になります。

次に、Kubernetes クラスターが必要です。クラスターを起動したら、DTP の Pod と関連リソースが必要とするサービス アカウントと権限を作成します。この目的で使用できる yaml ファイルの例を以下に示します。

parasoft-permissions.yaml
# Stable access for clients to license server
apiVersion: v1
kind: ServiceAccount
metadata:
  name: parasoft-account
  namespace: parasoft-dtp-namespace
automountServiceAccountToken: true
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: parasoft-read
  namespace: parasoft-dtp-namespace
rules:
- apiGroups:
  - ""
  resources:
  - "namespaces"
  - "pods"
  verbs:
  - get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: parasoft-read-bind
  namespace: parasoft-dtp-namespace
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: parasoft-read
subjects:
- kind: ServiceAccount
  name: parasoft-account
  namespace: parasoft-dtp-namespace

DTP 環境を構築する前に、yaml ファイルを使用して、必要とされるサービス アカウントと権限を作成します。

kubectl create -f parasoft-permissions.yaml

コンソールに以下のような出力が表示されるはずです。

serviceaccount/parasoft-account created role.rbac.authorization.k8s.io/parasoft-read created rolebinding.rbac.authorization.k8s.io/parasoft-read-bind created

カスタム キーストア

カスタム キーストアを設定する場合、.keystore および server.xml ファイルの構成マップを作成する必要があります。以下のコマンドは、カスタムの .keystore および server.xml ファイルのファイル マッピングを含む keystore-cfgmap という構成マップを作成します。この例では、各ファイル マッピングにキーが与えられています。.keystore ファイルに keystore、server.xml ファイルに server-config です。各ファイル マッピングにキーを指定する必要はありませんが、キーをファイル名にしたくない場合に便利です。 

~$ kubectl create configmap keystore-cfgmap --from-file=keystore=/path/to/.keystore --from-file=server-config=/path/to/server.xml configmap/keystore-cfgmap created

DTP のセットアップ

DTP をセットアップするには、yaml ファイルを作成します。このファイルは Secret (オプション)、ボリューム、Pod または StatefulSet、内部アクセス サービス、および外部アクセス サービス (オプション) を定義します。Secret は、リポジトリから DTP イメージをプルするために使用されます。Pod または StatefulSet は、DTP、Data Collector、および Extension Designer を個別のコンテナで実行するように設定されたポッドを作成します。各コンテナーは、データを永続化するためのボリュームと liveness プローブで構成されます。liveness プローブは、Docker のヘルスチェックに相当するものです。内部アクセス サービスは、DTP ポッドを他のポッドに公開し、明示的な IP アドレスの代わりにサービス名を介して通信できるようにします。外部アクセス サービスは、ノードにポートを割り当て、それらをポッドのポートにマッピングすることで、外部クライアント経由で DTP、Data Collector、および Extension Designer にアクセスできるようにします。Pod または StatefulSet の yaml ファイルの例 (どちらも parasoft-dtp.yaml) を以下に示します。この例では NFS ボリュームを使用していますが、これは必須ではありません。ニーズに合ったボリュームタイプを使用してください。

注意: kind: Deployment はサポートされません。kind: Pod または kind: StatefulSet のいずれかを使用してください。これらはサポートされています。

Pod または StatefulSet を使用して DTP をデプロイした後、Kind を切り替えると、マシンロック ライセンスが無効になります。

kind: Pod を使用した yaml の例

parasoft-dtp.yaml
apiVersion: v1
kind: Pod
metadata:
  name: dtp
  namespace: parasoft-dtp-namespace
  labels:
    app: DTP
spec:
  volumes:
    - name: dtp-data
      nfs:
        server: NFS_SERVER_HOST
        path: /dtp/
# 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: dtp-server
      securityContext:
        allowPrivilegeEscalation: false
        capabilities:
          drop: ["ALL"]
        seccompProfile:
          type: RuntimeDefault    
      image: DTP_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 configure DTP to connect to your database on startup, please provide your database type, user, user password, and connection URL to the container environment by injecting the values as the DB_TYPE, DB_USER, DB_PASSWORD, and DB_URL environment variables.
# To prevent exposing sensitive data, please create a user password secret to use for the DB_PASSWORD environment variable.
# Note that the database type must be one of the following: mysql | oracle | postgresql
# Note that the environment variable values will override the equivalent persisted values in the PSTRootConfig.xml each time the container or pod is restarted.
# The following are example settings for a MySQL container called "mysql-container", a database called "DTP", a user called "dtp_user", and a user password secret.
#        - name: DB_TYPE
#          value: "mysql"
#        - name: DB_USER
#          value: "dtp_user"
#        - name: DB_PASSWORD
#          valueFrom: 
#            secretKeyRef: 
#              name: YOUR_DB_USER_PASSWORD_SECRET
#              key: YOUR_DB_USER_PASSWORD_SECRET_KEY
#        - name: DB_URL
#          value: "jdbc:mysql://mysql-container:3306/DTP"
# To configure DTP to automatically download the driver for your database on startup, please provide the JDBC driver URL to the container environment by injecting the value as the JDBC_DRIVER_URL environment variable.
# The following is an example URL to download the JDBC driver for MySQL 8.0.30.
#        - name: JDBC_DRIVER_URL
#          value: "https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.30/mysql-connector-java-8.0.30.jar"
# To configure DTP to use JVM arguments, please provide the arguments to the container environment by injecting the value as the JAVA_CONFIG_ARGS environment variable.
# The following is an example JVM argument "com.parasoft.sdm.storage.managers.admin.enable.delete.project.data=true"
#        - name: JAVA_CONFIG_ARGS
#          value: "-Dcom.parasoft.sdm.storage.managers.admin.enable.delete.project.data=true"
      args: ["--run", "dtp"]
      ports:
        - name: "http-server"
          containerPort: 8080
        - name: "https-server"
          containerPort: 8443
      volumeMounts:
        - mountPath: "/usr/local/parasoft/data"
          name: dtp-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/dtp/tomcat/conf/.keystore"
#          subPath: keystore
#        - name: keystore-cfgmap-volume
#          mountPath: "/usr/local/parasoft/dtp/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
          - --verify
          - dtp
        initialDelaySeconds: 120
        periodSeconds: 60
        timeoutSeconds: 30
        failureThreshold: 5
    - name: data-collector
      securityContext:
        allowPrivilegeEscalation: false
        capabilities:
          drop: ["ALL"]
        seccompProfile:
          type: RuntimeDefault    
      image: DTP_DOCKER_IMAGE
      imagePullPolicy: Always
# To inject JVM arguments into the container, specify the "env" property as in the example below, which injects JAVA_DC_CONFIG_ARGS
#      env:
#        - name: JAVA_DC_CONFIG_ARGS
#          value: "-Dcom.parasoft.sdm.dc.traffic.max.length=1000000"
      args: ["--run", "datacollector", "--no-copy-data"]
      ports:
        - containerPort: 8082
      volumeMounts:
        - mountPath: "/usr/local/parasoft/data"
          name: dtp-data
# 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
          - --verify
          - datacollector
        initialDelaySeconds: 120
        periodSeconds: 60
        timeoutSeconds: 30
        failureThreshold: 5
# Uncomment section below if using DTP with Extension Designer
#    - name: extension-designer
#      securityContext:
#        allowPrivilegeEscalation: false
#        capabilities:
#          drop: ["ALL"]
#        seccompProfile:
#          type: RuntimeDefault
#      image: DTP_DOCKER_IMAGE
#      imagePullPolicy: Always
# To inject JVM arguments into the container, specify the "env" property as in the example below, which injects JAVA_CONFIG_ARGS
#      args: ["--run", "dtpservices"]
#      ports:
#        - containerPort: 8314
#      volumeMounts:
#        - mountPath: "/usr/local/parasoft/data"
#          name: dtp-data
# 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
#          - --verify
#          - dtpservices
#        initialDelaySeconds: 120
#        periodSeconds: 60
#        timeoutSeconds: 30
#        failureThreshold: 5
# Uncomment section below if using Extension Designer with an external MongoDB
#      env:
#       - name: DEP_USE_REMOTE_DB
#         value: "true"
#       - name: DEP_DB_HOSTNAME
#         value: "mongodb-hostname" # Put your mongodb hostname here
#       - name: DEP_DB_PORT
#         value: "27017"
  restartPolicy: Always
  serviceAccountName: parasoft-account
  automountServiceAccountToken: true
  imagePullSecrets:
    - name: YOUR_SECRET
---
apiVersion: v1
kind: Service
metadata:
  name: dtp
  namespace: parasoft-dtp-namespace
spec:
  selector:
    app: DTP
  ports:
    - name: "http-server"
      protocol: TCP
      port: 8080
      targetPort: 8080
    - name: "data-collector"
      protocol: TCP
      port: 8082
      targetPort: 8082
    - name: "https-server"
      protocol: TCP
      port: 8443
      targetPort: 8443
# Uncomment section below if using DTP with Extension Designer
#    - name: "extension-designer"
#      protocol: TCP
#      port: 8314
#      targetPort: 8314
---
apiVersion: v1
kind: Service
metadata:
  name: dtp-external
  namespace: parasoft-dtp-namespace
spec:
  type: NodePort
  selector:
    app: DTP
  ports:
    - port: 8080
      name: HTTP_PORT_NAME
      nodePort: XXXXX
    - port: 8082
      name: DC_PORT_NAME
      nodePort: XXXXX
    - port: 8443
      name: HTTPS_PORT_NAME
      nodePort: XXXXX
# Uncomment section below if using DTP with Extension Designer
#    - port: 8314
#      name: EXTENSION_DESIGNER_PORT_NAME
#      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

kind: StatefulSet を使用した yaml の例

parasoft-dtp.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: dtp
  namespace: parasoft-dtp-namespace
  labels:
    app: DTP
spec:
  selector:
    matchLabels:
      app: DTP
  serviceName: dtp-service
  replicas: 1
  template:
    metadata:
      labels:
        app: DTP
    spec:
      volumes:
      - name: dtp-data
        nfs:
          server: NFS_SERVER_HOST
          path: /dtp/
#        persistentVolumeClaim:
#          claimName: dtp-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: dtp-server
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
          seccompProfile:
            type: RuntimeDefault   
        image: DTP_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 configure DTP to connect to your database on startup, please provide your database type, user, user password, and connection URL to the container environment by injecting the values as the DB_TYPE, DB_USER, DB_PASSWORD, and DB_URL environment variables.
# To prevent exposing sensitive data, please create a user password secret to use for the DB_PASSWORD environment variable.
# Note that the database type must be one of the following: mysql | oracle | postgresql
# Note that the environment variable values will override the equivalent persisted values in the PSTRootConfig.xml each time the container or pod is restarted.
# The following are example settings for a MySQL container called "mysql-container", a database called "DTP", a user called "dtp_user", and a user password secret.
#        - name: DB_TYPE
#          value: "mysql"
#        - name: DB_USER
#          value: "dtp_user"
#        - name: DB_PASSWORD
#          valueFrom:
#            secretKeyRef:
#              name: YOUR_DB_USER_PASSWORD_SECRET
#              key: YOUR_DB_USER_PASSWORD_SECRET_KEY
#        - name: DB_URL
#          value: "jdbc:mysql://mysql-container:3306/DTP"
# To configure DTP to automatically download the driver for your database on startup, please provide the JDBC driver URL to the container environment by injecting the value as the JDBC_DRIVER_URL environment variable.
# The following is an example URL to download the JDBC driver for MySQL 8.0.30.
#        - name: JDBC_DRIVER_URL
#          value: "https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.30/mysql-connector-java-8.0.30.jar"
# To configure DTP to use JVM arguments, please provide the arguments to the container environment by injecting the value as the JAVA_CONFIG_ARGS environment variable.
# The following is an example JVM argument "com.parasoft.sdm.storage.managers.admin.enable.delete.project.data=true"
#        - name: JAVA_CONFIG_ARGS
#          value: "-Dcom.parasoft.sdm.storage.managers.admin.enable.delete.project.data=true"
        args: ["--run", "dtp"]
        ports:
        - name: "http-server"
          containerPort: 8080
        - name: "https-server"
          containerPort: 8443
        volumeMounts:
        - mountPath: "/usr/local/parasoft/data"
          name: dtp-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/dtp/tomcat/conf/.keystore"
#          subPath: keystore
#        - name: keystore-cfgmap-volume
#          mountPath: "/usr/local/parasoft/dtp/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
            - --verify
            - dtp
          initialDelaySeconds: 120
          periodSeconds: 60
          timeoutSeconds: 30
          failureThreshold: 5
      - name: data-collector
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
          seccompProfile:
            type: RuntimeDefault   
        image: DTP_DOCKER_IMAGE
        imagePullPolicy: Always
# To inject JVM arguments into the container, specify the "env" property as in the example below, which injects JAVA_DC_CONFIG_ARGS
#        env:
#        - name: JAVA_DC_CONFIG_ARGS
#          value: "-Dcom.parasoft.sdm.dc.traffic.max.length=1000000"
        args: ["--run", "datacollector", "--no-copy-data"]
        ports:
        - containerPort: 8082
        volumeMounts:
        - mountPath: "/usr/local/parasoft/data"
          name: dtp-data
# 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
            - --verify
            - datacollector
          initialDelaySeconds: 120
          periodSeconds: 60
          timeoutSeconds: 30
          failureThreshold: 5
# Uncomment section below if using DTP with Extension Designer
#      - name: extension-designer
#        securityContext:
#          allowPrivilegeEscalation: false
#          capabilities:
#            drop: ["ALL"]
#          seccompProfile:
#            type: RuntimeDefault
#        image: DTP_DOCKER_IMAGE
#        imagePullPolicy: Always
# To inject JVM arguments into the container, specify the "env" property as in the example below, which injects JAVA_CONFIG_ARGS
#        args: ["--run", "dtpservices"]
#        ports:
#        - containerPort: 8314
#        volumeMounts:
#        - mountPath: "/usr/local/parasoft/data"
#          name: dtp-data
# 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
#            - --verify
#            - dtpservices
#          initialDelaySeconds: 120
#          periodSeconds: 60
#          timeoutSeconds: 30
#          failureThreshold: 5
# Uncomment section below if using Extension Designer with an external MongoDB
#        env:
#        - name: DEP_USE_REMOTE_DB
#          value: "true"
#        - name: DEP_DB_HOSTNAME
#          value: "mongodb-hostname" # Put your mongodb hostname here
#        - name: DEP_DB_PORT
#          value: "27017"
      restartPolicy: Always
      serviceAccountName: parasoft-account
      automountServiceAccountToken: true
      imagePullSecrets:
      - name: YOUR_SECRET
---
apiVersion: v1
kind: Service
metadata:
  name: dtp
  namespace: parasoft-dtp-namespace
spec:
  selector:
    app: DTP
  ports:
    - name: "http-server"
      protocol: TCP
      port: 8080
      targetPort: 8080
    - name: "data-collector"
      protocol: TCP
      port: 8082
      targetPort: 8082
    - name: "https-server"
      protocol: TCP
      port: 8443
      targetPort: 8443
# Uncomment section below if using DTP with Extension Designer
#    - name: "extension-designer"
#      protocol: TCP
#      port: 8314
#      targetPort: 8314
---
apiVersion: v1
kind: Service
metadata:
  name: dtp-external
  namespace: parasoft-dtp-namespace
spec:
  type: NodePort
  selector:
    app: DTP
  ports:
    - port: 8080
      name: HTTP_PORT_NAME
      nodePort: XXXXX
    - port: 8082
      name: DC_PORT_NAME
      nodePort: XXXXX
    - port: 8443
      name: HTTPS_PORT_NAME
      nodePort: XXXXX
# Uncomment section below if using DTP with Extension Designer
#    - port: 8314
#      name: EXTENSION_DESIGNER_PORT_NAME
#      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

安定したマシン ID のために必要な設定

上記の parasoft-dtp.yaml サンプルを変更したり、独自の yaml を作成したりする場合は、安定したマシン ID を確保するために、アップグレードや再デプロイ時に以下のフィールドが一貫している必要があることに注意してください。

  • metadata: name
  • metadata: namespace
  • containers: name

さらに、以下の環境変数が必要です。

  • env: name: PARASOFT_POD_NAME
  • env: name: PARASOFT_POD_NAMESPACE

DTP 環境の作成

ハードウェアの最小要件が満たされている場合、DTP の起動には最大 2 分かかります。起動中は、ブラウザーから DTP にアクセスできません。

クラスター上のボリューム マウントの場所を準備します。デフォルトでは、イメージは UID 1000 および GID 1000 を持つ parasoft ユーザーとして実行されます。このユーザーが読み取り/書き込みできるようにボリュームを準備します。

次に、前に作成した DTP セットアップ yaml ファイルで定義された DTP 環境を作成します。

kubectl create -f parasoft-dtp.yaml

これで永続ボリュームの内容が初期化されます。

JVM 引数やデータベース構成設定などの環境変数を挿入した場合は、次のコマンドを使用してそのステータスを確認できます。

kubectl exec <POD_NAME> -c <CONTAINER_NAME> -- printenv

Extension Designer で DTP を使用している場合は、期待されるホスト名と、DTP および Extension Designer にアクセスするための公開ポートを反映するために、Extension Designer のリバース プロキシ設定を更新する必要があります。

データベース JDBC URL の設定

データベース URL の構造は、外部データベースへのアクセス方法によって異なります。例:

  • データベースがリモート サーバーでホストされている場合。この場合 (MySQL データベースを想定)、URL は次のようになります: jdbc:mysql://<DB_HOST>:3306/DTP
  • データベースは K8 クラスター内で実行されており、構成されたサービス名または IP アドレスでアクセスできる場合。この場合 (MySQL データベースを想定)、URL は次のようになります: jdbc:mysql://<CONFIGURED-SERVICE-NAME>.<NAMESPACE>:3306/DTP

カスタム トラストストア

Kubernetes 環境でのカスタム トラストストアの使用は、上記のカスタム キーストアの使用と同様です。カスタム キーストアの使用手順を適宜読み換えてください。なお、トラスト ストアの場所は /usr/local/parasoft/dtp/jre/lib/security/cacerts です。

トラブルシューティング

追加ログへのアクセス

DTP はデバッグログを自動的にキャプチャします。<DTP_DATA_DIR>/logs/ ディレクトリにある tests.log ファイルで確認できます。

machineId が LINUX2-0

この問題は、根本的な権限に問題がある場合に発生する場合があります。この問題を解決するには、次のオプションを試してください。

  1. <DTP_DATA_DIR>/logs/ ディレクトリにある testing.log ファイルで、次のエラーを検索します: "Kubernetes API call fails with status=403 error"
  2. parasoft-permissions.yaml を使用して DTP に必要な権限が作成されていることを確認します。
    • 注意: アップグレードする場合は、必ずアップグレード先のバージョンの parasoft-permissions.yaml を使用してください。
  3. Parasoft が必要とするすべてのリソースが同じ名前空間を使用していることを確認します。

ポッドの再起動時に machineId が変更される

この問題は、サポートされていない Kubernetes オブジェクトを使用している場合に発生することがあります。 kind: Deployment を使用していないことを確認してください。kind: Pod および kind: StatefulSet のみがサポートされます。 

  • No labels