當我們在Kubernetes部署的服務需要暴露給外部使用者使用時,有三種選擇:LoadBalancer,NodePort, Ingress。
LoadBalancer型別得結合各個Cloud Provider提供的LB來使用,如果需要暴露的service很多,需要很多LB以及公網IP,比較浪費cost。
NodePort 方式一個埠只能一個服務使用,根據埠劃分服務,可用埠範圍:30000~32767, 同樣如果在暴露的servicie很多的情況下會導致節點要開的埠越來越多,不好管理,平時測試可以用用。
Ingress是自kubernetes1.1版本後引入的資源型別,在這個資源中我們可以去設定我們的服務路由規則,但是要真正去實現識別這個 Ingress 並提供代理路由功能,還需要安裝一個對應的控制器Ingress controller才能實現。Ingress nginx controller 本質上就是kubernetes 部署的pod 裡面有一個 Nginx container,只不過它能根據 Ingress 資源的定義動態生成 Nginx 的組態檔,然後動態 Reload。可以理解成 Ingress controller是由Kubernetes管理的負載均衡器。
Ingress controller是以一種外掛的形式提供,有多種實現,有基於 Nginx 的,也有基於 HAProxy的,還有現在很流行的Envoy,詳見:https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/, 我後面文章也會介紹基於 Envoy的 Ingress controller。
本文使用Kubernetes 社群推出的 Ingress Controller: Ingress-nginx (github.com/kubernetes/ingress-nginx) 它是基於Nginx 的擴充套件版 OpenResty 及諸多第三方模組構建的,其基於 OpenResty 的 Lua 嵌入式程式設計能力,擴充套件了 Nginx 的功能,並基於 balancer_by_lua 模組實現了 Pod 變化的動態變更功能。
要注意區分另外一個名字相近由Nginx公司推出的Nginx ingress controller (github.com/nginxinc/kubernetes-ingress)。Nginx 官方版本提供其基於Go語言開發的 Ingress 控制器,並與 Nginx 整合分為 Nginx 開源版和 Nginx Plus 版,開源版僅基於 Nginx 的原始功能,不支援 Pod 變化的動態變更。Nginx Plus 版則提供了諸多完善的商業功能,其支援 Nginx 原生設定指令、JWT 驗證、Pod 變化的動態設定及主動健康檢查等功能。
安裝方式有多種,我這裡介紹使用Kustomize 安裝, Kustomize入門可以參考我這篇文章【雲原生之旅 - 6)不能錯過的一款 Kubernetes 應用編排管理神器 Kustomize】
k8s manifests 參考 my repo
根據需要修改自己所需,這裡的例子是為 atlantis namespace 下面的 atlantis serivce 設定一個Ingress
由於Ingress controller 和 Ingress 均安裝在dmz namespace, 和 atlantis 不在同一個namespace下面,我們需要為atlantis serivce 加了一個 ExternalName 型別的service 相當於別名。
這樣dmz namespace 下面 Ingress 就指向 -> ExternalName 型別的service -> 指向 atlantis ns 下面 atlantis svc。
(Optional)Ingress 和 atlantis 放在同一個namespace 下面,就不需要多一個 ExernalName service了。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: sre-ingress-resource annotations: nginx.ingress.kubernetes.io/proxy-connect-timeout: "300" nginx.ingress.kubernetes.io/proxy-send-timeout: "300" nginx.ingress.kubernetes.io/proxy-read-timeout: "300" nginx.ingress.kubernetes.io/proxy-body-size: 100m nginx.ingress.kubernetes.io/proxy-buffer-size: 512k nginx.ingress.kubernetes.io/client-body-buffer-size: 512k ingress.kubernetes.io/ssl-redirect: "true" ingress.kubernetes.io/force-ssl-redirect: "true" spec: ingressClassName: nginx rules: - host: atlantis-demo.wadexu.cloud http: paths: - path: / pathType: Prefix backend: service: name: atlantis-demo-ext-svc port: number: 8080 tls: - hosts: - atlantis-demo.wadexu.cloud secretName: wade-tls-secret
--- apiVersion: v1 kind: Service metadata: name: atlantis-demo-ext-svc spec: type: ExternalName externalName: atlantis.atlantis.svc.cluster.local ports: - name: http port: 8080 targetPort: 4141 protocol: TCP
build and apply
kustomize build ingress-nginx-public/sre-mgmt-dev/ > ~/deploy.yaml kubectl apply -f ~/deploy.yaml
因為用了 https ,所以需要加一個tls-secret
kubectl create secret -n dmz tls wade-tls-secret \ --key ./xxx.key \ --cert ./xxx.pem
同一個cluster 如果要安裝另一個ingress nginx controller,比如作為內部API閘道器,該怎麼實現呢?
為了避免多個ingress controller 以一種困惑的方式同時爭搶更新 ingress status欄位,需要使用IngressClasses 官方檔案
另外還要注意資源重名的情況,需要改name,否則後部署的Ingress controller 會覆蓋前者, 比如 ClusterRoleBinding
參考 my manifests 部署在app namespace的internal Ingress nginx 針對以上資源的修改。
如不瞭解 Kustomize build,請先參考入門檔案【雲原生之旅 - 6)不能錯過的一款 Kubernetes 應用編排管理神器 Kustomize】
apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: nginx spec: controller: k8s.io/internal-ingress-nginx
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: app commonLabels: app.kubernetes.io/name: internal-ingress-nginx app.kubernetes.io/instance: internal-ingress-nginx resources: - ../../base patchesStrategicMerge: - ingress-class-patch.yaml patches: - target: kind: IngressClass name: nginx patch: |- - op: replace path: /metadata/name value: internal-nginx - target: kind: Deployment name: ingress-nginx-controller patch: |- - op: replace path: /metadata/name value: internal-ingress-nginx-controller - op: replace path: /spec/template/spec/containers/0/args/3 value: "--controller-class=k8s.io/internal-ingress-nginx" - op: replace path: /spec/template/spec/containers/0/args/4 value: "--ingress-class=internal-nginx" - target: kind: ClusterRoleBinding name: ingress-nginx patch: |- - op: replace path: /metadata/name value: internal-ingress-nginx - target: kind: ClusterRoleBinding name: ingress-nginx-admission patch: |- - op: replace path: /metadata/name value: internal-ingress-nginx-admission - target: kind: ValidatingWebhookConfiguration name: ingress-nginx-admission patch: |- - op: replace path: /metadata/name value: internal-ingress-nginx-admission
一般來說,Ingress nginx 足以應付大部分場景了,除非你想用到一些高階功能,比如流量管理,熔斷等等。那麼我會推薦 後起之秀基於Enovy的那些Ingress controller,比如Ambassador 現在叫Emissary, CNCF的incubating 專案。
感謝閱讀,如果您覺得本文的內容對您的學習有所幫助,您可以打賞和推薦,您的鼓勵是我創作的動力。