Kubernetes Service 类型
  AWkq7aIjuRwO 2023年11月02日 66 0

Service

service是kubernetes核心资源之一,通常被看作微服务的一种实现.它事实上是一种服务发现的,是一种抽象,在k8s资源对象创建以后,是一种规则的抽象,要不然是iptables要不然是ipvs,它事实上是一组规则的抽象,service通过endpoint,endpoint通过标签选择器的方式和pod关联上,把你的pod给绑定到指定的endpoint,未来通过指定的ip就能访问到service

定义一个Service

type 类型 Service 的类型

service资源类型分为多少种种类,默认情况是Cluster Ip 除了这个以外还是ExternalName 还有个叫LoadBalancer还有个叫NodePort

就是service的四种类型

[root@k8s-master1 deployment]# kubectl explain service.spec.type
KIND:     Service
VERSION:  v1

FIELD:    type <string>

DESCRIPTION:
     type determines how the Service is exposed. Defaults to ClusterIP. Valid
     options are ExternalName, ClusterIP, NodePort, and LoadBalancer.
     "ClusterIP" allocates a cluster-internal IP address for load-balancing to
     endpoints. Endpoints are determined by the selector or if that is not
     specified, by manual construction of an Endpoints object or EndpointSlice
     objects. If clusterIP is "None", no virtual IP is allocated and the
     endpoints are published as a set of endpoints rather than a virtual IP.
     "NodePort" builds on ClusterIP and allocates a port on every node which
     routes to the same endpoints as the clusterIP. "LoadBalancer" builds on
     NodePort and creates an external load-balancer (if supported in the current
     cloud) which routes to the same endpoints as the clusterIP. "ExternalName"
     aliases this service to the specified externalName. Several other fields do
     not apply to ExternalName services. More info:
     https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types

     Possible enum values:
     - `"ClusterIP"` means a service will only be accessible inside the cluster,
     #service 第一种类型 也是默认的
     via the cluster IP.
     - `"ExternalName"` means a service consists of only a reference to an
     #service 第二种类型
     external name that kubedns or equivalent will return as a CNAME record,
     with no exposing or proxying of any pods involved.
     - `"LoadBalancer"` means a service will be exposed via an external load
     #service 第三种类型
     balancer (if the cloud provider supports it), in addition to 'NodePort'
     type.
     - `"NodePort"` means a service will be exposed on one port of every node,
     #service 第四种类型
     in addition to 'ClusterIP' type.

Selector 标签选择器 Service的标签选择器

这个标签选择器主要是和pod关联的

[root@k8s-master1 deployment]# kubectl explain service.spec.selector
KIND:     Service
VERSION:  v1

FIELD:    selector <map[string]string>

DESCRIPTION:
     Route service traffic to pods with label keys and values matching this
     selector. If empty or not present, the service is assumed to have an
     external process managing its endpoints, which Kubernetes will not modify.
     Only applies to types ClusterIP, NodePort, and LoadBalancer. Ignored if
     type is ExternalName. More info:
     https://kubernetes.io/docs/concepts/services-networking/service/

ports

[root@k8s-master1 deployment]# kubectl explain service.spec.ports
KIND:     Service
VERSION:  v1

RESOURCE: ports <[]Object>

DESCRIPTION:
     The list of ports that are exposed by this service. More info:
     https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies

     ServicePort contains information on service's port.

