栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

k8s篇- Service与Ingress对象详解

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

k8s篇- Service与Ingress对象详解

一、Service对象

为什么需要 Service:

每个Pod被创建后,都会有它自己的IP,但由于Pod存在生命周期,经常会被创建与销毁,一旦重新创建POD,该POD的IP就会发生变化。

所以这些POD应用需要对外提供一个统一的访问入口,即固定IP,外部才能正常访问,这个统一的访问入口就是service。


Service 定义:

我们可以将多个POD划分到同一个逻辑组中,并统一向外提供服务,这个逻辑组就是一个service。POD是通过Label Selector加入到指定的service中。

Service相当于是一个负载均衡器,用户请求会先到达service,再由service转发到它内部的某个POD上(默认以round-robin方式转发)。

请求(集群内部或外部) -> Service -> POD1,POD2,...

Service有四种类型:

不同service类型通过 services.spec.type 字段来指定。

  • ClusterIP:用于集群内部访问。该类型会为service分配一个IP,集群内部请求先到达service,再由service转发到其内部的某个POD上。
  • NodePort:用于集群外部访问。该类型会将Service的Port映射到集群的每个Node节点上,然后在集群之外,就能通过Node节点上的映射端口访问到这个Service。
  • LoadBalancer:用于集群外部访问
  • ExternalName:

Headless Service:

Service作为访问入口,它可以用 IP 或 service_name(要借助于内部DNS解析)这两种方式来访问。当创建好service时,系统会自动为Service分配一个IP,我们也可以通过services.spec.clusterIP 字段手动指定一个IP,但若这个字段设置为None,系统就不会再为这个service分配IP,后面就只能通过service_name来访问,而这种没有IP的service,就被称为Headless Service。

也就是,Headless表示这个service没有分配IP信息,只能通过service_name来访问。

service字段说明:

services.spec.
    clusterIP: 设置service的IP。若省略该字段,默认由系统随机分配
    ports:
        port: 设置service的访问端口
        targetPort: 设置service下的后端POD端口
        nodePort: 设置映射到node节点上的端口。当type为NodePort或LoadBalancer时,需要为service指定一个映射在Node节点上的端口
    selector: 设置标签选择器。POD根据匹配此标签来加入到此service下
    type: 定义service类型,可选值有ClusterIP(默认), NodePort, LoadBalancer, ExternalName
    sessionAffinity: 可选值是ClientIP或None。默认值为None,表示以round-robin方式将请求转发到后端Pod,若值为ClientIP,表示保持连接,请求始终会被调度到同一个Pod上

ClusterIP类型

需要将 services.spec.type 设置为 ClusterIP,该类型会为service分配一个IP,这个IP只能在集群内部访问,用户请求先到达service,再由service转发到其内部的某个POD上。

默认service是以round-robin方式将请求转发到后端Pod,若始终要转发到同一个POD上,需要设置services.spec.sessionAffinity。

请求(集群内部)---> service_ip/service_name:8080 -> POD1:80,POD2:80,POD3:80

示例1:带有IP的Service

第一步:创建一个ClusterIP类型的Service(手动指定IP或省略ClusterIP字段)

apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: default
spec:
  selector: 					#设置标签选择器。POD通过匹配此label来选择是否要加入到这个Service下
    app: myweb01
  type: ClusterIP 				#设置service类型为ClusterIP
  ClusterIP: 172.17.202.174     #为service指定一个IP,这个IP在集群内部可访问。若省略该字段,系统会自动分配一个IP
  ports:
  - name: nginx
    port: 8080
    protocol: TCP
    targetPort: 80
  sessionAffinity: None

第二步:创建POD(加入到此service中)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: svc01-pod-demo
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myweb01
  template:
    metadata:
      labels:
        app: myweb01
    spec:
      containers:
      - name: myweb01
        image: nginx:1.7.9
        ports:
        - name: http
          containerPort: 80

第三步:查看Service

$ kubectl get svc my-service
NAME          TYPE         CLUSTER-IP       EXTERNAL-IP    PORT(S)     AGE
my-service    ClusterIP    172.17.202.174            8080/TCP    4s

