目录

一、Service基本概念

1、Pod的特征

  1. Pod等资源的概念

2.解决pod进行如此多变化时的解决方案

2、Service

1. Kubernetes Service 定义了这样一种抽象:

2. Service的实现类型

3、Service模型

4、Endpoint Controller

5、Kube-proxy  iptables

6、Kube-proxy IPVS

二、服务发现

1、创建后端Deployment

2、创建Service

3、整理文件并创建

4、查看Service

1. 查看service简明信息,可以获取service提供服务的ip地址和端口

2.测试service是否正常提供服务

3. 使用describe命令可以查看service详细信息

5、创建可供外部访问的Service

三、集群中的DNS

1、CoreDNS

2、查看服务的完整域名

3、DNS记录

四、Headless Service(无头服务)

1、Headless Service

2、创建Headless Service

3、使用Headless Service

1.查看Headless Service的信息,可以看到没有IP地址

2.使用的时候利用DNS功能,通过访问“Headless-svc”或“headless-svc.default”来访问服务


一、Service基本概念

1、Pod的特征

  1. Pod等资源的概念

①.Pod有自己独立的IP

②.Pod可以被创建,销毁

③.当扩容时,pod的数量会发生变更(可以扩、缩容)

④.当pod故障时,replicaset会创建新的pod

20aa679d2757476284d9a7a23858c370.png

2.解决pod进行如此多变化时的解决方案

e45011bfd96340aaba7aa147212b004c.png

一组pod对应一个服务,通过服务访问后端

2、Service

1. Kubernetes Service 定义了这样一种抽象:

        逻辑上的一组Pod,一种可以访问它们的策略 — — 通常称为微服务

        这一组Pod能够被Service访问到,通常是通过Label Selector 实现的

2. Service的实现类型

ClusterIP 提供一个集群内部的虚拟IP地址以供Pod访问(默认模式),只能供内部使用
NodePort 在Node上打开一个端口以供外部访问
LoadBalancer 通过外部的负载均衡器来访问
官网(如何发布服务): 服务(Service) | Kubernetes

3、Service模型

edf81bcf0d0b4c09bbac44dd6085342d.png

每个节点都有一个Kube-Proxy服务,负责iptables(路由);

Endpoint Controller负责映射关系,通过其知道内部IP地址,内部IP映射到服务

最终通过Kube-proxy组件进行工作

4、Endpoint Controller

1.负责生成和维护所有endpoint对象的控制器
2.负责监听service和对应pod的变化
3.监听到service被删除,则删除和该service同名的endpoint对象

4.监听到新的service被创建,

    则根据新建service信息获取相关pod列表,然后创建对应endpoint对象

5.监听到service被更新,

   则根据更新后的service信息获取相关pod列表,然后更新对应endpoint对象

6.监听到pod事件,则更新对应的service的endpoint对象,将pod IP 记录到endpoint中

    endpoint其实就是个列表

5、Kube-proxy  iptables

f964fec1c22f4bab965367f764aee56b.png

集群内部的Client可以访问服务IP,通过服务IP可以找到集群内部的Pod

6、Kube-proxy IPVS

        从k8s的1.8版本开始,kube-proxy引入了IPVS模式,IPVS模式与iptables实现方式类似,但是采用的hash表,因此当service数量达到一定规模时,hash查表的速度优势就会显现出来,从而提高service的服务性能

Service基数 1 5,000 20,000
Rules基数 8 40,000 160,000
增加1条iptables规则 50us 11min 5hour
增加1条ipvs规则 30us 50us 70us

二、服务发现

1、创建后端Deployment

1. 创建一个deployment,特别注意其中的几个选项要和service匹配

        - Template 选项必须配置labels,示例中配置参数为“app:httpd”,该配置和service匹配

        Pod的属性中Ports选项指定pod对外提供服务的容器端口,图例中为"containerPort:80",该端口需要和service匹配

apiVersion: apps/v1    #版本
kind: Deployment    
metadata:              #元数据
  name: httpd
spec:                  #描述
  replicas: 3          #三副本
  selector:            #选择器
    matchLabels:       #匹配标签
      app: httpd
  template:            #模板
    metadata:          #模板元数据
      labels:          #模板标签
        app: httpd
    spec:              #针对template的描述
      containers:      #容器
      - name: httpd
        image: httpd
        ports:
        - containerPort: 80

参考文档: Deployments | Kubernetes

2、创建Service

1. 创建一个httpd-service.yaml,在编写时需要注意以下几点:

        - spec参数中添加selector字段,指定一组label的键值对,该值在示例中为"app:httpd",和上一步创建的deployment匹配

        - Port参数中,需要指定两个端口

                - Ports为该service的端口,客户端访问该服务时使用

                - targetPort 为后端pod的端口,需要与之前创建的pod提供服务端口一致

