前言
在Kubernetes中,服務和Pod的IP地址僅可以在集羣網絡內部使用,對於集羣外的應用是不可見的。爲了使外部的應用能夠訪問集羣內的服務,在Kubernetes 目前 提供了以下幾種方案:
- NodePort
- LoadBalancer
- Ingress
這三種方案中,考慮到NodePort
是直接開放外部端口,這樣需要管理所有服務開放的端口,跟我們原本使用k8s的初衷略有違背,我們初衷是希望對外是服務訪問,對內可以不針對每個服務所在的服務器以及端口進行管理,在降低運維壓力同時,實現負載均衡
,因此一般不選擇這種方案實現對外暴露服務,而LoadBalancer
需要雲端服務支持,就是一般是需要付費
,考慮成本也是不在參考範圍裏面的,因此最後的Ingress
這根稻草,在安全與成本
的方向的考慮,滿足了大部分人的需求,基礎部署參考:helm3.0部署nginx-ingress.
Ingress 簡介
在kubernetes集羣中,我們知道service和pod的ip僅在集羣內部訪問。如果外部應用要訪問集羣內的服務,集羣外部的請求需要通過負載均衡轉發到service在Node上暴露的NodePort上,然後再由kube-proxy組件將其轉發給相關的pod。 而Ingress就是爲進入集羣的請求提供路由規則的集合,通俗點就是
提供外部訪問集羣的入口
,將外部的HTTP或者HTTPS請求轉發到集羣內部service
上。
Ingress訪問原理
Ingress代理的並不是pod的service,而是pod,之所以在配置的時候是配置的service,是爲了通過service來獲取所有pod的信息。
訪問原理如下:
Ingress實現生產環境服務暴露方案
Ingress通常使用http://domain/path
的方式暴露服務,對於生產環境,是已經配置了一層Nginx代理,通過80/443
端口對外開放應用入口
具體訪問原理如下:
當服務部署到k8s之後,能不能用原本的方案呢?
方案一:使用Nginx-Ingress實現反向代理,替換原來的Nginx
具體實現邏輯如下:
這個需要一個前提條件是由於是生產環境,域名是必須能夠公網IP進行DNS解析,也就是Nginx-Ingress所在的服務器必須進行DNS解析纔可以實現直接對外暴露服務,但是nginx-ingress是通過k8s部署,在正常情況下,我們都不會指定節點去部署,因爲指定節點部署就可能會出現單點故障問題,且不能基於k8s進行動態分配服務器,也就是DNS解析這個除非全解析,不然不靠譜,鑑於時間問題以及風險問題,這種模式不考慮。
方案二:使用Nginx-Ingress實現反向代理,上游對接原有的Nginx服務
具體實現邏輯如下:
從圖上面可以看到,相當於加了一層代理,只需要改變原有生成環境的反向代理服務地址就能把服務訪問遷移到k8s的服務上面。這是一個相對比較合理跟成本較低的方案,在Nginx-Ingress這一層還是基於Ingress的規則統一開放k8s上面的應用服務,Nginx這一層反向代理Nginx-Ingress即可。
具體實現
開放nginx-ingress 80/443端口
按照我們正常使用,nginx-ingress所在服務器集羣式不開通外網,但是爲了方便使用,我們通過externalIPs
將服務使用固定IP的方式對內網開放,其他服務/應用可以通過http/https://externalIPs/xxx
的方式即可訪問nginx-ingress.
具體配置如下:
spec:
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
nodePort: 31314
- name: https
protocol: TCP
port: 443
targetPort: 443
nodePort: 30491
selector:
app: nginx-ingress
component: controller
release: nginx-ingress
clusterIP: 10.100.221.205
type: LoadBalancer
externalIPs:
- 192.168.1.123
sessionAffinity: None
externalTrafficPolicy: Cluster
Ingress規則編寫
編寫一個Ingress規則,將服務通過ingress開放出去
注意這裏跟普通的ingress規則差異的點在於spec.rules.host
這個選項,一般我們這個選項會填寫我們的域名如www.test.com
,但是這裏我們採用方案二
,因此不需要填寫這個選項,按照以下的配置,訪問test服務的時候,只需要通過我們上一步填寫的IP即可訪問,具體路徑:http://192.168.1.123/test
,這樣寫就可以訪問test服務,實現nginx-ingress通過統一IP訪問服務
。我們把上述的服務地址配置到上游的nginx代理即可。
spec:
rules:
- http:
paths:
- path: /test
backend:
serviceName: test
servicePort: 8080
解決ingress 308問題
如果只有上面的操作,訪問http://domain/path
的時候,頁面會跳轉不信任鏈接
,,報錯308
原因是當我們的ingress規則不填寫host
的時候,ingress-nginx默認要求https
,所以這時會遇到訪問總是308跳轉的問題。
針對這個問題,只需要修改nginx-ingress的參數如下:
打卡nginx-ingress的configmap:nginx-ingress-controller
設置 ssl-redirect: 'false'
data:
compute-full-forwarded-for: 'true'
enable-vts-status: 'false'
forwarded-for-header: X-Forwarded-For
ssl-redirect: 'false'
use-forwarded-headers: 'true'
然後就可以完成無縫對接生產上游~~~