一、service资源概述
每当我们企业的业务pod迭代功能的时候,都会修改pod,修改后重新启动pod,ip就会变化,那么在生产环境当中,从用户到宿主机、从宿主机到pod,这一个访问流程,都是事先写好的,一旦pod修改后,ip产生变化,就需要重新配置,因此,k8s提供了service资源用于解决这一问题;
二、service资源类型
创建一个工作目录
[root@k8s231 pod]# mkdir -pv /xinjizhiwa/service [root@k8s231 pod]# cd /xinjizhiwa/service
1,service的cluster IP类型
· 编辑service资源清单
[root@k8s231 service]# cat 01-service-clusterip.yaml apiVersion: v1 kind: Service metadata: name: svc-01 spec: #声明clusterip类型,不指定默认也是这个类型; type: ClusterIP #指定pod的标签 selector: k8s: xinjizhiwa #指定service的ip地址 clusterIP: 10.200.100.100 #用户访问service时,访问哪个端口? ports: #指定访问协议,若不指定协议,默认也是TCP - protocol: TCP #service的端口 port: 80 #pod的容器端口(目标端口) targetPort: 80
· 编辑pod资源清单
[root@k8s231 service]# cat pod.yaml apiVersion: v1 kind: Pod metadata: name: p5 labels: k8s: xinjizhiwa spec: containers: - name: c1 image: nginx:1.20.1-alpine ports: - containerPort: 80
· 创建资源
[root@k8s231 service]# kubectl apply -f .
· 测试访问service和pod资源看是否都能访问到容器
2,service的nodeport类型
nodeport类型,就是clusterip类型的升级版,它可以使用宿主机的端口,映射到service开放的端口上,从而,使得用户访问宿主机,宿主机转发到service资源,进而访问到pod资源;
· 编辑service资源清单
[root@k8s231 service]# cat 01-service-clusterip.yaml apiVersion: v1 kind: Service metadata: name: svc-02 spec: #声明nodePort类型; type: NodePort #指定pod的标签 selector: k8s: xinjizhiwa #指定service的ip地址(在nodeport类型中可以不设置,会随机生成) clusterIP: 10.200.100.101 #用户访问service时,访问哪个端口? ports: #指定访问协议,若不指定协议,默认也是TCP - protocol: TCP #service的端口 port: 80 #pod的容器端口(目标端口) targetPort: 80 #访问宿主机的哪个端口,可以转发访问到service? #注意,默认只能使用宿主机的30000-32767区间的端口号(可以放开限制,之后再说); nodePort: 30000
· 创建svc资源
[root@k8s231 service]# kubectl apply -f 01-service-clusterip.yaml
· 浏览器访问宿主机端口测试是否能够访问到容器
3,service的loadbalancer类型(了解即可)
日后我们使用云环境负载均衡器的时候,就将vip地址填写到这个类型之下,就可以实现云负载均衡访问svc访问pod;
· 模拟宿主机的vip
也就是说,模拟负载均衡器(模拟例如keepalive的bip地址)vip;
[root@k8s231 service]# ifconfig eth0:1 10.0.0.88
· 编辑svc资源清单
[root@k8s231 service]# vim 03-service-loadbalancer.yaml
kind: Service apiVersion: v1 metadata: name: svc-loadbalancer spec: # 指定service类型为LoadBalancer,注意,一般用于云环境 type: LoadBalancer selector: k8s: xinjizhiwa ports: - protocol: TCP port: 80 targetPort: 80 # 注意,将来这个nodeProt也对应的是云环境负载均衡的地址 nodePort: 30001 # 指定LoadBalancer云环境的负载均衡地址,要确保K8S集群能和负载均衡的IP地址进行通信! #用户通过vip:10.0.0.88就可以访问到svc资源了; externalIPs: - 10.0.0.88
· 创建svc资源
[root@k8s231 service]# kubectl apply -f 03-service-loadbalancer.yaml
· 宿主机浏览器访问
4,service的externalname类型(了解即可)
就是域名转发功能,就是做了一个跳转,将来用户访问svc就会直接访问到我们设置的挑战的地址上,写上“百度”,就跳转到“百度”。
· 编写svc资源清单
[root@k8s231 service]# vim 06-svc-ex.yaml
apiVersion: v1 kind: Service metadata: name: svc-externalname spec: # svc类型 type: ExternalName # 指定跳转到外部的域名地址 externalName: www.baidu.com
· 创建svc资源
[root@k8s231 service]# kubectl apply -f 06-svc-ex.yaml
· 随便创建一个pod查看其dns解析地址
[root@k8s231 service]# vim 02-pod-nginx.yaml
apiVersion: v1 kind: Pod metadata: name: p1 spec: containers: - name: c1 image: nginx:1.20.1-alpine
· 进入pod查看dns解析地址
[root@k8s231 service]# kubectl exec p1 -it -- sh
/ # cat /etc/resolv.conf nameserver 10.200.0.10 search default.svc.xinjizhiwa.com svc.xinjizhiwa.com xinjizhiwa.com
· 测试访问
[root@k8s231 ~]# dig @10.200.0.10 svc-externalname.default.svc.xinjizhiwa.com +short www.baidu.com. www.a.shifen.com. 110.242.68.3 110.242.68.4
三、nodeport的端口范围设置和svc的endpoint列表
还记得在svc资源nodeport类型中,宿主机端口映射的范围必须在30000-32767之间,否则会报错;
但是,这个范围是可以修改的;只需要进入到静态pod目录中,找到kube-apiserver的pod资源,进入添加一条命令【- --service-node-port-range=3000-50000】;
提那家完毕这个命令后,宿主机端口映射就变成了3000-50000了;
1,修改apiservice的宿主机映射端口范围
[root@k8s231 service]# vim /etc/kubernetes/manifests/kube-apiserver.yaml
apiVersion: v1 kind: Pod metadata: annotations: kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 10.0.0.231:6443 creationTimestamp: null labels: component: kube-apiserver tier: control-plane name: kube-apiserver namespace: kube-system spec: containers: - command: ......
#就是这一条命令;
- --service-node-port-range=3000-50000 - --advertise-address=10.0.0.231 ......
2,创建svc测试能否实现宿主机端口范围的映射
[root@k8s231 service]# cat 06-svc-ex.yaml apiVersion: v1 kind: Service metadata: name: svc-externalname spec: type: NodePort selector: k8s: xinjizhiwa clusterIP: 10.200.1.100 ports: - protocol: TCP port: 88 targetPort: 99 nodePort: 8080
3,查看svc的详细信息
[root@k8s231 service]# kubectl describe svc svc-externalname Name: svc-externalname Namespace: default Labels:
#还没有匹配到pod,所以Endpoints是none,匹配到的话,就会显示pod的ip地址 Endpoints:
4,创建pod
[root@k8s231 service]# vim pod.yaml
apiVersion: v1 kind: Pod metadata: name: p7 labels: k8s: xinjizhiwa spec: containers: - name: c1 image: nginx:1.20.1-alpine ports: - containerPort: 99
[root@k8s231 service]# kubectl apply -f pod.yaml pod/p7 created
5,再次查看svc的详细信息
[root@k8s231 service]# kubectl describe svc svc-externalname
四、svc小结(重点)
1,service资源的四种类型:
· ClusterIP:给svc资源一个固定的IP地址,默认的类型;
· NodePort:在ClusterIP基础上,映射到宿主机(物理机)的端口号,默认是30000-32767可修改;
· LoadBalancer:可以添加云环境的负载均衡VIP地址和负载均衡器的宿主机端口号,用户通过访问VIP+负载均衡器的端口访问到svc资源,进而访问到pod==容器==服务中;
· ExternalName:类似于HTTP请求的302/301跳转,可以将访问svc的请求转发到指定的地址上;主要是转发功能;
2,修改svc的NodePort类型中宿主机映射端口的范围
默认是30000-32767,可以通过静态pod目录下的kube-apiserver.yaml的pod资源清单中加上一条命令,来设置宿主机的映射端口范围;
3,svc的endpoint列表
用户通过访问SVC资源,进而将请求转发到endpoint列表中的pod中,endpoint列表,就是svc将请求转发到的目的地;
五、service资源中endpoint列表关联外部服务
1,创建一个svc资源
· 编辑资源清单
[root@k8s231 endpoint]# vim svc.yaml
apiVersion: v1 kind: Service metadata: name: svc01 spec: ports: - port: 888
· 创建svc资源
[root@k8s231 endpoint]# kubectl apply -f svc.yaml
· 查看svc资源
[root@k8s231 endpoint]# kubectl describe svc svc01
可以看到endpoint列表中什么都没有,也就是说,现在访问svc资源,什么都访问不到;我们还记得上面说的,svc资源是通过“标签选择”来将pod提那家到svc的endpoint列表中的,那么我们如何将k8s集群外部的容器添加到endpoint列表中纳?
举例:在生产环境中,我们的数据库服务,都是常年运行的历史性业务服务,当企业的应用上k8s时,数据库的迁移工作非常的繁琐,所以,如果能将外部的SQL服务,提那家到svc资源的endpoint列表中,就节省了数据库迁移k8s的繁杂工作;
2,svc资源与endpoint资源关联
对,你看的没错,endpoint本质上也是一个单独的资源,只是在我们创建svc资源的时候,系统自动给我们创建的;
svc资源与endpoint资源是通过元数据(metadata中的)名称,进行关联的,只要endpoint资源的名称与svc资源的名称相同,则,endpoint资源的服务IP就会出现在svc资源的endpoint列表中,即关联成功;
· k8s集群外部拉取一个mysql服务容器
随便找一个k8s集群之外的虚拟机,本次我们拿harbor虚拟机做演示;
[root@harbor ~]# docker run --name=xinjizhiwa-mysql \ -p 13306:3306 -d \ -e MYSQL_ALLOW_EMPTY_PASSWORD=yes \ -e MYSQL_DATABASE=wordpress \ -e MYSQL_USER=admin \ -e MYSQL_PASSWORD=xinjizhiwa \ --restart always \ mysql:8.0 \ --default-authentication-plugin=mysql_native_password \ --character-set-server=utf8 \ --collation-server=utf8_bin
· 测试登录mysql容器和添加测试数据
[root@harbor ~]# docker exec -it xinjizhiwa-mysql mysql -u admin -pxinjizhiwa ..............
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | wordpress | +--------------------+ ..............
mysql> show tables from wordpress;
· k8s集群中创建endpoint资源
[root@k8s231 endpoint]# vim endpoint.yaml
apiVersion: v1 kind: Endpoints metadata: name: svc01 subsets: #指定外部endpoints的宿主机ip - addresses: - ip: 10.0.0.230 ports: - port: 13306
[root@k8s231 endpoint]# kubectl apply -f endpoint.yaml
此时再次查看svc资源,发现endpoints列表中,出现了外部服务的ip+端口;
我们、成功了;
六、案例:wordpress博客案例
提醒,上述内容中,我们已经有了mysql,那么接下来,我们就搭建一套简单的架构,用户通过访问宿主机,转发到wordpress服务pod容器中,wordpress通过svc资源,访问到k8s外部数据库服务实现数据存储于查询;
· 创建wordpress的pod和svc资源
[root@k8s231 endpoint]# cat wp-pod.yaml apiVersion: v1 kind: Pod metadata: name: wp-pod labels: k8s: xinjizhiwa spec: containers: - name: wp-c1 image: wordpress:latest ports: - containerPort: 80 env: - name: WORDPRESS_DB_HOST #外部mysql服务的svc资源名称及端口; value: svc01:888 - name: WORDPRESS_DB_USER value: admin - name: WORDPRESS_DB_PASSWORD value: xinjizhiwa ---
apiVersion: v1 kind: Service metadata: name: wp-svc spec: type: NodePort selector: k8s: xinjizhiwa ports: - port: 80 targetPort: 80 nodePort: 30080
[root@k8s231 endpoint]# kubectl apply -f wp-pod.yaml
· 浏览器访问测试
可见访问成功,至此service资源就先告一段落;
推荐阅读
发表评论