Summary
Our demo Card application deployed as here in has OpenAPI yaml. Such specs should be published (https://deck-api.api.kambur.ie/shuffledDeck.yaml) and for convenience, easily testable using Swagger UI (https://deck-api.api.kambur.ie/swagger-ui.html).
We want to avoid exposing OpenAPI yaml from our application container as static content, generally, should be exposed
separate from API. We will also want to keep in mind that this yaml file we will use later for validation using APISIX
oas-validation plugin. Similarly, we want to keep Swagger UI separate from APIs like we did with yaml file.
Expose static files
Controversially, we will put both Swagger yaml and the files to K8s ConfigMap as they are small and attach to a sidecar
container of our ramblings-api container, running NGINX. These files aren’t terribly large. In a hindsight, it would have been easier to
have a separate container running NGINX but anyway…
Sidecar below but also requires changes to service also to expose port 80.
- name: api-docs-sidecar
image: nginx:latest
ports:
- containerPort: 80
name: http
volumeMounts:
- name: api-docs
mountPath: /usr/share/nginx/html
readOnly: true
resources:
requests:
memory: "32Mi"
cpu: "10m"
limits:
memory: "64Mi"
readinessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 5
periodSeconds: 5
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 10
periodSeconds: 10
volumes:
- name: api-docs
configMap:
name: api-docs
---
apiVersion: v1
kind: Service
metadata:
name: ramblings-app
namespace: ramblings
spec:
type: NodePort
selector:
app: ramblings-app
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
- name: api-docs
protocol: TCP
port: 80
targetPort: 80
Then, small change to the build pipeline to make sure ConfigMap is created:
- name: Deploy to Kubernetes
run: |
export IMAGE_TAG IMAGE_NAME
# Generate ConfigMap from source files
kubectl create configmap api-docs \
--from-file=shuffledDeck.yaml=src/main/resources/swagger/api-docs/shuffledDeck.yaml \
--from-file=swagger-ui.html=src/main/resources/swagger/api-docs/swagger-ui.html \
--from-file=health=src/main/resources/swagger/health \
-n ramblings \
--dry-run=client -o yaml | kubectl apply -f -
# Apply deployment with envsubst
envsubst < kubernetes/k8s-deployment.yaml | kubectl apply -f -
AI will quickly generate Swagger HTML - minor tweaks of paths have been needed.
Deploy.
Fix up the upstream
Changing the name of the service to http will break the upsteam which now needs be fixed:
curl -sS -X PUT \
-H "X-API-KEY: ${APISIX_ADMIN_KEY}" \
-H 'Content-Type: application/json' \
'http://127.0.0.1:9180/apisix/admin/upstreams/1' \
--data '{
"id": "1",
"type": "roundrobin",
"discovery_type": "kubernetes",
"service_name": "ramblings/ramblings-app:http",
"pass_host": "rewrite",
"upstream_host": "ramblings-app.ramblings.svc.cluster.local"
}'
curl -sS -X PUT \
-H "X-API-KEY: ${APISIX_ADMIN_KEY}" \
-H 'Content-Type: application/json' \
'http://127.0.0.1:9180/apisix/admin/routes/api-docs-html' \
--data '{
"id": "api-docs-html",
"uri": "/swagger-ui.html",
"upstream": {
"type": "roundrobin",
"scheme": "http",
"pass_host": "pass",
"nodes": {
"shuffled-deck-docs.ramblings.svc.cluster.local:80": 1
}
}
}'
curl -sS -X PUT \
-H "X-API-KEY: ${APISIX_ADMIN_KEY}" \
-H 'Content-Type: application/json' \
'http://127.0.0.1:9180/apisix/admin/routes/api-docs-yaml' \
--data '{
"id": "api-docs-yaml",
"uri": "/shuffledDeck.yaml",
"upstream": {
"type": "roundrobin",
"scheme": "http",
"pass_host": "pass",
"nodes": {
"shuffled-deck-docs.ramblings.svc.cluster.local:80": 1
}
}
}'
Resulting links
https://deck-api.api.kambur.ie/swagger-ui.html https://deck-api.api.kambur.ie/shuffledDeck.yaml