Kubernetes第七章--Service详解 (纯干货)

Service 存在的意义?

引入 Service 主要是解决 Pod 的动态变化,通过创建 Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。

若提供服务的容器应用是分布式,所以存在多个 pod 副本,而 Pod 副本数量可能在运行过程中动态改变,比如水平扩缩容,或者服务器发生故障 Pod 的 IP 地址也有可能发生变化。当 pod 的地址端口发生改变后,客户端再想连接访问应用就得人工干预,很麻烦,这时就可以通过 service 来解决问题。

概念:

Service 主要用于提供网络服务,通过 Service 的定义,能够为客户端应用提供稳定的访问地址(域名或 IP 地址)和负载均衡功能,以及屏蔽后端 Endpoint 的变化,是 K8s 实现微服务的核心资源

svc 特点:

  1. 服务发现,防止阴滚动升级等因素导致 Pod IP 发生改变而失联,找到提供同一个服务的 Pod。
  2. 负载均衡,定义一组 Pod 的访问策略。

svc 与 pod 关系:

  1. pod 在创建时,与资源没有明确关联,通过 service 标签和 pod 标签相匹配来以此关联。
  2. 可以通过 endpoints 来查看关联的 pod。

svc的三大特征:

服务的自动感知

服务会创建一个clusterlP这个地址对应资源地址,不管Pod 如何变化,服务总能找到对应的Pod,且clusterIP保持不变

服务的负载均衡

如果服务后端对应多个pod,则会通过Iptables/LVS规则将访问的请求最终映射到pod的容器内部,自动在多个容器间实现负载均衡

服务的自动发现

服务创建时会自动在内部DNS上注册域名

域名:<服务名称>.<名称空间>.svc.cluster.local

svc选中pod的逻辑

  1. pod是处于就绪状态
  2. pod的标签是svc标签的集合(同一个名称空间下)
  • 常用类型

ClusterIP(集群内部使用)

默认方式,分配一个稳定的IP地址,即VIP,只能在集群内部访问

示例:

# 创建Deployment,pod的副本数为2
[root@k8s-master test]# cat server.yaml 
---
kind: Deployment
apiVersion: apps/v1
metadata: 
  name: http-test
  labels: 
    run: http
spec:
  replicas: 2
  selector:
    matchLabels:
      run: http
  template:
    metadata:
      labels:
        run: http
    spec:
      containers:
      - name: http
        image: myos:httpd

# 创建service
[root@k8s-master test]# cat service.yaml 
---
kind: Service
apiVersion: v1
metadata: 
  name: http-test   # 定义service的名称
  labels:            # 定义Service的标签,用于与其他资源关联
    run: http
spec:                 # 定义Service的规格
  selector:          # 定义Service选择器,用于选择具有特定标签的Pod
    run: http
  ports:              # 定义Service的端口配置
    - name: http     # 定义多个端口的话需要为每个端口指定名字
      protocol: TCP  # 指定协议为TCP,不填的话默认 TCP
      port: 80        # service 暴露的端口
      targetPort: 80 # 关联的 Pod 的端口,不填的话默认和 port 字段相同
                        # 也可以定义端口别名,但是已有的pod要有端口别名才能被service调用
# 创建以上两个资源清单文件
[root@k8s-master test]# kubectl apply -f service.yaml -f server.yaml
# 查看标签为run=http的pod详细信息和ip地址
[root@k8s-master test]# kubectl get pods -owide -l run=http
NAME                         READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
http-test-57fb9c77d5-djrmd   1/1     Running   0          12m   10.244.58.193   k8s-node02   <none>           <none>
http-test-57fb9c77d5-k4znk   1/1     Running   0          12m   10.244.85.219   k8s-node01   <none>           <none>

# 查看service的属性信息
[root@k8s-master test]# kubectl describe svc http-test 
Name:              http-test     # Service的名称
Namespace:         default
Labels:            run=http      # Service自己的标签
Annotations:       <none>
Selector:          run=http       # 选择run=http标签的pod
Type:              ClusterIP       # Service的类型
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.245.50.225   # Service的IP地址
IPs:               10.245.50.225
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.58.193:80,10.244.85.219:80  # Endpoints是Service的实际后端,即流量最终被转发到的地方。
Session Affinity:  None
Events:            <none>

