From 0442c878aefd51d844f454a1414b838b623aa37b Mon Sep 17 00:00:00 2001 From: Rivindu Date: Thu, 9 Oct 2025 00:26:57 +0530 Subject: [PATCH] Add kubernetes artifacts --- resources/kubernetes/README.md | 145 ++++++ resources/kubernetes/dashboard-dockerfile | 16 + resources/kubernetes/opensearch-secret.yaml | 10 + resources/kubernetes/translator-dockerfile | 12 + .../kubernetes/wso2-swift-translator-k8s.yaml | 475 ++++++++++++++++++ 5 files changed, 658 insertions(+) create mode 100644 resources/kubernetes/README.md create mode 100644 resources/kubernetes/dashboard-dockerfile create mode 100644 resources/kubernetes/opensearch-secret.yaml create mode 100644 resources/kubernetes/translator-dockerfile create mode 100644 resources/kubernetes/wso2-swift-translator-k8s.yaml diff --git a/resources/kubernetes/README.md b/resources/kubernetes/README.md new file mode 100644 index 0000000..5ed7b07 --- /dev/null +++ b/resources/kubernetes/README.md @@ -0,0 +1,145 @@ +# WSO2 SWIFT MT/MX Translator and Dashboard: Kubernetes Deployment Guide + +This guide details the steps to deploy an all-in-one setup for the **WSO2 SWIFT MT/MX Translator and Dashboard** using Kubernetes. + +--- + +## Prerequisites + +Ensure you have the following installed and configured before proceeding: + +* **Kubernetes** cluster access and `kubectl` configured. +* **Docker** installed for building container images. +* **Docker Hub Account** (or any other container registry) to push the custom images. + +--- + +## Deployment Overview + +This setup involves deploying **four** main Kubernetes components: + +1. **Translator Deployment (Single Pod with up to Three Containers):** + * `translator` container (main application) + * `fluent-bit` container (for log forwarding) + * `extensions` container (optional, only required if extensions are enabled) +2. **Opensearch Deployments (Two):** The data store for the translator and dashboard. +3. **Opensearch Dashboard Deployment:** The visualization layer, leveraging the custom SWIFT Dashboard plugin. + +--- + +## Step-by-Step Deployment Instructions + +### 1. Obtain Translator and Dashboard Artifacts + +1. **Download Translator:** Get the latest `swift-mt-mx-translator.zip` from the [WSO2 reference-implementation-cbpr releases page](https://github.com/wso2/reference-implementation-cbpr/releases). +2. **Download Dashboard Plugin:** Get the latest `swift-dashboard.zip` from the same [releases page](https://github.com/wso2/reference-implementation-cbpr/releases). + +--- + +### 2. Build and Push the Translator Docker Image + +1. **Prepare Directory:** +- Create a directory named `translator-deployment`. + ```bash + mkdir translator-deployment + cd translator-deployment + ``` +- Extract the downloaded translator package (e.g., `swift-mt-mx-translator-1.0.0.zip`) and copy the **`swiftMtMxTranslator.jar`**. +- Copy **`extensions.jar`** (if applicable) +- Rename and copy the **`translator-dockerfile`** to **`Dockerfile`** + +2. **Build Image:** + + Build the Docker image. + ```bash + docker build -t swift-translator:latest . + ``` +3. **Tag & Push Image:** + + Tag the image with your registry name. **Replace ``** with your actual username or registry path. + ```bash + docker tag swift-translator:latest /swift-translator:latest + ``` + Push the image to your container registry. + ```bash + docker push /swift-translator:latest + ``` + +--- + +### 3. Build and Push the Dashboard Docker Image + +1. **Prepare Directory:** +- Create a directory named `dashboard-deployment`. + ```bash + mkdir translator-deployment + cd translator-deployment + ``` +- Copy the downloaded **`swift-dashboard.zip`** +- Rename and copy the **`dashboard-dockerfile`** to **`Dockerfile`** + +2. **Verify Dockerfile:** + + Before building, open the `Dockerfile` and ensure the version name of the Dashboard ZIP file (`swift-dashboard-1.0.0.zip`) matches the file you copied into the directory.** + +3. **Build Image:** Build the Docker image. + ```bash + docker build -t swift-dashboard:latest . + ``` +4. **Tag & Push Image:** + + Tag the image with your registry name. **Replace ``** with your actual username or registry path. + ```bash + docker tag swift-dashboard:latest /swift-dashboard:latest + ``` + Push the image to your container registry. + ```bash + docker push /swift-dashboard:latest + ``` + *(**Note:** Ensure your Kubernetes manifest (`wso2-swift-translator-k8s.yaml`) uses the correct registry paths for both images.)* + +--- + +### 4. Configure Kubernetes Environment (VM Max Map Count) + +Before deployment, if you are running Kubernetes on a local VM (like Minikube or Docker Desktop), you must increase the maximum memory map count (`vm.max_map_count`) for **Opensearch** to function correctly. + +1. **Access VM Shell:** Enter the shell environment of your Kubernetes VM. + ```bash + rdctl shell # Example for Rancher Desktop + # Use 'minikube ssh' for Minikube, or relevant command for your environment + ``` +2. **Increase Max Map Count:** Set the `vm.max_map_count` kernel parameter. + ```bash + sudo sysctl -w vm.max_map_count=262144 + ``` + +--- + +### 5. Deploy to Kubernetes + +1. Apply secrets & config maps + + Modify opensearch-secret.yaml with your default credentials and apply configurations. + ```bash + kubectl apply -f opensearch-secret.yaml + kubectl create configmap translator-config --from-file=Config.toml + ``` +2. Apply the combined Kubernetes YAML file to deploy all components (Translator, Opensearch, and Dashboard). + ```bash + kubectl apply -f wso2-swift-translator-k8s.yaml + ``` + +--- + +### 6. Monitor and Verify Deployment + +1. **Check Deployments:** Verify that all deployments are up and running. + ```bash + kubectl get deployments + ``` +2. **Check Pod Status:** Monitor the status of the created Pods. + ```bash + kubectl get pods + ``` + *Verify that all pods, including the Opensearch and Dashboard ones, are in the **Running** state.* diff --git a/resources/kubernetes/dashboard-dockerfile b/resources/kubernetes/dashboard-dockerfile new file mode 100644 index 0000000..5341538 --- /dev/null +++ b/resources/kubernetes/dashboard-dockerfile @@ -0,0 +1,16 @@ +# Start from the base image used in your Kubernetes YAML +FROM opensearchproject/opensearch-dashboards:2.19.0 + +# Define the installation directory +WORKDIR /usr/share/opensearch-dashboards + +# Copy the plugin ZIP into the container +COPY swift-dashboard-1.0.0.zip ./swift-dashboard.zip + +# Install the plugin and remove the ZIP file +# Note: The 'opensearch-dashboards-plugin install' command should be used. +# The trailing '&' is often used to ensure the command runs in the background. +RUN bin/opensearch-dashboards-plugin install file:///usr/share/opensearch-dashboards/swift-dashboard.zip \ + && rm swift-dashboard.zip + +# The ENTRYPOINT and CMD are inherited from the base image diff --git a/resources/kubernetes/opensearch-secret.yaml b/resources/kubernetes/opensearch-secret.yaml new file mode 100644 index 0000000..956ed64 --- /dev/null +++ b/resources/kubernetes/opensearch-secret.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: opensearch-auth +type: Opaque +data: + # Base64 encoded: echo -n 'admin' | base64 + username: YWRtaW4= + # Base64 encoded: echo -n 'Pass@123@pass' | base64 + password: UGFzc0AxMjNAcGFzcw== diff --git a/resources/kubernetes/translator-dockerfile b/resources/kubernetes/translator-dockerfile new file mode 100644 index 0000000..6106830 --- /dev/null +++ b/resources/kubernetes/translator-dockerfile @@ -0,0 +1,12 @@ +# Use a lightweight OpenJDK runtime image +FROM eclipse-temurin:17-jre-focal + +# Set the working directory +WORKDIR /app + +# Copy the two JAR files into the container +COPY swiftMtMxTranslator.jar /app/swiftMtMxTranslator.jar +COPY extensions.jar /app/extensions.jar + +# Define an entrypoint, though the Deployment will override the command +ENTRYPOINT ["java", "-jar"] diff --git a/resources/kubernetes/wso2-swift-translator-k8s.yaml b/resources/kubernetes/wso2-swift-translator-k8s.yaml new file mode 100644 index 0000000..85dfe16 --- /dev/null +++ b/resources/kubernetes/wso2-swift-translator-k8s.yaml @@ -0,0 +1,475 @@ +# -------------------------------------------------------------------------- +# A. Fluent Bit ConfigMap +# -------------------------------------------------------------------------- +apiVersion: v1 +kind: ConfigMap +metadata: + name: fluentbit-translator-config + labels: + app: swift-translator +data: + fluent-bit.conf: | + [SERVICE] + Flush 5 # Flush every 5 seconds + Log_Level info + Parsers_File /fluent-bit/config/parsers.conf + Daemon off # Essential for sidecar operation + + # Input 1: Read logs from the main translator app + [INPUT] + Name tail + Tag logs + Path /var/log/app/ballerina-logs/ballerina*.log + Parser ballerina_json_parser + Refresh_Interval 1 + exit_on_eof off + Mem_Buf_Limit 5MB + + [OUTPUT] + Name opensearch + Match logs + Host opensearch-svc + Port 9200 + HTTP_User admin + HTTP_Passwd ${OS_USER} + Index ${OS_PASS} + Suppress_Type_Name On + Logstash_Format Off + Time_Key time + Generate_ID On + tls On + tls.verify Off + + [INPUT] + Name tail + Tag mtmx + Path /var/log/app/dashboard-logs/dashboard*.log + Parser json + Refresh_Interval 1 + exit_on_eof off + + [OUTPUT] + Name opensearch + Match mtmx + Host opensearch-svc + Port 9200 + HTTP_User ${OS_USER} + HTTP_Passwd ${OS_PASS} + Index translated_log + Suppress_Type_Name On + Logstash_Format Off + Time_Key @timestamp + Generate_ID On + tls On + tls.verify Off + parsers.conf: | + [PARSER] + Name docker + Format json + Time_Key time + Time_Format %Y-%m-%dT%H:%M:%S %z + + [PARSER] + Name ballerina_json_parser + Format json + Time_Key time # The field in your JSON containing the timestamp + Time_Format %Y-%m-%dT%H:%M:%S.%L%z # The format of that timestamp string + Time_Keep On # Keep the original 'time' field + + [PARSER] + Name json + Format json + Time_Key time + Time_Format %d/%b/%Y:%H:%M:%S %z +--- +# -------------------------------------------------------------------------- +# B. Translator Deployment (Three-Container Pod) +# -------------------------------------------------------------------------- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: swift-translator-deployment + labels: + app: swift-translator +spec: + replicas: 1 + selector: + matchLabels: + app: swift-translator + template: + metadata: + labels: + app: swift-translator + spec: + securityContext: + runAsUser: 0 + fsGroup: 1000 + volumes: + # 1. shared-logs: A temporary volume for log files + - name: shared-logs + emptyDir: {} + + # 2. fluentbit-config-volume: To mount the ConfigMap file + - name: fluentbit-config-volume + configMap: + name: fluentbit-translator-config + items: + - key: fluent-bit.conf + path: fluent-bit.conf + - key: parsers.conf + path: parsers.conf + # 3. app-config-volume: To mount the application Config.toml file + - name: app-config-volume + configMap: + name: translator-config + items: + - key: Config.toml + path: Config.toml + + initContainers: + - name: fix-log-permissions + image: busybox:1.36 + command: ["sh", "-c", "chmod -R 777 /var/log/app; chmod -R 777 /var/log/ext"] + volumeMounts: + - name: shared-logs + mountPath: /var/log/app + - name: shared-logs + mountPath: /var/log/ext + + containers: + # --- 1. TRANSLATOR CONTAINER --- + - name: translator-main + image: /swift-translator:latest # Update registry name + workingDir: /app + command: ["/bin/sh", "-c"] + args: + - > + java + -Dlog.path=/var/log/app/translator.log + -Dconfig.file=/app/Config.toml + -jar /app/swiftMtMxTranslator.jar + ports: + - containerPort: 8080 + + volumeMounts: + - name: shared-logs + mountPath: /var/log/app # Translator writes logs here + + - name: app-config-volume + mountPath: /app/Config.toml + subPath: Config.toml + + # 🟢 LIVENESS PROBE (on /healthz, port 8080) + livenessProbe: + httpGet: + path: /healthz + port: 8080 + initialDelaySeconds: 15 + periodSeconds: 10 + failureThreshold: 3 + + # 🟡 READINESS PROBE (on /healthz, port 8080) + readinessProbe: + httpGet: + path: /healthz + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 1 + + # --- 2. EXTENSIONS (Sidecar 1) CONTAINER --- + - name: translator-extensions + image: /swift-translator:latest # Update registry name + workingDir: /app + command: ["java", "-Dlog.path=/var/log/ext/extensions.log", "-jar", "extensions.jar"] + ports: + - containerPort: 8081 + + volumeMounts: + - name: shared-logs + mountPath: /var/log/ext # Extensions app writes logs here + + # --- 3. FLUENT BIT (Sidecar 2) CONTAINER --- + - name: fluentbit-sidecar + image: fluent/fluent-bit:latest + command: ["/fluent-bit/bin/fluent-bit", "-c", "/fluent-bit/config/fluent-bit.conf"] + env: + # Inject the OpenSearch username from the Secret + - name: OS_USER + valueFrom: + secretKeyRef: + name: opensearch-auth + key: username + # Inject the OpenSearch password from the Secret + - name: OS_PASS + valueFrom: + secretKeyRef: + name: opensearch-auth + key: password + # Fluent Bit reads the shared log files and sends them to OpenSearch + volumeMounts: + # Read the logs from the shared volume + - name: shared-logs + mountPath: /var/log/app + # Provide the Fluent Bit configuration + - name: fluentbit-config-volume + mountPath: /fluent-bit/config + +--- + +# -------------------------------------------------------------------------- +# C. PVCs: Storage for the two data nodes +# -------------------------------------------------------------------------- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: opensearch-data1-claim + labels: + app: opensearch-node +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: opensearch-data2-claim + labels: + app: opensearch-node +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- + +# -------------------------------------------------------------------------- +# D. Data Node 1 Deployment (Manager Node) +# -------------------------------------------------------------------------- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: opensearch-node1-deployment + labels: + app: opensearch-node +spec: + replicas: 1 + selector: + matchLabels: + app: opensearch-node + node: opensearch-node1 + template: + metadata: + labels: + app: opensearch-node + node: opensearch-node1 + spec: + volumes: + - name: opensearch-data1 + persistentVolumeClaim: + claimName: opensearch-data1-claim + containers: + - name: opensearch-node1 + image: opensearchproject/opensearch:2.19.0 + ports: + - containerPort: 9200 + name: http + - containerPort: 9300 + name: transport + env: + - name: cluster.name + value: opensearch-cluster + - name: node.name + value: opensearch-node1 + - name: discovery.seed_hosts + value: opensearch-headless + - name: cluster.initial_cluster_manager_nodes + value: opensearch-node1,opensearch-node2 + - name: bootstrap.memory_lock + value: "false" + - name: OPENSEARCH_JAVA_OPTS + value: -Xms512m -Xmx512m + - name: OPENSEARCH_INITIAL_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: opensearch-auth + key: password + - name: plugins.security.ssl.http.enabled + value: "true" + - name: plugins.security.allow_unsafe_democertificates + value: "true" + - name: plugins.security.allow_default_init_securityindex + value: "true" + resources: + limits: + cpu: "1000m" + memory: "1Gi" + requests: + cpu: "500m" + memory: "1Gi" + volumeMounts: + - name: opensearch-data1 + mountPath: /usr/share/opensearch/data +--- +# -------------------------------------------------------------------------- +# E. Data Node 2 Deployment +# -------------------------------------------------------------------------- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: opensearch-node2-deployment + labels: + app: opensearch-node +spec: + replicas: 1 + selector: + matchLabels: + app: opensearch-node + node: opensearch-node2 + template: + metadata: + labels: + app: opensearch-node + node: opensearch-node2 + spec: + volumes: + - name: opensearch-data2 + persistentVolumeClaim: + claimName: opensearch-data2-claim + containers: + - name: opensearch-node2 + image: opensearchproject/opensearch:2.19.0 + ports: + - containerPort: 9200 + name: http + - containerPort: 9300 + name: transport + env: + - name: cluster.name + value: opensearch-cluster + - name: node.name + value: opensearch-node2 + - name: discovery.seed_hosts + value: opensearch-headless + - name: cluster.initial_cluster_manager_nodes + value: opensearch-node1,opensearch-node2 + - name: bootstrap.memory_lock + value: "false" + - name: OPENSEARCH_JAVA_OPTS + value: -Xms512m -Xmx512m + - name: OPENSEARCH_INITIAL_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: opensearch-auth + key: password + - name: plugins.security.ssl.http.enabled + value: "true" + - name: plugins.security.allow_unsafe_democertificates + value: "true" + - name: plugins.security.allow_default_init_securityindex + value: "true" + resources: + limits: + cpu: "1000m" + memory: "1Gi" + requests: + cpu: "500m" + memory: "1Gi" + volumeMounts: + - name: opensearch-data2 + mountPath: /usr/share/opensearch/data +--- +# -------------------------------------------------------------------------- +# F. Dashboard Deployment +# -------------------------------------------------------------------------- + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: swift-dashboard-deployment + labels: + app: opensearch-dashboard +spec: + replicas: 1 + selector: + matchLabels: + app: opensearch-dashboard + template: + metadata: + labels: + app: opensearch-dashboard + spec: + containers: + - name: opensearch-dashboards + image: /swift-dashboard:latest # Update registry name + ports: + - containerPort: 5601 + env: + - name: OPENSEARCH_HOSTS + value: '["https://opensearch-svc:9200"]' + - name: OPENSEARCH_USERNAME + valueFrom: + secretKeyRef: + name: opensearch-auth + key: username + - name: OPENSEARCH_PASSWORD + valueFrom: + secretKeyRef: + name: opensearch-auth + key: password + - name: OPENSEARCH_SSL_VERIFICATIONMODE + value: "none" + - name: DISABLE_SECURITY_DASHBOARDS_PLUGIN + value: "false" +--- +# -------------------------------------------------------------------------- +# G. Service Definitions +# -------------------------------------------------------------------------- +apiVersion: v1 +kind: Service +metadata: + name: opensearch-svc + labels: + app: opensearch +spec: + type: ClusterIP + ports: + - port: 9200 + targetPort: 9200 + protocol: TCP + selector: + app: opensearch-node +--- +apiVersion: v1 +kind: Service +metadata: + name: opensearch-headless + labels: + app: opensearch-node +spec: + clusterIP: None + ports: + - port: 9200 + name: rest + - port: 9300 + name: transport + selector: + app: opensearch-node +--- +apiVersion: v1 +kind: Service +metadata: + name: opensearch-dashboard-svc +spec: + type: NodePort + ports: + - port: 5601 + targetPort: 5601 + nodePort: 31709 + protocol: TCP + selector: + app: opensearch-dashboard