jens-skribble opened a new issue, #2821:
URL: https://github.com/apache/apisix-ingress-controller/issues/2821

   ### Current Behavior
   
   We run APISIX in **API-driven standalone** mode driven by the ingress 
controller
   (ADC, `provider.type: apisix-standalone`). We wanted a route's plugin to 
reference a
   Vault secret via APISIX's native `$secret://vault/...`. There is no CRD or
   `GatewayProxy` field we could find to declare the backing `secrets` 
secret-manager, so
   the only way to get one onto the data plane is to register it directly on 
APISIX's
   standalone Admin API (out of band).
   
   Doing that **deadlocks the controller**. Once the out-of-band manager bumps 
APISIX's
   `secrets_conf_version` from `0` to `1`, every subsequent controller/ADC 
full-config
   push is rejected:
   
   ```
   PUT /apisix/admin/configs → 400 Bad Request:
   secrets_conf_version must be greater than or equal to (1)
   ```
   
   ADC has no `secrets` resource type, so its push carries 
`secrets_conf_version: 0`
   while APISIX is now at `1`; APISIX's monotonic version check rejects the 
**whole**
   push. Because each standalone update replaces the full configuration 
**atomically**,
   nothing reconciles after that: the out-of-band manager is **not** wiped, the 
controller
   is simply **stuck**, and even unrelated routes stop applying (they 404 at 
the gateway).
   
   This looks like a robustness bug independent of the secret use case: once
   `secrets_conf_version` is `> 0` by **any** means (an out-of-band manager, a 
leftover
   from a prior setup), ADC - which always sends `0` - can never sync again, 
and it takes
   all other resources down with it.
   
   For reference, APISIX itself handles `$secret://` fine in this mode - we 
confirmed it
   end-to-end with two standalone docker/podman baselines (in the attached 
bundle), so the
   problem is on the controller/ADC side, not APISIX:
   - `compose/api-driven/` - in API-driven standalone, APISIX resolves 
`$secret://vault/...`
     when a `secrets` manager is present in the `/configs` payload.
   - `compose/file-driven/` - the documented `apisix.yaml` `secrets:` block 
resolves, but
     that mode disables the Admin API the controller drives (so it can't be 
used together
     with the controller).
   
   ### Expected Behavior
   
   - The controller/ADC should not deadlock on a resource type it doesn't 
manage: it
     should send a valid (or otherwise tolerated) `secrets_conf_version` so a 
stray or
     out-of-band `secrets` resource can't block reconciliation of everything 
else.
   - Ideally there would be a supported way to declare an APISIX `secrets` 
secret-manager
     through the controller (e.g. a `secrets` field on `GatewayProxy`, or a 
dedicated
     CRD), so `$secret://vault/...` references can be used. Today we can't find 
