Description
When using APISIX Ingress Controller 2.1.0 with ADC 0.27.1 and the apisix provider, ADC fails to synchronize resources if APISIX contains a Consumer Credential that was created directly through the APISIX Admin API and is not present in the Kubernetes desired state.
ADC detects the remote-only consumer_credential and generates a delete diff for it, but the synchronization then fails with HTTP 500:
TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string
or an instance of Buffer, TypedArray, or DataView. Received undefined
This prevents the entire ADC synchronization from completing.
As a consequence, unrelated resources managed by APISIX Ingress Controller, such as Upstreams, can remain stale.
Environment
- APISIX Ingress Controller:
2.1.0
- ADC:
0.27.1
- ADC image:
ghcr.io/api7/adc:0.27.1
- Provider:
apisix
- APISIX deployment mode: traditional / etcd-backed
- Kubernetes resources are managed by APISIX Ingress Controller.
- Consumers and Credentials are dynamically managed by an external application through the APISIX Admin API.
Ingress Controller provider configuration:
provider:
type: apisix
syncPeriod: 1m
initSyncDelay: 20m
Scenario
We have an external application that dynamically manages API keys.
The intended ownership model is:
Kubernetes
|
v
APISIX Ingress Controller
|
v
ADC
|
+---- Routes
+---- Upstreams
+---- TLS
+---- Plugin configuration
|
v
APISIX
External API key management application
|
v
APISIX Admin API
|
+---- Consumers
+---- Consumer Credentials
|
v
APISIX
The external application creates Consumers and key-auth Credentials using the APISIX Admin API.
There are no corresponding ApisixConsumer resources in Kubernetes.
For example:
$ kubectl get apisixconsumer -A
No resources found
The APISIX Admin API contained Consumers such as:
{
"username": "cust_9f19e3aa0f01",
"labels": {
"tenant_id": "2"
}
}
and the Consumer had a credential:
{
"id": "cred_b4ef3e46d9d24b3abd5e6aaf66e13038",
"plugins": {
"key-auth": {
"key": "<redacted>"
}
}
}
ADC behavior
With ADC debug logging enabled, ADC detected the credential as a remote-only resource.
The local desired state did not contain the credential, while the remote state contained:
consumer_credentials:
cred_b4ef3e46d9d24b3abd5e6aaf66e13038
ADC then generated a diff similar to:
resourceType: consumer_credential
type: delete
Immediately afterwards, synchronization failed with:
HTTP 500:
{
"message": "TypeError [ERR_INVALID_ARG_TYPE]: The \"data\" argument must be
of type string or an instance of Buffer, TypedArray, or DataView.
Received undefined"
}
The Ingress Controller reported:
ERROR provider.executor failed to run http sync for server
ERROR provider.client failed to execute adc command
ERROR provider.client failed to sync resources
ERROR provider failed to sync
The target server was the normal APISIX Admin API endpoint:
http://<apisix-admin-service>:9180
Impact
The failure appears to abort the complete ADC synchronization rather than only the Consumer Credential operation.
We observed an unrelated APISIX Upstream remaining stale.
The Kubernetes EndpointSlice contained:
while the corresponding APISIX Upstream still referenced an old Pod IP.
After removing the remote-only Consumer Credential, ADC synchronization recovered and the APISIX Upstream was automatically updated to:
After that, the following errors no longer appeared:
failed to run http sync
failed to execute adc command
failed to sync resources
ERR_INVALID_ARG_TYPE
This makes the issue reproducible in our environment.
Steps to reproduce
- Deploy APISIX with APISIX Ingress Controller 2.1.0.
- Use ADC 0.27.1 with:
- Do not create an
ApisixConsumer in Kubernetes.
- Create a Consumer directly through the APISIX Admin API.
- Create a
key-auth Credential for that Consumer through the Admin API.
- Trigger or wait for an APISIX Ingress Controller / ADC full synchronization.
- ADC discovers the remote-only
consumer_credential.
- ADC generates:
resourceType: consumer_credential
type: delete
- ADC synchronization fails with:
ERR_INVALID_ARG_TYPE
Received undefined
- Delete the Consumer Credential manually through the APISIX Admin API.
- Trigger another synchronization.
- Synchronization succeeds and unrelated resources such as Upstreams are updated normally.
Expected behavior
At minimum, processing a remote-only Consumer Credential should not cause ADC to return HTTP 500 or abort synchronization of unrelated resources.
However, we would also like clarification about the expected resource ownership model.
APISIX officially supports creating Consumers and Credentials through the Admin API.
Is the following configuration model supported when using APISIX Ingress Controller 2.x with the apisix provider?
AIC / ADC:
Routes
Upstreams
TLS
Plugins
Admin API / external application:
Consumers
Consumer Credentials
Specifically:
- Is ADC expected to delete Consumers or Consumer Credentials that exist in APISIX but are not present in the Kubernetes/AIC desired state?
- Is there a supported way to mark Admin API-created Consumers/Credentials as unmanaged by ADC?
- Is there a configuration option to exclude
consumer and consumer_credential resources from ADC reconciliation?
- If mixed ownership is not supported, what is the recommended architecture for applications that dynamically create, rotate, revoke, or suspend API keys through the APISIX Admin API while Routes and Upstreams are managed by APISIX Ingress Controller?
Additional observation
The Consumer itself did not have an APISIX Ingress Controller ownership label.
For example, it only contained application-specific labels:
{
"labels": {
"tenant_id": "2"
}
}
Despite this, its Credential was still included in the ADC remote diff and was scheduled for deletion.
Therefore, it does not appear that the absence of a managed-by: apisix-ingress-controller label prevents ADC from reconciling the Consumer Credential.
Workaround
Our current workaround is to remove the Admin API-created Consumer Credential.
After removing the credential:
- ADC synchronization succeeds.
ERR_INVALID_ARG_TYPE no longer occurs.
- Unrelated APISIX Upstreams are synchronized correctly.
However, this prevents us from using APISIX Admin API-managed Credentials for our dynamic API key management use case.
Description
When using APISIX Ingress Controller 2.1.0 with ADC 0.27.1 and the
apisixprovider, ADC fails to synchronize resources if APISIX contains a Consumer Credential that was created directly through the APISIX Admin API and is not present in the Kubernetes desired state.ADC detects the remote-only
consumer_credentialand generates adeletediff for it, but the synchronization then fails with HTTP 500:This prevents the entire ADC synchronization from completing.
As a consequence, unrelated resources managed by APISIX Ingress Controller, such as Upstreams, can remain stale.
Environment
2.1.00.27.1ghcr.io/api7/adc:0.27.1apisixIngress Controller provider configuration:
Scenario
We have an external application that dynamically manages API keys.
The intended ownership model is:
The external application creates Consumers and
key-authCredentials using the APISIX Admin API.There are no corresponding
ApisixConsumerresources in Kubernetes.For example:
The APISIX Admin API contained Consumers such as:
{ "username": "cust_9f19e3aa0f01", "labels": { "tenant_id": "2" } }and the Consumer had a credential:
{ "id": "cred_b4ef3e46d9d24b3abd5e6aaf66e13038", "plugins": { "key-auth": { "key": "<redacted>" } } }ADC behavior
With ADC debug logging enabled, ADC detected the credential as a remote-only resource.
The local desired state did not contain the credential, while the remote state contained:
ADC then generated a diff similar to:
Immediately afterwards, synchronization failed with:
The Ingress Controller reported:
The target server was the normal APISIX Admin API endpoint:
Impact
The failure appears to abort the complete ADC synchronization rather than only the Consumer Credential operation.
We observed an unrelated APISIX Upstream remaining stale.
The Kubernetes EndpointSlice contained:
while the corresponding APISIX Upstream still referenced an old Pod IP.
After removing the remote-only Consumer Credential, ADC synchronization recovered and the APISIX Upstream was automatically updated to:
After that, the following errors no longer appeared:
This makes the issue reproducible in our environment.
Steps to reproduce
ApisixConsumerin Kubernetes.key-authCredential for that Consumer through the Admin API.consumer_credential.Expected behavior
At minimum, processing a remote-only Consumer Credential should not cause ADC to return HTTP 500 or abort synchronization of unrelated resources.
However, we would also like clarification about the expected resource ownership model.
APISIX officially supports creating Consumers and Credentials through the Admin API.
Is the following configuration model supported when using APISIX Ingress Controller 2.x with the
apisixprovider?Specifically:
consumerandconsumer_credentialresources from ADC reconciliation?Additional observation
The Consumer itself did not have an APISIX Ingress Controller ownership label.
For example, it only contained application-specific labels:
{ "labels": { "tenant_id": "2" } }Despite this, its Credential was still included in the ADC remote diff and was scheduled for deletion.
Therefore, it does not appear that the absence of a
managed-by: apisix-ingress-controllerlabel prevents ADC from reconciling the Consumer Credential.Workaround
Our current workaround is to remove the Admin API-created Consumer Credential.
After removing the credential:
ERR_INVALID_ARG_TYPEno longer occurs.However, this prevents us from using APISIX Admin API-managed Credentials for our dynamic API key management use case.