Skip to content

hex.k8s.services.build ​

Total args: 94

Required Args ​

ArgNotes
name-
labels-
image-

Optional Args ​

ArgDefaultNotes
namespace"default"-
minreplicas-
maxreplicas * 2-
autoscaletrue-
autoscalingnullvalidated autoscaling/v2 config; defaults to the legacy CPU target
networkPolicytrue-
serviceAccounttrue-
serviceAccountTokenfalse-
roleBindingtrue-
port443-
altPortnull-
extraServicePorts[ ]-
cpuUtilization75-
replicas2-
revisionHistoryLimit2-
maxSurge1-
maxUnavailable1-
rolloutnulluse services.rollouts for Deployment strategy and readiness policy
disruptionBudgetnulluse services.disruptions; emits a selector-coupled PDB
cpuRequest"400m"-
cpuLimitnull-
memoryRequest"1Gi"-
memoryLimitnull-
ephemeralStorageRequestnull-
ephemeralStorageLimitnull-
commandnull-
argsnull-
env[ ]env vars, standard spec
envAttrs{ }env vars, as a nix attrset
envFrom[ ]envFrom standard spec
volumes[ ]our custom format for volume
initContainersnullwill only add to main container
sidecars[ ]additional containers; use services.containers.build
ipnull-
servicetrue-
exposurenulltyped Service spec from services.exposures
loadBalancerfalse-
ingressfalse-
nodePortfalse-
subdomainnull-
nodeSelectornull-
tolerationsnull-
topologySpread[ ]constraints from services.spread; selectors are derived from labels
terminationGracePeriodSecondsnulltotal budget for preStop and process shutdown
lifecyclenullmain container lifecycle; use services.actions for handlers
livenessProbenull-
readinessProbenull-
startupProbenull-
securityContextnull-
egressPolicydefaults.egressPolicy-
ingressPolicydefaults.ingressPolicy-
daemonSetfalse-
suffix""-
depSuffix"${suffix}"-
saSuffix"-service-account${suffix}"-
npSuffix"-policy${suffix}"-
rbSuffix"-role-binding-view${suffix}"-
hpaSuffix"-hpa${suffix}"-
pdbSuffix"-pdb${suffix}"-
serviceSuffix"-service${suffix}"-
ingressSuffix"-ingress${suffix}"-
tsSuffix"-ts${suffix}"-
pre1_18false-
pre1_30false-
hostnull-
extraContainer{ }-
extraPodSpec{ }additional PodSpec fields; Hex-managed fields cannot be replaced
extraDeploymentAnnotations{ }-
extraServiceAccountAnnotations{ }-
extraServiceAnnotations{ }-
extraIngressAnnotations{ }-
extraPodAnnotations{ }-
imagePullSecrets[ ]-
ingressTLSSecret""-
softAntiAffinityfalse-
hardAntiAffinityfalse-
disableHttptrue-
tailscaleSidecarfalse-
tailscale_image_basehex.k8s.tailscale.defaults.tailscale_image_base-
tailscale_image_taghex.k8s.tailscale.defaults.tailscale_image_tag-
hostAliases[ ]-
appArmorif pre1_30 then "unconfined" else "Unconfined"-
extraDep{ }-
extraSA{ }-
extraNP{ }-
extraRB{ }-
extraHPA{ }-
extraPDB{ }top-level PDB escape hatch; requires disruptionBudget
extraSvc{ }-
extraIng{ }-
__initfalse-

Lifecycle Actions ​

Use hex.k8s.services.actions to construct validated Kubernetes action fragments:

  • actions.exec [ "command" "arg" ]
  • actions.httpGet { port = 8080; path = "/healthz"; }
  • actions.sleep 5

Each postStart or preStop hook must contain exactly one action. The pod termination grace period is the total budget for the preStop hook and normal process shutdown.

nix
let
  actions = hex.k8s.services.actions;
  probes = hex.k8s.services.probes;
in
hex.k8s.services.build {
  # required service arguments omitted
  terminationGracePeriodSeconds = 60;
  lifecycle.preStop = actions.exec [ "/app/bin/drain" ];
  startupProbe = probes.httpGet {
    path = "/healthz";
    port = 8080;
    failureThreshold = 30;
    periodSeconds = 2;
  };
}

extraPodSpec adds uncommon PodSpec fields, but cannot replace fields managed directly by services.build.

Validated Service Policies ​

The service namespace provides constructors for Kubernetes shapes with unions, derived selectors, or cross-resource behavior:

  • disruptions.{minAvailable,maxUnavailable} for PodDisruptionBudgets
  • spread.{zones,nodes,constraint} for topology spread constraints
  • containers.build for additional sidecar containers
  • probes.{exec,httpGet,tcpSocket,grpc} for container probes
  • rollouts.{rolling,recreate} for Deployment rollout policy
  • autoscaling.{cpu,v2} and autoscaling.metrics.* for autoscaling/v2 HPAs
  • ports.* and exposures.* for typed Services
  • volumes.{emptyDir,pvc,secret,configMap,hostPath,projected,downwardAPI} for exactly-one-source volumes
nix
let
  services = hex.k8s.services;
in
services.build {
  # required service arguments omitted
  replicas = 3;
  disruptionBudget = services.disruptions.maxUnavailable 1;
  topologySpread = [
    (services.spread.zones { mode = "hard"; })
  ];
  rollout = services.rollouts.rolling {
    maxUnavailable = 0;
    maxSurge = "25%";
    minReadySeconds = 10;
    progressDeadlineSeconds = 600;
  };
}

Example ​

nix
{hex}:
hex [
  (hex.k8s.services.build {
    name = "api";
    labels = {app = "api";};
    image = "ghcr.io/example/api:latest";
    port = 8080;
    ingress = true;
    host = "api.example.com";
  })
]