前面講過 Service 對象可以通過 NodePort 的方式將單個(gè)服務(wù)暴露到 Kubernetes 集群的外部粘秆,而 Ingress 則是暴露服務(wù)的另一種方式称鳞,它更復(fù)雜摄欲、也更強(qiáng)大丛塌。
下面是 Ingress 工作示例圖喧笔,可以看出它所扮演的角色和 Spring Cloud Gateway 是類似的避矢。
Kubernetes Ingress 也是一個(gè) API 對象悼瘾,通過 Ingress 對象可以制定請求轉(zhuǎn)發(fā)的規(guī)則签赃,把外部的請求路由到集群中的 Service 服務(wù)中。不同的是分尸,Service 的暴露方式針對的是單個(gè)服務(wù)锦聊,而 Ingress 則是為整個(gè)集群的服務(wù)提供訪問入口。
下面就將前面通過 Docker Compose 部署的微服務(wù)示例項(xiàng)目部署到 Kubernetes 平臺中箩绍,關(guān)于 Kubernetes 平臺的快速搭建孔庭,可以參看其它章節(jié)《一鍵部署利器 Kubeadm 搭建 Kubernetes》章節(jié)。我這里使用了兩臺 2 核 8G 的 ECS 搭建的材蛛。
示例中各個(gè)微服務(wù)的 API 資源描述文件均放置在各個(gè)模塊中圆到,內(nèi)容較長,請 clone 項(xiàng)目后查看卑吭。
我們將各個(gè)模塊的 YML 文件 copy 至 ECS 中 /opt/cloud 目錄下芽淡。
- kubectl apply -f /opt/cloud/cloud-namespace.yml
- kubectl apply -f /opt/cloud/eureka-server.yml
- kubectl apply -f /opt/cloud/actuator-admin.yml
- kubectl apply -f /opt/cloud/api-gateway.yml
- kubectl apply -f /opt/cloud/auth-server.yml
- kubectl apply -f /opt/cloud/user-server.yml
- kubectl apply -f /opt/cloud/order-server.yml
通過 kubectl apply -f 命令依次部署上述 YML 文件,注意先部署第一個(gè) cloud-namespace.yml豆赏,因?yàn)橐葎?chuàng)建好自定義的 namespace 對象挣菲。
apiVersion: v1
kind: Namespace
metadata:
name: cloud
全部執(zhí)行完成后,登錄 kubernetes dashboard 查看工作負(fù)載信息掷邦。
下面這幾個(gè)服務(wù)的 Service 對象都通過 NodePort 的形式暴露到了集群外部白胀,可以在瀏覽器中訪問(注意要添加ECS 的安全組規(guī)則)。
暴露服務(wù) | 訪問地址 | 用戶密碼 |
---|---|---|
eureka-server | http://ip:31000/login | aAuHAd/aAuHAd |
spring boot admin | http://ip:32700/login | cloud/cloud@monitor |
api gateway swagger | http://ip:32000/swagger-ui.html | swagger 聚合入口 |
api gateway | http://ip:32000 | 網(wǎng)關(guān)入口 |
在 Dashboard 上可以進(jìn)行很多操作抚岗,例如擴(kuò)容或杠、縮容,查看日志宣蔚,進(jìn)入/刪除 Pod向抢,編輯 YML 文件等等。留給你去探索胚委,這里不在詳細(xì)說明挟鸠。
由于部署的時(shí)候允許 Master 參與調(diào)度(taint 污點(diǎn)標(biāo)簽實(shí)現(xiàn)),所以會看到注冊上來的 Pod 網(wǎng)段有兩個(gè)篷扩。
在 Service 列表兄猩,可以看到 type 有兩種: ClusterIP(集群內(nèi)通信 IP) 和 NodePort(暴露外網(wǎng)端口),網(wǎng)關(guān) api-gateway 服務(wù)已經(jīng)通過 NodePort 方式暴露到了公網(wǎng) 32000 端口鉴未,所以你還是可以使用 Spring Cloud Gateway 作為微服務(wù)入口測試的枢冤。
另外,我在項(xiàng)目中提供的每個(gè)微服務(wù)的 Kubernetes YML 描述文件都定義如下了四個(gè)對象:
- Service 暴露服務(wù)铜秆,負(fù)載均衡淹真,服務(wù)發(fā)現(xiàn)
(注意:NodePort 端口范圍是 30000-32767)
- Deployment 控制循環(huán),滾動(dòng)更新
- ReplicaSet 副本個(gè)數(shù)连茧,應(yīng)用版本核蘸,版本回滾
- Pod 存活探針巍糯,就緒探針,最小調(diào)度單位
這些對象也是在我們引入 Istio 服務(wù)網(wǎng)格時(shí)所必須滿足的前提條件客扎,對于 Kubernetes 中 Pod祟峦、Service、ReplicaSet徙鱼、Deployment 這些基礎(chǔ)常用概念一定要了然于心宅楞,對其 YML 描述字段要非常熟悉,對它們之間的協(xié)作關(guān)系袱吆、實(shí)現(xiàn)原理也要有所了解厌衙。
下面介紹并部署 Ingress 對象來作為集群服務(wù)的訪問入口。
為了讓 Ingress 對象工作绞绒,集群必須有一個(gè)正在運(yùn)行的 Ingress Controller婶希。它有很多的第三方實(shí)現(xiàn),本節(jié)選用的是 Nginx 提供的實(shí)現(xiàn) Nginx Ingress Controller 來演示
- HAProxy Ingress Controller for Kubernetes
- Istio Ingress is an Istio based ingress controller
- Kong Ingress Controller for Kubernetes
- NGINX Ingress Controller for Kubernetes
Ingress 和 Ingress Controller 的區(qū)別:
-
Ingress
它是 Kubernetes 中的一個(gè) API 對象蓬衡,定義請求如何轉(zhuǎn)發(fā)到 Service 的規(guī)則喻杈。
-
Ingress Controller
它是反向代理的程序,會根據(jù) Ingress 對象制定的規(guī)則實(shí)現(xiàn)請求轉(zhuǎn)發(fā)撤蟆。
部署 Nginx Ingress Controller奕塑。
我們將官方提供的 ingress-nginx YML 文件下載到本地堂污,因?yàn)槠渲?ingress-nginx-controller Pod 的鏡像名稱有點(diǎn)問題家肯,需要手動(dòng)修改。(我在項(xiàng)目的根目錄下也放置了一份 ingress-nginx.yml
盟猖,你可以直接用)
curl -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.44.0/deploy/static/provider/cloud/deploy.yaml >> /opt/cloud/ingress-nginx.yml
將:
image: k8s.gcr.io/ingress-nginx/controller:v0.44.0@sha256:3dd0fac48073beaca2d67a78c746c7593f9c575168a17139a9955a82c63c4b9a
修改為:
image: registry.cn-shanghai.aliyuncs.com/11060/ingress-nginx-controller:v0.44.0
部署命令:kubectl apply -f /opt/cloud/ingress-nginx.yml
讨衣,執(zhí)行成功后登錄 Dashboard 可以看見 ingress-nginx 這個(gè) namespace 下的所有資源。
I0221 11:26:17.7630407 flags.go:208] "Watching for Ingress" class="nginx"
W0221 11:26:17.7630767 flags.go:213] Ingresses with an empty class will also be processed by this Ingress controller
-------------------------------------------------------------------------------
NGINX Ingress controller
Release: v0.44.0
Build: f802554ccfadf828f7eb6d3f9a9333686706d613
Repository: https://github.com/kubernetes/ingress-nginx
nginx version: nginx/1.19.6
-------------------------------------------------------------------------------
上面這個(gè)是 ingress-nginx-controller
Pod 啟動(dòng)的部分日志式镐,看下第一行的輸出反镇,默認(rèn)配置下它會監(jiān)視所有命名空間下的 Ingress 對象的創(chuàng)建和修改,可以通過 --watch-namespace
參數(shù)將作用域限制到特定的命名空間娘汞。配置入口在 Deployment 對象中:https://kubernetes.github.io/ingress-nginx/user-guide/cli-arguments/
args:
- /nginx-ingress-controller
- --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller
- --election-id=ingress-controller-leader
- --ingress-class=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-namespace=cloud
下面是 ingress-nginx.yml 中定義的 Service 對象歹茶,這個(gè) Service 的類型為 LoadBalancer,它會將所有攜帶 ingress-nginx 標(biāo)簽的 Pod 通過 80 和 433 端口暴露出去你弦,這樣我們就可以在集群外部訪問到這個(gè) Nginx 了惊豺。
# Source: ingress-nginx/templates/controller-service.yaml
apiVersion: v1
kind: Service
metadata:
annotations:
labels:
helm.sh/chart: ingress-nginx-3.23.0
......
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
type: LoadBalancer
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
- name: https
port: 443
protocol: TCP
targetPort: https
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
查看下 Service 向外部暴露的端口 HTTP:32475 HTTPS:31729
[root@k8s001 ~]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.99.90.115 <pending> 80:32475/TCP,443:31729/TCP 20m
部署成功后可以在瀏覽器中測試下這兩個(gè)端口,注意先在阿里云控制臺添加這兩個(gè)端口的安全組規(guī)則禽作。
下面部署 Ingress 對象尸昧,它是用來制定請求轉(zhuǎn)發(fā)的規(guī)則,指定需要暴露到集群外的服務(wù)旷偿,這個(gè)文件我也在項(xiàng)目的根目錄下:cloud-ingress.yml
烹俗。其中 rules 屬性在 Kubernetes 里叫作 IngressRule爆侣,它的 Key 是 host,要注意 host 的值必須是一個(gè)全限定域名(FQDN)幢妄,不能是 IP 地址兔仰,所以如果要測試的話,你需要有一個(gè)域名蕉鸳,并且確保已經(jīng)正確解析到了你的 ECS 上斋陪。
https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-rules
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: cloud
name: cloud-ingress
spec:
rules:
- host: viewhub.cn
http:
paths:
- path: /user
pathType: Prefix
backend:
service:
name: user-server
port:
number: 9097
- path: /auth
pathType: Prefix
backend:
service:
name: auth-server
port:
number: 9096
- path: /order
pathType: Prefix
backend:
service:
name: order-server
port:
number: 9099
當(dāng)我們訪問 viewhub.cn 域名的時(shí)候,實(shí)際上訪問到的就是這個(gè) Ingress 對象置吓,然后 Kubernetes 會根據(jù) path 字段的規(guī)則來對請求進(jìn)行下一步轉(zhuǎn)發(fā)无虚。這里你可以把一個(gè) Ingress 對象理解為 Nginx 反向代理的配置文件 nginx.conf,把 ingress-controller 理解為 Nginx衍锚。
執(zhí)行 kubectl apply -f /opt/cloud/cloud-ingress.yml
命令部署友题,Nginx Ingress Controller 會 watch 到 Ingress 對象的創(chuàng)建,然后根據(jù) ingress 對象中的規(guī)則來修改 nginx.conf 文件戴质,提供對應(yīng)的代理能力度宦。
在 Dashboard 界面可以清晰的看到 cloud-ingress 所代理的路徑,要轉(zhuǎn)發(fā)到的服務(wù)及服務(wù)端口告匠。
這個(gè) /
規(guī)則會匹配所有路徑戈抄,我將它路由到了 eureka 服務(wù),你可以通過 http://viewhub.cn:32475 訪問進(jìn)入 eureka 頁面后专。如果 Ingress 中的多條路徑會匹配到同一個(gè)請求划鸽,最長的匹配路徑優(yōu)先。
再調(diào)用一個(gè)接口測試下戚哎,可以看到 /user/init 路徑正確轉(zhuǎn)發(fā)到了 user-server 服務(wù)裸诽。
你還可以通過 Dashboard 或者 kubectl exec 命令進(jìn)入 ingress-nginx-controller 這個(gè) Pod,去看下的它的 nginx.conf 配置文件型凳,你就會非常清晰的認(rèn)識到它到底在做些什么丈冬。
通過上面的測試,可以看到 Nginx Ingress Controller 創(chuàng)建的 Nginx 負(fù)載均衡器甘畅,已經(jīng)成功的根據(jù) Ingress 對象制定的規(guī)則將請求轉(zhuǎn)發(fā)到了對應(yīng)的后端 Service埂蕊。
你應(yīng)該可以感受到,Ingress 的功能還是比較弱的疏唾, 它工作在七層僅適用于 HTTP 路由蓄氧,而且用法相對簡單,只能通過匹配有限的字段 host荸实、path匀们、port 來路由流量。下一節(jié)我們將演示在 Istio 體系如何統(tǒng)一管理入口流量准给,你會發(fā)現(xiàn)它更能勝任云服務(wù)網(wǎng)關(guān)這個(gè)角色泄朴。
~ 終 ~