Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ Detailed instructions are enrolled in the README of each chart.
* [api7-control-plane](./charts/api7/README.md)
* [api7-gateway](./charts/gateway/README.md)
* [api7-ingress-controller](./charts/ingress-controller/README.md)
* [aisix](./charts/aisix/README.md)
13 changes: 13 additions & 0 deletions charts/aisix/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Patterns to ignore when building packages.
.DS_Store
.git/
.gitignore
.gitmodules
*.swp
*.bak
*.tmp
*.orig
*~
.vscode/
*.tmproj
.idea/
6 changes: 6 additions & 0 deletions charts/aisix/Chart.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
dependencies:
- name: etcd
repository: https://charts.bitnami.com/bitnami
version: 8.7.7
digest: sha256:c03ff5323e855335d94ce6cfce35745b84d03538dbb197e1a27520a7d69ea3ef
generated: "2026-04-15T17:14:56.064889296+08:00"
20 changes: 20 additions & 0 deletions charts/aisix/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: v2
name: aisix
description: A Helm chart for AISIX AI Gateway

type: application

version: 0.1.0

appVersion: "0.1.0"

maintainers:
- name: API7
email: support@api7.ai
url: https://api7.ai

dependencies:
- name: etcd
version: 8.7.7
repository: https://charts.bitnami.com/bitnami
condition: etcd.enabled
158 changes: 158 additions & 0 deletions charts/aisix/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
## AISIX AI Gateway

AISIX is an open-source, high-performance AI Gateway and LLM proxy.