# 访问serviceIP有负载的效果
[root@k8s-master test]# curl -s http://10.245.50.225/info.php | grep php_host
php_host:       http-test-57fb9c77d5-djrmd
[root@k8s-master test]# curl -s http://10.245.50.225/info.php | grep php_host
php_host:       http-test-57fb9c77d5-k4znk
# 查看ipvs规则
[root@k8s-master test]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.245.0.1:443 rr
  -> 192.168.88.120:6443          Masq    1      6          0         
TCP  10.245.0.10:53 rr
  -> 10.244.235.207:53            Masq    1      0          0         
  -> 10.244.235.208:53            Masq    1      0          0         
TCP  10.245.0.10:9153 rr
  -> 10.244.235.207:9153          Masq    1      0          0         
  -> 10.244.235.208:9153          Masq    1      0          0         
TCP  10.245.50.225:80 rr  # 自动添加的规则,以下是后端pod的IP
  -> 10.244.58.193:80             Masq    1      0          0         
  -> 10.244.85.219:80             Masq    1      0          0         
UDP  10.245.0.10:53 rr
  -> 10.244.235.207:53            Masq    1      0          0         
  -> 10.244.235.208:53            Masq    1      0          0  

#-------------------------------------------------------
# 这些规则是由 Kubernetes 的 kube-proxy 组件自动管理的。kube-proxy 负责维护 ipvs 规则,以确保流量能够正确地从 Service 转发到后端的 Pod。

域名自动注册

# 安装工具软件包
[root@k8s-master ~]# dnf install -y bind-utils
# 查看 DNS 服务地址
[root@k8s-master test]# kubectl -n kube-system get service kube-dns 
NAME       TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   10.245.0.10   <none>        53/UDP,53/TCP,9153/TCP   5d22h
# 域名解析测试
[root@k8s-master test]# host http-test.default.svc.cluster.local. 10.245.0.10
Using domain server:
Name: 10.245.0.10
Address: 10.245.0.10#53
Aliases: 

http-test.default.svc.cluster.local has address 10.245.50.225
# 创建pod充当客户端来测试
[root@k8s-master test]# vim client-test.yaml 
---
apiVersion: v1
kind: Pod
metadata:
  name: test-client
spec:
  containers:
    - name: client-test
      image: myos:latest
      command:
        - sleep
        - "3600"
# 创建pod
[root@k8s-master test]# kubectl apply -f client-test.yaml 
# 进入容器里,用域名来访问实现负载的效果
[root@k8s-master test]# kubectl exec -it test-client -- sh
/ # curl -s  http-test.default.svc.cluster.local./info.php | grep host
php_host:       http-test-57fb9c77d5-djrmd
/ # curl -s  http-test.default.svc.cluster.local./info.php | grep host
php_host:       http-test-57fb9c77d5-k4znk

补充一:

svc.spec.internalTrafficPolicy 是 Kubernetes 中 Service 对象的一个字段,用于控制来自集群内部源的流量如何被路由。该字段有两个可能的值:Cluster 和 Local。

  • 当设置为 Cluster(默认值)时,Kubernetes 会选择所有的服务端点来处理集群内部的流量。
  • 当设置为 Local 时,kube-proxy 仅对集群内部流量使用节点本地端点。这意味着流量只会被路由到与请求发起的客户端位于同一节点上的后端 Pod。这种策略通常用于优化性能,减少跨节点的网络流量,从而降低延迟和提高可靠性。
[root@k8s-master test]# kubectl explain svc.spec.internalTrafficPolicy
KIND:       Service
VERSION:    v1

FIELD: internalTrafficPolicy <string>

