提升CKA認證成功率:Kubernetes Ingress七層代理商全攻略!

2024.03.04


網路雲端運算
透過Ingress和Ingress Controller的配合,我們在管理外部存取時變得更加靈活和便捷,擺脫了手動修改Nginx配置的煩惱,讓我們能夠更專注於服務與域名的映射關係,提升了Kubernetes集群的可維護性。

一、Ingress介紹

Ingress是Kubernetes中負責將外部請求引導到叢集內部服務的機制,透過將服務對應到叢集外的URL,實現服務的外部可存取性。Ingress支援配置叢集內的Service,使其可以透過外部URL訪問,同時提供流量負載平衡和基於網域的虛擬主機等功能。

簡單理解Ingress就是將原本需要手動修改Nginx配置、配置網域名稱與服務對映的繁瑣步驟,抽象化成一個Ingress物件。透過使用YAML檔案建立和更新Ingress對象,我們不再需要手動操作Nginx設定文件,而是透過更方便的方式管理網域名稱與服務的關係。

然而,這引發了一個問題:「Nginx該如何處理這些變化?」這時候,Ingress Controller登場,專門解決Nginx處理方式的問題。Ingress Controller與Kubernetes API進行交互,即時感知叢集中Ingress規則的變化。一旦有變化,Ingress Controller會讀取這些規則,並根據自己的模板產生相應的Nginx配置。隨後,它將這段設定寫入Nginx Pod,最後觸發Nginx的重載操作,確保設定的生效。

透過Ingress和Ingress Controller的配合,我們在管理外部存取時變得更加靈活和便捷,擺脫了手動修改Nginx配置的煩惱,讓我們能夠更專注於服務與域名的映射關係,提升了Kubernetes集群的可維護性。

1.Ingress Controller介紹

Ingress Controller是一種七層負載平衡調度器,它作為客戶端請求的第一站,接收並處理所有外部請求。在這個七層負載平衡調度器的作用下,請求會經過反向代理,最後被路由到後端的Pod。常見的七層負載平衡器包括nginx、traefik等。以我們熟悉的nginx為例,當請求到達nginx時,nginx會透過upstream設定反向代理到後端Pod應用。

Ingress Controller

然而,後端Pod的IP位址是動態變化的,為了解決這個問題,我們引入了Service。這個Service並非實際的服務,而是扮演了後端Pod的分組角色。因此,在設定upstream時,我們只需要填入Service的位址即可,而不需要關心後端Pod的特定IP位址。

透過這樣的設計,Ingress Controller能夠靈活處理後端Pod的變化,保證請求能夠正確地路由到叢集中的服務。這種模式使得我們能夠更方便地管理後端服務的變化,而不必擔心Pod的IP位址的不斷變化所帶來的問題。

2.Ingress資源

一個最小的Ingress 資源範例:

apiVersion:networking.k8s.io/v1
kind:Ingress
metadata:
  name:minimal-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target:/
spec:
  ingressClassName:nginx-example
  rules:
  -http:
      paths:
      -path:/testpath
        pathType:Prefix
        backend:
          service:
            name:test
            port:
              number:80
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

Ingress 需要指定apiVersion、kind、 metadata和spec 欄位。Ingress 物件的命名必須是合法的 DNS 子網域名稱[1]。

3.Ingress Controller代理k8s內部應用的流程

  • 部署Ingress controller,我們ingress controller使用的是nginx
  • 建立Pod應用,可以透過控制器建立pod
  • 建立Service,用來分組pod
  • 建立Ingress http,測試透過http存取應用
  • 建立Ingress https,測試透過https存取應用

必須具有ingress 控制器,才能滿足Ingress 的要求。僅建立Ingress 資源無效。

Ingress

(1) 部署ingress-nginx

這裡同樣使用killercoda平台進行測試,該平台部署的是最新版V1.29.0的K8S環境。

由於該環境沒有部署Ingress。以下透過部署ingress-nginx[2]為例。透過查閱ingress-nginx官方,了解V1.29.0對應的是Ingress-NGINX 的V1.10.0或v1.9.6。如下:

Ingress-NGINX的版本列表

透過執行以下指令部署Ingress-NGINX 的V1.10.0。

kubectl apply -f \
https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.0/deploy/static/provider/cloud/deploy.yaml
  • 1.
  • 2.

執行完上述指令,輸出如下結果:

透過以下命令查看部署情況:


controlplane $ kubectl get pod -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-d69wp        0/1     Completed   0          102s
ingress-nginx-admission-patch-hkv66         0/1     Completed   0          102s
ingress-nginx-controller-7dcdbcff84-gfqcs   1/1     Running     0          102s
controlplane $ kubectl get svc  -n ingress-nginx
NAME                                 TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.98.23.38      <pending>     80:30770/TCP,443:31444/TCP   3m57s
ingress-nginx-controller-admission   ClusterIP      10.102.219.183   <none>        443/TCP                      3m57s
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

