When you need to expose a custom backend service through the OpenShift (Kubernetes) API server itself — complete with proper routing, authentication header forwarding, and API group registration — the **API Aggregation Layer** is your tool of choice. Instead of a standalone endpoint, your service becomes a first-class citizen of the cluster API, reachable at a path like `/apis/<your-group>/<version>/`.
## What Is an APIService?
The Kubernetes aggregation layer runs in-process with the `kube-apiserver`. Once you register an `APIService` object, the API server proxies any traffic matching your declared group/version path to the backing `Service` you specify. This is how components like the metrics server plug into the core API — and it's exactly how you can expose your own metadata endpoint.
Official references:
- [APIService v1beta1 (OpenShift Origin)](https://docs.openshift.org/latest/rest_api/apis-apiregistration.k8s.io/v1beta1.APIService.html)
- [APIService apiregistration.k8s.io/v1 (OpenShift 4.6)](https://docs.openshift.com/container-platform/4.6/rest_api/extension_apis/apiservice-apiregistration-k8s-io-v1.html)
## Registering the APIService
Create an `apiservice.yaml` manifest that tells the aggregation layer which group/version to claim and which Service to proxy to:
```yaml
kind: APIService
apiVersion: apiregistration.k8s.io/v1
metadata:
name: v1.cats.example.com
namespace: "somenamespace"
spec:
insecureSkipTLSVerify: false
group: cats.example.com
groupPriorityMinimum: 18000
service:
kind: service
namespace: somenamespace
name: my-header-echo-service
version: v1
versionPriority: 100
```
Apply it with:
```bash
oc apply -f apiservice.yaml
```
Key fields to understand:
- **`group`** — the API group this service will own (e.g. `cats.example.com`)
- **`version`** — the API version to register (`v1`)
- **`service`** — points to the Kubernetes `Service` that handles the actual requests
- **`groupPriorityMinimum` / `versionPriority`** — control ordering when multiple API groups or versions are present
- **`insecureSkipTLSVerify`** — skips TLS verification toward the backend if needed for testing only!
## Verifying the Aggregated Endpoint
Once applied, you can hit your new API path directly through the OpenShift API server. The aggregation layer will forward the request to your backing service, enriching it with forwarded headers that carry identity and routing information:
```bash
curl -k https://localhost:8443/apis/cats.example.com/v1/
```
Response from the backend service shows the injected headers:
```yaml
host: localhost:8443
user-agent: curl/7.29.0
accept: */*
x-forwarded-for: 127.0.0.1
x-forwarded-host: 172.30.109.230:443
x-forwarded-proto: https
x-forwarded-uri: /apis/cats.example.com/v1/
x-remote-group: system:unauthenticated
x-remote-user: system:anonymous
accept-encoding: gzip
```
Notice the `x-remote-user` and `x-remote-group` headers — these are injected by the API server and identify the caller. In a production setup with proper authentication, these would carry the actual user identity rather than `system:anonymous`, letting your backend make authorization decisions without needing to re-validate credentials itself.
## Production Considerations
- **RBAC**: Grant the aggregated API server the necessary permissions using `ClusterRole` and `ClusterRoleBinding` objects.
- **Service availability**: The `APIService` will show `Available: False` if the backing `Service` or its pods are unhealthy — check with `oc get apiservice v1.cats.example.com`.
- **Discovery**: Because the endpoint is registered in the API group tree, `kubectl` and `oc` can discover it automatically via API discovery, making it easy to integrate into tooling.
Comments
Post a Comment