kubernetes核心概念 Service
kubernetes核心概念 Service
总结:
- Service类型决定了客户访问Service的方法
- Kube-proxy工作模式是service实现代理时的底层实现方式
- service作用
使用kubernetes集群运行工作负载时,由于Pod经常处于用后即焚状态,Pod经常被重新生成,因此Pod对应的IP地址也会经常变化,导致无法直接访问Pod提供的服务,
Kubernetes中使用了Service来解决这一问题,即在Pod前面使用Service对Pod进行代理,无论Pod怎样变化 ,只要有Label,就可以让Service能够联系上Pod,把PodIP地址添加到Service对应的端点列表(Endpoints)实现对Pod IP跟踪,进而实现通过Service访问Pod目的。
- 通过service为pod客户端提供访问pod方法,即客户端访问pod入口
- 通过标签动态感知pod IP地址变化等
- 防止pod失联
- 定义访问pod访问策略
- 通过label-selector相关联
- 通过Service实现Pod的负载均衡(TCP/UDP 4层)
- 底层实现由kube-proxy通过userspace、iptables、ipvs三种代理模式完成
举例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx1
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.20
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: test-svc
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 1000
targetPort: 80
nodePort: 32034
- kube-proxy三种代理模式(service的实现方式)
- 中的 kube-proxy 是一个网络代理,负责为集群中的服务提供网络转发。
- userspace、iptables 和 ipvs。下面用通俗的例子来解释这三种模式。
- Userspace 模式
- kube-proxy)负责把你的订单(网络请求)交给厨师(后端 Pod)。服务员需要亲自跑到厨房,把订单交给厨师,然后再把做好的菜端给你。这个过程比较慢,因为服务员需要来回跑动。
- userspace 模式下,kube-proxy 在用户空间处理网络请求,数据包需要从内核空间传到用户空间,再由 kube-proxy 转发到后端 Pod。这种模式效率较低,因为数据包需要在用户空间和内核空间之间来回传递。

- iptables 模式
- iptables)。你点餐后,订单通过传送带直接送到厨师那里,厨师做好菜后也通过传送带直接送到你桌上。服务员只需要确保传送带正常工作。
- iptables 模式下,kube-proxy 通过配置 iptables 规则来实现网络转发。数据包直接在内核空间处理,不需要经过用户空间,效率更高。kube-proxy 只需要负责更新 iptables 规则,不需要亲自处理每个数据包。

- ipvs 模式
- ipvs)。这个系统可以根据厨师的工作负载,自动把订单分配给最空闲的厨师,确保每道菜都能快速做好并送到你桌上。
- ipvs 模式下,kube-proxy 使用 Linux 内核的 IP Virtual Server(IPVS)功能来实现负载均衡。IPVS 提供了更高效的负载均衡算法,能够根据后端 Pod 的负载情况动态调整流量分配。这种模式性能最好,适合大规模集群。

- Userspace 模式:服务员亲自跑腿,效率低。
- iptables 模式:使用传送带自动送餐,效率较高。
- ipvs 模式:引入智能调度系统,效率最高,适合大规模集群。
- iptables 和 ipvs 是更常用的模式,尤其是 ipvs,因为它提供了更好的性能和可扩展性。
注:使用iptables与ipvs时机:
1.10版本之前使用iptables(1.1版本之前使用UserSpace进行转发)
1.11版本之后同时支持iptables与ipvs,默认使用ipvs,如果ipvs模块没有加载时,会自动降级至iptables
修改kube-proxy的工作模式
# kubectl -n kube-system describe cm kube-proxy | grep mode # 查看configmap
mode: ""
# kubectl -n kube-system edit cm kube-proxy # 修改configmap
mode: "ipvs"
# kubectl -n kube-system rollout restart daemonset kube-proxy # 重启damonset控制器
- service类型
Service类型决定了访问Service的方法
3.1 service类型
- ClusterIP
- 默认,分配一个集群内部可以访问的虚拟IP
- NodePort
- 在每个Node上分配一个端口作为外部访问入口
- nodePort端口范围为:30000-32767
- LoadBalancer
- 工作在特定的Cloud Provider上,例如Google Cloud,AWS,OpenStack
ExternalName表示把集群外部的服务引入到集群内部中来,即实现了集群内部pod和集群外部的服务进行通信
3.2 Service参数
- port :访问service使用的端口
- targetPort :Pod中容器暴露端口
- nodePort: 通过Node实现外网用户访问k8s集群内service的端口 (30000-32767)
Service的创建在工作中有两种方式:
一是命令行创建
二是通过资源清单文件YAML文件创建。
4.1 ClusterIP分类
ClusterIP根据是否生成ClusterIP又可分为普通Service和Headless Service
Service两类:
- 普通Service:
为Kubernetes的Service分配一个集群内部可访问的固定虚拟IP(Cluster IP), 实现集群内的访问。
- Headless Service(无头服务,无群集ip):
该服务不会分配Cluster IP, 也不通过kube-proxy做反向代理和负载均衡。而是通过DNS提供稳定的网络ID来访问,DNS会将headless service的后端直接解析为pod IP列表。

