Merge pull request #537 from samuelattwood/hashicorp

Adding Hashicorp Consul & Vault
pull/539/head
Samuel Attwood 2022-10-18 14:53:07 -04:00 committed by GitHub
commit 46b68d765e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
212 changed files with 22549 additions and 0 deletions

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,4 @@
.git/
.terraform/
bin/
test/

View File

@ -0,0 +1,35 @@
annotations:
artifacthub.io/images: |
- name: consul
image: hashicorp/consul:1.13.2
- name: consul-k8s-control-plane
image: hashicorp/consul-k8s-control-plane:0.49.0
- name: envoy
image: envoyproxy/envoy:v1.23.1
artifacthub.io/license: MPL-2.0
artifacthub.io/links: |
- name: Documentation
url: https://www.consul.io/docs/k8s
- name: hashicorp/consul
url: https://github.com/hashicorp/consul
- name: hashicorp/consul-k8s
url: https://github.com/hashicorp/consul-k8s
artifacthub.io/prerelease: "false"
artifacthub.io/signKey: |
fingerprint: C874011F0AB405110D02105534365D9472D7468F
url: https://keybase.io/hashicorp/pgp_keys.asc
catalog.cattle.io/certified: partner
catalog.cattle.io/display-name: Hashicorp Consul
catalog.cattle.io/kube-version: '>=1.21.0-0'
catalog.cattle.io/release-name: consul
apiVersion: v2
appVersion: 1.13.2
description: Official HashiCorp Consul Chart
home: https://www.consul.io
icon: https://raw.githubusercontent.com/hashicorp/consul-k8s/main/assets/icon.png
kubeVersion: '>=1.21.0-0'
name: consul
sources:
- https://github.com/hashicorp/consul
- https://github.com/hashicorp/consul-k8s
version: 0.49.0

View File

@ -0,0 +1,68 @@
# Consul on Kubernetes Helm Chart
---
**We're looking for feedback on how folks are using Consul on Kubernetes. Please fill out our brief [survey](https://hashicorp.sjc1.qualtrics.com/jfe/form/SV_4MANbw1BUku7YhL)!**
> **Warning**
> Please read the following issue to learn more about upcoming breaking changes that will be implemented by Q4 2022 for the default deployment of Consul on Kubernetes: [Enabling of service mesh by default and disabling of node-level client agents from Consul Service Mesh on Kubernetes and Catalog Sync](https://github.com/hashicorp/consul-k8s/issues/1438)
## Overview
This is the Official HashiCorp Helm chart for installing and configuring Consul on Kubernetes. This chart supports multiple use cases of Consul on Kubernetes, depending on the values provided.
For full documentation on this Helm chart along with all the ways you can use Consul with Kubernetes, please see the Consul and Kubernetes documentation.
> :warning: **Please note**: We take Consul's security and our users' trust very seriously. If
you believe you have found a security issue in Consul K8s, _please responsibly disclose_
by contacting us at [security@hashicorp.com](mailto:security@hashicorp.com).
## Features
* [**Consul Service Mesh**](https://www.consul.io/docs/k8s/connect):
Run Consul Service Mesh on Kubernetes. This feature
injects Envoy sidecars and registers your Pods with Consul.
* [**Catalog Sync**](https://www.consul.io/docs/k8s/service-sync):
Sync Consul services into first-class Kubernetes services and vice versa.
This enables Kubernetes to easily access external services and for
non-Kubernetes nodes to easily discover and access Kubernetes services.
### Prerequisites
* **Helm 3.2+** (Helm 2 is not supported)
* **Kubernetes 1.21-1.24** - This is the earliest version of Kubernetes tested.
It is possible that this chart works with earlier versions but it is
untested.
### Usage
Detailed installation instructions for Consul on Kubernetes are found [here](https://www.consul.io/docs/k8s/installation/overview).
1. Add the HashiCorp Helm Repository:
``` bash
$ helm repo add hashicorp https://helm.releases.hashicorp.com
```
2. Ensure you have access to the Consul Helm chart and you see the latest chart version listed.
If you have previously added the HashiCorp Helm repository, run `helm repo update`.
```bash
$ helm search repo hashicorp/consul
```
3. Now you're ready to install Consul! To install Consul with the default configuration using Helm 3.2 run the following command below.
This will create a `consul` Kubernetes namespace if not already present, and install Consul on the dedicated namespace.
```bash
$ helm install consul hashicorp/consul --set global.name=consul --create-namespace -n consul
```
Please see the many options supported in the `values.yaml`
file. These are also fully documented directly on the
[Consul website](https://www.consul.io/docs/platform/k8s/helm.html).
# Tutorials
You can find examples and complete tutorials on how to deploy Consul on
Kubernetes using Helm on the [HashiCorp Learn website](https://learn.hashicorp.com/consul).

View File

@ -0,0 +1,34 @@
#!/usr/bin/env bash
WD=$(dirname "$0")
WD=$(cd "$WD"; pwd)
set -eux
TEMPLATES="${WD}/../templates"
DASHBOARDS="${WD}/dashboards"
TMP=$(mktemp -d)
# create Prometheus template
helm template prometheus prometheus \
--repo https://prometheus-community.github.io/helm-charts \
--namespace "replace-me-namespace" \
--version 13.2.1 \
-f "${WD}/values/prometheus.yaml" \
> "${TEMPLATES}/prometheus.yaml"
# Find and replace `replace-me-namespace` with `{{ .Release.Namespace }}` in Prometheus template.
sed -i'.orig' 's/replace-me-namespace/{{ .Release.Namespace }}/g' "${TEMPLATES}/prometheus.yaml"
# Add a comment to the top of the template file mentioning that the file is auto-generated.
sed -i'.orig' '1i\
# This file is auto-generated, see addons/gen.sh
' "${TEMPLATES}/prometheus.yaml"
# Add `{{- if .Values.prometheus.enabled }} to the top of the Prometheus template to ensure it is only templated when enabled.
sed -i'.orig' '1i\
{{- if .Values.prometheus.enabled }}
' "${TEMPLATES}/prometheus.yaml"
# Add `{{- end }} to the bottom of the Prometheus template to ensure it is only templated when enabled (closes the `if` statement).
sed -i'.orig' -e '$a\
{{- end }}' "${TEMPLATES}/prometheus.yaml"
# Remove the `prometheus.yaml.orig` file that is created as a side-effect of the `sed` command on OS X.
rm "${TEMPLATES}/prometheus.yaml.orig"

View File

@ -0,0 +1,18 @@
# Disable non-essential components
alertmanager:
enabled: false
pushgateway:
enabled: false
kubeStateMetrics:
enabled: false
nodeExporter:
enabled: false
server:
podAnnotations:
"consul.hashicorp.com/connect-inject": "false"
persistentVolume:
enabled: false
readinessProbeInitialDelay: 0
# Speed up scraping a bit from the default
global:
scrape_interval: 15s

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -0,0 +1,21 @@
Thank you for installing HashiCorp Consul!
Your release is named {{ .Release.Name }}.
To learn more about the release, run:
$ helm status {{ .Release.Name }} {{- if .Release.Namespace }} --namespace {{ .Release.Namespace }}{{ end }}
$ helm get all {{ .Release.Name }} {{- if .Release.Namespace }} --namespace {{ .Release.Namespace }}{{ end }}
Consul on Kubernetes Documentation:
https://www.consul.io/docs/platform/k8s
Consul on Kubernetes CLI Reference:
https://www.consul.io/docs/k8s/k8s-cli
{{- if (and .Values.global.acls.manageSystemACLs (gt (len .Values.server.extraConfig) 3)) }}
Warning: Defining server extraConfig potentially disrupts the automatic ACL
bootstrapping required settings. This may cause future issues if
there are conflicts.
{{- end }}

View File

@ -0,0 +1,314 @@
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to
this (by the DNS naming spec). Supports the legacy fullnameOverride setting
as well as the global.name setting.
*/}}
{{- define "consul.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else if .Values.global.name -}}
{{- .Values.global.name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- define "consul.vaultSecretTemplate" -}}
|
{{ "{{" }}- with secret "{{ .secretName }}" -{{ "}}" }}
{{ "{{" }}- {{ printf ".Data.data.%s" .secretKey }} -{{ "}}" }}
{{ "{{" }}- end -{{ "}}" }}
{{- end -}}
{{- define "consul.vaultCATemplate" -}}
|
{{ "{{" }}- with secret "{{ .secretName }}" -{{ "}}" }}
{{ "{{" }}- .Data.certificate -{{ "}}" }}
{{ "{{" }}- end -{{ "}}" }}
{{- end -}}
{{- define "consul.serverTLSCATemplate" -}}
{{ include "consul.vaultCATemplate" .Values.global.tls.caCert }}
{{- end -}}
{{- define "consul.serverTLSCertTemplate" -}}
|
{{ "{{" }}- with secret "{{ .Values.server.serverCert.secretName }}" "{{ printf "common_name=server.%s.%s" .Values.global.datacenter .Values.global.domain }}"
"alt_names={{ include "consul.serverTLSAltNames" . }}" "ip_sans=127.0.0.1{{ include "consul.serverAdditionalIPSANs" . }}" -{{ "}}" }}
{{ "{{" }}- .Data.certificate -{{ "}}" }}
{{ "{{" }}- if .Data.ca_chain -{{ "}}" }}
{{ "{{" }}- $lastintermediatecertindex := len .Data.ca_chain | subtract 1 -{{ "}}" }}
{{ "{{" }} range $index, $cacert := .Data.ca_chain {{ "}}" }}
{{ "{{" }} if (lt $index $lastintermediatecertindex) {{ "}}" }}
{{ "{{" }} $cacert {{ "}}" }}
{{ "{{" }} end {{ "}}" }}
{{ "{{" }} end {{ "}}" }}
{{ "{{" }}- end -{{ "}}" }}
{{ "{{" }}- end -{{ "}}" }}
{{- end -}}
{{- define "consul.serverTLSKeyTemplate" -}}
|
{{ "{{" }}- with secret "{{ .Values.server.serverCert.secretName }}" "{{ printf "common_name=server.%s.%s" .Values.global.datacenter .Values.global.domain }}"
"alt_names={{ include "consul.serverTLSAltNames" . }}" "ip_sans=127.0.0.1{{ include "consul.serverAdditionalIPSANs" . }}" -{{ "}}" }}
{{ "{{" }}- .Data.private_key -{{ "}}" }}
{{ "{{" }}- end -{{ "}}" }}
{{- end -}}
{{- define "consul.connectInjectWebhookTLSCertTemplate" -}}
|
{{ "{{" }}- with secret "{{ .Values.global.secretsBackend.vault.connectInject.tlsCert.secretName }}" "{{- $name := include "consul.fullname" . -}}{{ printf "common_name=%s-connect-injector" $name }}"
"alt_names={{ include "consul.connectInjectorTLSAltNames" . }}" -{{ "}}" }}
{{ "{{" }}- .Data.certificate -{{ "}}" }}
{{ "{{" }}- end -{{ "}}" }}
{{- end -}}
{{- define "consul.connectInjectWebhookTLSKeyTemplate" -}}
|
{{ "{{" }}- with secret "{{ .Values.global.secretsBackend.vault.connectInject.tlsCert.secretName }}" "{{- $name := include "consul.fullname" . -}}{{ printf "common_name=%s-connect-injector" $name }}"
"alt_names={{ include "consul.connectInjectorTLSAltNames" . }}" -{{ "}}" }}
{{ "{{" }}- .Data.private_key -{{ "}}" }}
{{ "{{" }}- end -{{ "}}" }}
{{- end -}}
{{- define "consul.controllerWebhookTLSCertTemplate" -}}
|
{{ "{{" }}- with secret "{{ .Values.global.secretsBackend.vault.controller.tlsCert.secretName }}" "{{- $name := include "consul.fullname" . -}}{{ printf "common_name=%s-controller-webhook" $name }}"
"alt_names={{ include "consul.controllerWebhookTLSAltNames" . }}" -{{ "}}" }}
{{ "{{" }}- .Data.certificate -{{ "}}" }}
{{ "{{" }}- end -{{ "}}" }}
{{- end -}}
{{- define "consul.controllerWebhookTLSKeyTemplate" -}}
|
{{ "{{" }}- with secret "{{ .Values.global.secretsBackend.vault.controller.tlsCert.secretName }}" "{{- $name := include "consul.fullname" . -}}{{ printf "common_name=%s-controller-webhook" $name }}"
"alt_names={{ include "consul.controllerWebhookTLSAltNames" . }}" -{{ "}}" }}
{{ "{{" }}- .Data.private_key -{{ "}}" }}
{{ "{{" }}- end -{{ "}}" }}
{{- end -}}
{{- define "consul.serverTLSAltNames" -}}
{{- $name := include "consul.fullname" . -}}
{{- $ns := .Release.Namespace -}}
{{ printf "localhost,%s-server,*.%s-server,*.%s-server.%s,%s-server.%s,*.%s-server.%s.svc,%s-server.%s.svc,*.server.%s.%s" $name $name $name $ns $name $ns $name $ns $name $ns (.Values.global.datacenter ) (.Values.global.domain) }}{{ include "consul.serverAdditionalDNSSANs" . }}
{{- end -}}
{{- define "consul.serverAdditionalDNSSANs" -}}
{{- if .Values.global.tls -}}{{- if .Values.global.tls.serverAdditionalDNSSANs -}}{{- range $san := .Values.global.tls.serverAdditionalDNSSANs }},{{ $san }} {{- end -}}{{- end -}}{{- end -}}
{{- end -}}
{{- define "consul.serverAdditionalIPSANs" -}}
{{- if .Values.global.tls -}}{{- if .Values.global.tls.serverAdditionalIPSANs -}}{{- range $san := .Values.global.tls.serverAdditionalIPSANs }},{{ $san }} {{- end -}}{{- end -}}{{- end -}}
{{- end -}}
{{- define "consul.connectInjectorTLSAltNames" -}}
{{- $name := include "consul.fullname" . -}}
{{- $ns := .Release.Namespace -}}
{{ printf "%s-connect-injector,%s-connect-injector.%s,%s-connect-injector.%s.svc,%s-connect-injector.%s.svc.cluster.local" $name $name $ns $name $ns $name $ns}}
{{- end -}}
{{- define "consul.controllerWebhookTLSAltNames" -}}
{{- $name := include "consul.fullname" . -}}
{{- $ns := .Release.Namespace -}}
{{ printf "%s-controller-webhook,%s-controller-webhook.%s,%s-controller-webhook.%s.svc,%s-controller-webhook.%s.svc.cluster.local" $name $name $ns $name $ns $name $ns}}
{{- end -}}
{{- define "consul.vaultReplicationTokenTemplate" -}}
|
{{ "{{" }}- with secret "{{ .Values.global.acls.replicationToken.secretName }}" -{{ "}}" }}
{{ "{{" }}- {{ printf ".Data.data.%s" .Values.global.acls.replicationToken.secretKey }} -{{ "}}" }}
{{ "{{" }}- end -{{ "}}" }}
{{- end -}}
{{- define "consul.vaultReplicationTokenConfigTemplate" -}}
|
{{ "{{" }}- with secret "{{ .Values.global.acls.replicationToken.secretName }}" -{{ "}}" }}
acl { tokens { agent = "{{ "{{" }}- {{ printf ".Data.data.%s" .Values.global.acls.replicationToken.secretKey }} -{{ "}}" }}", replication = "{{ "{{" }}- {{ printf ".Data.data.%s" .Values.global.acls.replicationToken.secretKey }} -{{ "}}" }}" }}
{{ "{{" }}- end -{{ "}}" }}
{{- end -}}
{{- define "consul.vaultBootstrapTokenConfigTemplate" -}}
|
{{ "{{" }}- with secret "{{ .Values.global.acls.bootstrapToken.secretName }}" -{{ "}}" }}
acl { tokens { initial_management = "{{ "{{" }}- {{ printf ".Data.data.%s" .Values.global.acls.bootstrapToken.secretKey }} -{{ "}}" }}" }}
{{ "{{" }}- end -{{ "}}" }}
{{- end -}}
{{/*
Sets up the extra-from-values config file passed to consul and then uses sed to do any necessary
substitution for HOST_IP/POD_IP/HOSTNAME. Useful for dogstats telemetry. The output file
is passed to consul as a -config-file param on command line.
*/}}
{{- define "consul.extraconfig" -}}
cp /consul/config/extra-from-values.json /consul/extra-config/extra-from-values.json
[ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /consul/extra-config/extra-from-values.json
[ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /consul/extra-config/extra-from-values.json
[ -n "${HOSTNAME}" ] && sed -Ei "s|HOSTNAME|${HOSTNAME?}|g" /consul/extra-config/extra-from-values.json
{{- end -}}
{{/*
Sets up a list of recusor flags for Consul agents by iterating over the IPs of every nameserver
in /etc/resolv.conf and concatenating them into a string of arguments that can be passed directly
to the consul agent command.
*/}}
{{- define "consul.recursors" -}}
recursor_flags=""
for ip in $(cat /etc/resolv.conf | grep nameserver | cut -d' ' -f2)
do
recursor_flags="$recursor_flags -recursor=$ip"
done
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "consul.chart" -}}
{{- printf "%s-helm" .Chart.Name | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Expand the name of the chart.
*/}}
{{- define "consul.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Compute the maximum number of unavailable replicas for the PodDisruptionBudget.
This defaults to (n/2)-1 where n is the number of members of the server cluster.
Special case of replica equaling 3 and allowing a minor disruption of 1 otherwise
use the integer value
Add a special case for replicas=1, where it should default to 0 as well.
*/}}
{{- define "consul.pdb.maxUnavailable" -}}
{{- if eq (int .Values.server.replicas) 1 -}}
{{ 0 }}
{{- else if .Values.server.disruptionBudget.maxUnavailable -}}
{{ .Values.server.disruptionBudget.maxUnavailable -}}
{{- else -}}
{{- if eq (int .Values.server.replicas) 3 -}}
{{- 1 -}}
{{- else -}}
{{- sub (div (int .Values.server.replicas) 2) 1 -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- define "consul.pdb.connectInject.maxUnavailable" -}}
{{- if eq (int .Values.connectInject.replicas) 1 -}}
{{ 0 }}
{{- else if .Values.connectInject.disruptionBudget.maxUnavailable -}}
{{ .Values.connectInject.disruptionBudget.maxUnavailable -}}
{{- else -}}
{{- if eq (int .Values.connectInject.replicas) 3 -}}
{{- 1 -}}
{{- else -}}
{{- sub (div (int .Values.connectInject.replicas) 2) 1 -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Inject extra environment vars in the format key:value, if populated
*/}}
{{- define "consul.extraEnvironmentVars" -}}
{{- if .extraEnvironmentVars -}}
{{- range $key, $value := .extraEnvironmentVars }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Get Consul client CA to use when auto-encrypt is enabled.
This template is for an init container.
*/}}
{{- define "consul.getAutoEncryptClientCA" -}}
- name: get-auto-encrypt-client-ca
image: {{ .Values.global.imageK8S }}
command:
- "/bin/sh"
- "-ec"
- |
consul-k8s-control-plane get-consul-client-ca \
-output-file=/consul/tls/client/ca/tls.crt \
-consul-api-timeout={{ .Values.global.consulAPITimeout }} \
{{- if .Values.externalServers.enabled }}
{{- if and .Values.externalServers.enabled (not .Values.externalServers.hosts) }}{{ fail "externalServers.hosts must be set if externalServers.enabled is true" }}{{ end -}}
-server-addr={{ quote (first .Values.externalServers.hosts) }} \
-server-port={{ .Values.externalServers.httpsPort }} \
{{- if .Values.externalServers.tlsServerName }}
-tls-server-name={{ .Values.externalServers.tlsServerName }} \
{{- end }}
{{- else }}
-server-addr={{ template "consul.fullname" . }}-server \
-server-port=8501 \
{{- end }}
{{- if or (not .Values.externalServers.enabled) (and .Values.externalServers.enabled (not .Values.externalServers.useSystemRoots)) }}
{{- if .Values.global.secretsBackend.vault.enabled }}
-ca-file=/vault/secrets/serverca.crt
{{- else }}
-ca-file=/consul/tls/ca/tls.crt
{{- end }}
{{- end }}
volumeMounts:
{{- if not (and .Values.externalServers.enabled .Values.externalServers.useSystemRoots) }}
{{- if not .Values.global.secretsBackend.vault.enabled }}
- name: consul-ca-cert
mountPath: /consul/tls/ca
{{- end }}
{{- end }}
- name: consul-auto-encrypt-ca-cert
mountPath: /consul/tls/client/ca
resources:
requests:
memory: "50Mi"
cpu: "50m"
limits:
memory: "50Mi"
cpu: "50m"
{{- end -}}
{{/*
Fails when a reserved name is passed in. This should be used to test against
Consul namespaces and partition names.
This template accepts an array that contains two elements. The first element
is the name that's being checked and the second is the name of the values.yaml
key that's setting the name.
Usage: {{ template "consul.reservedNamesFailer" (list .Values.key "key") }}
*/}}
{{- define "consul.reservedNamesFailer" -}}
{{- $name := index . 0 -}}
{{- $key := index . 1 -}}
{{- if or (eq "system" $name) (eq "universal" $name) (eq "operator" $name) (eq "root" $name) }}
{{- fail (cat "The name" $name "set for key" $key "is reserved by Consul for future use." ) }}
{{- end }}
{{- end -}}
{{/*
Fails when at least one but not all of the following have been set:
- global.secretsBackend.vault.connectInjectRole
- global.secretsBackend.vault.connectInject.tlsCert.secretName
- global.secretsBackend.vault.connectInject.caCert.secretName
- global.secretsBackend.vault.controllerRole
- global.secretsBackend.vault.controller.tlsCert.secretName
- global.secretsBackend.vault.controller.caCert.secretName
The above values are needed in full to turn off web cert manager and allow
connect inject and controller to manage its own webhook certs.
Usage: {{ template "consul.validateVaultWebhookCertConfiguration" . }}
*/}}
{{- define "consul.validateVaultWebhookCertConfiguration" -}}
{{- if or .Values.global.secretsBackend.vault.connectInjectRole .Values.global.secretsBackend.vault.connectInject.tlsCert.secretName .Values.global.secretsBackend.vault.connectInject.caCert.secretName .Values.global.secretsBackend.vault.controllerRole .Values.global.secretsBackend.vault.controller.tlsCert.secretName .Values.global.secretsBackend.vault.controller.caCert.secretName}}
{{- if or (not .Values.global.secretsBackend.vault.connectInjectRole) (not .Values.global.secretsBackend.vault.connectInject.tlsCert.secretName) (not .Values.global.secretsBackend.vault.connectInject.caCert.secretName) (not .Values.global.secretsBackend.vault.controllerRole) (not .Values.global.secretsBackend.vault.controller.tlsCert.secretName) (not .Values.global.secretsBackend.vault.controller.caCert.secretName) }}
{{fail "When one of the following has been set, all must be set: global.secretsBackend.vault.connectInjectRole, global.secretsBackend.vault.connectInject.tlsCert.secretName, global.secretsBackend.vault.connectInject.caCert.secretName, global.secretsBackend.vault.controllerRole, global.secretsBackend.vault.controller.tlsCert.secretName, and global.secretsBackend.vault.controller.caCert.secretName."}}
{{ end }}
{{ end }}
{{- end -}}

View File

@ -0,0 +1,239 @@
{{- if .Values.apiGateway.enabled }}
# The ClusterRole to enable the API Gateway controller to access required api endpoints.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ template "consul.fullname" . }}-api-gateway-controller
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: api-gateway-controller
rules:
- apiGroups:
- api-gateway.consul.hashicorp.com
resources:
- gatewayclassconfigs
verbs:
- get
- list
- update
- watch
- apiGroups:
- api-gateway.consul.hashicorp.com
resources:
- gatewayclassconfigs/finalizers
verbs:
- update
- apiGroups:
- apps
resources:
- deployments
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- create
- get
- list
- update
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- configmaps/status
verbs:
- get
- patch
- update
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- ""
resources:
- services
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- create
- get
- list
- watch
- apiGroups:
- gateway.networking.k8s.io
resources:
- referencegrants
verbs:
- get
- list
- watch
- apiGroups:
- gateway.networking.k8s.io
resources:
- referencepolicies
verbs:
- get
- list
- watch
- apiGroups:
- gateway.networking.k8s.io
resources:
- gatewayclasses
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- gateway.networking.k8s.io
resources:
- gatewayclasses/finalizers
verbs:
- update
- apiGroups:
- gateway.networking.k8s.io
resources:
- gatewayclasses/status
verbs:
- get
- patch
- update
- apiGroups:
- gateway.networking.k8s.io
resources:
- gateways
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- gateway.networking.k8s.io
resources:
- gateways/finalizers
verbs:
- update
- apiGroups:
- gateway.networking.k8s.io
resources:
- gateways/status
verbs:
- get
- patch
- update
- apiGroups:
- gateway.networking.k8s.io
resources:
- httproutes
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- gateway.networking.k8s.io
resources:
- httproutes/finalizers
verbs:
- update
- apiGroups:
- gateway.networking.k8s.io
resources:
- httproutes/status
verbs:
- get
- patch
- update
- apiGroups:
- gateway.networking.k8s.io
resources:
- tcproutes
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- gateway.networking.k8s.io
resources:
- tcproutes/finalizers
verbs:
- update
- apiGroups:
- gateway.networking.k8s.io
resources:
- tcproutes/status
verbs:
- get
- patch
- update
{{- end }}

View File

@ -0,0 +1,20 @@
{{- if .Values.apiGateway.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ template "consul.fullname" . }}-api-gateway-controller
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: api-gateway-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ template "consul.fullname" . }}-api-gateway-controller
subjects:
- kind: ServiceAccount
name: {{ template "consul.fullname" . }}-api-gateway-controller
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@ -0,0 +1,238 @@
{{- if .Values.apiGateway.enabled }}
{{- if not .Values.client.grpc }}{{ fail "client.grpc must be true for api gateway" }}{{ end }}
{{- if not .Values.apiGateway.image}}{{ fail "apiGateway.image must be set to enable api gateway" }}{{ end }}
{{- if and .Values.global.adminPartitions.enabled (not .Values.global.enableConsulNamespaces) }}{{ fail "global.enableConsulNamespaces must be true if global.adminPartitions.enabled=true" }}{{ end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "consul.fullname" . }}-api-gateway-controller
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: api-gateway-controller
spec:
replicas: {{ .Values.apiGateway.controller.replicas }}
selector:
matchLabels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
release: {{ .Release.Name }}
component: api-gateway-controller
template:
metadata:
annotations:
consul.hashicorp.com/connect-inject: "false"
{{- if (and .Values.global.secretsBackend.vault.enabled .Values.global.tls.enabled) }}
"vault.hashicorp.com/agent-init-first": "true"
"vault.hashicorp.com/agent-inject": "true"
"vault.hashicorp.com/role": {{ .Values.global.secretsBackend.vault.consulCARole }}
"vault.hashicorp.com/agent-inject-secret-serverca.crt": {{ .Values.global.tls.caCert.secretName }}
"vault.hashicorp.com/agent-inject-template-serverca.crt": {{ template "consul.serverTLSCATemplate" . }}
{{- if .Values.global.secretsBackend.vault.agentAnnotations }}
{{ tpl .Values.global.secretsBackend.vault.agentAnnotations . | nindent 8 | trim }}
{{- end }}
{{- if and .Values.global.secretsBackend.vault.ca.secretName .Values.global.secretsBackend.vault.ca.secretKey }}
"vault.hashicorp.com/agent-extra-secret": "{{ .Values.global.secretsBackend.vault.ca.secretName }}"
"vault.hashicorp.com/ca-cert": "/vault/custom/{{ .Values.global.secretsBackend.vault.ca.secretKey }}"
{{- end }}
{{- end }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
release: {{ .Release.Name }}
component: api-gateway-controller
spec:
serviceAccountName: {{ template "consul.fullname" . }}-api-gateway-controller
containers:
- name: api-gateway-controller
image: {{ .Values.apiGateway.image }}
ports:
- containerPort: 9090
name: sds
protocol: TCP
env:
{{- if .Values.global.tls.enabled }}
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- end }}
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
{{- if .Values.global.acls.manageSystemACLs }}
- name: CONSUL_HTTP_TOKEN_FILE
value: "/consul/login/acl-token"
{{- end }}
- name: CONSUL_HTTP_ADDR
{{- if .Values.global.tls.enabled }}
value: https://$(HOST_IP):8501
{{- else }}
value: http://$(HOST_IP):8500
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
consul-api-gateway server \
-sds-server-host {{ template "consul.fullname" . }}-api-gateway-controller.{{ .Release.Namespace }}.svc \
-k8s-namespace {{ .Release.Namespace }} \
{{- if .Values.global.enableConsulNamespaces }}
{{- if .Values.connectInject.consulNamespaces.consulDestinationNamespace }}
-consul-destination-namespace={{ .Values.connectInject.consulNamespaces.consulDestinationNamespace }} \
{{- end }}
{{- if .Values.connectInject.consulNamespaces.mirroringK8S }}
-mirroring-k8s=true \
{{- if .Values.connectInject.consulNamespaces.mirroringK8SPrefix }}
-mirroring-k8s-prefix={{ .Values.connectInject.consulNamespaces.mirroringK8SPrefix }} \
{{- end }}
{{- end }}
{{- end }}
{{- if and .Values.global.federation.enabled .Values.global.federation.primaryDatacenter }}
-primary-datacenter={{ .Values.global.federation.primaryDatacenter }} \
{{- end }}
-log-level {{ default .Values.global.logLevel .Values.apiGateway.logLevel }} \
-log-json={{ .Values.global.logJSON }}
volumeMounts:
{{- if .Values.global.acls.manageSystemACLs }}
- name: consul-bin
mountPath: /consul-bin
{{- end }}
{{- if .Values.global.tls.enabled }}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
{{- else }}
- name: consul-ca-cert
{{- end }}
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
- mountPath: /consul/login
name: consul-data
readOnly: true
{{- if .Values.apiGateway.resources }}
resources:
{{- toYaml .Values.apiGateway.resources | nindent 12 }}
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
lifecycle:
preStop:
exec:
command: [ "/bin/sh", "-ec", "/consul-bin/consul logout" ]
{{- end }}
volumes:
{{- if .Values.global.acls.manageSystemACLs }}
- name: consul-bin
emptyDir: { }
{{- end }}
{{- if .Values.global.tls.enabled }}
{{- if not (and .Values.externalServers.enabled .Values.externalServers.useSystemRoots) }}
- name: consul-ca-cert
secret:
{{- if .Values.global.tls.caCert.secretName }}
secretName: {{ .Values.global.tls.caCert.secretName }}
{{- else }}
secretName: {{ template "consul.fullname" . }}-ca-cert
{{- end }}
items:
- key: {{ default "tls.crt" .Values.global.tls.caCert.secretKey }}
path: tls.crt
{{- end }}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
emptyDir:
medium: "Memory"
{{- end }}
{{- end }}
- name: consul-data
emptyDir:
medium: "Memory"
{{- if or .Values.global.acls.manageSystemACLs (and .Values.global.tls.enabled .Values.global.tls.enableAutoEncrypt) }}
initContainers:
{{- if .Values.global.acls.manageSystemACLs }}
- name: copy-consul-bin
image: {{ .Values.global.image | quote }}
command:
- cp
- /bin/consul
- /consul-bin/consul
volumeMounts:
- name: consul-bin
mountPath: /consul-bin
{{- if .Values.apiGateway.initCopyConsulContainer }}
{{- if .Values.apiGateway.initCopyConsulContainer.resources }}
resources: {{ toYaml .Values.apiGateway.initCopyConsulContainer.resources | nindent 12 }}
{{- end }}
{{- end }}
{{- end }}
{{- if (and .Values.global.tls.enabled .Values.global.tls.enableAutoEncrypt) }}
{{- include "consul.getAutoEncryptClientCA" . | nindent 6 }}
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
- name: api-gateway-controller-acl-init
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
{{- if .Values.global.tls.enabled }}
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- end }}
- name: CONSUL_HTTP_ADDR
{{- if .Values.global.tls.enabled }}
value: https://$(HOST_IP):8501
{{- else }}
value: http://$(HOST_IP):8500
{{- end }}
image: {{ .Values.global.imageK8S }}
volumeMounts:
- mountPath: /consul/login
name: consul-data
readOnly: false
{{- if .Values.global.tls.enabled }}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
{{- else }}
- name: consul-ca-cert
{{- end }}
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
consul-k8s-control-plane acl-init \
-component-name=api-gateway-controller \
{{- if and .Values.global.federation.enabled .Values.global.federation.primaryDatacenter }}
-acl-auth-method={{ template "consul.fullname" . }}-k8s-component-auth-method-{{ .Values.global.datacenter }} \
-primary-datacenter={{ .Values.global.federation.primaryDatacenter }} \
{{- else }}
-acl-auth-method={{ template "consul.fullname" . }}-k8s-component-auth-method \
{{- end }}
{{- if .Values.global.adminPartitions.enabled }}
-partition={{ .Values.global.adminPartitions.name }} \
{{- end }}
-consul-api-timeout={{ .Values.global.consulAPITimeout }} \
-log-level={{ default .Values.global.logLevel .Values.apiGateway.logLevel }} \
-log-json={{ .Values.global.logJSON }}
resources:
requests:
memory: "25Mi"
cpu: "50m"
limits:
memory: "25Mi"
cpu: "50m"
{{- end }}
{{- end }}
{{- if .Values.apiGateway.controller.priorityClassName }}
priorityClassName: {{ .Values.apiGateway.controller.priorityClassName | quote }}
{{- end }}
{{- if .Values.apiGateway.controller.nodeSelector }}
nodeSelector:
{{ tpl .Values.apiGateway.controller.nodeSelector . | indent 8 | trim }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,27 @@
{{- if .Values.apiGateway.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ template "consul.fullname" . }}-api-gateway-controller
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: api-gateway-controller
annotations:
{{- if .Values.apiGateway.controller.service.annotations }}
{{ tpl .Values.apiGateway.controller.service.annotations . | nindent 4 | trim }}
{{- end }}
spec:
ports:
- name: sds
port: 9090
protocol: TCP
targetPort: 9090
selector:
app: {{ template "consul.name" . }}
release: "{{ .Release.Name }}"
component: api-gateway-controller
{{- end }}

View File

@ -0,0 +1,23 @@
{{- if .Values.apiGateway.enabled }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "consul.fullname" . }}-api-gateway-controller
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: api-gateway-controller
{{- if .Values.apiGateway.serviceAccount.annotations }}
annotations:
{{ tpl .Values.apiGateway.serviceAccount.annotations . | nindent 4 | trim }}
{{- end }}
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- range . }}
- name: {{ .name }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,18 @@
{{- if (and .Values.apiGateway.enabled .Values.apiGateway.managedGatewayClass.enabled) }}
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: GatewayClass
metadata:
name: consul-api-gateway
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: api-gateway-controller
spec:
controllerName: hashicorp.com/consul-api-gateway-controller
parametersRef:
group: api-gateway.consul.hashicorp.com
kind: GatewayClassConfig
name: consul-api-gateway
{{- end }}

View File

@ -0,0 +1,50 @@
{{- if (and .Values.apiGateway.enabled .Values.apiGateway.managedGatewayClass.enabled) }}
apiVersion: api-gateway.consul.hashicorp.com/v1alpha1
kind: GatewayClassConfig
metadata:
name: consul-api-gateway
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: api-gateway
spec:
consul:
authentication:
{{- if .Values.global.acls.manageSystemACLs }}
managed: true
method: {{ template "consul.fullname" . }}-k8s-auth-method
{{- end }}
{{- if .Values.global.tls.enabled }}
scheme: https
{{- else }}
scheme: http
{{- end }}
ports:
grpc: 8502
{{- if .Values.global.tls.enabled }}
http: 8501
{{- else }}
http: 8500
{{- end }}
{{- with .Values.apiGateway.managedGatewayClass.deployment }}
deployment:
{{- toYaml . | nindent 4 }}
{{- end }}
image:
consulAPIGateway: {{ .Values.apiGateway.image }}
envoy: {{ .Values.global.imageEnvoy }}
{{- if .Values.apiGateway.nodeSelector }}
nodeSelector:
{{ tpl .Values.apiGateway.managedGatewayClass.nodeSelector . | indent 4 | trim }}
{{- end }}
{{- if .Values.apiGateway.managedGatewayClass.copyAnnotations.service }}
copyAnnotations:
service:
{{ tpl .Values.apiGateway.managedGatewayClass.copyAnnotations.service.annotations . | nindent 6 | trim }}
{{- end }}
serviceType: {{ .Values.apiGateway.managedGatewayClass.serviceType }}
useHostPorts: {{ .Values.apiGateway.managedGatewayClass.useHostPorts }}
logLevel: {{ default .Values.global.logLevel .Values.apiGateway.managedGatewayClass.logLevel }}
{{- end }}

View File

@ -0,0 +1,18 @@
{{- if .Values.global.acls.manageSystemACLs }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ template "consul.fullname" . }}-auth-method
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: auth-method
rules:
- apiGroups: [ "" ]
resources:
- serviceaccounts
verbs:
- get
{{- end }}

