上篇文章介绍service时有说了暴露了service对外的三种方式ClusterIP、NodePort与LoadBalance,这几种方式都是在service的维度提供的,service的作用体现在两个方面,对集群内部,它不断跟踪pod的变化,更新endpoint中对应pod的对象,提供了ip不断变化的pod的服务发现机制,对集群外部,他类似负载均衡器,可以在集群内外部对pod进行访问。但是,单独用service暴露服务的方式,在实际生产环境中不太合适:
ClusterIP的方式只能在集群内部访问。
NodePort方式的话,测试环境使用还行,当有几十上百的服务在集群中运行时,NodePort的端口管理是灾难。
LoadBalance方式受限于云平台,且通常在云平台部署SLB还需要额外的费用。
那除了这种方法,是否还有其他更方便的方式呢?当然是有的,k8s还提供了一种集群维度暴露服务的方式,也就是ingress。ingress可以简单理解为service的service,他通过独立的ingress对象来制定请求转发的规则,把请求路由到一个或多个service中。这样就把服务与请求规则解耦了,可以从业务维度统一考虑业务的暴露,而不用为每个service单独考虑。
举个例子,可以通过一个ingress对象来实现图中的请求转发:
ingress规则是很灵活的,可以根据不同域名、不同path转发请求到不同的service,并且支持https/http。
ingress的组成:
ingress由两部分组成,ingress控制器和ingress,简单的抽象理解就是ingress控制器就是一个nginx服务,而ingress就是nginx的配置文件
ingress控制器:
实际负责实现ingress规则的组件
ingress:
K8S中的资源对象,用于管理集群外部到集群内部服务的流量路由。它定义了如何将外部流量路由到集群内的服务。
ingress的安装演示:
上面说了这么多,那实际安装一个ingress来演示
1.ingress的版本选择
2.下载对应版本
3.修改配置文件
3.1修改镜像地址
将所有的registry.k8s.io 修改为k8s.m.daocloud.io
3.2 修改Deployment 为DaemonSet
通过之前的学习,我们知道这是为了让每个node都能对外提供服务,同时注销掉strategy,因为daemonset没有这些。
3.3新增一行hostNetwork: true
添加该字段让docker使用物理机网络,在物理机暴露服务端口(80),注意物理机80端口提前不能被占用
3.4 修改dnsPolicy: ClusterFirst为 dnsPolicy: ClusterFirstWithHostNet
使用hostNetwork后容器会使用物理机网络包括DNS,会无法解析内部service,使用此参数让容器使用K8S的DNS
4.安装ingress
kubectl apply -f deploy.yaml
在创建了一些列的对象后,通过查看对应ingress这个namespace下的pod,看到安装了一个nginx-controller的pod 和2个admission的job
# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-925gj 0/1 Completed 0 84s
ingress-nginx-admission-patch-z2rpd 0/1 Completed 1 84s
ingress-nginx-controller-7974db866b-rpz4q 1/1 Running 0 84s
再查看下ingress-nginx这个namespace下的svc
# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.10.130.196 <none> 80:11604/TCP,443:13703/TCP 35m
ingress-nginx-controller-admission ClusterIP 10.10.247.32 <none> 443/TCP 35m
看到启动了一个NodePort类型的svc,名为ingress-nginx-controller,对外暴露的端口为11604-->80,13703-->443. 这2个是随机端口。请记住这2个对外的NodePort端口。
5.创建ingress的配置并应用
下文配置是在网上看到觉得写的挺好的,拿来直接用
# cat ingree_demo.yaml
# 部署3个nginx实例
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx-pod
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: m.daocloud.io/docker.io/nginx
ports:
- containerPort: 80
---
# 部署3个tomcat实例
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat-deployment
spec:
replicas: 3
selector:
matchLabels:
app: tomcat-pod
template:
metadata:
labels:
app: tomcat-pod
spec:
containers:
- name: tomcat
image: m.daocloud.io/docker.io/tomcat
ports:
- containerPort: 8080
---
# 部署nginx的Service
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx-pod
type: ClusterIP
ports:
- port: 80
targetPort: 80
---
# 部署tomcat的Service
apiVersion: v1
kind: Service
metadata:
name: tomcat-service
spec:
selector:
app: tomcat-pod
type: ClusterIP
ports:
- port: 8080
targetPort: 8080
---
# 创建ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-http
annotations: # 注意要开启这两行
kubernetes.io/ingress.class: "nginx"
spec:
# 上面的IngressClass名称
ingressClassName: "nginx"
rules:
# 域名,稍后要通过这个域名访问服务
- host: nginx.k8s.com
http:
paths:
# 路径,访问域名时后面添加的路径
- path: /
pathType: Prefix
backend:
# 要代理的服务和服务的端口
service:
name: nginx-service
port:
number: 80
- host: tomcat.k8s.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: tomcat-service
port:
number: 8080
# kubectl apply -f ingree_demo.yaml
deployment.apps/nginx-deployment created
deployment.apps/tomcat-deployment created
service/nginx-service created
service/tomcat-service created
ingress.networking.k8s.io/ingress-http created
6.查看pod和ingress对象
通过查看得知,创建了3个tomcat的pod和3个nginx的pod;创建了了1个tomcat的service和1个nginx的service;创建了一个ingress,里面包含2个域名nginx.k8s.com,tomcat.k8s.com
# kubectl get pod,svc,ingress
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-7d49b7f58-djkcj 1/1 Running 0 95s
pod/nginx-deployment-7d49b7f58-l9xlz 1/1 Running 0 95s
pod/nginx-deployment-7d49b7f58-wmpwd 1/1 Running 0 95s
pod/tomcat-deployment-9ddfdb848-4v5sx 1/1 Running 0 95s
pod/tomcat-deployment-9ddfdb848-t9jpq 1/1 Running 0 95s
pod/tomcat-deployment-9ddfdb848-vhd9n 1/1 Running 0 95s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.10.0.1 <none> 443/TCP 40d
service/nginx-service ClusterIP 10.10.81.35 <none> 80/TCP 95s
service/tomcat-service ClusterIP 10.10.3.65 <none> 8080/TCP 95s
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/ingress-http nginx nginx.k8s.com,tomcat.k8s.com 172.21.176.3 80 95s
通过kubectl describe ingress ingress-http ,可以看出来流量转发的走向
访问nginx.k8s.com/ --> service服务(nginx-service:80) --> 后端pod (10.20.213.52:80,10.20.213.56:80,10.20.213.57:80)
访问tomcat.k8s.com/ --> service服务(tomcat-service:8080) --> 后端pod (10.20.213.44:8080,10.20.213.45:8080,10.20.213.58:8080)
# kubectl describe ingress ingress-http
Name: ingress-http
Labels: <none>
Namespace: default
Address: 172.21.176.3
Ingress Class: nginx
Default backend: <default>
Rules:
Host Path Backends
---- ---- --------
nginx.k8s.com
/ nginx-service:80 (10.20.213.52:80,10.20.213.56:80,10.20.213.57:80)
tomcat.k8s.com
/ tomcat-service:8080 (10.20.213.44:8080,10.20.213.45:8080,10.20.213.58:8080)
Annotations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 10m (x2 over 10m) nginx-ingress-controller Scheduled for sync
7.访问测试
通过修改host的方式,将nginx.k8s.com 和 tomcat.k8s.com 域名解析到任意Node的公网IP。然后通过web去访问测试
# ping nginx.k8s.com
PING nginx.k8s.com (172.21.176.3) 56(84) bytes of data.
64 bytes from k8s-master 172.21.176.3): icmp_seq=1 ttl=64 time=1.54 ms
root@k8s-master:~# curl nginx.k8s.com:11604
<!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>
<body>
<h1>Welcome to nginx!</h1>
....
root@k8s-master:~# ping tomcat.k8s.com
PING tomcat.k8s.com (172.21.176.3) 56(84) bytes of data.
64 bytes from ht.prod.k8s001-local.wh (172.21.176.3): icmp_seq=1 ttl=64 time=0.310 ms
# 通过nodeport端口访问
root@k8s-master:~# curl tomcat.k8s.com:11604
<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found
.....
# 通过ingress 80端口访问
root@k8s-master:~# curl nginx.k8s.com
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
......
web页面打开测试