Added Helm chart for frps.

This commit is contained in:
Chung Tran 2025-01-07 23:18:28 -05:00
parent 27db6217ec
commit 44d9e18f3d
No known key found for this signature in database
GPG Key ID: ED45AC70BED27CE7
14 changed files with 729 additions and 0 deletions

View File

@ -58,6 +58,7 @@ frp also offers a P2P connect mode.
* [Enable HTTPS for a local HTTP(S) service](#enable-https-for-a-local-https-service)
* [Expose your service privately](#expose-your-service-privately)
* [P2P Mode](#p2p-mode)
* [Run in Kubernetes](#run-in-kubernetes)
* [Features](#features)
* [Configuration Files](#configuration-files)
* [Using Environment Variables](#using-environment-variables)
@ -472,6 +473,11 @@ Note that it may not work with all types of NAT devices. You might want to fallb
`ssh -oPort=6000 127.0.0.1`
### Run in Kubernetes
Refer to [helm/frps/README.md](./helm/frps/README.md) for examples on
how to run frps in Kubernetes.
## Features
### Configuration Files

23
helm/frps/.helmignore Normal file
View File

@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

27
helm/frps/Chart.yaml Normal file
View File

@ -0,0 +1,27 @@
apiVersion: v2
name: frps
description: A Helm chart for frps running in Kubernetes.
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "v0.61.1"
home: https://github.com/fatedier/frp

110
helm/frps/README.md Normal file
View File

@ -0,0 +1,110 @@
# frps Helm Chart
## Install the chart
```console
helm install frps .
```
## Uninstall the chart
```console
helm delete frps
```
## Examples
1. Use `LoadBalancer` service to expose frps.
```yaml
# values.yaml
service:
type: LoadBalancer
settings:
loadBalancerIP: 34.24.52.92 # Replace with correct IP
# frpc.yaml
serverAddr: 34.24.52.92
serverPort: 7000
auth:
method: token
token: "123456789"
```
1. Enable admin web server UI using nginx ingress controller.
```yaml
# values.yaml
service:
extras:
admin:
enabled: true
ingress:
extras:
admin:
enabled: true
className: nginx
hosts:
- host: frps-admin.mydomain.com
paths:
- path: /
pathType: ImplementationSpecific
```
1. Enable `vhostHTTPPort` proxying using nginx ingress controller.
```yaml
# values.yaml
service:
extras:
http:
enabled: true
ingress:
extras:
app1:
enabled: true
className: nginx
hosts:
- host: app1.mydomain.com
paths:
- path: /
pathType: ImplementationSpecific
backendService:
name: frps-http
port: 80
app2:
enabled: true
className: nginx
hosts:
- host: app2.mydomain.com
paths:
- path: /
pathType: ImplementationSpecific
backendService:
name: frps-http
port: 80
# frpc.yaml
serverAddr: 34.24.52.92
serverPort: 7000
auth:
method: token
token: "123456789"
proxies:
- name: app1
type: http
localIP: 127.0.0.1
localPort: 8081
customDomains:
- app1.mydomain.com
- name: app2
type: http
localIP: 127.0.0.1
localPort: 8082
customDomains:
- app2.mydomain.com
```
Refer to [values.yaml](./values.yaml) for additional settings.

View File

@ -0,0 +1,22 @@
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "frps.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch its status by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "frps.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "frps.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "frps.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
{{- end }}

View File

@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "frps.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
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).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "frps.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "frps.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "frps.labels" -}}
helm.sh/chart: {{ include "frps.chart" . }}
{{ include "frps.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "frps.selectorLabels" -}}
app.kubernetes.io/name: {{ include "frps.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "frps.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "frps.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "frps.fullname" . }}
labels:
{{- include "frps.labels" . | nindent 4 }}
data:
config.yaml: |
{{- toYaml .Values.config | nindent 4 }}

View File

@ -0,0 +1,77 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "frps.fullname" . }}
labels:
{{- include "frps.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "frps.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "frps.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "frps.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
args:
- --config
- /etc/frps/config.yaml
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: frps
containerPort: {{ .Values.service.port }}
protocol: TCP
livenessProbe:
{{- toYaml .Values.livenessProbe | nindent 12 }}
readinessProbe:
{{- toYaml .Values.readinessProbe | nindent 12 }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumeMounts:
- name: config
mountPath: /etc/frps
readOnly: true
{{- with .Values.volumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
volumes:
- name: config
configMap:
name: {{ include "frps.fullname" . }}
{{- with .Values.volumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}

View File

@ -0,0 +1,32 @@
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "frps.fullname" . }}
labels:
{{- include "frps.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "frps.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,94 @@
{{ $fullname := include "frps.fullname" . }}
{{ $labels := include "frps.labels" . }}
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullname }}
labels:
{{- $labels | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- with .Values.ingress.className }}
ingressClassName: {{ . }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- with .pathType }}
pathType: {{ . }}
{{- end }}
backend:
service:
name: {{ $.Values.ingress.backendService.name }}
port:
number: {{ $.Values.ingress.backendService.port }}
{{- end }}
{{- end }}
{{- end }}
{{- range $k, $v := .Values.ingress.extras }}
{{- if $v.enabled }}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullname }}-{{ $k }}
labels:
{{- $labels | nindent 4 }}
{{- with $v.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- with $v.className }}
ingressClassName: {{ . }}
{{- end }}
{{- if $v.tls }}
tls:
{{- range $v.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range $v.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- with .pathType }}
pathType: {{ . }}
{{- end }}
backend:
service:
name: {{ $v.backendService.name }}
port:
number: {{ $v.backendService.port }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,49 @@
{{ $fullname := include "frps.fullname" . }}
{{ $labels := include "frps.labels" . }}
{{ $selectors := include "frps.selectorLabels" . }}
apiVersion: v1
kind: Service
metadata:
name: {{ $fullname }}
labels:
{{- $labels | nindent 4 }}
annotations:
{{- toYaml .Values.service.annotations | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: frps
name: frps
selector:
{{- $selectors | nindent 4 }}
{{- with .Values.service.settings }}
{{- toYaml . | nindent 2 }}
{{- end }}
{{- range $k, $v := .Values.service.extras }}
{{- if $v.enabled }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ $fullname }}-{{ $k }}
labels:
{{- $labels | nindent 4 }}
annotations:
{{- toYaml $v.annotations | nindent 4 }}
spec:
type: {{ $v.type }}
ports:
- port: {{ $v.port }}
targetPort: {{ $v.port }}
name: {{ $k }}
selector:
{{- $selectors | nindent 4 }}
{{- with $v.settings }}
{{- toYaml . | nindent 2 }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,13 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "frps.serviceAccountName" . }}
labels:
{{- include "frps.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
{{- end }}

View File

@ -0,0 +1,15 @@
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "frps.fullname" . }}-test-connection"
labels:
{{- include "frps.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "frps.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never

189
helm/frps/values.yaml Normal file
View File

@ -0,0 +1,189 @@
# Default values for frps.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
# This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/
replicaCount: 1
# This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/
image:
repository: ckt114/frps
# This sets the pull policy for images.
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
# This is for the secretes for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
imagePullSecrets: []
# This is to override the chart name.
nameOverride: ""
fullnameOverride: ""
# frps configuration
# ref: https://github.com/fatedier/frp/blob/dev/conf/frps_full_example.toml
config:
bindAddr: "0.0.0.0"
bindPort: 7000
vhostHTTPPort: 80
vhostHTTPSPort: 443
webServer:
addr: "0.0.0.0"
port: 7500
user: "admin"
password: "admin"
auth:
method: "token"
token: "123456789"
#This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/
serviceAccount:
# Specifies whether a service account should be created
create: true
# Automatically mount a ServiceAccount's API credentials?
automount: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
# This is for setting Kubernetes Annotations to a Pod.
# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
podAnnotations: {}
# This is for setting Kubernetes Labels to a Pod.
# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
podLabels: {}
podSecurityContext: {}
# fsGroup: 2000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
# This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/
service:
# This sets the service type more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
type: ClusterIP
# This sets the ports more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#field-spec-ports
port: 7000
annotations: {}
settings: {}
# Create additional services.
extras:
# Service for admin UI.
admin:
enabled: false
type: ClusterIP
port: 7500
annotations: {}
settings: {}
# Service for vhostHTTPPort.
http:
enabled: false
type: ClusterIP
port: 80
annotations: {}
settings: {}
# Service for vhostHTTPSPort.
https:
enabled: false
type: ClusterIP
port: 443
annotations: {}
settings: {}
# This block is for setting up the ingress for more information can be found here: https://kubernetes.io/docs/concepts/services-networking/ingress/
ingress:
enabled: false
className: ""
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: frps.example.com
paths:
- path: /
pathType: ImplementationSpecific
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
backendService:
name: frps
port: 7000
# Create additional ingresses.
extras:
admin:
enabled: false
className: ""
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: frps-admin.example.com
paths:
- path: /
pathType: ImplementationSpecific
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
backendService:
name: frps-admin
port: 7500
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
# This is to setup the liveness and readiness probes more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
livenessProbe:
tcpSocket:
port: frps
readinessProbe:
tcpSocket:
port: frps
#This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80
# Additional volumes on the output Deployment definition.
volumes: []
# - name: foo
# secret:
# secretName: mysecret
# optional: false
# Additional volumeMounts on the output Deployment definition.
volumeMounts: []
# - name: foo
# mountPath: "/etc/foo"
# readOnly: true
nodeSelector: {}
tolerations: []
affinity: {}