View File

@ -0,0 +1,39 @@
{{- if .Values.global.acls.manageSystemACLs }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ template "consul.fullname" . }}-authdelegator
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: auth-method
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: "system:auth-delegator"
subjects:
- kind: ServiceAccount
name: {{ template "consul.fullname" . }}-auth-method
namespace: {{ .Release.Namespace }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ template "consul.fullname" . }}-auth-method
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: auth-method
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ template "consul.fullname" . }}-auth-method
subjects:
- kind: ServiceAccount
name: {{ template "consul.fullname" . }}-auth-method
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@ -0,0 +1,16 @@
{{- if .Values.global.acls.manageSystemACLs }}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "consul.fullname" . }}-auth-method
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: auth-method
annotations:
kubernetes.io/service-account.name: {{ template "consul.fullname" . }}-auth-method
type: kubernetes.io/service-account-token
{{- end }}

View File

@ -0,0 +1,19 @@
{{- if .Values.global.acls.manageSystemACLs }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "consul.fullname" . }}-auth-method
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: auth-method
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- range . }}
- name: {{ .name }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,37 @@
{{- if (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }}
# ConfigMap with extra configuration specified directly to the chart
# for client agents only.
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "consul.fullname" . }}-client-config
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: client
data:
client.json: |-
{
{{- if and .Values.global.secretsBackend.vault.enabled }}
"auto_reload_config": true
{{- end }}
}
extra-from-values.json: |-
{{ tpl .Values.client.extraConfig . | trimAll "\"" | indent 4 }}
central-config.json: |-
{
"enable_central_service_config": true
}
{{- if .Values.connectInject.enabled }}
{{/* We set check_update_interval to 0s so that check output is immediately viewable
in the UI. */}}
config.json: |-
{
"check_update_interval": "0s"
}
{{- end }}
{{- end }}

View File

@ -0,0 +1,608 @@
{{- if .Values.global.imageK8s }}{{ fail "global.imageK8s is not a valid key, use global.imageK8S (note the capital 'S')" }}{{ end -}}
{{- if (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }}
{{- $serverEnabled := (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) -}}
{{- if (and .Values.global.adminPartitions.enabled $serverEnabled (ne .Values.global.adminPartitions.name "default"))}}{{ fail "global.adminPartitions.name has to be \"default\" in the server cluster" }}{{ end -}}
{{- if (and (not .Values.global.secretsBackend.vault.consulClientRole) .Values.global.secretsBackend.vault.enabled) }}{{ fail "global.secretsBackend.vault.consulClientRole must be provided if global.secretsBackend.vault.enabled=true." }}{{ end -}}
{{- if (and (and .Values.global.secretsBackend.vault.enabled .Values.global.tls.enabled) (not .Values.global.tls.caCert.secretName)) }}{{ fail "global.tls.caCert.secretName must be provided if global.tls.enabled=true and global.secretsBackend.vault.enabled=true." }}{{ end -}}
{{- if (and (and .Values.global.secretsBackend.vault.enabled .Values.global.tls.enabled) (not .Values.global.tls.enableAutoEncrypt)) }}{{ fail "global.tls.enableAutoEncrypt must be true if global.secretsBackend.vault.enabled=true and global.tls.enabled=true" }}{{ end -}}
{{- if (and (and .Values.global.secretsBackend.vault.enabled .Values.global.tls.enabled) (not .Values.global.secretsBackend.vault.consulCARole)) }}{{ fail "global.secretsBackend.vault.consulCARole must be provided if global.secretsBackend.vault.enabled=true and global.tls.enabled=true" }}{{ end -}}
{{- if and .Values.global.federation.enabled .Values.global.adminPartitions.enabled }}{{ fail "If global.federation.enabled is true, global.adminPartitions.enabled must be false because they are mutually exclusive" }}{{ end }}
{{- if (and .Values.global.enterpriseLicense.secretName (not .Values.global.enterpriseLicense.secretKey)) }}{{fail "enterpriseLicense.secretKey and secretName must both be specified." }}{{ end -}}
{{- if (and (not .Values.global.enterpriseLicense.secretName) .Values.global.enterpriseLicense.secretKey) }}{{fail "enterpriseLicense.secretKey and secretName must both be specified." }}{{ end -}}
{{- if and .Values.externalServers.enabled (not .Values.externalServers.hosts) }}{{ fail "externalServers.hosts must be set if externalServers.enabled is true" }}{{ end -}}
# DaemonSet to run the Consul clients on every node.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: {{ template "consul.fullname" . }}-client
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: client
spec:
{{- if .Values.client.updateStrategy }}
updateStrategy:
{{ tpl .Values.client.updateStrategy . | nindent 4 | trim }}
{{- end }}
selector:
matchLabels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
release: {{ .Release.Name }}
component: client
hasDNS: "true"
template:
metadata:
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
release: {{ .Release.Name }}
component: client
hasDNS: "true"
{{- if .Values.client.extraLabels }}
{{- toYaml .Values.client.extraLabels | nindent 8 }}
{{- end }}
annotations:
{{- if .Values.global.secretsBackend.vault.enabled }}
"vault.hashicorp.com/agent-inject": "true"
"vault.hashicorp.com/agent-init-first": "true"
"vault.hashicorp.com/role": "{{ .Values.global.secretsBackend.vault.consulClientRole }}"
{{- if and .Values.global.secretsBackend.vault.ca.secretName .Values.global.secretsBackend.vault.ca.secretKey }}
"vault.hashicorp.com/agent-extra-secret": "{{ .Values.global.secretsBackend.vault.ca.secretName }}"
"vault.hashicorp.com/ca-cert": "/vault/custom/{{ .Values.global.secretsBackend.vault.ca.secretKey }}"
{{- end }}
{{- if .Values.global.gossipEncryption.secretName }}
{{- with .Values.global.gossipEncryption }}
"vault.hashicorp.com/agent-inject-secret-gossip.txt": {{ .secretName }}
"vault.hashicorp.com/agent-inject-template-gossip.txt": {{ template "consul.vaultSecretTemplate" . }}
{{- end }}
{{- end }}
{{- if .Values.global.tls.enabled }}
"vault.hashicorp.com/agent-inject-secret-serverca.crt": {{ .Values.global.tls.caCert.secretName }}
"vault.hashicorp.com/agent-inject-template-serverca.crt": {{ template "consul.serverTLSCATemplate" . }}
{{- end }}
{{- if .Values.global.secretsBackend.vault.agentAnnotations }}
{{ tpl .Values.global.secretsBackend.vault.agentAnnotations . | nindent 8 | trim }}
{{- end }}
{{- if and .Values.global.enterpriseLicense.secretName (not .Values.global.acls.manageSystemACLs) }}
{{- with .Values.global.enterpriseLicense }}
"vault.hashicorp.com/agent-inject-secret-enterpriselicense.txt": "{{ .secretName }}"
"vault.hashicorp.com/agent-inject-template-enterpriselicense.txt": {{ template "consul.vaultSecretTemplate" . }}
{{- end }}
{{- end }}
{{- end }}
"consul.hashicorp.com/connect-inject": "false"
"consul.hashicorp.com/config-checksum": {{ include (print $.Template.BasePath "/client-config-configmap.yaml") . | sha256sum }}
{{- if .Values.client.annotations }}
{{- tpl .Values.client.annotations . | nindent 8 }}
{{- end }}
{{- if (and .Values.global.metrics.enabled .Values.global.metrics.enableAgentMetrics) }}
"prometheus.io/scrape": "true"
"prometheus.io/path": "/v1/agent/metrics"
"prometheus.io/port": "8500"
{{- end }}
spec:
{{- if .Values.client.affinity }}
affinity:
{{ tpl .Values.client.affinity . | nindent 8 | trim }}
{{- end }}
{{- if .Values.client.tolerations }}
tolerations:
{{ tpl .Values.client.tolerations . | nindent 8 | trim }}
{{- end }}
terminationGracePeriodSeconds: 10
serviceAccountName: {{ template "consul.fullname" . }}-client
{{- if not .Values.global.openshift.enabled }}
securityContext:
{{- toYaml .Values.client.securityContext | nindent 8 -}}
{{- end }}
{{- if .Values.client.priorityClassName }}
priorityClassName: {{ .Values.client.priorityClassName | quote }}
{{- end }}
{{- if .Values.client.dnsPolicy }}
dnsPolicy: {{ .Values.client.dnsPolicy }}
{{- end }}
{{- if .Values.client.hostNetwork }}
hostNetwork: {{ .Values.client.hostNetwork }}
{{- end }}
volumes:
- name: data
{{- if .Values.client.dataDirectoryHostPath }}
hostPath:
path: {{ .Values.client.dataDirectoryHostPath }}
type: DirectoryOrCreate
{{- else }}
emptyDir: {}
{{- end }}
- name: config
configMap:
name: {{ template "consul.fullname" . }}-client-config
- name: extra-config
emptyDir: {}
- name: consul-data
emptyDir:
medium: "Memory"
{{- if .Values.global.tls.enabled }}
{{- if not .Values.global.secretsBackend.vault.enabled }}
- name: consul-ca-cert
secret:
{{- if .Values.global.tls.caCert.secretName }}
secretName: {{ .Values.global.tls.caCert.secretName }}
{{- else }}
secretName: {{ template "consul.fullname" . }}-ca-cert
{{- end }}
items:
- key: {{ default "tls.crt" .Values.global.tls.caCert.secretKey }}
path: tls.crt
{{- end }}
{{- if (and (not .Values.global.secretsBackend.vault.enabled) (not .Values.global.tls.enableAutoEncrypt)) }}
- name: consul-ca-key
secret:
{{- if .Values.global.tls.caKey.secretName }}
secretName: {{ .Values.global.tls.caKey.secretName }}
{{- else }}
secretName: {{ template "consul.fullname" . }}-ca-key
{{- end }}
items:
- key: {{ default "tls.key" .Values.global.tls.caKey.secretKey }}
path: tls.key
- name: consul-client-cert
emptyDir:
# We're using tmpfs here so that
# client certs are not written to disk
medium: "Memory"
{{- end }}
{{- end }}
{{- range .Values.client.extraVolumes }}
- name: userconfig-{{ .name }}
{{ .type }}:
{{- if (eq .type "configMap") }}
name: {{ .name }}
{{- else if (eq .type "secret") }}
secretName: {{ .name }}
{{- end }}
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
- name: aclconfig
emptyDir: {}
{{- else }}
{{- if (and .Values.global.enterpriseLicense.secretName .Values.global.enterpriseLicense.secretKey .Values.global.enterpriseLicense.enableLicenseAutoload (not .Values.global.secretsBackend.vault.enabled)) }}
- name: consul-license
secret:
secretName: {{ .Values.global.enterpriseLicense.secretName }}
{{- end }}
{{- end }}
containers:
- name: consul
image: "{{ default .Values.global.image .Values.client.image }}"
{{- if .Values.global.acls.manageSystemACLs }}
lifecycle:
preStop:
exec:
command:
- "/bin/sh"
- "-ec"
- |
consul logout
{{- end }}
env:
{{- if .Values.global.acls.manageSystemACLs }}
- name: CONSUL_HTTP_TOKEN_FILE
value: "/consul/login/acl-token"
{{- end }}
- name: ADVERTISE_IP
valueFrom:
fieldRef:
{{- if .Values.client.exposeGossipPorts }}
{{- /* Clients will be exposed on their node's hostPort for external-to-k8s communication,
so they need to advertise their host ip instead of their pod ip. */}}
fieldPath: status.hostIP
{{- else }}
fieldPath: status.podIP
{{- end }}
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: NODE
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: CONSUL_DISABLE_PERM_MGMT
value: "true"
{{- if (or .Values.global.gossipEncryption.autoGenerate (and .Values.global.gossipEncryption.secretName .Values.global.gossipEncryption.secretKey)) }}
{{- if not .Values.global.secretsBackend.vault.enabled }}
- name: GOSSIP_KEY
valueFrom:
secretKeyRef:
{{- if .Values.global.gossipEncryption.autoGenerate }}
name: {{ template "consul.fullname" . }}-gossip-encryption-key
key: key
{{- else if (and .Values.global.gossipEncryption.secretName .Values.global.gossipEncryption.secretKey) }}
name: {{ .Values.global.gossipEncryption.secretName }}
key: {{ .Values.global.gossipEncryption.secretKey }}
{{- end }}
{{- end }}
{{- end }}
{{- if (and .Values.global.enterpriseLicense.secretName .Values.global.enterpriseLicense.secretKey .Values.global.enterpriseLicense.enableLicenseAutoload (not .Values.global.acls.manageSystemACLs)) }}
- name: CONSUL_LICENSE_PATH
{{- if .Values.global.secretsBackend.vault.enabled }}
value: /vault/secrets/enterpriselicense.txt
{{- else }}
value: /consul/license/{{ .Values.global.enterpriseLicense.secretKey }}
{{- end }}
{{- end }}
{{- if .Values.global.tls.enabled }}
- name: CONSUL_HTTP_ADDR
value: https://localhost:8501
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: CONSUL_HTTP_SSL_VERIFY
value: "false"
{{- else }}
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- end }}
{{- end }}
{{- include "consul.extraEnvironmentVars" .Values.client | nindent 12 }}
command:
- "/bin/sh"
- "-ec"
- |
CONSUL_FULLNAME="{{template "consul.fullname" . }}"
{{- if and .Values.global.secretsBackend.vault.enabled .Values.global.gossipEncryption.secretName }}
GOSSIP_KEY=`cat /vault/secrets/gossip.txt`
{{- end }}
{{- if (and .Values.dns.enabled .Values.dns.enableRedirection) }}
{{ template "consul.recursors" }}
{{- end }}
{{ template "consul.extraconfig" }}
exec /usr/local/bin/docker-entrypoint.sh consul agent \
-node="${NODE}" \
-advertise="${ADVERTISE_IP}" \
-bind=0.0.0.0 \
-client=0.0.0.0 \
{{- range $k, $v := .Values.client.nodeMeta }}
-node-meta={{ $k }}:{{ $v }} \
{{- end }}
-hcl='leave_on_terminate = true' \
{{- if .Values.global.tls.enabled }}
{{- if .Values.global.peering.enabled }}
{{- if .Values.global.secretsBackend.vault.enabled }}
-hcl='tls { defaults { ca_file = "/vault/secrets/serverca.crt" }}' \
{{- else }}
-hcl='tls { defaults { ca_file = "/consul/tls/ca/tls.crt" }}' \
{{- end }}
{{- if .Values.global.tls.enableAutoEncrypt }}
-hcl='auto_encrypt = {tls = true}' \
-hcl="auto_encrypt = {ip_san = [\"$HOST_IP\",\"$POD_IP\"]}" \
-hcl='tls { grpc { use_auto_cert = true } }' \
{{- else }}
-hcl='tls { defaults { cert_file = "/consul/tls/client/tls.crt" }}' \
-hcl='tls { defaults { key_file = "/consul/tls/client/tls.key" }}' \
{{- end }}
{{- if .Values.global.tls.verify }}
-hcl='tls { defaults { verify_outgoing = true }}' \
{{- if not .Values.global.tls.enableAutoEncrypt }}
-hcl='tls { internal_rpc { verify_incoming = true }}' \
-hcl='tls { internal_rpc { verify_server_hostname = true }}' \
{{- end }}
{{- end }}
-hcl='ports { https = 8501 }' \
{{- if .Values.global.tls.httpsOnly }}
-hcl='ports { http = -1 }' \
{{- end }}
{{- else}}
{{- if .Values.global.secretsBackend.vault.enabled }}
-hcl='ca_file = "/vault/secrets/serverca.crt"' \
{{- else }}
-hcl='ca_file = "/consul/tls/ca/tls.crt"' \
{{- end }}
{{- if .Values.global.tls.enableAutoEncrypt }}
-hcl='auto_encrypt = {tls = true}' \
-hcl="auto_encrypt = {ip_san = [\"$HOST_IP\",\"$POD_IP\"]}" \
{{- else }}
-hcl='cert_file = "/consul/tls/client/tls.crt"' \
-hcl='key_file = "/consul/tls/client/tls.key"' \
{{- end }}
{{- if .Values.global.tls.verify }}
-hcl='verify_outgoing = true' \
{{- if not .Values.global.tls.enableAutoEncrypt }}
-hcl='verify_incoming_rpc = true' \
-hcl='verify_server_hostname = true' \
{{- end }}
{{- end }}
-hcl='ports { https = 8501 }' \
{{- if .Values.global.tls.httpsOnly }}
-hcl='ports { http = -1 }' \
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.client.grpc }}
-hcl='ports { grpc = 8502 }' \
{{- end }}
{{- if (and .Values.global.metrics.enabled .Values.global.metrics.enableAgentMetrics) }}
-hcl='telemetry { prometheus_retention_time = "{{ .Values.global.metrics.agentMetricsRetentionTime }}" }' \
{{- end }}
{{- if .Values.global.adminPartitions.enabled }}
-hcl='partition = "{{ .Values.global.adminPartitions.name }}"' \
{{- end }}
-config-dir=/consul/config \
{{- if .Values.global.acls.manageSystemACLs }}
-config-dir=/consul/aclconfig \
{{- end }}
{{- /* Always include the extraVolumes at the end so that users can
override other Consul settings. The last -config-dir takes
precedence. */}}
{{- range .Values.client.extraVolumes }}
{{- if .load }}
-config-dir=/consul/userconfig/{{ .name }} \
{{- end }}
{{- end }}
-datacenter={{ .Values.global.datacenter }} \
-data-dir=/consul/data \
{{- if (or .Values.global.gossipEncryption.autoGenerate (and .Values.global.gossipEncryption.secretName .Values.global.gossipEncryption.secretKey)) }}
-encrypt="${GOSSIP_KEY}" \
{{- end }}
{{- if .Values.client.join }}
{{- range $value := .Values.client.join }}
-retry-join={{ quote $value }} \
{{- end }}
{{- else }}
{{- if .Values.server.enabled }}
{{- $serverSerfLANPort := .Values.server.ports.serflan.port -}}
{{- range $index := until (.Values.server.replicas | int) }}
-retry-join="${CONSUL_FULLNAME}-server-{{ $index }}.${CONSUL_FULLNAME}-server.${NAMESPACE}.svc:{{ $serverSerfLANPort }}" \
{{- end }}
{{- end }}
{{- end }}
{{- range $value := .Values.global.recursors }}
-recursor={{ quote $value }} \
{{- end }}
{{- if (and .Values.dns.enabled .Values.dns.enableRedirection) }}
$recursor_flags \
{{- end }}
-config-file=/consul/extra-config/extra-from-values.json \
-domain={{ .Values.global.domain }}
volumeMounts:
- name: data
mountPath: /consul/data
- name: config
mountPath: /consul/config
- name: extra-config
mountPath: /consul/extra-config
- mountPath: /consul/login
name: consul-data
readOnly: true
{{- if .Values.global.tls.enabled }}
{{- if not .Values.global.secretsBackend.vault.enabled }}
- name: consul-ca-cert
mountPath: /consul/tls/ca
readOnly: true
{{- if not .Values.global.tls.enableAutoEncrypt }}
- name: consul-client-cert
mountPath: /consul/tls/client
readOnly: true
{{- end }}
{{- end }}
{{- end }}
{{- range .Values.client.extraVolumes }}
- name: userconfig-{{ .name }}
readOnly: true
mountPath: /consul/userconfig/{{ .name }}
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
- name: aclconfig
mountPath: /consul/aclconfig
{{- else }}
{{- if (and .Values.global.enterpriseLicense.secretName .Values.global.enterpriseLicense.secretKey .Values.global.enterpriseLicense.enableLicenseAutoload (not .Values.global.secretsBackend.vault.enabled)) }}
- name: consul-license
mountPath: /consul/license
readOnly: true
{{- end }}
{{- end }}
ports:
{{- if (or (not .Values.global.tls.enabled) (not .Values.global.tls.httpsOnly)) }}
- containerPort: 8500
hostPort: 8500
name: http
{{- end }}
{{- if .Values.global.tls.enabled }}
- containerPort: 8501
hostPort: 8501
name: https
{{- end }}
- containerPort: 8502
hostPort: 8502
name: grpc
- containerPort: 8301
{{- if .Values.client.exposeGossipPorts }}
hostPort: 8301
{{- end }}
protocol: "TCP"
name: serflan-tcp
- containerPort: 8301
{{- if .Values.client.exposeGossipPorts }}
hostPort: 8301
{{- end }}
protocol: "UDP"
name: serflan-udp
- containerPort: 8600
name: dns-tcp
protocol: "TCP"
- containerPort: 8600
name: dns-udp
protocol: "UDP"
readinessProbe:
# NOTE(mitchellh): when our HTTP status endpoints support the
# proper status codes, we should switch to that. This is temporary.
exec:
command:
- "/bin/sh"
- "-ec"
- |
{{- if .Values.global.tls.enabled }}
curl \
-k \
https://127.0.0.1:8501/v1/status/leader \
{{- else }}
curl http://127.0.0.1:8500/v1/status/leader \
{{- end }}
2>/dev/null | grep -E '".+"'
{{- if .Values.client.resources }}
resources:
{{- if eq (typeOf .Values.client.resources) "string" }}
{{ tpl .Values.client.resources . | nindent 12 | trim }}
{{- else }}
{{- toYaml .Values.client.resources | nindent 12 }}
{{- end }}
{{- end }}
{{- if not .Values.global.openshift.enabled }}
securityContext:
{{- toYaml .Values.client.containerSecurityContext.client | nindent 12 }}
{{- end }}
{{- if .Values.client.extraContainers }}
{{ toYaml .Values.client.extraContainers | nindent 8 }}
{{- end }}
{{- if (or .Values.global.acls.manageSystemACLs (and .Values.global.tls.enabled (not .Values.global.tls.enableAutoEncrypt))) }}
initContainers:
{{- if .Values.global.acls.manageSystemACLs }}
- name: client-acl-init
image: {{ .Values.global.imageK8S }}
env:
- name: CONSUL_HTTP_ADDR
{{- if .Values.global.tls.enabled }}
value: https://{{ template "consul.fullname" . }}-server.{{ .Release.Namespace }}.svc:8501
{{- else }}
value: http://{{ template "consul.fullname" . }}-server.{{ .Release.Namespace }}.svc:8500
{{- end }}
{{- if (and .Values.global.tls.enabled (not .Values.externalServers.useSystemRoots)) }}
- name: CONSUL_CACERT
{{- if .Values.global.secretsBackend.vault.enabled }}
value: "/vault/secrets/serverca.crt"
{{- else }}
value: "/consul/tls/ca/tls.crt"
{{- end }}
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
consul-k8s-control-plane acl-init \
-component-name=client \
-acl-auth-method="{{ template "consul.fullname" . }}-k8s-component-auth-method" \
{{- if .Values.global.adminPartitions.enabled }}
-partition={{ .Values.global.adminPartitions.name }} \
{{- end }}
-log-level={{ default .Values.global.logLevel .Values.client.logLevel }} \
-log-json={{ .Values.global.logJSON }} \
{{- if .Values.externalServers.enabled }}
{{- if .Values.global.tls.enabled }}
-use-https \
{{- end }}
{{- range .Values.externalServers.hosts }}
-server-address={{ quote . }} \
{{- end }}
-server-port={{ .Values.externalServers.httpsPort }} \
{{- if .Values.externalServers.tlsServerName }}
-tls-server-name={{ .Values.externalServers.tlsServerName }} \
{{- end }}
{{- end }}
-consul-api-timeout={{ .Values.global.consulAPITimeout }} \
-init-type="client"
volumeMounts:
- name: aclconfig
mountPath: /consul/aclconfig
- mountPath: /consul/login
name: consul-data
readOnly: false
{{- if (and .Values.global.tls.enabled (not .Values.global.secretsBackend.vault.enabled) (not .Values.externalServers.useSystemRoots)) }}
- name: consul-ca-cert
mountPath: /consul/tls/ca
readOnly: false
{{- end }}
resources:
requests:
memory: "25Mi"
cpu: "50m"
limits:
memory: "25Mi"
cpu: "50m"
{{- if not .Values.global.openshift.enabled }}
securityContext:
{{- toYaml .Values.client.containerSecurityContext.aclInit | nindent 10 }}
{{- end }}
{{- end }}
{{- if and .Values.global.tls.enabled (not .Values.global.tls.enableAutoEncrypt) }}
- name: client-tls-init
image: "{{ default .Values.global.image .Values.client.image }}"
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
command:
- "/bin/sh"
- "-ec"
- |
cd /consul/tls/client
consul tls cert create -client \
-additional-ipaddress=${HOST_IP} \
-additional-ipaddress=${POD_IP} \
-dc={{ .Values.global.datacenter }} \
-domain={{ .Values.global.domain }} \
-ca=/consul/tls/ca/cert/tls.crt \
-key=/consul/tls/ca/key/tls.key
mv {{ .Values.global.datacenter }}-client-{{ .Values.global.domain }}-0.pem tls.crt
mv {{ .Values.global.datacenter }}-client-{{ .Values.global.domain }}-0-key.pem tls.key
volumeMounts:
{{- if not .Values.global.secretsBackend.vault.enabled }}
- name: consul-client-cert
mountPath: /consul/tls/client
- name: consul-ca-cert
mountPath: /consul/tls/ca/cert
readOnly: true
- name: consul-ca-key
mountPath: /consul/tls/ca/key
readOnly: true
{{- end }}
resources:
requests:
memory: "50Mi"
cpu: "50m"
limits:
memory: "50Mi"
cpu: "50m"
{{- if not .Values.global.openshift.enabled }}
securityContext:
{{- toYaml .Values.client.containerSecurityContext.tlsInit | nindent 10 }}
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.client.nodeSelector }}
nodeSelector:
{{ tpl .Values.client.nodeSelector . | indent 8 | trim }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,76 @@
{{- if (and .Values.global.enablePodSecurityPolicies (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled))) }}
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: {{ template "consul.fullname" . }}-client
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: client
spec:
privileged: false
# Required to prevent escalations to root.
allowPrivilegeEscalation: false
# This is redundant with non-root + disallow privilege escalation,
# but we can provide it for defense in depth.
requiredDropCapabilities:
- ALL
# Allow core volume types.
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
{{- if .Values.client.dataDirectoryHostPath }}
- 'hostPath'
{{- end }}
{{- if .Values.client.hostNetwork }}
hostNetwork: {{ .Values.client.hostNetwork }}
{{- else }}
hostNetwork: false
{{- end }}
hostPorts:
{{- if (not (and .Values.global.tls.enabled .Values.global.tls.httpsOnly)) }}
# HTTP Port
- min: 8500
max: 8500
{{- end }}
{{- if .Values.global.tls.enabled }}
# HTTPS port
- min: 8501
max: 8501
{{- end }}
{{- if .Values.client.grpc }}
# gRPC Port
- min: 8502
max: 8502
{{- end }}
{{- if (or .Values.client.exposeGossipPorts .Values.client.hostNetwork) }}
- min: 8301
max: 8301
{{- end }}
{{- if .Values.client.hostNetwork }}
- min: 8600
max: 8600
{{- end }}
hostIPC: false
hostPID: false
runAsUser:
rule: 'RunAsAny'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'
readOnlyRootFilesystem: false
{{- if .Values.client.dataDirectoryHostPath }}
allowedHostPaths:
- pathPrefix: {{ .Values.client.dataDirectoryHostPath | quote }}
readOnly: false
{{- end }}
{{- end }}

