نصب و استفاده از Traefik در Kubernetes
Traefik یک reverse proxy و load balancer مدرن و کامله که به توسعه میکروسرویس ها خیلی کمک میکنه. از ویژگی های خوبش اینه که با Endpoint های مختلف سازگاری خوبی داره و میشه همه جا ازش استفاده کرد. برای مثال یک سرویس عادی رو باهاش مسیردهی کنید یا اینکه توی Docker یا K8S ازش استفاده کنید.
در آموزش قبلی یاد گرفتیم که چطور یک کلاستر K8S درست کنیم. این کلاستر میتونه ترکیبی از ماشین های مجازی ، سرور های فیزیکی یا حتی یک شبیه سازی با minikube باشه. حالا که کلاستر ما آماده است ، قبل از استقرار سرویس هامون نیازه تا مواردی رو برای بهبود کار با کلاستر پیاده سازی کنیم
درگیری ها با دنیای خارج
به صورت پیش فرض ، کوبرنتیز شبکه بسته ای رو برای شما تشکیل میده که تا وقتی درون اون باشید هیچ مشکلی وجود نداره. با راه های مختلف هم میتونید به منابع دسترسی داشته باشید و هرکار خواستید انجام بدید. ولی وقتی صحبت از دسترسی های خارج از کلاستر میشه ، بحث فرق داره. اینجا با دو مبحث Ingress و Egress برخورد می کنیم :
- Ingress : انتقال ترافیک اینترنت به کوبرنتیز
- Egress : فرستادن ترافیک به اینترنت
انتقال ترافیک به داخل کلاستر عمل پیچیده ای محسوب میشه و بسته به مدل شبکه ای که پیاده سازی کردید از دو طریق Load Balancer و Ingress Controller انجام میشه.
در حال حاضر Ingress Controller های زیادی برای کوبرنتیز وجود داره که در این جدول میتونید معروف ترین ها رو مشاهده کرده و باهم مقایسه کنید :
در این مطلب کار با Traefik رو بهتون آموزش میدم. در خیلی موارد اگر از کسی در مورد Reverse Proxy , Load Balancer و Ingress Controller بپرسید اولین چیزی که به شما معرفی میکنه Nginx هست. ابزار خوب و قدرتمند که خودش هم اثبات کرده. ولی وقتشه کمی این انحصار رو کنار بذاریم و ابزار های دیگه هم آزمایش کنیم.
دقیقا Traefik چی میکنه ؟
یکی از مواردی که traefik رو برام به یک ابزار همیشگی تبدیل کرده ، سادگی در استفاده است. برعکس باقی کتابخانه های این حوزه که به ازای هر سرویس باید تنظیمات جدیدی اعمال کنید تا عملیات مورد نظر مثل Proxy یا Load-Balancing انجام بشه ، اینجا نیاز به چنین کاری نیست. شما یک بار Traefik رو اجرا می کنید و هنگام استقرار سرویس ها تنظیمات مربوطه رو همونجا اعمال می کنید. اگر با Docker سر و کار داشته باشید از Label و در K8S هم از annotation ها استفاده می کنیم.
اگر پیاده سازی Ingress با کتابخانه های دیگه رو تجربه کرده باشید میدونید که ما همیشه به یک Ingress Route نیاز داریم. حالا Traefik کار رو بازهم برای ما ساده تر کرده و از نسخه 2.2 به بعد فقط کافیه از یک annotation ساده استفاده کرد.
در ادامه بیشتر با روند کارش آشنا میشید
نصب Traefik
آموزش های زیادی برای نصب Traefik وجود داره. برای مثال شما میتونید خیلی راحت از Helm استفاده کنید ( روشی که خود Traefik هم تو مستنداتش ذکر کرده ). یا اینکه خودتون همه چیز رو مدیریت کنید. به علت اینکه ساختار این پیاده سازی واضح تر باشه با روش دوم ادامه میدیم و همه چیز رو خودمون مستقر می کنیم.
CRD / Roles
در اولین مرحله لازمه تا یکسری CRD برای مواردی مانند سرویس ها ، مسیر های TCP ، TLS و ... داشته باشیم. همچنین یک ClusterRole با سطوح دسترسی مختلف تعریف می کنیم. برای تمام این مباحث فایلی با نام rbac.yml
و محتوای زیر آماده کنید :
---
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: 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: 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: 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: traefikservices.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TraefikService
plural: traefikservices
singular: traefikservice
scope: Namespaced
---
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
namespace: kube-system
این فایل را با استفاده از دستور زیر ، اعمال کنید :
kubectl create -f rbac.yml
Deployment
در ادامه لازمه تا Pod اصلی مربوط به Traefik را آماده کنیم. این کار از طریق یک Deployment انجام میشه. فایلی با نام deployment.yml
و محتوای زیر آماده کنید :
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: traefik
release: traefik
name: traefik
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: traefik
release: traefik
template:
metadata:
labels:
app: traefik
release: traefik
spec:
containers:
- args:
- --api
- --api.insecure
- --api.dashboard=true
- --accesslog
- --global.checknewversion=true
- --entryPoints.traefik.address=:8100
- --entryPoints.web.address=:80
- --entryPoints.websecure.address=:443
- --ping=true
- --providers.kubernetescrd=true
- --providers.kubernetesingress=true
- --log.level=INFO
- --serversTransport.insecureSkipVerify=true
image: traefik:2.2.5
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /ping
port: 8100
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 2
name: traefik
ports:
- containerPort: 8100
name: admin
protocol: TCP
- containerPort: 80
name: web
protocol: TCP
- containerPort: 443
name: websecure
protocol: TCP
readinessProbe:
failureThreshold: 1
httpGet:
path: /ping
port: 8100
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 2
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: traefik
serviceAccountName: traefik
terminationGracePeriodSeconds: 60
اینجا موارد مهمی هست که باید بهش توجه داشته باشید.
- تمامی موارد در فضانام kube-system اعمال میشه
- برای استفاده از قابلیت جدید نسخه 2.2 که در بالا توضیح دادم ، گزینه های
providers.kubernetescrd
وproviders.kubernetesingress
باید فعال شوند - پورت 8100 را برای مواردی مانند API, Dashboard و HealthCheck تنظیم می کنیم
این فایل را با استفاده از دستور زیر ، اعمال کرده و صبر کنید تا Pod مربوطه ساخته شود :
kubectl create -f deployment.yml
Service
حالا برای دسترسی به Entrypoint ها ، داشبورد و موارد دیگه باید سرویسی برای Traefik تعریف کنیم. فایلی با نام service.yml
و محتوای زیر آماده کنید :
# ServiceAccount
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik
namespace: kube-system
# Service
---
apiVersion: v1
kind: Service
metadata:
labels:
app: traefik
release: traefik
name: traefik
namespace: kube-system
spec:
externalIPs:
- '<Cluster-IP>'
externalTrafficPolicy: Cluster
ports:
- name: web
nodePort: 31909
port: 80
protocol: TCP
targetPort: 80
- name: websecure
nodePort: 30584
port: 443
protocol: TCP
targetPort: 443
- name: admin
nodePort: 32316
port: 8100
protocol: TCP
targetPort: 8100
selector:
app: traefik
release: traefik
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer: {}
به این موارد توجه کنید :
- در قسمت
<Cluster-IP>
حتما آدرس آی پی کلاستر خودتون رو وارد کنید ( آدرس Manager/Master Node ) - به صورت پیش فرض تمامی پورت ها به صورت NodePort تنظیم شدن. این مورد برای محیط توسعه است و میتونید چنین روشی رو انجام ندید
- این سرویس به عنوان LoadBalander عمل می کنه
سرویس مورد نظر هم با استفاده از دستور زیر اعمل کنید :
kubectl create -f service.yml
دسترسی به داشبورد
حالا که همه چیز آماده است ، راه های مختلفی برای دسترسی به داشبورد اصلی Traefik و مشاهده وضعیت سیستم وجود داره. برای مثال میتونید از پورت تعریف شده در قسمت قبل استفاده کنیم. در این فایل پورت 32316
با نام admin مخصوص دسترسی به داشبورد قرار داده شده است که در این صورت با این آدرس میشه به داشبورد دسترسی داشت :
http://<Cluster-IP>:32316/dashboard
اما حالا که Traefik داریم استفاده از چنین روشی منطقی نیست. ما تمام این کار ها رو کردیم تا دسترسی به درون کوبرنتیز ساده تر باشه و از طریق یک دامنه همه چیز انجام بشه. پس به عنوان اولین سرویس ، از Traefik برای دسترسی به داشبورد خودش استفاده می کنیم.
تنظیم سرویس ها
برای اینکه دامنه های خودمون رو به سرویس مربوطه متصل کنیم فقط کافیه یک Ingress ساده و مختصر تعریف کنیم. برای مثال چنین فایلی رو در نظر بگیرید :
---
kind: Ingress
apiVersion: networking.k8s.io/v1beta1
metadata:
name: traefik
namespace: kube-system
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web, websecure
spec:
rules:
- host: traefik.k8s
http:
paths:
- path: /
backend:
serviceName: traefik
servicePort: 8100
در اینجا همانطور که قبلا هم گفته بودم ، بحث معرفی سرویس به Traefik از طریق یک annotation ساده انجام میشه :
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web, websecure
اینجاست که نقاط ورودی رو مشخص می کنیم و Traefik به صورت خودکار سرویس رو شناسایی می کنه. در ادامه مسلما نیاز به تعریف دامنه خودمون داریم که این کار در قسمت host
انجام میشه. اینجا من از دامنه traefik.k8s
استفاده کردم.
در ادامه و قسمت backend باید نام و پورت سرویس وارد بشه که ما در اینجا از مقادیر traefik
و 8100
استفاده می کنیم.
با اعمال چنین فایلی خیلی راحت اولین سرویس خودمون رو به Traefik معرفی می کنیم که درواقع داشبورد خودشه.
با مراجعه به آدرس http://traefik.k8s/dashboard
داشبورد ما آماده است و اگر به انتهای صفحه مراجعه کنید Provider های مربوطه رو میبینید :
در قسمت سرویس ها هم میتونید مشاهده کنید که سرویس ما به درستی شناسایی شده
حالا دیگه همه چیز آماده است و به راحتی میتونید از Traefik برای سرویس های بعدی خودتون استفاده کنید. با مراجعه به پست بعدی ، یاد میگیرید که چطوری یک سرویس آزمایشی برای اولین بار در Kubernetes مستقر کنید. البته از روشی که همینجا توضیح داده شد استفاده میشه ولی مباحث Load-Balancing و ترکیب با Replication هم مورد آزمایش قرار داده میشه :