This chart bootstraps AISIX on a Kubernetes cluster using [Helm](https://helm.sh).

## Prerequisites

* Kubernetes 1.21+
* Helm 3.7+

## Install

```sh
helm repo add api7 https://charts.api7.ai
helm repo update

helm install [RELEASE_NAME] api7/aisix
```

## Uninstall

```sh
helm delete [RELEASE_NAME]
```

## Connecting to API7 EE Control Plane

When using AISIX with an API7 EE control plane, you need to provide mTLS credentials
via environment variables: `API7_CONTROL_PLANE_ENDPOINTS`, `API7_GATEWAY_GROUP_ID`,
`API7_CONTROL_PLANE_CA`, `API7_CONTROL_PLANE_CERT`, and `API7_CONTROL_PLANE_KEY`.

> **Note:** The CA, cert, and key values are multi-line PEM strings. Use `--from-file`
> when creating the Secret to preserve line breaks correctly.

**Step 1: Save your certificates to files**

```sh
# Save CA certificate
cat > ca.pem << 'EOF'
-----BEGIN CERTIFICATE-----
<your-ca-certificate>
-----END CERTIFICATE-----
EOF

# Save client certificate
cat > cert.pem << 'EOF'
-----BEGIN CERTIFICATE-----
<your-client-certificate>
-----END CERTIFICATE-----
EOF

# Save client private key
cat > key.pem << 'EOF'
-----BEGIN PRIVATE KEY-----
<your-private-key>
-----END PRIVATE KEY-----
EOF
```

**Step 2: Create a Kubernetes Secret from the certificate files**

```sh
kubectl create secret generic aisix-cp-creds \
--from-file=API7_CONTROL_PLANE_CA=ca.pem \
--from-file=API7_CONTROL_PLANE_CERT=cert.pem \
--from-file=API7_CONTROL_PLANE_KEY=key.pem
```

**Step 3: Install the chart**

```sh
helm install my-aisix api7/aisix \
--set extraEnvVarsSecret=aisix-cp-creds \
--set extraEnvVars[0].name=API7_CONTROL_PLANE_ENDPOINTS \
--set 'extraEnvVars[0].value=["https://<dp-manager-host>:<port>"]' \
--set extraEnvVars[1].name=API7_GATEWAY_GROUP_ID \
--set extraEnvVars[1].value=<gateway-group-id> \
--set etcd.enabled=false
```

Replace `<dp-manager-host>:<port>` and `<gateway-group-id>` with the values from
your API7 EE console under **Gateway Group → Connection Info**.

## Parameters

## Values

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| admin | object | `{"annotations":{},"containerPort":3001,"enabled":true,"ingress":{"annotations":{},"enabled":false,"hosts":[{"host":"aisix-admin.local","paths":["/ui","/aisix/admin"]}],"tls":[]},"ip":"0.0.0.0","servicePort":3001,"type":"ClusterIP"}` | AISIX admin service settings (port 3001) — Admin API and UI |
| admin.containerPort | int | `3001` | Container port |
| admin.enabled | bool | `true` | Enable admin service |
| admin.ingress | object | `{"annotations":{},"enabled":false,"hosts":[{"host":"aisix-admin.local","paths":["/ui","/aisix/admin"]}],"tls":[]}` | Using ingress access AISIX admin service |
| admin.ingress.annotations | object | `{}` | Ingress annotations |
| admin.ip | string | `"0.0.0.0"` | which ip to listen on for the admin service |
| admin.servicePort | int | `3001` | Service port |
| admin.type | string | `"ClusterIP"` | admin service type |
| affinity | object | `{}` | Set affinity for deploy |
| autoscaling.enabled | bool | `false` | |
| autoscaling.maxReplicas | int | `10` | |
| autoscaling.minReplicas | int | `1` | |
| autoscaling.targetCPUUtilizationPercentage | int | `80` | |
| autoscaling.targetMemoryUtilizationPercentage | int | `80` | |
| autoscaling.version | string | `"v2"` | HPA version, the value is "v2" or "v2beta1", default "v2" |
| deployment.admin.adminKey | list | `[{"key":"changeme"}]` | Admin API key. Used to create an internal Secret when existingSecret is not set. WARNING: change this before deploying to production. |
| deployment.admin.existingSecret | string | `""` | Name of an existing Secret that contains an admin key field. If set, adminKey above is ignored and the key is read from the Secret. |
| deployment.admin.existingSecretKey | string | `"admin-key"` | Key inside the existing Secret that holds the admin key value |
| deployment.etcd.host | list | `["http://etcd.host:2379"]` | List of etcd hosts. Ignored when etcd.enabled is true (auto-constructed). |
| deployment.etcd.prefix | string | `"/aisix"` | Key prefix used by aisix in etcd |
| deployment.etcd.timeout | int | `30` | etcd request timeout in seconds |
| etcd | object | `{"auth":{"rbac":{"create":false,"rootPassword":""},"tls":{"certFilename":"","certKeyFilename":"","enabled":false,"existingSecret":"","sni":"","verify":false}},"enabled":false,"image":{"repository":"api7/etcd"},"replicaCount":3,"service":{"port":2379}}` | etcd subchart (bitnami/etcd) |
| etcd.auth.rbac.create | bool | `false` | No authentication by default. Enable RBAC (set create: true and configure rootPassword) for production or multi-tenant clusters to prevent unauthenticated etcd access. |
| etcd.auth.rbac.rootPassword | string | `""` | root password for etcd. Requires etcd.auth.rbac.create to be true. |
| etcd.auth.tls.certFilename | string | `""` | etcd client cert filename using in etcd.auth.tls.existingSecret |
| etcd.auth.tls.certKeyFilename | string | `""` | etcd client cert key filename using in etcd.auth.tls.existingSecret |
| etcd.auth.tls.enabled | bool | `false` | enable etcd client certificate |
| etcd.auth.tls.existingSecret | string | `""` | name of the secret contains etcd client cert |
| etcd.auth.tls.sni | string | `""` | specify the TLS Server Name Indication extension, the ETCD endpoint hostname will be used when this setting is unset. |
| etcd.auth.tls.verify | bool | `false` | whether to verify the etcd endpoint certificate when setup a TLS connection to etcd |
| etcd.enabled | bool | `false` | Install etcd as a subchart. Set false to use an external etcd. |
| extraEnvVars | list | `[]` | Additional environment variables |
| extraEnvVarsCM | string | `""` | |
| extraEnvVarsSecret | string | `""` | |
| extraInitContainers | list | `[]` | Additional init containers |
| extraVolumeMounts | list | `[]` | Additional volume mounts |
| extraVolumes | list | `[]` | Additional volumes |
| fullnameOverride | string | `""` | |
| gateway | object | `{"annotations":{},"containerPort":3000,"externalIPs":[],"externalTrafficPolicy":"Cluster","ingress":{"annotations":{},"enabled":false,"hosts":[{"host":"aisix.local","paths":["/"]}],"tls":[]},"ip":"0.0.0.0","nodePort":"","servicePort":3000,"type":"NodePort"}` | AISIX proxy service settings (port 3000) — user traffic |
| gateway.containerPort | int | `3000` | Container port |
| gateway.externalIPs | list | `[]` | IPs for which nodes in the cluster will also accept traffic for the service |
| gateway.externalTrafficPolicy | string | `"Cluster"` | Setting how the Service route external traffic |
| gateway.ingress | object | `{"annotations":{},"enabled":false,"hosts":[{"host":"aisix.local","paths":["/"]}],"tls":[]}` | Using ingress access AISIX proxy service |
| gateway.ingress.annotations | object | `{}` | Ingress annotations |
| gateway.ip | string | `"0.0.0.0"` | which ip to listen on for the proxy service |
| gateway.nodePort | string | `""` | Optional static nodePort (only relevant when type is NodePort) |
| gateway.servicePort | int | `3000` | Service port |
| gateway.type | string | `"NodePort"` | proxy service type |
| global.imagePullSecrets | list | `[]` | Global Docker registry secret names as an array |
| image.pullPolicy | string | `"IfNotPresent"` | AISIX image pull policy |
| image.repository | string | `"ghcr.io/api7/aisix"` | AISIX image repository |
| image.tag | string | `"0.1.0"` | AISIX image tag; overrides the chart appVersion |
| livenessProbe | object | `{}` | Kubernetes liveness probe override |
| nameOverride | string | `""` | |
| nodeSelector | object | `{}` | Node labels for pod assignment |
| podAnnotations | object | `{}` | Annotations to add to the pod |
| podLabels | object | `{}` | Labels to add to the pod |
| podSecurityContext | object | `{}` | Set the securityContext for AISIX pods |
| readinessProbe | object | `{}` | Kubernetes readiness probe override |
| replicaCount | int | `1` | Number of AISIX replicas |
| resources | object | `{}` | Set pod resource requests & limits |
| securityContext | object | `{}` | Set the securityContext for AISIX container |
| serviceAccount.annotations | object | `{}` | Annotations to add to the service account |
| serviceAccount.create | bool | `false` | Specifies whether a service account should be created |
| serviceAccount.name | string | `""` | The name of the service account to use. |
| timezone | string | `""` | timezone for the container, e.g. "UTC" or "Asia/Shanghai" |
| tolerations | list | `[]` | List of node taints to tolerate |
| updateStrategy | object | `{}` | |
87 changes: 87 additions & 0 deletions charts/aisix/README.md.gotmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
## AISIX AI Gateway

AISIX is an open-source, high-performance AI Gateway and LLM proxy.

This chart bootstraps AISIX on a Kubernetes cluster using [Helm](https://helm.sh).

## Prerequisites

* Kubernetes 1.21+
* Helm 3.7+

## Install

```sh
helm repo add api7 https://charts.api7.ai
helm repo update

helm install [RELEASE_NAME] api7/aisix
```

## Uninstall

```sh
helm delete [RELEASE_NAME]
```

## Connecting to API7 EE Control Plane

When using AISIX with an API7 EE control plane, you need to provide mTLS credentials
via environment variables: `API7_CONTROL_PLANE_ENDPOINTS`, `API7_GATEWAY_GROUP_ID`,
`API7_CONTROL_PLANE_CA`, `API7_CONTROL_PLANE_CERT`, and `API7_CONTROL_PLANE_KEY`.

> **Note:** The CA, cert, and key values are multi-line PEM strings. Use `--from-file`
> when creating the Secret to preserve line breaks correctly.

**Step 1: Save your certificates to files**

```sh
# Save CA certificate
cat > ca.pem << 'EOF'
-----BEGIN CERTIFICATE-----
<your-ca-certificate>
-----END CERTIFICATE-----
EOF

# Save client certificate
cat > cert.pem << 'EOF'
-----BEGIN CERTIFICATE-----
<your-client-certificate>
-----END CERTIFICATE-----
EOF

# Save client private key
cat > key.pem << 'EOF'
-----BEGIN PRIVATE KEY-----
<your-private-key>
-----END PRIVATE KEY-----
EOF
```

**Step 2: Create a Kubernetes Secret from the certificate files**

```sh
kubectl create secret generic aisix-cp-creds \
--from-file=API7_CONTROL_PLANE_CA=ca.pem \
--from-file=API7_CONTROL_PLANE_CERT=cert.pem \
--from-file=API7_CONTROL_PLANE_KEY=key.pem
```

**Step 3: Install the chart**

```sh
helm install my-aisix api7/aisix \
--set extraEnvVarsSecret=aisix-cp-creds \
--set extraEnvVars[0].name=API7_CONTROL_PLANE_ENDPOINTS \
--set 'extraEnvVars[0].value=["https://<dp-manager-host>:<port>"]' \
--set extraEnvVars[1].name=API7_GATEWAY_GROUP_ID \
--set extraEnvVars[1].value=<gateway-group-id> \
--set etcd.enabled=false
```

Replace `<dp-manager-host>:<port>` and `<gateway-group-id>` with the values from
your API7 EE console under **Gateway Group → Connection Info**.

## Parameters

{{ template "chart.valuesSection" . }}
Binary file added charts/aisix/charts/etcd-8.7.7.tgz
Binary file not shown.
37 changes: 37 additions & 0 deletions charts/aisix/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
AISIX has been installed. Check its status by running:
kubectl --namespace {{ .Release.Namespace }} get pods -l "app.kubernetes.io/name={{ include "aisix.name" . }}"

1. Get the Proxy API URL:
{{- if .Values.gateway.ingress.enabled }}
{{- range .Values.gateway.ingress.hosts }}
http{{ if $.Values.gateway.ingress.tls }}s{{ end }}://{{ .host }}
{{- end }}
{{- else if eq .Values.gateway.type "NodePort" }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "aisix.fullname" . }}-gateway)
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo "Proxy API: http://$NODE_IP:$NODE_PORT"
{{- else if eq .Values.gateway.type "LoadBalancer" }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "aisix.fullname" . }}-gateway --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo "Proxy API: http://$SERVICE_IP:{{ .Values.gateway.servicePort }}"
{{- else }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "aisix.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 3000:{{ .Values.gateway.containerPort }}
echo "Proxy API: http://127.0.0.1:3000"
{{- end }}

2. Get the Admin UI URL:
{{- if .Values.admin.enabled }}
{{- if .Values.admin.ingress.enabled }}
{{- range .Values.admin.ingress.hosts }}
http{{ if $.Values.admin.ingress.tls }}s{{ end }}://{{ .host }}/ui
{{- end }}
{{- else }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "aisix.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 3001:{{ .Values.admin.containerPort }}
echo "Admin UI: http://127.0.0.1:3001/ui"
echo "Admin API: http://127.0.0.1:3001/aisix/admin"
{{- end }}
{{- else }}
Admin service is disabled. Enable it with --set admin.enabled=true
{{- end }}
Loading
Loading