View File

@ -0,0 +1,43 @@
{{- if (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ template "consul.fullname" . }}-client
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: client
{{- if (or .Values.global.acls.manageSystemACLs .Values.global.enablePodSecurityPolicies .Values.global.openshift.enabled) }}
rules:
{{- if .Values.global.enablePodSecurityPolicies }}
- apiGroups: ["policy"]
resources: ["podsecuritypolicies"]
resourceNames:
- {{ template "consul.fullname" . }}-client
verbs:
- use
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
- apiGroups: [""]
resources:
- secrets
resourceNames:
- {{ template "consul.fullname" . }}-client-acl-token
verbs:
- get
{{- end }}
{{- if .Values.global.openshift.enabled}}
- apiGroups: ["security.openshift.io"]
resources: ["securitycontextconstraints"]
resourceNames:
- {{ template "consul.fullname" . }}-client
verbs:
- use
{{- end}}
{{- else}}
rules: []
{{- end }}
{{- end }}

View File

@ -0,0 +1,20 @@
{{- if (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ template "consul.fullname" . }}-client
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: client
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ template "consul.fullname" . }}-client
subjects:
- kind: ServiceAccount
name: {{ template "consul.fullname" . }}-client
{{- end }}

View File

@ -0,0 +1,56 @@
{{- if (and .Values.global.openshift.enabled (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled))) }}
apiVersion: security.openshift.io/v1
kind: SecurityContextConstraints
metadata:
name: {{ template "consul.fullname" . }}-client
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: client
annotations:
kubernetes.io/description: {{ template "consul.fullname" . }}-client are the security context constraints required
to run the consul client.
{{- if .Values.client.dataDirectoryHostPath }}
allowHostDirVolumePlugin: true
{{- else }}
allowHostDirVolumePlugin: false
{{- end}}
allowHostIPC: false
allowHostNetwork: {{ .Values.client.hostNetwork }}
allowHostPID: false
allowHostPorts: true
allowPrivilegeEscalation: true
allowPrivilegedContainer: false
allowedCapabilities: null
defaultAddCapabilities: null
fsGroup:
type: MustRunAs
groups: []
priority: null
readOnlyRootFilesystem: false
requiredDropCapabilities:
- KILL
- MKNOD
- SETUID
- SETGID
runAsUser:
type: MustRunAsRange
seLinuxContext:
type: MustRunAs
supplementalGroups:
type: MustRunAs
users: []
volumes:
- configMap
- downwardAPI
- emptyDir
- persistentVolumeClaim
- projected
- secret
{{- if .Values.client.dataDirectoryHostPath }}
- hostPath
{{- end }}
{{- end}}

View File

@ -0,0 +1,23 @@
{{- if (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "consul.fullname" . }}-client
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: client
{{- if .Values.client.serviceAccount.annotations }}
annotations:
{{ tpl .Values.client.serviceAccount.annotations . | nindent 4 | trim }}
{{- end }}
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- range . }}
- name: {{ .name }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,281 @@
{{- if (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }}
{{- if or (and .Values.client.snapshotAgent.configSecret.secretName (not .Values.client.snapshotAgent.configSecret.secretKey)) (and (not .Values.client.snapshotAgent.configSecret.secretName) .Values.client.snapshotAgent.configSecret.secretKey) }}{{fail "client.snapshotAgent.configSecret.secretKey and client.snapshotAgent.configSecret.secretName must both be specified." }}{{ end -}}
{{- if .Values.client.snapshotAgent.enabled }}
{{- if or (and .Values.client.snapshotAgent.configSecret.secretName (not .Values.client.snapshotAgent.configSecret.secretKey)) (and (not .Values.client.snapshotAgent.configSecret.secretName) .Values.client.snapshotAgent.configSecret.secretKey) }}{{fail "client.snapshotAgent.configSecret.secretKey and client.snapshotAgent.configSecret.secretName must both be specified." }}{{ end -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "consul.fullname" . }}-snapshot-agent
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: client-snapshot-agent
spec:
replicas: {{ .Values.client.snapshotAgent.replicas }}
selector:
matchLabels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
release: {{ .Release.Name }}
component: client-snapshot-agent
template:
metadata:
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
release: {{ .Release.Name }}
component: client-snapshot-agent
annotations:
"consul.hashicorp.com/connect-inject": "false"
{{- if .Values.global.secretsBackend.vault.enabled }}
{{- if .Values.client.snapshotAgent.configSecret.secretName }}
"vault.hashicorp.com/role": {{ .Values.global.secretsBackend.vault.consulSnapshotAgentRole }}
{{- else if and .Values.global.tls.enabled }}
"vault.hashicorp.com/role": {{ .Values.global.secretsBackend.vault.consulCARole }}
{{- end }}
{{- if .Values.global.tls.enabled }}
"vault.hashicorp.com/agent-init-first": "true"
"vault.hashicorp.com/agent-inject": "true"
"vault.hashicorp.com/agent-inject-secret-serverca.crt": {{ .Values.global.tls.caCert.secretName }}
"vault.hashicorp.com/agent-inject-template-serverca.crt": {{ template "consul.serverTLSCATemplate" . }}
{{- if and .Values.global.secretsBackend.vault.ca.secretName .Values.global.secretsBackend.vault.ca.secretKey }}
"vault.hashicorp.com/agent-extra-secret": "{{ .Values.global.secretsBackend.vault.ca.secretName }}"
"vault.hashicorp.com/ca-cert": "/vault/custom/{{ .Values.global.secretsBackend.vault.ca.secretKey }}"
{{- end }}
{{- if .Values.global.secretsBackend.vault.agentAnnotations }}
{{ tpl .Values.global.secretsBackend.vault.agentAnnotations . | nindent 8 | trim }}
{{- end }}
{{- end }}
{{- if .Values.global.enterpriseLicense.secretName }}
{{- with .Values.global.enterpriseLicense }}
"vault.hashicorp.com/agent-inject-secret-enterpriselicense.txt": "{{ .secretName }}"
"vault.hashicorp.com/agent-inject-template-enterpriselicense.txt": {{ template "consul.vaultSecretTemplate" . }}
{{- end }}
{{- end }}
{{- if .Values.client.snapshotAgent.configSecret.secretName }}
{{- with .Values.client.snapshotAgent.configSecret }}
"vault.hashicorp.com/agent-inject-secret-snapshot-agent-config.json": "{{ .secretName }}"
"vault.hashicorp.com/agent-inject-template-snapshot-agent-config.json": {{ template "consul.vaultSecretTemplate" . }}
{{- end }}
{{- end }}
{{- end }}
spec:
{{- if .Values.client.tolerations }}
tolerations:
{{ tpl .Values.client.tolerations . | nindent 8 | trim }}
{{- end }}
terminationGracePeriodSeconds: 10
serviceAccountName: {{ template "consul.fullname" . }}-snapshot-agent
{{- if .Values.client.priorityClassName }}
priorityClassName: {{ .Values.client.priorityClassName | quote }}
{{- end }}
volumes:
{{- if .Values.client.snapshotAgent.caCert }}
- name: extra-ssl-certs
emptyDir:
medium: "Memory"
{{- end }}
{{- if (or .Values.global.acls.manageSystemACLs .Values.global.tls.enabled (and .Values.client.snapshotAgent.configSecret.secretName .Values.client.snapshotAgent.configSecret.secretKey) (and .Values.global.enterpriseLicense.secretName .Values.global.enterpriseLicense.secretKey .Values.global.enterpriseLicense.enableLicenseAutoload)) }}
- name: consul-data
emptyDir:
medium: "Memory"
{{- if (and .Values.client.snapshotAgent.configSecret.secretName .Values.client.snapshotAgent.configSecret.secretKey (not .Values.global.secretsBackend.vault.enabled)) }}
- name: snapshot-config
secret:
secretName: {{ .Values.client.snapshotAgent.configSecret.secretName }}
items:
- key: {{ .Values.client.snapshotAgent.configSecret.secretKey }}
path: snapshot-config.json
{{- end }}
{{- if (and .Values.global.enterpriseLicense.secretName .Values.global.enterpriseLicense.secretKey .Values.global.enterpriseLicense.enableLicenseAutoload (not .Values.global.secretsBackend.vault.enabled) (not .Values.global.acls.manageSystemACLs)) }}
- name: consul-license
secret:
secretName: {{ .Values.global.enterpriseLicense.secretName }}
{{- end }}
{{- if .Values.global.tls.enabled }}
{{- if not (and .Values.externalServers.enabled .Values.externalServers.useSystemRoots) }}
- name: consul-ca-cert
secret:
{{- if .Values.global.tls.caCert.secretName }}
secretName: {{ .Values.global.tls.caCert.secretName }}
{{- else }}
secretName: {{ template "consul.fullname" . }}-ca-cert
{{- end }}
items:
- key: {{ default "tls.crt" .Values.global.tls.caCert.secretKey }}
path: tls.crt
{{- end }}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
emptyDir:
medium: "Memory"
{{- end }}
{{- end }}
{{- end }}
containers:
- name: consul-snapshot-agent
image: "{{ default .Values.global.image .Values.client.image }}"
env:
{{- if .Values.client.snapshotAgent.caCert }}
- name: SSL_CERT_DIR
value: "/etc/ssl/certs:/extra-ssl-certs"
{{- end }}
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
{{- if .Values.global.tls.enabled }}
- name: CONSUL_HTTP_ADDR
value: https://$(HOST_IP):8501
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- else }}
- name: CONSUL_HTTP_ADDR
value: http://$(HOST_IP):8500
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
- name: CONSUL_HTTP_TOKEN_FILE
value: /consul/login/acl-token
{{- else }}
{{- if (and .Values.global.enterpriseLicense.secretName .Values.global.enterpriseLicense.secretKey .Values.global.enterpriseLicense.enableLicenseAutoload) }}
- name: CONSUL_LICENSE_PATH
{{- if .Values.global.secretsBackend.vault.enabled }}
value: /vault/secrets/enterpriselicense.txt
{{- else }}
value: /consul/license/{{ .Values.global.enterpriseLicense.secretKey }}
{{- end }}
{{- end }}
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
{{- if .Values.client.snapshotAgent.caCert }}
cat <<EOF > /extra-ssl-certs/custom-ca.pem
{{- .Values.client.snapshotAgent.caCert | nindent 14 }}
EOF
{{- end }}
exec /bin/consul snapshot agent \
-interval={{ .Values.client.snapshotAgent.interval }} \
{{- if (and .Values.client.snapshotAgent.configSecret.secretName .Values.client.snapshotAgent.configSecret.secretKey) }}
{{- if .Values.global.secretsBackend.vault.enabled }}
-config-file=/vault/secrets/snapshot-agent-config.json \
{{- else }}
-config-dir=/consul/config \
{{- end }}
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
-config-dir=/consul/login \
{{- end }}
volumeMounts:
{{- if .Values.client.snapshotAgent.caCert }}
- name: extra-ssl-certs
mountPath: /extra-ssl-certs
readOnly: false
{{- end }}
{{- if (or .Values.global.acls.manageSystemACLs .Values.global.tls.enabled (and .Values.client.snapshotAgent.configSecret.secretName .Values.client.snapshotAgent.configSecret.secretKey) (and .Values.global.enterpriseLicense.secretName .Values.global.enterpriseLicense.secretKey .Values.global.enterpriseLicense.enableLicenseAutoload)) }}
{{- if (and .Values.client.snapshotAgent.configSecret.secretName .Values.client.snapshotAgent.configSecret.secretKey (not .Values.global.secretsBackend.vault.enabled)) }}
- name: snapshot-config
mountPath: /consul/config
readOnly: true
{{- end }}
- mountPath: /consul/login
name: consul-data
readOnly: true
{{- if (and .Values.global.enterpriseLicense.secretName .Values.global.enterpriseLicense.secretKey .Values.global.enterpriseLicense.enableLicenseAutoload (not .Values.global.secretsBackend.vault.enabled) (not .Values.global.acls.manageSystemACLs))}}
- name: consul-license
mountPath: /consul/license
readOnly: true
{{- end }}
{{- if .Values.global.tls.enabled }}
{{- if .Values.global.tls.enableAutoEncrypt}}
- name: consul-auto-encrypt-ca-cert
{{- else }}
- name: consul-ca-cert
{{- end }}
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
lifecycle:
preStop:
exec:
command:
- "/bin/sh"
- "-ec"
- |
/bin/consul logout
{{- end }}
{{- with .Values.client.snapshotAgent.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if (or .Values.global.acls.manageSystemACLs (and .Values.global.tls.enabled .Values.global.tls.enableAutoEncrypt)) }}
initContainers:
{{- if (and .Values.global.tls.enabled .Values.global.tls.enableAutoEncrypt) }}
{{- include "consul.getAutoEncryptClientCA" . | nindent 6 }}
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
- name: snapshot-agent-acl-init
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
{{- if .Values.global.tls.enabled }}
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- end }}
- name: CONSUL_HTTP_ADDR
{{- if .Values.global.tls.enabled }}
value: https://$(HOST_IP):8501
{{- else }}
value: http://$(HOST_IP):8500
{{- end }}
image: {{ .Values.global.imageK8S }}
volumeMounts:
- mountPath: /consul/login
name: consul-data
readOnly: false
{{- if .Values.global.tls.enabled }}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
{{- else }}
- name: consul-ca-cert
{{- end }}
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
consul-k8s-control-plane acl-init \
-component-name=snapshot-agent \
-acl-auth-method={{ template "consul.fullname" . }}-k8s-component-auth-method \
{{- if .Values.global.adminPartitions.enabled }}
-partition={{ .Values.global.adminPartitions.name }} \
{{- end }}
-token-sink-file=/consul/login/acl-token \
-consul-api-timeout={{ .Values.global.consulAPITimeout }} \
-log-level={{ default .Values.global.logLevel }} \
-log-json={{ .Values.global.logJSON }}
resources:
requests:
memory: "25Mi"
cpu: "50m"
limits:
memory: "25Mi"
cpu: "50m"
{{- end }}
{{- end }}
{{- if .Values.client.nodeSelector }}
nodeSelector:
{{ tpl .Values.client.nodeSelector . | indent 8 | trim }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,42 @@
{{- if (and .Values.global.enablePodSecurityPolicies (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled))) }}
{{- if .Values.client.snapshotAgent.enabled }}
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: {{ template "consul.fullname" . }}-snapshot-agent
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: client-snapshot-agent
spec:
privileged: false
# Required to prevent escalations to root.
allowPrivilegeEscalation: false
# This is redundant with non-root + disallow privilege escalation,
# but we can provide it for defense in depth.
requiredDropCapabilities:
- ALL
# Allow core volume types.
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
hostNetwork: false
hostIPC: false
hostPID: false
runAsUser:
rule: 'RunAsAny'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'
readOnlyRootFilesystem: false
{{- end }}
{{- end }}

View File

@ -0,0 +1,26 @@
{{- if (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }}
{{- if .Values.client.snapshotAgent.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ template "consul.fullname" . }}-snapshot-agent
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: client-snapshot-agent
{{- if .Values.global.enablePodSecurityPolicies }}
rules:
- apiGroups: [ "policy" ]
resources: [ "podsecuritypolicies" ]
resourceNames:
- {{ template "consul.fullname" . }}-snapshot-agent
verbs:
- use
{{- else }}
rules: [ ]
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,22 @@
{{- if (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }}
{{- if .Values.client.snapshotAgent.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ template "consul.fullname" . }}-snapshot-agent
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: client-snapshot-agent
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ template "consul.fullname" . }}-snapshot-agent
subjects:
- kind: ServiceAccount
name: {{ template "consul.fullname" . }}-snapshot-agent
{{- end }}
{{- end }}

View File

@ -0,0 +1,25 @@
{{- if (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }}
{{- if .Values.client.snapshotAgent.enabled }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "consul.fullname" . }}-snapshot-agent
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: client-snapshot-agent
{{- if .Values.client.snapshotAgent.serviceAccount.annotations }}
annotations:
{{ tpl .Values.client.snapshotAgent.serviceAccount.annotations . | nindent 4 | trim }}
{{- end }}
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- range . }}
- name: {{ .name }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,38 @@
{{- if .Values.connectInject.cni.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ template "consul.fullname" . }}-cni
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: cni
rules:
- apiGroups: [""]
resources:
- pods
verbs:
- get
- list
- watch
- patch
- update
- apiGroups: ["policy"]
resources:
- podsecuritypolicies
resourceNames:
- {{ template "consul.fullname" . }}-cni
verbs:
- use
{{- if .Values.global.openshift.enabled}}
- apiGroups: ["security.openshift.io"]
resources: ["securitycontextconstraints"]
resourceNames:
- {{ template "consul.fullname" . }}-cni
verbs:
- use
{{- end }}
{{- end }}

View File

@ -0,0 +1,20 @@
{{- if .Values.connectInject.cni.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ template "consul.fullname" . }}-cni
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: cni
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ template "consul.fullname" . }}-cni
subjects:
- kind: ServiceAccount
name: {{ template "consul.fullname" . }}-cni
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@ -0,0 +1,84 @@
{{- if (and (.Values.connectInject.cni.enabled) (not .Values.connectInject.enabled)) }}{{ fail "connectInject.enabled must be true if connectInject.cni.enabled is true" }}{{ end -}}
{{- if .Values.connectInject.cni.enabled }}
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: {{ template "consul.fullname" . }}-cni
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: cni
spec:
{{- if .Values.connectInject.cni.updateStrategy }}
updateStrategy:
{{ tpl .Values.connectInject.cni.updateStrategy . | nindent 4 | trim }}
{{- end }}
selector:
matchLabels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
release: {{ .Release.Name }}
component: cni
template:
metadata:
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
release: {{ .Release.Name }}
component: cni
annotations:
consul.hashicorp.com/connect-inject: "false"
spec:
# consul-cni only runs on linux operating systems
nodeSelector:
kubernetes.io/os: linux
tolerations:
# Mark the pod as a critical add-on for rescheduling.
- key: CriticalAddonsOnly
operator: Exists
- effect: NoExecute
operator: Exists
# Tell kubernetes that this daemonset is critical so that it will be scheduled on a new node before other pods
priorityClassName: system-node-critical
serviceAccountName: {{ template "consul.fullname" . }}-cni
{{- if not .Values.global.openshift.enabled }}
securityContext:
{{- toYaml .Values.connectInject.cni.securityContext | nindent 8 -}}
{{- end }}
# Minimize downtime during a rolling upgrade or deletion; tell Kubernetes to do a "force
# deletion": https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods.
terminationGracePeriodSeconds: 10
containers:
# This container installs the consul CNI binaries and CNI network config file on each node
- name: install-cni
image: {{ .Values.global.imageK8S }}
securityContext:
privileged: true
command:
- consul-k8s-control-plane
- install-cni
- -log-level={{ default .Values.global.logLevel .Values.connectInject.cni.logLevel }}
- -cni-bin-dir={{ .Values.connectInject.cni.cniBinDir }}
- -cni-net-dir={{ .Values.connectInject.cni.cniNetDir }}
- -multus={{ .Values.connectInject.cni.multus }}
{{- with .Values.connectInject.cni.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
- mountPath: {{ .Values.connectInject.cni.cniBinDir }}
name: cni-bin-dir
- mountPath: {{ .Values.connectInject.cni.cniNetDir }}
name: cni-net-dir
volumes:
# Used to install CNI.
- name: cni-bin-dir
hostPath:
path: {{ .Values.connectInject.cni.cniBinDir }}
- name: cni-net-dir
hostPath:
path: {{ .Values.connectInject.cni.cniNetDir }}
{{- end }}

View File

@ -0,0 +1,25 @@
{{- if (and (.Values.connectInject.cni.enabled) (.Values.connectInject.cni.multus)) }}
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: {{ template "consul.fullname" . }}-cni
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: cni
spec:
config: '{
"cniVersion": "0.3.1",
"type": "consul-cni",
"cni_bin_dir": "{{ .Values.connectInject.cni.cniBinDir }}",
"cni_net_dir": "{{ .Values.connectInject.cni.cniNetDir }}",
"kubeconfig": "ZZZ-consul-cni-kubeconfig",
"log_level": "{{ default .Values.global.logLevel .Values.connectInject.cni.logLevel }}",
"multus": true,
"name": "consul-cni",
"type": "consul-cni"
}'
{{- end }}

View File

@ -0,0 +1,31 @@
{{- if (and .Values.connectInject.cni.enabled .Values.global.enablePodSecurityPolicies) }}
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: {{ template "consul.fullname" . }}-cni
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: cni
spec:
privileged: true
# GKE requires that allowPrivilegeEscalation:true if privileged: true.
allowPrivilegeEscalation: true
volumes:
- hostPath
- secret
- emptyDir
hostNetwork: false
readOnlyRootFilesystem: false
runAsUser:
rule: 'RunAsAny'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'
{{- end }}

View File

@ -0,0 +1,22 @@
{{- if .Values.connectInject.cni.enabled }}
apiVersion: v1
kind: ResourceQuota
metadata:
name: {{ template "consul.fullname" . }}-cni
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: cni
spec:
hard:
pods: {{ .Values.connectInject.cni.resourceQuota.pods | quote }}
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values:
- system-node-critical
{{- end }}

View File

@ -0,0 +1,50 @@
{{- if (and (.Values.connectInject.cni.enabled) (.Values.global.openshift.enabled)) }}
apiVersion: security.openshift.io/v1
kind: SecurityContextConstraints
metadata:
name: {{ template "consul.fullname" . }}-cni
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: cni
annotations:
kubernetes.io/description: {{ template "consul.fullname" . }}-cni are the security context constraints required
to run consul-cni.
allowHostDirVolumePlugin: true
allowHostIPC: false
allowHostNetwork: false
allowHostPID: false
allowHostPorts: false
allowPrivilegeEscalation: true
allowPrivilegedContainer: true
allowedCapabilities: null
defaultAddCapabilities: null
fsGroup:
type: MustRunAs
groups: []
priority: null
readOnlyRootFilesystem: false
requiredDropCapabilities:
- KILL
- MKNOD
- SETUID
- SETGID
runAsUser:
type: MustRunAsRange
seLinuxContext:
type: MustRunAs
supplementalGroups:
type: MustRunAs
users: []
volumes:
- configMap
- downwardAPI
- emptyDir
- persistentVolumeClaim
- projected
- secret
- hostPath
{{- end }}

View File

@ -0,0 +1,19 @@
{{- if .Values.connectInject.cni.enabled }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "consul.fullname" . }}-cni
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: cni
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- range . }}
- name: {{ .name }}
{{- end }}
{{- end }}
{{- end}}

View File

@ -0,0 +1,109 @@
{{- if or (and (ne (.Values.connectInject.enabled | toString) "-") .Values.connectInject.enabled) (and (eq (.Values.connectInject.enabled | toString) "-") .Values.global.enabled) }}
# The ClusterRole to enable the Connect injector to get, list, watch and patch MutatingWebhookConfiguration.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ template "consul.fullname" . }}-connect-injector
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: connect-injector
rules:
{{- if .Values.global.acls.manageSystemACLs }}
- apiGroups: [ "" ]
resources: ["serviceaccounts", "secrets"]
verbs:
- get
{{- end }}
- apiGroups: [ "" ]
resources: [ "endpoints", "services", "namespaces", "nodes" ]
verbs:
- "get"
- "list"
- "watch"
- apiGroups: [ "" ]
resources:
- pods
verbs:
- "get"
- "list"
- "watch"
- "update"
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- create
- get
- list
- update
{{- if (and .Values.global.secretsBackend.vault.enabled .Values.global.secretsBackend.vault.connectInjectRole .Values.global.secretsBackend.vault.connectInject.tlsCert.secretName .Values.global.secretsBackend.vault.connectInject.caCert.secretName)}}
- apiGroups:
- admissionregistration.k8s.io
resources:
- mutatingwebhookconfigurations
verbs:
- get
- list
- watch
- patch
{{- end }}
{{- if .Values.global.peering.enabled }}
- apiGroups: [ "" ]
resources: ["secrets"]
verbs:
- "get"
- "list"
- "watch"
- "create"
- "update"
- "delete"
- apiGroups: ["consul.hashicorp.com"]
resources: ["peeringacceptors"]
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- consul.hashicorp.com
resources:
- peeringacceptors/status
verbs:
- get
- patch
- update
- apiGroups: ["consul.hashicorp.com"]
resources: ["peeringdialers"]
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- consul.hashicorp.com
resources:
- peeringdialers/status
verbs:
- get
- patch
- update
{{- end }}
{{- if .Values.global.enablePodSecurityPolicies }}
- apiGroups: [ "policy" ]
resources: [ "podsecuritypolicies" ]
resourceNames:
- {{ template "consul.fullname" . }}-connect-injector
verbs:
- use
{{- end }}
{{- end }}

View File

@ -0,0 +1,20 @@
{{- if or (and (ne (.Values.connectInject.enabled | toString) "-") .Values.connectInject.enabled) (and (eq (.Values.connectInject.enabled | toString) "-") .Values.global.enabled) }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ template "consul.fullname" . }}-connect-injector
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: connect-injector
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ template "consul.fullname" . }}-connect-injector
subjects:
- kind: ServiceAccount
name: {{ template "consul.fullname" . }}-connect-injector
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@ -0,0 +1,437 @@
{{- if and .Values.global.peering.enabled (not .Values.connectInject.enabled) }}{{ fail "setting global.peering.enabled to true requires connectInject.enabled to be true" }}{{ end }}
{{- if (or (and (ne (.Values.connectInject.enabled | toString) "-") .Values.connectInject.enabled) (and (eq (.Values.connectInject.enabled | toString) "-") .Values.global.enabled)) }}
{{- if not (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }}{{ fail "clients must be enabled for connect injection" }}{{ end }}
{{- if not .Values.client.grpc }}{{ fail "client.grpc must be true for connect injection" }}{{ end }}
{{- if and .Values.connectInject.consulNamespaces.mirroringK8S (not .Values.global.enableConsulNamespaces) }}{{ fail "global.enableConsulNamespaces must be true if mirroringK8S=true" }}{{ end }}
{{- if and .Values.global.adminPartitions.enabled (not .Values.global.enableConsulNamespaces) }}{{ fail "global.enableConsulNamespaces must be true if global.adminPartitions.enabled=true" }}{{ end }}
{{- if .Values.connectInject.centralConfig }}{{- if eq (toString .Values.connectInject.centralConfig.enabled) "false" }}{{ fail "connectInject.centralConfig.enabled cannot be set to false; to disable, set enable_central_service_config to false in server.extraConfig and client.extraConfig" }}{{ end -}}{{ end -}}
{{- if .Values.connectInject.centralConfig }}{{- if .Values.connectInject.centralConfig.defaultProtocol }}{{ fail "connectInject.centralConfig.defaultProtocol is no longer supported; instead you must migrate to CRDs (see www.consul.io/docs/k8s/crds/upgrade-to-crds)" }}{{ end }}{{ end -}}
{{- if .Values.connectInject.centralConfig }}{{ if .Values.connectInject.centralConfig.proxyDefaults }}{{- if ne (trim .Values.connectInject.centralConfig.proxyDefaults) `{}` }}{{ fail "connectInject.centralConfig.proxyDefaults is no longer supported; instead you must migrate to CRDs (see www.consul.io/docs/k8s/crds/upgrade-to-crds)" }}{{ end }}{{ end }}{{ end -}}
{{- if .Values.connectInject.imageEnvoy }}{{ fail "connectInject.imageEnvoy must be specified in global.imageEnvoy" }}{{ end }}
{{- if .Values.global.lifecycleSidecarContainer }}{{ fail "global.lifecycleSidecarContainer has been renamed to global.consulSidecarContainer. Please set values using global.consulSidecarContainer." }}{{ end }}
{{ template "consul.validateVaultWebhookCertConfiguration" . }}
{{- template "consul.reservedNamesFailer" (list .Values.connectInject.consulNamespaces.consulDestinationNamespace "connectInject.consulNamespaces.consulDestinationNamespace") }}
{{- $serverEnabled := (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) -}}
{{- $serverExposeServiceEnabled := (or (and (ne (.Values.server.exposeService.enabled | toString) "-") .Values.server.exposeService.enabled) (and (eq (.Values.server.exposeService.enabled | toString) "-") (or .Values.global.peering.enabled .Values.global.adminPartitions.enabled))) -}}
{{- if not (or (eq .Values.global.peering.tokenGeneration.serverAddresses.source "") (or (eq .Values.global.peering.tokenGeneration.serverAddresses.source "static") (eq .Values.global.peering.tokenGeneration.serverAddresses.source "consul"))) }}{{ fail "global.peering.tokenGeneration.serverAddresses.source must be one of empty string, 'consul' or 'static'" }}{{ end }}
# The deployment for running the Connect sidecar injector
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "consul.fullname" . }}-connect-injector
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: connect-injector
spec:
replicas: {{ .Values.connectInject.replicas }}
selector:
matchLabels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
release: {{ .Release.Name }}
component: connect-injector
template:
metadata:
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
release: {{ .Release.Name }}
component: connect-injector
annotations:
"consul.hashicorp.com/connect-inject": "false"
{{- if .Values.connectInject.annotations }}
{{- tpl .Values.connectInject.annotations . | nindent 8 }}
{{- end }}
{{- if (and .Values.global.secretsBackend.vault.enabled .Values.global.tls.enabled) }}
"vault.hashicorp.com/agent-init-first": "true"
"vault.hashicorp.com/agent-inject": "true"
{{- if .Values.global.secretsBackend.vault.connectInjectRole }}
"vault.hashicorp.com/role": {{ .Values.global.secretsBackend.vault.connectInjectRole }}
{{ else }}
"vault.hashicorp.com/role": {{ .Values.global.secretsBackend.vault.consulCARole }}
{{ end }}
"vault.hashicorp.com/agent-inject-secret-serverca.crt": {{ .Values.global.tls.caCert.secretName }}
"vault.hashicorp.com/agent-inject-template-serverca.crt": {{ template "consul.serverTLSCATemplate" . }}
{{- if .Values.global.secretsBackend.vault.connectInject.caCert.secretName }}
{{- with .Values.global.secretsBackend.vault.connectInject.caCert }}
"vault.hashicorp.com/agent-inject-secret-ca.crt": {{ .secretName }}
"vault.hashicorp.com/agent-inject-template-ca.crt": {{ template "consul.vaultCATemplate" . }}
"vault.hashicorp.com/secret-volume-path-ca.crt": "/vault/secrets/connect-injector/certs"
{{- end }}
{{- end }}
{{- if .Values.global.secretsBackend.vault.connectInject.tlsCert.secretName }}
"vault.hashicorp.com/agent-inject-secret-tls.crt": {{ .Values.global.secretsBackend.vault.connectInject.tlsCert.secretName }}
"vault.hashicorp.com/agent-inject-template-tls.crt": {{ include "consul.connectInjectWebhookTLSCertTemplate" . }}
"vault.hashicorp.com/secret-volume-path-tls.crt": "/vault/secrets/connect-injector/certs"
"vault.hashicorp.com/agent-inject-secret-tls.key": {{ .Values.global.secretsBackend.vault.connectInject.tlsCert.secretName }}
"vault.hashicorp.com/agent-inject-template-tls.key": {{ include "consul.connectInjectWebhookTLSKeyTemplate" . }}
"vault.hashicorp.com/secret-volume-path-tls.key": "/vault/secrets/connect-injector/certs"
{{- end }}
{{- if and .Values.global.secretsBackend.vault.ca.secretName .Values.global.secretsBackend.vault.ca.secretKey }}
"vault.hashicorp.com/agent-extra-secret": "{{ .Values.global.secretsBackend.vault.ca.secretName }}"
"vault.hashicorp.com/ca-cert": "/vault/custom/{{ .Values.global.secretsBackend.vault.ca.secretKey }}"
{{- end }}
{{- if .Values.global.secretsBackend.vault.agentAnnotations }}
{{ tpl .Values.global.secretsBackend.vault.agentAnnotations . | nindent 8 | trim }}
{{- end }}
{{- end }}
spec:
serviceAccountName: {{ template "consul.fullname" . }}-connect-injector
containers:
- name: sidecar-injector
image: "{{ default .Values.global.imageK8S .Values.connectInject.image }}"
ports:
- containerPort: 8080
name: webhook-server
protocol: TCP
env:
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
{{- if .Values.global.acls.manageSystemACLs }}
- name: CONSUL_HTTP_TOKEN_FILE
value: "/consul/login/acl-token"
{{- end }}
{{- if .Values.global.tls.enabled }}
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- end }}
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
{{- if (and .Values.connectInject.aclInjectToken.secretName .Values.connectInject.aclInjectToken.secretKey) }}
- name: CONSUL_HTTP_TOKEN
valueFrom:
secretKeyRef:
name: {{ .Values.connectInject.aclInjectToken.secretName }}
key: {{ .Values.connectInject.aclInjectToken.secretKey }}
{{- end }}
- name: CONSUL_HTTP_ADDR
{{- if .Values.global.tls.enabled }}
value: https://$(HOST_IP):8501
{{- else }}
value: http://$(HOST_IP):8500
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
consul-k8s-control-plane inject-connect \
-consul-api-timeout={{ .Values.global.consulAPITimeout }} \
-log-level={{ default .Values.global.logLevel .Values.connectInject.logLevel }} \
-log-json={{ .Values.global.logJSON }} \
-default-inject={{ .Values.connectInject.default }} \
-consul-image="{{ default .Values.global.image .Values.connectInject.imageConsul }}" \
-envoy-image="{{ .Values.global.imageEnvoy }}" \
-consul-k8s-image="{{ default .Values.global.imageK8S .Values.connectInject.image }}" \
-release-name="{{ .Release.Name }}" \
-release-namespace="{{ .Release.Namespace }}" \
-resource-prefix={{ template "consul.fullname" . }} \
-listen=:8080 \
{{- if .Values.connectInject.transparentProxy.defaultEnabled }}
-default-enable-transparent-proxy=true \
{{- else }}
-default-enable-transparent-proxy=false \
{{- end }}
-enable-cni={{ .Values.connectInject.cni.enabled }} \
{{- if .Values.global.peering.enabled }}
-enable-peering=true \
{{- if (eq .Values.global.peering.tokenGeneration.serverAddresses.source "") }}
{{- if (and $serverEnabled $serverExposeServiceEnabled) }}
-read-server-expose-service=true \
{{- else }}
{{- if .Values.externalServers.enabled }}
{{- $port := .Values.externalServers.grpcPort }}
{{- range $h := .Values.externalServers.hosts }}
-token-server-address="{{ $h }}:{{ $port }}" \
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- if (eq .Values.global.peering.tokenGeneration.serverAddresses.source "static") }}
{{- range $addr := .Values.global.peering.tokenGeneration.serverAddresses.static }}
-token-server-address="{{ $addr }}" \
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.global.openshift.enabled }}
-enable-openshift \
{{- end }}
{{- if .Values.connectInject.transparentProxy.defaultOverwriteProbes }}
-transparent-proxy-default-overwrite-probes=true \
{{- else }}
-transparent-proxy-default-overwrite-probes=false \
{{- end }}
{{- if (and .Values.dns.enabled .Values.dns.enableRedirection) }}
-enable-consul-dns=true \
{{- end }}
{{- if .Values.global.openshift.enabled }}
-enable-openshift \
{{- end }}
{{- if (or (and (ne (.Values.connectInject.metrics.defaultEnabled | toString) "-") .Values.connectInject.metrics.defaultEnabled) (and (eq (.Values.connectInject.metrics.defaultEnabled | toString) "-") .Values.global.metrics.enabled)) }}
-default-enable-metrics=true \
{{- else }}
-default-enable-metrics=false \
{{- end }}
-default-enable-metrics-merging={{ .Values.connectInject.metrics.defaultEnableMerging }} \
-default-merged-metrics-port={{ .Values.connectInject.metrics.defaultMergedMetricsPort }} \
-default-prometheus-scrape-port={{ .Values.connectInject.metrics.defaultPrometheusScrapePort }} \
-default-prometheus-scrape-path="{{ .Values.connectInject.metrics.defaultPrometheusScrapePath }}" \
{{- if .Values.connectInject.envoyExtraArgs }}
-envoy-extra-args="{{ .Values.connectInject.envoyExtraArgs }}" \
{{- end }}
{{- if .Values.connectInject.overrideAuthMethodName }}
-acl-auth-method="{{ .Values.connectInject.overrideAuthMethodName }}" \
{{- else if .Values.global.acls.manageSystemACLs }}
-acl-auth-method="{{ template "consul.fullname" . }}-k8s-auth-method" \
{{- end }}
{{- range $value := .Values.connectInject.k8sAllowNamespaces }}
-allow-k8s-namespace="{{ $value }}" \
{{- end }}
{{- range $value := .Values.connectInject.k8sDenyNamespaces }}
-deny-k8s-namespace="{{ $value }}" \
{{- end }}
{{- if .Values.global.adminPartitions.enabled }}
-enable-partitions=true \
-partition={{ .Values.global.adminPartitions.name }} \
{{- end }}
{{- if .Values.global.enableConsulNamespaces }}
-enable-namespaces=true \
{{- if .Values.connectInject.consulNamespaces.consulDestinationNamespace }}
-consul-destination-namespace={{ .Values.connectInject.consulNamespaces.consulDestinationNamespace }} \
{{- end }}
{{- if .Values.connectInject.consulNamespaces.mirroringK8S }}
-enable-k8s-namespace-mirroring=true \
{{- if .Values.connectInject.consulNamespaces.mirroringK8SPrefix }}
-k8s-namespace-mirroring-prefix={{ .Values.connectInject.consulNamespaces.mirroringK8SPrefix }} \
{{- end }}
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
-consul-cross-namespace-acl-policy=cross-namespace-policy \
{{- end }}
{{- end }}
{{- if and .Values.global.secretsBackend.vault.enabled .Values.global.secretsBackend.vault.connectInject.tlsCert.secretName }}
-tls-cert-dir=/vault/secrets/connect-injector/certs \
-enable-webhook-ca-update \
{{- else }}
-tls-cert-dir=/etc/connect-injector/certs \
{{- end }}
{{- $resources := .Values.connectInject.sidecarProxy.resources }}
{{- /* kindIs is used here to differentiate between null and 0 */}}
{{- if not (kindIs "invalid" $resources.limits.memory) }}
-default-sidecar-proxy-memory-limit={{ $resources.limits.memory }} \
{{- end }}
{{- if not (kindIs "invalid" $resources.requests.memory) }}
-default-sidecar-proxy-memory-request={{ $resources.requests.memory }} \
{{- end }}
{{- if not (kindIs "invalid" $resources.limits.cpu) }}
-default-sidecar-proxy-cpu-limit={{ $resources.limits.cpu }} \
{{- end }}
{{- if not (kindIs "invalid" $resources.requests.cpu) }}
-default-sidecar-proxy-cpu-request={{ $resources.requests.cpu }} \
{{- end }}
-default-envoy-proxy-concurrency={{ .Values.connectInject.sidecarProxy.concurrency }} \
{{- if .Values.connectInject.initContainer }}
{{- $initResources := .Values.connectInject.initContainer.resources }}
{{- if not (kindIs "invalid" $initResources.limits.memory) }}
-init-container-memory-limit={{ $initResources.limits.memory }} \
{{- end }}
{{- if not (kindIs "invalid" $initResources.requests.memory) }}
-init-container-memory-request={{ $initResources.requests.memory }} \
{{- end }}
{{- if not (kindIs "invalid" $initResources.limits.cpu) }}
-init-container-cpu-limit={{ $initResources.limits.cpu }} \
{{- end }}
{{- if not (kindIs "invalid" $initResources.requests.cpu) }}
-init-container-cpu-request={{ $initResources.requests.cpu }} \
{{- end }}
{{- end }}
{{- if .Values.global.consulSidecarContainer }}
{{- $consulSidecarResources := .Values.global.consulSidecarContainer.resources }}
{{- if not (kindIs "invalid" $consulSidecarResources.limits.memory) }}
-default-consul-sidecar-memory-limit={{ $consulSidecarResources.limits.memory }} \
{{- end }}
{{- if not (kindIs "invalid" $consulSidecarResources.requests.memory) }}
-default-consul-sidecar-memory-request={{ $consulSidecarResources.requests.memory }} \
{{- end }}
{{- if not (kindIs "invalid" $consulSidecarResources.limits.cpu) }}
-default-consul-sidecar-cpu-limit={{ $consulSidecarResources.limits.cpu }} \
{{- end }}
{{- if not (kindIs "invalid" $consulSidecarResources.requests.cpu) }}
-default-consul-sidecar-cpu-request={{ $consulSidecarResources.requests.cpu }} \
{{- end }}
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
lifecycle:
preStop:
exec:
command:
- "/bin/sh"
- "-ec"
- |
consul-k8s-control-plane consul-logout -consul-api-timeout={{ .Values.global.consulAPITimeout }}
{{- end }}
startupProbe:
httpGet:
path: /readyz/ready
port: 9445
scheme: HTTP
failureThreshold: 15
periodSeconds: 2
timeoutSeconds: 5
livenessProbe:
httpGet:
path: /readyz/ready
port: 9445
scheme: HTTP
failureThreshold: 2
initialDelaySeconds: 1
successThreshold: 1
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /readyz/ready
port: 9445
scheme: HTTP
failureThreshold: 2
initialDelaySeconds: 2
successThreshold: 1
timeoutSeconds: 5
volumeMounts:
{{- if not (and .Values.global.secretsBackend.vault.enabled .Values.global.secretsBackend.vault.connectInject.tlsCert.secretName) }}
- name: certs
mountPath: /etc/connect-injector/certs
readOnly: true
{{- end }}
- mountPath: /consul/login
name: consul-data
readOnly: true
{{- if .Values.global.tls.enabled }}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
{{- else }}
- name: consul-ca-cert
{{- end }}
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
{{- with .Values.connectInject.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
volumes:
{{- if not (and .Values.global.secretsBackend.vault.enabled .Values.global.secretsBackend.vault.connectInject.tlsCert.secretName) }}
- name: certs
secret:
defaultMode: 420
secretName: {{ template "consul.fullname" . }}-connect-inject-webhook-cert
{{- end }}
- name: consul-data
emptyDir:
medium: "Memory"
{{- if .Values.global.tls.enabled }}
{{- if not (and .Values.externalServers.enabled .Values.externalServers.useSystemRoots) }}
- name: consul-ca-cert
secret:
{{- if .Values.global.tls.caCert.secretName }}
secretName: {{ .Values.global.tls.caCert.secretName }}
{{- else }}
secretName: {{ template "consul.fullname" . }}-ca-cert
{{- end }}
items:
- key: {{ default "tls.crt" .Values.global.tls.caCert.secretKey }}
path: tls.crt
{{- end }}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
emptyDir:
medium: "Memory"
{{- end }}
{{- end }}
{{- if or (and .Values.global.acls.manageSystemACLs) (and .Values.global.tls.enabled .Values.global.tls.enableAutoEncrypt) }}
initContainers:
{{- if and .Values.global.tls.enabled .Values.global.tls.enableAutoEncrypt }}
{{- include "consul.getAutoEncryptClientCA" . | nindent 6 }}
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
- name: connect-injector-acl-init
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
{{- if .Values.global.tls.enabled }}
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- end }}
- name: CONSUL_HTTP_ADDR
{{- if .Values.global.tls.enabled }}
value: https://$(HOST_IP):8501
{{- else }}
value: http://$(HOST_IP):8500
{{- end }}
image: {{ .Values.global.imageK8S }}
volumeMounts:
- mountPath: /consul/login
name: consul-data
readOnly: false
{{- if .Values.global.tls.enabled }}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
{{- else }}
- name: consul-ca-cert
{{- end }}
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
consul-k8s-control-plane acl-init \
-component-name=connect-injector \
{{- if and .Values.global.federation.enabled .Values.global.federation.primaryDatacenter .Values.global.enableConsulNamespaces }}
-acl-auth-method={{ template "consul.fullname" . }}-k8s-component-auth-method-{{ .Values.global.datacenter }} \
-primary-datacenter={{ .Values.global.federation.primaryDatacenter }} \
{{- else }}
-acl-auth-method={{ template "consul.fullname" . }}-k8s-component-auth-method \
{{- end }}
{{- if .Values.global.adminPartitions.enabled }}
-partition={{ .Values.global.adminPartitions.name }} \
{{- end }}
-consul-api-timeout={{ .Values.global.consulAPITimeout }} \
-log-level={{ default .Values.global.logLevel .Values.connectInject.logLevel }} \
-log-json={{ .Values.global.logJSON }}
resources:
requests:
memory: "25Mi"
cpu: "50m"
limits:
memory: "25Mi"
cpu: "50m"
{{- end }}
{{- end }}
{{- if .Values.connectInject.priorityClassName }}
priorityClassName: {{ .Values.connectInject.priorityClassName | quote }}
{{- end }}
{{- if .Values.connectInject.nodeSelector }}
nodeSelector:
{{ tpl .Values.connectInject.nodeSelector . | indent 8 | trim }}
{{- end }}
{{- if .Values.connectInject.affinity }}
affinity:
{{ tpl .Values.connectInject.affinity . | indent 8 | trim }}
{{- end }}
{{- if .Values.connectInject.tolerations }}
tolerations:
{{ tpl .Values.connectInject.tolerations . | indent 8 | trim }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,41 @@
{{- if or (and (ne (.Values.connectInject.enabled | toString) "-") .Values.connectInject.enabled) (and (eq (.Values.connectInject.enabled | toString) "-") .Values.global.enabled) }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ template "consul.fullname" . }}-connect-inject-leader-election
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: connect-injector
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- ""
resources:
- configmaps/status
verbs:
- get
- update
- patch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
{{- end }}

View File

@ -0,0 +1,21 @@
{{- if or (and (ne (.Values.connectInject.enabled | toString) "-") .Values.connectInject.enabled) (and (eq (.Values.connectInject.enabled | toString) "-") .Values.global.enabled) }}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ template "consul.fullname" . }}-connect-inject-leader-election
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: connect-injector
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ template "consul.fullname" . }}-connect-inject-leader-election
subjects:
- kind: ServiceAccount
name: {{ template "consul.fullname" . }}-connect-injector
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@ -0,0 +1,85 @@
{{- if (or (and (ne (.Values.connectInject.enabled | toString) "-") .Values.connectInject.enabled) (and (eq (.Values.connectInject.enabled | toString) "-") .Values.global.enabled)) }}
# The MutatingWebhookConfiguration to enable the Connect injector.
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: {{ template "consul.fullname" . }}-connect-injector
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: connect-injector
webhooks:
- name: {{ template "consul.fullname" . }}-connect-injector.consul.hashicorp.com
# The webhook will fail scheduling all pods that are not part of consul if all replicas of the webhook are unhealthy.
objectSelector:
matchExpressions:
- key: app
operator: NotIn
values: [ {{ template "consul.name" . }} ]
failurePolicy: {{ .Values.connectInject.failurePolicy }}
sideEffects: None
admissionReviewVersions:
- "v1beta1"
- "v1"
clientConfig:
service:
name: {{ template "consul.fullname" . }}-connect-injector
namespace: {{ .Release.Namespace }}
path: "/mutate"
rules:
- operations: [ "CREATE" ]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
{{- if .Values.connectInject.namespaceSelector }}
namespaceSelector:
{{ tpl .Values.connectInject.namespaceSelector . | indent 6 }}
{{- end }}
{{- if .Values.global.peering.enabled }}
- name: {{ template "consul.fullname" . }}-mutate-peeringacceptors.consul.hashicorp.com
clientConfig:
service:
name: {{ template "consul.fullname" . }}-connect-injector
namespace: {{ .Release.Namespace }}
path: "/mutate-v1alpha1-peeringacceptors"
rules:
- apiGroups:
- consul.hashicorp.com
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- peeringacceptors
failurePolicy: Fail
sideEffects: None
admissionReviewVersions:
- "v1beta1"
- "v1"
- name: {{ template "consul.fullname" . }}-mutate-peeringdialers.consul.hashicorp.com
clientConfig:
service:
name: {{ template "consul.fullname" . }}-connect-injector
namespace: {{ .Release.Namespace }}
path: "/mutate-v1alpha1-peeringdialers"
rules:
- apiGroups:
- consul.hashicorp.com
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- peeringdialers
failurePolicy: Fail
sideEffects: None
admissionReviewVersions:
- "v1beta1"
- "v1"
{{- end }}
{{- end }}

View File

@ -0,0 +1,40 @@
{{- if (and .Values.global.enablePodSecurityPolicies (or (and (ne (.Values.connectInject.enabled | toString) "-") .Values.connectInject.enabled) (and (eq (.Values.connectInject.enabled | toString) "-") .Values.global.enabled))) }}
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: {{ template "consul.fullname" . }}-connect-injector
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: connect-injector
spec:
privileged: false
# Required to prevent escalations to root.
allowPrivilegeEscalation: false
# This is redundant with non-root + disallow privilege escalation,
# but we can provide it for defense in depth.
requiredDropCapabilities:
- ALL
# Allow core volume types.
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
hostNetwork: false
hostIPC: false
hostPID: false
runAsUser:
rule: 'RunAsAny'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'
readOnlyRootFilesystem: false
{{- end }}

View File

@ -0,0 +1,23 @@
{{- if (or (and (ne (.Values.connectInject.enabled | toString) "-") .Values.connectInject.enabled) (and (eq (.Values.connectInject.enabled | toString) "-") .Values.global.enabled)) }}
# The service for the Connect sidecar injector
apiVersion: v1
kind: Service
metadata:
name: {{ template "consul.fullname" . }}-connect-injector
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: connect-injector
spec:
ports:
- port: 443
targetPort: 8080
selector:
app: {{ template "consul.name" . }}
release: "{{ .Release.Name }}"
component: connect-injector
{{- end }}

View File