DESCRIPTION:
    InternalTrafficPolicy describes how nodes distribute service traffic they
    receive on the ClusterIP. If set to "Local", the proxy will assume that pods
    only want to talk to endpoints of the service on the same node as the pod,
    dropping the traffic if there are no local endpoints. The default value,
    "Cluster", uses the standard behavior of routing to all endpoints evenly
    (possibly modified by topology and other features).
    
    Possible enum values:
         # 默认值为Cluster。node和pod都可以发送请求
     - `"Cluster"` routes traffic to all endpoints.  
         # 值为Local 只有pod可以发送请求,node发送请求报错
     - `"Local"` routes traffic only to endpoints on the same node as the client
    pod (dropping the traffic if there are no local endpoints).

补充二:

svc.spec.sessionAffinityConfig.clientIP 是 Kubernetes 中 Service 对象的一个字段,用于配置基于客户端 IP 的会话亲和性。会话亲和性是一种机制,它确保来自同一客户端 IP 的请求总是被路由到同一个后端 Pod,从而在多个请求之间保持会话状态。

如果 ServiceAffinity 设置为 "ClientIP",则该值必须大于 0 且小于等于 86400(1 天)。默认值为 10800(3 小时)。这意味着在默认情况下,来自同一客户端 IP 的请求将在 3 小时内被路由到同一个 Pod。如果在这段时间内没有来自该客户端 IP 的新请求,会话亲和性将不再生效,后续的请求可能会被路由到不同的 Pod。

[root@k8s-master test]# kubectl explain svc.spec.sessionAffinityConfig.clientIP
KIND:       Service
VERSION:    v1

FIELD: clientIP <ClientIPConfig>

DESCRIPTION:
    clientIP contains the configurations of Client IP based session affinity.
    ClientIPConfig represents the configurations of Client IP based session
    affinity.
    
FIELDS:
  timeoutSeconds        <integer>
    timeoutSeconds specifies the seconds of ClientIP type session sticky time.
    The value must be >0 && <=86400(for 1 day) if ServiceAffinity == "ClientIP".
    Default value is 10800(for 3 hours).

NodePort(对外暴露应用)

NodePort相当于是ClusterIP的一个升级版可以实现ClusterIP的完整功能,在每个节点启用一个端口来暴露服务,可以在集群外部访问,通过NodeIP:NodePort访问端口范围:30000~32767

示例:

# 创建deployment,pod副本数为3
[root@k8s-master test]# vim deploy_nodeport.yaml 
---
kind: Deployment
apiVersion: apps/v1
metadata: 
  name: nodeprot-deploy
spec:
  replicas: 3
  selector: 
    matchLabels:
      app: apache
  template: 
    metadata: 
      labels: 
        app: apache
    spec: 
      containers: 
      - name: http
        image: myos:httpd
# 创建service的nodeport类型,实现集群外部访问
[root@k8s-master test]# vim nodeport.yaml 
---
kind: Service
apiVersion: v1
metadata: 
  name: nodeport
spec: 
  type: NodePort      # NodePort类型
  selector: 
    app: apache
  ports: 
  - name: http         # 定义多个端口的话需要为每个端口指定名字
    port: 80           # clusterIP 暴露的端口
    nodePort: 30333   # 集群的每台机器上要暴露的端口,不填的话由系统随机指定 (30000-32767)
    targetPort: 80    # 关联的 Pod 的端口,不指定的话默认和 port 字段相同

# 创建以上资源清单文件
[root@k8s-master test]# kubectl apply -f deploy_nodeport.yaml -f nodeport.yaml 
deployment.apps/nodeprot-deploy configured
service/nodeport unchanged
[root@k8s-master test]# kubectl get pods -o wide
NAME                               READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
nodeprot-deploy-644c7f78f7-6czqq   1/1     Running   0          26m   10.244.85.197   k8s-node01   <none>           <none>
nodeprot-deploy-644c7f78f7-7pm4n   1/1     Running   0          26m   10.244.58.196   k8s-node02   <none>           <none>
nodeprot-deploy-644c7f78f7-r4lkx   1/1     Running   0          26m   10.244.58.195   k8s-node02   <none>           <none>

