k8s selector_Kubernetes 服务选择(selector)

K8S中的Service是一个抽象概念,它定义了一个服务的多个pod逻辑合集和访问pod的策略,一般把service称为微服务

举个例子:一个a服务运行3个pod,b服务怎么访问a服务的pod,pod的ip都不是持久化的重启之后就会有变化。

这时候b服务可以访问跟a服务绑定的service,service信息是固定的提前告诉b就行了,service通过Label Selector跟a服务的pod绑定,无论a的pod如何变化对b来说都是透明的。

创建服务对应的后端

先创建一个可以充当 backend pods 的 deployment

文件名:service-deployment-hello.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

name: hello

labels:

app: hello

spec:

selector:

matchLabels:

app: hello

replicas: 5

template:

metadata:

labels:

app: hello

spec:

containers:

- name: hello

image: nginx

imagePullPolicy: IfNotPresent

resources:

requests:

cpu: 100m

memory: 100Mi

ports:

- containerPort: 80

这个普通的 Deployment。唯一需要注意的是 ports 信息,它显示了这个 Pod 暴露了哪些端口,类似于 docker 中 expose 的意义。但是一般来讲,这个信息是没必要的。因为 Pod 具有唯一的集群内可访问的 ip, 不会跟其他 Pod 产生冲突,任何监听了 0.0.0.0 这样地址的服务都可以通过 :的方式访问。这里写上的作用主要是提供一些更明确的信息,也方便一些工具比如 kubectl 的使用而已。

在终端执行如下命令创建 deployment:

ctr -n k8s.io i import /share/images/nginx.tar

kubectl create -f /share/lesson/kubernetes/service-deployment-hello.yaml

看下最终我们创建出来的 pods 结果

kubectl get po

然后我们来创建对应的 Service

文件名:service-svc-hello.yaml

apiVersion: v1

kind: Service

metadata:

name: hello

labels:

app: hello

spec:

ports:

- port: 80

targetPort: 80

selector:

app: hello

Service 的 spec 部分就是它的主要信息,主要包含以下内容:

ports: 是一个端口信息列表,也就是说一个 Service 可以管理多个端口的访问。本身 Pod 可以对外暴露多个端口

port: service 绑定的端口,也就是这个 Service 所对应的 ip 监听的端口

targetPort: backend 的端口,也就是 Pod 所暴露的端口

selector: 标签选择,符合这个标签的 Pod 会作为这个 Service 的 backend。

在终端执行如下命令创建并查看:

kubectl create -f /share/lesson/kubernetes/service-svc-hello.yaml

kubectl get svc

这条命令用来查看 default namespace 下的 Service 信息列表。因为 default namespace 是默认值,可不写。 -o wide 会增加一些额外的信息展示,看下结果:

除了 yaml 中我们填写的信息之外,kubernetes 帮我们补充了其他的默认信息:

Type: 类型,决定着 Service 如何对外提供服务。因为我们在 yaml 里未设置,所以这里用的默认值: ClusterIP, 具体有哪些可选的会在下面讲解。

Cluster IP: 系统帮我们自动生成的 ip 地址。这个 ip 地址的范围是可配置的,并且只能在集群内部访问。

看下完整的 yaml:

kubectl get svc hello -o yaml

这里又比刚才的列表页显示了更多的信息,需要注意的如下:

sessionAffinity: 这是负载均衡里面比较常见的一个概念,就是让来自于同一个 client 的请求落到同一个 backend 上。默认为 None。

ports[0].protocol: 端口协议,默认为 TCP ,目前只支持 TCP/UDP。

容器的轻量级特性,让作为 backend 的 Pod 可以比传统方式更加随意地起停。Service 只记录了 labelSelector,但具体的映射关系仍然需要有个地方记录下来。当然这个工作是由 kubernetes 来完成,而不是用户。记录这个映射关系的资源就是 Endpoints,同一个 namespace 下与 Service 同名的 Endpoints Resource 即是这个映射关系的管理者。刚才我们创建好了 Service 之后,Kubernetes 已经帮我们创建好了相应的 Endpoints 资源:

kubectl get ep hello -o yaml

注:ep 是 endpoints 的简称。

主要信息在 subsets 里面,addresses 列表记录了每个 backend 的信息,这里面的两个 Pod 信息就是我们刚才创建的两个 Pod 。addresses 里面记录了 Pod 的 ip、所在的主机名称、以及具体的 Resource Object 的引用。

下面我们可以通过访问这个 service 的 ip(即CLUSTERIP) 来访问这个服务了。

helloclusterip=$(kubectl get svc hello -o go-template --template='{{.spec.clusterIP}}')

echo $helloclusterip

curl $helloclusterip

其中$helloclusterip即上面的 service 生成之后所分配的 ip ,每次创建的 ip 都是不一样的。

注意:

我们的hello程序运行了一个页面,其中显示了运行其的 host 的 hostname, 在这个场景中就是 pod 的 hostname, 而 pod 的 hostname 一般就是其名字。

这里我们可以观察出来, Service 做了负载均衡,将流量转发到了不同的pod实例上。

DNS

上面的使用 ip 的使用有一个很致命的问题,就是它不好记,而且不方便使用。如果你让系统自动分配,那很难知道生成的结果是什么,无法提前配置。如果是自己选好固定的 ip ,服务多了又不好管理。而服务发现就解决了这个问题。我们仍然拿刚才的实验继续验证下。

首先要注意的是,service 的 ip 是可以在 kubernetes 的 node 上和 pod 里面直接访问的。但 dns 只能在 pod 里面访问,因为它需要配置 kubernetes 的 dns 服务为解析服务器,而且还要配置其他参数。 kubernetes 在启动每个 pod 时都会将这些配置好。

准备busybox pod

ctr -n k8s.io i import /share/images/busybox.latest.tar

kubectl create -f /share/lesson/kubernetes/busybox.yaml

进入busybox pod

kubectl exec -it busybox sh

使用域名访问服务,而不是IP

wget -O- hello

可以看到,运行结果与上面通过 curl 是一样的。那么它是怎么实现的呢?

我们用 nslookup 命令来探究下:

nslookup hello

nslookup 命令用于解析某一个域名,会得到如下类似的结果

Server: 10.96.0.10

Address: 10.96.0.10:53

Name: hello.default.svc.cluster.local

Address: 10.96.177.43

这里我们需要注意的是:

(1)server 的地址,这里显示的 server 就是 dns server, 它就是 kubernetes 中 dns 服务的地址。

kubectl get svc -n kube-system

在部署完集群后,这个 svc 就自动创建了。

(2)解析到的名字

dns server 帮我们解析到了正确的 ip ,但是后面显示的域名比较长。这里涉及到了一个 dns search-path 的概念。我们看下 dns resolve 的配置文件。

cat /etc/resolv.conf

简单来讲,当我们查询 hello 这个域名时,dns server 会帮我们查询下面的几个名字:

hello

hello.default.svc.cluster.local

hello.svc.cluster.local

hello.cluster.local

其中 hello.default.svc.cluster.local 是正确的域名,它的格式为..svc.。其中 suffix 是集群配置,而 namespace 则视具体的情况而定。有了 search path, kubernetes 的服务不仅实现了通过域名访问,而且实现了最简单的仅通过名字即可访问的模式。在实际的业务场景中,这是非常便利的一个条件。想象一个常见的场景, 有一个 namespace 叫 http,里面有服务 a 、 b, 有一个 namespace 叫 storage, 里面有 redis、db 两个服务,那么 a、b 之间的互相访问只需要知道对方的名字即可,不需要知道它们所处的 namespace(可以方便地一起迁移)。而 a b 想要访问 redis 或者 db, 那么也仅仅需要用 redis.storage 或者 db.storage 这两个名字即可。

kubernetes 在线安装过程录屏

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kubernetes中,Selector用于筛选和选择特定的资源对象。通过Selector,可以根据资源对象的标签或其他属性来选择要操作的对象。使用Selector可以很方便地对资源对象进行分类和组织。 在引用中提到了使用kubectl命令连接到已创建的Kubernetes集群,并展示了如何查看和修改Kubernetes对象中的元数据,其中包括标签、注解和OwnerReference。 在引用中提到了两种常见的Selector:等式型Selector和集合型Selector。等式型Selector使用等式运算符来筛选出具有特定属性值的资源对象,而集合型Selector使用集合运算符来筛选具有特定属性集合的资源对象。 引用中提到了Kubernetes的元数据部分,其中包括标签(Labels)用于识别资源、注解(Annotations)用于描述资源和OwnerReference用于描述资源之间的关系。这些元数据在Kubernetes中起着非常重要的作用。 综上所述,KubernetesSelector是用于选择和筛选特定资源对象的机制,可以根据资源对象的属性值来进行选择。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [应用编排与管理:核心原理](https://blog.csdn.net/alisystemsoftware/article/details/109335267)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值