Add dedicated Cloudflare Tunnel for portfolio

This commit is contained in:
2026-07-16 06:08:54 +00:00
parent 4b8aeb524e
commit 08c458a078
12 changed files with 447 additions and 0 deletions
+15
View File
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Namespace
metadata:
name: portfolio-edge
annotations:
argocd.argoproj.io/sync-wave: "-2"
labels:
app.kubernetes.io/name: portfolio-edge
app.kubernetes.io/part-of: portfolio-platform
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: v1.36
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/audit-version: v1.36
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/warn-version: v1.36
+39
View File
@@ -0,0 +1,39 @@
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: portfolio-edge
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "-1"
spec:
description: Restricted GitOps project for the public portfolio Cloudflare Tunnel
sourceRepos:
- http://git.home.lan/jay/k8s-gitops.git
destinations:
- namespace: portfolio-edge
server: https://kubernetes.default.svc
namespaceResourceWhitelist:
- group: ""
kind: LimitRange
- group: ""
kind: ResourceQuota
- group: ""
kind: ServiceAccount
- group: apps
kind: Deployment
- group: bitnami.com
kind: SealedSecret
- group: networking.k8s.io
kind: NetworkPolicy
- group: policy
kind: PodDisruptionBudget
orphanedResources:
warn: true
ignore:
- group: ""
kind: Secret
name: portfolio-edge-tunnel-token
+34
View File
@@ -0,0 +1,34 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: portfolio-edge
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "0"
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: portfolio-edge
source:
repoURL: http://git.home.lan/jay/k8s-gitops.git
targetRevision: main
path: apps/portfolio-edge
destination:
server: https://kubernetes.default.svc
namespace: portfolio-edge
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- ApplyOutOfSyncOnly=true
- PruneLast=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 1m
+125
View File
@@ -0,0 +1,125 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: portfolio-edge
namespace: portfolio-edge
labels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
app.kubernetes.io/component: edge
app.kubernetes.io/part-of: portfolio-platform
spec:
replicas: 2
revisionHistoryLimit: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
template:
metadata:
labels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
app.kubernetes.io/component: edge
app.kubernetes.io/part-of: portfolio-platform
spec:
serviceAccountName: portfolio-edge
automountServiceAccountToken: false
terminationGracePeriodSeconds: 30
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
seccompProfile:
type: RuntimeDefault
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
containers:
- name: cloudflared
image: cloudflare/cloudflared:2026.7.2
imagePullPolicy: IfNotPresent
command:
- cloudflared
- tunnel
- --no-autoupdate
- --loglevel
- info
- --metrics
- 0.0.0.0:2000
- run
env:
- name: TUNNEL_TOKEN
valueFrom:
secretKeyRef:
name: portfolio-edge-tunnel-token
key: token
ports:
- name: metrics
containerPort: 2000
protocol: TCP
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumeMounts:
- name: tmp
mountPath: /tmp
resources:
requests:
cpu: 25m
memory: 64Mi
ephemeral-storage: 16Mi
limits:
cpu: 250m
memory: 256Mi
ephemeral-storage: 128Mi
startupProbe:
httpGet:
path: /ready
port: metrics
periodSeconds: 3
timeoutSeconds: 2
failureThreshold: 40
readinessProbe:
httpGet:
path: /ready
port: metrics
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
livenessProbe:
httpGet:
path: /ready
port: metrics
initialDelaySeconds: 20
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
volumes:
- name: tmp
emptyDir:
medium: Memory
sizeLimit: 16Mi
+13
View File
@@ -0,0 +1,13 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: portfolio-edge
resources:
- serviceaccount.yaml
- sealedsecret.yaml
- resourcequota.yaml
- limitrange.yaml
- deployment.yaml
- networkpolicy.yaml
- poddisruptionbudget.yaml
+24
View File
@@ -0,0 +1,24 @@
apiVersion: v1
kind: LimitRange
metadata:
name: portfolio-edge-limits
namespace: portfolio-edge
labels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
app.kubernetes.io/part-of: portfolio-platform
spec:
limits:
- type: Container
defaultRequest:
cpu: 25m
memory: 64Mi
ephemeral-storage: 16Mi
default:
cpu: 250m
memory: 256Mi
ephemeral-storage: 128Mi
max:
cpu: 500m
memory: 512Mi
ephemeral-storage: 256Mi
+108
View File
@@ -0,0 +1,108 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: portfolio-edge
labels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
app.kubernetes.io/part-of: portfolio-platform
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
namespace: portfolio-edge
labels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
app.kubernetes.io/part-of: portfolio-platform
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-cloudflare-tunnel-egress
namespace: portfolio-edge
labels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
app.kubernetes.io/part-of: portfolio-platform
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
- 100.64.0.0/10
- 127.0.0.0/8
- 169.254.0.0/16
- 172.16.0.0/12
- 192.168.0.0/16
ports:
- protocol: UDP
port: 7844
- protocol: TCP
port: 7844
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-portfolio-origin-egress
namespace: portfolio-edge
labels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
app.kubernetes.io/part-of: portfolio-platform
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: portfolio
podSelector:
matchLabels:
app.kubernetes.io/name: portfolio
app.kubernetes.io/instance: portfolio
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 8080
@@ -0,0 +1,15 @@
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: portfolio-edge
namespace: portfolio-edge
labels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
app.kubernetes.io/part-of: portfolio-platform
spec:
minAvailable: 1
selector:
matchLabels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
+22
View File
@@ -0,0 +1,22 @@
apiVersion: v1
kind: ResourceQuota
metadata:
name: portfolio-edge-quota
namespace: portfolio-edge
labels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
app.kubernetes.io/part-of: portfolio-platform
spec:
hard:
requests.cpu: "250m"
requests.memory: 512Mi
limits.cpu: "1"
limits.memory: 1Gi
requests.ephemeral-storage: 256Mi
limits.ephemeral-storage: 1Gi
pods: "4"
secrets: "5"
count/deployments.apps: "2"
count/networkpolicies.networking.k8s.io: "10"
count/poddisruptionbudgets.policy: "2"
+13
View File
@@ -0,0 +1,13 @@
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: portfolio-edge-tunnel-token
namespace: portfolio-edge
spec:
encryptedData:
token: AgAxFQBo2LTfbjzYFIBy8W/6KpnDy0IKQa5CY5LNZcSVv6+O7P/TCYbR9oUQBV5celabmDpZXVmoAHOrrXZeEiLcHjVpwur9hTbFUkE6jSyOL1X46SA7MHwZg3Y7jR+RXE9MWVGVJhy2QxZ3gExsOAAEi+9NZvy7pwFKocLIVpkux1gfXDTjMRTy9OwclD96kTPAcoxq7y99VccTVQo6/6Au1Ry+wEyvmMjiZhbYx1W5f3g1/j7JLvpLXe0OBcqHTIdbcRh6EQQQYnulzhuDfK1rOmpZ+PBit2amD1NN3+okGXm01EvKtu08cTTczn1Xp/jwkwlr0RYKNeOM0pnhhZbWrdSVRYIASYDc3B67ZT2SyHn0TfKDJS2RJ8KtPcXpEu5rGMa7l3sppMwXAemUI/mATe1TtZDHtfMKqBYHFRHNKynVdGs6FXGzQ2qisSzStx4nMg0M2MpQ2Qp9HIMJQ8n0X41Xn5VrGUQ+nf+rMi/fEXeD04r8502Mt7I9E5k0apxh3b9WzVNUa2mohkhhMV4AiJtaTy/Yesothb5vZ13WnyWIRqgh8aRDjvzhdDLDBKaZCpnbytlooSjg7JdQmcHoZNcL3Eb6HBjGj9v4JEnLpSPaplOz3jyLcGfXyTykoiPxWsWXrjVNyA5JkOS2dvU6vQQ65JRJW0NDoqUkDSLXJBQIRpWt8eWHfEyXfAWVErZM2uR74QoB/ABWdKspGR+S0pfhrhpe4c2ycJQ8MZByMegXMmV1JxwfUGi6P0gnvHpHw1V9L8ZYRQpA6cokCdY5cLwmqNjrhZ9K28PwrlaBOdHexPy39B9FmswaE5+L4zLSqMcp+2cimdoKsAlAKzpNi/e/SFFkqfGI5Ekpw6SRAd/doXoymxE4fShATFApRaNsfyPpo09/hfyjJwM9BApRvbjM6IF7dGnShkMfnjYCET4ghQuqhw5NRFM+RKREd6+1z9cnI65JEsybzhXL+6b5qzSj1hGuRMEjLMbF1Zl6Whjta0krl5YatrT4AB18bHW0xpSMVtW6YCT/y4xHYXhZa/uCOSepcp7sQ9TlafRWPBsvuN9nlCI5AiMoaZGkFiQ25CParB+RNtMIj5/TnGJSI9DmhK3Nhrapymxg1h+tAZXyF3sbtX1F3YbZ+k0IJRWlFC+pE5lBTKC3Y2C5AcGTGI9UNPI6HT5FWepGT5k4Zw==
template:
metadata:
name: portfolio-edge-tunnel-token
namespace: portfolio-edge
+11
View File
@@ -0,0 +1,11 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: portfolio-edge
namespace: portfolio-edge
labels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
app.kubernetes.io/component: edge
app.kubernetes.io/part-of: portfolio-platform
automountServiceAccountToken: false
+28
View File
@@ -39,3 +39,31 @@ spec:
ports: ports:
- protocol: TCP - protocol: TCP
port: 8080 port: 8080
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-portfolio-edge
namespace: portfolio
labels:
app.kubernetes.io/name: portfolio
app.kubernetes.io/part-of: portfolio-platform
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: portfolio
app.kubernetes.io/instance: portfolio
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: portfolio-edge
podSelector:
matchLabels:
app.kubernetes.io/name: cloudflared
app.kubernetes.io/instance: portfolio-edge
ports:
- protocol: TCP
port: 8080