k8s loadbalancer與ingress實踐


k8s可以通過三種方式將集群內服務暴露到外網,分別是NodePort、LoadBalancer、Ingress,其中NodePort作為基礎通信形式我們在《k8s網絡模型與集群通信》中進行了介紹,這里我們主要關注LoadBalancer和Ingress

LoadBalancer


loadbalancer是服務暴露到因特網的標准形式,和nodeport一樣我們只需在創建service是指定type為loadbalancer即可,接着Service 的通過status.loadBalancer字段將需要創建的負載均衡器信息發布供負載均衡服務創建。不過loadbalancer是雲服務商”專屬“,像騰訊雲CLB、阿里雲SLB,這樣在創建service時會自動幫我們創建一個負載均衡器。

大多數雲上負載均衡也是基於nodeport,他們的結構如下:

image-20220104155502920

如果要在本地創建一個負載均衡器如何實現呢?

MetalLB,一個CNCF沙箱項目,使用標准路由協議(ARP/BGP),實現裸機K8s集群的負載均衡器。

安裝方式可參考官方文檔:installation

L2(子網)模式的結構,圖源

image-20220104163613950

安裝后我們獲得如下兩個組件:

  • metallb-system/controller deployment。用於處理IP分配的控制器。
  • metallb-system/speakerdaemonset。集群中每個節點啟動一個協議服務守護進程。

接着添加一個configmap配置metallb IP池。

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.1.240-192.168.1.250

這樣當我們創建一個loadbalancer類型的service時,EXTERNAL-IP將會從地址池中獲取一個用於外部訪問的IP 192.168.1.243 當外部流量進入時,ARP將我們的請求地址廣播獲取所屬的service,接着k8s內部 通過iptables 規則和 kube-proxy,將流量從服務端點引導到后端。

#nginx_deployment_service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: metallb-system
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - name: http
          containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  namespace: metallb-system
  name: nginx
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer

查看service kubectl get svc

NAME     TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
nginx    LoadBalancer   10.96.243.159   192.168.1.243   80:31052/TCP   40h

測試訪問:curl 192.168.1.243

# curl 192.168.1.243
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>

負載均衡可以建立在 OSI 網絡模型的不同級別上,主要是在 L4(傳輸層,例如 TCP/UDP)和 L7(應用層,例如 HTTP)上。在 Kubernetes 中,Services是 L4 的抽象,LoadBalancer類型負載均衡依然有局限性,同時我們看到每創建一個service對應的負載均衡器都會消耗一個靜態IP,這並不合理。當然k8s中的另一種資源對象ingress可工作在 L7 層實現應用程序協議(HTTP/HTTPS)的負載均衡。

Ingress


Ingress 公開了從集群外部到集群內服務的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 資源上定義的規則控制。我們可以將 Ingress 配置為服務提供外部可訪問的 URL、負載均衡流量、終止 SSL/TLS,以及提供基於名稱的虛擬主機等能力。

我們所說的Ingress包含兩個部分:

  • ingress k8s資源對象:流量路由規則的控制
  • ingress-controller控制器:控制器的實現有非常多,可參考官方文檔中列表Ingress 控制器,這里我們使用k8s官方維護的控制器NGINX Ingress Controller

外部流量進入集群時先經過ingress-controller,然后根據ingress配置的路由規則將請求轉發到后端service。

image-20220104174923429

ingress-controller

ingress-controller其實就是守護進程加一個反向代理的應用,守護進程不斷監聽集群中資源的變化,將ingress中的配置信息生成反向代理配置。在nginx-ingress controller中即生成nginx.conf的配置文件。

在本文中因為我們上面已經配置好了loadbalancer的服務,這樣我們創建一個type為LoadBalancer的service關聯這組pod,再把域名解析指向該地址,就實現了集群服務的對外暴露。當然你也可以使用NodePortHostnetwork的方式,感興趣的小伙伴可以進行測試。

ingress-controller不是k8s內部組件,可以通過helm或資源清單方式安裝,可查看ingress-nginx deploy

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.0/deploy/static/provider/cloud/deploy.yaml

然后我們編輯service

kubectl edit service/ingress-nginx-controller -n ingress-nginx

修改spec.type為LoadBalancer即可。

這樣我們創建好了nginx-ingress controller,下一步就要配置ingress路由規則。

ingress規則

host:k8s.com

基於url的路由:

  • /api/v1
  • /api/v2

這兩個url分別路由到不同的service中

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
  namespace: training
  annotations:
    ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: k8s.com
    http:
      paths:
      - path: /api/v1
        backend:
          serviceName: service-apiv1
          servicePort: 80
      - path: /api/v2
        backend:
          serviceName: service-apiv2
          servicePort: 80

ingress.kubernetes.io/rewrite-target是nginx-ingress controller的一個注解,當后端服務中暴露的 URL 與 Ingress 規則中指定的路徑不同時可以通過此重定向。

查看svc可以看到此時控制器已經獲得了一個EXTERNAL-IP

#kubectl get svc -n ingress-nginx
NAME                                 TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.96.87.23    192.168.1.245   80:32603/TCP,443:31906/TCP   621d
ingress-nginx-controller-admission   ClusterIP      10.96.109.70   <none>          443/TCP                      621d

現在nginx-ingress controller和ingress路由規則都有了。

我們可以進入到nginx-ingress controller pod中查看nginx.conf可以看到此時我們的ingress配置已經被生成為路由規則。

image-20220104211938284接下來就是指定我們的backend,即上面的server-apiv1/2

我們添加兩個用於暴露的service和deployment,和loadbalancer中測試清單一樣,我們稍稍修改一下名稱即可。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-apiv1
  namespace: training
spec:
  selector:
    matchLabels:
      app: nginx-apiv1
  template:
    metadata:
      labels:
        app: nginx-apiv1
    spec:
      containers:
      - name: nginx-apiv1
        image: nginx:latest
        ports:
        - name: http
          containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  namespace: training
  name: service-apiv1
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx-apiv1
  type: NodePort

將nginx-apiv1換成nginx-apiv2創建出另一個service和deployment。

最后修改hosts解析k8s.com

192.168.1.245 k8s.com

使用curl命令測試url路由(記得在pod中添加測試文件,否則雖然url進行了路由但會出現404)。

# curl k8s.com/api/v1/index.html
api v1
# curl k8s.com/api/v2/index.html
api v2

這樣我們對ingress有了初步了解,ingress的路由規則可自定項較多也比較繁雜,可通過官方文檔進一步學習。


希望小作文對你有些許幫助,如果內容有誤請指正。

您可以隨意轉載、修改、發布本文,無需經過本人同意。


免責聲明!

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



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