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