FIELDS:
   appProtocol  <string>
   #协议
     The application protocol for this port. This field follows standard
     Kubernetes label syntax. Un-prefixed names are reserved for IANA standard
     service names (as per RFC-6335 and
     https://www.iana.org/assignments/service-names). Non-standard protocols
     should use prefixed names such as mycompany.com/my-custom-protocol.

   name <string>
   #名字 可写可不写
     The name of this port within the service. This must be a DNS_LABEL. All
     ports within a ServiceSpec must have unique names. When considering the
     endpoints for a Service, this must match the 'name' field in the
     EndpointPort. Optional if only one ServicePort is defined on this service.

   nodePort     <integer>
   #如果这种service 的类型(type)本身是NodePort的时候,这个字段nodePort在这里面才有效,不是那个是无效的
     The port on each node on which this service is exposed when type is
     NodePort or LoadBalancer. Usually assigned by the system. If a value is
     specified, in-range, and not in use it will be used, otherwise the
     operation will fail. If not specified, a port will be allocated if this
     Service requires one. If this field is specified when creating a Service
     which does not need it, creation will fail. This field will be wiped when
     updating a Service to no longer need it (e.g. changing type from NodePort
     to ClusterIP). More info:
     https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport

   port <integer> -required-
   #必选字段,定义我们service的端口号 
     The port that will be exposed by this service.

   protocol     <string>
   #协议
     The IP protocol for this port. Supports "TCP", "UDP", and "SCTP". Default
     is TCP.

     Possible enum values:
     - `"SCTP"` is the SCTP protocol.
     - `"TCP"` is the TCP protocol.
     - `"UDP"` is the UDP protocol.

   targetPort   <string>
   #定义后端的pod的端口号    他和上面那个port字段 通常一块出现 是个映射关系  这说白了就是iptalbes或者ipvs的一个规则,不管是nat还是dr  在lvs定义的时候 要定义ip+端口号映射到后端真实服务器的某个ip和端口号 
     Number or name of the port to access on the pods targeted by the service.
     Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. If
     this is a string, it will be looked up as a named port in the target Pod's
     container ports. If this is not specified, the value of the 'port' field is
     used (an identity map). This field is ignored for services with
     clusterIP=None, and should be omitted or set equal to the 'port' field.
     More info:
     https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service

ClusterIP

clusterip和上面的nodeport 如果不自定义 会给我们自动生成的 如果我们类型(type)本身是Cluster IP 和nodeport类型的时候他会自动给我们产生一个ip 不需要人为定义的

externalTrafficPolicy 外部流量引用策略

这个外部流量引用策略只有在类型(type)为ExternalName的类型的service 这个才有效

loadBalancerIP

负载均衡使用的ip地址,这个只有类型(type)为LoadBalancer 的类型的service 这个才有效

ExternalName

对应的externalName类型

我们开始定义一个Service

[root@k8s-master1 service]# cat service-v1.yaml
apiVersion: v1 #service是核心群组,所有版本为v1
kind: Service
metadata:
  name: my-service-nginx
  labels:
    run: nginx #给service定义标签没有任何意义 以后查询可能方便点
spec:
  selector:  #标签选择器
    app: nginx  #在生产上需要定义大量标签  比如你的项目名  运行环境 层级  那个团队 版本号 都要对应
    env: test       #测试环境 生产环境 准生产环境 预发布环境  为了区分不同的应用 因为应用名称是意义  通过标签区分
    version: v1   #定义大量标签选择器 为了区分不用应用的
  type: ClusterIP  #类型 默认就是Cluster IP 不写也是
  ports:
  - protocol: TCP #协议
    port: 80
    targetPort: 80   #你的后端应用程序端口号 也就是你的pod端口号
--- #两个不通的资源对象 用三个-分割
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-svc-1
spec:
  replicas: 3
  selector:   #这个是pod控制器的标签选择器
    matchLabels:  #这个是deployment 去控制pod的标签
      app: nginx
      env: test
      version: v1
  template:
    metadata:
      labels:
        app: nginx  #这个必须包含 pod控制器的标签选择器的那三个标签  也就是上面的那三
        env: test   #这三个必须和service的标签关联上  只有关联上才能把对应的pod创建到 service endpoint上面
        version: v1
    spec:
      containers:
      - name: nginx
        image: images.guoguo.com/apps/nginx:1.22.1
        ports:
        - containerPort: 80

deployment标签选择器和service本身没有什么关系通常我们三个都写一样的 service 的标签 deployment的标签选择器还有pod的标签都一样

[root@k8s-master1 service]# kubectl apply -f service-v1.yaml
service/my-service-nginx created
deployment.apps/nginx-svc-1 created

看下创建的deployment

[root@k8s-master1 service]# kubectl get deployments.apps
NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
nginx-svc-1              3/3     3            3           7s

看下创建的service

[root@k8s-master1 service]# kubectl get service
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
my-service-nginx   ClusterIP   10.106.205.251   <none>        80/TCP    7s

看下创建的endpoint

[root@k8s-master1 service]# kubectl get endpoints
NAME               ENDPOINTS                                              AGE
my-service-nginx   192.17.65.206:80,192.26.131.189:80,192.28.252.208:80   7s
#endpoint是一组ip加端口号

看下pod的ip是不是被endpoint关联了

[root@k8s-master1 service]# kubectl get pods -l env=test -owide
NAME                          READY   STATUS    RESTARTS   AGE     IP               NODE                   NOMINATED NODE   READINESS GATES
nginx-svc-1-7b5444f57-6s6rg   1/1     Running   0          7s   192.28.252.208   k8s-node2.guoguo.com   <none>           <none>
nginx-svc-1-7b5444f57-7dqxw   1/1     Running   0          7s   192.17.65.206    k8s-node3.guoguo.com   <none>           <none>
nginx-svc-1-7b5444f57-drxtg   1/1     Running   0          7s   192.26.131.189   k8s-node1.guoguo.com   <none>           <none>

意味着三个创建的pod被endpoint关联上了,我就可以通过service的ip地址加端口号访问后端资源

试一下

[root@k8s-master1 service]# curl 10.106.205.251
test

endpoint是怎么关联的pod

就是靠标签选择器

[root@k8s-master1 service]# kubectl describe endpoints
kubernetes        my-service-nginx  nginx-deployment
[root@k8s-master1 service]# kubectl describe endpoints my-service-nginx
Name:         my-service-nginx
Namespace:    default
Labels:       run=nginx
Annotations:  endpoints.kubernetes.io/last-change-trigger-time: 2023-08-14T08:53:48Z
Subsets:
  Addresses:          192.17.65.206,192.26.131.189,192.28.252.208
  					#关联的pod地址
  NotReadyAddresses:  <none>
  Ports:
    Name     Port  Protocol
    ----     ----  --------
    <unset>  80    TCP
    		#端口号 协议

Events:  <none>

比如我们把pod的标签修改一个

endpoint会发现期望值变了,会把该标签的踢出去,然后新建一个pod

[root@k8s-master1 deployment]# kubectl get pods -owide
NAME                                READY   STATUS    RESTARTS   AGE   IP               NODE                   NOMINATED NODE   READINESS GATES
nginx-svc-1-7b5444f57-6s6rg         1/1     Running   0          14m   192.28.252.208   k8s-node2.guoguo.com   <none>           <none>
nginx-svc-1-7b5444f57-7dqxw         1/1     Running   0          14m   192.17.65.206    k8s-node3.guoguo.com   <none>           <none>
nginx-svc-1-7b5444f57-drxtg         1/1     Running   0          14m   192.26.131.189   k8s-node1.guoguo.com   <none>           <none>

#比如我们修改 ip为192.168.65.206的 他的名字叫nginx-svc-1-7b5444f57-7dqxw
[root@k8s-master1 service]# kubectl label pods nginx-svc-1-7b5444f57-7dqxw version=v2 --overwrite
deployment.apps/nginx-svc-1 labeled
[root@k8s-master1 deployment]# kubectl get pods -owide
NAME                                READY   STATUS    RESTARTS   AGE    IP               NODE                   NOMINATED NODE   READINESS GATES
nginx-svc-1-7b5444f57-6s6rg         1/1     Running   0          15m    192.28.252.208   k8s-node2.guoguo.com   <none>           <none>
nginx-svc-1-7b5444f57-7dqxw         1/1     Running   0          15m    192.17.65.206    k8s-node3.guoguo.com   <none>           <none>
nginx-svc-1-7b5444f57-9drkd         1/1     Running   0          26s    192.17.65.208    k8s-node3.guoguo.com   <none>           <none>
nginx-svc-1-7b5444f57-drxtg         1/1     Running   0          15m    192.26.131.189   k8s-node1.guoguo.com   <none>           <none>

#随着他就新建了一个,并将206踢出去了  并加入新的ip为192.17.65.208 名字为nginx-svc-1-7b5444f57-9drkd

[root@k8s-master1 deployment]# kubectl get endpoints
NAME               ENDPOINTS                                              AGE
kubernetes         172.17.8.1:6443,172.17.8.2:6443,172.17.8.3:6443        11d
my-service-nginx   192.17.65.208:80,192.26.131.189:80,192.28.252.208:80   16m

这个就是通过标签和标签选择器匹配,如果你的pod的标签变更了,endpoint会给你新创建一个pod,和你pod的标签一样并挂载到endpoint里面

这个就是通过service和标签标签选择器关联的对应的pod

Service类型 Type

Kubernetes Service Type (服务类型)主要包括以下几种

ClusterIP:在集群内部使用,默认值,只能从集群中访问.

在你的service产生一个ip地址出来,默认情况下,这个ip可以自己指定,但是要求在service网段内,如果不指定会随机在网段里分配一个ip地址,通过ClusterIP可以访问到deployment绑定的pod

NodePort:在所有安装了Kube-Proxy 的节点上打开一个端口,此端口可以代理至后端Pod,可以通过NodePort从集群外部访问集群内的服务,格式为NodeIP:NodePort.

就相当于端口映射,通过这个节点ip加端口号形式访问service和pod的资源,这个就是nodeIP加端口号,就可以访问,dashboard就是nodeport类型的service

LoadBalanCer:使用云提供商的负载均衡器公开服务,成本较高

通常在公有云上:阿里云或aws云服务厂商提供的负载均衡服务器

ExternalName:通过返回定义的CNAME别名,没有设置任何类型的代理,需要1.7或更高版本kube-dns支持

通过一个cname别名,去访问

NodePort类型

Kubenetes在创建集群的时候默认有个Service-node-port-range 端口号范围参数,创建集群就有这个范围,(默认范围在30000-32767)两千多个端口号随机找个端口号给你做映射,和定义的service端口号做映射,然后通过这个映射就可以访问到pod资源对象

写一个

我们看下我们之前创建的Dashboard

[root@k8s-master1 manifests]# kubectl get pods -n kubernetes-dashboard
NAME                                        READY   STATUS    RESTARTS       AGE
dashboard-metrics-scraper-b4dcbdc8f-pkndv   1/1     Running   10 (26m ago)   10d
kubernetes-dashboard-5964546dfc-czrpk       1/1     Running   11 (26m ago)   10d

#看下标签
[root@k8s-master1 manifests]# kubectl get pods -n kubernetes-dashboard --show-labels
NAME                                        READY   STATUS    RESTARTS       AGE   LABELS
dashboard-metrics-scraper-b4dcbdc8f-pkndv   1/1     Running   10 (27m ago)   10d   k8s-app=dashboard-metrics-scraper,pod-template-hash=b4dcbdc8f
kubernetes-dashboard-5964546dfc-czrpk       1/1     Running   11 (27m ago)   10d   k8s-app=kubernetes-dashboard,pod-template-hash=5964546dfc
#第二个是

我们得到了Dashboard的标签可以创建一个Service可以和这个标签关联

[root@k8s-master1 service]# vim service-nodeport-1.yml
apiVersion: v1
kind: Service
metadata:
  name: kubernetes-dashboard-1
  namespace: kubernetes-dashboard  #这里要注意  必须名称空间要统一!!!
spec:
  type: NodePort  #类型使用NodePort
  ports:
  - port: 443  #因为dashboard是https的
    targetPort: 8443  #这个8443是dashboard的pod端口号
        nodePort: 30000 #这个端口号生产上都是随机的  如果我们不写这个值那他就是随机的
  selector:
    k8s-app: kubernetes-dashboard #写一个就可以  这个是dashboard的标签
[root@k8s-master1 service]# kubectl apply -f service-nodeport-1.yml 
#启动
[root@k8s-master1 service]# kubectl get service -n kubernetes-dashboard
NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
dashboard-metrics-scraper   ClusterIP   10.101.27.2      <none>        8000/TCP        10d
kubernetes-dashboard        NodePort    10.99.155.12     <none>        443:31416/TCP   10d
kubernetes-dashboard-1      NodePort    10.105.148.237   <none>        443:30000/TCP   6m16s
#这个-1是我们创建的
#再看下endpoints
[root@k8s-master1 service]# kubectl get endpoints -n kubernetes-dashboard
NAME                        ENDPOINTS             AGE
dashboard-metrics-scraper   192.17.65.210:8000    10d
kubernetes-dashboard        192.28.252.210:8443   10d
kubernetes-dashboard-1      192.28.252.210:8443   7m1s
#这个-1是我们创建的 也关联上了

他是通过ipvs或者iptalbes进行的规则转换 我安装的时候把iptables改为ipvs了所以去任何一个node节点查看就能看到3000的端口号

[root@k8s-node2 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.28.252.192:30000 rr  #在这里  
  -> 192.28.252.210:8443          Masq    1      0          0
TCP  192.28.252.192:31416 rr
  -> 192.28.252.210:8443          Masq    1      0          0
TCP  192.168.1.102:30000 rr  #在这里 
  -> 192.28.252.210:8443          Masq    1      0          0
TCP  192.168.1.102:31416 rr
  -> 192.28.252.210:8443          Masq    1      0          0
TCP  10.96.0.1:443 rr
  -> 192.168.1.11:6443            Masq    1      1          0
  -> 192.168.1.12:6443            Masq    1      0          0
  -> 192.168.1.13:6443            Masq    1      1          0
TCP  10.96.0.10:53 rr
  -> 192.22.96.223:53             Masq    1      0          0
  -> 192.22.96.224:53             Masq    1      0          0
TCP  10.96.0.10:9153 rr
  -> 192.22.96.223:9153           Masq    1      0          0
  -> 192.22.96.224:9153           Masq    1      0          0
TCP  10.99.155.12:443 rr
  -> 192.28.252.210:8443          Masq    1      0          0
TCP  10.101.27.2:8000 rr
  -> 192.17.65.210:8000           Masq    1      0          0
TCP  10.102.8.242:80 rr
  -> 192.17.65.217:80             Masq    1      0          0
  -> 192.26.131.151:80            Masq    1      0          0
  -> 192.28.252.208:80            Masq    1      0          0
TCP  10.103.4.127:443 rr
  -> 192.28.252.202:4443          Masq    1      0          0
TCP  10.105.49.165:5473 rr
  -> 192.168.1.101:5473           Masq    1      0          0
TCP  10.105.148.237:443 rr
  -> 192.28.252.210:8443          Masq    1      0          0
UDP  10.96.0.10:53 rr
  -> 192.22.96.223:53             Masq    1      0          0
  -> 192.22.96.224:53             Masq    1      0          0

我们精准查找下

[root@k8s-node2 ~]# ipvsadm -Ln | grep -A2 3000
TCP  192.28.252.192:30000 rr  #这就可以看到了  3000端口转发8443
  -> 192.28.252.210:8443          Masq    1      0          0
TCP  192.28.252.192:31416 rr
--
TCP  192.168.1.102:30000 rr
  -> 192.28.252.210:8443          Masq    1      0          0
TCP  192.168.1.102:31416 rr

自然浏览器就可以访问到了

这就是第二种NodePort类型service

#

使用Service代理K8s外部服务

External类型

使用Service代理k8s外部服务,我们现在访问的资源都是集群内部的,如果想访问集群外部的,就需要用到External

我们需要一个External IP我们可以把外部的某一个资源给映射进来,事实上是通过Endpoints来做的

这时候需要启动一个机器,安装个nginx吧

这里就不演示了

要求:启动一个nginx服务器:我的nginx服务器ip为192.168.1.123

因为我们创建service他会自动给我们创建一个endpoints节点然后绑定pod,如果我们想映射集群外部的进来我们就不能让service自动的去创建endpoints了,我们人为去创建endpoints去绑定集群外部资源,然后创建一个同名的service,endpoints会自动的把endpoint和service绑定起来

创建的endpoints名字要和service一样!意义就是不让service自动的去创建endpoints了

其实endpoints就是snat字段 绑定ip 只要网络可达都可以绑定过来

[root@k8s-master1 service]# curl 192.168.1.123
test-123
IP:192.168.1.123
NAME:NGINX
#现在我们的外部nginx服务器是可以访问的,也就是网络可达

我们现在思路是创建一个CLusterIP的Service 然后不让他关联endpoints 所以我们要自己先把同名的endpoints创建出来

我们先看下endpoints字段的介绍

[root@k8s-master1 service]# kubectl explain endPoints
KIND:     Endpoints
VERSION:  v1

DESCRIPTION:
     Endpoints is a collection of endpoints that implement the actual service.
     Example:

     Name: "mysvc", Subsets: [ { Addresses: [{"ip": "10.10.1.1"}, {"ip":
     "10.10.2.2"}], Ports: [{"name": "a", "port": 8675}, {"name": "b", "port":
     309}] }, { Addresses: [{"ip": "10.10.3.3"}], Ports: [{"name": "a", "port":
     93}, {"name": "b", "port": 76}] }, ]

FIELDS:
   apiVersion   <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

   kind <string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

   metadata     <Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

   subsets      <[]Object>
     The set of all endpoints is the union of all subsets. Addresses are placed
     into subsets according to the IPs they share. A single address with
     multiple ports, some of which are ready and some of which are not (because
     they come from different containers) will result in the address being
     displayed in different subsets for the different ports. No address will
     appear in both Addresses and NotReadyAddresses in the same subset. Sets of
     addresses and ports that comprise a service.
#没有spec  这是个特殊的资源对象类型,百分之99的资源对象都有五个字段:apiVersion  kind metadata spec status  
#但是 endpoint没有 spec 和status  他多了个subsets字段

看下subsets字段

[root@k8s-master1 service]# kubectl explain endpoints.subsets
KIND:     Endpoints
VERSION:  v1

RESOURCE: subsets <[]Object>

DESCRIPTION:
     The set of all endpoints is the union of all subsets. Addresses are placed
     into subsets according to the IPs they share. A single address with
     multiple ports, some of which are ready and some of which are not (because
     they come from different containers) will result in the address being
     displayed in different subsets for the different ports. No address will
     appear in both Addresses and NotReadyAddresses in the same subset. Sets of
     addresses and ports that comprise a service.

     EndpointSubset is a group of addresses with a common set of ports. The
     expanded set of endpoints is the Cartesian product of Addresses x Ports.
     For example, given:

     { Addresses: [{"ip": "10.10.1.1"}, {"ip": "10.10.2.2"}], Ports: [{"name":
     "a", "port": 8675}, {"name": "b", "port": 309}] }

     The resulting set of endpoints can be viewed as:

     a: [ 10.10.1.1:8675, 10.10.2.2:8675 ], b: [ 10.10.1.1:309, 10.10.2.2:309 ]

FIELDS:
   addresses    <[]Object>
   #ip地址   这个是个列表 需要查看一下
     IP addresses which offer the related ports that are marked as ready. These
     endpoints should be considered safe for load balancers and clients to
     utilize.

   notReadyAddresses    <[]Object>
     IP addresses which offer the related ports but are not currently marked as
     ready because they have not yet finished starting, have recently failed a
     readiness check, or have recently failed a liveness check.

   ports        <[]Object>
   #端口号 列表也需要查看一下
     Port numbers available on the related IP addresses.

看下addresses字段

[root@k8s-master1 service]# kubectl explain Endpoints.subsets.addresses
KIND:     Endpoints
VERSION:  v1

RESOURCE: addresses <[]Object>

DESCRIPTION:
     IP addresses which offer the related ports that are marked as ready. These
     endpoints should be considered safe for load balancers and clients to
     utilize.

     EndpointAddress is a tuple that describes single IP address.

FIELDS:
   hostname     <string>
     The Hostname of this endpoint

   ip   <string> -required-
   #ip地址
     The IP of this endpoint. May not be loopback (127.0.0.0/8), link-local
     (169.254.0.0/16), or link-local multicast ((224.0.0.0/24). IPv6 is also
     accepted but not fully supported on all platforms. Also, certain kubernetes
     components, like kube-proxy, are not IPv6 ready.

   nodeName     <string>
     Optional: Node hosting this endpoint. This can be used to determine
     endpoints local to a node.

   targetRef    <Object>
     Reference to object providing the endpoint.

看下ports

[root@k8s-master1 service]# kubectl explain Endpoints.subsets.ports
KIND:     Endpoints
VERSION:  v1

RESOURCE: ports <[]Object>

DESCRIPTION:
     Port numbers available on the related IP addresses.

     EndpointPort is a tuple that describes a single port.

FIELDS:
   appProtocol  <string>
     The application protocol for this port. This field follows standard
     Kubernetes label syntax. Un-prefixed names are reserved for IANA standard
     service names (as per RFC-6335 and
     https://www.iana.org/assignments/service-names). Non-standard protocols
     should use prefixed names such as mycompany.com/my-custom-protocol.

   name <string>
     The name of this port. This must match the 'name' field in the
     corresponding ServicePort. Must be a DNS_LABEL. Optional only if one port
     is defined.

   port <integer> -required-
     The port number of the endpoint.

   protocol     <string>
     The IP protocol for this port. Must be UDP, TCP, or SCTP. Default is TCP.
     Possible enum values:
     - `"SCTP"` is the SCTP protocol.
     - `"TCP"` is the TCP protocol.
     - `"UDP"` is the UDP protocol.

写一个

[root@k8s-master1 service]# cat service-external.yml
apiVersion: v1
kind: Service
metadata:
  name: external-nginx
spec:
  type: ClusterIP
  ports:
  - port: 80  #如果说想给这个port加个名称 在下面也需要加 相同的名称 要么都不加 要么都加
    targetPort: 80  #ExternalName类型不需要标签选择器 因为它不需要去和pod关联
    protocol: TCP
---
apiVersion: v1 #因为我们不想让service自动创建endpoint然后关联  所以我们直接创建同名的endpoint
kind: Endpoints
metadata:
  name: external-nginx  #这个名称必须和service 的名称相同 否则无法关联
subsets: #这个是特殊的字段  类似spec吧
- addresses:  #ip
  - ip: 192.168.1.123 #nginx 的ip
  ports:   #如果说想给这个port加个名称 在上面也需要加 相同的名称 要么都不加 要么都加
  - port: 80 #端口号
    protocol: TCP #协议
[root@k8s-master1 service]# kubectl apply -f service-external.yml
service/external-nginx created
endpoints/external-nginx created

查看一下

[root@k8s-master1 service]# kubectl get endpoints
NAME              ENDPOINTS                                               AGE
external-nginx    192.168.1.123:80                                        2m6s
[root@k8s-master1 service]# kubectl get service
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
external-nginx    ClusterIP   10.104.149.57   <none>        80/TCP    2m25s

然后这时候我们访问service的ip就能访问到nginx的地址了

[root@k8s-master1 service]# curl 10.104.149.57
test-123
IP:192.168.1.123
NAME:NGINX

这样就可以把我们集群外部的服务发布到集群内部,不光master node节点可以访问,因为他的网段和pod在一个网段 pod里面也是可以访问的

这种方式生产上用的比较多,如果你在k8s以内想监控k8s以外的东西就得需要这种方式来创建

比如监控服务装在k8s里面但是你想监控集群外部的服务就需要这个方式来去监控集群之外的服务

第四种Service类型

ExternalName

ExternalName是一种特殊的Service资源,也不需要关联标签选择器关联任何Pod,也无需定义任何端口号或Endpoints,但是必须使用spec.ExternalName属性定义一个别名(CNAME)记录,

类似于我访问一个百度,集群里面访问百度,我就可以给百度做一个别名,然后用别名去访问百度

生产上用的少

这种和External类似,他事实上也是把集群外部的资源弄到集群内部,只是弄得域名,上面是使用endpoints把多个ip地址通过subsets把addresses ip地址导进去的

这个是拓展域名的方式,把集群外部通过域名的某一个服务给你映射集群内部去,最终不是通过域名访问是通过cluster名称访问

写一个

[root@k8s-master1 ~]# kubectl explain service.spec
KIND:     Service
VERSION:  v1

RESOURCE: spec <Object>

DESCRIPTION:
     Spec defines the behavior of a service.
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

     ServiceSpec describes the attributes that a user creates on a service.

FIELDS:
   externalName <string>
   #用这个之前type类型必须是ExternalName才可以
   #这里是指定要映射进来的域名是谁
     externalName is the external reference that discovery mechanisms will
     return as an alias for this service (e.g. a DNS CNAME record). No proxying
     will be involved. Must be a lowercase RFC-1123 hostname
     (https://tools.ietf.org/html/rfc1123) and requires `type` to be
     "ExternalName".

   ports        <[]Object>
   #需要写端口号  域名的端口号 和映射进来的端口号
     The list of ports that are exposed by this service. More info:
     https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies

   selector     <map[string]string>
   #虽然不用写标签选择器内容 但是得写上为空 {} 两个大括号就代表为空
     Route service traffic to pods with label keys and values matching this
     selector. If empty or not present, the service is assumed to have an
     external process managing its endpoints, which Kubernetes will not modify.
     Only applies to types ClusterIP, NodePort, and LoadBalancer. Ignored if
     type is ExternalName. More info:
     https://kubernetes.io/docs/concepts/services-networking/service/

   type <string>
   #类型  这个写上 ExternalName 
     type determines how the Service is exposed. Defaults to ClusterIP. Valid
     options are ExternalName, ClusterIP, NodePort, and LoadBalancer.
     "ClusterIP" allocates a cluster-internal IP address for load-balancing to
     endpoints. Endpoints are determined by the selector or if that is not
     specified, by manual construction of an Endpoints object or EndpointSlice
     objects. If clusterIP is "None", no virtual IP is allocated and the
     endpoints are published as a set of endpoints rather than a virtual IP.
     "NodePort" builds on ClusterIP and allocates a port on every node which
     routes to the same endpoints as the clusterIP. "LoadBalancer" builds on
     NodePort and creates an external load-balancer (if supported in the current
     cloud) which routes to the same endpoints as the clusterIP. "ExternalName"
     aliases this service to the specified externalName. Several other fields do
     not apply to ExternalName services. More info:
     https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types

     Possible enum values:
     - `"ClusterIP"` means a service will only be accessible inside the cluster,
     via the cluster IP.
     - `"ExternalName"` means a service consists of only a reference to an
     external name that kubedns or equivalent will return as a CNAME record,
     with no exposing or proxying of any pods involved.
     - `"LoadBalancer"` means a service will be exposed via an external load
     balancer (if the cloud provider supports it), in addition to 'NodePort'
     type.
     - `"NodePort"` means a service will be exposed on one port of every node,
     in addition to 'ClusterIP' type.

写一个

[root@k8s-master1 service]# cat externalname-1.yml
apiVersion: v1
kind: Service
metadata:
  name: baidu-externalname  #这里是映射的域名,
spec:
  type: ExternalName
  externalName: www.baidu.com  #映射前的域名
  selector: {}   #不需要写标签内容 但是要写为空 {} 代表为空
  ports:
  - port: 80  #映射后的端口号
    protocol: TCP
    targetPort: 80 #映射前 百度的端口号
[root@k8s-master1 service]# kubectl apply -f externalname-1.yml
service/baidu-externalname created

测试一下

[root@k8s-master1 service]# kubectl exec nginx-67c6f5c7bf-65x25 -- nslookup baidu-externalname
Server:         10.96.0.10
Address:        10.96.0.10#53

baidu-externalname.default.svc.cluster.local    canonical name = www.baidu.com.
www.baidu.com   canonical name = www.a.shifen.com.
Name:   www.a.shifen.com
Address: 110.242.68.4
Name:   www.a.shifen.com
Address: 110.242.68.3

#可以正常解析到

这就是我们通过externalname的方式把我们集群外部的某一个域名映射进来,通过别名的方式来解析

公司很少直接使用ip方式,刚才那个service subsets 用ip方式少

因为生产上ip可能会变,但是域名不会

上面那种通过cluster ip的方式去关联ip的方式和这个用域名关联的方式类似的,只是后面这种不需要创建endpoints,标签选择器为空,字段类型为ExternalName就可以了

多端口Service

就是我们定义ports本身就是个列表,ports可以定义多个

就是同时可以把80和443都映射出来

[root@k8s-master1 chapter03]# cat service-ports.yaml
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: myapp
  ports:  #ports是个列表  代表可以定义多个端口号  这样80和443 都可以同时映射出来 多个端口号对应多个端口号
  - name: http
    protocol: TCP
    port: 80
    targetPort: 9376
  - name: https
    protocol: TCP
    port: 443
    targetPort: 9377

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

AWkq7aIjuRwO