$ kubectl describe svc my-service
Name:              my-service
Namespace:         default
Labels:            
Annotations:       ...
Selector:          app=myweb01 			#service会通过匹配此label,选择哪些POD加入到这个service下
Type:              ClusterIP
IP:                172.17.2.14
Port:              nginx  8080/TCP
TargetPort:        80/TCP
Endpoints:         172.16.1.12:80,172.16.2.17:80,172.16.2.45:80 	#表示当前已加入到此service下的POD
Session Affinity:  None
Events:            

第四步:集群内部访问Service

  • 直接访问Service的IP;
  • 直接访问Service的Name(依靠DNS解析):同一个Namespace下直接通过servicename访问,跨Namespace访问需要加上namespace,如{servicename}.{namespace};
  • 通过环境变量访问:将service的一些IP、端口等信息,通过环境变量方式传到Pod里;
              集群内的Pod和Node
                     |
                     | curl 172.17.2.14:8080
                     | curl my-service:8080
                     | curl $service_name:$service_port
                     |
               ——————↓———————
              |  my-service  |
              |  172.17.2.14 |
              '——————↓———————'
                     |
 ____________________|_________________________
|           /        |                        |
|          /         |                        |
|       POD1         |          POD3           |
|  172.16.1.12:80    |      172.16.2.17:80     |
|                   POD2                       |
|              172.16.2.45:80                  |
|                                              |
|  Deployment                                  |
|  Pod Label: app=myweb01                      |
|______________________________________________|

补充说明:关于用service_name访问服务

域名解析操作是通过集群内部的DNS服务器来完成的,DNS服务器IP 就是名为kube-dns的service的IP,如下:

$ kubectl -n kube-system get svc kube-dns
NAME       TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)         AGE
kube-dns   ClusterIP   172.17.0.10           53/UDP,53/TCP   478d

$ kubectl -n kube-system describe svc kube-dns
Name:              kube-dns
Namespace:         kube-system
Labels:            k8s-app=kube-dns
                   kubernetes.io/cluster-service=true
                   kubernetes.io/name=KubeDNS
Annotations:       .....
Selector:          k8s-app=kube-dns
Type:              ClusterIP
IP:                172.17.0.10
Port:              dns  53/UDP
TargetPort:        53/UDP
Endpoints:         172.16.0.5:53,172.16.1.2:53
Port:              dns-tcp  53/TCP
TargetPort:        53/TCP
Endpoints:         172.16.0.5:53,172.16.1.2:53
Session Affinity:  ClientIP
Events:            

kube-dns这个service下还有两个名为coredns的POD,也就是说,域名解析功能实际上是通过这两个POD来实现的,所以要确保集群内有coredns容器处于运行状态。

$ kubectl -n kube-system get pods | grep coredns
NAME                           READY   STATUS        RESTARTS   AGE
coredns-86f77d55bb-2j2wc       1/1     Running       14         478d
coredns-86f77d55bb-gbjpg       1/1     Running       15         478d

可以进入到某个POD容器中查看/etc/resolv.conf文件中的nameserver,默认是指向kube-dns这个servcie的IP。

$ kubectl exec my-pod01-55d7dbfdfd-2w7sv cat /etc/resolv.conf
nameserver 172.17.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

集群中默认的域名后缀为:svc.cluster.local.

若两个service在不同的namespace中,它们的POD之间要通过域名互相访问时,就需要在默认域名后缀前加多一级,即加上对应的namespace名称,也就是【NAMESPACE.svc.cluster.local.】。

比如,对于在同一个namespace下,若service1的POD访问service2的POD,则直接【ping service2】就能解析域名;对于跨Namespace情况(service2在名为testns的namespace下),则需要【ping service2.testns】才能解析域名。

一个完整service名称为:SERVICE_NAME.NAMESPACE.svc.cluster.local.

示例2:Headless Service(无IP的Service)

第一步:创建一个ClusterIP类型的Headless Service(ClusterIP字段设置为None)

apiVersion: v1
kind: Service
metadata:
  name: my-svc01
  namespace: mytest
spec:
  selector:
    app: my-test01-pod
  type: ClusterIP
  clusterIP: None 			#指定为None,创建的service就不会分配到IP信息
  ports:
  - name: nginx
    port: 80
    targetPort: 8082