@ -0,0 +1,23 @@
{{- if or (and (ne (.Values.connectInject.enabled | toString) "-") .Values.connectInject.enabled) (and (eq (.Values.connectInject.enabled | toString) "-") .Values.global.enabled) }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "consul.fullname" . }}-connect-injector
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: connect-injector
{{- if .Values.connectInject.serviceAccount.annotations }}
annotations:
{{ tpl .Values.connectInject.serviceAccount.annotations . | nindent 4 | trim }}
{{- end }}
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- range . }}
- name: {{ .name }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,26 @@
{{- if (and .Values.connectInject.disruptionBudget.enabled (or (and (ne (.Values.connectInject.enabled | toString) "-") .Values.connectInject.enabled) (and (eq (.Values.connectInject.enabled | toString) "-") .Values.global.enabled))) }}
# PodDisruptionBudget to prevent degrading the connectInject cluster through
# voluntary cluster changes.
{{- if .Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" }}
apiVersion: policy/v1
{{- else }}
apiVersion: policy/v1beta1
{{- end }}
kind: PodDisruptionBudget
metadata:
name: {{ template "consul.fullname" . }}-connect-injector
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: connect-injector
spec:
maxUnavailable: {{ template "consul.pdb.connectInject.maxUnavailable" . }}
selector:
matchLabels:
app: {{ template "consul.name" . }}
release: "{{ .Release.Name }}"
component: connect-injector
{{- end }}

View File

@ -0,0 +1,79 @@
{{- if .Values.controller.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ template "consul.fullname" . }}-controller
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: controller
rules:
- apiGroups:
- consul.hashicorp.com
resources:
- servicedefaults
- serviceresolvers
- proxydefaults
- meshes
- exportedservices
- servicerouters
- servicesplitters
- serviceintentions
- ingressgateways
- terminatinggateways
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- consul.hashicorp.com
resources:
- servicedefaults/status
- serviceresolvers/status
- proxydefaults/status
- meshes/status
- exportedservices/status
- servicerouters/status
- servicesplitters/status
- serviceintentions/status
- ingressgateways/status
- terminatinggateways/status
verbs:
- get
- patch
- update
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- create
- get
- list
- update
{{- if (and .Values.global.secretsBackend.vault.enabled .Values.global.secretsBackend.vault.controllerRole .Values.global.secretsBackend.vault.controller.tlsCert.secretName .Values.global.secretsBackend.vault.controller.caCert.secretName)}}
- apiGroups:
- admissionregistration.k8s.io
resources:
- mutatingwebhookconfigurations
verbs:
- get
- list
- watch
- patch
{{- end }}
{{- if .Values.global.enablePodSecurityPolicies }}
- apiGroups: ["policy"]
resources: ["podsecuritypolicies"]
resourceNames:
- {{ template "consul.fullname" . }}-controller
verbs:
- use
{{- end }}
{{- end }}

View File

@ -0,0 +1,20 @@
{{- if .Values.controller.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ template "consul.fullname" . }}-controller
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ template "consul.fullname" . }}-controller
subjects:
- kind: ServiceAccount
name: {{ template "consul.fullname" . }}-controller
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@ -0,0 +1,277 @@
{{- if .Values.controller.enabled }}
{{- if and .Values.global.adminPartitions.enabled (not .Values.global.enableConsulNamespaces) }}{{ fail "global.enableConsulNamespaces must be true if global.adminPartitions.enabled=true" }}{{ end }}
{{ template "consul.validateVaultWebhookCertConfiguration" . }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "consul.fullname" . }}-controller
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: controller
spec:
replicas: {{ .Values.controller.replicas }}
selector:
matchLabels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: controller
template:
metadata:
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: controller
annotations:
"consul.hashicorp.com/connect-inject": "false"
{{- if (and .Values.global.secretsBackend.vault.enabled .Values.global.tls.enabled) }}
"vault.hashicorp.com/agent-init-first": "true"
"vault.hashicorp.com/agent-inject": "true"
{{- if .Values.global.secretsBackend.vault.controllerRole }}
"vault.hashicorp.com/role": {{ .Values.global.secretsBackend.vault.controllerRole }}
{{ else }}
"vault.hashicorp.com/role": {{ .Values.global.secretsBackend.vault.consulCARole }}
{{ end }}
"vault.hashicorp.com/agent-inject-secret-serverca.crt": {{ .Values.global.tls.caCert.secretName }}
"vault.hashicorp.com/agent-inject-template-serverca.crt": {{ template "consul.serverTLSCATemplate" . }}
{{- if .Values.global.secretsBackend.vault.controller.caCert.secretName }}
{{- with .Values.global.secretsBackend.vault.controller.caCert }}
"vault.hashicorp.com/agent-inject-secret-ca.crt": {{ .secretName }}
"vault.hashicorp.com/agent-inject-template-ca.crt": {{ template "consul.vaultCATemplate" . }}
"vault.hashicorp.com/secret-volume-path-ca.crt": "/vault/secrets/controller-webhook/certs"
{{- end }}
{{- end }}
{{- if .Values.global.secretsBackend.vault.controller.tlsCert.secretName }}
"vault.hashicorp.com/agent-inject-secret-tls.crt": {{ .Values.global.secretsBackend.vault.controller.tlsCert.secretName }}
"vault.hashicorp.com/agent-inject-template-tls.crt": {{ include "consul.controllerWebhookTLSCertTemplate" . }}
"vault.hashicorp.com/secret-volume-path-tls.crt": "/vault/secrets/controller-webhook/certs"
"vault.hashicorp.com/agent-inject-secret-tls.key": {{ .Values.global.secretsBackend.vault.controller.tlsCert.secretName }}
"vault.hashicorp.com/agent-inject-template-tls.key": {{ include "consul.controllerWebhookTLSKeyTemplate" . }}
"vault.hashicorp.com/secret-volume-path-tls.key": "/vault/secrets/controller-webhook/certs"
{{- end }}
{{- if and .Values.global.secretsBackend.vault.ca.secretName .Values.global.secretsBackend.vault.ca.secretKey }}
"vault.hashicorp.com/agent-extra-secret": "{{ .Values.global.secretsBackend.vault.ca.secretName }}"
"vault.hashicorp.com/ca-cert": "/vault/custom/{{ .Values.global.secretsBackend.vault.ca.secretKey }}"
{{- end }}
{{- if .Values.global.secretsBackend.vault.agentAnnotations }}
{{ tpl .Values.global.secretsBackend.vault.agentAnnotations . | nindent 8 | trim }}
{{- end }}
{{- end }}
spec:
{{- if or .Values.global.acls.manageSystemACLs (and .Values.global.tls.enabled .Values.global.tls.enableAutoEncrypt) }}
initContainers:
{{- if and .Values.global.tls.enabled .Values.global.tls.enableAutoEncrypt }}
{{- include "consul.getAutoEncryptClientCA" . | nindent 6 }}
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
- name: controller-acl-init
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
{{- if .Values.global.tls.enabled }}
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- end }}
- name: CONSUL_HTTP_ADDR
{{- if .Values.global.tls.enabled }}
value: https://$(HOST_IP):8501
{{- else }}
value: http://$(HOST_IP):8500
{{- end }}
image: {{ .Values.global.imageK8S }}
volumeMounts:
- mountPath: /consul/login
name: consul-data
readOnly: false
{{- if .Values.global.tls.enabled }}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
{{- else }}
- name: consul-ca-cert
{{- end }}
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
consul-k8s-control-plane acl-init \
-component-name=controller \
{{- if and .Values.global.federation.enabled .Values.global.federation.primaryDatacenter }}
-acl-auth-method={{ template "consul.fullname" . }}-k8s-component-auth-method-{{ .Values.global.datacenter }} \
-primary-datacenter={{ .Values.global.federation.primaryDatacenter }} \
{{- else }}
-acl-auth-method={{ template "consul.fullname" . }}-k8s-component-auth-method \
{{- end }}
{{- if .Values.global.adminPartitions.enabled }}
-partition={{ .Values.global.adminPartitions.name }} \
{{- end }}
-consul-api-timeout={{ .Values.global.consulAPITimeout }} \
-log-level={{ default .Values.global.logLevel .Values.controller.logLevel }} \
-log-json={{ .Values.global.logJSON }}
resources:
requests:
memory: "25Mi"
cpu: "50m"
limits:
memory: "25Mi"
cpu: "50m"
{{- end }}
{{- end }}
containers:
- command:
- "/bin/sh"
- "-ec"
- |
consul-k8s-control-plane controller \
-consul-api-timeout={{ .Values.global.consulAPITimeout }} \
-log-level={{ default .Values.global.logLevel .Values.controller.logLevel }} \
-log-json={{ .Values.global.logJSON }} \
-resource-prefix={{ template "consul.fullname" . }} \
{{- if and .Values.global.secretsBackend.vault.enabled .Values.global.secretsBackend.vault.controller.tlsCert.secretName }}
-enable-webhook-ca-update \
-webhook-tls-cert-dir=/vault/secrets/controller-webhook/certs \
{{- else }}
-webhook-tls-cert-dir=/tmp/controller-webhook/certs \
{{- end }}
-datacenter={{ .Values.global.datacenter }} \
{{- if .Values.global.adminPartitions.enabled }}
-partition={{ .Values.global.adminPartitions.name }} \
{{- end }}
-enable-leader-election \
{{- if .Values.global.enableConsulNamespaces }}
-enable-namespaces=true \
{{- if .Values.connectInject.consulNamespaces.consulDestinationNamespace }}
-consul-destination-namespace={{ .Values.connectInject.consulNamespaces.consulDestinationNamespace }} \
{{- end }}
{{- if .Values.connectInject.consulNamespaces.mirroringK8S }}
-enable-k8s-namespace-mirroring=true \
{{- if .Values.connectInject.consulNamespaces.mirroringK8SPrefix }}
-k8s-namespace-mirroring-prefix={{ .Values.connectInject.consulNamespaces.mirroringK8SPrefix }} \
{{- end }}
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
-consul-cross-namespace-acl-policy=cross-namespace-policy \
{{- end }}
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
lifecycle:
preStop:
exec:
command:
- "/bin/sh"
- "-ec"
- |
consul-k8s-control-plane consul-logout -consul-api-timeout={{ .Values.global.consulAPITimeout }}
{{- end }}
env:
{{- if .Values.global.acls.manageSystemACLs }}
- name: CONSUL_HTTP_TOKEN_FILE
value: "/consul/login/acl-token"
{{- end }}
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
{{- if (and .Values.controller.aclToken.secretName .Values.controller.aclToken.secretKey) }}
- name: CONSUL_HTTP_TOKEN
valueFrom:
secretKeyRef:
name: {{ .Values.controller.aclToken.secretName }}
key: {{ .Values.controller.aclToken.secretKey }}
{{- end }}
{{- if .Values.global.tls.enabled }}
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- end }}
- name: CONSUL_HTTP_ADDR
{{- if .Values.global.tls.enabled }}
value: https://$(HOST_IP):8501
{{- else }}
value: http://$(HOST_IP):8500
{{- end }}
image: {{ .Values.global.imageK8S }}
name: controller
ports:
- containerPort: 9443
name: webhook-server
protocol: TCP
{{- with .Values.controller.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
- mountPath: /consul/login
name: consul-data
readOnly: true
{{- if not (and .Values.global.secretsBackend.vault.enabled .Values.global.secretsBackend.vault.controller.tlsCert.secretName) }}
- mountPath: /tmp/controller-webhook/certs
name: cert
readOnly: true
{{- end }}
{{- if .Values.global.tls.enabled }}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
{{- else }}
- name: consul-ca-cert
{{- end }}
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
terminationGracePeriodSeconds: 10
volumes:
{{- if not (and .Values.global.secretsBackend.vault.enabled .Values.global.secretsBackend.vault.controller.tlsCert.secretName) }}
- name: cert
secret:
defaultMode: 420
secretName: {{ template "consul.fullname" . }}-controller-webhook-cert
{{- end }}
{{- if .Values.global.tls.enabled }}
{{- if not (and .Values.externalServers.enabled .Values.externalServers.useSystemRoots) }}
- name: consul-ca-cert
secret:
{{- if .Values.global.tls.caCert.secretName }}
secretName: {{ .Values.global.tls.caCert.secretName }}
{{- else }}
secretName: {{ template "consul.fullname" . }}-ca-cert
{{- end }}
items:
- key: {{ default "tls.crt" .Values.global.tls.caCert.secretKey }}
path: tls.crt
{{- end }}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
emptyDir:
medium: "Memory"
{{- end }}
{{- end }}
- name: consul-data
emptyDir:
medium: "Memory"
serviceAccountName: {{ template "consul.fullname" . }}-controller
{{- if .Values.controller.nodeSelector }}
nodeSelector:
{{ tpl .Values.controller.nodeSelector . | indent 8 | trim }}
{{- end }}
{{- if .Values.controller.affinity }}
affinity:
{{ tpl .Values.controller.affinity . | indent 8 | trim }}
{{- end }}
{{- if .Values.controller.tolerations }}
tolerations:
{{ tpl .Values.controller.tolerations . | indent 8 | trim }}
{{- end }}
{{- if .Values.controller.priorityClassName }}
priorityClassName: {{ .Values.controller.priorityClassName | quote }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,41 @@
{{- if .Values.controller.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ template "consul.fullname" . }}-controller-leader-election
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: controller
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- ""
resources:
- configmaps/status
verbs:
- get
- update
- patch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
{{- end }}

View File

@ -0,0 +1,20 @@
{{- if .Values.controller.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ template "consul.fullname" . }}-controller-leader-election
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ template "consul.fullname" . }}-controller-leader-election
subjects:
- kind: ServiceAccount
name: {{ template "consul.fullname" . }}-controller
{{- end }}

View File

@ -0,0 +1,224 @@
{{- if .Values.controller.enabled }}
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: {{ template "consul.fullname" . }}-controller
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: controller
webhooks:
- clientConfig:
service:
name: {{ template "consul.fullname" . }}-controller-webhook
namespace: {{ .Release.Namespace }}
path: /mutate-v1alpha1-proxydefaults
failurePolicy: Fail
admissionReviewVersions:
- "v1beta1"
- "v1"
name: mutate-proxydefaults.consul.hashicorp.com
rules:
- apiGroups:
- consul.hashicorp.com
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- proxydefaults
sideEffects: None
- clientConfig:
service:
name: {{ template "consul.fullname" . }}-controller-webhook
namespace: {{ .Release.Namespace }}
path: /mutate-v1alpha1-mesh
failurePolicy: Fail
admissionReviewVersions:
- "v1beta1"
- "v1"
name: mutate-mesh.consul.hashicorp.com
rules:
- apiGroups:
- consul.hashicorp.com
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- meshes
sideEffects: None
- clientConfig:
service:
name: {{ template "consul.fullname" . }}-controller-webhook
namespace: {{ .Release.Namespace }}
path: /mutate-v1alpha1-servicedefaults
failurePolicy: Fail
admissionReviewVersions:
- "v1beta1"
- "v1"
name: mutate-servicedefaults.consul.hashicorp.com
rules:
- apiGroups:
- consul.hashicorp.com
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- servicedefaults
sideEffects: None
- clientConfig:
service:
name: {{ template "consul.fullname" . }}-controller-webhook
namespace: {{ .Release.Namespace }}
path: /mutate-v1alpha1-serviceresolver
failurePolicy: Fail
admissionReviewVersions:
- "v1beta1"
- "v1"
name: mutate-serviceresolver.consul.hashicorp.com
rules:
- apiGroups:
- consul.hashicorp.com
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- serviceresolvers
sideEffects: None
- clientConfig:
service:
name: {{ template "consul.fullname" . }}-controller-webhook
namespace: {{ .Release.Namespace }}
path: /mutate-v1alpha1-servicerouter
failurePolicy: Fail
admissionReviewVersions:
- "v1beta1"
- "v1"
name: mutate-servicerouter.consul.hashicorp.com
rules:
- apiGroups:
- consul.hashicorp.com
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- servicerouters
sideEffects: None
- clientConfig:
service:
name: {{ template "consul.fullname" . }}-controller-webhook
namespace: {{ .Release.Namespace }}
path: /mutate-v1alpha1-servicesplitter
failurePolicy: Fail
admissionReviewVersions:
- "v1beta1"
- "v1"
name: mutate-servicesplitter.consul.hashicorp.com
rules:
- apiGroups:
- consul.hashicorp.com
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- servicesplitters
sideEffects: None
- clientConfig:
service:
name: {{ template "consul.fullname" . }}-controller-webhook
namespace: {{ .Release.Namespace }}
path: /mutate-v1alpha1-serviceintentions
failurePolicy: Fail
admissionReviewVersions:
- "v1beta1"
- "v1"
name: mutate-serviceintentions.consul.hashicorp.com
rules:
- apiGroups:
- consul.hashicorp.com
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- serviceintentions
sideEffects: None
- clientConfig:
service:
name: {{ template "consul.fullname" . }}-controller-webhook
namespace: {{ .Release.Namespace }}
path: /mutate-v1alpha1-ingressgateway
failurePolicy: Fail
admissionReviewVersions:
- "v1beta1"
- "v1"
name: mutate-ingressgateway.consul.hashicorp.com
rules:
- apiGroups:
- consul.hashicorp.com
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- ingressgateways
sideEffects: None
- clientConfig:
service:
name: {{ template "consul.fullname" . }}-controller-webhook
namespace: {{ .Release.Namespace }}
path: /mutate-v1alpha1-terminatinggateway
failurePolicy: Fail
admissionReviewVersions:
- "v1beta1"
- "v1"
name: mutate-terminatinggateway.consul.hashicorp.com
rules:
- apiGroups:
- consul.hashicorp.com
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- terminatinggateways
sideEffects: None
- clientConfig:
service:
name: {{ template "consul.fullname" . }}-controller-webhook
namespace: {{ .Release.Namespace }}
path: /mutate-v1alpha1-exportedservices
failurePolicy: Fail
admissionReviewVersions:
- "v1beta1"
- "v1"
name: mutate-exportedservices.consul.hashicorp.com
rules:
- apiGroups:
- consul.hashicorp.com
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- exportedservices
sideEffects: None
{{- end }}

View File

@ -0,0 +1,40 @@
{{- if and .Values.controller.enabled .Values.global.enablePodSecurityPolicies }}
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: {{ template "consul.fullname" . }}-controller
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: controller
spec:
privileged: false
# Required to prevent escalations to root.
allowPrivilegeEscalation: false
# This is redundant with non-root + disallow privilege escalation,
# but we can provide it for defense in depth.
requiredDropCapabilities:
- ALL
# Allow core volume types.
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
hostNetwork: false
hostIPC: false
hostPID: false
runAsUser:
rule: 'RunAsAny'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'
readOnlyRootFilesystem: false
{{- end }}

View File

@ -0,0 +1,23 @@
{{- if .Values.controller.enabled }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "consul.fullname" . }}-controller
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: controller
{{- if .Values.controller.serviceAccount.annotations }}
annotations:
{{ tpl .Values.controller.serviceAccount.annotations . | nindent 4 | trim }}
{{- end }}
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- range . }}
- name: {{ .name }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,23 @@
{{- if .Values.controller.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ template "consul.fullname" . }}-controller-webhook
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: controller
spec:
ports:
- port: 443
targetPort: 9443
selector:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: controller
{{- end }}

View File

@ -0,0 +1,143 @@
{{- if .Values.controller.enabled }}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: exportedservices.consul.hashicorp.com
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: crd
spec:
group: consul.hashicorp.com
names:
kind: ExportedServices
listKind: ExportedServicesList
plural: exportedservices
shortNames:
- exported-services
singular: exportedservices
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: The sync status of the resource with Consul
jsonPath: .status.conditions[?(@.type=="Synced")].status
name: Synced
type: string
- description: The last successful synced time of the resource with Consul
jsonPath: .status.lastSyncedTime
name: Last Synced
type: date
- description: The age of the resource
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: ExportedServices is the Schema for the exportedservices API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ExportedServicesSpec defines the desired state of ExportedServices.
properties:
services:
description: Services is a list of services to be exported and the
list of partitions to expose them to.
items:
description: ExportedService manages the exporting of a service
in the local partition to other partitions.
properties:
consumers:
description: Consumers is a list of downstream consumers of
the service to be exported.
items:
description: ServiceConsumer represents a downstream consumer
of the service to be exported.
properties:
partition:
description: Partition is the admin partition to export
the service to.
type: string
peer:
description: '[Experimental] Peer is the name of the peer
to export the service to.'
type: string
type: object
type: array
name:
description: Name is the name of the service to be exported.
type: string
namespace:
description: Namespace is the namespace to export the service
from.
type: string
type: object
type: array
type: object
status:
properties:
conditions:
description: Conditions indicate the latest available observations
of a resource's current state.
items:
description: 'Conditions define a readiness condition for a Consul
resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties'
properties:
lastTransitionTime:
description: LastTransitionTime is the last time the condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition.
type: string
required:
- status
- type
type: object
type: array
lastSyncedTime:
description: LastSyncedTime is the last time the resource successfully
synced with Consul.
format: date-time
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
{{- end }}

View File

@ -0,0 +1,336 @@
{{- if .Values.controller.enabled }}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: ingressgateways.consul.hashicorp.com
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: crd
spec:
group: consul.hashicorp.com
names:
kind: IngressGateway
listKind: IngressGatewayList
plural: ingressgateways
shortNames:
- ingress-gateway
singular: ingressgateway
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: The sync status of the resource with Consul
jsonPath: .status.conditions[?(@.type=="Synced")].status
name: Synced
type: string
- description: The last successful synced time of the resource with Consul
jsonPath: .status.lastSyncedTime
name: Last Synced
type: date
- description: The age of the resource
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: IngressGateway is the Schema for the ingressgateways API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: IngressGatewaySpec defines the desired state of IngressGateway.
properties:
listeners:
description: Listeners declares what ports the ingress gateway should
listen on, and what services to associated to those ports.
items:
description: IngressListener manages the configuration for a listener
on a specific port.
properties:
port:
description: Port declares the port on which the ingress gateway
should listen for traffic.
type: integer
protocol:
description: 'Protocol declares what type of traffic this listener
is expected to receive. Depending on the protocol, a listener
might support multiplexing services over a single port, or
additional discovery chain features. The current supported
values are: (tcp | http | http2 | grpc).'
type: string
services:
description: Services declares the set of services to which
the listener forwards traffic. For "tcp" protocol listeners,
only a single service is allowed. For "http" listeners, multiple
services can be declared.
items:
description: IngressService manages configuration for services
that are exposed to ingress traffic.
properties:
hosts:
description: "Hosts is a list of hostnames which should
be associated to this service on the defined listener.
Only allowed on layer 7 protocols, this will be used
to route traffic to the service by matching the Host
header of the HTTP request. \n If a host is provided
for a service that also has a wildcard specifier defined,
the host will override the wildcard-specifier-provided
\"<service-name>.*\" domain for that listener. \n This
cannot be specified when using the wildcard specifier,
\"*\", or when using a \"tcp\" listener."
items:
type: string
type: array
name:
description: "Name declares the service to which traffic
should be forwarded. \n This can either be a specific
service, or the wildcard specifier, \"*\". If the wildcard
specifier is provided, the listener must be of \"http\"
protocol and means that the listener will forward traffic
to all services. \n A name can be specified on multiple
listeners, and will be exposed on both of the listeners."
type: string
namespace:
description: Namespace is the namespace where the service
is located. Namespacing is a Consul Enterprise feature.
type: string
partition:
description: Partition is the admin-partition where the
service is located. Partitioning is a Consul Enterprise
feature.
type: string
requestHeaders:
description: Allow HTTP header manipulation to be configured.
properties:
add:
additionalProperties:
type: string
description: Add is a set of name -> value pairs that
should be appended to the request or response (i.e.
allowing duplicates if the same header already exists).
type: object
remove:
description: Remove is the set of header names that
should be stripped from the request or response.
items:
type: string
type: array
set:
additionalProperties:
type: string
description: Set is a set of name -> value pairs that
should be added to the request or response, overwriting
any existing header values of the same name.
type: object
type: object
responseHeaders:
description: HTTPHeaderModifiers is a set of rules for
HTTP header modification that should be performed by
proxies as the request passes through them. It can operate
on either request or response headers depending on the
context in which it is used.
properties:
add:
additionalProperties:
type: string
description: Add is a set of name -> value pairs that
should be appended to the request or response (i.e.
allowing duplicates if the same header already exists).
type: object
remove:
description: Remove is the set of header names that
should be stripped from the request or response.
items:
type: string
type: array
set:
additionalProperties:
type: string
description: Set is a set of name -> value pairs that
should be added to the request or response, overwriting
any existing header values of the same name.
type: object
type: object
tls:
description: TLS allows specifying some TLS configuration
per listener.
properties:
sds:
description: SDS allows configuring TLS certificate
from an SDS service.
properties:
certResource:
description: CertResource is the SDS resource
name to request when fetching the certificate
from the SDS service.
type: string
clusterName:
description: ClusterName is the SDS cluster name
to connect to, to retrieve certificates. This
cluster must be specified in the Gateway's bootstrap
configuration.
type: string
type: object
type: object
type: object
type: array
tls:
description: TLS config for this listener.
properties:
cipherSuites:
description: Define a subset of cipher suites to restrict
Only applicable to connections negotiated via TLS 1.2
or earlier.
items:
type: string
type: array
enabled:
description: Indicates that TLS should be enabled for this
gateway service.
type: boolean
sds:
description: SDS allows configuring TLS certificate from
an SDS service.
properties:
certResource:
description: CertResource is the SDS resource name to
request when fetching the certificate from the SDS
service.
type: string
clusterName:
description: ClusterName is the SDS cluster name to
connect to, to retrieve certificates. This cluster
must be specified in the Gateway's bootstrap configuration.
type: string
type: object
tlsMaxVersion:
description: TLSMaxVersion sets the default maximum TLS
version supported. Must be greater than or equal to `TLSMinVersion`.
One of `TLS_AUTO`, `TLSv1_0`, `TLSv1_1`, `TLSv1_2`, or
`TLSv1_3`. If unspecified, Envoy will default to TLS 1.3
as a max version for incoming connections.
type: string
tlsMinVersion:
description: TLSMinVersion sets the default minimum TLS
version supported. One of `TLS_AUTO`, `TLSv1_0`, `TLSv1_1`,
`TLSv1_2`, or `TLSv1_3`. If unspecified, Envoy v1.22.0
and newer will default to TLS 1.2 as a min version, while
older releases of Envoy default to TLS 1.0.
type: string
required:
- enabled
type: object
type: object
type: array
tls:
description: TLS holds the TLS configuration for this gateway.
properties:
cipherSuites:
description: Define a subset of cipher suites to restrict Only
applicable to connections negotiated via TLS 1.2 or earlier.
items:
type: string
type: array
enabled:
description: Indicates that TLS should be enabled for this gateway
service.
type: boolean
sds:
description: SDS allows configuring TLS certificate from an SDS
service.
properties:
certResource:
description: CertResource is the SDS resource name to request
when fetching the certificate from the SDS service.
type: string
clusterName:
description: ClusterName is the SDS cluster name to connect
to, to retrieve certificates. This cluster must be specified
in the Gateway's bootstrap configuration.
type: string
type: object
tlsMaxVersion:
description: TLSMaxVersion sets the default maximum TLS version
supported. Must be greater than or equal to `TLSMinVersion`.
One of `TLS_AUTO`, `TLSv1_0`, `TLSv1_1`, `TLSv1_2`, or `TLSv1_3`.
If unspecified, Envoy will default to TLS 1.3 as a max version
for incoming connections.
type: string
tlsMinVersion:
description: TLSMinVersion sets the default minimum TLS version
supported. One of `TLS_AUTO`, `TLSv1_0`, `TLSv1_1`, `TLSv1_2`,
or `TLSv1_3`. If unspecified, Envoy v1.22.0 and newer will default
to TLS 1.2 as a min version, while older releases of Envoy default
to TLS 1.0.
type: string
required:
- enabled
type: object
type: object
status:
properties:
conditions:
description: Conditions indicate the latest available observations
of a resource's current state.
items:
description: 'Conditions define a readiness condition for a Consul
resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties'
properties:
lastTransitionTime:
description: LastTransitionTime is the last time the condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition.
type: string
required:
- status
- type
type: object
type: array
lastSyncedTime:
description: LastSyncedTime is the last time the resource successfully
synced with Consul.
format: date-time
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
{{- end }}

View File

@ -0,0 +1,198 @@
{{- if .Values.controller.enabled }}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: meshes.consul.hashicorp.com
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: crd
spec:
group: consul.hashicorp.com
names:
kind: Mesh
listKind: MeshList
plural: meshes
singular: mesh
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: The sync status of the resource with Consul
jsonPath: .status.conditions[?(@.type=="Synced")].status
name: Synced
type: string
- description: The last successful synced time of the resource with Consul
jsonPath: .status.lastSyncedTime
name: Last Synced
type: date
- description: The age of the resource
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: Mesh is the Schema for the mesh API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: MeshSpec defines the desired state of Mesh.
properties:
http:
description: HTTP defines the HTTP configuration for the service mesh.
properties:
sanitizeXForwardedClientCert:
type: boolean
required:
- sanitizeXForwardedClientCert
type: object
tls:
description: TLS defines the TLS configuration for the service mesh.
properties:
incoming:
description: Incoming defines the TLS configuration for inbound
mTLS connections targeting the public listener on Connect and
TerminatingGateway proxy kinds.
properties:
cipherSuites:
description: CipherSuites sets the default list of TLS cipher
suites to support when negotiating connections using TLS
1.2 or earlier. If unspecified, Envoy will use a default
server cipher list. The list of supported cipher suites
can be seen in https://github.com/hashicorp/consul/blob/v1.11.2/types/tls.go#L154-L169
and is dependent on underlying support in Envoy. Future
releases of Envoy may remove currently-supported but insecure
cipher suites, and future releases of Consul may add new
supported cipher suites if any are added to Envoy.
items:
type: string
type: array
tlsMaxVersion:
description: TLSMaxVersion sets the default maximum TLS version
supported. Must be greater than or equal to `TLSMinVersion`.
One of `TLS_AUTO`, `TLSv1_0`, `TLSv1_1`, `TLSv1_2`, or `TLSv1_3`.
If unspecified, Envoy will default to TLS 1.3 as a max version
for incoming connections.
type: string
tlsMinVersion:
description: TLSMinVersion sets the default minimum TLS version
supported. One of `TLS_AUTO`, `TLSv1_0`, `TLSv1_1`, `TLSv1_2`,
or `TLSv1_3`. If unspecified, Envoy v1.22.0 and newer will
default to TLS 1.2 as a min version, while older releases
of Envoy default to TLS 1.0.
type: string
type: object
outgoing:
description: Outgoing defines the TLS configuration for outbound
mTLS connections dialing upstreams from Connect and IngressGateway
proxy kinds.
properties:
cipherSuites:
description: CipherSuites sets the default list of TLS cipher
suites to support when negotiating connections using TLS
1.2 or earlier. If unspecified, Envoy will use a default
server cipher list. The list of supported cipher suites
can be seen in https://github.com/hashicorp/consul/blob/v1.11.2/types/tls.go#L154-L169
and is dependent on underlying support in Envoy. Future
releases of Envoy may remove currently-supported but insecure
cipher suites, and future releases of Consul may add new
supported cipher suites if any are added to Envoy.
items:
type: string
type: array
tlsMaxVersion:
description: TLSMaxVersion sets the default maximum TLS version
supported. Must be greater than or equal to `TLSMinVersion`.
One of `TLS_AUTO`, `TLSv1_0`, `TLSv1_1`, `TLSv1_2`, or `TLSv1_3`.
If unspecified, Envoy will default to TLS 1.3 as a max version
for incoming connections.
type: string
tlsMinVersion:
description: TLSMinVersion sets the default minimum TLS version
supported. One of `TLS_AUTO`, `TLSv1_0`, `TLSv1_1`, `TLSv1_2`,
or `TLSv1_3`. If unspecified, Envoy v1.22.0 and newer will
default to TLS 1.2 as a min version, while older releases
of Envoy default to TLS 1.0.
type: string
type: object
type: object
transparentProxy:
description: TransparentProxy controls the configuration specific
to proxies in "transparent" mode. Added in v1.10.0.
properties:
meshDestinationsOnly:
description: MeshDestinationsOnly determines whether sidecar proxies
operating in "transparent" mode can proxy traffic to IP addresses
not registered in Consul's catalog. If enabled, traffic will
only be proxied to upstreams with service registrations in the
catalog.
type: boolean
type: object
type: object
status:
properties:
conditions:
description: Conditions indicate the latest available observations
of a resource's current state.
items:
description: 'Conditions define a readiness condition for a Consul
resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties'
properties:
lastTransitionTime:
description: LastTransitionTime is the last time the condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition.
type: string
required:
- status
- type
type: object
type: array
lastSyncedTime:
description: LastSyncedTime is the last time the resource successfully
synced with Consul.
format: date-time
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
{{- end }}

View File

@ -0,0 +1,154 @@
{{- if and .Values.connectInject.enabled .Values.global.peering.enabled }}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: peeringacceptors.consul.hashicorp.com
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: crd
spec:
group: consul.hashicorp.com
names:
kind: PeeringAcceptor
listKind: PeeringAcceptorList
plural: peeringacceptors
shortNames:
- peering-acceptor
singular: peeringacceptor
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: The sync status of the resource with Consul
jsonPath: .status.conditions[?(@.type=="Synced")].status
name: Synced
type: string
- description: The last successful synced time of the resource with Consul
jsonPath: .status.lastSyncedTime
name: Last Synced
type: date
- description: The age of the resource
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: PeeringAcceptor is the Schema for the peeringacceptors API.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: PeeringAcceptorSpec defines the desired state of PeeringAcceptor.
properties:
peer:
description: Peer describes the information needed to create a peering.
properties:
secret:
description: Secret describes how to store the generated peering
token.
properties:
backend:
description: 'Backend is where the generated secret is stored.
Currently supports the value: "kubernetes".'
type: string
key:
description: Key is the key of the secret generated.
type: string
name:
description: Name is the name of the secret generated.
type: string
type: object
type: object
required:
- peer
type: object
status:
description: PeeringAcceptorStatus defines the observed state of PeeringAcceptor.
properties:
conditions:
description: Conditions indicate the latest available observations
of a resource's current state.
items:
description: 'Conditions define a readiness condition for a Consul
resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties'
properties:
lastTransitionTime:
description: LastTransitionTime is the last time the condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition.
type: string
required:
- status
- type
type: object
type: array
lastSyncedTime:
description: LastSyncedTime is the last time the resource successfully
synced with Consul.
format: date-time
type: string
latestPeeringVersion:
description: LatestPeeringVersion is the latest version of the resource
that was reconciled.
format: int64
type: integer
secret:
description: SecretRef shows the status of the secret.
properties:
backend:
description: 'Backend is where the generated secret is stored.
Currently supports the value: "kubernetes".'
type: string
key:
description: Key is the key of the secret generated.
type: string
name:
description: Name is the name of the secret generated.
type: string
resourceVersion:
description: ResourceVersion is the resource version for the secret.
type: string
type: object
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
{{- end }}

View File

@ -0,0 +1,154 @@
{{- if and .Values.connectInject.enabled .Values.global.peering.enabled }}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: peeringdialers.consul.hashicorp.com
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: crd
spec:
group: consul.hashicorp.com
names:
kind: PeeringDialer
listKind: PeeringDialerList
plural: peeringdialers
shortNames:
- peering-dialer
singular: peeringdialer
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: The sync status of the resource with Consul
jsonPath: .status.conditions[?(@.type=="Synced")].status
name: Synced
type: string
- description: The last successful synced time of the resource with Consul
jsonPath: .status.lastSyncedTime
name: Last Synced
type: date
- description: The age of the resource
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: PeeringDialer is the Schema for the peeringdialers API.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: PeeringDialerSpec defines the desired state of PeeringDialer.
properties:
peer:
description: Peer describes the information needed to create a peering.
properties:
secret:
description: Secret describes how to store the generated peering
token.
properties:
backend:
description: 'Backend is where the generated secret is stored.
Currently supports the value: "kubernetes".'
type: string
key:
description: Key is the key of the secret generated.
type: string
name:
description: Name is the name of the secret generated.
type: string
type: object
type: object
required:
- peer
type: object
status:
description: PeeringDialerStatus defines the observed state of PeeringDialer.
properties:
conditions:
description: Conditions indicate the latest available observations
of a resource's current state.
items:
description: 'Conditions define a readiness condition for a Consul
resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties'
properties:
lastTransitionTime:
description: LastTransitionTime is the last time the condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition.
type: string
required:
- status
- type
type: object
type: array
lastSyncedTime:
description: LastSyncedTime is the last time the resource successfully
synced with Consul.
format: date-time
type: string
latestPeeringVersion:
description: LatestPeeringVersion is the latest version of the resource
that was reconciled.
format: int64
type: integer
secret:
description: SecretRef shows the status of the secret.
properties:
backend:
description: 'Backend is where the generated secret is stored.
Currently supports the value: "kubernetes".'
type: string
key:
description: Key is the key of the secret generated.
type: string
name:
description: Name is the name of the secret generated.
type: string
resourceVersion:
description: ResourceVersion is the resource version for the secret.
type: string
type: object
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
{{- end }}

View File

@ -0,0 +1,186 @@
{{- if .Values.controller.enabled }}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: proxydefaults.consul.hashicorp.com
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: crd
spec:
group: consul.hashicorp.com
names:
kind: ProxyDefaults
listKind: ProxyDefaultsList
plural: proxydefaults
shortNames:
- proxy-defaults
singular: proxydefaults
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: The sync status of the resource with Consul
jsonPath: .status.conditions[?(@.type=="Synced")].status
name: Synced
type: string
- description: The last successful synced time of the resource with Consul
jsonPath: .status.lastSyncedTime
name: Last Synced
type: date
- description: The age of the resource
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: ProxyDefaults is the Schema for the proxydefaults API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ProxyDefaultsSpec defines the desired state of ProxyDefaults.
properties:
config:
description: Config is an arbitrary map of configuration values used
by Connect proxies. Any values that your proxy allows can be configured
globally here. Supports JSON config values. See https://www.consul.io/docs/connect/proxies/envoy#configuration-formatting
type: object
x-kubernetes-preserve-unknown-fields: true
expose:
description: Expose controls the default expose path configuration
for Envoy.
properties:
checks:
description: Checks defines whether paths associated with Consul
checks will be exposed. This flag triggers exposing all HTTP
and GRPC check paths registered for the service.
type: boolean
paths:
description: Paths is the list of paths exposed through the proxy.
items:
properties:
listenerPort:
description: ListenerPort defines the port of the proxy's
listener for exposed paths.
type: integer
localPathPort:
description: LocalPathPort is the port that the service
is listening on for the given path.
type: integer
path:
description: Path is the path to expose through the proxy,
ie. "/metrics".
type: string
protocol:
description: Protocol describes the upstream's service protocol.
Valid values are "http" and "http2", defaults to "http".
type: string
type: object
type: array
type: object
meshGateway:
description: MeshGateway controls the default mesh gateway configuration
for this service.
properties:
mode:
description: Mode is the mode that should be used for the upstream
connection. One of none, local, or remote.
type: string
type: object
mode:
description: 'Mode can be one of "direct" or "transparent". "transparent"
represents that inbound and outbound application traffic is being
captured and redirected through the proxy. This mode does not enable
the traffic redirection itself. Instead it signals Consul to configure
Envoy as if traffic is already being redirected. "direct" represents
that the proxy''s listeners must be dialed directly by the local
application and other proxies. Note: This cannot be set using the
CRD and should be set using annotations on the services that are
part of the mesh.'
type: string
transparentProxy:
description: 'TransparentProxy controls configuration specific to
proxies in transparent mode. Note: This cannot be set using the
CRD and should be set using annotations on the services that are
part of the mesh.'
properties:
dialedDirectly:
description: DialedDirectly indicates whether transparent proxies
can dial this proxy instance directly. The discovery chain is
not considered when dialing a service instance directly. This
setting is useful when addressing stateful services, such as
a database cluster with a leader node.
type: boolean
outboundListenerPort:
description: OutboundListenerPort is the port of the listener
where outbound application traffic is being redirected to.
type: integer
type: object
type: object
status:
properties:
conditions:
description: Conditions indicate the latest available observations
of a resource's current state.
items:
description: 'Conditions define a readiness condition for a Consul
resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties'
properties:
lastTransitionTime:
description: LastTransitionTime is the last time the condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition.
type: string
required:
- status
- type
type: object
type: array
lastSyncedTime:
description: LastSyncedTime is the last time the resource successfully
synced with Consul.
format: date-time
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
{{- end }}

View File

@ -0,0 +1,422 @@
{{- if .Values.controller.enabled }}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: servicedefaults.consul.hashicorp.com
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: crd
spec:
group: consul.hashicorp.com
names:
kind: ServiceDefaults
listKind: ServiceDefaultsList
plural: servicedefaults
shortNames:
- service-defaults
singular: servicedefaults
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: The sync status of the resource with Consul
jsonPath: .status.conditions[?(@.type=="Synced")].status
name: Synced
type: string
- description: The last successful synced time of the resource with Consul
jsonPath: .status.lastSyncedTime
name: Last Synced
type: date
- description: The age of the resource
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: ServiceDefaults is the Schema for the servicedefaults API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ServiceDefaultsSpec defines the desired state of ServiceDefaults.
properties:
destination:
description: Destination is an address(es)/port combination that represents
an endpoint outside the mesh. This is only valid when the mesh is
configured in "transparent" mode. Destinations live outside of Consul's
catalog, and because of this, they do not require an artificial
node to be created.
properties:
addresses:
description: Addresses is a list of IPs and/or hostnames that
can be dialed and routed through a terminating gateway.
items:
type: string
type: array
port:
description: Port is the port that can be dialed on any of the
addresses in this Destination.
format: int32
type: integer
type: object
expose:
description: Expose controls the default expose path configuration
for Envoy.
properties:
checks:
description: Checks defines whether paths associated with Consul
checks will be exposed. This flag triggers exposing all HTTP
and GRPC check paths registered for the service.
type: boolean
paths:
description: Paths is the list of paths exposed through the proxy.
items:
properties:
listenerPort:
description: ListenerPort defines the port of the proxy's
listener for exposed paths.
type: integer
localPathPort:
description: LocalPathPort is the port that the service
is listening on for the given path.
type: integer
path:
description: Path is the path to expose through the proxy,
ie. "/metrics".
type: string
protocol:
description: Protocol describes the upstream's service protocol.
Valid values are "http" and "http2", defaults to "http".
type: string
type: object
type: array
type: object
externalSNI:
description: ExternalSNI is an optional setting that allows for the
TLS SNI value to be changed to a non-connect value when federating
with an external system.
type: string
maxInboundConnections:
description: MaxInboundConnections is the maximum number of concurrent
inbound connections to each service instance. Defaults to 0 (using
consul's default) if not set.
type: integer
meshGateway:
description: MeshGateway controls the default mesh gateway configuration
for this service.
properties:
mode:
description: Mode is the mode that should be used for the upstream
connection. One of none, local, or remote.
type: string
type: object
mode:
description: 'Mode can be one of "direct" or "transparent". "transparent"
represents that inbound and outbound application traffic is being
captured and redirected through the proxy. This mode does not enable
the traffic redirection itself. Instead it signals Consul to configure
Envoy as if traffic is already being redirected. "direct" represents
that the proxy''s listeners must be dialed directly by the local
application and other proxies. Note: This cannot be set using the
CRD and should be set using annotations on the services that are
part of the mesh.'
type: string
protocol:
description: Protocol sets the protocol of the service. This is used
by Connect proxies for things like observability features and to
unlock usage of the service-splitter and service-router config entries
for a service.
type: string
transparentProxy:
description: 'TransparentProxy controls configuration specific to
proxies in transparent mode. Note: This cannot be set using the
CRD and should be set using annotations on the services that are
part of the mesh.'
properties:
dialedDirectly:
description: DialedDirectly indicates whether transparent proxies
can dial this proxy instance directly. The discovery chain is
not considered when dialing a service instance directly. This
setting is useful when addressing stateful services, such as
a database cluster with a leader node.
type: boolean
outboundListenerPort:
description: OutboundListenerPort is the port of the listener
where outbound application traffic is being redirected to.
type: integer
type: object
upstreamConfig:
description: UpstreamConfig controls default configuration settings
that apply across all upstreams, and per-upstream configuration
overrides. Note that per-upstream configuration applies across all
federated datacenters to the pairing of source and upstream destination
services.
properties:
defaults:
description: Defaults contains default configuration for all upstreams
of a given service. The name field must be empty.
properties:
connectTimeoutMs:
description: ConnectTimeoutMs is the number of milliseconds
to timeout making a new connection to this upstream. Defaults
to 5000 (5 seconds) if not set.
type: integer
envoyClusterJSON:
description: 'EnvoyClusterJSON is a complete override ("escape
hatch") for the upstream''s cluster. The Connect client
TLS certificate and context will be injected overriding
any TLS settings present. Note: This escape hatch is NOT
compatible with the discovery chain and will be ignored
if a discovery chain is active.'
type: string
envoyListenerJSON:
description: 'EnvoyListenerJSON is a complete override ("escape
hatch") for the upstream''s listener. Note: This escape
hatch is NOT compatible with the discovery chain and will
be ignored if a discovery chain is active.'
type: string
limits:
description: Limits are the set of limits that are applied
to the proxy for a specific upstream of a service instance.
properties:
maxConcurrentRequests:
description: MaxConcurrentRequests is the maximum number
of in-flight requests that will be allowed to the upstream
cluster at a point in time. This is mostly applicable
to HTTP/2 clusters since all HTTP/1.1 requests are limited
by MaxConnections.
type: integer
maxConnections:
description: MaxConnections is the maximum number of connections
the local proxy can make to the upstream service.
type: integer
maxPendingRequests:
description: MaxPendingRequests is the maximum number
of requests that will be queued waiting for an available
connection. This is mostly applicable to HTTP/1.1 clusters
since all HTTP/2 requests are streamed over a single
connection.
type: integer
type: object
meshGateway:
description: MeshGatewayConfig controls how Mesh Gateways
are configured and used.
properties:
mode:
description: Mode is the mode that should be used for
the upstream connection. One of none, local, or remote.
type: string
type: object
name:
description: Name is only accepted within a service-defaults
config entry.
type: string
namespace:
description: Namespace is only accepted within a service-defaults
config entry.
type: string
partition:
description: Partition is only accepted within a service-defaults
config entry.
type: string
passiveHealthCheck:
description: PassiveHealthCheck configuration determines how
upstream proxy instances will be monitored for removal from
the load balancing pool.
properties:
enforcing_consecutive_5xx:
description: EnforcingConsecutive5xx is the % chance that
a host will be actually ejected when an outlier status
is detected through consecutive 5xx. This setting can
be used to disable ejection or to ramp it up slowly.
format: int32
type: integer
interval:
description: Interval between health check analysis sweeps.
Each sweep may remove hosts or return hosts to the pool.
type: string
maxFailures:
description: MaxFailures is the count of consecutive failures
that results in a host being removed from the pool.
format: int32
type: integer
type: object
protocol:
description: Protocol describes the upstream's service protocol.
Valid values are "tcp", "http" and "grpc". Anything else
is treated as tcp. This enables protocol aware features
like per-request metrics and connection pooling, tracing,
routing etc.
type: string
type: object
overrides:
description: Overrides is a slice of per-service configuration.
The name field is required.
items:
properties:
connectTimeoutMs:
description: ConnectTimeoutMs is the number of milliseconds
to timeout making a new connection to this upstream. Defaults
to 5000 (5 seconds) if not set.
type: integer
envoyClusterJSON:
description: 'EnvoyClusterJSON is a complete override ("escape
hatch") for the upstream''s cluster. The Connect client
TLS certificate and context will be injected overriding
any TLS settings present. Note: This escape hatch is NOT
compatible with the discovery chain and will be ignored
if a discovery chain is active.'
type: string
envoyListenerJSON:
description: 'EnvoyListenerJSON is a complete override ("escape
hatch") for the upstream''s listener. Note: This escape
hatch is NOT compatible with the discovery chain and will
be ignored if a discovery chain is active.'
type: string
limits:
description: Limits are the set of limits that are applied
to the proxy for a specific upstream of a service instance.
properties:
maxConcurrentRequests:
description: MaxConcurrentRequests is the maximum number
of in-flight requests that will be allowed to the
upstream cluster at a point in time. This is mostly
applicable to HTTP/2 clusters since all HTTP/1.1 requests
are limited by MaxConnections.
type: integer
maxConnections:
description: MaxConnections is the maximum number of
connections the local proxy can make to the upstream
service.
type: integer
maxPendingRequests:
description: MaxPendingRequests is the maximum number
of requests that will be queued waiting for an available
connection. This is mostly applicable to HTTP/1.1
clusters since all HTTP/2 requests are streamed over
a single connection.
type: integer
type: object
meshGateway:
description: MeshGatewayConfig controls how Mesh Gateways
are configured and used.
properties:
mode:
description: Mode is the mode that should be used for
the upstream connection. One of none, local, or remote.
type: string
type: object
name:
description: Name is only accepted within a service-defaults
config entry.
type: string
namespace:
description: Namespace is only accepted within a service-defaults
config entry.
type: string
partition:
description: Partition is only accepted within a service-defaults
config entry.
type: string
passiveHealthCheck:
description: PassiveHealthCheck configuration determines
how upstream proxy instances will be monitored for removal
from the load balancing pool.
properties:
enforcing_consecutive_5xx:
description: EnforcingConsecutive5xx is the % chance
that a host will be actually ejected when an outlier
status is detected through consecutive 5xx. This setting
can be used to disable ejection or to ramp it up slowly.
format: int32
type: integer
interval:
description: Interval between health check analysis
sweeps. Each sweep may remove hosts or return hosts
to the pool.
type: string
maxFailures:
description: MaxFailures is the count of consecutive
failures that results in a host being removed from
the pool.
format: int32
type: integer
type: object
protocol:
description: Protocol describes the upstream's service protocol.
Valid values are "tcp", "http" and "grpc". Anything else
is treated as tcp. This enables protocol aware features
like per-request metrics and connection pooling, tracing,
routing etc.
type: string
type: object
type: array
type: object
type: object
status:
properties:
conditions:
description: Conditions indicate the latest available observations
of a resource's current state.
items:
description: 'Conditions define a readiness condition for a Consul
resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties'
properties:
lastTransitionTime:
description: LastTransitionTime is the last time the condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition.
type: string
required:
- status
- type
type: object
type: array
lastSyncedTime:
description: LastSyncedTime is the last time the resource successfully
synced with Consul.
format: date-time
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
{{- end }}

View File

@ -0,0 +1,241 @@
{{- if .Values.controller.enabled }}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: serviceintentions.consul.hashicorp.com
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: crd
spec:
group: consul.hashicorp.com
names:
kind: ServiceIntentions
listKind: ServiceIntentionsList
plural: serviceintentions
shortNames:
- service-intentions
singular: serviceintentions
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: The sync status of the resource with Consul
jsonPath: .status.conditions[?(@.type=="Synced")].status
name: Synced
type: string
- description: The last successful synced time of the resource with Consul
jsonPath: .status.lastSyncedTime
name: Last Synced
type: date
- description: The age of the resource
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: ServiceIntentions is the Schema for the serviceintentions API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ServiceIntentionsSpec defines the desired state of ServiceIntentions.
properties:
destination:
description: Destination is the intention destination that will have
the authorization granted to.
properties:
name:
description: Name is the destination of all intentions defined
in this config entry. This may be set to the wildcard character
(*) to match all services that don't otherwise have intentions
defined.
type: string
namespace:
description: Namespace specifies the namespace the config entry
will apply to. This may be set to the wildcard character (*)
to match all services in all namespaces that don't otherwise
have intentions defined.
type: string
type: object
sources:
description: Sources is the list of all intention sources and the
authorization granted to those sources. The order of this list does
not matter, but out of convenience Consul will always store this
reverse sorted by intention precedence, as that is the order that
they will be evaluated at enforcement time.
items:
properties:
action:
description: Action is required for an L4 intention, and should
be set to one of "allow" or "deny" for the action that should
be taken if this intention matches a request.
type: string
description:
description: Description for the intention. This is not used
by Consul, but is presented in API responses to assist tooling.
type: string
name:
description: Name is the source of the intention. This is the
name of a Consul service. The service doesn't need to be registered.
type: string
namespace:
description: Namespace is the namespace for the Name parameter.
type: string
partition:
description: Partition is the Admin Partition for the Name parameter.
type: string
peer:
description: '[Experimental] Peer is the peer name for the Name
parameter.'
type: string
permissions:
description: Permissions is the list of all additional L7 attributes
that extend the intention match criteria. Permission precedence
is applied top to bottom. For any given request the first
permission to match in the list is terminal and stops further
evaluation. As with L4 intentions, traffic that fails to match
any of the provided permissions in this intention will be
subject to the default intention behavior is defined by the
default ACL policy. This should be omitted for an L4 intention
as it is mutually exclusive with the Action field.
items:
properties:
action:
description: Action is one of "allow" or "deny" for the
action that should be taken if this permission matches
a request.
type: string
http:
description: HTTP is a set of HTTP-specific authorization
criteria.
properties:
header:
description: Header is a set of criteria that can
match on HTTP request headers. If more than one
is configured all must match for the overall match
to apply.
items:
properties:
exact:
description: Exact matches if the header with
the given name is this value.
type: string
invert:
description: Invert inverts the logic of the
match.
type: boolean
name:
description: Name is the name of the header
to match.
type: string
prefix:
description: Prefix matches if the header with
the given name has this prefix.
type: string
present:
description: Present matches if the header with
the given name is present with any value.
type: boolean
regex:
description: Regex matches if the header with
the given name matches this pattern.
type: string
suffix:
description: Suffix matches if the header with
the given name has this suffix.
type: string
type: object
type: array
methods:
description: Methods is a list of HTTP methods for
which this match applies. If unspecified all HTTP
methods are matched. If provided the names must
be a valid method.
items:
type: string
type: array
pathExact:
description: PathExact is the exact path to match
on the HTTP request path.
type: string
pathPrefix:
description: PathPrefix is the path prefix to match
on the HTTP request path.
type: string
pathRegex:
description: PathRegex is the regular expression to
match on the HTTP request path.
type: string
type: object
type: object
type: array
type: object
type: array
type: object
status:
properties:
conditions:
description: Conditions indicate the latest available observations
of a resource's current state.
items:
description: 'Conditions define a readiness condition for a Consul
resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties'
properties:
lastTransitionTime:
description: LastTransitionTime is the last time the condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition.
type: string
required:
- status
- type
type: object
type: array
lastSyncedTime:
description: LastSyncedTime is the last time the resource successfully
synced with Consul.
format: date-time
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
{{- end }}

View File

@ -0,0 +1,283 @@
{{- if .Values.controller.enabled }}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: serviceresolvers.consul.hashicorp.com
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: crd
spec:
group: consul.hashicorp.com
names:
kind: ServiceResolver
listKind: ServiceResolverList
plural: serviceresolvers
shortNames:
- service-resolver
singular: serviceresolver
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: The sync status of the resource with Consul
jsonPath: .status.conditions[?(@.type=="Synced")].status
name: Synced
type: string
- description: The last successful synced time of the resource with Consul
jsonPath: .status.lastSyncedTime
name: Last Synced
type: date
- description: The age of the resource
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: ServiceResolver is the Schema for the serviceresolvers API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ServiceResolverSpec defines the desired state of ServiceResolver.
properties:
connectTimeout:
description: ConnectTimeout is the timeout for establishing new network
connections to this service.
type: string
defaultSubset:
description: DefaultSubset is the subset to use when no explicit subset
is requested. If empty the unnamed subset is used.
type: string
failover:
additionalProperties:
properties:
datacenters:
description: Datacenters is a fixed list of datacenters to try
during failover.
items:
type: string
type: array
namespace:
description: Namespace is the namespace to resolve the requested
service from to form the failover group of instances. If empty
the current namespace is used.
type: string
service:
description: Service is the service to resolve instead of the
default as the failover group of instances during failover.
type: string
serviceSubset:
description: ServiceSubset is the named subset of the requested
service to resolve as the failover group of instances. If
empty the default subset for the requested service is used.
type: string
type: object
description: Failover controls when and how to reroute traffic to
an alternate pool of service instances. The map is keyed by the
service subset it applies to and the special string "*" is a wildcard
that applies to any subset not otherwise specified here.
type: object
loadBalancer:
description: LoadBalancer determines the load balancing policy and
configuration for services issuing requests to this upstream service.
properties:
hashPolicies:
description: HashPolicies is a list of hash policies to use for
hashing load balancing algorithms. Hash policies are evaluated
individually and combined such that identical lists result in
the same hash. If no hash policies are present, or none are
successfully evaluated, then a random backend host will be selected.
items:
properties:
cookieConfig:
description: CookieConfig contains configuration for the
"cookie" hash policy type.
properties:
path:
description: Path is the path to set for the cookie.
type: string
session:
description: Session determines whether to generate
a session cookie with no expiration.
type: boolean
ttl:
description: TTL is the ttl for generated cookies. Cannot
be specified for session cookies.
type: string
type: object
field:
description: Field is the attribute type to hash on. Must
be one of "header", "cookie", or "query_parameter". Cannot
be specified along with sourceIP.
type: string
fieldValue:
description: FieldValue is the value to hash. ie. header
name, cookie name, URL query parameter name Cannot be
specified along with sourceIP.
type: string
sourceIP:
description: SourceIP determines whether the hash should
be of the source IP rather than of a field and field value.
Cannot be specified along with field or fieldValue.
type: boolean
terminal:
description: Terminal will short circuit the computation
of the hash when multiple hash policies are present. If
a hash is computed when a Terminal policy is evaluated,
then that hash will be used and subsequent hash policies
will be ignored.
type: boolean
type: object
type: array
leastRequestConfig:
description: LeastRequestConfig contains configuration for the
"leastRequest" policy type.
properties:
choiceCount:
description: ChoiceCount determines the number of random healthy
hosts from which to select the one with the least requests.
format: int32
type: integer
type: object
policy:
description: Policy is the load balancing policy used to select
a host.
type: string
ringHashConfig:
description: RingHashConfig contains configuration for the "ringHash"
policy type.
properties:
maximumRingSize:
description: MaximumRingSize determines the maximum number
of entries in the hash ring.
format: int64
type: integer
minimumRingSize:
description: MinimumRingSize determines the minimum number
of entries in the hash ring.
format: int64
type: integer
type: object
type: object
redirect:
description: Redirect when configured, all attempts to resolve the
service this resolver defines will be substituted for the supplied
redirect EXCEPT when the redirect has already been applied. When
substituting the supplied redirect, all other fields besides Kind,
Name, and Redirect will be ignored.
properties:
datacenter:
description: Datacenter is the datacenter to resolve the service
from instead of the current one.
type: string
namespace:
description: Namespace is the Consul namespace to resolve the
service from instead of the current namespace. If empty the
current namespace is assumed.
type: string
partition:
description: Partition is the Consul partition to resolve the
service from instead of the current partition. If empty the
current partition is assumed.
type: string
service:
description: Service is a service to resolve instead of the current
service.
type: string
serviceSubset:
description: ServiceSubset is a named subset of the given service
to resolve instead of one defined as that service's DefaultSubset
If empty the default subset is used.
type: string
type: object
subsets:
additionalProperties:
properties:
filter:
description: Filter is the filter expression to be used for
selecting instances of the requested service. If empty all
healthy instances are returned. This expression can filter
on the same selectors as the Health API endpoint.
type: string
onlyPassing:
description: OnlyPassing specifies the behavior of the resolver's
health check interpretation. If this is set to false, instances
with checks in the passing as well as the warning states will
be considered healthy. If this is set to true, only instances
with checks in the passing state will be considered healthy.
type: boolean
type: object
description: Subsets is map of subset name to subset definition for
all usable named subsets of this service. The map key is the name
of the subset and all names must be valid DNS subdomain elements.
This may be empty, in which case only the unnamed default subset
will be usable.
type: object
type: object
status:
properties:
conditions:
description: Conditions indicate the latest available observations
of a resource's current state.
items:
description: 'Conditions define a readiness condition for a Consul
resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties'
properties:
lastTransitionTime:
description: LastTransitionTime is the last time the condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition.
type: string
required:
- status
- type
type: object
type: array
lastSyncedTime:
description: LastSyncedTime is the last time the resource successfully
synced with Consul.
format: date-time
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
{{- end }}

View File

@ -0,0 +1,316 @@
{{- if .Values.controller.enabled }}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: servicerouters.consul.hashicorp.com
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: crd
spec:
group: consul.hashicorp.com
names:
kind: ServiceRouter
listKind: ServiceRouterList
plural: servicerouters
shortNames:
- service-router
singular: servicerouter
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: The sync status of the resource with Consul
jsonPath: .status.conditions[?(@.type=="Synced")].status
name: Synced
type: string
- description: The last successful synced time of the resource with Consul
jsonPath: .status.lastSyncedTime
name: Last Synced
type: date
- description: The age of the resource
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: ServiceRouter is the Schema for the servicerouters API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ServiceRouterSpec defines the desired state of ServiceRouter.
properties:
routes:
description: Routes are the list of routes to consider when processing
L7 requests. The first route to match in the list is terminal and
stops further evaluation. Traffic that fails to match any of the
provided routes will be routed to the default service.
items:
properties:
destination:
description: Destination controls how to proxy the matching
request(s) to a service.
properties:
namespace:
description: Namespace is the Consul namespace to resolve
the service from instead of the current namespace. If
empty the current namespace is assumed.
type: string
numRetries:
description: NumRetries is the number of times to retry
the request when a retryable result occurs
format: int32
type: integer
partition:
description: Partition is the Consul partition to resolve
the service from instead of the current partition. If
empty the current partition is assumed.
type: string
prefixRewrite:
description: PrefixRewrite defines how to rewrite the HTTP
request path before proxying it to its final destination.
This requires that either match.http.pathPrefix or match.http.pathExact
be configured on this route.
type: string
requestHeaders:
description: Allow HTTP header manipulation to be configured.
properties:
add:
additionalProperties:
type: string
description: Add is a set of name -> value pairs that
should be appended to the request or response (i.e.
allowing duplicates if the same header already exists).
type: object
remove:
description: Remove is the set of header names that
should be stripped from the request or response.
items:
type: string
type: array
set:
additionalProperties:
type: string
description: Set is a set of name -> value pairs that
should be added to the request or response, overwriting
any existing header values of the same name.
type: object
type: object
requestTimeout:
description: RequestTimeout is the total amount of time
permitted for the entire downstream request (and retries)
to be processed.
type: string
responseHeaders:
description: HTTPHeaderModifiers is a set of rules for HTTP
header modification that should be performed by proxies
as the request passes through them. It can operate on
either request or response headers depending on the context
in which it is used.
properties:
add:
additionalProperties:
type: string
description: Add is a set of name -> value pairs that
should be appended to the request or response (i.e.
allowing duplicates if the same header already exists).
type: object
remove:
description: Remove is the set of header names that
should be stripped from the request or response.
items:
type: string
type: array
set:
additionalProperties:
type: string
description: Set is a set of name -> value pairs that
should be added to the request or response, overwriting
any existing header values of the same name.
type: object
type: object
retryOnConnectFailure:
description: RetryOnConnectFailure allows for connection
failure errors to trigger a retry.
type: boolean
retryOnStatusCodes:
description: RetryOnStatusCodes is a flat list of http response
status codes that are eligible for retry.
items:
format: int32
type: integer
type: array
service:
description: Service is the service to resolve instead of
the default service. If empty then the default service
name is used.
type: string
serviceSubset:
description: ServiceSubset is a named subset of the given
service to resolve instead of the one defined as that
service's DefaultSubset. If empty, the default subset
is used.
type: string
type: object
match:
description: Match is a set of criteria that can match incoming
L7 requests. If empty or omitted it acts as a catch-all.
properties:
http:
description: HTTP is a set of http-specific match criteria.
properties:
header:
description: Header is a set of criteria that can match
on HTTP request headers. If more than one is configured
all must match for the overall match to apply.
items:
properties:
exact:
description: Exact will match if the header with
the given name is this value.
type: string
invert:
description: Invert inverts the logic of the match.
type: boolean
name:
description: Name is the name of the header to
match.
type: string
prefix:
description: Prefix will match if the header with
the given name has this prefix.
type: string
present:
description: Present will match if the header
with the given name is present with any value.
type: boolean
regex:
description: Regex will match if the header with
the given name matches this pattern.
type: string
suffix:
description: Suffix will match if the header with
the given name has this suffix.
type: string
required:
- name
type: object
type: array
methods:
description: Methods is a list of HTTP methods for which
this match applies. If unspecified all http methods
are matched.
items:
type: string
type: array
pathExact:
description: PathExact is an exact path to match on
the HTTP request path.
type: string
pathPrefix:
description: PathPrefix is a path prefix to match on
the HTTP request path.
type: string
pathRegex:
description: PathRegex is a regular expression to match
on the HTTP request path.
type: string
queryParam:
description: QueryParam is a set of criteria that can
match on HTTP query parameters. If more than one is
configured all must match for the overall match to
apply.
items:
properties:
exact:
description: Exact will match if the query parameter
with the given name is this value.
type: string
name:
description: Name is the name of the query parameter
to match on.
type: string
present:
description: Present will match if the query parameter
with the given name is present with any value.
type: boolean
regex:
description: Regex will match if the query parameter
with the given name matches this pattern.
type: string
required:
- name
type: object
type: array
type: object
type: object
type: object
type: array
type: object
status:
properties:
conditions:
description: Conditions indicate the latest available observations
of a resource's current state.
items:
description: 'Conditions define a readiness condition for a Consul
resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties'
properties:
lastTransitionTime:
description: LastTransitionTime is the last time the condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition.
type: string
required:
- status
- type
type: object
type: array
lastSyncedTime:
description: LastSyncedTime is the last time the resource successfully
synced with Consul.
format: date-time
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
{{- end }}

View File

@ -0,0 +1,194 @@
{{- if .Values.controller.enabled }}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: servicesplitters.consul.hashicorp.com
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: crd
spec:
group: consul.hashicorp.com
names:
kind: ServiceSplitter
listKind: ServiceSplitterList
plural: servicesplitters
shortNames:
- service-splitter
singular: servicesplitter
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: The sync status of the resource with Consul
jsonPath: .status.conditions[?(@.type=="Synced")].status
name: Synced
type: string
- description: The last successful synced time of the resource with Consul
jsonPath: .status.lastSyncedTime
name: Last Synced
type: date
- description: The age of the resource
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: ServiceSplitter is the Schema for the servicesplitters API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ServiceSplitterSpec defines the desired state of ServiceSplitter.
properties:
splits:
description: Splits defines how much traffic to send to which set
of service instances during a traffic split. The sum of weights
across all splits must add up to 100.
items:
properties:
namespace:
description: Namespace is the Consul namespace to resolve the
service from instead of the current namespace. If empty the
current namespace is assumed.
type: string
partition:
description: Partition is the Consul partition to resolve the
service from instead of the current partition. If empty the
current partition is assumed.
type: string
requestHeaders:
description: Allow HTTP header manipulation to be configured.
properties:
add:
additionalProperties:
type: string
description: Add is a set of name -> value pairs that should
be appended to the request or response (i.e. allowing
duplicates if the same header already exists).
type: object
remove:
description: Remove is the set of header names that should
be stripped from the request or response.
items:
type: string
type: array
set:
additionalProperties:
type: string
description: Set is a set of name -> value pairs that should
be added to the request or response, overwriting any existing
header values of the same name.
type: object
type: object
responseHeaders:
description: HTTPHeaderModifiers is a set of rules for HTTP
header modification that should be performed by proxies as
the request passes through them. It can operate on either
request or response headers depending on the context in which
it is used.
properties:
add:
additionalProperties:
type: string
description: Add is a set of name -> value pairs that should
be appended to the request or response (i.e. allowing
duplicates if the same header already exists).
type: object
remove:
description: Remove is the set of header names that should
be stripped from the request or response.
items:
type: string
type: array
set:
additionalProperties:
type: string
description: Set is a set of name -> value pairs that should
be added to the request or response, overwriting any existing
header values of the same name.
type: object
type: object
service:
description: Service is the service to resolve instead of the
default.
type: string
serviceSubset:
description: ServiceSubset is a named subset of the given service
to resolve instead of one defined as that service's DefaultSubset.
If empty the default subset is used.
type: string
weight:
description: Weight is a value between 0 and 100 reflecting
what portion of traffic should be directed to this split.
The smallest representable weight is 1/10000 or .01%.
type: number
type: object
type: array
type: object
status:
properties:
conditions:
description: Conditions indicate the latest available observations
of a resource's current state.
items:
description: 'Conditions define a readiness condition for a Consul
resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties'
properties:
lastTransitionTime:
description: LastTransitionTime is the last time the condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition.
type: string
required:
- status
- type
type: object
type: array
lastSyncedTime:
description: LastSyncedTime is the last time the resource successfully
synced with Consul.
format: date-time
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
{{- end }}

View File

@ -0,0 +1,145 @@
{{- if .Values.controller.enabled }}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: terminatinggateways.consul.hashicorp.com
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: crd
spec:
group: consul.hashicorp.com
names:
kind: TerminatingGateway
listKind: TerminatingGatewayList
plural: terminatinggateways
shortNames:
- terminating-gateway
singular: terminatinggateway
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: The sync status of the resource with Consul
jsonPath: .status.conditions[?(@.type=="Synced")].status
name: Synced
type: string
- description: The last successful synced time of the resource with Consul
jsonPath: .status.lastSyncedTime
name: Last Synced
type: date
- description: The age of the resource
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: TerminatingGateway is the Schema for the terminatinggateways
API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: TerminatingGatewaySpec defines the desired state of TerminatingGateway.
properties:
services:
description: Services is a list of service names represented by the
terminating gateway.
items:
description: A LinkedService is a service represented by a terminating
gateway.
properties:
caFile:
description: CAFile is the optional path to a CA certificate
to use for TLS connections from the gateway to the linked
service.
type: string
certFile:
description: CertFile is the optional path to a client certificate
to use for TLS connections from the gateway to the linked
service.
type: string
keyFile:
description: KeyFile is the optional path to a private key to
use for TLS connections from the gateway to the linked service.
type: string
name:
description: Name is the name of the service, as defined in
Consul's catalog.
type: string
namespace:
description: The namespace the service is registered in.
type: string
sni:
description: SNI is the optional name to specify during the
TLS handshake with a linked service.
type: string
type: object
type: array
type: object
status:
properties:
conditions:
description: Conditions indicate the latest available observations
of a resource's current state.
items:
description: 'Conditions define a readiness condition for a Consul
resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties'
properties:
lastTransitionTime:
description: LastTransitionTime is the last time the condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition.
type: string
required:
- status
- type
type: object
type: array
lastSyncedTime:
description: LastSyncedTime is the last time the resource successfully
synced with Consul.
format: date-time
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
{{- end }}

View File

@ -0,0 +1,161 @@
{{- if .Values.global.federation.createFederationSecret }}
{{- if not .Values.global.federation.enabled }}{{ fail "global.federation.enabled must be true when global.federation.createFederationSecret is true" }}{{ end }}
{{- if and (not .Values.global.acls.createReplicationToken) .Values.global.acls.manageSystemACLs }}{{ fail "global.acls.createReplicationToken must be true when global.acls.manageSystemACLs is true because the federation secret must include the replication token" }}{{ end }}
{{- if eq (int .Values.server.updatePartition) 0 }}
apiVersion: batch/v1
kind: Job
metadata:
name: {{ template "consul.fullname" . }}-create-federation-secret
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: create-federation-secret
annotations:
"helm.sh/hook": post-install,post-upgrade
{{- /* Hook weight needs to be 1 so that the service account is provisioned first */}}
"helm.sh/hook-weight": "1"
"helm.sh/hook-delete-policy": hook-succeeded
spec:
template:
metadata:
name: {{ template "consul.fullname" . }}-create-federation-secret
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
release: {{ .Release.Name }}
component: create-federation-secret
annotations:
"consul.hashicorp.com/connect-inject": "false"
spec:
restartPolicy: Never
serviceAccountName: {{ template "consul.fullname" . }}-create-federation-secret
{{- if .Values.client.tolerations }}
tolerations:
{{ tpl .Values.client.tolerations . | nindent 8 | trim }}
{{- end }}
{{- if .Values.client.priorityClassName }}
priorityClassName: {{ .Values.client.priorityClassName | quote }}
{{- end }}
{{- if .Values.client.nodeSelector }}
nodeSelector:
{{ tpl .Values.client.nodeSelector . | indent 8 | trim }}
{{- end }}
volumes:
{{- /* We can assume tls is enabled because there is a check in server-statefulset
that requires tls to be enabled if federation is enabled. */}}
- name: consul-ca-cert
secret:
{{- if .Values.global.tls.caCert.secretName }}
secretName: {{ .Values.global.tls.caCert.secretName }}
{{- else }}
secretName: {{ template "consul.fullname" . }}-ca-cert
{{- end }}
items:
- key: {{ default "tls.crt" .Values.global.tls.caCert.secretKey }}
path: tls.crt
- name: consul-ca-key
secret:
{{- if .Values.global.tls.caKey.secretName }}
secretName: {{ .Values.global.tls.caKey.secretName }}
{{- else }}
secretName: {{ template "consul.fullname" . }}-ca-key
{{- end }}
items:
- key: {{ default "tls.key" .Values.global.tls.caKey.secretKey }}
path: tls.key
{{- /* We must incude both auto-encrypt and server CAs because we make API calls to the local
Consul client (requiring the auto-encrypt CA) but the secret generated must include the server CA */}}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
emptyDir:
medium: "Memory"
{{- end }}
{{- if (and .Values.global.gossipEncryption.secretName .Values.global.gossipEncryption.secretKey) }}
- name: gossip-encryption-key
secret:
secretName: {{ .Values.global.gossipEncryption.secretName }}
items:
- key: {{ .Values.global.gossipEncryption.secretKey }}
path: gossip.key
{{- else if .Values.global.gossipEncryption.autoGenerate }}
- name: gossip-encryption-key
secret:
secretName: {{ template "consul.fullname" . }}-gossip-encryption-key
items:
- key: key
path: gossip.key
{{- end }}
{{- if .Values.global.tls.enableAutoEncrypt }}
initContainers:
{{- include "consul.getAutoEncryptClientCA" . | nindent 6 }}
{{- end }}
containers:
- name: create-federation-secret
image: "{{ .Values.global.imageK8S }}"
env:
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: CONSUL_HTTP_ADDR
value: https://$(HOST_IP):8501
- name: CONSUL_CACERT
{{- if .Values.global.tls.enableAutoEncrypt }}
value: /consul/tls/client/ca/tls.crt
{{- else }}
value: /consul/tls/ca/tls.crt
{{- end }}
volumeMounts:
- name: consul-ca-cert
mountPath: /consul/tls/ca
readOnly: true
- name: consul-ca-key
mountPath: /consul/tls/server/ca
readOnly: true
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
mountPath: /consul/tls/client/ca
readOnly: true
{{- end }}
{{- if (or .Values.global.gossipEncryption.autoGenerate (and .Values.global.gossipEncryption.secretName .Values.global.gossipEncryption.secretKey)) }}
- name: gossip-encryption-key
mountPath: /consul/gossip
readOnly: true
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
consul-k8s-control-plane create-federation-secret \
-log-level={{ .Values.global.logLevel }} \
-log-json={{ .Values.global.logJSON }} \
{{- if (or .Values.global.gossipEncryption.autoGenerate (and .Values.global.gossipEncryption.secretName .Values.global.gossipEncryption.secretKey)) }}
-gossip-key-file=/consul/gossip/gossip.key \
{{- end }}
{{- if .Values.global.acls.createReplicationToken }}
-export-replication-token=true \
{{- end }}
-mesh-gateway-service-name={{ .Values.meshGateway.consulServiceName }} \
-k8s-namespace="${NAMESPACE}" \
-resource-prefix="{{ template "consul.fullname" . }}" \
-server-ca-cert-file=/consul/tls/ca/tls.crt \
-server-ca-key-file=/consul/tls/server/ca/tls.key \
-consul-api-timeout={{ .Values.global.consulAPITimeout }}
resources:
requests:
memory: "50Mi"
cpu: "50m"
limits:
memory: "50Mi"
cpu: "50m"
{{- end }}
{{- end }}

View File

@ -0,0 +1,42 @@
{{- if .Values.global.enablePodSecurityPolicies }}
{{- if .Values.global.federation.createFederationSecret }}
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: {{ template "consul.fullname" . }}-create-federation-secret
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: create-federation-secret
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation
spec:
privileged: false
# Required to prevent escalations to root.
allowPrivilegeEscalation: false
# This is redundant with non-root + disallow privilege escalation,
# but we can provide it for defense in depth.
requiredDropCapabilities:
- ALL
# Allow core volume types.
volumes:
- 'secret'
- 'emptyDir'
hostNetwork: false
hostIPC: false
hostPID: false
runAsUser:
rule: 'RunAsAny'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'
readOnlyRootFilesystem: false
{{- end }}
{{- end }}

View File

@ -0,0 +1,49 @@
{{- if .Values.global.federation.createFederationSecret }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ template "consul.fullname" . }}-create-federation-secret
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: create-federation-secret
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation
rules:
{{/* Must have separate rule for create secret permissions vs update because
can't set resourceNames for create (https://github.com/kubernetes/kubernetes/issues/80295) */}}
- apiGroups: [""]
resources:
- secrets
verbs:
- create
- apiGroups: [""]
resources:
- secrets
resourceNames:
- {{ template "consul.fullname" . }}-federation
verbs:
- update
{{- if .Values.global.acls.manageSystemACLs }}
- apiGroups: [""]
resources:
- secrets
resourceNames:
- {{ template "consul.fullname" . }}-acl-replication-acl-token
verbs:
- get
{{- end }}
{{- if .Values.global.enablePodSecurityPolicies }}
- apiGroups: ["policy"]
resources:
- podsecuritypolicies
verbs:
- use
resourceNames:
- {{ template "consul.fullname" . }}-create-federation-secret
{{- end }}
{{- end }}

View File

@ -0,0 +1,23 @@
{{- if .Values.global.federation.createFederationSecret }}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ template "consul.fullname" . }}-create-federation-secret
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: create-federation-secret
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ template "consul.fullname" . }}-create-federation-secret
subjects:
- kind: ServiceAccount
name: {{ template "consul.fullname" . }}-create-federation-secret
{{- end }}