[root@k8s-master test]# kubectl describe svc nodeport 
Name:                     nodeport      # service名称
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=apache   # 选择app=apache标签的pod
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.245.67.236 # 访问集群内部的IP
IPs:                      10.245.67.236
Port:                     http  80/TCP  # 端口名为http,svc暴露的端口
TargetPort:               80/TCP        # 关联pod的端口
NodePort:                 http  30333/TCP # 端口名为http,集群节点暴露的端口
                            # 以下3个IP是关联pod的ip
Endpoints:                10.244.58.195:80,10.244.58.196:80,10.244.85.197:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

查看ipvs规则发现每个节点的每张物理网卡都自动绑定了30333端口,而且还有rr算法轮询的效果,是NAT模式

[root@k8s-master test]# ipvsadm -Ln | grep :30333 -A 3
TCP  172.17.0.1:30333 rr
  -> 10.244.58.195:80             Masq    1      0          0         
  -> 10.244.58.196:80             Masq    1      0          0         
  -> 10.244.85.197:80             Masq    1      0          0               
TCP  192.168.88.120:30333 rr
  -> 10.244.58.195:80             Masq    1      0          1         
  -> 10.244.58.196:80             Masq    1      0          2         
  -> 10.244.85.197:80             Masq    1      0          1                
TCP  10.244.235.192:30333 rr
  -> 10.244.58.195:80             Masq    1      0          0         
  -> 10.244.58.196:80             Masq    1      0          0         
  -> 10.244.85.197:80             Masq    1      0          0  
  .....       
[root@k8s-node01 ~]# ipvsadm -Ln | grep :30333 -A 3       
TCP  192.168.88.121:30333 rr
  -> 10.244.58.195:80             Masq    1      0          0         
  -> 10.244.58.196:80             Masq    1      0          0         
  -> 10.244.85.197:80             Masq    1      0          0         
TCP  192.168.122.1:30333 rr
  -> 10.244.58.195:80             Masq    1      0          0         
  -> 10.244.58.196:80             Masq    1      0          0         
  -> 10.244.85.197:80             Masq    1      0          0         
TCP  10.244.85.192:30333 rr
  -> 10.244.58.195:80             Masq    1      0          0         
  -> 10.244.58.196:80             Masq    1      0          0         
  -> 10.244.85.197:80             Masq    1      0          0 
  ......        
[root@k8s-node02 ~]# ipvsadm -Ln | grep :30333 -A 3
TCP  192.168.88.122:30333 rr
  -> 10.244.58.195:80             Masq    1      0          0         
  -> 10.244.58.196:80             Masq    1      0          0         
  -> 10.244.85.197:80             Masq    1      0          0         
TCP  192.168.122.1:30333 rr
  -> 10.244.58.195:80             Masq    1      0          0         
  -> 10.244.58.196:80             Masq    1      0          0         
  -> 10.244.85.197:80             Masq    1      0          0         
TCP  10.244.58.192:30333 rr
  -> 10.244.58.195:80             Masq    1      0          0         
  -> 10.244.58.196:80             Masq    1      0          0         
  -> 10.244.85.197:80             Masq    1      0          0 
  ......       

访问每个节点的30333端口实现k8s集群外部访问的效果

验证效果:

[root@k8s-master test]# curl -s http://192.168.88.120:30333/info.php | grep host
php_host:       nodeprot-deploy-644c7f78f7-r4lkx
[root@k8s-master test]# curl -s http://192.168.88.120:30333/info.php | grep host
php_host:       nodeprot-deploy-644c7f78f7-6czqq
[root@k8s-master test]# curl -s http://192.168.88.120:30333/info.php | grep host
php_host:       nodeprot-deploy-644c7f78f7-7pm4n
[root@k8s-master test]# curl -s http://192.168.88.121:30333/info.php | grep host
php_host:       nodeprot-deploy-644c7f78f7-6czqq
[root@k8s-master test]# curl -s http://192.168.88.121:30333/info.php | grep host
php_host:       nodeprot-deploy-644c7f78f7-7pm4n
[root@k8s-master test]# curl -s http://192.168.88.121:30333/info.php | grep host
php_host:       nodeprot-deploy-644c7f78f7-r4lkx
[root@k8s-master test]# curl -s http://192.168.88.122:30333/info.php | grep host
php_host:       nodeprot-deploy-644c7f78f7-6czqq
[root@k8s-master test]# curl -s http://192.168.88.122:30333/info.php | grep host
php_host:       nodeprot-deploy-644c7f78f7-7pm4n
[root@k8s-master test]# curl -s http://192.168.88.122:30333/info.php | grep host
php_host:       nodeprot-deploy-644c7f78f7-r4lkx

