diff --git a/charts/tailscale-subnet-router/.helmignore b/charts/tailscale-subnet-router/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/charts/tailscale-subnet-router/.helmignore @@ -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/ diff --git a/charts/tailscale-subnet-router/Chart.yaml b/charts/tailscale-subnet-router/Chart.yaml new file mode 100644 index 00000000..a4c3eaa9 --- /dev/null +++ b/charts/tailscale-subnet-router/Chart.yaml @@ -0,0 +1,9 @@ +apiVersion: v2 +name: tailscale-subnet-router +description: Deploy a Tailscale subnet router on Kubernetes +type: application +version: 0.1.0 +appVersion: "v1.20" +home: https://github.com/gtaylor/helm-charts/charts/tailscale-subnet-router +sources: + - https://github.com/gtaylor/helm-charts/charts/tailscale-subnet-router diff --git a/charts/tailscale-subnet-router/README.md b/charts/tailscale-subnet-router/README.md new file mode 100644 index 00000000..c3a7ab70 --- /dev/null +++ b/charts/tailscale-subnet-router/README.md @@ -0,0 +1,7 @@ +# tailscale-subnet-router + +Deploy a [Tailscale subnet router](https://tailscale.com/blog/kubecon-21/) on Kubernetes. + +## Values + +See [values.yaml](values.yaml). diff --git a/charts/tailscale-subnet-router/templates/_helpers.tpl b/charts/tailscale-subnet-router/templates/_helpers.tpl new file mode 100644 index 00000000..f5e5dad3 --- /dev/null +++ b/charts/tailscale-subnet-router/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "tailscale-subnet-router.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 "tailscale-subnet-router.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 "tailscale-subnet-router.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "tailscale-subnet-router.labels" -}} +helm.sh/chart: {{ include "tailscale-subnet-router.chart" . }} +{{ include "tailscale-subnet-router.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "tailscale-subnet-router.selectorLabels" -}} +app.kubernetes.io/name: {{ include "tailscale-subnet-router.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "tailscale-subnet-router.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "tailscale-subnet-router.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/charts/tailscale-subnet-router/templates/role.yaml b/charts/tailscale-subnet-router/templates/role.yaml new file mode 100644 index 00000000..cc419187 --- /dev/null +++ b/charts/tailscale-subnet-router/templates/role.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "tailscale-subnet-router.fullname" . }} + labels: + {{- include "tailscale-subnet-router.labels" . | nindent 4 }} +rules: + - apiGroups: [""] # "" indicates the core API group + resources: ["secrets"] + # Create can not be restricted to a resource name. + verbs: ["create"] + - apiGroups: [""] + resourceNames: [ {{ .Values.tailscale.state.secretName }} ] + resources: ["secrets"] + verbs: ["get", "update"] diff --git a/charts/tailscale-subnet-router/templates/rolebinding.yaml b/charts/tailscale-subnet-router/templates/rolebinding.yaml new file mode 100644 index 00000000..463986c4 --- /dev/null +++ b/charts/tailscale-subnet-router/templates/rolebinding.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "tailscale-subnet-router.fullname" . }} + labels: + {{- include "tailscale-subnet-router.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ include "tailscale-subnet-router.serviceAccountName" . }} +roleRef: + kind: Role + name: {{ include "tailscale-subnet-router.fullname" . }} + apiGroup: rbac.authorization.k8s.io diff --git a/charts/tailscale-subnet-router/templates/serviceaccount.yaml b/charts/tailscale-subnet-router/templates/serviceaccount.yaml new file mode 100644 index 00000000..05465724 --- /dev/null +++ b/charts/tailscale-subnet-router/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "tailscale-subnet-router.serviceAccountName" . }} + labels: + {{- include "tailscale-subnet-router.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/tailscale-subnet-router/templates/statefulset.yaml b/charts/tailscale-subnet-router/templates/statefulset.yaml new file mode 100644 index 00000000..e9721d99 --- /dev/null +++ b/charts/tailscale-subnet-router/templates/statefulset.yaml @@ -0,0 +1,68 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "tailscale-subnet-router.fullname" . }} + labels: + {{- include "tailscale-subnet-router.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicas }} + updateStrategy: + type: RollingUpdate + selector: + matchLabels: + {{- include "tailscale-subnet-router.selectorLabels" . | nindent 6 }} + serviceName: {{ include "tailscale-subnet-router.name" . }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "tailscale-subnet-router.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "tailscale-subnet-router.fullname" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: {{ .Values.image.repository }}:{{ default .Chart.AppVersion .Values.image.tag }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + - name: KUBE_SECRET + value: {{ .Values.tailscale.state.secretName }} + - name: USERSPACE + value: "true" + - name: AUTH_KEY + valueFrom: + secretKeyRef: + name: {{ .Values.tailscale.auth.secretName }} + key: {{ .Values.tailscale.auth.secretKey }} + - name: ROUTES + value: "{{ .Values.tailscale.routes.serviceCIDR}},{{ .Values.tailscale.routes.podCIDR}}" + {{- with .Values.resources }} + resources: {{ toYaml . | nindent 16 }} + {{- end }} + {{- if .Values.volumeMounts }} + volumeMounts: + {{- toYaml .Values.volumeMounts | nindent 12}} + {{- 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 }} + {{- if .Values.volumes }} + volumes: + {{- toYaml .Values.volumes | nindent 8}} + {{- end }} diff --git a/charts/tailscale-subnet-router/values.yaml b/charts/tailscale-subnet-router/values.yaml new file mode 100644 index 00000000..bfd0fac3 --- /dev/null +++ b/charts/tailscale-subnet-router/values.yaml @@ -0,0 +1,73 @@ +replicas: 1 + +image: + repository: docker.aegn.dev:5443/tailscale/tailscale-subnet-proxy + pullPolicy: Always + tag: latest + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +tailscale: + auth: + secretName: tailscale-subnet-router-secrets + secretKey: AUTH_KEY + state: + secretName: tailscale-subnet-router-state + routes: + serviceCIDR: "10.96.0.0/12" + podCIDR: "10.244.0.0/16" + +serviceAccount: + # Specifies whether a service account should be created + create: 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: "" + +volumes: [] + +volumeMounts: [] + +# -- Additional annotations for the pods +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: + runAsUser: 1000 + runAsGroup: 1000 + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + +## Resources to allocate to the pods +## +resources: {} +# limits: +# cpu: 50m +# memory: 64Mi +# requests: +# cpu: 50m +# memory: 64Mi + +## Node labels for pod assignment +## ref: https://kubernetes.io/docs/user-guide/node-selection/ +# +nodeSelector: {} + +## Tolerations for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] + +## Affinity for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## +affinity: {}