kubernetes Service svc endpoints
service --> endpoints --> deployment --> ReplicaSet -->Pod
创建
创建clusterIP类型的service:
kubectl create service clusterip myapp-svc --tcp=80:80 --dry-run -o yaml
service资源文件:
selector
type
ports.port
apiVersion: v1 kind: Service metadata: labels: app: myapp-svc name: myapp-svc spec: selector: app: myapp # Pod的标签 type: ClusterIP ports: - name: 80-80 port: 80 targetPort: 80
查看 endpoints:这个 endpoints 也可以手动创建。
kubectl get endpoints myapp-svc NAME ENDPOINTS AGE myapp-svc 10.244.1.128:80,10.244.1.129:80,10.244.1.130:80 29s
在Pod中访问Service:
运行一个Pod:
kubectl run busybox --image=busybox:1.28 --generator=run-pod/v1 --command sleep 3600
然后在Pod中访问service:
kubectl run cirros-$RANDOM --rm -it --image=cirros --generator=run-pod/v1 -- sh / # curl http://10.97.36.35:80/hostname.html myapp-6c5bfd4dff-fpf9c
service会话粘性:根据ip来在一定时间内调度到同一个Pod上,默认为10800秒。
spec.sessionAffinity:定义粘性的类型,只有 ClientIP 和 None 两种类型。
spec.sessionAffinityConfig:会话保持的时长,默认10800 秒。
spec: sessionAffinity: ClientIP sessionAffinityConfig: clientIP: timeoutSeconds: 100
在原来的Service上打上标签:
kubectl patch service myapp-svc -p '{"spec":{"sessionAffinity":"ClientIP"}}'
此时在去请求就不会轮询了:
/ # curl http://10.97.36.35/hostname.html
服务发现
userspace:
ClientPod --> Service(iptables)--> kube-proxy --> Service --> server Pod
iptables:
Client Pod --> Service(iptables) --> Server Pod
ipvs:
Client Pod --> Service(ipvs) --> Server Pod
环境变量:在创建Pod之前创建的Service信息会被以环境变量的方式注入Pod中,还有service和Pod必须在同一个名称空间。
kubectl exec myapp-6c5bfd4dff-fpf9c -it -- sh / # printenv | grep SVC MYAPP_SVC_PORT_80_TCP_ADDR=10.97.36.35 MYAPP_SVC_SERVICE_PORT_80_80=80 MYAPP_SVC_PORT_80_TCP_PORT=80 MYAPP_SVC_PORT_80_TCP_PROTO=tcp MYAPP_SVC_PORT_80_TCP=tcp://10.97.36.35:80 MYAPP_SVC_SERVICE_HOST=10.97.36.35 MYAPP_SVC_SERVICE_PORT=80 MYAPP_SVC_PORT=tcp://10.97.36.35:80
DNS:
kubectl run cirros-$RANDOM --rm -it --image=cirros -- sh / # nslookup myapp-svc.default Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: myapp-svc.default Address 1: 10.97.36.35 myapp-svc.default.svc.cluster.local
Service的类型
service的类型:
ClusterIP 集群内部使用的服务IP。
NodePort 供节点外部的访问的IP。
LoadBalance 部署在云环境下实现自动负载均衡。
ExternalName 将集群外部的服务引入到集群内部直接使用。
1、ClusterIP:集群内部使用的服务IP。
kubectl create service clusterip nginx-svc --tcp=8912:80 --dry-run -o yaml apiVersion: v1 kind: Service metadata: labels: app: nginx-svc name: nginx-svc spec: ports: - name: 8912-80 port: 8912 # service的port protocol: TCP targetPort: 80 # Pod的port selector: app: nginx-svc type: ClusterIP # 类型定义
2、NodePort:将内部服务暴露给外部客户端访问。
apiVersion: v1 kind: Service metadata: labels: app: nodeport-svc name: nodeport-svc spec: type: NodePort ports: - name: 80-80 port: 80 # service的端口 protocol: TCP targetPort: 80 # Pod的端口 nodePort: 32223 # 节点端口,一般省略自动分配 selector: app: myapp
访问服务:NodeIP:NodePort,客户端可由任何一个节点IP加端口访问service。
curl 192.168.1.140:32223
访问转发过程:NodeIP:NodePort --> ServiceIP:ServicePort --> PodIP:PodPort
3、LoadBalancer:在云环境中可自动创建软负载均衡器。
kubectl create service loadbalancer myapp-svc-lb --tcp=80:80 --dry-run -o yaml
yaml文件:
apiVersion: v1 kind: Service metadata: labels: app: myapp-svc-lb name: myapp-svc-lb spec: ports: - name: 80-80 port: 80 protocol: TCP targetPort: 80 selector: app: myapp-svc-lb type: LoadBalancer nodePort: 32223 # 一般省略自动分配 status: loadBalancer: {}
4、ExternalName:将外部服务引入到集群内部的Pod使用,无ClusterIP。
kubectl create service externalname external-test --external-name www.zhuqiyang.com --dry-run -o yaml
yaml文件:
apiVersion: v1 kind: Service metadata: labels: app: external-test name: external-test spec: externalName: www.zhuqiyang.com selector: app: external-test type: ExternalName
在Pod中解析service:
在Pod中就可以使用 external-redis-svc 或 external-redis-svc.default.svc.cluster.local 来访问外部资源了。
/ # nslookup external-test.default.svc.cluster.local Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: external-test.default.svc.cluster.local Address 1: 39.105.168.208 / # / # nslookup external-test Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: external-test Address 1: 39.105.168.208
5、Headless Service:没有 ClusterIP,通过DNS以轮询的方式调度到后端的各个Pod IP上。
创建Headless资源:
apiVersion: v1 kind: Service metadata: labels: app: headless name: headless spec: ports: - name: 80-80 port: 80 protocol: TCP targetPort: 80 selector: app: myapp clusterIP: None
Pod资源发现:可以看到解析的IP为 selector 匹配到的Pod IP,而不是service的IP。
kubectl run busybox --generator='run-pod/v1' --image=busybox:1.28 -it --rm -- sh / # nslookup headless Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: headless Address 1: 10.244.1.152 10-244-1-152.headless.default.svc.cluster.local Address 2: 10.244.1.154 10-244-1-154.headless.default.svc.cluster.local Address 3: 10.244.1.155 10-244-1-155.headless.default.svc.cluster.local
6、externalIPs:将k8s内部服务暴露到公网上,需要手动设置ip,虽然ingress也可以但是一般用于七层代理。
apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: MyApp ports: - name: http protocol: TCP port: 80 targetPort: 9376 externalIPs: - 80.11.12.10
endpoints
较早版本的endpoints是有spec字段的,后面的版本就没有这个字段了。
新版本写法:
apiVersion: v1 kind: Endpoints metadata: labels: cattle.io/creator: norman name: example namespace: default subsets: - addresses: - ip: 10.42.7.161 nodeName: node01 targetRef: kind: Pod name: nginx-7cc684969-xsqhl namespace: default ports: - name: web port: 8080 protocol: TCP