1.前言
service只能作用与网络模型中的四层,ingress可以作用于网络模型中的七层,Service是一种抽象,定义了一个逻辑上的一组Pod以及访问它们的策略。Service为Pod提供了一个稳定的IP地址和DNS名称,并通过标签选择器来定义需要暴露的Pod。Service可以通过Cluster IP、Node Port、Load Balancer和External Name等方式来提供服务,这取决于具体的部署需求
Ingress是在Kubernetes集群中暴露HTTP和HTTPS服务的API对象。它为集群中的服务提供外部访问,并提供负载均衡、SSL终止和基于名称的虚拟主机等功能。Ingress通过将流量路由到不同的后端Service来实现这些功能。Ingress需要一个Ingress Controller来实现其规则,这个控制器可以是Kubernetes自带的或者是第三方提供的
简单来说,Service用于在Kubernetes集群内部暴露服务,而Ingress则用于将服务暴露到集群外部,使得外部用户可以通过HTTP或HTTPS协议访问应用程序,相当于nginx的反向代理
2.更改kube-proxy代理
在开始之前,先把kube-proxy代理的模式改为ipvs模式
kubectl edit cm kube-proxy -n kube-system
再把所有kube-proxy的pod重启一下
kubectl delete pod -l k8s-app=kube-proxy -n kube-system
kubectl get pod -l k8s-app=kube-proxy -n kube-system
3.service
接下来简单的使用一下service的几种方式,这里就展示ClusterIP、NodePort这两种常用的方式
3.1ClusterIP
编辑yaml文件
vi deployment-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
replicas: 5
progressDeadlineSeconds: 600
minReadySeconds: 10
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: default
spec:
selector: #配置标签选择,选择符合该标签的pod
app: nginx
type: ClusterIP #配置service模式为ClusterIP
clusterIP: #可以指定ClusterIP地址,留空就会自动生成ClusterIP地址
ports:
- port: 80 #service服务的端口
targetPort: 80 #pod监听的端口
protocol: TCP #配置网络协议
执行yaml文件
kubectl create -f deployment-nginx.yaml
kubectl get service
kubectl describe service nginx
kubectl get pod -o wide -l app=nginx
可以看到service已经创建出来了,并且已经绑定了pod,通过service访问一下pod的端口服务看看效果
curl 10.98.144.122:80
可以看到能成功访问到pod的端口服务,使用ClusterIP方式只能在集群内部访问,集群外访问不了
以下再补充一下ClusterIP方式的一些知识
ipvsadm -Ln
通过ipvsadm命令可以看到我们使用的ClusterIP访问pod的方式为轮询,rr代表轮询模式,即每次请求都会按顺序顺延访问每个pod的服务 ,有些场景下我们可能会希望每个访问的ip,都能固定访问一个pod服务,而不是轮询每个pod,我们就可以在配置文件中引入一个sessionAffinity参数,接下来配置一下看看
vi deployment-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
replicas: 5
progressDeadlineSeconds: 600
minReadySeconds: 10
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: default
spec:
selector:
app: nginx
type: ClusterIP
clusterIP:
sessionAffinity: ClientIP #增加ClientIP参数值,使得访问的ip固定访问一个pod服务
ports:
- port: 80
targetPort: 80
protocol: TCP
执行一下yaml
kubectl create -f deployment-nginx.yaml
kubectl get service
kubectl get pod -o wide -l app=nginx
ipvsadm -Ln
从上图可以看到不在单单是显示rr轮询模式,可以更改nginx的页面内容去试一下,相同的ip访问的内容是固定的,因为我这边做过了试验,在这里就不展示了
3.2NodePort
编辑yaml文件
vi deployment-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
replicas: 5
progressDeadlineSeconds: 600
minReadySeconds: 10
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: default
spec:
selector:
app: nginx
type: NodePort #选择NodePort类型
clusterIP:
sessionAffinity: ClientIP
ports:
- port: 80
targetPort: 80
nodePort: 30001 #配置nodePort外部端口,不设置则随机分配
protocol: TCP
执行yaml
kubectl create -f deployment-nginx.yam
kubectl get service
kubectl get pod -o wide -l app=nginx
可以看到已经按要求创建出了service,现在来访问一下看看效果,我们直接用集群外的网络来访问看看
可以看到使用NodePort方式,可以在集群外部访问到pod端口服务
4.ingress
这里使用nginx作为Ingress Controller来实现ingress定义的规则,也可以使用haproxy等工具来实现,实际上工作流程就是,向ingress写入规则,ingress Controller将规则转化为nginx的规则,写入nginx配置中,以实现反向代理
4.1搭建ingress环境
这里我直接使用helm安装nginx ingress控制器
helm配置可以参考:k8s helm安装使用_Apex Predator的博客-CSDN博客
查找镜像源
helm search repo ingress
安装插件
helm install ingress bitnami/nginx-ingress-controller
helm list
状态为deployed就表示正常部署
查看一下pod,svc,deployment中的ingress服务
kubectl get pod,svc,deployment
可以看到都已经正常启动了,但是svc中的ingress-nginx-ingress-controller默认用的是LoadBalancer模式,需要修改为NodePort模式,上图中我已经修改过后的状态
修改一下svc的配置
kubectl edit svc service/ingress-nginx-ingress-controller
type: NodePort #将type项的LoadBalancer改为NodePort即可保存退出
再次查看svc
至此ingress环境已经部署好了
4.2使用ingress
编辑yaml文件
vi deployment-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
replicas: 5
progressDeadlineSeconds: 600
minReadySeconds: 10
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: default
spec:
selector:
app: nginx
type: ClusterIP
clusterIP:
ports:
- port: 80
targetPort: 80
protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress
namespace: default
spec:
rules: #配置代理规则
- host: nginx.apex.com #配置反向代理的域名
http:
paths:
- path: / #匹配路径,相当于nginx location,以下的pathType用于配置匹配规则
pathType: ImplementationSpecific #pathType 字段用于指定 Ingress 路由规则中的路径类型,pathType 字段有三个可选值,Exact表示 Ingress 规则中的路径必须与请求的路径完全匹配,Prefix表示 Ingress 规则中的路径必须是请求路径的前缀,ImplementationSpecific表示 Ingress 控制器可以自行决定路径类型
backend: #配置需要代理服务的参数
service:
name: nginx #配置需要代理的sevice服务的名称
port:
number: 80 #配置需要代理的service监听端口
ingressClassName: nginx #指定实现规则的应用类型,controller会将以上的规则转变为适合该应用的配置写入应用的配置文件中
我这边把deployment、service、ingress的yaml配置都写在了一个yaml文件上,现在来执行yaml看看效果
kubectl create -f deployment-nginx.yaml
kubectl get pod -l app=nginx
kubectl get ingress
可以看到pod、svc、ingress都已经正常运行,可以看到ingress监听的端口为80,因为代理的是http服务
编辑一下本机的hosts文件,使得域名能正常解析到服务主机上
vi /etc/hosts
10.1.60.119 nginx.apex.com #在末尾新增此条内容
查看ingress service服务端口,测试访问一下域名看是否能正常访问到pod中的服务
kubectl get svc
可以看到http服务使用31079端口,https服务使用31920端口
curl nginx.apex.com:31079
域名可以正常访问pod服务
接下来配置一下https服务
创建证书
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=BJ/L=BJ/O=nginx/CN=apex.com"
创建密钥
kubectl create secret tls tls-secret --key tls.key --cert tls.crt
编辑yaml文件
vi deployment-tomcat.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: tomcat
name: tomcat
namespace: default
spec:
replicas: 2
progressDeadlineSeconds: 600
minReadySeconds: 10
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
selector:
matchLabels:
app: tomcat
template:
metadata:
labels:
app: tomcat
spec:
containers:
- name: tomcat
image: tomcat
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: tomcat
namespace: default
spec:
selector:
app: tomcat
type: ClusterIP
clusterIP:
ports:
- port: 8080
targetPort: 8080
protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-tomcat
namespace: default
spec:
tls: #https服务配置项
- hosts:
- tomcat.apex.com #配置需要使用https服务的域名
secretName: tls-secret #配置创建的证书名称
rules:
- host: tomcat.apex.com
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: tomcat
port:
number: 8080
ingressClassName: nginx
执行一下yaml
kubectl create -f deployment-tomcat.yaml
kubectl get pod -l app=tomcat
kubectl get ingress
可以看到pod正常启动,ingress也正常创建好了,端口也显示监听80和443端口,即代理了http和https服务
也可以查看一下ingress的详细信息
kubectl describe ingress ingress-tomcat
看一下svc服务
可以看到创建的tomcat svc服务监听端口为配置的8080端口
现在来访问一下域名看看是否代理成功
curl --insecure https://tomcat.apex.com:31920
可以看到使用域名能正常访问到pod的服务
至此https配置完成