K8s: Service对象以及与Pod之间的通信关系

发布于:2024-04-28 ⋅ 阅读:(22) ⋅ 点赞:(0)

Service 对象


1 )概述

  • 每个 Pod 都有自己的 IP 地址,但是在 Deployment 中
  • 注意,实际在部署我们服务的时候创建的是 Deployment 而非 pod
    • Deployment 是控制器的一种
  • 在同一时刻运行的 Pod 集合可能与稍后运行该应用程序的 Pod 集合不同
  • 这导致了一个问题: 如果一组 Pod(比如: “后端”)即有3个pod提供同一个微服务
  • 这是微服务的多实例,也是 K8s 的核心作用
  • 后端为群集内的其他 Pod(比如: “前端”)提供功能
  • 在这种情况下,如果后端的一组pod失效
  • 它会无缝漂移到其他节点上重新启动,这时候服务的ip地址就变了
  • 这时候,外部访问pod(前端)如何找出并跟踪要连接的 IP 地址
  • 以便前端可以继续使用后端部分
  • 为了应对这个问题,K8s 提供了一个资源对象 Service
  • Service 将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法
  • 简单来说,K8s 通过 Service 来暴露 Pod 对外服务的一个地址
  • 通过集群外部访问pod的时候,不应该访问 Pod 的ip地址,而是访问为pod提供的DNS域名
  • Service 负责把请求从后端路由到对应的Pod
  • 使用 K8s 服务无需修改应用程序即可使用通用的服务发现机制
  • K8s 为 Pods 提供自己的 IP 地址,并为一组 Pod 提供相同的 DNS 名
  • 并且可以在它们之间进行负载均衡

2 ) 定义 Service

  • Service 在 K8s 中是一个 REST 对象,和 Pod 类似
  • 像所有的 REST 对象一样,Service 定义可以基于 POST 方式,请求 API server 创建新的实例
  • 例如,假定有一组 Pod,它们对外暴露了 9376 端口,同时还被打上 app=MyApp 标签
  • 示例说明
    apiVersion: v1
    kind: Service
    metadata:
      name: my-service # 这里的名称将来会被用作请求的域名来被集群外部和内部对象使用
    spec:
      selector: # 选择器,Service 会通过满足选择器的Pod去建立和Pod的映射关系,一般是1对多
        app: xxx # 会找对应 这个 xxx label 的 Pod
      ports:
      - protocol: TCP
        port: 80 # 对外暴露的端口,集群内部可访问
        targetPort: 9376 # 容器底层的端口,如果不配置这个,默认使用和上面的 port 一致的
    
  • 创建 my-service.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
    spec:
      selector:
        app: sss-app
      ports:
      - protocol: TCP
        port: 80
        targetPort: 9376
    
  • 可以看到,它没有创建任何容器,它就是虚拟的对象
  • 它只负责建立一系列的规则来访问 Service
  • $ kubectl create -f my-service.yaml
    service/my-service created
    
  • $ kubectl get svc
    kubernetes   ClusterIP   10.1.0.1     <none>        443/TCP   2d8h
    my-service   ClusterIP   10.1.38.99   <none>        80/TCP    35s
    

用Service暴露Pod的服务地址


