Service主要用于Pod之间的通信。Service是提前定义好并且是不变的资源类型,在生产环境中最佳的实践方式是每个应用互相调用时使用Service的名称进行连接,因为Pod的ip在重启之后会发生变化。
Service是一种抽象的概念:逻辑上的一组Pod,即一种可以访问Pod的策略。
1. 定义Service
创建一个名为my-service的Service对象,它会将请求代理到TCP端口为80并且具有app=myapp的pod上。
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 81
targetPort: 80
通过my-service:81即可访问具有app=myapp标签的Pod的80端口。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-service
labels:
app: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: nginx
image: registry.cn-beijing.aliyuncs.com/jiangxiaonan/nginx:1.22.1
ports:
- containerPort: 80
查看创建的Service:
# kubectl get svc my-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-service ClusterIP 10.96.216.119 <none> 81/TCP 7s
2. Service和Endpoint
为什么Service不用在意Pod的ip变化?
因为创建Service的同时会创建一个同名的endpoint,里面将会记录pod ip的变化,并且随着pod的更新而更新。当我们使用Service名称链接后端pod时,并不会感知到这些变化。
# kubectl get ep my-service
NAME ENDPOINTS AGE
my-service 10.244.69.232:80,10.244.79.100:80,10.244.79.101:80 15m
# kubectl get pod -l app=myapp -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-service-6b95c4ff54-6qcpg 1/1 Running 0 8m46s 10.244.79.101 k8s-worker01 <none> <none>
nginx-service-6b95c4ff54-jqcvd 1/1 Running 0 8m46s 10.244.79.100 k8s-worker01 <none> <none>
nginx-service-6b95c4ff54-wdgzl 1/1 Running 0 8m46s 10.244.69.232 k8s-worker02 <none> <none>
3. Service的类型
主要包括以下几种:
ClusterIP:在集群内部使用,默认值,只能从集群中访问。
NodePort:在所有安装了Kube-Proxy的节点上打开一个端口,此端口可以代理到后端Pod,可以通过NodePort从集群外访问集群内的服务,格式为NodeIP:NodePort。
LoadBalancer:使用云提供商的负载均衡公开服务。
ExternalName:通过返回定义的CNAME别名,将Service映射到可被DNS解析的其他域名。
一般情况下,NodePort端口范围默认为30000-32767。
4. 多端口Service
例如将 Service 的 80 端口代理到后端的 9376,443 端口代理到后端的 9377:
kind: Service
apiVersion: v1
metadata:
name: my-services
spec:
selector:
app: myapp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
- name: https
protocol: TCP
port: 443
targetPort: 9377