Kubernetes-Service介紹(三)-Ingress(含最新版安裝踩坑實踐)


前言

本篇是Kubernetes第十篇,大家一定要把環境搭建起來,看是解決不了問題的,必須實戰。

Kubernetes系列文章:
  1. Kubernetes介紹
  2. Kubernetes環境搭建
  3. Kubernetes-kubectl介紹
  4. Kubernetes-Pod介紹(-)
  5. Kubernetes-Pod介紹(二)-生命周期
  6. Kubernetes-Pod介紹(三)-Pod調度
  7. Kubernetes-Pod介紹(四)-Deployment
  8. Kubernetes-Service介紹(一)-基本概念
  9. Kubernetes-Service介紹(二)-服務發現

什么需要Ingress

Service是基於四層TCP和UDP協議轉發的,而Ingress可以基於七層的HTTP和HTTPS協議轉發,可以通過域名和路徑做到更細粒度的划分,如下圖所示:

img
img

Ingress請求過程

用戶請求首先到達Ingress Controller,Ingress Controller根據Ingress的路由規則,查找到對應的Service,進而通過Endpoint查詢到Pod的IP地址,然后將請求轉發給Pod。

img
img

Ingress與Ingress Controller

簡單來說,Ingress Controller是負責具體轉發的組件,通過各種方式將它暴露在集群入口,外部對集群的請求流量會先到Ingress Controller,而Ingress對象是用來告訴Ingress Controller該如何轉發請求,比如哪些域名哪些Path要轉發到哪些服務等等。

Ingress Controller

Ingress Controller並不是Kubernetes自帶的組件,實際上Ingress Controller只是一個統稱,用戶可以選擇不同的Ingress Controller實現,目前,由Kubernetes維護的Ingress Controller只有Google的GCE與Ingress Nginx兩個,其他還有很多第三方維護的Ingress Controller。但是不管哪一種Ingress Controller,實現的機制都基本一致,只是在具體配置上有差異。一般來說,Ingress Controller的形式都是一個Pod,里面跑着daemon程序和反向代理程序。daemon負責不斷監控集群的變化,根據Ingress對象生成配置並應用新配置到反向代理,比如Nginx Ingress就是動態生成Nginx配置,動態更新upstream,並在需要的時候重新加載應用新配置。

Ingress

Ingress是一個API對象,和其他對象一樣,通過yaml文件來配置。Ingress通過Http或Https暴露集群內部Service,給Service提供外部URL、負載均衡、SSL/TLS能力以及基於Host代理。

Ingress的部署

Deployment+LoadBalancer模式的Service

如果要把Ingress部署在公有雲,那可以選擇這種方式。用Deployment部署Ingress Controller,創建一個type為LoadBalancer的Service關聯這組Pod。大部分公有雲,都會為LoadBalancer的Service自動創建一個負載均衡器,通常還綁定了公網地址。只要把域名解析指向該地址,就實現了集群服務的對外暴露。此方案確定需要在公有雲上部署。

img
img
Deployment+NodePort模式的Service

使用Deployment模式部署Ingress Controller,並創建對應的服務,但是type為NodePort。這樣,Ingress就會暴露在集群節點ip的特定端口上。由於Nodeport暴露的端口是隨機端口,一般會在前面再搭建一套負載均衡器來轉發請求。該方式一般用於宿主機是相對固定IP地址。

缺點:

  1. NodePort方式暴露Ingress雖然簡單方便,但是NodePort多了一層轉發,在請求量級很大時可能對性能會有一定影響;
  2. 請求節點會是類似http://www.a.com:3008,其中3008是Ingress Nginx的svc暴露出來的Nodeport端口,看起來不太專業;
image.png
image.png
DaemonSet+HostNetwork+NodeSelector模式

使用DaemonSet結合Nodeselector來部署Ingress Controller到特定的Node上,然后使用HostNetwork直接把該Pod與宿主機Node的網絡打通,直接使用宿主機的80/433端口就能訪問服務。這時Ingress Controller所在的Node機器就是流量入口。

優點

該方式整個請求鏈路最簡單,性能相對NodePort減少一層轉發,因此性能更好;

缺點

由於直接利用宿主機節點的網絡和端口,一個Node只能部署一個Ingress Controller的pod;

image.png
image.png

部署實戰

關於版本問題需要注意以下幾點:

本篇采用ingress-nginx v1.0.0,最新版本 v1.0.0適用於 Kubernetes 版本 v1.19+ ;

Kubernetes-v1.22+ 需要使用 ingress-nginx>=1.0,因為 networking.k8s.io/v1beta 已經移除;

Deployment+NodePort模式
  1. 使用wget下載v1.0.0的deploy.yaml,該處可能由於網絡的原因下載不下來,大家可以在第二步下載我改好的文件;
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.0/deploy/static/provider/baremetal/deploy.yaml
  1. 接下來我們需要修改deploy.yaml里面的鏡像文件,由於k8s.gcr.io相關的鏡像國內都進行屏蔽了,這里我采用了從docker官方去下載相關的鏡像文件,需要將k8s.gcr.io/ingress-nginx/controller:v1.0.0和k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.0鏡像替換為willdockerhub/ingress-nginx-controller:v1.0.0和jettech/kube-webhook-certgen:v1.5.2,這里需要注意的是kube-webhook-certgen有兩處不要漏替換,此外需要在args處增加--watch-ingress-without-class=true配置,這里將修改好的文件v1.0.0-deploy.yaml上傳到網盤, 鏈接 提取碼: sksc ;
image.png
image.png
image.png
image.png
  1. 部署nginx-ingress-controller;
