Files
kea-operator/config/crd/bases/kea.unkin.net_keaclientclasses.yaml
T
unkinben d3fb5dcd1a
ci/woodpecker/pr/build Pipeline failed
ci/woodpecker/pr/pre-commit Pipeline failed
ci/woodpecker/pr/test Pipeline failed
Scaffold kea-operator: CRDs, controllers, config rendering, REST API, CI
Replace the ISC dhcpd PXE-boot VM with a Kea DHCP Kubernetes operator, modelled
on bind-operator. The operator renders kea-dhcp4 config from CRs and runs an HA
pair of kea-dhcp4 + kea-ctrl-agent servers behind an anycast Service.

- add KeaCluster/KeaSubnet/KeaClientClass/KeaAPI CRDs (group kea.unkin.net)
- render deterministic kea-dhcp4.conf + kea-ctrl-agent.conf into a ConfigMap and
  roll the StatefulSet via a config-hash annotation; best-effort hot-reload via
  the kea-ctrl-agent REST channel
- run HA hot-standby (memfile leases) with stable per-peer DNS identity from a
  StatefulSet; expose an anycast LoadBalancer Service for PureLB
- represent the full legacy dhcpd config: 198.18.13-17.0/24 pools, pool-less
  198.18.25.0/24, and the Legacy/UEFI-64 PXE arch classes (option 93)
- add the KeaAPI-spawned REST service: Terraform-friendly CRUD over subnet and
  client-class CRs (stable IDs, PUT upsert, 404 drift, bearer-token auth)
- add Makefile (patch/minor/major tag targets), distroless operator/api images,
  an AlmaLinux+EPEL kea workload image, and woodpecker CI with k8s resources +
  serviceAccountName on every step
- unit tests for config rendering, controller reconcile/config-hash, and the API

Claude-Session: https://claude.ai/code/session_01JUoARVdmhxKQHyyyp1pxeT
2026-08-02 18:42:46 +10:00

186 lines
7.7 KiB
YAML

---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.17.3
name: keaclientclasses.kea.unkin.net
spec:
group: kea.unkin.net
names:
kind: KeaClientClass
listKind: KeaClientClassList
plural: keaclientclasses
shortNames:
- kcc
singular: keaclientclass
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.clusterRef
name: Cluster
type: string
- jsonPath: .spec.bootFileName
name: BootFile
type: string
- jsonPath: .status.phase
name: Phase
type: string
name: v1alpha1
schema:
openAPIV3Schema:
description: KeaClientClass is a PXE boot class matched on the client architecture.
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: |-
KeaClientClassSpec defines a PXE boot client-class, typically matching the
DHCP client architecture option (code 93).
properties:
archHex:
description: |-
ArchHex is a convenience list of client-architecture values (option 93),
e.g. ["0x0000"] or ["0x0007","0x0009"]. Rendered into a Test expression
of the form: option[93].hex == 0x0007 or option[93].hex == 0x0009.
items:
type: string
type: array
bootFileName:
description: BootFileName handed to matching clients (option 67 /
boot-file-name).
type: string
clusterRef:
description: |-
ClusterRef selects the owning KeaCluster by name. Empty means every
KeaCluster in the namespace.
type: string
nextServer:
description: NextServer overrides siaddr for matching clients.
type: string
optionData:
description: OptionData carries additional options set for matching
clients.
items:
description: OptionData is a rendered DHCPv4 option value (subnet-
or class-scoped).
properties:
code:
description: Code of the option (alternative to Name).
type: integer
csvFormat:
description: CSVFormat controls whether Data is parsed as CSV
(default true in Kea).
type: boolean
data:
description: Data is the option value(s), comma-separated per
Kea convention.
type: string
name:
description: Name of the option, e.g. "routers", "domain-name-servers".
type: string
space:
description: Space defaults to "dhcp4".
type: string
required:
- data
type: object
type: array
serverHostname:
description: ServerHostname (sname) for matching clients.
type: string
test:
description: |-
Test is a raw Kea class-match expression. When empty it is generated
from ArchHex.
type: string
type: object
status:
description: KeaClientClassStatus captures observed state.
properties:
conditions:
items:
description: Condition contains details for one aspect of the current
state of this API Resource.
properties:
lastTransitionTime:
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
observedGeneration:
format: int64
type: integer
phase:
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}