Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 25 additions & 21 deletions charts/cloudflared/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
{{/* SPDX-License-Identifier: Apache-2.0 */}}
cloudflared has been installed
==============================
cloudflared has been installed.

Installation summary
--------------------
1. Installation summary
-----------------------
Release: {{ .Release.Name }}
Namespace: {{ .Release.Namespace }}
Chart version: {{ .Chart.Version }}
Expand All @@ -14,8 +13,8 @@ Quick tunnel: {{ ternary "enabled" "disabled" .Values.tunnel.quickTunnel.enabled
Metrics service: {{ ternary "enabled" "disabled" .Values.metrics.enabled }}
ServiceMonitor: {{ ternary "enabled" "disabled" .Values.serviceMonitor.enabled }}

Tunnel status
-------------
2. Tunnel status
----------------
cloudflared creates outbound-only connections from this cluster to Cloudflare.
No inbound Kubernetes Service or LoadBalancer is required for application
traffic. Public hostnames and origins are configured in the Cloudflare Zero
Expand All @@ -29,25 +28,22 @@ Follow connection logs:

kubectl logs -l app.kubernetes.io/name=cloudflared -n {{ .Release.Namespace }} --all-containers --tail=50 -f

Look for established tunnel connections:

kubectl logs -l app.kubernetes.io/name=cloudflared -n {{ .Release.Namespace }} --all-containers | grep -i "connection\|tunnel\|registered"

3. Metrics
----------
{{- if .Values.metrics.enabled }}

Metrics
-------
Internal metrics endpoint:

http://{{ include "cloudflared.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.service.port | default 2000 }}/metrics

Port-forward metrics locally:

kubectl port-forward svc/{{ include "cloudflared.fullname" . }} -n {{ .Release.Namespace }} 2000:{{ .Values.service.port | default 2000 }}
{{- else }}
Metrics Service rendering is disabled.
{{- end }}

Credentials
-----------
4. Credentials
--------------
{{- if .Values.tunnel.quickTunnel.enabled }}
Quick tunnel mode does not use a managed tunnel token. Use it only for demos or
smoke tests.
Expand All @@ -68,8 +64,16 @@ Tunnel token was provided through chart-managed Secret data. Prefer an existing
Secret or External Secrets Operator for production.
{{- end }}

Troubleshooting
---------------
5. High availability
--------------------
Replicas: {{ .Values.replicaCount }}
PodDisruptionBudget: {{ ternary "enabled" "disabled" .Values.pdb.enabled }}
{{- if .Values.pdb.enabled }}
PDB minAvailable: {{ .Values.pdb.minAvailable }}
{{- end }}

6. Troubleshooting
------------------
Describe pods:

kubectl describe pod -l app.kubernetes.io/name=cloudflared -n {{ .Release.Namespace }}
Expand All @@ -82,15 +86,15 @@ Inspect recent events:

kubectl get events -n {{ .Release.Namespace }} --sort-by=.lastTimestamp

Cloudflare routing
------------------
7. Cloudflare routing
---------------------
Configure Public Hostnames in the Cloudflare Zero Trust dashboard and point
origins to Kubernetes DNS names such as:

http://service.namespace.svc.cluster.local:80

Documentation
-------------
8. Resources
------------
Chart docs: https://helmforge.dev/docs/charts/cloudflared
Chart source: https://github.com/helmforgedev/charts/tree/main/charts/cloudflared
Cloudflare Tunnel docs: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/
Expand Down
31 changes: 31 additions & 0 deletions charts/cloudflared/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,37 @@ app.kubernetes.io/instance: {{ .Release.Name }}
{{- printf "%s:%s" .Values.image.repository .Values.image.tag -}}
{{- end -}}

{{- define "cloudflared.validate" -}}
{{- if and (not .Values.tunnel.quickTunnel.enabled) (not .Values.tunnel.token) (not .Values.tunnel.existingSecret) -}}
{{- fail "tunnel.token or tunnel.existingSecret is required when tunnel.quickTunnel.enabled is false" -}}
{{- end -}}
{{- if and .Values.tunnel.quickTunnel.enabled (not .Values.tunnel.quickTunnel.helloWorld) (not .Values.tunnel.quickTunnel.url) -}}
{{- fail "tunnel.quickTunnel.url is required when tunnel.quickTunnel.enabled=true and helloWorld=false" -}}
{{- end -}}
{{- if and .Values.externalSecrets.enabled (not .Values.tunnel.existingSecret) -}}
{{- fail "externalSecrets.enabled requires tunnel.existingSecret to be set to prevent credential drift between the chart-managed Secret and the ExternalSecret." -}}
{{- end -}}
{{- if and .Values.externalSecrets.enabled (not .Values.externalSecrets.secretStoreRef.name) -}}
{{- fail "externalSecrets.secretStoreRef.name is required when externalSecrets.enabled=true" -}}
{{- end -}}
{{- if and .Values.externalSecrets.enabled (not .Values.externalSecrets.data) -}}
{{- fail "externalSecrets.data must not be empty when externalSecrets.enabled=true" -}}
{{- end -}}
{{- if and .Values.serviceMonitor.enabled (not .Values.metrics.enabled) -}}
{{- fail "metrics.enabled must be true when serviceMonitor.enabled is true" -}}
{{- end -}}
{{- if and .Values.pdb.enabled (lt (int .Values.replicaCount) (int .Values.pdb.minAvailable)) -}}
{{- fail "replicaCount must be greater than or equal to pdb.minAvailable when pdb.enabled is true" -}}
{{- end -}}
{{- $podLabels := .Values.podLabels | default dict -}}
{{- $selectorLabels := include "cloudflared.selectorLabels" . | fromYaml -}}
{{- range $key, $_ := $selectorLabels -}}
{{- if hasKey $podLabels $key -}}
{{- fail (printf "podLabels must not override selector label %q" $key) -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{/* Tunnel token secret name */}}
{{- define "cloudflared.tunnelSecretName" -}}
{{- if .Values.tunnel.existingSecret -}}
Expand Down
2 changes: 2 additions & 0 deletions charts/cloudflared/templates/validate.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{{/* SPDX-License-Identifier: Apache-2.0 */}}
{{- include "cloudflared.validate" . -}}
91 changes: 91 additions & 0 deletions charts/cloudflared/tests/validation_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# SPDX-License-Identifier: Apache-2.0
suite: Validation
templates:
- templates/validate.yaml
tests:
- it: should render no validation manifest by default
asserts:
- hasDocuments:
count: 0

- it: should fail when managed tunnel has no credentials
set:
tunnel.quickTunnel.enabled: false
asserts:
- failedTemplate:
errorMessage: "tunnel.token or tunnel.existingSecret is required when tunnel.quickTunnel.enabled is false"

- it: should fail when quick tunnel url mode has no url
set:
tunnel.quickTunnel.enabled: true
tunnel.quickTunnel.helloWorld: false
tunnel.quickTunnel.url: ""
asserts:
- failedTemplate:
errorMessage: "tunnel.quickTunnel.url is required when tunnel.quickTunnel.enabled=true and helloWorld=false"

- it: should fail when external secrets has no target secret
set:
externalSecrets.enabled: true
externalSecrets.secretStoreRef.name: helmforge-fake-store
externalSecrets.data:
- secretKey: token
remoteRef:
key: test/password
asserts:
- failedTemplate:
errorMessage: "externalSecrets.enabled requires tunnel.existingSecret to be set to prevent credential drift between the chart-managed Secret and the ExternalSecret."

- it: should fail when external secrets has no store reference
set:
tunnel.existingSecret: cloudflared-tunnel-token
externalSecrets.enabled: true
externalSecrets.data:
- secretKey: token
remoteRef:
key: test/password
asserts:
- failedTemplate:
errorMessage: "externalSecrets.secretStoreRef.name is required when externalSecrets.enabled=true"

- it: should fail when external secrets has no data mappings
set:
tunnel.existingSecret: cloudflared-tunnel-token
externalSecrets.enabled: true
externalSecrets.secretStoreRef.name: helmforge-fake-store
asserts:
- failedTemplate:
errorMessage: "externalSecrets.data must not be empty when externalSecrets.enabled=true"

- it: should fail when service monitor has no metrics service
set:
metrics.enabled: false
serviceMonitor.enabled: true
asserts:
- failedTemplate:
errorMessage: "metrics.enabled must be true when serviceMonitor.enabled is true"

- it: should fail when pdb minAvailable exceeds replicas
set:
replicaCount: 1
pdb.enabled: true
pdb.minAvailable: 2
asserts:
- failedTemplate:
errorMessage: "replicaCount must be greater than or equal to pdb.minAvailable when pdb.enabled is true"

- it: should fail when podLabels override selector labels
set:
podLabels:
app.kubernetes.io/name: custom
asserts:
- failedTemplate:
errorMessage: 'podLabels must not override selector label "app.kubernetes.io/name"'

- it: should fail when podLabels override release selector labels
set:
podLabels:
app.kubernetes.io/instance: custom
asserts:
- failedTemplate:
errorMessage: 'podLabels must not override selector label "app.kubernetes.io/instance"'