kubectl apply -f v1.0.0-deploy.yaml 
  1. 檢查nginx-ingress-controller創建的情況,這個我們會發現該Service是一個NodePort類型,並且被隨機分配兩個端口,分別是32368和32577,后續我們就需要通過這個端口訪問改地址信息;
#查看相關pod狀態
kubectl get pods -n ingress-nginx -owide
#查看service
kubectl get service -n ingress-nginx
image.png
image.png
  1. 創建Deployment和Service,這里我們就是就使用之前的nginx-deployment.yaml和nginx-service.yaml;
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: backend
  replicas: 3
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        resources:
          limits:
            memory: "128Mi"
            cpu: "128m"
        ports:
        - containerPort: 80
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  #定義后端pod標簽為app=backend
  selector:
    app: backend
  ports:
  #service端口號
  - port: 80
    #pod的端口號
    targetPort: 80
kubectl apply -f nginx-service.yaml
kubectl apply -f nginx-nodeport-service.yaml
  1. 驗證Service創建情況,並且可以通過Service地址訪問相關服務;
#查看service狀況
kubectl get svc
#訪問服務
curl http://10.96.45.195
  1. 新建ingress策略nodeport-ingress.yaml,創建對應資源;
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nodeport-ingress
  namespace: default
spec:
  rules:
  - host: aa.bb.cc
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: nginx-service
            port:
              number: 80
#創建ingress資源
kubectl apply -f nodeport-ingress.yaml
#檢查ingress資源
kubectl get ingress
image.png
image.png
  1. 檢查資源的訪問,這里使用nginx-ingress-controller暴露的端口32368訪問服務的信息;
#第一種方案可以在對應Node上設置host文件
echo '172.21.122.231 aa.bb.cc' >> /etc/hosts
curl aa.bb.cc:32368
#使用curl方式
curl -v http://172.21.122.231:32368 -H 'host: aa.bb.cc'
image.png
image.png
DaemonSet+HostNetwork+nodeSelector模式
  1. 清除資源;
kubectl delete -f v.1.0.0-deploy.yaml
kubectl delete -f nginx-nodeport-service.yaml
kubectl delete -f nodeport-ingress.yaml
  1. 給Node節點打標簽為ingress=nginx;
kubectl label nodes demo-work-1 ingress=nginx
  1. 編輯v1.0.0-deploy.yaml,找到deployment部分,將kind變為DaemonSet,nodeSelector節點選擇器變為ingress等於nginx,增加網絡為hostNetwork等於true,這里需要在args新增--watch-ingress-without-class,這樣ingress規則才能生效,這個是新版的以后不太一樣的地方, 鏈接提取碼: dbag;
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    helm.sh/chart: ingress-nginx-4.0.1
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 1.0.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: controller
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/instance: ingress-nginx
      app.kubernetes.io/component: controller
  revisionHistoryLimit: 10
  minReadySeconds: 0
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/instance: ingress-nginx
        app.kubernetes.io/component: controller
    spec:
      dnsPolicy: ClusterFirst
      containers:
        - name: controller
          image: willdockerhub/ingress-nginx-controller:v1.0.0
          imagePullPolicy: IfNotPresent
          lifecycle:
            preStop:
              exec:
                command:
                  - /wait-shutdown
          args:
            - /nginx-ingress-controller
            - --election-id=ingress-controller-leader
            - --controller-class=k8s.io/ingress-nginx
            - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
            - --validating-webhook=:8443
            - --validating-webhook-certificate=/usr/local/certificates/cert
            - --validating-webhook-key=/usr/local/certificates/key
            - --watch-ingress-without-class=true  # 新增
          securityContext:
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            runAsUser: 101
            allowPrivilegeEscalation: true
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: LD_PRELOAD
              value: /usr/local/lib/libmimalloc.so
          livenessProbe:
            failureThreshold: 5
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 1
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 1
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
            - name: https
              containerPort: 443
              protocol: TCP
            - name: webhook
              containerPort: 8443
              protocol: TCP
          volumeMounts:
            - name: webhook-cert
              mountPath: /usr/local/certificates/
              readOnly: true
          resources:
            requests:
              cpu: 100m
              memory: 90Mi
      nodeSelector:
        ingress: nginx
      hostNetwork: true
      serviceAccountName: ingress-nginx
      terminationGracePeriodSeconds: 300
      volumes:
        - name: webhook-cert
          secret:
            secretName: ingress-nginx-admission
  1. 部署和檢查ingress-nginx;
#部署ingress-nginx
kubectl apply -f v1.0.0-deploy.yaml
#查看相關pod狀態
kubectl get pods -n ingress-nginx -owide
#查看service
kubectl get service -n ingress-nginx
  1. 新建nginx-service.yaml,將方式改變為ClusterIP形式;
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  #定義后端pod標簽為app=backend
  selector:
    app: backend
  ports:
  #service端口號
  - port: 80
    #pod的端口號
    targetPort: 80
  1. 創建nginx-service,並檢查資源情況;
#創建nginx-service
kubectl apply -f nginx-service.yaml
#檢查資源狀況
kubectl get svc
#資源的綁定情況
kubectl describe service nginx-service
#通過curl訪問
curl 10.96.53.148
image.png
image.png
  1. 創建hostnetwork-ingress.yaml文件;
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nodeport-ingress
  namespace: default
spec:
  rules:
  - host: aa.bb.cc
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: nginx-service
            port:
              number: 80
  1. 創建ingress資源;
#創建ingress
kubectl apply -f hostnetwork-ingress.yaml
#檢查ingress資源
kubectl get ingress
  1. 檢查資源的訪問;
curl -v http://172.21.122.231 -H 'host: aa.bb.cc'
image.png
image.png

結束

歡迎大家點點關注,點點贊!


免責聲明!

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



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