4.1.1 普通ClusterIP Service创建
4.1.1.1 命令行创建Service
- 创建Deployment类型的应用
[root@master01 ~]# cat nginx1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-server1
spec:
replicas: 2
selector:
matchLabels:
app: nginx1
template:
metadata:
labels:
app: nginx1
spec:
containers:
- name: c1
image: nginx:1.20
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
应用资源清单文件
[root@master01 ~]# kubectl apply -f nginx1.yaml
验证Deployment类型的创建情况
[root@master01 ~]# kubectl get deployment.apps
[root@master01 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-server1-5cfd5b5644-kxkh2 1/1 Running 0 2m4s 10.244.5.6 worker01 <none> <none>
nginx-server1-5cfd5b5644-mjzgc 1/1 Running 0 2m4s 10.244.30.70 worker02 <none>
[root@master01 ~]# curl 10.244.5.6 (pod ip地址)
可查看到网页内容
创建ClusterIP类型service与Deployment类型应用关联
命令创建service
[root@master01 ~]# kubectl expose deployment.apps nginx-server1 --type=ClusterIP --target-port=80 --port=80
说明:
expose 创建service
deployment.apps 控制器类型
nginx-server1 应用名称,也是service名称
--type=ClusterIP 指定service类型
--target-port=80 指定Pod中容器端口
--port=80 指定service端口
[root@master01 ~]# kubectl get service nginx-server1
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-server1 ClusterIP 10.100.81.30 <none> 80/TCP 23s
[root@master01 ~]# curl 10.100.81.30 (ClusterIP 群集IP)
4.1.1.2 通过资源清单文件创建Service
[root@master01 ~]# cat nginx-server2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-server2
spec:
replicas: 2
selector:
matchLabels:
app: nginx2
template:
metadata:
labels:
app: nginx2
spec:
containers:
- name: nginx2
image: nginx:1.20
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-server2
spec:
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 80
selector:
app: nginx2
[root@master01 ~]# kubectl delete all --all
[root@master01 ~]# kubectl apply -f nginx-server2.yaml
查看service
[root@master01 ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14m
nginx-server1 ClusterIP 10.100.81.30 <none> 80/TCP 10m
nginx-server2 ClusterIP 10.103.207.91 <none> 80/TCP 3m18s
查看endpoints
[root@master01 ~]# kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 192.168.10.11:6443 12m
nginx-server1 10.244.30.70:80,10.244.5.6:80 9m2s
nginx-server2 10.244.30.72:80,10.244.5.8:80 92s
4.1.1.3 访问
[root@master01 ~]# curl http:// 10.100.81.30
可看到网页内容
4.1.1.4 两个pod里做成不同的主页方便测试负载均衡
[root@master01 ~]# kubectl exec -it nginx-server2-pod名称1 -- bash
root@nginx-server1-5cfd5b5644-kxkh2:/# cd /usr/share/nginx/html/
root@nginx-server1-5cfd5b5644-kxkh2:/usr/share/nginx/html# echo web1 > index.html
root@nginx-server1-5cfd5b5644-kxkh2:/usr/share/nginx/html# exit
[root@master01 ~]# kubectl exec -it nginx-server2-pod名称2 -- bash
root@nginx-server1-5cfd5b5644-mjzgc:/# cd /usr/share/nginx/html/
root@nginx-server1-5cfd5b5644-mjzgc:/usr/share/nginx/html# echo web2 > index.html
root@nginx-server1-5cfd5b5644-mjzgc:/usr/share/nginx/html# exit
4.1.1.5 测试
[root@master01 ~]# curl 10.100.81.30
web2
[root@master01 ~]# curl 10.100.81.30
web1
[root@master01 ~]# curl 10.100.81.30
web2
[root@master01 ~]# curl 10.100.81.30
web1
4.1.2 Headless Service
- 普通的ClusterIP service是service name解析为cluster ip,然后cluster ip对应到后面的pod ip
- Headless service是指service name 直接解析为后面的pod ip
4.1.2.1 编写用于创建Deployment控制器类型的资源清单文件
[root@master01 ~]# cat nginx-server3.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-server3
spec:
replicas: 2
selector:
matchLabels:
app: nginx3
template:
metadata:
labels:
app: nginx3
spec:
containers:
- name: nginx-smart
image: nginx:1.20
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
[root@master01 ~]# kubectl apply -f nginx-server3.yaml
4.1.2.2 通过资源清单文件创建headless Service
[root@master ~]# vim headless-service.yml
apiVersion: v1
kind: Service
metadata:
name: headless-service
namespace: default
spec:
type: ClusterIP # ClusterIP类型,也是默认类型
clusterIP: None # None就代表是无头service
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx3
4.1.2.3 应用资源清单文件创建headless Service
[root@master ~]# kubectl apply -f headless-service.yml
4.1.2.4 查看已创建的headless Service
[root@master01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
headless-service ClusterIP None <none> 80/TCP 10s
可以看到headless-service没有CLUSTER-IP,用None表示
[root@master01 ~]# kubectl get endpoints
NAME ENDPOINTS AGE
headless-service 10.244.30.77:80,10.244.5.13:80 69s
4.1.2.5 DNS
DNS服务监视Kubernetes API,为每一个Service创建DNS记录用于域名解析
headless service需要DNS来解决访问问题
DNS记录格式为: 服务名.名称空间.svc.cluster.local.
4.1.2.5.1 查看kube-dns服务的IP (k8s群集内DNS服务)
[root@master01 ~]# kubectl get svc -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 15h
查看到coreDNS的服务地址是10.96.0.10
4.1.2.5.2 在集群主机通过DNS服务地址查找无头服务的dns解析
[root@master01 ~]# dig -t A headless-service.default.svc.cluster.local. @10.96.0.10
...
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;headless-service.default.svc.cluster.local. IN A
;; ANSWER SECTION:
headless-service.default.svc.cluster.local. 30 IN A 10.244.5.9
headless-service.default.svc.cluster.local. 30 IN A 10.244.30.73
4.1.2.5.3 验证pod的IP
[root@master01 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-server3-8cb76d66-j9rxm 1/1 Running 0 3m55s 10.244.5.13 worker01 <none> <none>
nginx-server3-8cb76d66-vx6d8 1/1 Running 0 3m55s 10.244.30.77 worker02 <none> <none>
4.1.2.5.4 在集群中创建一个pod验证
创建一个镜像为yauritux/busybox-curl的pod,pod名称为busybox,用来解析域名
[root@master01 ~]# kubectl run busybox --image=yauritux/busybox-curl -it
/home # curl headless-service.default.svc.cluster.local.
显示网页内容
- NodePort类型
创建资源清单文件
[root@master01 ~]# cat nodeport-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-server4
spec:
replicas: 2
selector:
matchLabels:
app: nginx-nodeport
template:
metadata:
labels:
app: nginx-nodeport
spec:
containers:
- name: nginx-nodeport
image: nginx:1.20
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
type: NodePort
selector:
app: nginx-nodeport
ports:
- protocol: TCP
nodePort: 30001
port: 8060
targetPort: 80
应用资源清单文件
[root@master01 ~]# kubectl apply -f nodeport-service.yaml
验证service创建
[root@master01 ~]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-server4 2/2 2 2 10s
[root@master01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 94s
nginx-nodeport NodePort 10.108.118.158 <none> 8060:30001/TCP 18s
[root@master01 ~]# kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 192.168.10.11:6443 100s
nginx-nodeport 10.244.30.81:80,10.244.5.21:80 24s
访问kubernetes 任一节点ip的nodeport端口30001,均可成功访问
更多推荐
所有评论(0)