补充:

svc.spec.internalTrafficPolicy和svc.spec.externalTrafficPolicy字段

ClusterIP类型

internalTrafficPolicy

Cluster:

集群节点的工具可以通过虚拟IP进行访问

集群内部的Pod可以通过虚拟IP进行访问

Local:

仅仅只支持集群内部的Pod可以通过虚拟IP进行访问

NodePort 类型

internalTrafficPolicy

Cluster:

集群节点的工具可以通过虚拟IP进行访问

集群内部的Pod可以通过虚拟IP进行访问

Local:

仅仅只支持集群内部的Pod可以通过虚拟IP进行访问

externalTrafficPolicy

Cluster:

集群以外的客户端可以通过节点的物理网卡的物理IP对应的端口进行访问

集群节点的工具可以通过节点的物理网卡的物理IP对应的端口进行访问

Local:

仅仅只支持集群节点的工具可以通过节点的物理网卡的物理对应的端口进行访问

Ingress

为什么引入Ingress?

我们说k8s 的服务(service)时说暴露了service的三种方式ClusterIP、NodePort与LoadBalance,这几种方式都是在service的维度提供的,service的作用体现在两个方面,对集群内部,它不断跟踪pod的变化,更新endpoint中对应pod的对象,提供了ip不断变化的pod的服务发现机制,对集群外部,他类似负载均衡器,可以在集群内外部对pod进行访问。但是,单独用service暴露服务的方式,在实际生产环境中不太合适:

  • ClusterIP的方式只能在集群内部访问。
  • NodePort方式的话,测试环境使用还行,当有几十上百的服务在集群中运行时,NodePort的端口管理是灾难。
  • LoadBalance方式受限于云平台,且通常在云平台部署ELB还需要额外的费用。

所幸k8s还提供了一种集群维度暴露服务的方式,也就是ingress。ingress可以简单理解为service的service,他通过独立的ingress对象来制定请求转发的规则,把请求路由到一个或多个service中。这样就把服务与请求规则解耦了,可以从业务维度统一考虑业务的暴露,而不用为每个service单独考虑。

The design of NGINX Ingress Controller | NGINX Ingress Controller

service是四层的负载均衡方案,Ingress是七层负载均衡访问方案

service通过iptables、ipvs实现。有缺陷:每一组业务都要开启nodePort,这样nodePort越来越多越来越难管理

解决方案:多加一层管理庞大的service

本来nodePort是映射到Service的,现在在往上抽一层,映射到上层,由上层再分发到service,此方案Ingress实现了

而Ingress是K8S中的资源,接口,可以由不同的控制器实现

Ingress-nginx是其中的一种实现,是对nginx的二次开发,来满足Ingress的规范

Ingress 是什么?

  • Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制。
  • Ingress 控制器通常由负载均衡器来实现(Nginx、HAProxy)

Ingerss安装

  • 安装Ingress控制器
  • Ingress服务由(规则+控制器)组成
  • 规则负责制定策略,控制器负责执行
  • 如果没有控制器,单独设置规则无效
  • 获取控制器镜像及资源文件

地址: https://github.com/kubernetes/ingress-nginx

示例:

# 验证后端服务
[root@master ~]# kubectl get pods,services 
NAME       READY   STATUS    RESTARTS   AGE
pod/web1   1/1     Running   0          35m

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)
service/kubernetes   ClusterIP   10.245.0.1    <none>        443/TCP
service/websvc       ClusterIP   10.245.1.80   <none>        80/TCP
service/mysvc        NodePort    10.245.3.88   <none>        80:30080/TCP

[root@master ~]# curl http://10.245.1.80
Welcome to The Apache.