第二步:创建POD(加入到此service中)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test01-pod
  namespace: mytest
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-test01-pod
  template:
    metadata:
      labels:
        app: my-test01-pod
    spec:
      containers:
      - name: my-nginx
        image: nginx:1.7.9
        ports:
        - name: http
          containerPort: 8082

第三步:查看service

$ kubectl -n mytest get svc my-svc01
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
my-svc01   ClusterIP   None                 80/TCP    11m


$ kubectl -n mytest describe svc my-svc01
Name:              my-svc01
Namespace:         mytest
Labels:            
Annotations:       ...
Selector:          app=my-test01-pod
Type:              ClusterIP
IP:                None
Port:              nginx  80/TCP
TargetPort:        8082/TCP
Endpoints:         172.16.1.169:8082,172.16.2.52:8082,172.16.1.143:8082
Session Affinity:  None
Events:            

第四步:通过域名(即service_name)访问服务

访问流程:

                集群内的Pod
                     |
                     | curl my-svc01:8082 (直接解析到后端POD的IP上,且指定的是Pod容器里的服务实际监听的Port)
                     |
 ____________________|_________________________
|           /        |                        |
|          /         |                        |
|       POD1         |          POD3           |
| 172.16.2.52:8082   |    172.16.1.143:8082    |
|                   POD2                       |
|              172.16.1.169:8082               |
|                                              |
|  Deployment                                  |
|  Pod Label: app=myweb01                      |
|______________________________________________|

查看一下POD容器里面服务监听的端口,如下:

$ kubectl -n mytest get pods
NAME                             READY   STATUS    RESTARTS   AGE  IP
test01-pod-5cfd78675c-wcrgx      1/1     Running   0          20m  172.16.2.52
test01-pod-5cfd78675c-abxyd      1/1     Running   0          20m  172.16.1.143
test01-pod-5cfd78675c-xxsjz      1/1     Running   0          20m  172.16.1.169

#因为在打包nginx镜像时,就已经将nginx服务的监听端口修改为8082了
$ kubectl -n mytest exec -it test01-pod-5cfd78675c-wcrgx bash
root@test01-pod-5cfd78675c-wcrgx:/# ss -tnlp
State     Recv-Q   Send-Q    Local Address:Port      Peer Address:Port
LISTEN    0        128                   *:8082                 *:*      users:(("nginx",1,10))

跨namespace访问,在default命名空间下的Pod容器里面,访问mytest命名空间下的my-svc01服务,如下:

$ kubectl -n default exec testpod bash
root@testpod:/# ping my-svc01.mytest
PING my-svc01.mytest.svc.cluster.local (172.16.2.52) 56(84) bytes of data.
64 bytes from 172.16.2.52: icmp_seq=1 ttl=63 time=0.266 ms
...
root@testpod:/# curl my-svc01.mytest:8082
test01-pod-5cfd78675c-wcrgx
root@testpod:/# curl my-svc01.mytest:8082
test01-pod-5cfd78675c-xxsjz

不跨namespace访问,在mytest命名空间下的Pod容器里面访问服务,如下:

$ kubectl -n zjmtest exec testpod2 bash
root@testpod:/# ping my-svc01
PING my-svc01.mytest.svc.cluster.local (172.16.2.52): 48 data bytes
64 bytes from 172.16.2.52: icmp_seq=1 ttl=63 time=0.266 ms
...
root@testpod2:/# curl my-svc01:8082
test01-pod-5cfd78675c-wcrgx
root@testpod2:/# curl my-svc01:8082
test01-pod-5cfd78675c-xxsjz

NodePort类型

需要将 services.spec.type 设置为 NodePort,该类型是建立在ClusterIP基础上的,所以必须要为service分配一个IP,所以不能将 services.spec.clusterIP 字段设置为None。

设置为NodePort类型后,系统会在集群中的每个节点上监听一个nodePort端口。当在集群外部发起一个请求时,请求会先到达节点上监听的端口,然后再路由到service的IP,最后由service转发到内部POD上;