View File

@ -0,0 +1,22 @@
{{- if .Values.global.federation.createFederationSecret }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "consul.fullname" . }}-create-federation-secret
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: create-federation-secret
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- range . }}
- name: {{ .name }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,41 @@
{{- if (or (and (ne (.Values.dns.enabled | toString) "-") .Values.dns.enabled) (and (eq (.Values.dns.enabled | toString) "-") .Values.global.enabled)) }}
# Service for Consul DNS.
apiVersion: v1
kind: Service
metadata:
name: {{ template "consul.fullname" . }}-dns
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: dns
{{- if .Values.dns.annotations }}
annotations:
{{ tpl .Values.dns.annotations . | nindent 4 | trim }}
{{- end }}
spec:
{{- if .Values.dns.type }}
type: {{ .Values.dns.type }}
{{- end }}
{{- if .Values.dns.clusterIP }}
clusterIP: {{ .Values.dns.clusterIP }}
{{- end }}
ports:
- name: dns-tcp
port: 53
protocol: "TCP"
targetPort: dns-tcp
- name: dns-udp
port: 53
protocol: "UDP"
targetPort: dns-udp
selector:
app: {{ template "consul.name" . }}
release: "{{ .Release.Name }}"
hasDNS: "true"
{{- if .Values.dns.additionalSpec }}
{{ tpl .Values.dns.additionalSpec . | nindent 2 | trim }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,138 @@
{{- if .Values.server.enterpriseLicense }}{{ fail "server.enterpriseLicense has been moved to global.enterpriseLicense" }}{{ end -}}
{{- if (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) }}
{{- if (and .Values.global.enterpriseLicense.secretName .Values.global.enterpriseLicense.secretKey (not .Values.global.enterpriseLicense.enableLicenseAutoload)) }}
apiVersion: batch/v1
kind: Job
metadata:
name: {{ template "consul.fullname" . }}-enterprise-license
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: {{.Release.Service | quote }}
app.kubernetes.io/instance: {{.Release.Name | quote }}
helm.sh/chart: "{{.Chart.Name}}-{{.Chart.Version}}"
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: license
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-weight": "100"
"helm.sh/hook-delete-policy": hook-succeeded
spec:
template:
metadata:
name: {{ template "consul.fullname" . }}-license
labels:
app.kubernetes.io/managed-by: {{.Release.Service | quote }}
app.kubernetes.io/instance: {{.Release.Name | quote }}
helm.sh/chart: "{{.Chart.Name}}-{{.Chart.Version}}"
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
release: {{ .Release.Name }}
component: license
annotations:
"consul.hashicorp.com/connect-inject": "false"
spec:
restartPolicy: Never
serviceAccountName: {{ template "consul.fullname" . }}-enterprise-license
{{- if .Values.global.tls.enabled }}
volumes:
- name: consul-ca-cert
secret:
{{- if .Values.global.tls.caCert.secretName }}
secretName: {{ .Values.global.tls.caCert.secretName }}
{{- else }}
secretName: {{ template "consul.fullname" . }}-ca-cert
{{- end }}
items:
- key: {{ default "tls.crt" .Values.global.tls.caCert.secretKey }}
path: tls.crt
{{- end }}
containers:
- name: apply-enterprise-license
image: "{{ default .Values.global.image .Values.server.image }}"
env:
- name: ENTERPRISE_LICENSE
{{- if .Values.global.secretsBackend.vault.enabled }}
value: /vault/secrets/enterpriselicense.txt
{{- else }}
valueFrom:
secretKeyRef:
name: {{ .Values.global.enterpriseLicense.secretName }}
key: {{ .Values.global.enterpriseLicense.secretKey }}
{{- end }}
- name: CONSUL_HTTP_ADDR
{{- if .Values.global.tls.enabled }}
value: https://{{ template "consul.fullname" . }}-server:8501
{{- else }}
value: http://{{ template "consul.fullname" . }}-server:8500
{{- end }}
{{- if .Values.global.tls.enabled }}
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- end}}
{{- if .Values.global.acls.manageSystemACLs }}
- name: CONSUL_HTTP_TOKEN
valueFrom:
secretKeyRef:
name: "{{ template "consul.fullname" . }}-enterprise-license-acl-token"
key: "token"
{{- end}}
command:
- "/bin/sh"
- "-c"
- |
# Create a script that we can execute with the timeout command.
mkdir -p /tmp/scripts/
cat > /tmp/scripts/apply-license.sh << 'EOF'
#!/bin/sh
while true; do
echo "Applying license..."
if consul license put "${ENTERPRISE_LICENSE}" 2>&1; then
echo "License applied successfully"
break
fi
echo "Retrying in 2s..."
sleep 2
done
EOF
chmod +x /tmp/scripts/apply-license.sh
# Time out after 20 minutes. Use || to support new timeout versions that don't accept -t
timeout -t 1200 /tmp/scripts/apply-license.sh 2> /dev/null || timeout 1200 /tmp/scripts/apply-license.sh 2> /dev/null
{{- if .Values.global.tls.enabled }}
volumeMounts:
- name: consul-ca-cert
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
resources:
requests:
memory: "50Mi"
cpu: "50m"
limits:
memory: "50Mi"
cpu: "50m"
{{- if .Values.global.acls.manageSystemACLs }}
initContainers:
- name: ent-license-acl-init
image: {{ .Values.global.imageK8S }}
command:
- "/bin/sh"
- "-ec"
- |
consul-k8s-control-plane acl-init \
-secret-name="{{ template "consul.fullname" . }}-enterprise-license-acl-token" \
-k8s-namespace={{ .Release.Namespace }} \
-consul-api-timeout={{ .Values.global.consulAPITimeout }}
resources:
requests:
memory: "25Mi"
cpu: "50m"
limits:
memory: "25Mi"
cpu: "50m"
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,39 @@
{{- if (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) }}
{{- if (and .Values.global.enterpriseLicense.secretName .Values.global.enterpriseLicense.secretKey (not .Values.global.enterpriseLicense.enableLicenseAutoload)) }}
{{- if .Values.global.enablePodSecurityPolicies }}
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: {{ template "consul.fullname" . }}-enterprise-license
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: license
spec:
privileged: false
# Allow core volume types.
volumes:
- 'secret'
allowPrivilegeEscalation: false
# This is redundant with non-root + disallow privilege escalation,
# but we can provide it for defense in depth.
requiredDropCapabilities:
- ALL
hostNetwork: false
hostIPC: false
hostPID: false
runAsUser:
rule: 'RunAsAny'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'
readOnlyRootFilesystem: false
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,37 @@
{{- if (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) }}
{{- if (and .Values.global.enterpriseLicense.secretName .Values.global.enterpriseLicense.secretKey (not .Values.global.enterpriseLicense.enableLicenseAutoload)) }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ template "consul.fullname" . }}-enterprise-license
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: license
{{- if or .Values.global.acls.manageSystemACLs .Values.global.enablePodSecurityPolicies }}
rules:
{{- if .Values.global.acls.manageSystemACLs }}
- apiGroups: [""]
resources:
- secrets
resourceNames:
- {{ template "consul.fullname" . }}-enterprise-license-acl-token
verbs:
- get
{{- end }}
{{- if .Values.global.enablePodSecurityPolicies }}
- apiGroups: ["policy"]
resources: ["podsecuritypolicies"]
resourceNames:
- {{ template "consul.fullname" . }}-enterprise-license
verbs:
- use
{{- end }}
{{- else }}
rules: []
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,22 @@
{{- if (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) }}
{{- if (and .Values.global.enterpriseLicense.secretName .Values.global.enterpriseLicense.secretKey (not .Values.global.enterpriseLicense.enableLicenseAutoload)) }}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ template "consul.fullname" . }}-enterprise-license
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: license
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ template "consul.fullname" . }}-enterprise-license
subjects:
- kind: ServiceAccount
name: {{ template "consul.fullname" . }}-enterprise-license
{{- end }}
{{- end }}

