feat(ingress): Add additional traefik for internal only access

A new traefik deployment has been added, and two ingressclasses have been set for the new instance, as well as the previous one. This allows the network to be split in two, one for external access and another for internal access. Each traefik deployment is connected to a loadbalancer requesting the IP necessary for each type of access.
This commit is contained in:
Tanguy Herbron 2022-11-20 03:38:22 +01:00
parent aa9e372c98
commit 0a41373688
12 changed files with 181 additions and 49 deletions

View File

@ -1,8 +1,10 @@
# K3s cluster # K3s cluster
/!\ CHECK PORT RULES FOR EXPOSING INTERNAL SERVICES
| Name | Usage | Accessibility | Host | DB type | Additional data | Backup configuration | Loki integration | Prometheus integration | Status | | Name | Usage | Accessibility | Host | DB type | Additional data | Backup configuration | Loki integration | Prometheus integration | Status |
|-------------------------|--------------------------------------|---------------|--------------|------------|----------------------|----------------------|------------------|------------------------|-----------------------------------| |-------------------------|--------------------------------------|---------------|--------------|------------|----------------------|----------------------|------------------|------------------------|-----------------------------------|
| Traefik | Reverse proxy and load balancer | Public* | Socrates | - | - | - | Configured | Configured | Completed | | Traefik | Reverse proxy and load balancer | Public* | Socrates | - | - | - | Configured | Configured | Completed<sup>5</sup> |
| Vaultwarden | Password manager | Public | Pythagoras-b | MariaDB | - | 4AM K8s CronJob | Configured | Not available | Completed | | Vaultwarden | Password manager | Public | Pythagoras-b | MariaDB | - | 4AM K8s CronJob | Configured | Not available | Completed |
| Gitlab | Version control system | Public | Pythagoras-b | PostgreSQL | User created content | 5AM internal CronJob | Configured | Configured | Completed<sup>4</sup> | | Gitlab | Version control system | Public | Pythagoras-b | PostgreSQL | User created content | 5AM internal CronJob | Configured | Configured | Completed<sup>4</sup> |
| Prometheus | Metrics aggregator | Private | Pythagoras-b | TBD | - | Not configured | Configured | Configured | Partial | | Prometheus | Metrics aggregator | Private | Pythagoras-b | TBD | - | Not configured | Configured | Configured | Partial |
@ -32,6 +34,7 @@
<sup>2</sup> Missing configuration for NAS volume mounting (over network)<br> <sup>2</sup> Missing configuration for NAS volume mounting (over network)<br>
<sup>3</sup> Missing Longhorn scheduling for saving media_store and secret management<br> <sup>3</sup> Missing Longhorn scheduling for saving media_store and secret management<br>
<sup>4</sup> Backup management is not handled by k3s but by an internal cronjob rule (Change image name when putting to production)<br> <sup>4</sup> Backup management is not handled by k3s but by an internal cronjob rule (Change image name when putting to production)<br>
<sup>5</sup> Missing dashboard configuration<br>
## Backup management ## Backup management
### Databases ### Databases
@ -57,7 +60,7 @@ longhorn
- Change host/deployment specific variables to use environment variables - Change host/deployment specific variables to use environment variables
- Write CI/CD pipeline to create environment loaded files - Write CI/CD pipeline to create environment loaded files
- Write CI/CD pipeline to deploy cluster - Write CI/CD pipeline to deploy cluster
- ~~Setup internal traefik with nodeport as reverse proxy for internal only services~~ Done through internal LB - ~~Setup internal traefik with nodeport as reverse proxy for internal only services~~ Done through double ingress class and LB
- ~~Setup DB container sidecars for automated backups to Longhorn volume~~ - ~~Setup DB container sidecars for automated backups to Longhorn volume~~
- Setup secrets configuration through CI/CD variable injection - Setup secrets configuration through CI/CD variable injection
- Explore permission issues when issuing OVH API keys (not working for wildcard and `beta.halia.dev` subdomain) - Explore permission issues when issuing OVH API keys (not working for wildcard and `beta.halia.dev` subdomain)
@ -103,5 +106,11 @@ This ansible script could create one (or more) additional client(s) depending on
Cf : https://docs.k3s.io/advanced#auto-deploying-manifests Cf : https://docs.k3s.io/advanced#auto-deploying-manifests
### Development domains ### Development domains
To access a service publicly when developping, the domain name should be *.beta.halia.dev To access a service publicly when developing, the domain name should be *.beta.halia.dev
To only expose a service internally, the domain name should be *.k3s.beta To only expose a service internally, the domain name should be *.k3s.beta
### Ingresses
To split between external and internal services, two traefik ingresses are implemented through the `ingressclass` annotation.
`traefik-external` will only allow external access to a given service, while `traefik-internal` restrict to an internal only access.

View File

@ -26,7 +26,7 @@ items:
name: minecrafttcp name: minecrafttcp
targetPort: "minecrafttcp" targetPort: "minecrafttcp"
protocol: TCP protocol: TCP
- port: 80 - port: 80 # Change port here to accomodate for internal only services
name: web name: web
targetPort: "web" targetPort: "web"
protocol: TCP protocol: TCP

View File

