statefulService.ts
Overview
The **statefulService.ts** file provides core functionality to define and deploy stateful blockchain services (such as daemons and indexers) on Kubernetes using Pulumi, a programmable infrastructure as code tool. It exposes two main functions:
createCoinService: Constructs a detailed service specification describing container configuration, health probes, persistent storage, and lifecycle scripts for a blockchain coinstack component.deployStatefulService: Deploys one or more such service specifications as a Kubernetes StatefulSet, along with associated Services, ConfigMaps, TLS certificates, ingress routing, and persistent storage claims.
This file automates the translation of high-level blockchain service parameters and lifecycle scripts into Kubernetes-native constructs, enabling scalable, maintainable, and secure deployments on a Kubernetes cluster.
Detailed API Documentation
Types and Imports
k8s: Pulumi Kubernetes SDK is used to define Kubernetes API objects.readFileSync: Node.js file system function to read lifecycle scripts.Config,Service,CoinServiceArgs: Types imported from the local module, representing configuration inputs and deployment abstractions.
Function: createCoinService
function createCoinService(args: CoinServiceArgs, assetName: string): Service
Purpose
Generates a service specification object representing a single blockchain coinstack component (e.g., daemon, indexer). This includes container definitions, port mappings, environment variables, persistent volume claims, lifecycle probe scripts (init, startup, readiness, liveness), and resource limits.
Parameters
args(CoinServiceArgs): Configuration arguments defining the service's behavior and resources, including:name: Service name (e.g., "daemon").image: Docker image to use.ports: Optional port definitions keyed by port name.env: Optional environment variables as key-value pairs.command: Optional container command override.args: Optional container command arguments.cpuLimit,memoryLimit: Resource limits.cpuRequest,memoryRequest: Resource requests.startupProbe,livenessProbe,readinessProbe: Optional Kubernetes probe configurations.useMonitorContainer: Flag to enable a separate monitor container for readiness probes.configMapData: Extra static config data to inject via ConfigMap.volumeMounts: Additional container volume mounts.dataDir: Mount path for persistent data volume.storageClassName,storageSize,storageIops,storageThroughput: Persistent storage configuration.
assetName(string): Prefix to namespace Kubernetes resource names for uniqueness.
Returns
Service: An object describing the Kubernetes service components:name: Service name.configMapData: Lifecycle scripts and extra config injected as ConfigMap data.containers: Array of Kubernetes container specs.ports: Array of port definitions.volumeClaimTemplates: Persistent volume claim templates for storage.
Description and Usage
Reads lifecycle shell scripts (
init.sh,startup.sh,liveness.sh,readiness.sh) from the service's directory to inject into a ConfigMap and mount into containers.Configures the main service container with ports, environment, resource limits, security context, command overrides, and volume mounts.
Optionally adds a separate "monitor" container to run readiness probes if
useMonitorContaineris enabled.Defines PersistentVolumeClaims using the specified storage class and size, and sets AWS EBS-specific annotations if applicable.
Useful for defining stateful blockchain node daemons or indexers with custom lifecycle and health checks.
Example
const daemonService = createCoinService({
name: 'daemon',
image: 'shapeshiftdao/bitcoin-daemon:latest',
ports: { rpc: { port: 8332 } },
env: { BITCOIN_NETWORK: 'mainnet' },
cpuLimit: '1000m',
memoryLimit: '1Gi',
storageSize: '10Gi',
storageClassName: 'gp3',
useMonitorContainer: true,
}, 'bitcoin')
console.log(daemonService.name) // 'bitcoin-daemon'
console.log(daemonService.containers.length) // 2 (main + monitor container)
Function: deployStatefulService
async function deployStatefulService(
appName: string,
assetName: string,
provider: k8s.Provider,
namespace: string,
config: Pick<Config, 'rootDomainName' | 'environment' | 'statefulService'>,
services: Service[],
volumes?: Array<k8s.types.input.core.v1.Volume>
): Promise<void>
Purpose
Deploys an array of stateful blockchain services as a Kubernetes StatefulSet with supporting resources: Service, ConfigMap, TLS certificates, Traefik ingress routes, and persistent storage. This function orchestrates the full lifecycle deployment of stateful services within a namespace.
Parameters
appName(string): Application name label for Kubernetes resources.assetName(string): Prefix used for Kubernetes resource names.provider(k8s.Provider): Pulumi Kubernetes provider instance to manage resource deployment.namespace(string): Kubernetes namespace to deploy into.config(Pick<Config, 'rootDomainName' | 'environment' | 'statefulService'>): Partial configuration object containing:rootDomainName: Base domain for TLS certificates and ingress.environment: Deployment environment (e.g., "prod", "staging").statefulService: Configuration including replica count.
services(Service[]): Array of service specifications created bycreateCoinService.volumes(Array<k8s.types.input.core.v1.Volume>, optional): Additional volumes to mount in pods.
Returns
Promise<void>: Asynchronous deployment completion.
Description and Usage
Validates if stateful service deployment is enabled and has replicas.
Aggregates container specs, ports, ConfigMap data, and volume claim templates from all provided services.
Creates a Kubernetes ClusterIP Service exposing all ports from all services.
Creates a ConfigMap combining all lifecycle scripts and configuration data.
Defines a Pod template spec with all containers and volume mounts, including the ConfigMap and optional external volumes.
Creates a StatefulSet with rolling update strategy and parallel pod management.
If a
rootDomainNameis provided, it creates:cert-manager TLS Certificates for all services' domains.
Traefik Middleware to strip path prefixes for ingress routing.
Traefik IngressRoute resources to route HTTP(s) traffic securely.
Kubernetes Ingress resource with DNS rules.
Labels all resources consistently for discoverability and management.
Integrates with Traefik and cert-manager to enable zero-downtime secure ingress.
Example
await deployStatefulService(
'bitcoin-app',
'bitcoin',
k8sProvider,
'default',
{
rootDomainName: 'example.com',
environment: 'prod',
statefulService: { replicas: 3 },
},
[daemonService, indexerService],
[]
)
Implementation Details and Algorithms
Lifecycle Script Handling:
The file reads shell scripts (init.sh,startup.sh,liveness.sh,readiness.sh) dynamically from service directories. If scripts are missing, empty strings are used. These scripts are injected into Kubernetes ConfigMaps and mounted inside containers as executable files, then referenced in Kubernetes probe configurations.Container Probes:
KubernetesstartupProbe,livenessProbe, andreadinessProbeare configured asexeccommands running the respective mounted shell scripts, allowing custom health check logic tailored to blockchain node readiness and liveness.Monitor Container Pattern:
If requested, readiness probes are run in a separate "monitor" container to isolate health check execution, improving main container stability and separation of concerns.Persistent Storage Configuration:
PersistentVolumeClaims are templated with configurable storage class and size. For AWS EBS gp3 storage, optional IOPS and throughput annotations are added to tune volume performance.Resource Aggregation:
When deploying multiple services, ports, containers, volume claims, and ConfigMap data are aggregated to form a single StatefulSet pod spec and service.Ingress and TLS Automation:
Using cert-manager Custom Resources, TLS certificates are requested for all service domains. Traefik ingress routes and middlewares are created to route HTTP traffic to the correct services with optional path prefix stripping. Kubernetes native Ingress resource is also created to facilitate domain routing.Labeling Strategy:
Consistent labels (app,asset,tier) are applied to all Kubernetes objects to enable organization, filtering, and monitoring.
Interaction with Other System Components
Coinstack Deployment Scripts:
This file is typically invoked by coinstack-specific Pulumi deployment scripts that defineCoinServiceArgsfor each blockchain service (daemon, indexer, etc.) and callcreateCoinServiceanddeployStatefulService.Infrastructure and Config Management:
Relies on environment variables and configuration files to determine image names, resource limits, and domain names.Lifecycle Scripts:
Depends on external shell scripts located in each coinstack service directory to define initialization and health probe behavior.Docker Image Automation:
The container images referenced here are built and pushed by other parts of the deployment system (e.g.,deployApi), ensuring consistent and immutable image versions.Ingress and TLS Management:
Integrates with cert-manager and Traefik ingress controllers installed in the Kubernetes cluster to provide secure and routable external access.Persistent Storage:
Works with the Kubernetes storage subsystem, including cloud provider-specific storage classes and annotations, to ensure durable storage of blockchain data.
Visual Diagram: Class and Function Structure
classDiagram
class createCoinService {
+args: CoinServiceArgs
+assetName: string
+returns Service
}
class deployStatefulService {
+appName: string
+assetName: string
+provider: k8s.Provider
+namespace: string
+config: Pick<Config, 'rootDomainName' | 'environment' | 'statefulService'>
+services: Service[]
+volumes?: k8s.types.input.core.v1.Volume[]
+returns Promise<void>
}
createCoinService <.. deployStatefulService : uses >
Summary
The **statefulService.ts** file is a critical part of the blockchain coinstack deployment automation system. It abstracts the complexity of Kubernetes StatefulSet resource creation for stateful blockchain node services, with rich support for lifecycle scripts, health probes, persistent storage, secure ingress, and TLS certificates. By converting declarative service arguments into Kubernetes manifests programmatically via Pulumi, it enables repeatable, configurable, and scalable deployments suited to the unique requirements of blockchain infrastructure components.