目录
一、部署nginx容器
二、部署tomcat服务
三、使用nginx代理tomcat服务
四、测试
服务发现简介:
1、service是用于K8S的服务发现的重要组件,pod作为运行业务的承载方式,要想被客户端访问或者集群内部其它服务访问,就需要提供一个访问入口;
2、传统来说ip+端口是普适的访问方式,但是pod是一种动态的资源,它会因故障被重建或重启,因而pod ip会发生变化,所以使用ip作为pod的访问入口并不合适;而K8S是通过service来充当pod与访问端的中间代理,要访问pod首先访问pod对应的service,再由service代理到对应的pod
3、而pod采用了标签来代替ip作为唯一标识,以供service筛选。service对应的也有标签选择器用来筛选pod标签
4、 而service本身是ipvs规则,是由kube-porxy组件生成的,这个规则只要不删除就会一直存在,但是删除了service ip也会发生变化,这样一来客户端仍有无法访问到service ip的风险
5、因此K8S使用了DNS来记录service ip和service域名的记录,客户端使用域名就可以通过DNS中拿到对应的service ip了,而当service ip发生变化时,DNS也会动态的即使跟新到记录表中,这样即使service ip发生改变,仍然可以通过service的域名拿到对应的service ip,有了service ip就可以访问到Service 而后service代理到对应的pod上
service类型:(主要用两种)
1、clusterIP:
2、NodePort: 可以接入集群外部流量,在每个node节点监听一个和service定义的相同的端口,用于客户端的访问,把请求转发到对应的service,然后service再转发给pod; 用于将K8S服务暴露给K8S以外的客户端访问
注:serviceIP=clusterIP
NodePort 访问流程如下:
cluster_IP+端口-------->pod_IP+端口
上面的访问流程可以看出NodePort类型还是需要借助clusterIP才能把集群外的访问引入到集群内
3、何为无头服务?
service的不同模式都是在上一种模式的基础上增强版,nodePort就是在clusterIP的基础上新增了功能,并不是一种新的功能模式,因为nodePort模式下客户端访问过程中还是要经过clusterIP的,这意味着clusterIP是service最基本要件,但也可以把这个clusterIP移除掉,而一旦No cluster,就称为无头服务了,无头服务的主要作用在于可以把服务名称(service_name)直接解析到后端的podIP;而本来只能解析到serviceIP
NodePort 示例:
部署nginx和tomcat这两个前后端服务pod,通过NodePort类型service 相互调用
一、部署nginx容器
1、编写yaml文件
root@k8s-deploy:~# vim nginx.yaml
kind: Deployment
apiVersion: apps/v1 #可查询它的api版本 kubectl explain deployment.apiVersion
metadata: #定义pod元数据信息,可查询它的下级子字段kubectl explain deployment.metadata
labels: #定义deployment控制器标签
app: nginx-deployment-label #标签名称以键值形式定义,可以定义多个,这里标签是app值为nginx-deployment-label
name: nginx-deployment #deployment资源的名字
namespace: myserver #deployment所属的namespace,默认是defaule
spec: #定义Deployment中容器的详细信息,可通过kubectl explain deployment.spec查询
replicas: 1 #定义创建出pod的副本数,默认值是1个pod
selector: #定义标签选择器,它跟上面的Deployment标签不是一回事,它是找下面template中定义的labels标签
matchLabels: #定义匹配的标签,必须要设置
app: nginx-selector #匹配的目标标签,控制器会拿这个标签匹配下面的pod
template: #定义模板,用来描述需要创建的pod作用
metadata: #定义模板元数据
labels: #这个labels会继承给这个yaml文件Deployment控制器创建的所有pod
app: nginx-selector #这个labels的key是app,值是nginx-selector,它会继承给下面的pod,和上面matchLabels.app: nginx-selector一样
spec: #定义pod的详细信息
containers: #定义pod中容器列表,可以定义多个pod
- name: nginx-container #容器名称
image: nginx:1.20 #容器镜像
imagePullPolicy: Always #镜像拉取策略
ports: #定义容器端口列表
- containerPort: 80 #定义一个端口
protocol: TCP #定义协议
name: http #端口名称
- containerPort: 443
protocol: TCP
name: https
env: #给容器传递环境变量
- name: "password" #变量名称,必须引号引起来
value: "123" #上面变量的值
- name: "age"
value: "18"
---
kind: Service
apiVersion: v1
metadata:
name: nginx-service
labels:
app: nginx-service-label #service资源的标签
namespace: myserver #所在的命名空间,与上面控制器必须在同一个命名空间
spec:
type: NodePort #service类型是NodePort
ports: #定义访问端口,一个service可以定义多个端口的映射关系
- name: http #定义协议名称
port: 80 #定义service端口,它可以和pod,node端口都不同,它是K8S中一个独立子网
protocol: TCP #定义类型
targetPort: 80 #目标pod端口,当访问宿主机30004端口时就会转达到pod的80端口
nodePort: 30004 #手动指定node节点暴露的端口,如果没有指定端口,那service会随机分配一个端口
- name: https
port: 443
protocol: TCP
targetPort: 443
nodePort: 30443
selector:
app: nginx-selector #这个标签就是上面pod的标签,service通过这个标签来匹配对应的pod
2、创建资源
创建资源
# kubectl apply -f nginx.yaml
查看nginx pod已经启动
root@k8s-deploy:~# kubectl get pod -A | grep nginx
myserver nginx-deployment-766fc9dfdd-f488k 1/1 Running 0 8m11s
查看nginx-service已经创建
root@k8s-deploy:~# kubectl get svc -A | grep nginx-service
default nginx-service NodePort 10.100.57.113 <none> 80:30004/TCP,443:30443/TCP 2m11s
3、访问node节点的http协议的30004端口
因为service中定义了nodePort规则,因此要访问nginx容器的80端口,直接访问任意node节点的30004端口即可转发到nginx容器的80端口
二、部署tomcat服务
1、编写yaml文件
root@k8s-deploy:~# vim tomcat.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: tomcat-deployment
namespace: myserver
labels:
app: tomcat-deployment-label
spec:
replicas: 1
selector:
matchLabels:
app: tomcat-selector
template:
metadata:
labels:
app: tomcat-selector
spec:
containers:
- name: tomcat-container
image: tomcat:7.0.109-jdk8-openjdk
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
env:
- name: "password"
value: "123"
- name: "age"
value: "18"
---
kind: Service
apiVersion: v1
metadata:
name: tomcat-serivce
namespace: myserver
labels:
app: tomcat-service-label
spec:
type: NodePort #service有四种类型,默认是cluser ip
ports:
- name: http
port: 80
protocol: TCP
nodePort: 30005
targetPort: 8080
selector:
app: tomcat-selector
2、创建资源
root@k8s-deploy:~# kubectl apply -f tomcat.yaml
3、访问tomcat
可以访问下node节点的30005端口,报404是因为还没有页面,下面进入tomcat容器中手动创建一个页面
root@k8s-deploy:~# kubectl get pod -A | grep tomcat
myserver tomcat-deployment-5576d59694-rv2sb 1/1 Running 0 7m16s
进入容器
root@k8s-deploy:~# kubectl exec -it nginx-deployment-7d7bd78b5c-v9mjs bash -n myserver
root@tomcat-deployment-5576d59694-rv2sb:/usr/local/tomcat# cd webapps
root@tomcat-deployment-5576d59694-rv2sb:/usr/local/tomcat/webapps# mkdir myapp
root@tomcat-deployment-5576d59694-rv2sb:/usr/local/tomcat/webapps# echo "myapp web magedu n70" > myapp/index.jsp
而后再来访问这个页面就有内容了,说明现在tomcat服务是正常的
三、使用nginx代理tomcat服务
这个tomcat端口其实不是必须要暴露的,测试完后,我这里再把它注释掉,去掉之后就没有nodeport了,就是仅在K8S内部的一个cluser ip了 ,仅能在K8S内部访问,下面用nginx代理tomcat服务,实现在K8S内部两个服务之间通过service相互转发
1、注释
2、 注释后再执行下apply,可以看见tomcat-deployment是不变的,tomcat-serivce配置了
3、 查看tomcat service的名称,下面配置nginx代理tomcat文件要用
4、修改nginx容器的配置文件
下面用nginx作为代理访问tomcat,进入nginx容器中进行配置
root@k8s-deploy:~# kubectl get pod -A | grep nginx
myserver nginx-deployment-766fc9dfdd-f488k 1/1 Running 0 8m11s
进入nginx容器
root@k8s-deploy:~# kubectl exec -it nginx-deployment-766fc9dfdd-f488k bash -n myserver
root@nginx-deployment-766fc9dfdd-f488k:/etc/nginx# vim conf.d/default.conf
修改nginx容器的配置文件/etc/nginx/conf.d/default.conf (这是在nginx容器里配置的,配置如下图),添加完配置后nginx -s reload重置下再curl访问
全路径访问如下:
这里cluster.local是当时创建集群时候在hosts文件里定义的
可以看下当时定义的K8S集群域名
四、测试
访问nginx的30004端口,就可以代理到tomcat服务了
可以看下nginx的日志,每当请求/myapp/index.jsp文件就由nginx通过tomcat service转发给tomcat service后面的pod了
root@k8s-deploy:~# kubectl logs -f nginx-deployment-766fc9dfdd-nq4ck -n myserver
10.200.166.128 - - [18/Nov/2022:07:50:45 +0000] "GET /myapp/ HTTP/1.1" 200 21 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0" "-"
10.200.166.128 - - [18/Nov/2022:07:50:53 +0000] "GET /myapp/index.jsp HTTP/1.1" 200 21 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0" "-"
10.200.166.128 - - [18/Nov/2022:07:52:09 +0000] "GET /myapp/index.jsp HTTP/1.1" 200 21 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0" "-"
10.200.166.128 - - [18/Nov/2022:07:52:10 +0000] "GET /myapp/index.jsp HTTP/1.1" 200 21 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0" "-"
注意:
上面使用curl访问的是tomcat-service,是因为nginx和tomcat都在同一个namesapce中,所以可以之间访问名称简写
如果不在一个namespace中需要名字全称,如果不在一个namespace就需要把nginx容器里的配置文件修改 ,其中80端口可以不写,因为这里调用的是service,而tomcat service的端口定义的就是80
因为在tomcat.yaml文件中定义的service 端口是80,所以在nignx配置文件中调用这个端口,这个80端口会转给pod的8080端口
总结:
客户端访问node节点的30004端口,而后转发到nginx-service, 如果nginx-pod是多副本的,再由nginx-service根据算法转发给某个nginx-pod; 然后nginx-pod把请求转发给tomcat-service,最后再由tomcat-service根据算法转发给tomcat-pod进行处理