1 )配置 Deployment 对象用来维护 Pod

  • 新建 dep-my-nginx.yaml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-dep-nginx # 这个是 Deployment 对象的名称
    spec:
      selector:
        matchLabels: # 匹配标签
          run: my-dep-nginx # 运行匹配的 my-nginx 容器
      replicas: 2 # 2个副本,会创建 2个 pod
      template: # 定义模板
        metadata:
          labels:
            run: my-dep-nginx
        spec: # 模板说明
          containers:
          - name: my-dep-nginx
            image: nginx
            resources:
              limits:
                memory: "32Mi"
                cpu: "100m"
            ports:
            - containerPort: 80
    
  • $ kubectl apply -f dep-my-nginx.yaml

    deployment.apps/my-nginx created
    
  • 这样就会创建2个pod, 之后,创建 Service

  • $ kubectl get po | grep my-dep 查看相关 pod

    my-dep-nginx-7776c5d85c-crtgj   1/1     Running     0                 24s
    my-dep-nginx-7776c5d85c-ljztm   1/1     Running     0                 37s
    
    • 注意这里,上面两个pod我们不知道其ip和域名
    • 即使知道了,也访问不了,因为不应该被外部访问,因为其ip地址随时可能变化
    • 如果需要访问的话,就需要下面的 Service
  • $ kubectl get all 可以看到,多了一个 deploment

    NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/my-dep-nginx   2/2     2            2           6m42s
    
  • $ kubectl get pods -l run=my-dep-nginx -o yaml 通过 label 来查看

    • 这里输出过多,不便于在此展示,可以看到 pod 很多详细信息
    • 比如 pod ip 我们可以过滤来看 $ kubectl get pods -l run=my-dep-nginx -o yaml | grep podIP
    • 再比如,通过 $ ip addr | grep 10.244 可以看到网段是从 flannel.1 和 cni 中来的
    • 这里 10.244 是上面输出的,在 ip addr 作为过滤条件
    • 通过这个ip网段,底层容器间就可以相互通信了

2 )创建 Service

  • 这里通常有两种方式

2.1 使用 命令通过 Development 来暴露

  • $ kubectl expose deployment.apps/my-dep-nginx 这里的 deployment 是从上面获取的
    service/my-dep-nginx exposed
    
    • 执行完成后,服务就暴露出来了
  • $ kubectl get svc my-dep-nginx 验证暴露出的 Service
    NAME           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
    my-dep-nginx   ClusterIP   10.1.128.101   <none>        80/TCP    76s
    

2.2 基于yaml文件来处理

  • 上面等价于通过 yaml 文件创建 Service

  • 在用这种方式创建的时候,先把之前创建的 Service 删除

  • $ kubectl delete service my-dep-nginx

    service "my-dep-nginx" deleted
    
  • 现在创建 svc-my-nginx.yaml 文件

    apiVersion: v1
    kind: Service
    metadata:
      name: my-svc-nginx
      labels:
        run: my-dep-nginx # 注意这里和上面 deployment 匹配
    spec:
      ports:
      - port: 80
        protocol: TCP
      selector:
       run: my-dep-nginx # 注意这里和上面 deployment 匹配
    
  • $ kubectl create -f svc-my-nginx.yaml 创建 Service

    service/my-svc-nginx created
    
  • $ kubectl get svc my-svc-nginx

    NAME           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    my-svc-nginx   ClusterIP   10.1.231.159   <none>        80/TCP    59s
    
  • $ kubectl describe svc my-svc-nginx

    Name:              my-svc-nginx
    Namespace:         default
    Labels:            run=my-dep-nginx
    Annotations:       <none>
    Selector:          run=my-dep-nginx
    Type:              ClusterIP
    IP Family Policy:  SingleStack
    IP Families:       IPv4
    IP:                10.1.231.159
    IPs:               10.1.231.159
    Port:              <unset>  80/TCP
    TargetPort:        80/TCP
    Endpoints:         10.244.2.22:80,10.244.2.23:80
    Session Affinity:  None
    Events:            <none>
    
    • 这里 Endpoints 也是 K8s 对象
    • 如果 Service 创建之后,如果匹配到 Pod Label 之后
    • 会为 Label 创建 Endpoint 对象
    • 这个 Endpoint 值就是ip, 端口就是port
  • 看下: $ curl 10.1.231.159 这里端口 80 是默认,不用添加

    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
    html { color-scheme: light dark; }
    body { width: 35em; margin: 0 auto;
    font-family: Tahoma, Verdana, Arial, sans-serif; }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>
    
  • 看到上面显示是服务通了


网站公告

今日签到

点亮在社区的每一天
去签到