内容简介:為了能夠讓使用者能夠更直接順利的存取到這篇要來跟大家介紹另外一個相輔相成且好用的概念,也就是所謂的都能夠簡單地完成。 為了能夠順利使用
為了能夠讓使用者能夠更直接順利的存取到 kubernetes
眾多運行的 Pods
, kubernetes
花了很大把的精力在網路架構與使用這方面,之前已經詳細介紹過 Kubernetes Service
的 用法以及原理
這篇要來跟大家介紹另外一個相輔相成且好用的概念,也就是所謂的 Ingress
. 透過 Ingress
我們能夠提供一些更方便的伺服器存取,不論是基於 URL
的存取導向,亦或是簡化整個 SSL
憑證部署的方式
都能夠簡單地完成。 為了能夠順利使用 SSL
憑證,我們也可以搭配Cert-Manager 來進行憑證的處理,並且將其與 Ingress
給整合。
本文主要會從 Ingress
的基本概念出發,介紹其基本架構並且從最常用的 Ingress Nginx
作為一個使用範例,來介紹實際上整個 Kubernetes
集群內是如何運作的
Introduction
Kubernetes
有一個非常有趣且迷人的地方,就是大量的抽象化,部分的功能則是公開其介面,依賴第三方廠商自行實現該介面來提供此功能。
譬如以前有提過的 Network Policy
就是這樣的一種概念,不同的 網路解決方案提供者
可以針對自己的應用特性來實現對應的 Network Policy
進而提供多一層的網路保護。
而 Ingress
也是一個類似的架構,接下來會仔細介紹一下其架構以及如何使用。最後則是會使用 Nginx Ingress Controller
當作一個範例來解釋整個運作
Architecture
Kubernetes
的 Ingress
裡面我們可以設定一些如何轉發封包的選項,範例如下
apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: name: nginx-demo namespace: default spec: rules: - host: nginx.example.com http: paths: - path: /v1 backend: serviceName: nginx servicePort: http - path: /v2 backend: serviceName: nginx-v2 servicePort: http - host: note.example.com http: paths: - path: / backend: serviceName: jupyter servicePort: http
Ingress
內我們可以針對 Host
或是 Path
不同的選項來決定該封包要怎麼轉發。以上述範例來說,我們希望達到的是
- 如果看到的是
note.example.com
可以送給特定的service
- 如果看到的是
nginx.example.com
,則根據後面的path (v1/v2)
來決定最後要怎麼轉發。
這邊要特別注意的是,對於 Kubernetes
來說, Ingress
物件本身只有描述的功用,實際上並不會真的把使用者所描述與敘述的功能給實現完畢,這部分需要依賴剩下的元件來補足。
接下來我們使用下列這張圖示來解釋一下一個完整 Ingress
的架構。
圖中標示為 Ingress Resource
的元件就是使用者們透過 Ingress Yaml
去描述預期行為的設定檔,也就是上圖的部分。
綠色的 Backend server
則是後端不同類型的服務器,使用者會預期 Ingress
可以根據 Host/Path
等不同的規則將對應的封包轉發到後端真正服務的 Backend Server
.
接下來真正重要的就是 Ingress-Controller
以及 Ingress-Server
.
Ingress-Server
普遍上來說,就是一個能夠接受 HTTP/HTTPS
連線的網路伺服器,以本篇文章來說就是 Nginx
.
過往的使用經驗上,我們的確可以透過 nginx.conf
的方式來設定 nginx server
. 來達到根據不同的情況來決定不同的封包轉發等行為。
但是在 kubernetes ingress
的架構下,使用者並不一定熟悉 nginx.conf
的格式與撰寫,而熟悉的只有 Kubernetes Ingress
的格式。
在此條件下,我們需要一個轉換者,該轉換者能夠將 Ingress Resource
的設定轉換成 Ingress-Server (Nginx)
所能夠處理的格式。
這個角色也就是所謂的 Ingress-Controller
.
將上述的設定與使用流程以順序來看
- 使用者透過
yaml
部署ingress
設定到kubernetes
裡面 -
Ingress-Controller
偵測到Ingress Resource
的更動,讀取該設定後產生對應的Nginx.conf
供Ingress-Server
使用 - 外部使用者嘗試存取服務,該封包會先到達
Ingress-Server(Nginx)
. -
Ingrss-Server(Nginx)
根據nginx.conf
的設定決定將該封包轉發到後段的服務器backend server
.
從上述的概念來說,我們可以簡單歸納一下 Ingress
的架構
-
Kubernetes
本身只提供一個統一的Ingress
介面,本身不參與該介面的實作 - 服務提供者本身必須要實現
Ingress-Server
以及Ingress-Controller
這兩個元件將使用者描述的抽象概念轉換成實際上可以運作的設定
所以可以看到目前現實上有非常多的 Ingress
實作,不論是 Traefik
, Kong
, Nginx
甚至是各個公有雲(GKE/AKS/EKS)都有跟自行架構更加整合的實現。
關於 Ingress
更多的概念可以參考 官方文件
Annotation
有實際上使用過 Ingress
的玩家會發現在 Yaml
內有各式各樣的 annotation
要使用,譬如
annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/rewrite-target: /
首先,根據上述的架構概念,我們可以知道 Ingress-Controller
會去讀取 Ingress
的設定,然後來進行後續的動作。
假想一個情況,系統內同時有多個 Ingress-Controller
的實現,使用者要如何指派該 Ingress
要使用哪一個 Ingress-Controller
來使用?
再者個情況下,我們可以透過 annotations
的方式來加註一些額外的資訊,當然這些資訊不是標準的,反而是各個 Ingress-Controller
自行決定看到什麼樣的資訊來進行什麼處理。
此外,不同的 Ingress-Server
提供的功能與使用方式都不同,基本上 Ingress Resource
很難有一個完美的介面來滿足所有的實現,因此大部分的情況下,不同的 Ingress-Controller/Ingress-Server
都會要求使用者在 Annotation
的部分使用特定的字眼來描述額外的功能,譬如
nginx.ingress.kubernetes.io/rewrite-target: /
所以在選擇 Ingess
的使用上,遇到任何問題的時候,如果是 Ingress Resource
的介面問題,則可以尋求 Kubernetes
官方文件的幫助,如果是更細緻的需求,則該查詢 Ingress-Controller
的說明文件,看看自己的需求與相對應的設定是否有辦法完成。
Compare
跟 Kubernetes Service
比較起來,兩者都在提供便捷的 網路存取
服務
Server
針對的單位主要是 Pod(Container)
, 提供一個更方便的方式讓用戶端可以不用在意後端 Pod(Container)
的真實 IP
地址。
而 Ingress
目前的使用上更偏向是 HTTP/HTTPS
的應用,在上述的 Service
上搭建一層更方便的服務,可以根據 Host(NameBasd Virtaul Hosting)
或是 Path(Fanout)
來決定後續真正轉發的對象,而該對象則是不同後端服務所搭建起來的 Service
.
因此在使用上,這兩者並沒有誰取代誰的問題,反而是根據需求來使用,大部分情況下都是互相整合來提供更方便與好用的功能。
Example
上述已經介紹完關於 Ingress
的基本概念,接下來要使用 Nginx
作為 Ingress-Server
來實際搭建一個 Ingress
的範例。
接下來的所有範例文件都可以在 KubeDemo 內找到對應的檔案。
該範例的架構圖如下
我們會在 Kubernetes
裡面進行下列部署
- 搭建一個基於
Nginx
的Ingress-Controller/Ingress-Server
, - 透過
Deployment
部署三套不同的後端服務,分別是Jupyter Notebook
以及兩個有者不同Index.html
的Nginx Server
. - 透過三個不同的
kubernetes service
將上述的Deployment
包裝起來提供更方便的存取功能 - 部署對應的
Ingress
, 希望可以完成- 存取
note.example.com
會存取到jupyter notebook
- 存取
nginx.example.com/v1
會存取到nginx
- 存取
nginx.example.com/v2
會存取到nginx-v2
- 存取
接下來我們就要依據上述的概念進行相關檔案的部署。
我的測試環境是基於 MAC
上透過 Vagrant
創建一個 UbuntuOS
並且使用 Kubeadm
實現的一個小型 Kubernetes
叢集。
Nginx Controller
首先我們要先部署 Nginx Controller
到 kubernetes
叢集內,詳細的安裝方式可以參閱其 官網
首先我們要先安裝相關的資源,譬如 RBAC
以及相關的 Deployment
.
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml
接下來為了讓外界的服務可以存取到該 Nginx Server (Ingress-Server)
,這邊會根據你的機器環境而有所不同。
以我 Baremetal
的環境,我需要部署下列的資源,透過 Kubernetes Service NodePort
的方式讓我的 Nginx Server
可以被外界存取
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/baremetal/service-nodeport.yaml
上述的部屬都會安裝到 ingress-nginx
的 kubernetes namespace
上,所以透過下列的指令觀察安裝的情形
$ kubectl -n ingress-nginx get all NAME READY STATUS RESTARTS AGE pod/nginx-ingress-controller-d88dbf49c-9b6td 1/1 Running 0 23h NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/ingress-nginx NodePort 10.111.134.97 <none> 80:32663/TCP,443:31309/TCP 1d NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deployment.apps/nginx-ingress-controller 1 1 1 1 1d NAME DESIRED CURRENT READY AGE replicaset.apps/nginx-ingress-controller-d88dbf49c 1 1 1 1d
Outside Internet Access
為了從外部 MAC
的瀏覽器進行測試,我對機器上的 /etc/hosts
進行了相關的修改, 加上了下列的資料,讓我可以透過相關的設定來存取該 NodePort
的 Nginx(Ingress-Server)
.
172.17.8.101 nginx.example.com note.example.com
172.17.8.101
是我 VM(Ubuntu)
的 Virtaul IP address
.
Backend Servers
Jupyter
基本上需要的就是 Deployment
配上一個對應的 Service
即可
詳細的請參閱 KubeDemo
kubectl apply -f https://raw.githubusercontent.com/hwchiu/kubeDemo/master/ingress/jupyter.yml
Nginx
類似上述 Jupyter
的安裝流程,但是為了客製化 index.html
的內容,會額外部署一個 configMap
來產生不同的內容
kubectl apply -f https://raw.githubusercontent.com/hwchiu/kubeDemo/master/ingress/nginx.yaml kubectl apply -f https://raw.githubusercontent.com/hwchiu/kubeDemo/master/ingress/nginx2.yaml
這些應用程式都會部署到 default
這個 namespace
,所以可以用下列指令確保部署正確
kubectl -n default get all NAME READY STATUS RESTARTS AGE pod/jupyter 1/1 Running 0 15h pod/nginx-7dd9f89db4-tvfkk 1/1 Running 0 15h pod/nginx-v2-5c45597f57-746p8 1/1 Running 0 15h NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/jupyter LoadBalancer 10.106.190.88 <pending> 80:32444/TCP 15h service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 89d service/nginx ClusterIP 10.110.237.87 <none> 80/TCP 15h service/nginx-v2 ClusterIP 10.103.43.44 <none> 80/TCP 15h NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deployment.apps/nginx 1 1 1 1 15h deployment.apps/nginx-v2 1 1 1 1 15h NAME DESIRED CURRENT READY AGE replicaset.apps/nginx-7dd9f89db4 1 1 1 15h replicaset.apps/nginx-v2-5c45597f57 1 1 1 15h
上述服務完畢後,先用 curl
針對三個 service
的 ClusterIP
去確認服務有正常起來
$ curl 10.110.237.87 Nginx V1 $ curl 10.103.43.44 Nginx V2 $ curl 10.106.190.88/tree ....
Deploy Ingress
上述相關的服務都部署完畢後,接下來就要部署 Ingress
物件進去,我們期望的行為是 Nginx Controller
能夠讀取這個 Ingress
的物件並且產生對應的 nginx.conf
供 Nginx Server(Ingress-Server)
使用.
所以先來看一下對應的 Ingress Resource
apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/rewrite-target: / name: nginx-demo namespace: default spec: rules: - host: nginx.example.com http: paths: - path: /v1 backend: serviceName: nginx servicePort: http - path: /v2 backend: serviceName: nginx-v2 servicePort: http - host: note.example.com http: paths: - path: / backend: serviceName: jupyter servicePort: http
該物件部署完畢後,透過下列指令觀察部署結果
$ kubectl get ingress NAME HOSTS ADDRESS PORTS AGE nginx-demo nginx.example.com,note.example.com 80 15h
Check Nginx
接下來我們將直接進入到 Nginx Controller
去觀察一下是否有對應的 nginx.conf
被產生
$ kubectl -n ingress-nginx exec -it $(kubectl -n ingress-nginx get pods -l app.kubernetes.io/name=ingress-nginx -o jsonpath="{.items[0].metadata.name}") bash
[email protected]:/etc/nginx$
[email protected]:/etc/nginx$ grep "example.com" nginx.conf
## start server nginx.example.com
server_name nginx.example.com ;
## end server nginx.example.com
## start server note.example.com
server_name note.example.com ;
## end server note.example.com
[email protected]:/etc/nginx$ grep "v1" nginx.conf
ssl_protocols TLSv1.2;
location ~* "^/v1\/?(?<baseuri>.*)" {
set $location_path "/v1";
rewrite "(?i)/v1/(.*)" /$1 break;
rewrite "(?i)/v1$" / break;
[email protected]:/etc/nginx$ grep "v2" nginx.conf
location ~* "^/v2\/?(?<baseuri>.*)" {
set $service_name "nginx-v2";
set $location_path "/v2";
set $proxy_upstream_name "default-nginx-v2-http";
rewrite "(?i)/v2/(.*)" /$1 break;
rewrite "(?i)/v2$" / break;
到這邊為止,基本上的一切都順利設定完畢了,接下來就可以開啟瀏覽器嘗試去瀏覽看看.
Access the Nginx Server
因為我們的 Nginx Server
是基於 NorePort
的方式來供對外存取,所以我們要先確認一下開啟的 NodePort
資訊是什麼
$ kubectl -n ingress-nginx get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx NodePort 10.111.134.97 <none> 80:32663/TCP,443:31309/TCP 1d
在我的範例環境中,預設 HTTP
所使用的的連接埠是 32663
, 因此等下需要使用這個資訊來進行測試連線
首先,我們先針對 nginx.example.com
進行測試,結果如下圖
結果如預期般,可以透過不同的 PATH
來導向不同的服務後端
接下來測試 node.example.com
, 看看是否能夠針對 host
來導向不同的後端
的確也能夠正常運作,意味者我們的 Ingress
測試滿順利的,都能夠如預期般的運作
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
快速转行做产品经理
李三科 / 华中科技大学出版社 / 2018-6-1 / 39.90
互联网已经进入以产品为中心的时代,不懂技术一样做高薪产品经理。本书将满足你转行、就业、加薪的愿望。 . 作者李三科,互联网资深产品经理。2011年离开传统销售行业进入互联网行业工作,从对产品经理的工作一无所知,到成长为一名年薪几十万的资深产品经理,他对产品经理职业有着深刻的理解,也积累了丰富的学习、工作经验。本书以作者亲身经历为线索,讲解学习产品经理相关知识和工作方法的经验,同时介绍求......一起来看看 《快速转行做产品经理》 这本书的介绍吧!