為什么需要ingress
一組pod 對外暴露服務通過service 有兩種方式一個是nodeport 另一個是loadbalancer。但是它們都是有弊端。
nodeport 必須知道節點服務器的地址和端口,如果此節點掛了那么就需要更換其他節點地址,而且每個服務都會對應一個node上的端口配置維護麻煩。而且odeport 實現的是四層轉發
loadbalancer 每個 LoadBalancer 服務都需要自己的負載均衡器, 以及獨有的公有 IP 地址,一個loadbalancer 只對應一組pod , 而 Ingress 只需要一個公網 IP 就能為許多服務提供訪問。使得所有的Pod 都具有統一的入口
ingress控制器和ingress資源
ingress 控制器實際上就是運行在kube-system 空間的一組pod ,可以簡單把它理解為一個負責均衡器例如nginx ,ingress 資源可以理解為配置在nginx 上面的conf.d下面的配置文件,定義的是基於后端一個服務的轉發規則。
ingress 控制器有很多種,其中 NGINX Ingress Controller 是比較常用的一種,pod 里面運行的就是nginx ,所有的ingress 資源的創建最后都會在此控制器對應的pod 里面生成對應的nginx 配置,另外整個控制器的配置是通過一個configmap實現的,可以查看一下與控制器相同命名空間內是否有一個ingress 命名的configmap,這是控制器的全局配置文件。
Ingress 實現原理
簡單理解為在service 基礎上加入了一個負載代理。
實現原理
分為ingress 控制器和ingress 資源。ingress是一個負載代理規則,它是通過ingress-controller 實現的。它通過統一的端口(80/443)可實現4/7層負載,為每個服務創建一個域名,ingress 通過域名來識別訪問的服務,所有的域名配置解析到這一個唯一的ingress 的IP ,實際與pod 通訊還是會經過service。它的底層實際就是nginx或者其他的負載軟件,每一個服務做代理的過程即使為這個服務的pod 創建一個upstream和proxy.
客戶端訪問流程圖
Igress 的創建

$ kubectl get po --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE ... ... kube-system nginx-ingress-controller-gdts 1/1 Running 0 18m
如果沒有,需要先創建ingress 控制器,再創建ingress 規則
創建ingress 控制器
通過編寫yaml 文件或者命令方式,在yaml 中可以定義對外提供的統一端口。
kubectl apply -f ingress.yaml
kubectl get pods -n ingress-nginx #查看創建的ingress,必須在它自己的命名空間ingress-nginx 中查看
創建Ingress 規則
vi ingress.yaml

apiVersion: extensions/vlbetal kind: Ingress metadata: name: kubia spec: rules: - host: kubia.example.com #將此域名映射為你的服務 http: paths - path: / #域名后的路徑 backend: serviceName: kubia-asdf #對應的是service 名稱 servicePort:80 #service 對外端口
獲取ingress 地址
kubectl get ingresses -n kzf
可以同一個ingress 暴露多個服務
類比nginx 同一個server name 下面多個location 轉發不同的后端服務

apiVersion: extensions/vlbetal kind: Ingress metadata: name: kubia spec: rules: - host: kubia.example.com #對於http://kubia.example.com/ 的訪問轉發到kubia-asdf服務 http: paths - path: / #域名后的路徑 backend: serviceName: kubia-asdf #對應的是service 名稱 servicePort:80 - path: /foo #對於http://kubia.example.com/foo 訪問轉發到 bar 服務 backend: serviceName : bar servicePort: 80
dns解析
把任意一個 ingress controler所在的pod 的ip 地址解析為定義的應用程序域名,訪問域名后請求到底controller,控制器通過規則和域名找到應用程序實現負載轉發。
配置 Ingress 處理 TLS 傳輸
kubectl create secret tls tls-secret --cert=tls.cert --key=tls.key #私鑰和證書現在存儲在名為 tls-key 的Secret 中
3、配置ingress

apiVersion: extensions/vlbetal kind: Ingress metadata: name: kubia spec: tls: #這個屬性下包含了所有的tls 配置 - hosts: - kubia.example.com #將接收所有來自kubia.example.com 的TLS 連接 secretName: tls secret rules: - host: kubia.example.com http: paths - path: / backend: serviceName: kubia-asdf servicePort:80
ingress-nginx 配置rewrite

apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: /kzf/$1$2 # nginx.ingress.kubernetes.io/rewrite-target: / name: {{ .Values.projectName }} namespace: {{ .Values.namespace }} spec: rules: - host: pay-server.kzf.k8s.asdf.com http: paths: - path: /jtlq/kzf(/|$)(.*) #訪問的ingress的uri ,此處匹配三種情況/jtlq/kzf或/jtlq/kzf/或/jtlq/kzf/... backend: serviceName: pay-server servicePort: 8090 解釋: 訪問 http://pay-server.kzf.k8s.asdf.com.k8s.asdf.com/jtlq/kzf(/|$)(.*) 轉發到后端service pay-server 的8090 端口並且uri 變為/kzf/$1$2, 替換了/jtlq/kzf(/|$)(.*) 注意:路徑如果寫成這樣 - path: /jtlq/kzf/(.*) 那么直匹配 /jtlq/kzf/或/jtlq/kzf/...這兩種情況。
ingress 控制器 配置映射片段
nginx ingress 控制器的使用文檔詳見 https://kubernetes.github.io/ingress-nginx/
如果你想在nginx-controller-pod中生成的nginx.conf文件中添加一些自定義配置,例如配置請求頭,gzip 等等,可以通過 snippet,一共分為 http-snippet,server-snippet和location-snippet 等,例如
server-snippet表示會把配置映射到nginx.conf 里面的server 區域,默認情況gzip 是啟動的,如果想要配置某個ingress 資源為關閉,配置如下
apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/server-snippet: | gzip off;
關於gzip 壓縮的驗證,可以通過瀏覽器訪問url ,查看的是響應頭的 Accept-Encoding ,如果沒有此字段表示gzip 關閉了。