View File

@ -0,0 +1,21 @@
{{- if (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) }}
{{- if (and .Values.global.enterpriseLicense.secretName .Values.global.enterpriseLicense.secretKey (not .Values.global.enterpriseLicense.enableLicenseAutoload)) }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "consul.fullname" . }}-enterprise-license
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: license
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- range . }}
- name: {{ .name }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,63 @@
{{- $serverEnabled := (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) -}}
{{- $serverExposeServiceEnabled := (or (and (ne (.Values.server.exposeService.enabled | toString) "-") .Values.server.exposeService.enabled) (and (eq (.Values.server.exposeService.enabled | toString) "-") (or .Values.global.peering.enabled .Values.global.adminPartitions.enabled))) -}}
{{- if (and $serverEnabled $serverExposeServiceEnabled) }}
# Service with an external IP to reach Consul servers.
# Used for exposing gRPC port for peering and ports for client partitions to discover servers.
apiVersion: v1
kind: Service
metadata:
name: {{ template "consul.fullname" . }}-expose-servers
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: server
annotations:
{{- if .Values.server.exposeService.annotations }}
{{ tpl .Values.server.exposeService.annotations . | nindent 4 | trim }}
{{- end }}
spec:
type: "{{ .Values.server.exposeService.type }}"
ports:
{{- if (or (not .Values.global.tls.enabled) (not .Values.global.tls.httpsOnly)) }}
- name: http
port: 8500
targetPort: 8500
{{ if (and (eq .Values.server.exposeService.type "NodePort") .Values.server.exposeService.nodePort.http) }}
nodePort: {{ .Values.server.exposeService.nodePort.http }}
{{- end }}
{{- end }}
{{- if .Values.global.tls.enabled }}
- name: https
port: 8501
targetPort: 8501
{{ if (and (eq .Values.server.exposeService.type "NodePort") .Values.server.exposeService.nodePort.https) }}
nodePort: {{ .Values.server.exposeService.nodePort.https }}
{{- end }}
{{- end }}
- name: serflan
port: 8301
targetPort: 8301
{{ if (and (eq .Values.server.exposeService.type "NodePort") .Values.server.exposeService.nodePort.serf) }}
nodePort: {{ .Values.server.exposeService.nodePort.serf }}
{{- end }}
- name: rpc
port: 8300
targetPort: 8300
{{ if (and (eq .Values.server.exposeService.type "NodePort") .Values.server.exposeService.nodePort.rpc) }}
nodePort: {{ .Values.server.exposeService.nodePort.rpc }}
{{- end }}
- name: grpc
port: 8502
targetPort: 8503
{{ if (and (eq .Values.server.exposeService.type "NodePort") .Values.server.exposeService.nodePort.grpc) }}
nodePort: {{ .Values.server.exposeService.nodePort.grpc }}
{{- end }}
selector:
app: {{ template "consul.name" . }}
release: "{{ .Release.Name }}"
component: server
{{- end }}

View File

@ -0,0 +1,62 @@
{{- if .Values.global.gossipEncryption.autoGenerate }}
{{- if (or .Values.global.gossipEncryption.secretName .Values.global.gossipEncryption.secretKey) }}
{{ fail "If global.gossipEncryption.autoGenerate is true, global.gossipEncryption.secretName and global.gossipEncryption.secretKey must not be set." }}
{{ end }}
# automatically generate encryption key for gossip protocol and save it in Kubernetes secret
apiVersion: batch/v1
kind: Job
metadata:
name: {{ template "consul.fullname" . }}-gossip-encryption-autogenerate
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: gossip-encryption-autogenerate
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "1"
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation
spec:
template:
metadata:
name: {{ template "consul.fullname" . }}-gossip-encryption-autogenerate
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
release: {{ .Release.Name }}
component: gossip-encryption-autogenerate
annotations:
"consul.hashicorp.com/connect-inject": "false"
spec:
restartPolicy: Never
serviceAccountName: {{ template "consul.fullname" . }}-gossip-encryption-autogenerate
{{- if not .Values.global.openshift.enabled }}
securityContext:
runAsNonRoot: true
runAsGroup: 1000
runAsUser: 100
fsGroup: 1000
{{- end }}
containers:
- name: gossip-encryption-autogen
image: "{{ .Values.global.imageK8S }}"
command:
- "/bin/sh"
- "-ec"
- |
consul-k8s-control-plane gossip-encryption-autogenerate \
-namespace={{ .Release.Namespace }} \
-secret-name={{ template "consul.fullname" . }}-gossip-encryption-key \
-secret-key="key" \
-log-level={{ .Values.global.logLevel }} \
-log-json={{ .Values.global.logJSON }}
resources:
requests:
memory: "50Mi"
cpu: "50m"
limits:
memory: "50Mi"
cpu: "50m"
{{- end }}

View File

@ -0,0 +1,40 @@
{{- if .Values.global.gossipEncryption.autoGenerate }}
---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: {{ template "consul.fullname" . }}-gossip-encryption-autogenerate
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: gossip-encryption-autogenerate
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation
spec:
privileged: false
# Required to prevent escalations to root.
allowPrivilegeEscalation: false
# This is redundant with non-root + disallow privilege escalation,
# but we can provide it for defense in depth.
requiredDropCapabilities:
- ALL
# Allow core volume types.
volumes:
- 'secret'
hostNetwork: false
hostIPC: false
hostPID: false
runAsUser:
rule: 'RunAsAny'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'
readOnlyRootFilesystem: false
{{- end }}

View File

@ -0,0 +1,32 @@
{{- if .Values.global.gossipEncryption.autoGenerate }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ template "consul.fullname" . }}-gossip-encryption-autogenerate
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: gossip-encryption-autogenerate
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation
rules:
- apiGroups: [""]
resources:
- secrets
verbs:
- create
- get
{{- if .Values.global.enablePodSecurityPolicies }}
- apiGroups: ["policy"]
resources:
- podsecuritypolicies
verbs:
- use
resourceNames:
- {{ template "consul.fullname" . }}-gossip-encryption-autogenerate
{{- end }}
{{- end }}

View File

@ -0,0 +1,23 @@
{{- if .Values.global.gossipEncryption.autoGenerate }}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ template "consul.fullname" . }}-gossip-encryption-autogenerate
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: gossip-encryption-autogenerate
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ template "consul.fullname" . }}-gossip-encryption-autogenerate
subjects:
- kind: ServiceAccount
name: {{ template "consul.fullname" . }}-gossip-encryption-autogenerate
{{- end }}

View File

@ -0,0 +1,22 @@
{{- if .Values.global.gossipEncryption.autoGenerate }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "consul.fullname" . }}-gossip-encryption-autogenerate
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: gossip-encryption-autogenerate
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- range . }}
- name: {{ .name }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,489 @@
{{- if .Values.ingressGateways.enabled }}
{{- if not .Values.connectInject.enabled }}{{ fail "connectInject.enabled must be true" }}{{ end -}}
{{- if not .Values.client.grpc }}{{ fail "client.grpc must be true" }}{{ end -}}
{{- if and .Values.global.adminPartitions.enabled (not .Values.global.enableConsulNamespaces) }}{{ fail "global.enableConsulNamespaces must be true if global.adminPartitions.enabled=true" }}{{ end }}
{{- if not (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }}{{ fail "clients must be enabled" }}{{ end -}}
{{- if .Values.global.lifecycleSidecarContainer }}{{ fail "global.lifecycleSidecarContainer has been renamed to global.consulSidecarContainer. Please set values using global.consulSidecarContainer." }}{{ end }}
{{- $root := . }}
{{- $defaults := .Values.ingressGateways.defaults }}
{{- $names := dict }}
{{- /* Check if gateway names are unique. */ -}}
{{- $gateways := .Values.ingressGateways.gateways }}
{{- range $outerIngressIndex, $outerIngressVal := $gateways }}
{{- range $innerIngressIndex, $innerIngressVal := $gateways }}
{{- if (and (ne $outerIngressIndex $innerIngressIndex) (eq $outerIngressVal.name $innerIngressVal.name)) }}
{{ fail (cat "ingress gateways must have unique names but found duplicate name" $innerIngressVal.name) }}
{{ end -}}
{{ end -}}
{{ end -}}
{{- range .Values.ingressGateways.gateways }}
{{- $service := .service }}
{{- if empty .name }}
# Check that the gateway name is provided
{{ fail "Ingress gateway names cannot be empty"}}
{{ end -}}
{{- if hasKey $names .name }}
# Check that the gateway name is unique
{{ fail "Ingress gateway names must be unique"}}
{{ end -}}
{{- /* Add the gateway name to the $names dict to ensure uniqueness */ -}}
{{- $_ := set $names .name .name }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "consul.fullname" $root }}-{{ .name }}
namespace: {{ $root.Release.Namespace }}
labels:
app: {{ template "consul.name" $root }}
chart: {{ template "consul.chart" $root }}
heritage: {{ $root.Release.Service }}
release: {{ $root.Release.Name }}
component: ingress-gateway
ingress-gateway-name: {{ template "consul.fullname" $root }}-{{ .name }}
spec:
replicas: {{ default $defaults.replicas .replicas }}
selector:
matchLabels:
app: {{ template "consul.name" $root }}
chart: {{ template "consul.chart" $root }}
heritage: {{ $root.Release.Service }}
release: {{ $root.Release.Name }}
component: ingress-gateway
ingress-gateway-name: {{ template "consul.fullname" $root }}-{{ .name }}
template:
metadata:
labels:
app: {{ template "consul.name" $root }}
chart: {{ template "consul.chart" $root }}
heritage: {{ $root.Release.Service }}
release: {{ $root.Release.Name }}
component: ingress-gateway
ingress-gateway-name: {{ template "consul.fullname" $root }}-{{ .name }}
annotations:
{{- if (and $root.Values.global.secretsBackend.vault.enabled $root.Values.global.tls.enabled) }}
"vault.hashicorp.com/agent-init-first": "true"
"vault.hashicorp.com/agent-inject": "true"
"vault.hashicorp.com/role": {{ $root.Values.global.secretsBackend.vault.consulCARole }}
"vault.hashicorp.com/agent-inject-secret-serverca.crt": {{ $root.Values.global.tls.caCert.secretName }}
"vault.hashicorp.com/agent-inject-template-serverca.crt": {{ template "consul.serverTLSCATemplate" $root }}
{{- if and $root.Values.global.secretsBackend.vault.ca.secretName $root.Values.global.secretsBackend.vault.ca.secretKey }}
"vault.hashicorp.com/agent-extra-secret": {{ $root.Values.global.secretsBackend.vault.ca.secretName }}
"vault.hashicorp.com/ca-cert": /vault/custom/{{ $root.Values.global.secretsBackend.vault.ca.secretKey }}
{{- end }}
{{- if $root.Values.global.secretsBackend.vault.agentAnnotations }}
{{ tpl $root.Values.global.secretsBackend.vault.agentAnnotations $root | nindent 8 | trim }}
{{- end }}
{{- end }}
"consul.hashicorp.com/connect-inject": "false"
{{- if (and $root.Values.global.metrics.enabled $root.Values.global.metrics.enableGatewayMetrics) }}
"prometheus.io/scrape": "true"
"prometheus.io/path": "/metrics"
"prometheus.io/port": "20200"
{{- end }}
{{- if $defaults.annotations }}
# We allow both default annotations and gateway-specific annotations
{{- tpl $defaults.annotations $root | nindent 8 }}
{{- end }}
{{- if .annotations }}
{{- tpl .annotations $root | nindent 8 }}
{{- end }}
spec:
{{- if (or $defaults.affinity .affinity) }}
affinity:
{{ tpl (default $defaults.affinity .affinity) $root | nindent 8 | trim }}
{{- end }}
{{- if (or $defaults.tolerations .tolerations) }}
tolerations:
{{ tpl (default $defaults.tolerations .tolerations) $root | nindent 8 | trim }}
{{- end }}
{{- if (or $defaults.topologySpreadConstraints .topologySpreadConstraints) }}
topologySpreadConstraints:
{{ tpl (default $defaults.topologySpreadConstraints .topologySpreadConstraints) $root | nindent 8 | trim }}
{{- end }}
terminationGracePeriodSeconds: {{ default $defaults.terminationGracePeriodSeconds .terminationGracePeriodSeconds }}
serviceAccountName: {{ template "consul.fullname" $root }}-{{ .name }}
volumes:
- name: consul-bin
emptyDir: {}
- name: consul-service
emptyDir:
medium: "Memory"
{{- if $root.Values.global.tls.enabled }}
{{- if not (and $root.Values.externalServers.enabled $root.Values.externalServers.useSystemRoots) }}
- name: consul-ca-cert
secret:
{{- if $root.Values.global.tls.caCert.secretName }}
secretName: {{ $root.Values.global.tls.caCert.secretName }}
{{- else }}
secretName: {{ template "consul.fullname" $root }}-ca-cert
{{- end }}
items:
- key: {{ default "tls.crt" $root.Values.global.tls.caCert.secretKey }}
path: tls.crt
{{- end }}
{{- if $root.Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
emptyDir:
medium: "Memory"
{{- end }}
{{- end }}
initContainers:
# We use the Envoy image as our base image so we use an init container to
# copy the Consul binary to a shared directory that can be used when
# starting Envoy.
- name: copy-consul-bin
image: {{ $root.Values.global.image | quote }}
command:
- cp
- /bin/consul
- /consul-bin/consul
volumeMounts:
- name: consul-bin
mountPath: /consul-bin
{{- $initContainer := .initCopyConsulContainer }}
{{- if (or $initContainer $defaults.initCopyConsulContainer) }}
{{- if (default $defaults.initCopyConsulContainer.resources $initContainer.resources) }}
resources: {{ toYaml (default $defaults.initCopyConsulContainer.resources $initContainer.resources) | nindent 12 }}
{{- end }}
{{- end }}
{{- if (and $root.Values.global.tls.enabled $root.Values.global.tls.enableAutoEncrypt) }}
{{- include "consul.getAutoEncryptClientCA" $root | nindent 8 }}
{{- end }}
# ingress-gateway-init registers the ingress gateway service with Consul.
- name: ingress-gateway-init
image: {{ $root.Values.global.imageK8S }}
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
{{- if $root.Values.global.tls.enabled }}
- name: CONSUL_HTTP_ADDR
value: https://$(HOST_IP):8501
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- else }}
- name: CONSUL_HTTP_ADDR
value: http://$(HOST_IP):8500
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
{{- if $root.Values.global.acls.manageSystemACLs }}
consul-k8s-control-plane acl-init \
-component-name=ingress-gateway/{{ template "consul.fullname" $root }}-{{ .name }} \
-acl-auth-method={{ template "consul.fullname" $root }}-k8s-component-auth-method \
{{- if $root.Values.global.adminPartitions.enabled }}
-partition={{ $root.Values.global.adminPartitions.name }} \
{{- end }}
-token-sink-file=/consul/service/acl-token \
-consul-api-timeout={{ $root.Values.global.consulAPITimeout }} \
-log-level={{ default $root.Values.global.logLevel }} \
-log-json={{ $root.Values.global.logJSON }}
{{ end }}
{{- $serviceType := (default $defaults.service.type $service.type) }}
{{- if (eq $serviceType "NodePort") }}
WAN_ADDR="${HOST_IP}"
{{- else if (or (eq $serviceType "ClusterIP") (eq $serviceType "LoadBalancer")) }}
consul-k8s-control-plane service-address \
-log-level={{ $root.Values.global.logLevel }} \
-log-json={{ $root.Values.global.logJSON }} \
-k8s-namespace={{ $root.Release.Namespace }} \
-name={{ template "consul.fullname" $root }}-{{ .name }} \
-output-file=/tmp/address.txt
WAN_ADDR="$(cat /tmp/address.txt)"
{{- else }}
{{- fail "currently set ingressGateway value service.type is not supported" }}
{{- end }}
{{- if (eq $serviceType "NodePort") }}
{{- if $service.ports }}
{{- $firstPort := first $service.ports}}
{{- if $firstPort.nodePort }}
WAN_PORT={{ $firstPort.nodePort }}
{{- else }}{{ fail "if ingressGateways .service.type=NodePort and defining ingressGateways.gateways.service.ports, the first port entry must include a nodePort" }}
{{- end }}
{{- else if $defaults.service.ports }}
{{- $firstDefaultPort := first $defaults.service.ports}}
{{- if $firstDefaultPort.nodePort }}
WAN_PORT={{ $firstDefaultPort.nodePort }}
{{- else }}{{ fail "if ingressGateways .service.type=NodePort and using ingressGateways.defaults.service.ports, the first port entry must include a nodePort" }}
{{- end }}
{{- else }}{{ fail "if ingressGateways .service.type=NodePort, the first port entry in either the defaults or specific gateway must include a nodePort" }}
{{- end }}
{{- else }}
{{- if $service.ports }}
{{- $firstPort := first $service.ports}}
{{- if $firstPort.port }}
WAN_PORT={{ $firstPort.port }}
{{- else }}{{ fail "if ingressGateways .service.type is not NodePort and defining ingressGateways.gateways.service.ports, the first port entry must include a port" }}
{{- end }}
{{- else if $defaults.service.ports }}
{{- $firstDefaultPort := first $defaults.service.ports}}
{{- if $firstDefaultPort.port }}
WAN_PORT={{ $firstDefaultPort.port }}
{{- else }}{{ fail "if ingressGateways .service.type is not NodePort and using ingressGateways.defaults.service.ports, the first port entry must include a port" }}
{{- end }}
{{- else }}{{ fail "if ingressGateways .service.type is not NodePort, the first port entry in either the defaults or specific gateway must include a port" }}
{{- end }}
{{- end }}
cat > /consul/service/service.hcl << EOF
service {
kind = "ingress-gateway"
name = "{{ .name }}"
id = "${POD_NAME}"
{{- if $root.Values.global.enableConsulNamespaces }}
namespace = "{{ (default $defaults.consulNamespace .consulNamespace) }}"
{{- end }}
{{- if $root.Values.global.adminPartitions.enabled }}
partition = "{{ $root.Values.global.adminPartitions.name }}"
{{- end }}
port = ${WAN_PORT}
address = "${WAN_ADDR}"
tagged_addresses {
lan {
address = "${POD_IP}"
port = 21000
}
wan {
address = "${WAN_ADDR}"
port = ${WAN_PORT}
}
}
proxy {
config {
{{- if (and $root.Values.global.metrics.enabled $root.Values.global.metrics.enableGatewayMetrics) }}
envoy_prometheus_bind_addr = "${POD_IP}:20200"
{{- end }}
envoy_gateway_no_default_bind = true
envoy_gateway_bind_addresses {
all-interfaces {
address = "0.0.0.0"
}
}
}
}
checks = [
{
name = "Ingress Gateway Listening"
interval = "10s"
tcp = "${POD_IP}:21000"
deregister_critical_service_after = "6h"
}
]
}
EOF
/consul-bin/consul services register \
{{- if $root.Values.global.acls.manageSystemACLs }}
-token-file=/consul/service/acl-token \
{{- end }}
/consul/service/service.hcl
volumeMounts:
- name: consul-service
mountPath: /consul/service
- name: consul-bin
mountPath: /consul-bin
{{- if $root.Values.global.tls.enabled }}
{{- if $root.Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
{{- else }}
- name: consul-ca-cert
{{- end }}
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
resources:
requests:
memory: "50Mi"
cpu: "50m"
limits:
memory: "50Mi"
cpu: "50m"
containers:
- name: ingress-gateway
image: {{ $root.Values.global.imageEnvoy | quote }}
{{- if (default $defaults.resources .resources) }}
resources: {{ toYaml (default $defaults.resources .resources) | nindent 12 }}
{{- end }}
volumeMounts:
- name: consul-bin
mountPath: /consul-bin
- name: consul-service
mountPath: /consul/service
readOnly: true
{{- if $root.Values.global.tls.enabled }}
{{- if $root.Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
{{- else }}
- name: consul-ca-cert
{{- end }}
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
{{- if $root.Values.global.acls.manageSystemACLs }}
- name: CONSUL_HTTP_TOKEN_FILE
value: "/consul/service/acl-token"
{{- end}}
{{- if $root.Values.global.tls.enabled }}
- name: CONSUL_HTTP_ADDR
value: https://$(HOST_IP):8501
- name: CONSUL_GRPC_ADDR
value: https://$(HOST_IP):8502
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- else }}
- name: CONSUL_HTTP_ADDR
value: http://$(HOST_IP):8500
- name: CONSUL_GRPC_ADDR
value: $(HOST_IP):8502
{{- end }}
command:
- /consul-bin/consul
- connect
- envoy
- -gateway=ingress
- -proxy-id=$(POD_NAME)
- -address=$(POD_IP):21000
{{- if $root.Values.global.enableConsulNamespaces }}
- -namespace={{ default $defaults.consulNamespace .consulNamespace }}
{{- end }}
{{- if $root.Values.global.adminPartitions.enabled }}
- -partition={{ $root.Values.global.adminPartitions.name }}
{{- end }}
livenessProbe:
tcpSocket:
port: 21000
failureThreshold: 3
initialDelaySeconds: 30
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
readinessProbe:
tcpSocket:
port: 21000
failureThreshold: 3
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
ports:
- name: gateway-health
containerPort: 21000
{{- range $index, $allPorts := (default $defaults.service.ports $service.ports) }}
- name: gateway-{{ $index }}
containerPort: {{ $allPorts.port }}
{{- end }}
lifecycle:
preStop:
exec:
command:
- "/bin/sh"
- "-ec"
- |
/consul-bin/consul services deregister \
{{- if $root.Values.global.enableConsulNamespaces }}
-namespace={{ default $defaults.consulNamespace .consulNamespace }} \
{{- end }}
{{- if $root.Values.global.adminPartitions.enabled }}
-partition={{ $root.Values.global.adminPartitions.name }} \
{{- end }}
-id="${POD_NAME}"
{{- if $root.Values.global.acls.manageSystemACLs }}
- "/consul-bin/consul logout"
{{- end}}
# consul-sidecar ensures the ingress gateway is always registered with
# the local Consul agent, even if it loses the initial registration.
- name: consul-sidecar
image: {{ $root.Values.global.imageK8S }}
volumeMounts:
- name: consul-service
mountPath: /consul/service
readOnly: true
- name: consul-bin
mountPath: /consul-bin
{{- if $root.Values.global.tls.enabled }}
{{- if $root.Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
{{- else }}
- name: consul-ca-cert
{{- end }}
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
{{- if $root.Values.global.consulSidecarContainer }}
{{- if $root.Values.global.consulSidecarContainer.resources }}
resources: {{ toYaml $root.Values.global.consulSidecarContainer.resources | nindent 12 }}
{{- end }}
{{- end }}
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
{{- if $root.Values.global.tls.enabled }}
- name: CONSUL_HTTP_ADDR
value: https://$(HOST_IP):8501
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- else }}
- name: CONSUL_HTTP_ADDR
value: http://$(HOST_IP):8500
{{- end }}
command:
- consul-k8s-control-plane
- consul-sidecar
- -log-level={{ $root.Values.global.logLevel }}
- -log-json={{ $root.Values.global.logJSON }}
- -service-config=/consul/service/service.hcl
- -consul-binary=/consul-bin/consul
- -consul-api-timeout={{ $root.Values.global.consulAPITimeout }}
{{- if $root.Values.global.acls.manageSystemACLs }}
- -token-file=/consul/service/acl-token
{{- end }}
{{- if (default $defaults.priorityClassName .priorityClassName) }}
priorityClassName: {{ default $defaults.priorityClassName .priorityClassName | quote }}
{{- end }}
{{- if (default $defaults.nodeSelector .nodeSelector) }}
nodeSelector:
{{ tpl (default $defaults.nodeSelector .nodeSelector) $root | indent 8 | trim }}
{{- end }}
---
{{- end }}
{{- end }}

View File

@ -0,0 +1,45 @@
{{- if (and .Values.global.enablePodSecurityPolicies .Values.ingressGateways.enabled) }}
{{- $root := . }}
{{- range .Values.ingressGateways.gateways }}
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: {{ template "consul.fullname" $root }}-{{ .name }}
namespace: {{ $root.Release.Namespace }}
labels:
app: {{ template "consul.name" $root }}
chart: {{ template "consul.chart" $root }}
heritage: {{ $root.Release.Service }}
release: {{ $root.Release.Name }}
component: ingress-gateway
ingress-gateway-name: {{ template "consul.fullname" $root }}-{{ .name }}
spec:
privileged: false
# Required to prevent escalations to root.
allowPrivilegeEscalation: false
# This is redundant with non-root + disallow privilege escalation,
# but we can provide it for defense in depth.
requiredDropCapabilities:
- ALL
# Allow core volume types.
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
hostNetwork: false
hostIPC: false
hostPID: false
runAsUser:
rule: 'RunAsAny'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'
readOnlyRootFilesystem: false
---
{{- end }}
{{- end }}

View File

@ -0,0 +1,46 @@
{{- if .Values.ingressGateways.enabled }}
{{- $root := . }}
{{- $defaults := .Values.ingressGateways.defaults }}
{{- range .Values.ingressGateways.gateways }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ template "consul.fullname" $root }}-{{ .name }}
namespace: {{ $root.Release.Namespace }}
labels:
app: {{ template "consul.name" $root }}
chart: {{ template "consul.chart" $root }}
heritage: {{ $root.Release.Service }}
release: {{ $root.Release.Name }}
component: ingress-gateway
ingress-gateway-name: {{ template "consul.fullname" $root }}-{{ .name }}
rules:
- apiGroups: [""]
resources:
- services
resourceNames:
- {{ template "consul.fullname" $root }}-{{ .name }}
verbs:
- get
{{- if $root.Values.global.enablePodSecurityPolicies }}
- apiGroups: ["policy"]
resources: ["podsecuritypolicies"]
resourceNames:
- {{ template "consul.fullname" $root }}-{{ .name }}
verbs:
- use
{{- end }}
{{- if $root.Values.global.acls.manageSystemACLs }}
- apiGroups: [""]
resources:
- secrets
resourceNames:
- {{ template "consul.fullname" $root }}-{{ .name }}-acl-token
verbs:
- get
{{- end }}
---
{{- end }}
{{- end }}

View File

@ -0,0 +1,25 @@
{{- if .Values.ingressGateways.enabled }}
{{- $root := . }}
{{- range .Values.ingressGateways.gateways }}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ template "consul.fullname" $root }}-{{ .name }}
namespace: {{ $root.Release.Namespace }}
labels:
app: {{ template "consul.name" $root }}
chart: {{ template "consul.chart" $root }}
heritage: {{ $root.Release.Service }}
release: {{ $root.Release.Name }}
component: ingress-gateway
ingress-gateway-name: {{ template "consul.fullname" $root }}-{{ .name }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ template "consul.fullname" $root }}-{{ .name }}
subjects:
- kind: ServiceAccount
name: {{ template "consul.fullname" $root }}-{{ .name }}
---
{{- end }}
{{- end }}

