Neutron Operator
The Neutron operator runs the OpenStack network service on one mechanism driver. mechanism_drivers = ovn is what the rendered ml2_conf.ini carries, and no other value is reachable through the CRD. There is no ML2/OVS stack under it and no agent tier beside it: no L2, L3 or DHCP agent is projected, no neutron-dynamic-routing, and no BGP agent. The logical network model lives in the OVN Northbound database the OVN operator runs, and this operator programs it through the ML2/OVN mechanism driver.
Processes
Three long-running processes carry the service, plus the per-node agent:
| Process | Workload | What it does |
|---|---|---|
uWSGI on neutron.wsgi.api | the {name} Deployment of a Neutron | The REST API on port 9696. The image ships no entry script, so uWSGI loads the module directly, and the configuration reaches it through OS_NEUTRON_CONFIG_DIR and OS_NEUTRON_CONFIG_FILES |
neutron-periodic-workers | the {name}-periodic-workers Deployment | The recurring maintenance tasks of the ML2 plugin |
neutron-ovn-maintenance-worker | the {name}-ovn-maintenance-worker Deployment | Reconciles the Northbound model against the Neutron database |
neutron-ovn-metadata-agent | the {name}-metadata-agent DaemonSet of a NeutronMetadataAgent | Answers the 169.254.169.254 requests of the instances on its node |
neutron-rpc-server is absent from that list. Nothing in this deployment consumes RPC, so the process has no work, and at rpc_workers = 0 it exits 0 on 2026.1. Both worker Deployments serve no HTTP and get no Service, no HorizontalPodAutoscaler and no PodDisruptionBudget.
The bus
Neutron never touches the broker in this posture. rpc_workers and rpc_state_report_workers are both 0, [oslo_messaging_notifications] driver is noop, and dhcp_agent_notification together with the two notify_nova_on_port_* options stays false. Measured across four states, including after a network create, that adds up to zero connections, zero channels, zero queues and zero non-default exchanges.
A valid transport_url is still required. config.init calls n_rpc.init unconditionally in every neutron process, so the URL has to parse even though nothing dials the broker with it. spec.messaging is therefore a required field on Neutron, and the URL reaches every process and every migration Job as the OS_DEFAULT__TRANSPORT_URL environment override sourced from the derived {name}-transport-url Secret. It is never written into the rendered configuration, so the broker password stays out of the ConfigMap.
The two kinds
Neutron describes the service: the API Deployment, the two worker Deployments, the database and cache connections, the Keystone integration, the bus, and the optional recurring comparison of the Neutron database against the OVN Northbound database. It names one OVNCentral through spec.ovn.centralRef, reads the two connection strings and the client certificate off that CR's status, and mirrors the certificate into a Secret of its own.
The figure shows the OVNCentral a Neutron names and the other clients of its two databases.
NeutronMetadataAgent describes the per-node metadata proxy. It names an OVNChassis and puts one DaemonSet onto the nodes that chassis selects. The kind is separate because it belongs in the chassis's namespace: the pods are privileged, run on the compute and network nodes, and mount the local Open vSwitch socket the chassis pods create. That namespace has to be listed under privilegedNamespaces in the target-cluster access chart, which the API Deployment's namespace does not. See Target Clusters.
Design decisions
The Phase-0 decision record lives in meta issue #898. These are the entries this operator implements.
- D2 (operator split): a separate ovn-operator with the kinds
OVNCentralandOVNChassis, beside a neutron-operator that owns theNeutronkind. The coupling is CR status alone: this operator watchesOVNCentraland reads the addresses it publishes, which keeps the OVN layer available to a later consumer. D7 added the second kind on this side of the split. - D5 (RabbitMQ scope): the shared bus from #895, with quorum queues and stable queue names,
transport_urldelivered by environment override only, and the notifications driver atnoop. - D7 (metadata agent):
neutron-ovn-metadata-agentas a DaemonSet on the compute nodes, projected by this operator rather than by the ovn-operator, because this operator is the one that rendersneutron_ovn_metadata_agent.ini. It carries a same-node startup gate on chassis readiness, expressed as an init container that reads the node'ssystem-idfrom the local ovsdb socket and waits until the Southbound database holds theChassis_Privaterow of that name. See Node contract. - D10 (neutron-server launch mode): one launch mode for the API on every release.
neutron/wsgi/api.pyis byte-identical at 27.0.3 and 28.0.1, 29.0.0 addsprog='neutron-api'to theboot_servercall, and no release ships aneutron-serverbinary, so the API isuwsgi … --module neutron.wsgi.api. Configuration travels inOS_NEUTRON_CONFIG_DIRandOS_NEUTRON_CONFIG_FILES, since--config-diralone fails withConfigFilesNotFoundError.--set-placeholder start-time=%tmust not be rendered on the command line: uWSGI passes the literal%tand neutron dies onint('%t'). The operator writesstart-time = %tinto auwsgi.iniinstead, where uWSGI expands it while reading the file. - D11 (minimal RPC-worker posture): the process inventory above and the bus posture above. The contrast run with the two worker keys removed cost one AMQP connection, one channel, four durable quorum queues and three exchanges, and those queues outlive the process that declared them.
BGP is out of scope here and tracked in its own meta, #899.
Owned resources
The figure under Owned Resources of the Keystone operator draws the baseline this list follows: serving objects, config and Secrets, Jobs and CronJobs.
For a Neutron named {name} the operator manages:
| Resource | Name | Purpose |
|---|---|---|
| Deployment | {name} | The API pods, uWSGI on port 9696 |
| Service | {name} | ClusterIP in front of the API pods on port 9696 |
| PodDisruptionBudget | {name} | minAvailable: 1 above a lower replica bound of one, maxUnavailable: 1 at one (the bound is the HPA's minReplicas while spec.autoscaling is set); selects the API component only |
| HorizontalPodAutoscaler | {name} | Only while spec.autoscaling is set; the workers are never autoscaled |
| NetworkPolicy | {name} | Only while spec.networkPolicy is set |
| HTTPRoute | {name} | Only while spec.gateway is set |
MariaDB Database / User / Grant | {name} | Managed mode only (spec.database.clusterRef); a brownfield database is left alone |
| Deployment | {name}-periodic-workers | neutron-periodic-workers |
| Deployment | {name}-ovn-maintenance-worker | neutron-ovn-maintenance-worker |
| ConfigMap | {name}-config-<hash> | Immutable, content-addressed neutron.conf, ml2_conf.ini and uwsgi.ini, plus logging.conf for json logging; 3 historical retained |
| Secret | {name}-db-connection | The derived pymysql DSN, consumed through OS_DATABASE__CONNECTION |
| Secret | {name}-transport-url | The derived rabbit:// URL, consumed through OS_DEFAULT__TRANSPORT_URL |
| Secret | {name}-ovn-client | The mirror of the client identity the OVNCentral publishes: tls.crt, tls.key, ca.crt |
| Job | {name}-db-sync | neutron-db-manage upgrade head |
| Job | {name}-db-expand, {name}-db-migrate, {name}-db-contract | The three release-upgrade phases |
| CronJob | {name}-ovn-db-sync | neutron-ovn-db-sync-util, only while spec.ovnDBSync is set |
For a NeutronMetadataAgent named {name}:
| Resource | Name | Purpose |
|---|---|---|
| DaemonSet | {name}-metadata-agent | The agent pods on the nodes the referenced OVNChassis selects |
| ConfigMap | {name}-config-<hash> | Immutable, content-addressed neutron_ovn_metadata_agent.ini, plus logging.conf for json logging; 3 historical retained |
| Secret | {name}-transport-url | The derived rabbit:// URL, written only while spec.messaging is set |
The client Secret the agent pods mount is not in that list. cert-manager issues it and the OVNCentral publishes it; this operator reads its name off the central and mounts it.
Reference pages
- Neutron CRD: the
spec/statuscontract of the service, the rendered defaults, and the validation rules - NeutronMetadataAgent CRD: the node contract, the agent's own spec, and its conditions
- Neutron Controller Events: the Kubernetes events both controllers emit
- Reconciler Architecture: the two pipelines, their conditions, and requeue semantics
A ControlPlane projects the Neutron child from ServiceNeutronSpec, which derives the database, the cache, the Keystone endpoint and the bus from the plane and leaves the rest to that spec. The OVN layer this operator programs is documented under OVN Operator.