# 查询 ingress 控制器类名称
[root@master ~]# kubectl get ingressclasses.networking.k8s.io 
NAME    CONTROLLER             PARAMETERS   AGE
nginx   k8s.io/ingress-nginx   <none>       5m7s

[root@master ~]# vim mying.yaml 
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata: 
  name: mying
spec: 
  ingressClassName: nginx  # 使用的类名称
  rules:                   # ingress规则定义
  - host: nsd.tedu.cn      # 域名定义,没有可以不写
    http:                  # 协议
      paths:               # 访问的路径定义
      - path: /            # 访问的url路径
        pathType: Prefix   # 路径的类型[Exact(精准)、Prefix(宽松]
        backend:           # 定义后端服务
          service:         # 服务声明
            name: websvc   # 服务名称
            port:          # 端口号声明
              number: 80   # 访问服务的端口号
              
[root@master ~]# kubectl apply -f mying.yaml 
ingress.networking.k8s.io/mying created
[root@master ~]# kubectl get ingress
NAME    CLASS   HOSTS         ADDRESS        PORTS
mying   nginx   nsd.tedu.cn   192.168.88.51   80
[root@master ~]# curl -H "Host: nsd.tedu.cn" http://192.168.88.51
Welcome to The Apache.

 LoadBalancer(对外暴露应用,适用于公有云)

与NodePort类似,在每个节点启用一个端口来暴露服务。除此之外,K8s请求底层云平台的负载均衡器,把每个[Node IP]:[NodePort]作为后端添加进去

华为云示例:

# 使用 CCE 集群服务调用 ELB 负载均衡
[root@harbor ~]# vim websvc.yaml
---
kind: Service
apiVersion: v1
metadata:
  name: websvc
  annotations:
    kubernetes.io/elb.class: union           # ELB 类型
    kubernetes.io/elb.id:       # ELB 服务的 ID
    kubernetes.io/elb.transparent-client-ip: 'true'  # 获取客户端 IP
spec:
  type: LoadBalancer
  selector:
    app: xk8s-httpd
  ports:
  - name: websvc
    protocol: TCP
    port: 80
    targetPort: webport

[root@harbor ~]# kubectl apply -f websvc.yaml 
service/websvc created

[root@harbor ~]# kubectl get service 
NAME         TYPE           CLUSTER-IP       EXTERNAL-IP
kubernetes   ClusterIP      10.245.0.1       
websvc       LoadBalancer   10.245.209.220   139.9.168.100,192.168.0.250
# 使用浏览器访问公网IP 139.9.168.100,就能访问集群内的pod

ExternalName

ExternalName 类型的 Service 是 Kubernetes 中用于提供从集群内部访问外部 DNS 名称的一种方式。它的主要目的是简化集群内部应用访问外部服务的过程。当你创建一个类型为 ExternalName 的 Service 时,Kubernetes 会为这个 Service 创建一个 DNS 条目,该条目将解析为指定的外部 DNS 名称。

与 NodePort 或 LoadBalancer 类型的 Service 不同,ExternalName 类型的 Service 不会暴露任何集群内部的服务到外部网络,而是相反,它让集群内部的服务可以访问外部的服务。

示例:

[root@k8s-master test]# cat test.yaml 
---
kind: Pod
apiVersion: v1
metadata: 
  name: test
spec: 
  containers: 
  - name: test
    image: myos:httpd
[root@k8s-master test]# cat externalname.yaml 
---
kind: Service
apiVersion: v1
metadata: 
  name: externalname
spec: 
  type: ExternalName # 类型
  externalName: www.baidu.com # 外部的dns

