diff --git a/charts/apisix/README.md b/charts/apisix/README.md index f39508d3..5a0f8e23 100644 --- a/charts/apisix/README.md +++ b/charts/apisix/README.md @@ -132,6 +132,16 @@ The command removes all the Kubernetes components associated with the chart and | autoscaling.targetCPUUtilizationPercentage | int | `80` | | | autoscaling.targetMemoryUtilizationPercentage | int | `80` | | | autoscaling.version | string | `"v2"` | HPA version, the value is "v2" or "v2beta1", default "v2" | +| control.enabled | bool | `true` | Enable Control API | +| control.ingress | object | `{"annotations":{},"enabled":false,"hosts":[{"host":"apisix-control.local","paths":["/*"]}],"tls":[]}` | Using ingress access Apache APISIX Control service | +| control.ingress.annotations | object | `{}` | Ingress annotations | +| control.ingress.hosts | list | `[{"host":"apisix-control.local","paths":["/*"]}]` | Ingress Class Name className: "nginx" | +| control.service.annotations | object | `{}` | Control annotations | +| control.service.externalIPs | list | `[]` | IPs for which nodes in the cluster will also accept traffic for the servic | +| control.service.ip | string | `"127.0.0.1"` | which ip to listen on for Apache APISIX Control API | +| control.service.port | int | `9090` | which port to use for Apache APISIX Control API | +| control.service.servicePort | int | `9090` | Service port to use for Apache APISIX Control API | +| control.service.type | string | `"ClusterIP"` | Control service type | | dashboard.config.conf.etcd.endpoints | list | `["apisix-etcd:2379"]` | Supports defining multiple etcd host addresses for an etcd cluster | | dashboard.config.conf.etcd.password | string | `nil` | Specifies etcd basic auth password if enable etcd auth | | dashboard.config.conf.etcd.prefix | string | `"/apisix"` | apisix configurations prefix | diff --git a/charts/apisix/templates/_pod.tpl b/charts/apisix/templates/_pod.tpl new file mode 100644 index 00000000..4a574d41 --- /dev/null +++ b/charts/apisix/templates/_pod.tpl @@ -0,0 +1,272 @@ +{{- define "apisix.podTemplate" -}} +metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- with .Values.apisix.podAnnotations }} + {{ tpl (toYaml .) $ | nindent 4}} + {{- end }} + labels: + {{- include "apisix.selectorLabels" . | nindent 4 }} +spec: + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- range $.Values.global.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + serviceAccountName: {{ include "apisix.serviceAccountName" . }} + {{- with .Values.apisix.podSecurityContext }} + securityContext: + {{- . | toYaml | nindent 4 }} + {{- end }} + {{- with .Values.apisix.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + {{- with .Values.apisix.securityContext }} + securityContext: + {{- . | toYaml | nindent 8 }} + {{- end }} + image: "{{ .Values.apisix.image.repository }}:{{ default .Chart.AppVersion .Values.apisix.image.tag }}" + {{- if eq .Values.deployment.mode "standalone" }} + command: ["sh", "-c","ln -s /apisix-config/apisix.yaml /usr/local/apisix/conf/apisix.yaml && /docker-entrypoint.sh docker-start"] + {{- end }} + imagePullPolicy: {{ .Values.apisix.image.pullPolicy }} + env: + {{- if .Values.apisix.timezone }} + - name: TZ + value: {{ .Values.apisix.timezone }} + {{- end }} + {{- if .Values.apisix.extraEnvVars }} + {{- include "apisix.tplvalues.render" (dict "value" .Values.apisix.extraEnvVars "context" $) | nindent 8 }} + {{- end }} + + {{- if .Values.admin.credentials.secretName }} + - name: APISIX_ADMIN_KEY + valueFrom: + secretKeyRef: + name: {{ .Values.admin.credentials.secretName | quote }} + key: {{ include "apisix.admin.credentials.secretAdminKey" . }} + - name: APISIX_VIEWER_KEY + valueFrom: + secretKeyRef: + name: {{ .Values.admin.credentials.secretName | quote }} + key: {{ include "apisix.admin.credentials.secretViewerKey" . }} + {{- end }} + {{- if and (not .Values.etcd.enabled) .Values.etcd.existingSecret }} + - name: APISIX_ETCD_USER + valueFrom: + secretKeyRef: + name: {{ .Values.etcd.existingSecret | quote }} + key: {{ include "apisix.etcd.credentials.userKey" . }} + - name: APISIX_ETCD_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.etcd.existingSecret | quote }} + key: {{ include "apisix.etcd.credentials.passwordKey" . }} + {{- end }} + {{- if and .Values.etcd.enabled .Values.etcd.auth.rbac.existingSecret }} + - name: APISIX_ETCD_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.etcd.auth.rbac.existingSecret | quote }} + key: {{ include "apisix.etcd.auth.rbac.passwordKey" . }} + {{- end }} + + ports: + - name: http + containerPort: {{ .Values.gateway.http.containerPort }} + protocol: TCP + {{- range .Values.gateway.http.additionalContainerPorts }} + - name: http-{{ .port | toString }} + containerPort: {{ .port }} + protocol: TCP + {{- end }} + - name: tls + containerPort: {{ .Values.gateway.tls.containerPort }} + protocol: TCP + {{- range .Values.gateway.tls.additionalContainerPorts }} + - name: tls-{{ .port | toString }} + containerPort: {{ .port }} + protocol: TCP + {{- end }} + {{- if .Values.admin.enabled }} + - name: admin + containerPort: {{ .Values.admin.port }} + protocol: TCP + {{- end }} + {{- if .Values.control.enabled }} + - name: control + containerPort: {{ .Values.control.service.port }} + protocol: TCP + {{- end }} + {{- if .Values.serviceMonitor.enabled }} + - name: prometheus + containerPort: {{ .Values.serviceMonitor.containerPort }} + protocol: TCP + {{- end }} + {{- if and .Values.gateway.stream.enabled (or (gt (len .Values.gateway.stream.tcp) 0) (gt (len .Values.gateway.stream.udp) 0)) }} + {{- with .Values.gateway.stream }} + {{- if (gt (len .tcp) 0) }} + {{- range $index, $port := .tcp }} + - name: proxy-tcp-{{ $index | toString }} + {{- if kindIs "map" $port }} + containerPort: {{ splitList ":" ($port.addr | toString) | last }} + {{- else }} + containerPort: {{ $port }} + {{- end }} + protocol: TCP + {{- end }} + {{- end }} + {{- if (gt (len .udp) 0) }} + {{- range $index, $port := .udp }} + - name: proxy-udp-{{ $index | toString }} + containerPort: {{ $port }} + protocol: UDP + {{- end }} + {{- end }} + {{- end }} + {{- end }} + + {{- if ne .Values.deployment.role "control_plane" }} + readinessProbe: + {{- toYaml .Values.apisix.readinessProbe | nindent 8 }} + {{- end }} + lifecycle: + preStop: + exec: + command: + - /bin/sh + - -c + - "sleep 30" + volumeMounts: + {{- if eq .Values.deployment.mode "standalone" }} + - mountPath: /apisix-config + name: apisix-admin + {{- end }} + {{- if .Values.apisix.setIDFromPodUID }} + - mountPath: /usr/local/apisix/conf/apisix.uid + name: id + subPath: apisix.uid + {{- end }} + - mountPath: /usr/local/apisix/conf/config.yaml + name: apisix-config + subPath: config.yaml + {{- if and .Values.gateway.tls.enabled .Values.gateway.tls.existingCASecret }} + - mountPath: /usr/local/apisix/conf/ssl/{{ .Values.gateway.tls.certCAFilename }} + name: ssl + subPath: {{ .Values.gateway.tls.certCAFilename }} + {{- end }} + + {{- if .Values.etcd.auth.tls.enabled }} + - mountPath: /etcd-ssl + name: etcd-ssl + {{- end }} + {{- if .Values.customPlugins.enabled }} + {{- range $plugin := .Values.customPlugins.plugins }} + {{- range $mount := $plugin.configMap.mounts }} + {{- if ne $plugin.configMap.name "" }} + - mountPath: {{ $mount.path }} + name: plugin-{{ $plugin.configMap.name }} + subPath: {{ $mount.key }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.apisix.luaModuleHook.enabled }} + {{- range $mount := .Values.apisix.luaModuleHook.configMapRef.mounts }} + - mountPath: {{ $mount.path }} + name: lua-module-hook + subPath: {{ $mount.key }} + {{- end }} + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- toYaml .Values.extraVolumeMounts | nindent 8 }} + {{- end }} + resources: + {{- toYaml .Values.apisix.resources | nindent 8 }} + {{- if .Values.apisix.hostNetwork }} + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet + {{- end }} + hostNetwork: {{ .Values.apisix.hostNetwork }} + initContainers: + {{- if .Values.etcd.enabled }} + - name: wait-etcd + image: {{ .Values.initContainer.image }}:{{ .Values.initContainer.tag }} + {{- if .Values.etcd.fullnameOverride }} + command: ['sh', '-c', "until nc -z {{ .Values.etcd.fullnameOverride }} {{ .Values.etcd.service.port }}; do echo waiting for etcd `date`; sleep 2; done;"] + {{ else }} + command: ['sh', '-c', "until nc -z {{ .Release.Name }}-etcd.{{ .Release.Namespace }}.svc.{{ .Values.etcd.clusterDomain }} {{ .Values.etcd.service.port }}; do echo waiting for etcd `date`; sleep 2; done;"] + {{- end }} + {{- with .Values.initContainer.securityContext }} + securityContext: + {{- . | toYaml | nindent 8 }} + {{- end }} + + {{- end }} + {{- if .Values.extraInitContainers }} + {{- toYaml .Values.extraInitContainers | nindent 4 }} + {{- end }} + volumes: + {{- if eq .Values.deployment.mode "standalone" }} + - configMap: + name: apisix.yaml + name: apisix-admin + {{- end }} + - configMap: + name: {{ include "apisix.fullname" . }} + name: apisix-config + {{- if and .Values.gateway.tls.enabled .Values.gateway.tls.existingCASecret }} + - secret: + secretName: {{ .Values.gateway.tls.existingCASecret | quote }} + name: ssl + {{- end }} + {{- if .Values.etcd.auth.tls.enabled }} + - secret: + secretName: {{ .Values.etcd.auth.tls.existingSecret | quote }} + name: etcd-ssl + {{- end }} + {{- if .Values.apisix.setIDFromPodUID }} + - downwardAPI: + items: + - path: "apisix.uid" + fieldRef: + fieldPath: metadata.uid + name: id + {{- end }} + {{- if .Values.customPlugins.enabled }} + {{- range $plugin := .Values.customPlugins.plugins }} + {{- if ne $plugin.configMap.name "" }} + - name: plugin-{{ $plugin.configMap.name }} + configMap: + name: {{ $plugin.configMap.name }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.apisix.luaModuleHook.enabled }} + - name: lua-module-hook + configMap: + name: {{ .Values.apisix.luaModuleHook.configMapRef.name }} + {{- end }} + {{- if .Values.extraVolumes }} + {{- toYaml .Values.extraVolumes | nindent 4 }} + {{- end }} + {{- with .Values.apisix.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.apisix.affinity }} + affinity: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.apisix.tolerations }} + tolerations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.apisix.topologySpreadConstraints }} + topologySpreadConstraints: + {{- tpl (. | toYaml) $ | nindent 4 }} + {{- end }} +{{- end -}} diff --git a/charts/apisix/templates/configmap.yaml b/charts/apisix/templates/configmap.yaml index e3917c6b..3876c5de 100644 --- a/charts/apisix/templates/configmap.yaml +++ b/charts/apisix/templates/configmap.yaml @@ -59,6 +59,13 @@ data: extra_lua_path: {{ .Values.apisix.customPlugins.luaPath }};{{ .Values.apisix.luaModuleHook.luaPath }} {{- end }} + enable_control: {{ .Values.control.enabled }} + {{- if .Values.control.enabled }} + control: + ip: {{ default "127.0.0.1" .Values.control.service.ip }} + port: {{ default 9090 .Values.control.service.port }} + {{- end }} + {{- if .Values.apisix.luaModuleHook.enabled }} lua_module_hook: {{ .Values.apisix.luaModuleHook.hookPoint | quote }} {{- end }} diff --git a/charts/apisix/templates/ingress-control.yaml b/charts/apisix/templates/ingress-control.yaml new file mode 100644 index 00000000..a53c7f6c --- /dev/null +++ b/charts/apisix/templates/ingress-control.yaml @@ -0,0 +1,76 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +{{- if (and .Values.control.enabled .Values.control.ingress.enabled) -}} +{{- $fullName := include "apisix.fullname" . -}} +{{- $svcPort := .Values.control.servicePort -}} +{{- if and .Values.control.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.control.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.control.ingress.annotations "kubernetes.io/ingress.class" .Values.control.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.Version }} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.Version }} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }}-control + labels: + {{- include "apisix.labels" . | nindent 4 }} + {{- with .Values.control.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.control.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.control.ingress.className }} + {{- end }} + {{- if .Values.control.ingress.tls }} + tls: + {{- range .Values.control.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.control.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ . }} + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.Version }} + pathType: ImplementationSpecific + backend: + service: + name: {{ $fullName }}-control + port: + number: {{ $svcPort }} + {{- else }} + backend: + serviceName: {{ $fullName }}-control + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} diff --git a/charts/apisix/templates/service-control.yaml b/charts/apisix/templates/service-control.yaml new file mode 100644 index 00000000..0519aed8 --- /dev/null +++ b/charts/apisix/templates/service-control.yaml @@ -0,0 +1,58 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +{{ if (and .Values.apisix.enabled .Values.control.enabled) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "apisix.fullname" . }}-control + namespace: {{ .Release.Namespace }} + annotations: + {{- range $key, $value := .Values.control.service.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + labels: + {{- include "apisix.labels" . | nindent 4 }} + app.kubernetes.io/service: apisix-control +spec: + type: {{ .Values.control.service.type }} + {{- if eq .Values.control.service.type "LoadBalancer" }} + {{- if .Values.control.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.control.service.loadBalancerIP }} + {{- end }} + {{- if .Values.control.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.control.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} + {{- end }} + {{- end }} + {{- if gt (len .Values.control.service.externalIPs) 0 }} + externalIPs: + {{- range $ip := .Values.control.service.externalIPs }} + - {{ $ip }} + {{- end }} + {{- end }} + ports: + - name: apisix-control + port: {{ .Values.control.service.servicePort }} + targetPort: {{ .Values.control.service.port }} + {{- if (and (eq .Values.control.service.type "NodePort") (not (empty .Values.control.service.nodePort))) }} + nodePort: {{ .Values.control.service.nodePort }} + {{- end }} + protocol: TCP + selector: + {{- include "apisix.selectorLabels" . | nindent 4 }} +{{ end }} diff --git a/charts/apisix/values.yaml b/charts/apisix/values.yaml index 6c7cd9c9..ccd1d313 100644 --- a/charts/apisix/values.yaml +++ b/charts/apisix/values.yaml @@ -157,6 +157,49 @@ serviceAccount: rbac: create: false + +control: + # -- Enable Control API + enabled: true + service: + # -- Control annotations + annotations: {} + # -- Control service type + type: ClusterIP + # loadBalancerIP: a.b.c.d + # loadBalancerSourceRanges: + # - "143.231.0.0/16" + # -- IPs for which nodes in the cluster will also accept traffic for the servic + externalIPs: [] + + # -- NodePort (only if control.service.type is NodePort) + # nodePort: 32000 + + # -- which ip to listen on for Apache APISIX Control API + ip: "127.0.0.1" + # -- which port to use for Apache APISIX Control API + port: 9090 + # -- Service port to use for Apache APISIX Control API + servicePort: 9090 + # -- Using ingress access Apache APISIX Control service + ingress: + enabled: false + # -- Ingress annotations + annotations: + {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # -- Ingress Class Name + # className: "nginx" + hosts: + - host: apisix-control.local + paths: + - "/*" + tls: [] + # - secretName: apisix-tls + # hosts: + # - chart-example.local + service: # -- Apache APISIX service type for user access itself type: NodePort