Kubernetes Ingress
Kubernetes Ingress是路由規則的集合,這些規則控制外部用戶如何訪問Kubernetes集群中運行的服務。
在Kubernetes中,有三種方式可以使內部Pod公開訪問。
- NodePort:使用Kubernetes Pod的
NodePort
,將Pod內應用程序公開到每個節點上的端口上。 - Service LoadBalancer:使用Kubernetes Service,改功能會創建一個外部負載均衡器,使流量轉向集群中的Kubernetes Pod。
- Ingress Controller:
Node Port是在Kubernetes集群中每個節點(Node)上開放端口,Kubernetes直接將流量轉向集群中Pod。Kubernetes集群中使用NodePort,則需要編輯防火牆規則,但是NodePort是范圍在Kubernetes集群中默認設置的范圍為 30000–32767,最終導致流量端口暴露在非標准端口之上。
LoadBalancer一般應用於雲廠商提供的Kubernetes服務,如果自行在機器上部署Kubernetes集群,則需要自行配置LoadBalancer的實現,
Kubernetes Ingress,為Kubernetes中的抽象概念,實現為第三方代理實現,這種三方實現集合統稱為Ingress Controller。Ingress Controller負責引入外部流量並將流量處理並轉向對應的服務。
Kubernetes IngressController功能實現
上面只是說道,在Kubernetes集群中,如何將外部流量引入到Kubernetes集群服務中。
負載均衡
無論在Kubernetes集群中,無論采用什么方式進行流量引入,都需要在外部負載均衡完成,而后負載均衡將流量引入Kubernetes集群入口或內部中,
通常情況下,NodePort方式管理繁瑣,一般不用於生產環境。
服務的Ingress選擇
Kubernetes Ingress是選擇正確的方法來管理引入外部流量到服務內部。一般選擇也是具有多樣性的。
- Nginx Ingress Controller,Kubernetes默認推薦的Ingress,弊端①最終配置加載依賴
config reload
,②定制化開發較難,配置基本來源於config file。 - Envoy & traefik api網關,支持tcp/udp/grpc/ws等多協議,支持流量控制,可觀測性,多配置提供者。
- 雲廠商提供的Ingress。AWS ALB,GCP GLBG/GCE,Azure AGIC
Traefik介紹
traefik-現代反向代理,也可稱為現代邊緣路由;traefik原聲兼容主流集群,Kubernetes,Docker,AWS等。官方的定位traefik是一個讓開發人員將時間花費在系統研發與部署功能上,而非配置和維護。並且traefik官方也提供自己的服務網格解決方案
作為一個 modern edge router ,traefik擁有與envoy相似的特性
- 基於go語言研發,目的是為了簡化開發人員的配置和維護
- tcp/udp支持
- http L7支持
- GRPC支持
- 服務發現和動態配置
- front/ edge prory支持
- 可觀測性
- 流量管理
- ...
traefik 術語
要了解trafik,首先需要先了解一下 有關trafik中的一些術語。
- EntryPoints 入口點,是可以被下游客戶端連接的命名網絡位置,類似於envoy 的listener和nginx的listen
- services 服務,負載均衡,上游主機接收來自traefik的連接和請求並返回響應。 類似於nginx upstream envoy的clusters
- Providers 提供者,提供配置文件的后端,如file,kubernetes,consul,redis,etcd等,可使traefik自動更新
- routers 路由器,承上啟下,分析請求,將下游主機的請求處理轉入到services
- middlewares: 中間件,在將下游主機的請求轉入到services時進行的流量調整
在Kubernetes中使用traefik網關作為Ingress
Traefik於2019年9月發布2.0 GA版,增加了很多新特性,包括IngressRoute Kubernetes CRD,TCP,最新版增加UDP等。
安裝traefik
Traefik 支持兩種方式創建路由規則,一是Traefik 自定義 Kubernetes CRD
,還有一種是 Kubernetes Ingress
。
創建traefik使用的Kubernetes CRD 資源
traefik官網提供了創建時所需要的 yaml文件,這里僅需要使用官網提供的Definitions與RBAC即可。
在官網提供的yaml文件缺少 ServiceAccount,需要自行創建。
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: default
name: traefik-ingress-controller
創建控制器
官方文件中,暫未找到所需運行traefik的控制器,需要自己創建一個。
traefik配置一般分為靜態和動態配置,此處的靜態是指,大部分時間內,不改變的配置(如nginx.conf),動態配置指,經常情況下改變的配置(可以理解為 nginx中 virtual host的每個獨立配置文件)。
traefik提供配置的提供者也有很多種,此處使用命令行方式設置不長改變靜態配置,也可以使用配置文件方式進行配置提供。
apiVersion: v1
kind: Service
metadata:
name: traefik
spec:
selector:
app: traefik-ingress
type: NodePort
ports:
- name: web
port: 80
targetPort: 80
- name: ssl
port: 443
targetPort: 443
- name: dashboard
port: 8080
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: traefik-ingress-controller-deployment
labels:
app: traefik-ingress
spec:
replicas: 1
selector:
matchLabels:
app: traefik-ingress
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
template:
metadata:
name: traefik-ingress
labels:
app: traefik-ingress
spec:
serviceAccountName: traefik-ingress-controller
volumes:
- name: ssl
hostPath:
path: /etc/kubernetes/pki
type: DirectoryOrCreate
containers:
- image: traefik:v2.3.3
name: traefik-ingress-lb
imagePullPolicy: IfNotPresent
volumeMounts:
- name: ssl
mountPath: /usr/local/pki
ports:
- name: web
containerPort: 80
hostPort: 1880
- name: ssl
containerPort: 443
hostPort: 18443
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
args:
- --entrypoints.web.address=:80
- --entrypoints.ssl.address=:443
- --providers.kubernetescrd
- --providers.kubernetesingress
- --api=true
- --ping=true
- --api.dashboard=true
- --serverstransport.insecureskipverify=true
- --serverstransport.rootcas=/usr/local/pki/ca.crt
- --accesslog
livenessProbe:
httpGet:
path: /ping
port: 8080
failureThreshold: 3
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /ping
port: 8080
failureThreshold: 3
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
配置文件方式,僅需參考官網,把--agrs中的參數轉換為配置文件並引入到pod后。替換啟動參數
args:
- --configfile=/config/traefik.yaml
使用CRD配置Traefik的流量管理
官網提供的基於Kubernetes CRD方式配置不是很多,可以參考動態配置中Kubernetes CRD Resources小結。
基於traefik dashboard方式配置增加HTTP router
前面使用官方提供CRD文件注冊了Kubernetes CRD資源,所以traefik 中的資源類型,可作為kubernetes中資源使用。如 kubectl get Middleware
dashboard是traefik自己提供的服務所需的services為自己,traefik的entryPoints,當開啟--api.dashboard=true
會增加一個8080端口作為traefik dashboard使用。而 api@internal
是traefik自己提供的services資源。
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard-route
spec:
entryPoints:
- traefik
routes:
- match: Host(`10.0.0.5`)
kind: Rule
services:
- name: api@internal
port: 8080
kind: TraefikService
為Kubernetes dashboard增加HTTP路由
基於kubernetes crd作為提供者運行的traefik中,后端service可以是traefik的services也可以是kubernetes資源中的service。
基於kubernetes sevices
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: kubernetes-dashboard-route
namespace: kubernetes-dashboard
annotations:
traefik.ingress.kubernetes.io/ssl-redirect: "true"
spec:
entryPoints:
- ssl
tls:
secretName: k8s-ca
routes:
- match: PathPrefix(`/ui`)
kind: Rule
middlewares:
- name: strip-ui
services:
- name: kubernetes-dashboard # kubernetes中的service對應的名稱
kind: Service # kubernetes中的service
port: 443
namespace: kubernetes-dashboard # kubernetes中的service對應的名稱空間。
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: strip-ui
namespace: kubernetes-dashboard
spec:
stripPrefix:
prefixes:
- "/ui"
- "/ui/"
此處使用了TLS的,開啟了TLS,默認traefik是進行雙向認證的,而kubernetes的dashboard的證書的ca並不知道,在訪問時會出現Internal Server Error
,目前沒有找到有效的雙向認證方法,普遍使用的方法都是調過認證--serverstransport.insecureskipverify=true
reference
https://github.com/traefik/traefik/issues/6821
負載均衡
負載均衡使用到的是traefik的services部分。
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
name: LoadBalancer
spec:
weighted:
services:
- name: prod-v1.2
port: 443
weight: 1
kind: Service
- name: prod-v1
port: 443
weight: 2
kind: Service
---
流量鏡像
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
name: mirror1
spec:
mirroring:
name: s1
port: 80
mirrors:
- name: s3
percent: 20
port: 80
- name: mirror2
kind: TraefikService
percent: 20