Всем привет. Сегодня я хочу рассказать о том, как установить traefik в свой собственный on-premise kubernetes кластер в качестве Ingress Controller.
Traefik может работать в Kubernetes в 2 режимах:
kubernetesingress
- это когда он будет мониторить стандартные объекты с kind: Ingress
с строить маршруты на базе ихkubernetescrd
- это когда для описания маршрутов надо будет создавать объкты kind: IngressRoute
. Этот способ более гибкий, однако при переходе на другой Ingress Controller, вам полностью придется переписать Ingress правила. Кроме того, с точки зрения kubernetes, такой способ развертывания не является Ingress Controller'ом, но нам это не так важно. Важно что мы получим тот же результат.Мы будем разворачивать и то, и то. Кроме того, мы еще и Let's Encrypt подключим.
Что и как мы будет делать: мы пометим один из узлов кластера меткой, которую будем использовать в nodeSelector
для определения того узла, где будет запускаться наш daemonset
. Этот daemonset
будет запускаться в режиме hostNetwork: true
для того, чтобы мы могли открыть порты 80 и 443. Выделенный узел не будет непосредственно доступен из интернета. Для него будут лишь "проброшены" порты 80 и 443.
Итак, метим наш узел:
kubectl label nodes k8s-us1804-a traefik=true
Описываем все необходимые ресурсы для traefik:
# All resources definition must be declared
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressroutes.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRoute
plural: ingressroutes
singular: ingressroute
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: middlewares.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: Middleware
plural: middlewares
singular: middleware
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressroutetcps.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRouteTCP
plural: ingressroutetcps
singular: ingressroutetcp
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressrouteudps.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRouteUDP
plural: ingressrouteudps
singular: ingressrouteudp
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsoptions.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSOption
plural: tlsoptions
singular: tlsoption
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsstores.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSStore
plural: tlsstores
singular: tlsstore
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: traefikservices.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TraefikService
plural: traefikservices
singular: traefikservice
scope: Namespaced
Выдаем права для service account
:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- traefik.containo.us
resources:
- middlewares
- ingressroutes
- traefikservices
- ingressroutetcps
- ingressrouteudps
- tlsoptions
- tlsstores
verbs:
- get
- list
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: default
И запускаем наш traefik:
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
---
apiVersion: v1
kind: ConfigMap
metadata:
name: traefikconfig
data:
traefik.yaml: |-
api:
dashboard: true
entryPoints:
web:
address: ":80"
forwardedHeaders:
insecure: true
websecure:
address: ":443"
forwardedHeaders:
insecure: true
providers:
kubernetesingress: {}
kubernetescrd: {}
certificatesResolvers:
letsencrypt:
acme:
email: vitaliy@leschenko.by
storage: /acme/acme.json
caserver: https://acme-v02.api.letsencrypt.org/directory
httpChallenge:
entryPoint: web
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: traefik
labels:
app: traefik
spec:
selector:
matchLabels:
app: traefik
template:
metadata:
labels:
app: traefik
spec:
hostNetwork: true
serviceAccountName: traefik-ingress-controller
nodeSelector:
kubernetes.io/os: linux
traefik: "true"
volumes:
- name: acme
hostPath:
path: /acme
- name: config
configMap:
name: traefikconfig
containers:
- name: traefik
image: traefik:v2.2
volumeMounts:
- name: acme
mountPath: /acme
- name: config
mountPath: /traefik
args:
- --configFile=/traefik/traefik.yaml
- --log.level=DEBUG
ports:
- name: web
containerPort: 80
- name: https
containerPort: 443
- name: admin
containerPort: 8080
В качестве бонуса создаем правило для dashboard самого traefik'а:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard
spec:
entryPoints:
- websecure
routes:
- match: Host(`traefik.vitaliy.org`)
kind: Rule
services:
- name: api@internal
kind: TraefikService
middlewares:
- name: auth
tls:
certResolver: letsencrypt
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: auth
spec:
basicAuth:
secret: authsecret
---
# A file containing test/test and test2/test2
apiVersion: v1
kind: Secret
metadata:
name: authsecret
namespace: default
data:
users: |2
dGVzdDokYXByMSRINnVza2trVyRJZ1hMUDZld1RyU3VCa1RycUU4d2ovCnRlc3QyOiRhcHIxJGQ5
aHI5SEJCJDRIeHdnVWlyM0hQNEVzZ2dQL1FObzAK
Всё. Через несколько секунд можно обращаться по адресу https://traefik.vitaliy.org.