one.
     (`secretRef` reads a Kubernetes Secret and injects plaintext - a different 
mechanism,
     not APISIX's native `$secret://` manager.)
   
   ### Error Logs
   
   Controller `manager` container - this block repeats on **every** sync 
attempt after the
   out-of-band `secrets` resource exists:
   
   ```
   2026-07-22T09:14:48.222Z    INFO    provider.client    client/client.go:214  
  syncing all resources
   2026-07-22T09:14:48.239Z    ERROR    provider.executor    
client/executor.go:420    ADC Server sync failed    {"result": 
{"status":"all_failed","total_resources":0,"success_count":0,"failed_count":1,"success":[],"failed":[],"endpoint_status":[{"server":"http://10.244.0.3:9180","success":false,"reason":"PUT
 http://10.244.0.3:9180/apisix/admin/configs, responded with status 400 Bad 
Request, error_msg: secrets_conf_version must be greater than or equal to 
(1)"}]}, "error": "ADC Server sync failed (standalone mode): 
http://10.244.0.3:9180: PUT http://10.244.0.3:9180/apisix/admin/configs, 
responded with status 400 Bad Request, error_msg: secrets_conf_version must be 
greater than or equal to (1)"}
   2026-07-22T09:14:48.240Z    ERROR    provider.executor    
client/executor.go:153    failed to run http sync for server    {"server": 
"http://10.244.0.3:9180";, "error": "ServerAddr: http://10.244.0.3:9180, Err: 
http://10.244.0.3:9180: PUT http://10.244.0.3:9180/apisix/admin/configs, 
responded with status 400 Bad Request, error_msg: secrets_conf_version must be 
greater than or equal to (1)"}
   2026-07-22T09:14:48.240Z    ERROR    provider.client    client/client.go:306 
   failed to execute adc command    {"config": 
{"name":"GatewayProxy/ingress-apisix/apisix-config","serverAddrs":["http://10.244.0.3:9180"],"tlsVerify":false},
 "error": "ADC execution error for GatewayProxy/ingress-apisix/apisix-config: 
[ServerAddr: http://10.244.0.3:9180, Err: http://10.244.0.3:9180: PUT 
http://10.244.0.3:9180/apisix/admin/configs, responded with status 400 Bad 
Request, error_msg: secrets_conf_version must be greater than or equal to (1)]"}
   2026-07-22T09:14:48.240Z    ERROR    provider.client    client/client.go:247 
   failed to sync resources    {"name": 
"GatewayProxy/ingress-apisix/apisix-config", "error": "ADC execution errors: 
[ADC execution error for GatewayProxy/ingress-apisix/apisix-config: 
[ServerAddr: http://10.244.0.3:9180, Err: http://10.244.0.3:9180: PUT 
http://10.244.0.3:9180/apisix/admin/configs, responded with status 400 Bad 
Request, error_msg: secrets_conf_version must be greater than or equal to 
(1)]]"}
   2026-07-22T09:14:48.240Z    ERROR    provider    apisix/provider.go:282    
failed to sync    {"error": "failed to sync 1 configs: 
GatewayProxy/ingress-apisix/apisix-config"}
   2026-07-22T09:14:56.241Z    INFO    provider.client    client/client.go:214  
  syncing all resources
   2026-07-22T09:14:56.254Z    ERROR    provider.executor    
client/executor.go:420    ADC Server sync failed    {"result": 
{"status":"all_failed","total_resources":0,"success_count":0,"failed_count":1,"success":[],"failed":[],"endpoint_status":[{"server":"http://10.244.0.3:9180","success":false,"reason":"PUT
 http://10.244.0.3:9180/apisix/admin/configs, responded with status 400 Bad 
Request, error_msg: secrets_conf_version must be greater than or equal to 
(1)"}]}, "error": "ADC Server sync failed (standalone mode): 
http://10.244.0.3:9180: PUT http://10.244.0.3:9180/apisix/admin/configs, 
responded with status 400 Bad Request, error_msg: secrets_conf_version must be 
greater than or equal to (1)"}
   2026-07-22T09:14:56.254Z    ERROR    provider.executor    
client/executor.go:153    failed to run http sync for server    {"server": 
"http://10.244.0.3:9180";, "error": "ServerAddr: http://10.244.0.3:9180, Err: 
http://10.244.0.3:9180: PUT http://10.244.0.3:9180/apisix/admin/configs, 
responded with status 400 Bad Request, error_msg: secrets_conf_version must be 
greater than or equal to (1)"}
   2026-07-22T09:14:56.254Z    ERROR    provider.client    client/client.go:306 
   failed to execute adc command    {"config": 
{"name":"GatewayProxy/ingress-apisix/apisix-config","serverAddrs":["http://10.244.0.3:9180"],"tlsVerify":false},
 "error": "ADC execution error for GatewayProxy/ingress-apisix/apisix-config: 
[ServerAddr: http://10.244.0.3:9180, Err: http://10.244.0.3:9180: PUT 
http://10.244.0.3:9180/apisix/admin/configs, responded with status 400 Bad 
Request, error_msg: secrets_conf_version must be greater than or equal to (1)]"}
   2026-07-22T09:14:56.255Z    ERROR    provider.client    client/client.go:247 
   failed to sync resources    {"name": 
"GatewayProxy/ingress-apisix/apisix-config", "error": "ADC execution errors: 
[ADC execution error for GatewayProxy/ingress-apisix/apisix-config: 
[ServerAddr: http://10.244.0.3:9180, Err: http://10.244.0.3:9180: PUT 
http://10.244.0.3:9180/apisix/admin/configs, responded with status 400 Bad 
Request, error_msg: secrets_conf_version must be greater than or equal to 
(1)]]"}
   2026-07-22T09:14:56.255Z    ERROR    provider    apisix/provider.go:282    
failed to sync    {"error": "failed to sync 1 configs: 
GatewayProxy/ingress-apisix/apisix-config"}
   ```
   
   ### Steps to Reproduce
   
   A self-contained reproduction is attached as 
[apisix-secrets-repro.zip](https://github.com/user-attachments/files/30263545/apisix-secrets-repro.zip):
   
   - `k8s/` - a kustomization that stands everything up + a Job that automates 
steps 3–6
     below and prints the controller's own rejection log.
   - `compose/api-driven/` - docker/podman baseline: APISIX resolves 
`$secret://vault/...`
     in API-driven standalone (shows the gap is controller-side, not APISIX).
   - `compose/file-driven/` - docker/podman baseline: the documented 
`apisix.yaml`
     `secrets:` block resolves, but that mode has no Admin API for the 
controller to drive.
   
   To reproduce the deadlock manually against the controller:
   
   1. Deploy APISIX in API-driven standalone mode (`deployment.role: 
traditional`,
      `role_traditional.config_provider: yaml`) + APISIX Ingress Controller 
2.1.0 — e.g.
      the `apisix` Helm chart 2.16.0 with `ingress-controller.enabled: true`,
      `ingress-controller.config.provider.type: apisix-standalone`, and
      `ingress-controller.gatewayProxy.createDefault: true`.
   2. Apply any `ApisixRoute`; confirm the controller syncs it —
      `GET /apisix/admin/configs` shows the route and `.secrets` is empty 
(`secrets = 0`).
   3. Register a `secrets` manager **out of band** via the standalone Admin API 
(echo the
      existing `*_conf_version` values back, omit `secrets_conf_version`, add 
the manager):
      ```
      PUT /apisix/admin/configs
      { ...existing *_conf_version..., "secrets": [
          { "id": "vault/oidc", "uri": "http://vault.example:8200";, "prefix": 
"kv/apisix", "token": "root" } ] }
      ```
      Confirm `.secrets` now has 1 entry (`secrets = 1`); APISIX's 
`secrets_conf_version`
      is now `1`.
   4. Trigger a controller re-sync (e.g. `kubectl annotate apisixroute <name> 
poke=$(date +%s) --overwrite`).
   5. Watch the controller logs: every sync now fails with
      `400 ... secrets_conf_version must be greater than or equal to (1)`.
   6. Observe the blast radius: the out-of-band manager is **not** removed, and 
because the
      push is atomic, no route reconciles — `curl` against the gateway returns 
`404` even
      for routes unrelated to secrets.
   
   ### Environment
   
   APISIX Ingress controller version (`apisix-ingress-controller version 
--long`):   **2.1.0**
   ```Version: 2.1.0
   Git SHA: 
   Go Version: go1.24.13
   Building OS/Arch: /
   Running OS/Arch: linux/amd64
   ```
   
   Kubernetes cluster version (`kubectl version`): 
   ```
   Client Version: v1.33.13
   Kustomize Version: v5.6.0
   Server Version: v1.35.1
   ```
   (reproduced on minikube, Podman driver)
   
   APISIX: **3.17.0**; installed via the `apisix` Helm chart **2.16.0**;
     `provider.type: apisix-standalone`
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to