apiVersion: v1                                                                                     
kind: Service    #类型为service
metadata:
  name: httpd-svc
spec:
  selector:
    app: httpd   #要和上一个文件标签要对上
  ports:
    - protocol: TCP 
      port: 8080        #对应service端口
      targetPort: 80    #对应pod端口

参考文档: 服务(Service) | Kubernetes

3、整理文件并创建

$ kubectl apply -f- <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd
spec:
  replicas: 3
  selector:
    matchLabels:
      app: httpd
  template:
    metadata:
      labels:
        app: httpd
    spec:
      containers:
      - name: httpd
        image: httpd
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: httpd-svc
spec:
  selector:
    app: httpd
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 80
EOF

4、查看Service

1. 查看service简明信息,可以获取service提供服务的ip地址和端口

$ kubectl get deployments.apps httpd 
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
httpd   3/3     3            3           76s

$ kubectl get service httpd-svc  #查看service,集群类型默认就是Cluster-IP
NAME        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
httpd-svc   ClusterIP   10.100.160.205   <none>        8080/TCP   107s

$ kubectl get endpoints httpd-svc #查看后端对应IP
NAME        ENDPOINTS                                             AGE
httpd-svc   172.16.126.7:80,172.16.194.102:80,172.16.194.103:80   16m

$ kubectl get pod -owide #列出pod所在节点,纯文本格式输出,包含所有附加信息
NAME                                      READY   STATUS    RESTARTS        AGE    IP               NODE          NOMINATED NODE   READINESS GATES
 k8s-worker2   <none>           <none>
httpd-7cd5646885-9rkwj                    1/1     Running   0               32m    172.16.126.7     k8s-worker2   <none>           <none>
httpd-7cd5646885-jzd5z                    1/1     Running   0               32m    172.16.194.102   k8s-worker1   <none>           <none>
httpd-7cd5646885-n6t7s                    1/1     Running   0               32m    172.16.194.103   k8s-worker1   <none>           <none>

2.测试service是否正常提供服务

$ curl 10.100.160.205:8080
<html><body><h1>It works!</h1></body></html>

3. 使用describe命令可以查看service详细信息

如:endpoints信息,显示service关联pod的地址和服务端口

$ kubectl describe service httpd-svc 
Name:              httpd-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=httpd
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.100.160.205
IPs:               10.100.160.205
Port:              <unset>  8080/TCP
TargetPort:        80/TCP
Endpoints:         172.16.126.7:80,172.16.194.102:80,172.16.194.103:80
Session Affinity:  None
Events:            <none>

5、创建可供外部访问的Service

1.如果需要service可供外部进行访问,可以使用Nodeport的方式

2.编辑Yaml文件时,添加type(类型)参数

3.可以在使用nodeport字段指定对外服务端口,如果不进行指定,系统会自动分配空闲端口

4.访问时通过访问 “节点IP地址:端口” 进行服务使用

$ vim http_service.yml
apiVersion: v1                                                                                     
kind: Service
metadata:
  name: httpd-svc
spec:
  type: NodePort
  selector:
    app: httpd
  ports:
    - protocol: TCP 
      port: 8080
      targetPort: 80
      nodePort: 30144 #指明对外节点端口,不指明时随机

5.测试

$ kubectl get service httpd-svc #查看类型已经变为NodePort,端口号也改变
NAME        TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
httpd-svc   NodePort   10.100.160.205   <none>        8080:30144/TCP   18h

kiosk@k8s-master:~$ curl k8s-worker1:30144
<html><body><h1>It works!</h1></body></html>

kiosk@k8s-master:~$ curl k8s-worker2:30144
<html><body><h1>It works!</h1></body></html>

参考文档: 服务(Service) | Kubernetes

三、集群中的DNS

1、CoreDNS

1.CoreDNS是一个轻量级的DNS服务器,通过插件的形式在Kubernetes集群内实现,提供服务发现功能,使得用户除了可以用IP访问服务外,也可用域名来访问服务

2.从1.13版本的Kubernetes开始CoreDNS取代了原有的kubeDNS,成为了kubernetes集群内部的默认DNS组件

$ kubectl get pods -n kube-system | grep dns    #查看coredns的pod
coredns-74586cf9b6-fcmv6                   1/1     Running   13 (27h ago)   25d
coredns-74586cf9b6-wfbn4                   1/1     Running   13 (27h ago)   25d

$ kubectl get pods -o wide -n kube-system  | grep dns
coredns-74586cf9b6-fcmv6                   1/1     Running   13 (27h ago)   25d   172.16.235.232    k8s-master    <none>           <none>
coredns-74586cf9b6-wfbn4                   1/1     Running   13 (27h ago)   25d   172.16.235.234    k8s-master    <none>           <none>

