k8s Ingress 理解和部署


前言

在跟隨書籍學習 kubernetes 的過程中,我一直在思考如何從外部訪問集群的服務,誠然到了 Ingress 的內容,才理解 kubernetes 對外提供內部服務的方式。

Ingress 與 ingress-controller

Ingress 是 kubernetes 的一種資源對象,該對象允許外部訪問 kubernetes 服務, 通過創建規則集合來配置訪問權限,這些規則定義了哪些入站連接可以訪問哪些服務。
ingress-controller 是實現反向代理和負載均衡的程序,其功能是為了使 ingress 工作,通過解析 ingress 的規則來實現請求轉發。集群內可以有多個 ingress-controller。

Ingress 部署

Ingress 部署的方式有多種,一般情況下需要考慮場景才選擇部署方式。以下是筆者摘抄的常見部署方式:
Deployment + LoadBalancer

如果要把 ingress 部署在公有雲,那用這種方式比較合適。用 Deployment 部署 ingress-controller,創建一個 type 為 LoadBalancer 的 service 關聯這組 pod。大部分公有雲,都會為 LoadBalancer 的 service 自動創建一個負載均衡器,通常還綁定了公網地址。只要把域名解析指向該地址,就實現了集群服務的對外暴露。

Deployment + NodePort

同樣用 deployment 模式部署 ingress-controller,並創建對應的服務,但是 type 為 NodePort。這樣,ingress 就會暴露在集群節點 ip 的特定端口上。由於 nodeport 暴露的端口是隨機端口,一般會在前面再搭建一套負載均衡器來轉發請求。該方式一般用於宿主機是相對固定的環境 ip 地址不變的場景。NodePort 方式暴露 ingress 雖然簡單方便,但是 NodePort 多了一層 NAT,在請求量級很大時可能對性能會有一定影響。

DaemonSet + HostNetwork + nodeSelector

用 DaemonSet 結合 nodeselector 來部署 ingress-controller 到特定的 node 上,然后使用 HostNetwork 直接把該 pod 與宿主機 node 的網絡打通,直接使用宿主機的 80/433 端口就能訪問服務。這時,ingress-controller 所在的 node 機器就很類似傳統架構的邊緣節點,比如機房入口的 nginx 服務器。該方式整個請求鏈路最簡單,性能相對 NodePort 模式更好。缺點是由於直接利用宿主機節點的網絡和端口,一個 node 只能部署一個 ingress-controller pod。比較適合大並發的生產環境使用。

在本次實驗中也根據相關教程使用 DaemonSet+HostNetwork+nodeSelector 的方式部署。

1、部署 ingress-controller

為需要部署為邊緣節點的 node 打上 labe:

$ kubectl  label   node k8sn91 isIngress="true"

在官方 yaml 配置文件中,相關資源的創建已經包含在內,但是我們需要使用 DaemonSet 的方式部署,就需要修改一小部分內容。下載官方 yaml:

$ wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml

修改 Deployment 部分的配置:

……
apiVersion: apps/v1
# kind: Deployment
# 修改成 DaemonSet
kind: DaemonSet
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
#  注釋掉 replicas
#  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
      annotations:
        prometheus.io/port: "10254"
        prometheus.io/scrape: "true"
    spec:
      # wait up to five minutes for the drain of connections
      terminationGracePeriodSeconds: 300
      serviceAccountName: nginx-ingress-serviceaccount
      # 選擇打上 isIngress 標簽的 node
      nodeSelector:
        isIngress: "true"
      # 暴露服務
      hostNetwork: true
      containers:
        - name: nginx-ingress-controller
          image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1
……

部署 nginx-ingress-controller:

$ kubectl apply -f mandatory.yaml

查看:

$ kubectl get ds -n ingress-nginx
NAME                       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR    AGE
nginx-ingress-controller   1         1         1       1            1           isIngress=true   10m
$ kubectl get pods -n ingress-nginx
NAME                             READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-prqv5   1/1     Running   0          10m

2、部署測試 web 服務

為了展示 ingress 路由轉發功能,創建兩個 web 服務,然后通過 ingress 編寫規則來轉發相關請求。
apple.yaml

kind: Pod
apiVersion: v1
metadata:
  name: apple-app
  labels:
    app: apple
spec:
  containers:
    - name: apple-app
      image: hashicorp/http-echo
      args:
        - "-text=apple"

---

kind: Service
apiVersion: v1
metadata:
  name: apple-service
spec:
  selector:
    app: apple
  ports:
    - port: 5678 # Default port for image

banana.yaml

kind: Pod
apiVersion: v1
metadata:
  name: banana-app
  labels:
    app: banana
spec:
  containers:
    - name: banana-app
      image: hashicorp/http-echo
      args:
        - "-text=banana"

---

kind: Service
apiVersion: v1
metadata:
  name: banana-service
spec:
  selector:
    app: banana
  ports:
    - port: 5678 # Default port for image

部署 pod

$ kubectl apply -f apple.yaml
$ kubectl apply -f banana.yaml

查看 service、pod:

$ kubectl get svc,po | grep -E "apple|banana"
service/apple-service          ClusterIP   10.106.133.148   <none>        5678/TCP   10m
service/banana-service         ClusterIP   10.108.239.61    <none>        5678/TCP   10m
pod/apple-app                           1/1     Running             0          10m
pod/banana-app                          1/1     Running             0          10m
$ curl 10.106.133.148:5678
apple
$ curl 10.108.239.61:5678
banana

3、部署 Ingress

編寫 yaml 文件,指定路由規則

$ vim ingress-nginx.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: nginx.tempdomain.com
    http:
      paths:
      - path: /apple
        backend:
          serviceName: apple-service
          servicePort: 5678
      - path: /banana
        backend:
          serviceName: banana-service
          servicePort: 5678

部署 ingress:

$ kubectl apply -f ingress-nginx.yaml

查看 ingress:

$ kubectl get ingress
NAME            HOSTS               ADDRESS   PORTS   AGE
nginx-ingress   nginx.tempdomain.com             80      10m
$ kubectl describe ingress nginx-ingress
Name:             nginx-ingress
Namespace:        default
Address:
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host               Path  Backends
  ----               ----  --------
  nginx.tempdomain.com
                     /apple    apple-service:5678 (100.93.23.211:5678)
                     /banana   banana-service:5678 (100.107.55.15:5678)

4、檢查可用性

$ curl nginx.tempdomain.com/apple
apple
$ curl nginx.tempdomain.com/banana
banana

參考:
https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/
https://matthewpalmer.net/kubernetes-app-developer/articles/kubernetes-ingress-guide-nginx-example.html
https://segmentfault.com/a/1190000019908991#articleHeader5


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM