1.什么是ingress?
k8s 對外暴露服務(service)主要有兩種方式:NotePort, LoadBalance;
此外externalIP也可以使各類service對外提供服務,但是當集群服務很多的時候,NodePort方式最大的缺點是會占用很多集群機器的端口;
LB方式最大的缺點則是每個service一個LB又有點浪費和麻煩,並且需要k8s之外的支持;
而ingress則只需要一個NodePort或者一個LB就可以滿足所有service對外服務的需求。
2.ingress介紹
#k8s內部並沒有自帶代理程序完成這種規則轉發。
ingress-controller 是一個代理服務器,將ingress的規則能真正實現的方式。
常用的有Nginx-Ingress-Controller,Traefik-Ingress-Controller, Haproxy-Ingress-Controller。
要理解ingress,需要區分兩個概念,ingress和ingress-controller:
#ingress對象:
指的是k8s中的一個api對象,一般用yaml配置。作用是定義請求如何轉發到service的規則,可以理解為配置模板。
#ingress-controller:
具體實現反向代理及負載均衡的程序,對ingress定義的規則進行解析,根據配置的規則來實現請求轉發。
簡單來說,ingress-controller才是負責具體轉發的組件,通過各種方式將它暴露在集群入口,外部對集群的請求流量會先到ingress-controller,而ingress對象是用來告訴ingress-controller該如何轉發請求,比如哪些域名哪些path要轉發到哪些服務等等。
3.對比nginx 和 traefik
#nginx:
使用nginx作為前端負載均衡,通過ingress controller不斷的和kubernetes api交互,實時獲取后端service,pod等的變化,然后動態更新nginx配置,並刷新使配置生效,達到服務發現的目的。
#traefik:
traefik本身設計的就能夠實時跟kubernetes api交互,感知后端service,pod等的變化,自動更新配置並重載。
相對來說traefik更快速方便,同時支持更多的特性,使反向代理,負載均衡更直接更高效。可參考下圖功能對比:
4.在 kubernetes 集群部署 Traefik-ingress
#traefik簡介
https://traefik.cn/
https://docs.traefik.io/
Traefik 是一個為了讓部署微服務更加便捷而誕生的現代HTTP反向代理、負載均衡工具。 它支持多種后台 (Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, Zookeeper, BoltDB, Rest API, file…) 來自動化、動態的應用它的配置文件設置。
#kubernetes部署
traefik有多種部署方式,可以以deploymen/daemonset方式手動部署,也可以使用helm來快速部署。
#helm部署參考:https://github.com/containous/traefik-helm-chart
#下面使用daemonset方式部署,部署版本:traefik v2.1.2
#mkdir /root/k8s/ingress && cd /root/k8s/ingress
(1)創建 CRD 資源
參考:https://docs.traefik.io/routing/providers/kubernetes-crd/
展開Configuration Examples有相關示例yaml。
在 traefik v2.1 版本后,開始使用 CRD(Custom Resource Definition)來完成路由配置等,所以需要提前創建 CRD 資源。
#cat traefik-crd.yaml
## IngressRoute
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressroutes.traefik.containo.us
spec:
scope: Namespaced
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRoute
plural: ingressroutes
singular: ingressroute
---
## IngressRouteTCP
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressroutetcps.traefik.containo.us
spec:
scope: Namespaced
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRouteTCP
plural: ingressroutetcps
singular: ingressroutetcp
---
## Middleware
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: middlewares.traefik.containo.us
spec:
scope: Namespaced
group: traefik.containo.us
version: v1alpha1
names:
kind: Middleware
plural: middlewares
singular: middleware
---
## TLSOption
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsoptions.traefik.containo.us
spec:
scope: Namespaced
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSOption
plural: tlsoptions
singular: tlsoption
---
## TraefikService
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: traefikservices.traefik.containo.us
spec:
scope: Namespaced
group: traefik.containo.us
version: v1alpha1
names:
kind: TraefikService
plural: traefikservices
singular: traefikservice
#kubectl apply -f traefik-crd.yaml
(2)創建RBAC資源
參考:https://docs.traefik.io/routing/providers/kubernetes-crd/
Kubernetes 在 1.6 版本中引入了基於角色的訪問控制(RBAC)策略,方便對 Kubernetes 資源和 API 進行細粒度控制。Traefik 需要一定的權限,所以這里提前創建好 Traefik ServiceAccount 並分配一定的權限。
#cat traefik-rbac.yaml
## ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: kube-system
name: traefik-ingress-controller
---
## ClusterRole
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"]
verbs: ["get","list","watch"]
- apiGroups: ["traefik.containo.us"]
resources: ["ingressroutes"]
verbs: ["get","list","watch"]
- apiGroups: ["traefik.containo.us"]
resources: ["ingressroutetcps"]
verbs: ["get","list","watch"]
- apiGroups: ["traefik.containo.us"]
resources: ["tlsoptions"]
verbs: ["get","list","watch"]
- apiGroups: ["traefik.containo.us"]
resources: ["traefikservices"]
verbs: ["get","list","watch"]
---
## ClusterRoleBinding
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: kube-system
# kubectl apply -f traefik-rbac.yaml -n kube-system
(3)創建configmap
由於 Traefik 配置很多,通過 CLI 定義不是很方便,一般選擇將其配置選項放到配置文件中,然后存入 ConfigMap,將其掛入 traefik 中。
#cat traefik-config.yaml :
kind: ConfigMap
apiVersion: v1
metadata:
name: traefik-config
data:
traefik.yaml: |-
ping: "" ## 啟用 Ping
serversTransport:
insecureSkipVerify: true ## Traefik 忽略驗證代理服務的 TLS 證書
api:
insecure: true ## 允許 HTTP 方式訪問 API
dashboard: true ## 啟用 Dashboard
debug: false ## 啟用 Debug 調試模式
metrics:
prometheus: "" ## 配置 Prometheus 監控指標數據,並使用默認配置
entryPoints:
web:
address: ":80" ## 配置 80 端口,並設置入口名稱為 web
websecure:
address: ":443" ## 配置 443 端口,並設置入口名稱為 websecure
providers:
kubernetesCRD: "" ## 啟用 Kubernetes CRD 方式來配置路由規則
kubernetesIngress: "" ## 啟動 Kubernetes Ingress 方式來配置路由規則
log:
filePath: "" ## 設置調試日志文件存儲路徑,如果為空則輸出到控制台
level: error ## 設置調試日志級別
format: json ## 設置調試日志格式
accessLog:
filePath: "" ## 設置訪問日志文件存儲路徑,如果為空則輸出到控制台
format: json ## 設置訪問調試日志格式
bufferingSize: 0 ## 設置訪問日志緩存行數
filters:
#statusCodes: ["200"] ## 設置只保留指定狀態碼范圍內的訪問日志
retryAttempts: true ## 設置代理訪問重試失敗時,保留訪問日志
minDuration: 20 ## 設置保留請求時間超過指定持續時間的訪問日志
fields: ## 設置訪問日志中的字段是否保留(keep 保留、drop 不保留)
defaultMode: keep ## 設置默認保留訪問日志字段
names: ## 針對訪問日志特別字段特別配置保留模式
ClientUsername: drop
headers: ## 設置 Header 中字段是否保留
defaultMode: keep ## 設置默認保留 Header 中字段
names: ## 針對 Header 中特別字段特別配置保留模式
User-Agent: redact
Authorization: drop
Content-Type: keep
#創建Traefik ConfigMap 資源
# kubectl apply -f traefik-config.yaml -n kube-system
(4)節點設置label標簽
由於是 Kubernetes DeamonSet 這種方式部署 Traefik,所以需要提前給節點設置 Label,這樣當程序部署時 Pod 會自動調度到設置 Label 的節點上。
#節點設置 Label 標簽
#kubectl label nodes master.k8s.com IngressProxy=true
#kubectl label nodes node.k8s.com IngressProxy=true
#查看節點是否設置 Label 成功
#kubectl get nodes --show-labels
#如果想刪除標簽,可以使用
#kubectl label nodes node.k8s.com IngressProxy-
(5)部署traefik
使用 DaemonSet 方式部署,便於在多服務器間擴展,用 hostport 方式占用服務器 80、443 端口,方便流量進入。
#創建 traefik 部署文件 traefik-deploy.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
---
apiVersion: v1
kind: Service
metadata:
name: traefik
spec:
ports:
- name: web
port: 80
- name: websecure
port: 443
- name: admin
port: 8080
selector:
app: traefik
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: traefik-ingress-controller
labels:
app: traefik
spec:
selector:
matchLabels:
app: traefik
template:
metadata:
name: traefik
labels:
app: traefik
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 1
containers:
- image: traefik:v2.1.2
name: traefik-ingress-lb
ports:
- name: web
containerPort: 80
hostPort: 80 ## 將容器端口綁定所在服務器的 80 端口
- name: websecure
containerPort: 443
hostPort: 443 ## 將容器端口綁定所在服務器的 443 端口
- name: admin
containerPort: 8080 ## Traefik Dashboard 端口
resources:
limits:
cpu: 2000m
memory: 1024Mi
requests:
cpu: 1000m
memory: 1024Mi
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
args:
- --configfile=/config/traefik.yaml
volumeMounts:
- mountPath: "/config"
name: "config"
volumes:
- name: config
configMap:
name: traefik-config
tolerations: ## 設置容忍所有污點,防止節點被設置污點
- operator: "Exists"
nodeSelector: ## 設置node篩選器,在特定label的節點上啟動
IngressProxy: "true"
#部署 Traefik
#kubectl apply -f traefik-deploy.yaml -n kube-system
#到此 Traefik v2.1 應用已經部署完成。
Traefik 路由規則配置
(1)、配置 HTTP 路由規則 (Traefik Dashboard 為例)
Traefik 應用已經部署完成,但是想讓外部訪問 Kubernetes 內部服務,還需要配置路由規則,這里開啟了 Traefik Dashboard 配置,所以首先配置 Traefik Dashboard 看板的路由規則,使外部能夠訪問 Traefik Dashboard。
創建 Traefik Dashboard 路由規則文件 traefik-dashboard-route.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard-route
spec:
entryPoints:
- web
routes:
- match: Host(`traefik.k8s.com`)
kind: Rule
services:
- name: traefik
port: 8080
創建 Traefik Dashboard 路由規則對象
# kubectl apply -f traefik-dashboard-route.yaml -n kube-system
接下來配置 Hosts,客戶端想通過域名訪問服務,必須要進行 DNS 解析,由於這里沒有 DNS 服務器進行域名解析,所以修改 hosts 文件將 Traefik 指定節點的 IP 和自定義 host 綁定。打開電腦的 Hosts 配置文件,往其加入下面配置:
192.168.25.66 traefik.k8s.com
配置完成后,打開瀏覽器輸入地址:http://traefik.k8s.com打開 Traefik Dashboard。
(2)、配置 HTTPS 路由規則(Kubernetes Dashboard 為例)
這里我們創建 Kubernetes 的 Dashboard 看板,它是 Https 協議方式,由於它是需要使用 Https 請求,所以我們配置基於 Https 的路由規則並指定證書。
創建證書文件
# 創建自簽名證書
# openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=master.k8s.com"
# 將證書存儲到 Kubernetes Secret 中
# kubectl create secret generic cloud-mydlq-tls --from-file=tls.crt --from-file=tls.key -n kubernetes-dashboard
創建 Traefik Dashboard 路由規則文件 kubernetes-dashboard.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: kubernetes-dashboard-route
spec:
entryPoints:
- websecure
tls:
secretName: cloud-mydlq-tls
routes:
- match: Host(`master.k8s.com`)
kind: Rule
services:
- name: kubernetes-dashboard
port: 443
創建 Kubernetes Dashboard 路由規則對象
# kubectl apply -f kubernetes-dashboard.yaml -n kubernetes-dashboard
跟上面一樣,配置 Hosts 文件
192.168.25.65 master.k8s.com
配置完成后,打開瀏覽器輸入地址:https://master.k8s.com 打開 Dashboard Dashboard。