$ kubectl get deployments.apps -n kube-system  #经过名称反推coredns为deployment创建出来
NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
calico-kube-controllers   1/1     1            1           25d
coredns                   2/2     2            2           25d
metrics-server            1/1     1            1           23d

2、查看服务的完整域名

1.创建一个clientpod,用于查看httpd服务的完整名字

2.在记录总可以看到,服务的IP地址对应的名称是httpd-svc.default.svc.cluster.local

$ kubectl apply -f- <<EOF    #创建一个持续运行的Pod
apiVersion: v1
kind: Pod
metadata:
  name: clientpod
spec:
  containers:
    - name: clientpod
      image: busybox:1.28.3
      args:
      - /bin/sh  #指定解释器
      - -c       
      - sleep 3h #睡眠时间
EOF

3.测试

$ kubectl get service    #查看集群IP地址
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
httpd-svc       NodePort    10.100.160.205   <none>        8080:30144/TCP   23h
kubernetes      ClusterIP   10.96.0.1        <none>        443/TCP          25d #k8s自身的集群

$ nslookup 10.100.160.205    #查询DNS名
** server can't find 205.160.100.10.in-addr.arpa: NXDOMAIN 
无法解析,要在pod当中查,因为coredns是在集群内部

$ kubectl exec -it clientpod -- /bin/sh #进入pod
/ # nslookup 10.100.160.205
Server:    10.96.0.10    #服务器相关信息
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      10.100.160.205    #地址dns对应的是谁
Address 1: 10.100.160.205 httpd-svc.default.svc.cluster.local

/ # nslookup httpd-svc.default.svc.cluster.local #一样可以解析
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      httpd-svc.default.svc.cluster.local
Address 1: 10.100.160.205 httpd-svc.default.svc.cluster.local

/ # wget httpd-svc.default.svc.cluster.local:8080
Connecting to httpd-svc.default.svc.cluster.local:8080 (10.100.160.205:8080)
index.html           100% |**************************************************|    45   0:00:00 ETA
/ # cat index.html #验证可以正常工作
<html><body><h1>It works!</h1></body></html>

参考文档: 为容器设置启动时要执行的命令和参数 | Kubernetes

3、DNS记录

1.服务的DNS记录名称为:

        <服务名称>.<namespace>.svc.cluster.local

2.服务后端的deployment中Pod的DNS记录名称为:

        <PodIP>.<服务名称>.<namespace>.svc.cluster.local

3.ClientPod访问服务时,可以使用<服务名称>.<namespace>便携抵达服务、甚至在ClientPod与服务在同一namespace时,直接使用<服务名称>进行访问

/ # nslookup 172.16.126.7    #反向解析,查看podIP通过谁来解析
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      172.16.126.7
Address 1: 172.16.126.7 172-16-126-7.httpd-svc.default.svc.cluster.local

四、Headless Service(无头服务)

1、Headless Service

1. 有的时候不需要或者不想要负载均衡,以及单独的Service IP,可以通过指定Cluster IP的值为“None” 来创建Headless Service
2. 对这类Service 并不会分配Cluster IP,kube-proxy不会处理他们,并且平台也不会为他们进行负载均衡和路由
3. 对定义了selector的Headless Service,意味着后端有一些提供业务的Pod,Endpoint控制器在API中创建了Endpoint记录,当通过域名访问服务时,流量会被直接转发到对应的Pod上

2、创建Headless Service

1. 创建一个简单的deployment和Headless Service。(区别多了一条clusterIP:None参数)

$ kubectl apply -f- <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd
spec:
  replicas: 3
  selector:
    matchLabels:
      app: httpd
  template:
    metadata:
      labels:
        app: httpd
    spec:
      containers:
      - name: httpd
        image: httpd
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: headless-svc
spec:
  selector:
    app: httpd
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  clusterIP: None
EOF

3、使用Headless Service

1.查看Headless Service的信息,可以看到没有IP地址

$ kubectl get service
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
headless-svc    ClusterIP   None             <none>        80/TCP           9s
...
$ kubectl get endpoints
NAME                                          ENDPOINTS                                             AGE
headless-svc                                  172.16.126.7:80,172.16.194.102:80,172.16.194.103:80   2m38s
...

2.使用的时候利用DNS功能,通过访问“Headless-svc”或“headless-svc.default”来访问服务

观察看出,域名解析到的IP地址其实是Pod的IP地址

$ kubectl exec -it clientpod -- /bin/sh
/ # nslookup headless-svc
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      headless-svc    #解析出了3个IP
Address 1: 172.16.126.7 172-16-126-7.httpd-svc.default.svc.cluster.local
Address 2: 172.16.194.102 172-16-194-102.httpd-svc.default.svc.cluster.local
Address 3: 172.16.194.103 172-16-194-103.httpd-svc.default.svc.cluster.local
'解析到了后端Pod的IP,通过名字访问,访问的就是后端的Pod,只是做了转发功能

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