[筆記] Kubernetes Ingress
主要目的是將外部流量設置level7 反向代理至kubernetes cluster內部的service, 並將流量導向到對應的pod
這部份會有兩個組件, ingress 與 ingress controller
- Ingress: 可以理解成kubernetes反向代理的設定檔, 用來定義流量如何反向代理至特定pod, 用傳統web server比喻, 它就像nginx中/etc/nginx/conf.d/下的設定檔
- Ingress controller: 這邊可以理解成 真正實際實現反向代理的元件, 外部流量近來後, 會把相對應的流量導向目標pod, 用傳統web server比喻, 它就像nginx service
兩者關係概念, 就是當你創建一個ingress (反向代理規則), ingress controller就會發現該rule, 並將該rule轉換成設定檔, 並且reload 但兩者實際上都是獨立的元件, 設定檔並無相依關係, 不會互相影響
graph LR
client --> A["Ingress Controller"] --> Service --> Pod
A <-->|Add reverse proxy rule| B["Ingress"]
Ingress Controller
- 實際上可以理解為kubernetes的web server, 但只負責處理反向代理的部份, 並且將流量導向到對應的pod上
- 工作方式就是監聽流量進行反向代理至Pod, 並將新發現的ingress 轉換成反向代理的rule 套用, 並reload
- 非kubernetes內建的元件, 需要自行佈署
- cluster 層級, 無關namespace
- 有不同類型的ingress controller (nginx,haproxy,apache…)
- port 8443 ingress-nginx admission controller
- port 80 / 443
- 分為 雲端load balance 與 baremetal本地 佈署
這邊舉例 controller以 nginx 類型為主
類型
- cloud provider: 這部份是結合cloud provider提供的服務, 簡單說是把雲端上的load balancer抽象化成 service(load-balancer), 該service就是 ingress controller的入口
graph LR
client ---> A["cloud load-balancer"]
A --- B["Service(load-balancer)"] ---> Pod
- baremetal
graph LR
client ---> A["?"]
A --- B["Service"] ---> Pod
- Metallb: 可做為on-premise ingress controller的 load-balancer service 解決方案
- layer2: 通過ARP來宣告IP, 用於較簡易架構的服務
- BGP: 用於大規模跨網段佈署, 路由器需支援BGP, 常用於異地數據中心, 混合雲環境
- NodePort: 將NodePort Service 綁定特定ingress rule,
- Via the host network: 類似一般nginx用法, 直接代理至 service
Config簡介
controller需自行佈署, 這邊簡單解析一下佈署的config
這邊會分成
- ingress controller: 這邊處理是處理ingress的設定, 並且產生相對應的設定檔,
- ingress-nginx-admission: admission-webhook, 是kubernetes的機制, 主要是ApiServer準備將資源持久話至etcd前, 用來驗證ingress的設定是否合法 (e.g. annotations設定是否有缺少, 設定檔與資源的一致性… )
設定檔由多個部分組成,這邊用nginx-ingress-controller為例
- Namespace: 主要用來隔離環境, 用來放置ingress controller的元件
- ServiceAccount: 為ingress controller創建一個service account, 確保身份驗證
- ingress-nginx: 用於ingress controller的身份驗證
- ingress-nginx-admission: 用於ingress controller的webhook身份驗證
- configmap: 存儲基本設定, 可以讓 ingress controller讀取
- ClusterRole:
- ingress-nginx: 確保ingress controller有權限操作cluster的元件
- ingress-nginx-admission: 確保Admission Webhook有權限操作cluster的元件
- ClusterRoleBinding: 榜定clusterRole至對應的service account
- Deployment: 定義環境變數,probe,port,而內部controller pod主要負責動態產生nginx的反向代理設定
- Service:
- ingress-nginx-controller: 暴露ingress controller的http ,https port
- ingress-nginx-admission: 暴露webhook port
- Job:
- ingress-nginx-admission-create: 創建webhook 憑證
- ingress-nginx-admission-patch: 更新webhook 憑證
- ingressClass: 定義該該ingress的名稱 與ingress的類型是由哪個ingress controller處理 , 如為 controller: k8s.io/ingress-nginx, 此外若要啟動多個controller,也是metadata的name 可將controller做區分
Ingress
- kubernetes的反向代理設定檔的抽象化物件, 用來定義流量如何反向代理至特定pod
- 無論使用哪種ingress controller, ingress設定檔都 相同, 並且不會因為ingress controller的不同而有所改變
- ingressClass 是標記該controller是哪種web server type, controller的pod 是藉由–arg 相依
- Ingress 的rule 是藉由 ingressClass 標記 注入rule至 controller
config, 主要是由 test2.com
可被導向 名為 info
service後的pod的8010
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
namespace: dev
spec:
ingressClassName: nginx ## 這邊是表示使用哪個ingress controller
rules:
- host: "test2.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: info
port:
number: 8010
ingress controller config宣告 ingressClassName
位置
spec:
containers:
- args:
- /nginx-ingress-controller
- --election-id=ingress-nginx-leader
- --controller-class=k8s.io/ingress-nginx
- --ingress-class=nginx <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 這個地方
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
- --validating-webhook=:8443
實際測試
共用config
demo app port 8010, 由clusterIP service, satefulset 組成
該app 為 api, 會回傳創建時產生的uuid
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: info1
namespace: dev
spec:
serviceName: "info"
replicas: 1
selector:
matchLabels:
app: info1
template:
metadata:
labels:
app: info1
spec:
containers:
- name: info
image: y40103/info:2.0
ports:
- containerPort: 8010
---
apiVersion: v1
kind: Service
metadata:
name: info1
namespace: dev
spec:
ports:
- protocol: TCP
port: 80
targetPort: 8010
selector:
app: info1
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: info
namespace: dev
spec:
serviceName: "info"
replicas: 1
selector:
matchLabels:
app: info2
template:
metadata:
labels:
app: info2
spec:
containers:
- name: info
image: y40103/info:2.0
ports:
- containerPort: 8010
---
apiVersion: v1
kind: Service
metadata:
name: info2
namespace: dev
spec:
ports:
- protocol: TCP
port: 80
targetPort: 8010
selector:
app: info2
ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
namespace: dev
spec:
ingressClassName: nginx # IngressController config中定義的 ingressClass 名稱
rules:
- host: "test2.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: info1
port:
number: 8010
- host: "test3.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: info2
port:
number: 8010
Cloud provider
kubectl apply -f kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.1/deploy/static/provider/cloud/deploy.yaml
實作待補充,
NodePort ingress
簡單說就是該ingress controller組件中的service為 NodePort, 藉由該service 可藉由訪問代理 根據hostname 導向其他service
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.1/deploy/static/provider/baremetal/deploy.yaml
# 佈署controller
確認 controller service 為 NodePort
kubectl get svc -n ingress-nginx
#NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
#ingress-nginx-controller NodePort 10.96.40.93 <none> 80:30436/TCP,443:30556/TCP 6m44s
#ingress-nginx-controller-admission ClusterIP 10.96.247.29 <none> 443/TCP 6m44s
curl test2.com:30436
#ID: cdb25b50-1688-41c6-96c9-a18d3c9d4086
#
curl test3.com:30436
#ID: 9b6aec0d-09b1-4463-96c1-c701820e08bd
#