一.service
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将请求转发到的目的地;
1.概述
pod功能迭代时需要修改pod,pod每次重启IP都会变化,在生产环境中,从用户到宿主机,宿主机到pod这一整个访问流程都是事先写好的,一旦IP发生变化,就需要重新配置,就需要service来解决这个问题
pod与service通过标签关联起来
Kubernetes 中 Service 是 将运行在一个或一组 Pod 上的网络应用程序公开为网络服务的方法。Kubernetes 中 Service 的一个关键目标是让你无需修改现有应用以使用某种不熟悉的服务发现机制。 你可以在 Pod 集合中运行代码,无论该代码是为云原生环境设计的,还是被容器化的老应用。 你可以使用 Service 让一组 Pod 可在网络上访问,这样客户端就能与之交互。如果你使用 Deployment 来运行你的应用, Deployment 可以动态地创建和销毁 Pod。 在任何时刻,你都不知道有多少个这样的 Pod 正在工作以及它们健康与否; 你可能甚至不知道如何辨别健康的 Pod。 Kubernetes Pod 的创建和销毁是为了匹配集群的预期状态。 Pod 是临时资源(你不应该期待单个 Pod 既可靠又耐用)。每个 Pod 会获得属于自己的 IP 地址(Kubernetes 期待网络插件来保证这一点)。 对于集群中给定的某个 Deployment,这一刻运行的 Pod 集合可能不同于下一刻运行该应用的 Pod 集合。
2.cluster IP
当 Kubernetes 需要为 Service 分配虚拟 IP 地址时,该分配会通过以下两种方式之一进行:
动态分配
集群的控制面自动从所配置的 IP 范围内为
type: ClusterIP
选择一个空闲 IP 地址。静态分配
根据为 Service 所配置的 IP 范围,选定并设置你的 IP 地址。
在整个集群中,每个 Service 的
ClusterIP
都必须是唯一的。 尝试使用已分配的ClusterIP
创建 Service 将返回错误。
· 编辑service资源清单
[root@master service]# cat 01-service-clusterip.yaml
apiVersion: v1
kind: Service
metadata:name: svc-demo01
spec:#声明clusterip类型,不指定默认也是这个类型type: ClusterIP#指定pod的标签selector:test: test#指定service的ip地址clusterIP: 10.200.100.101#用户访问service时,访问的端口ports:#指定访问协议,若不指定协议,默认也是TCP- protocol: TCP#service的端口port: 80#pod的容器端口(目标端口)targetPort: 80
· 编辑pod资源清单
[root@master service]# cat pod-service.yaml
apiVersion: v1
kind: Pod
metadata:name: demoe00labels:test: test
spec:containers:- name: demo-nginximage: nginx:1.20.1-alpineports:- containerPort: 80
· 创建查看
[root@master service]# kubectl apply -f .
service/svc-demo01 created
pod/demoe00 created
[root@master service]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.200.0.1 <none> 443/TCP 6d20h
svc-demo01 ClusterIP 10.200.100.101 <none> 80/TCP 4s
[root@master service]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demoe00 1/1 Running 0 10s 10.100.1.40 worker1 <none> <none>
nginx-demo 1/1 Running 0 4d20h 10.100.2.49 worker2 <none> <none>
·测试访问:访问service设置的IP和pod节点IP 都可以访问到
[root@master service]# curl 10.200.100.101
[root@master service]# curl 10.100.1.40
3.nodeport
nodeport类型,就是clusterip类型的升级版,它可以使用宿主机的端口,映射到service开放的端口上,从而,使得用户访问宿主机,宿主机转发到service资源,进而访问到pod资源;
· 编辑service资源清单
[root@master service]# cat 02-service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:name: svc-demo02
spec:#声明nodePort类型type: NodePort#指定pod的标签selector:test: test#指定service的ip地址(在nodeport类型中可以不设置,会随机生成)clusterIP: 10.200.100.102#用户访问service时,访问的端口ports:#指定访问协议,若不指定协议,默认也是TCP- protocol: TCP#pod的容器端口(目标端口)port: 80#访问宿主机的哪个端口,可以转发访问到servicetargetPort: 80#注意,默认只能使用宿主机的30000-32767区间的端口号,可以放开限制nodePort: 30000
·编辑pod资源清单
[root@master service]# cat pod-service.yaml
apiVersion: v1
kind: Pod
metadata:name: demoe00labels:test: test
spec:containers:- name: demo-nginximage: nginx:1.20.1-alpineports:- containerPort: 80
·创建查看资源
[root@master service]# kubectl apply -f 02-service-nodeport.yaml
service/svc-demo02 created
[root@master service]# kubectl apply -f pod-service.yaml
pod/demoe00 created
[root@master service]# kubectl get svc,pods -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.200.0.1 <none> 443/TCP 6d21h <none>
service/svc-demo02 NodePort 10.200.100.102 <none> 80:30000/TCP 34s test=testNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/demoe00 1/1 Running 0 25s 10.100.2.51 worker2 <none> <none>
pod/nginx-demo 1/1 Running 0 4d20h 10.100.2.49 worker2 <none> <none>
·浏览器访问宿主机端口测试是否能够访问到容器
3.loadbalancer
日后我们使用云环境负载均衡器的时候,就将vip地址填写到这个类型之下,就可以实现云负载均衡访问svc访问pod
· 模拟宿主机的vip
模拟负载均衡器vip
[root@master service]# ifconfig eth0:1 10.0.0.88
[root@master service]# ip addr
· 编辑svc资源清单
[root@master service]# cat 03-service-load.yaml
apiVersion: v1
kind: Service
metadata:name: svc-demo03
spec:#声明LoadBalancer类型type: LoadBalancer#指定pod的标签selector:test: test#指定service的ip地址clusterIP: 10.200.100.103#用户访问service时,访问的端口ports:#指定访问协议,若不指定协议,默认也是TCP- protocol: TCP#pod的容器端口(目标端口)port: 80#访问宿主机的哪个端口,可以转发访问到servicetargetPort: 80#注意,默认只能使用宿主机的30000-32767区间的端口号,可以放开限制nodePort: 30000# 指定LoadBalancer云环境的负载均衡地址,要确保K8S集群能和负载均衡的IP地址进行通信!#用户通过vip:10.0.0.88就可以访问到svc资源了externalIPs:- 10.0.0.88
·编辑pod资源清单
[root@master service]# cat pod-service.yaml
apiVersion: v1
kind: Pod
metadata:name: demoe00labels:test: test
spec:containers:- name: demo-nginximage: nginx:1.20.1-alpineports:- containerPort: 80
·创建查看资源
[root@master service]# kubectl apply -f pod-service.yaml
pod/demoe00 created
[root@master service]# kubectl apply -f 03-service-load.yaml
service/svc-demo03 created
[root@master service]# kubectl get svc,pods -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.200.0.1 <none> 443/TCP 6d21h <none>
service/svc-demo03 LoadBalancer 10.200.100.103 10.0.0.88 80:30000/TCP 14s test=testNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/demoe00 1/1 Running 0 107s 10.100.1.41 worker1 <none> <none>
pod/nginx-demo 1/1 Running 0 4d21h 10.100.2.49 worker2 <none> <none>
·浏览器访问宿主机端口测试是否能够访问到容器
4.externalname
就是域名转发功能,就是做了一个重定向,用户访问svc就会直接访问到我们设置的重定向地址
· 编写svc资源清单
[root@master service]# cat 04-service-ex.yaml
apiVersion: v1
kind: Service
metadata:name: svc-demo04
spec:# svc类型type: ExternalName# 指定跳转到外部的域名地址externalName: www.baidu.com
·编辑pod资源清单
[root@master service]# cat pod-service.yaml
apiVersion: v1
kind: Pod
metadata:name: demoe00
spec:containers:- name: demo-nginximage: nginx:1.20.1-alpine
·创建查看资源
[root@master service]# kubectl apply -f pod-service.yaml
pod/demoe00 created
[root@master service]# kubectl apply -f 04-service-ex.yaml
service/svc-demo04 created
[root@master service]# kubectl get svc,pods -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.200.0.1 <none> 443/TCP 6d21h <none>
service/svc-demo04 ExternalName <none> www.baidu.com <none> 23s <none>NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/demoe00 1/1 Running 0 30s 10.100.2.52 worker2 <none> <none>
pod/nginx-demo 1/1 Running 0 4d21h 10.100.2.49 worker2 <none> <none>
· 进入pod查看dns解析地址
[root@master service]# kubectl exec demoe00 -it -- sh
/ # cat /etc/resolv.conf
nameserver 10.200.0.10
5.nodeport的端口范围设置和svc的endpoint列表
svc资源nodeport类型中,宿主机端口映射的范围必须在30000-32767之间,否则会报错
这个范围是可以修改的;只需要进入到静态pod目录中,找到kube-apiserver的pod资源,进入添加一条命令【- --service-node-port-range=3000-50000】
添加后宿主机端口映射就变成了3000-50000了
每个Service都有一个相应的Endpoint。当Service被创建时,K8s会自动创建对应的Endpoint,并将Service选择的Pod的IP地址和端口号添加到Endpoint中。这种关系保证了Service与Pod之间的正确通信。
在Service和Endpoint之间的关系中,Service充当了一种抽象,为应用程序提供了一个稳定的入口点,而Endpoint则提供了Service后端的真实网络终端。这种分离使得用户能够更加灵活地管理和维护后端Pod的变化,而不需要改变Service的定义。
·修改apiservice的宿主机映射端口范围
[root@master 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:6443creationTimestamp: nulllabels:component: kube-apiservertier: control-planename: kube-apiservernamespace: kube-system
spec:containers:- command:......- --service-node-port-range=3000-50000- --advertise-address=10.0.0.231
......
·创建svc测试能否实现宿主机端口范围的映射
[root@master service]# cat 05-svc-endpoint.yaml
apiVersion: v1
kind: Service
metadata:name: demo000
spec:type: NodePortselector:test: testclusterIP: 10.200.1.104ports:- protocol: TCPport: 88targetPort: 99nodePort: 8080
[root@master service]# kubectl apply -f 05-svc-endpoint.yaml
service/demo000 created
·查看svc的详细信息
[root@master service]# kubectl describe svc demo000
Name: demo000
Namespace: default
Labels: <none>
Annotations: <none>
Selector: test=test
Type: NodePort
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.200.1.104
IPs: 10.200.1.104
Port: <unset> 88/TCP
TargetPort: 99/TCP
NodePort: <unset> 8080/TCP
Endpoints: <none>
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
·创建查看pod
[root@master service]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:name: demo909labels:test: test
spec:containers:- name: c1image: nginx:1.20.1-alpineports:- containerPort: 99
[root@master service]# kubectl apply -f pod.yaml
pod/demo909 created
·再次查看svc的详细信息
[root@master service]# kubectl describe svc demo000
Name: demo000
Namespace: default
Labels: <none>
Annotations: <none>
Selector: test=test
Type: NodePort
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.200.1.104
IPs: 10.200.1.104
Port: <unset> 88/TCP
TargetPort: 99/TCP
NodePort: <unset> 8080/TCP
Endpoints: 10.100.2.54:99
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
6.service中endpoint列表关联外部服务
·编辑svc资源清单
[root@master service]# cat svc.yaml
apiVersion: v1
kind: Service
metadata:name: svc01
spec:ports:- port: 888
·查看资源
[root@master service]# kubectl describe svc svc01
可以看到endpoint列表中什么都没有,也就是说,现在访问svc资源,什么都访问不到;我们还记得上面说的,svc资源是通过“标签选择”来将pod提那家到svc的endpoint列表中的,那么我们如何将k8s集群外部的容器添加到endpoint列表中纳?
举例:在生产环境中,我们的数据库服务,都是常年运行的历史性业务服务,当企业的应用上k8s时,数据库的迁移工作非常的繁琐,所以,如果能将外部的SQL服务,提那家到svc资源的endpoint列表中,就节省了数据库迁移k8s的繁杂工作
·svc资源与endpoint资源关联
endpoint本质上也是一个单独的资源,只是在我们创建svc资源的时候,系统自动给我们创建的;
svc资源与endpoint资源是通过元数据(metadata中的name)名称进行关联的,只要endpoint资源的名称与svc资源的名称相同,则,endpoint资源的服务IP就会出现在svc资源的endpoint列表中,即关联成功;
·k8s集群外部拉取一个mysql服务容器
找一个k8s集群之外的虚拟机
docker run --name=demoo-mysql \-p 13306:3306 -d \-e MYSQL_ALLOW_EMPTY_PASSWORD=yes \-e MYSQL_DATABASE=wordpress \-e MYSQL_USER=admin \-e MYSQL_PASSWORD=demoo \--restart always \mysql:8.0 \--default-authentication-plugin=mysql_native_password \--character-set-server=utf8 \--collation-server=utf8_bin
·测试登录mysql容器和添加测试数据
docker exec -it demoo-mysql mysql -u admin -pdemoo
·k8s集群中创建endpoint资源
[root@master service]# cat endpoint.yaml
apiVersion: v1
kind: Endpoints
metadata:name: svc01
subsets:
#指定外部endpoints的宿主机ip
- addresses:- ip: 10.0.0.230ports:- port: 13306
·再次查看svc资源
发现endpoints列表中,出现了外部服务的ip,端口
[root@master service]# kubectl describe svc svc01
7.wordpress案例
用户通过访问宿主机,转发到wordpress服务pod容器中,wordpress通过svc资源,访问到k8s外部数据库服务实现数据存储于查询
· 创建wordpress的pod和svc资源
[root@master service]# cat wp-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: wp-podlabels: testa: testa
spec:containers:- name: wp-c1image: wordpress:latestports:- containerPort: 80env:- name: WORDPRESS_DB_HOST#外部mysql服务的svc资源名称及端口;value: svc01:888- name: WORDPRESS_DB_USERvalue: admin- name: WORDPRESS_DB_PASSWORDvalue: demoo
---apiVersion: v1
kind: Service
metadata:name: wp-svc
spec:type: NodePortselector:testa: testaports:- port: 80targetPort: 80nodePort: 30090
· 浏览器访问测试