View File

@ -0,0 +1,51 @@
{{- if .Values.ingressGateways.enabled }}
{{- $root := . }}
{{- $defaults := .Values.ingressGateways.defaults }}
{{- range .Values.ingressGateways.gateways }}
{{- $service := .service }}
apiVersion: v1
kind: Service
metadata:
name: {{ template "consul.fullname" $root }}-{{ .name }}
namespace: {{ $root.Release.Namespace }}
labels:
app: {{ template "consul.name" $root }}
chart: {{ template "consul.chart" $root }}
heritage: {{ $root.Release.Service }}
release: {{ $root.Release.Name }}
component: ingress-gateway
ingress-gateway-name: {{ template "consul.fullname" $root }}-{{ .name }}
{{- if (or $defaults.service.annotations $service.annotations) }}
# We allow both default annotations and gateway-specific annotations
annotations:
{{- if $defaults.service.annotations }}
{{ tpl $defaults.service.annotations $root | nindent 4 | trim }}
{{- end }}
{{- if $service.annotations }}
{{ tpl $service.annotations $root | nindent 4 | trim }}
{{- end }}
{{- end }}
spec:
selector:
app: {{ template "consul.name" $root }}
release: "{{ $root.Release.Name }}"
component: ingress-gateway
ingress-gateway-name: {{ template "consul.fullname" $root }}-{{ .name }}
ports:
{{- range $index, $ports := (default $defaults.service.ports $service.ports) }}
- name: gateway-{{ $index }}
port: {{ $ports.port }}
{{- if (and (eq (default $defaults.service.type $service.type) "NodePort") $ports.nodePort) }}
nodePort: {{ $ports.nodePort }}
{{- end}}
{{- end }}
type: {{ default $defaults.service.type $service.type }}
{{- if (default $defaults.service.additionalSpec $service.additionalSpec) }}
{{ tpl (default $defaults.service.additionalSpec $service.additionalSpec) $root | nindent 2 | trim }}
{{- end }}
---
{{- end }}
{{- end }}

View File

@ -0,0 +1,35 @@
{{- if .Values.ingressGateways.enabled }}
{{- $root := . }}
{{- $defaults := .Values.ingressGateways.defaults }}
{{- range .Values.ingressGateways.gateways }}
{{- $serviceAccount := .serviceAccount }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "consul.fullname" $root }}-{{ .name }}
namespace: {{ $root.Release.Namespace }}
labels:
app: {{ template "consul.name" $root }}
chart: {{ template "consul.chart" $root }}
heritage: {{ $root.Release.Service }}
release: {{ $root.Release.Name }}
component: ingress-gateway
ingress-gateway-name: {{ template "consul.fullname" $root }}-{{ .name }}
{{- if (or $defaults.serviceAccount.annotations $serviceAccount.annotations) }}
annotations:
{{- if $defaults.serviceAccount.annotations }}
{{ tpl $defaults.serviceAccount.annotations $root | nindent 4 | trim }}
{{- end }}
{{- if $serviceAccount.annotations }}
{{ tpl $serviceAccount.annotations $root | nindent 4 | trim }}
{{- end }}
{{- end }}
{{- with $root.Values.global.imagePullSecrets }}
imagePullSecrets:
{{- range . }}
- name: {{ .name }}
{{- end }}
{{- end }}
---
{{- end }}
{{- end }}

View File

@ -0,0 +1,34 @@
{{- if .Values.meshGateway.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ template "consul.fullname" . }}-mesh-gateway
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: mesh-gateway
{{- if or .Values.global.acls.manageSystemACLs .Values.global.enablePodSecurityPolicies (eq .Values.meshGateway.wanAddress.source "Service") }}
rules:
{{- if .Values.global.enablePodSecurityPolicies }}
- apiGroups: ["policy"]
resources: ["podsecuritypolicies"]
resourceNames:
- {{ template "consul.fullname" . }}-mesh-gateway
verbs:
- use
{{- end }}
{{- if eq .Values.meshGateway.wanAddress.source "Service" }}
- apiGroups: [""]
resources:
- services
resourceNames:
- {{ template "consul.fullname" . }}-mesh-gateway
verbs:
- get
{{- end }}
{{- else }}
rules: []
{{- end }}
{{- end }}

View File

@ -0,0 +1,20 @@
{{- if .Values.meshGateway.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ template "consul.fullname" . }}-mesh-gateway
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: mesh-gateway
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ template "consul.fullname" . }}-mesh-gateway
subjects:
- kind: ServiceAccount
name: {{ template "consul.fullname" . }}-mesh-gateway
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@ -0,0 +1,423 @@
{{- if .Values.meshGateway.enabled }}
{{- if not .Values.connectInject.enabled }}{{ fail "connectInject.enabled must be true" }}{{ end -}}
{{- if not .Values.client.grpc }}{{ fail "client.grpc must be true" }}{{ end -}}
{{- if and .Values.global.acls.manageSystemACLs (ne .Values.meshGateway.consulServiceName "") (ne .Values.meshGateway.consulServiceName "mesh-gateway") }}{{ fail "if global.acls.manageSystemACLs is true, meshGateway.consulServiceName cannot be set" }}{{ end -}}
{{- if .Values.meshGateway.imageEnvoy }}{{ fail "meshGateway.imageEnvoy must be specified in global.imageEnvoy" }}{{ end -}}
{{- if .Values.meshGateway.globalMode }}{{ fail "meshGateway.globalMode is no longer supported; instead, you must migrate to CRDs (see www.consul.io/docs/k8s/crds/upgrade-to-crds)" }}{{ end -}}
{{- if .Values.global.lifecycleSidecarContainer }}{{ fail "global.lifecycleSidecarContainer has been renamed to global.consulSidecarContainer. Please set values using global.consulSidecarContainer." }}{{ end }}
{{- /* The below test checks if clients are disabled (and if so, fails). We use the conditional from other client files and prepend 'not' */ -}}
{{- if not (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }}{{ fail "clients must be enabled" }}{{ end -}}
{{- if and .Values.global.adminPartitions.enabled (not .Values.global.enableConsulNamespaces) }}{{ fail "global.enableConsulNamespaces must be true if global.adminPartitions.enabled=true" }}{{ end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "consul.fullname" . }}-mesh-gateway
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: mesh-gateway
spec:
replicas: {{ .Values.meshGateway.replicas }}
selector:
matchLabels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
release: {{ .Release.Name }}
component: mesh-gateway
template:
metadata:
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
release: {{ .Release.Name }}
component: mesh-gateway
annotations:
"consul.hashicorp.com/connect-inject": "false"
{{- if (and .Values.global.secretsBackend.vault.enabled .Values.global.tls.enabled) }}
"vault.hashicorp.com/agent-init-first": "true"
"vault.hashicorp.com/agent-inject": "true"
"vault.hashicorp.com/role": {{ .Values.global.secretsBackend.vault.consulCARole }}
"vault.hashicorp.com/agent-inject-secret-serverca.crt": {{ .Values.global.tls.caCert.secretName }}
"vault.hashicorp.com/agent-inject-template-serverca.crt": {{ template "consul.serverTLSCATemplate" . }}
{{- if and .Values.global.secretsBackend.vault.ca.secretName .Values.global.secretsBackend.vault.ca.secretKey }}
"vault.hashicorp.com/agent-extra-secret": "{{ .Values.global.secretsBackend.vault.ca.secretName }}"
"vault.hashicorp.com/ca-cert": "/vault/custom/{{ .Values.global.secretsBackend.vault.ca.secretKey }}"
{{- end }}
{{- if .Values.global.secretsBackend.vault.agentAnnotations }}
{{ tpl .Values.global.secretsBackend.vault.agentAnnotations . | nindent 8 | trim }}
{{- end }}
{{- end }}
{{- if (and .Values.global.metrics.enabled .Values.global.metrics.enableGatewayMetrics) }}
"prometheus.io/scrape": "true"
"prometheus.io/path": "/metrics"
"prometheus.io/port": "20200"
{{- end }}
{{- if .Values.meshGateway.annotations }}
{{- tpl .Values.meshGateway.annotations . | nindent 8 }}
{{- end }}
spec:
{{- if .Values.meshGateway.affinity }}
affinity:
{{ tpl .Values.meshGateway.affinity . | nindent 8 | trim }}
{{- end }}
{{- if .Values.meshGateway.tolerations }}
tolerations:
{{ tpl .Values.meshGateway.tolerations . | nindent 8 | trim }}
{{- end }}
{{- if .Values.meshGateway.topologySpreadConstraints }}
topologySpreadConstraints:
{{ tpl .Values.meshGateway.topologySpreadConstraints . | nindent 8 | trim }}
{{- end }}
terminationGracePeriodSeconds: 10
serviceAccountName: {{ template "consul.fullname" . }}-mesh-gateway
volumes:
- name: consul-bin
emptyDir: {}
- name: consul-service
emptyDir:
medium: "Memory"
{{- if .Values.global.tls.enabled }}
{{- if not (and .Values.externalServers.enabled .Values.externalServers.useSystemRoots) }}
- name: consul-ca-cert
secret:
{{- if .Values.global.tls.caCert.secretName }}
secretName: {{ .Values.global.tls.caCert.secretName }}
{{- else }}
secretName: {{ template "consul.fullname" . }}-ca-cert
{{- end }}
items:
- key: {{ default "tls.crt" .Values.global.tls.caCert.secretKey }}
path: tls.crt
{{- end }}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
emptyDir:
medium: "Memory"
{{- end }}
{{- end }}
{{- if .Values.meshGateway.hostNetwork }}
hostNetwork: {{ .Values.meshGateway.hostNetwork }}
{{- end }}
{{- if .Values.meshGateway.dnsPolicy }}
dnsPolicy: {{ .Values.meshGateway.dnsPolicy }}
{{- end }}
initContainers:
# We use the Envoy image as our base image so we use an init container to
# copy the Consul binary to a shared directory that can be used when
# starting Envoy.
- name: copy-consul-bin
image: {{ .Values.global.image | quote }}
command:
- cp
- /bin/consul
- /consul-bin/consul
volumeMounts:
- name: consul-bin
mountPath: /consul-bin
{{- if .Values.meshGateway.initCopyConsulContainer }}
{{- if .Values.meshGateway.initCopyConsulContainer.resources }}
resources: {{ toYaml .Values.meshGateway.initCopyConsulContainer.resources | nindent 12 }}
{{- end }}
{{- end }}
{{- if (and .Values.global.tls.enabled .Values.global.tls.enableAutoEncrypt) }}
{{- include "consul.getAutoEncryptClientCA" . | nindent 8 }}
{{- end }}
- name: mesh-gateway-init
image: {{ .Values.global.imageK8S }}
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
{{- if .Values.global.tls.enabled }}
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- end }}
- name: CONSUL_HTTP_ADDR
{{- if .Values.global.tls.enabled }}
value: https://$(HOST_IP):8501
{{- else }}
value: http://$(HOST_IP):8500
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
{{- if .Values.global.acls.manageSystemACLs }}
consul-k8s-control-plane acl-init \
-component-name=mesh-gateway \
-token-sink-file=/consul/service/acl-token \
{{- if and .Values.global.federation.enabled .Values.global.federation.primaryDatacenter }}
-acl-auth-method={{ template "consul.fullname" . }}-k8s-component-auth-method-{{ .Values.global.datacenter }} \
-primary-datacenter={{ .Values.global.federation.primaryDatacenter }} \
{{- else }}
-acl-auth-method={{ template "consul.fullname" . }}-k8s-component-auth-method \
{{- end }}
{{- if .Values.global.adminPartitions.enabled }}
-partition={{ .Values.global.adminPartitions.name }} \
{{- end }}
-consul-api-timeout={{ .Values.global.consulAPITimeout }} \
-log-level={{ default .Values.global.logLevel }} \
-log-json={{ .Values.global.logJSON }}
{{ end }}
{{- $source := .Values.meshGateway.wanAddress.source }}
{{- $serviceType := .Values.meshGateway.service.type }}
{{- if and (eq $source "Service") (not .Values.meshGateway.service.enabled) }}{{ fail "if meshGateway.wanAddress.source=Service then meshGateway.service.enabled must be set to true" }}{{ end }}
{{- if or (eq $source "NodeIP") (and (eq $source "Service") (eq $serviceType "NodePort")) }}
WAN_ADDR="${HOST_IP}"
{{- else if eq $source "NodeName" }}
WAN_ADDR="${NODE_NAME}"
{{- else if and (eq $source "Service") (or (eq $serviceType "ClusterIP") (eq $serviceType "LoadBalancer")) }}
consul-k8s-control-plane service-address \
-log-level={{ .Values.global.logLevel }} \
-log-json={{ .Values.global.logJSON }} \
-k8s-namespace={{ .Release.Namespace }} \
-name={{ template "consul.fullname" . }}-mesh-gateway \
-output-file=/tmp/address.txt
WAN_ADDR="$(cat /tmp/address.txt)"
{{- else if eq $source "Static" }}
{{- if eq .Values.meshGateway.wanAddress.static "" }}{{ fail "if meshGateway.wanAddress.source=Static then meshGateway.wanAddress.static cannot be empty" }}{{ end }}
WAN_ADDR="{{ .Values.meshGateway.wanAddress.static }}"
{{- else }}
{{- fail "currently set meshGateway values for wanAddress.source and service.type are not supported" }}
{{- end }}
{{- if eq $source "Service" }}
{{- if eq $serviceType "NodePort" }}
{{- if not .Values.meshGateway.service.nodePort }}{{ fail "if meshGateway.wanAddress.source=Service and meshGateway.service.type=NodePort, meshGateway.service.nodePort must be set" }}{{ end }}
WAN_PORT="{{ .Values.meshGateway.service.nodePort }}"
{{- else }}
WAN_PORT="{{ .Values.meshGateway.service.port }}"
{{- end }}
{{- else }}
WAN_PORT="{{ .Values.meshGateway.wanAddress.port }}"
{{- end }}
cat > /consul/service/service.hcl << EOF
service {
kind = "mesh-gateway"
name = "{{ .Values.meshGateway.consulServiceName }}"
{{- if .Values.global.federation.enabled }}
meta {
consul-wan-federation = "1"
}
{{- end }}
{{- if (and .Values.global.metrics.enabled .Values.global.metrics.enableGatewayMetrics) }}
proxy { config { envoy_prometheus_bind_addr = "${POD_IP}:20200" } }
{{- end }}
port = {{ .Values.meshGateway.containerPort }}
address = "${POD_IP}"
{{- if .Values.global.adminPartitions.enabled }}
partition = "{{ .Values.global.adminPartitions.name }}"
{{- end }}
tagged_addresses {
lan {
address = "${POD_IP}"
port = {{ .Values.meshGateway.containerPort }}
}
wan {
address = "${WAN_ADDR}"
port = ${WAN_PORT}
}
}
checks = [
{
name = "Mesh Gateway Listening"
interval = "10s"
tcp = "${POD_IP}:{{ .Values.meshGateway.containerPort }}"
deregister_critical_service_after = "6h"
}
]
}
EOF
/consul-bin/consul services register \
{{- if .Values.global.acls.manageSystemACLs }}
-token-file=/consul/service/acl-token \
{{- end }}
/consul/service/service.hcl
volumeMounts:
- name: consul-service
mountPath: /consul/service
- name: consul-bin
mountPath: /consul-bin
{{- if .Values.global.tls.enabled }}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
{{- else }}
- name: consul-ca-cert
{{- end }}
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
{{- if .Values.meshGateway.initServiceInitContainer.resources }}
resources: {{ toYaml .Values.meshGateway.initServiceInitContainer.resources | nindent 12 }}
{{- end }}
containers:
- name: mesh-gateway
image: {{ .Values.global.imageEnvoy | quote }}
{{- if .Values.meshGateway.resources }}
resources:
{{- if eq (typeOf .Values.meshGateway.resources) "string" }}
{{ tpl .Values.meshGateway.resources . | nindent 12 | trim }}
{{- else }}
{{- toYaml .Values.meshGateway.resources | nindent 12 }}
{{- end }}
{{- end }}
volumeMounts:
- mountPath: /consul/service
name: consul-service
readOnly: true
- name: consul-bin
mountPath: /consul-bin
{{- if .Values.global.tls.enabled }}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
{{- else }}
- name: consul-ca-cert
{{- end }}
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
{{- if eq .Values.meshGateway.wanAddress.source "NodeName" }}
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
{{- end }}
{{- if .Values.global.acls.manageSystemACLs }}
- name: CONSUL_HTTP_TOKEN_FILE
value: /consul/service/acl-token
{{- end }}
{{- if .Values.global.tls.enabled }}
- name: CONSUL_HTTP_ADDR
value: https://$(HOST_IP):8501
- name: CONSUL_GRPC_ADDR
value: https://$(HOST_IP):8502
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- else }}
- name: CONSUL_HTTP_ADDR
value: http://$(HOST_IP):8500
- name: CONSUL_GRPC_ADDR
value: $(HOST_IP):8502
{{- end }}
command:
- /consul-bin/consul
- connect
- envoy
- -mesh-gateway
{{- if .Values.global.adminPartitions.enabled }}
- -partition={{ .Values.global.adminPartitions.name }}
{{- end }}
livenessProbe:
tcpSocket:
port: {{ .Values.meshGateway.containerPort }}
failureThreshold: 3
initialDelaySeconds: 30
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
readinessProbe:
tcpSocket:
port: {{ .Values.meshGateway.containerPort }}
failureThreshold: 3
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
ports:
- name: gateway
containerPort: {{ .Values.meshGateway.containerPort }}
{{- if .Values.meshGateway.hostPort }}
hostPort: {{ .Values.meshGateway.hostPort }}
{{- end }}
lifecycle:
preStop:
exec:
command:
- "/bin/sh"
- "-ec"
- "/consul-bin/consul services deregister -id=\"{{ .Values.meshGateway.consulServiceName }}\""
{{- if .Values.global.acls.manageSystemACLs }}
- "/consul-bin/consul logout"
{{- end}}
# consul-sidecar ensures the mesh gateway is always registered with
# the local Consul agent, even if it loses the initial registration.
- name: consul-sidecar
image: {{ .Values.global.imageK8S }}
volumeMounts:
- name: consul-service
mountPath: /consul/service
readOnly: true
- name: consul-bin
mountPath: /consul-bin
{{- if .Values.global.tls.enabled }}
{{- if .Values.global.tls.enableAutoEncrypt }}
- name: consul-auto-encrypt-ca-cert
{{- else }}
- name: consul-ca-cert
{{- end }}
mountPath: /consul/tls/ca
readOnly: true
{{- end }}
{{- if .Values.global.consulSidecarContainer }}
{{- if .Values.global.consulSidecarContainer.resources }}
resources: {{ toYaml .Values.global.consulSidecarContainer.resources | nindent 12 }}
{{- end }}
{{- end }}
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
{{- if .Values.global.tls.enabled }}
- name: CONSUL_HTTP_ADDR
value: https://$(HOST_IP):8501
- name: CONSUL_CACERT
value: /consul/tls/ca/tls.crt
{{- else }}
- name: CONSUL_HTTP_ADDR
value: http://$(HOST_IP):8500
{{- end }}
command:
- consul-k8s-control-plane
- consul-sidecar
- -log-level={{ .Values.global.logLevel }}
- -log-json={{ .Values.global.logJSON }}
- -service-config=/consul/service/service.hcl
- -consul-binary=/consul-bin/consul
- -consul-api-timeout={{ .Values.global.consulAPITimeout }}
{{- if .Values.global.acls.manageSystemACLs }}
- -token-file=/consul/service/acl-token
{{- end }}
{{- if .Values.meshGateway.priorityClassName }}
priorityClassName: {{ .Values.meshGateway.priorityClassName | quote }}
{{- end }}
{{- if .Values.meshGateway.nodeSelector }}
nodeSelector:
{{ tpl .Values.meshGateway.nodeSelector . | indent 8 | trim }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,52 @@
{{- if and .Values.global.enablePodSecurityPolicies .Values.meshGateway.enabled }}
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: {{ template "consul.fullname" . }}-mesh-gateway
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: mesh-gateway
spec:
privileged: false
# Required to prevent escalations to root.
allowPrivilegeEscalation: false
# This is redundant with non-root + disallow privilege escalation,
# but we can provide it for defense in depth.
requiredDropCapabilities:
- ALL
# Allow core volume types.
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
{{- if .Values.meshGateway.hostNetwork }}
hostNetwork: {{ .Values.meshGateway.hostNetwork }}
{{- else }}
hostNetwork: false
{{- end }}
hostPorts:
{{- if .Values.meshGateway.hostPort }}
- min: {{ .Values.meshGateway.hostPort }}
max: {{ .Values.meshGateway.hostPort }}
{{- else if .Values.meshGateway.hostNetwork }}
- min: {{ .Values.meshGateway.containerPort }}
max: {{ .Values.meshGateway.containerPort }}
{{- end }}
hostIPC: false
hostPID: false
runAsUser:
rule: 'RunAsAny'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'
readOnlyRootFilesystem: false
{{- end }}

View File

@ -0,0 +1,33 @@
{{- if and .Values.meshGateway.enabled .Values.meshGateway.service.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ template "consul.fullname" . }}-mesh-gateway
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: mesh-gateway
{{- if .Values.meshGateway.service.annotations }}
annotations:
{{ tpl .Values.meshGateway.service.annotations . | nindent 4 | trim }}
{{- end }}
spec:
selector:
app: {{ template "consul.name" . }}
release: "{{ .Release.Name }}"
component: mesh-gateway
ports:
- name: gateway
port: {{ .Values.meshGateway.service.port }}
targetPort: {{ .Values.meshGateway.containerPort }}
{{- if .Values.meshGateway.service.nodePort }}
nodePort: {{ .Values.meshGateway.service.nodePort }}
{{- end}}
type: {{ .Values.meshGateway.service.type }}
{{- if .Values.meshGateway.service.additionalSpec }}
{{ tpl .Values.meshGateway.service.additionalSpec . | nindent 2 | trim }}
{{- end }}
{{- end }}

Some files were not shown because too many files have changed in this diff Show More