(2) 部署後端tomcat服務

透過部署tomcat服務測試Ingress HTTP代理k8s內部站點,編寫以下資源清單:

apiVersion:v1
kind:Service
metadata:
  name:tomcat
  namespace:default
spec:
  selector:
    app:tomcat
    release:canary
  ports:
    -name:scport
      targetPort:8080
      port:8009
---
apiVersion:apps/v1
kind:Deployment
metadata:
  name:tomcat-deploy
  namespace:default
spec:
  replicas:2
  selector:
    matchLabels:
      app:tomcat
      release:canary
  template:
    metadata:
      labels:
        app:tomcat
        release:canary
    spec:
      containers:
        -name:tomcat
          image:tomcat:8.5.34-jre8-alpine
          imagePullPolicy:IfNotPresent
          ports:
            -name:containerport
              containerPort:8080
              name:ajp
              containerPort:8009
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.

查看pod是否部署成功:

controlplane $ kubectl apply -f ingress-demo.yaml 
service/tomcat created
deployment.apps/tomcat-deploy created
controlplane $ kubectl get pod      
NAME                             READY   STATUS    RESTARTS   AGE
tomcat-deploy-7c67c4d459-5s859   1/1     Running   0          11m
tomcat-deploy-7c67c4d459-bvp2k   1/1     Running   0          11m
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

(3) 撰寫Ingress規則

apiVersion:networking.k8s.io/v1
kind:Ingress
metadata:
  name:ingress-myapp
  namespace:default
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target:/
spec:
  ingressClassName:nginx
  rules:# 定义后端的转发规则
   -host:tomcat.test.com# 通过域名进行转发
     http:
       paths:
         -path:/#配置访问路径,如果通过url进行转发。需要修改,空的默认访问路径是"/"
           pathType:Prefix
           backend:# 配置后端服务
             service:
               name:tomcat# 配置关联的serverce
               port:
                 number:8080# service暴露的端口
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

ingressClassName:這個值可以透過kubectl get ingressclasses。

查看ingress-myapp的詳細資訊:

controlplane $ kubectl apply  -f ingress-myapp.yaml 
ingress.networking.k8s.io/ingress-myapp created
controlplane $ kubectl get ingress
NAME            CLASS   HOSTS             ADDRESS   PORTS   AGE
ingress-myapp   nginx   tomcat.test.com             80      8s
controlplane $ kubectl describe ingress ingress-myapp 
Name:             ingress-myapp
Labels:           <none>
Namespace:        default
Address:          
Ingress Class:    nginx
Default backend:  <default>
Rules:
  Host             Path  Backends
  ----             ----  --------
  tomcat.test.com  
                   /   tomcat:8080 ()
Annotations:       nginx.ingress.kubernetes.io/rewrite-target: /
Events:
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  Sync    62s   nginx-ingress-controller  Scheduled for sync
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.

查看ingress-nginx部署到那個節點上,如下圖:

通上圖可知ingress-nginx部署到node1上,且SVC方式是透過LoadBalancer方式部署。如果,要存取到這個後端tomcat服務,就需要做網域的解析。如下:

...省略..
172.30.2.2 tomcat.test.com
  • 1.
  • 2.

正常訪問如下:

4.CKA真題

(1) 真題截圖

(2) 中文解析

切換k8s 叢集環境:kubectl config use-context k8s

Task:

如下建立一個新的nginx lngress資源:

名稱:pong Namespace:ing-internal

使用服務埠5678 在路徑/hi 上公開服務hi

可以使用以下命令檢查服務hi 的可用性,該命令應返回hi, curl -kL/hi

(3) 官方參考文檔

Ingress[3]

(4) 解題作答

切換k8s 叢集環境:

kubectl config use-context k8s
  • 1.

建立一個名為pong.yaml。資源內容如下:

apiVersion:networking.k8s.io/v1
kind:Ingress
metadata:
  name:pong
  namespace:ing-internal
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target:/
spec:
  ingressClassName:nginx-example
  rules:
  -http:
      paths:
      -path:/hi
        pathType:Prefix
        backend:
          service:
            name:hi
            port:
              number:5678
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • ingressClassName的值,建議在考試的時候通過kubectl get ingressclasses
  • service.name的值,題目中沒有告訴,建議考試時間可以用kubectl get svc 查看

提交資源清單:

kubectl apply -f pong.yaml
  • 1.

透過curl -kL<INTERNAL_IP>/hi驗證,看是否返回hi。

參考資料:

  • [1]DNS 子網域名稱: https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/names#dns-subdomain-names
  • [2]ingress-nginx: https://github.com/kubernetes/ingress-nginx
  • [3]Ingress: https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/