# 创建以上两个资源清单
[root@k8s-master test]# kubectl apply -f test.yaml -f externalname.yaml
# 查看svc信息
[root@k8s-master test]# kubectl get svc
NAME           TYPE           CLUSTER-IP   EXTERNAL-IP     PORT(S)   AGE
externalname   ExternalName          www.baidu.com       11m
kubernetes     ClusterIP      10.245.0.1             443/TCP   6d17h
# 进入测试pod
[root@k8s-master test]# kubectl exec -it test -- bash
# 访问名为externalname的svc的域名,得到是百度的响应就成功
[root@test html]# ping externalname.default.svc.cluster.local.
PING www.a.shifen.com (103.235.47.188) 56(84) bytes of data.
64 bytes from 103.235.47.188 (103.235.47.188): icmp_seq=1 ttl=127 time=228 ms
64 bytes from 103.235.47.188 (103.235.47.188): icmp_seq=2 ttl=127 time=236 ms
64 bytes from 103.235.47.188 (103.235.47.188): icmp_seq=3 ttl=127 time=231 ms
^C
--- www.a.shifen.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2008ms
rtt min/avg/max/mdev = 228.156/231.495/235.757/3.170 ms

Endpoints与Service和Pod间的关联

Kubernetes中的Service,它定义了一组Pods的逻辑集合和一个用于访问它们的策略。一个Service的目标Pod集合通常是由LabelSelector来决定的

Endpoints是一组实际服务的端点集合。一个Endpoint是一个可被访问的服务端点,即一个状态为running的pod的可访问端点。一般Pod都不是一个独立存在,所以一组Pod的端点合在一起称为EndPoints。只有被ServiceSelector匹配选中并且状态为Running的Pod才会被加入到和Service同名的Endpoints 中。

Service endpoints

有标签选择器

自动创建一个同名的endpoints资源对象

匹配对象

当前名字空间中的pod

标签子集运算

就绪的状态

没有定义标签选择器

不会创建同名的endpoints资源对象,需要管理员手动创建

匹配对象

管理员填写的端点信息,灵活性强

手动关联service示例:

[root@k8s-master test02]# vim test_service.yaml 
---
kind: Service
apiVersion: v1
metadata: 
  name: nginx
spec: 
  type: ClusterIP  # service的类型
  clusterIP: 10.245.8.8 # 固定service的IP
  ports: 
    - targetPort: 80 # 访问后端服务器的端口
      port: 8888     # service暴露的端口
      protocol: TCP  # 使用的协议
---
kind: Endpoints
apiVersion: v1
metadata:
  name: nginx # 要和关联的service的名一样
subsets:  # 定义关联的后端服务器的IP
  - addresses:
      - ip: 192.168.88.122 # 关联集群中的nodeIP,可以是多个
    ports:
      - port: 80 # 访问nodeIP的80端口

# 创建资源清单文件
[root@k8s-master test02]# kubectl apply -f test_service.yaml 
service/nginx created
endpoints/nginx created

# 查看svc信息
[root@k8s-master test02]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.245.0.1   <none>        443/TCP    7d3h
nginx        ClusterIP   10.245.8.8   <none>        8888/TCP   6s

# 查看endpoints信息
[root@k8s-master test02]# kubectl get ep
NAME         ENDPOINTS             AGE
kubernetes   192.168.88.120:6443   7d3h
nginx        192.168.88.122:80     9s

# 查看ipvs规则,自动添加的规则
[root@k8s-master test02]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.245.0.1:443 rr
  -> 192.168.88.120:6443          Masq    1      6          0         
TCP  10.245.0.10:53 rr
  -> 10.244.235.207:53            Masq    1      0          0         
  -> 10.244.235.208:53            Masq    1      0          0         
TCP  10.245.0.10:9153 rr
  -> 10.244.235.207:9153          Masq    1      0          0         
  -> 10.244.235.208:9153          Masq    1      0          0         
TCP  10.245.8.8:8888 rr  # svcIP的规则,自动绑定后端ip,实现轮询效果
  -> 192.168.88.122:80            Masq    1      0          0         
UDP  10.245.0.10:53 rr
  -> 10.244.235.207:53            Masq    1      0          0         
  -> 10.244.235.208:53            Masq    1      0          0       
 
# 验证访问svc的8888端口,得到的是自己关联的后端的80端口的信息
[root@k8s-master test02]# curl 10.245.8.8:8888
wo shi hehe   

你可能感兴趣的:(kubernetes,容器,云原生,docker,etcd)