Kuberne...

k8s service 与 pod

2019-10-01  本文已影响0人  taj3991

k8s Pod 创建

文件名:deploy-echoserver.yml (这里以 Deployment 的方式来创建与管理 Pod)

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  # Deployment 实例名称
  name: echoserver
spec:
  # 设置 Pod 个数
  replicas: 2
  template:
    metadata:
      # 设置 Pod 标签
      labels:
        app: echoserver
    spec:
      # 运行 docker 镜像
      containers:
      - name: echoserver 
        image: jasonn/php-echoserver

启动命令:
kubectl create -f deploy-echoserver.yml

查看 deployment 启动情况:


对 Pod 的访问情况如下(通过kubectl describe pods获取 Pod 的 IP 地址):


问题

场景1:现在 K8S 上运行着2个 Pod。我们希望通过上述所说的 Service 来整合这两个 Pod 的访问,完成对它们的统一访问,而不用向具体的 Pod 发出请求。

Service 创建脚本内容如下(service-echoserver.yml):

apiVersion: v1
kind: Service
metadata:
  # Service 实例名称
  name: svc-echoserver
spec:
  ports:
    - protocol: TCP
      # Service 端口地址
      port: 8080
      # Pod 端口地址
      targetPort: 80
  selector:
    # 匹配符合标签条件的 Pod
    app: echoserver

创建 Service 命令:
kubectl create -f service-echoserver.yml

由此,我们创建好了一个 Service,同时也生成了一个对应的 VIP。

查看 Serivce 创建情况:

下面,我们来验证下是否如之前所说,对 VIP 的访问能访问到 Pod 的内容。


场景2:了解了 Service 是通过 label & selecor 来进行整合 Pod 的。那如果 Pod 不存在标签,又或者是在不同 Namespace 下,也可能是 K8S 集群外的一个服务。现实情况往往更加复杂,这样的情况下,Service 又该如何整合。

发现在 Service 创建的同时,还生成了一个 Endpoints。 该 Endpoints 与 Service 同名,它所暴露的地址信息正是对应 Pod 的地址。由此猜测是 Endpoints 维护了 Service 与 Pod 的映射关系。

为了验证我们的猜测,我们手动删除 Endpoints,发现之前能成功访问到 Pod 的 VIP,现在已经已经访问不到了。


我们在手动把 Endpoints 创建回来,创建脚本如下(endpoint-echoserver.yml):

apiVersion: v1
kind: Endpoints
metadata:
  # Endpoints 实例的名称
  name: svc-echoserver
subsets:
  - addresses:
    - ip: 172.17.0.5
    - ip: 172.17.0.6
    ports:
    - port: 80

创建命令:
kubectl create -f endpoint-echoserver.yml

注意:Endpoints 与 Service 的绑定关系通过名称来关联的,所以这两者的名称(name)一定要一致。

如果创建失败,出现的错误信息是“...endpoints "svc-echoserver" already exists”,说明 Service 已经更新了 Endpoints。这里就说到了 Service 会定期去检查 Pod 的状态,并且将结果更新到 Endpoints 上。

VIP 再次访问时又能成功访问到,如图:


现在我们已经能轻松的解决场景2的问题了,在创建 Service 时,只要不设置 Selector 属性,那么将不会自动创建 Endpoints,这是我们可以根据需求手动的创建指定地址(address)的 Endpoints,来解决标签无法实现的整合。

场景3:知道了 Service、Endpoints、Pod 的三者关系后,我们来具体看看所说的代理到底是如何实现的。从之前 K8S 的架构中,我们知道 Service 的代理是由 kube-proxy 实现的。而它的代理模式(Proxy mode)主要有两种:userspace 与 iptables。自 K8S v1.2 开始,默认的代理模式就是 iptables,并且它的性能也是要高于 userspace 的,所以在这儿只讨论 iptables 的实现。

根据 iptables 的机制,请求是先到 nat 表的 PREROUTING 链(chain)上的,它的规则如下:

图中发现,请求首先经过 KUBE-SERVICE 链,其次再到 DOCKER 链上的。

我们看一下 KUBE-SERVICE 的情况:


我们发现 KUBE-SERVICE 中包含了一系列 Service 的规则。根据我们请求的 VIP 的目的地址,对应到了下一个名叫 KUBE-SVC-PRQ3AXYQLQGIVVIU 的 Service 链上。

1.KUBE-SVC-PRQ3AXYQLQGIVVIU 规则如下:


从规则的名字上可以看出,该条 Service 链上记录的是2个 Endpoints 链,具体的选择是通过 50% 的随机性的进行决定(这也是它的一个负载规则)。

从图中,我们已经很清晰的看到了它转发到 Pod 的具体规则。

关于 DOCKER 链的跟踪,方法是差不多的,请求 从 nat 表结束后,在到 filter 表中,这里就不加以说明了。

而这些规则的实现正是由 Service、Endpoints 来完成的。我们在创建、更新、以及其自身的检测机制,都会对这些规则进行更新。

场景4:Service 的创建、内部结构以及映射关系,我们都了解了。下面我们就要关心如何优雅的使用它,上面我们都是通过 Service 的 VIP 进行访问的。这存在的问题是,如果有服务与服务之间的调用,难道我还要知道所调用服务的 VIP 不成,对于 VIP 的访问能否更通用一些。

环境变量

在 Pod 中,集群中的 Service 会以环境变量的方式赋值在容器中,我们可以通过 {SERVICE_NAME}_SERVICE_HOST 和 {SERVICE_NAME}_SERVICE_PORT 进行获取(对于有多个 Port 的,可以通过带指定 PORT 名称的变量获得。)

busybox 中 环境变量如下:

dns 解析

第二种方式是通过 kube-dns 对 Service 进行域名解析,同样能达到服务发现的目的。查看 DNS 域名解析配


通过 nslookup 查询 dns 记录


原文

https://blog.csdn.net/yb223731/article/details/82705235

上一篇下一篇

猜你喜欢

热点阅读