@ -0,0 +1,146 @@
---
# Source: traefik/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: traefik-inter
labels:
app.kubernetes.io/name: traefik-inter
app.kubernetes.io/instance: traefik-inter
annotations:
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: traefik-inter
app.kubernetes.io/instance: traefik-inter
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
minReadySeconds: 0
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/path: "/metrics"
prometheus.io/port: "9100"
labels:
app.kubernetes.io/name: traefik-inter
app.kubernetes.io/instance: traefik-inter
spec:
serviceAccountName: traefik
terminationGracePeriodSeconds: 60
hostNetwork: false
containers:
- image: "traefik:2.8.4"
imagePullPolicy: IfNotPresent
name: traefik-inter
resources:
readinessProbe:
httpGet:
path: /ping
port: 9000
failureThreshold: 1
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 2
livenessProbe:
httpGet:
path: /ping
port: 9000
failureThreshold: 3
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 2
ports:
- name: "admin"
containerPort: 8080
protocol: "TCP"
- name: "metrics"
containerPort: 9100
protocol: "TCP"
- name: "traefik"
containerPort: 9000
protocol: "TCP"
- name: "web"
containerPort: 8000
protocol: "TCP"
- name: "websecure"
containerPort: 8443
protocol: "TCP"
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsGroup: 65532
runAsNonRoot: true
runAsUser: 65532
volumeMounts:
- name: data
mountPath: /certs
- name: tmp
mountPath: /tmp
args:
- "--global.checknewversion"
- "--entrypoints.admin.address=:8080/tcp"
- "--entrypoints.metrics.address=:9100/tcp"
- "--entrypoints.traefik.address=:9000/tcp"
- "--entrypoints.web.address=:8000/tcp"
- "--entrypoints.websecure.address=:8443/tcp"
- "--api.dashboard=true"
- "--api.insecure=true"
- "--ping=true"
- "--metrics.prometheus=true"
- "--metrics.prometheus.entrypoint=metrics"
- "--providers.kubernetescrd"
- "--providers.kubernetesingress"
- "--providers.kubernetescrd.ingressclass=traefik-inter"
- "--providers.kubernetesingress.ingressclass=traefik-inter"
- "--entrypoints.web.http.redirections.entryPoint.to=:443"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
- "--log.level=DEBUG"
- "--accesslog=true"
- "--entrypoints.websecure.http.tls=true"
- "--entrypoints.websecure.http.tls.certresolver=letsencrypt"
- "--entrypoints.websecure.http.tls.domains[0].main=k3s.beta"
- "--entrypoints.websecure.http.tls.domains[0].sans=*.k3s.beta"
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.dnschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=ovh"
- "--certificatesresolvers.letsencrypt.acme.dnschallenge.resolvers=1.1.1.1"
- "--certificatesresolvers.letsencrypt.acme.email=tanguy.herbron@outlook.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/certs/acme.json"
env:
- name: OVH_APPLICATION_KEY
valueFrom:
secretKeyRef:
key: appKey
name: ovh-api-credentials
- name: OVH_APPLICATION_SECRET
valueFrom:
secretKeyRef:
key: appSecret
name: ovh-api-credentials
- name: OVH_CONSUMER_KEY
valueFrom:
secretKeyRef:
key: consumerKey
name: ovh-api-credentials
- name: OVH_ENDPOINT
valueFrom:
secretKeyRef:
key: endpoint
name: ovh-api-credentials
volumes:
- name: data
persistentVolumeClaim:
claimName: traefik-inter
- name: tmp
emptyDir: {}
securityContext:
fsGroup: 65532

View File

@ -0,0 +1,18 @@
---
# Source: traefik/templates/pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: traefik-inter
annotations:
helm.sh/resource-policy: keep
labels:
app.kubernetes.io/name: traefik-inter
app.kubernetes.io/instance: traefik-inter
spec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: "128Mi"
storageClassName: "local-path"

View File

@ -10,22 +10,16 @@ items:
metadata: metadata:
name: traefik-internal name: traefik-internal
labels: labels:
app.kubernetes.io/name: traefik-internal app.kubernetes.io/name: traefik-inter
helm.sh/chart: traefik-10.24.2 app.kubernetes.io/instance: traefik-inter
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/instance: traefik
annotations: annotations:
spec: spec:
type: LoadBalancer type: LoadBalancer
loadBalancerIP: 10.10.0.64 loadBalancerIP: 10.10.0.64
selector: selector:
app.kubernetes.io/name: traefik app.kubernetes.io/name: traefik-inter
app.kubernetes.io/instance: traefik app.kubernetes.io/instance: traefik-inter
ports: ports:
- port: 25565
name: minecrafttcp
targetPort: "minecrafttcp"
protocol: TCP
- port: 80 - port: 80
name: web name: web
targetPort: "web" targetPort: "web"

View File

@ -1,22 +0,0 @@
---
# Source: traefik/templates/dashboard-hook-ingressroute.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard
annotations:
helm.sh/hook: "post-install,post-upgrade"
labels:
app.kubernetes.io/name: traefik
helm.sh/chart: traefik-10.24.2
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/instance: traefik
spec:
entryPoints:
- traefik
routes:
- match: PathPrefix(`/dashboard`) || PathPrefix(`/api`)
kind: Rule
services:
- name: api@internal
kind: TraefikService

View File

@ -1,13 +0,0 @@
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`traefik.k3s.beta`)
services:
- name: api@internal
kind: TraefikService