请求(集群外部)---> node_ip:31180 ---> service_ip:8080 ---> POD1:80,POD2:80,POD3:80
示例:

第一步:创建一个NodePort类型的service(必须指定一个IP)

apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: default
spec:
  selector:
    app: myweb01
  type: NodePort
  clusterIP: 172.17.99.99
  ports:
  - name: nginx
    port: 8080           #service的端口
    targetPort: 80       #service下的Pod端口
    nodePort: 31180      #当type为NodePort时,需要指定一个端口,该端口会监听在集群内的每个节点上
  sessionAffinity: None

第二步:创建POD(加入到此service中)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: svc01-pod-demo
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myweb01
  template:
    metadata:
      labels:
        app: myweb01
    spec:
      containers:
      - name: myweb01
        image: nginx:1.7.9
        ports:
        - name: http
          containerPort: 80

第三步:查看Service

$ kubectl get svc my-service -owide
NAME         TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE   SELECTOR
my-service   NodePort   172.17.99.99           8080:31180/TCP   21m   app=myweb01

$ kubectl describe svc my-service
Name:                     my-service
Namespace:                default
Labels:                   
Annotations:              
Selector:                 app=myweb01
Type:                     NodePort
IP:                       172.17.99.99
Port:                     nginx  8080/TCP
TargetPort:               80/TCP
NodePort:                 nginx  31180/TCP
Endpoints:                172.16.1.164:80,172.16.2.169:80,172.16.2.46:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   

第四步:查看集群node节点上的监听端口(会在每个node节点监听上31180端口)

$ netstat -tunlp | grep 31180
tcp6    0    0 :::31180      :::*        LISTEN      4164/kube-proxy

第五步:集群外部访问Service

$ kubectl get nodes -owide
NAME      STATUS   ROLES    AGE    VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION               CONTAINER-RUNTIME
master1   Ready    master   478d   v1.15.1   172.24.11.208           CentOS Linux 7 (Core)   3.10.0-957.21.3.el7.x86_64   docker://18.9.2
master2   Ready    master   478d   v1.15.1   172.24.11.209           CentOS Linux 7 (Core)   3.10.0-957.21.3.el7.x86_64   docker://18.9.2
master3   Ready    master   478d   v1.15.1   172.24.11.207           CentOS Linux 7 (Core)   3.10.0-957.21.3.el7.x86_64   docker://18.9.2
node1     Ready       478d   v1.15.1   172.24.11.210           CentOS Linux 7 (Core)   3.10.0-957.21.3.el7.x86_64   docker://18.9.2
node2     Ready       478d   v1.15.1   172.24.11.212           CentOS Linux 7 (Core)   3.10.0-957.21.3.el7.x86_64   docker://18.9.2
node3     Ready       478d   v1.15.1   172.24.11.211           CentOS Linux 7 (Core)   3.10.0-957.21.3.el7.x86_64   docker://18.9.2

$ curl 172.24.11.210:31180
$ curl 172.24.11.211:31180
$ curl 172.24.11.212:31180

访问流程:

				     集群外部
                        |
                        | curl node_ip:node_port
                        |
 _______________________|_________________________
|                       |                         |
| 集群节点               |                         |
|  		      .—————————↓———————————.             |
|  		      | nodes_ip:node_port	|             |
|  		      | 172.24.11.210:31180 |             |
|  		      | 172.24.11.211:31180 |             |
|  		      | 172.24.11.212:31180 |		      |
|  		      '—————————↓———————————'             |
|  		    			|                         |
|             .—————————↓——————————.              |
|             |    my-service      |              |
|             | 172.17.99.99:8080  |              |
|             '—————————↓——————————'              |
|                       |                         |
|   ____________________|______________________   |
|  |           /        |                     |  |
|  |          /         |                     |  |
|  |       POD1         |          POD3        |  |
|  |  172.16.1.164:80   |      172.16.2.46:80  |  |
|  |                   POD2                    |  |
|  |              172.16.2.169:80              |  |
|  |                                           |  |
|  |  Deployment                               |  |
|  |  Pod Label: app=myweb01                   |  |
|  |___________________________________________|  |
|_________________________________________________|

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/291657.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号