【Kubernetes】Service学习(一)Service的基本用法

此文为学习《Kubernetes权威指南》和阿里云原生公开课的相关笔记

学习笔记:

Pod作为K8s中调度和使用的基本单位,承担了在集群中建立容器、部署基本功能的任务,而RC/RS/Delpoymet/DaemonSet/Job/StatefulSet等类型的资源对象担当控制器,负责Pod的创建和生命周期的管理,上述的这些工作使得一个K8s集群能够有序的被部署进行设计者想要安排的任务,然而一个集群的最终目的应当是面向用户提供服务,包装容器功能为用户提供服务入口这项任务是由Service这一资源对象来完成的。

Service解决的问题有:

  • K8s应用之间互相调用较为困难,Pod生命周期较短、IP地址变化快。

  • 单单是副本控制器管理下的Pod群无法统一对外提供接口、无法实现负载均衡。

K8s中的每一个Service与微服务架构中的一个微服务所对应,每个Service定义了一个服务的访问入口地址,外部网络或者前端的应用(其他Pod)通过这个入口访问K8s集群中一组由Pod副本组成的集群实例,而Service与其后端的Pod副本则通过Label Selector来实现无缝对接,从这个视角看,Service才是K8s的真正核心,Pod的建立是为了集群具备对外提供某一Service的能力,而副本控制器则是保证Service的服务能力和服务质量始终符合预期的标准。

最终,系统将由多个提供不同业务能力而又彼此独立的微服务单元组成,服务之间通过TCP/IP进行通信,从而形成强大的分布式能力、弹性扩展能力、容错能力,程序架构也变得简单和直观。

画了一张逻辑关系图:

下面通过几个实例学习Service的基本用法:

一、通过Service实现服务提供和自动负载

1、创建一个提供Web服务的Deployment

该Deployment包含两个Tomcat容器副本,通过containerPort开放8080端口

apiVersion: apps/v1
kind: Deployment
metadata:
 name: webapp
spec:
 replicas: 2
 selector:
  matchLabels:
   app: webapp
 template:
  metadata:
   name: webapp
   labels:
    app: webapp
  spec:
   containers:
   - name: webapp
     image: tomcat
     ports:
     - containerPort: 8080

2、创建并查看部署情况

# kubectl create -f webapp-deployment.yaml
deployment.apps/webapp created

# kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
webapp-57ff49ddcf-kms92   1/1     Running   0          41s
webapp-57ff49ddcf-r9p26   1/1     Running   0          41s

通过下面的命令可以到具有指定label的Pod对应的PodIP

kubectl get pods -l <label-key>=<label-value> -o yaml | grep <field-name>

# kubectl get pods -l app=webapp -o yaml |grep podIP:
    podIP: 10.44.0.1
    podIP: 10.44.0.2

可以通过PodIP:containerPort的方式访问到容器应用提供的服务

# curl 10.44.0.1:8080

<!DOCTYPE html>
<html lang="en">
    <head>

......

# curl 10.44.0.2:8080

<!DOCTYPE html>
<html lang="en">
    <head>

......

3、部署Service对外提供服务入口

在不提供spec.type时,默认值为ClusterIP,Service有自己的簇地址,可以用于内部Pod访问。

在Node上的kube-proxy通过设置的iptables规则进行转发。

# vim webapp-service.yaml

apiVersion: v1
kind: Service
metadata:
 name: webapp
spec:            #开放8081端口,映射到后台容器的8080端口,即web服务提供端口
 ports:
 - port: 8081
   targetPort: 8080

# type: ClusterIp      #默认就是ClusterIp域
 selector:
  app: webapp

# kubectl create -f webapp-service.yaml
service/webapp created

通过kubectl get svc命令可以看到系统为其自动创建的ClusterIP

当spec.type=ClusterIP,可以设置spec.clusterIP指定该Service的ClusterIP,不再由K8s生成
# kubectl get svc
NAME                  TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
......
webapp                ClusterIP   10.97.130.15   <none>        8081/TCP   10s

......

4、访问Service的ClusterIP:8081,可以看到成功访问到了web服务

# curl 10.97.130.15:8081

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />

......

在这个过程中,Service通过Label Selector找到其后台的Pod副本列表,自动负载分发到两个Pod之一,实现了服务的统一接口

K8s提供了两种负载分发策略:

  • RoundRobin:轮询模式,即轮询将请求转发到后端的各个Pod副本上,默认是该模式。
  • SessionAffinity:基于客户端IP地址进行会话保持的模式,同一个客户端发来的请求由同一个Pod处理。

5、以NodePort模式建立Service

指定spec.tpye为NodePort,将使用宿主机的端口,使能够访问各Node的外部客户端通过Node的Ip地址和端口号就能访问服务

K8s限制使用宿主机的端口号范围为30000-32767

apiVersion: v1
kind: Service
metadata:
 name: webapp-nodeport
spec:
 ports:
 - port: 8081
   targetPort: 8080
   nodePort: 31234    #30000-32767
 type: NodePort

 selector:
  app: webapp

 创建该Service

# kubectl create -f webapp-service-nodeport.yaml
service/webapp-nodeport created

可以看到,在NodePort模式下,K8s同样会给Service提供一个ClusterIP用于内部Pod的访问

# kubectl get svc
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
......
webapp-nodeport       NodePort    10.108.207.69   <none>        8081:31234/TCP   12s

......

这时,我们即可以通过ClusterIP从内部访问web服务,也可以通过宿主机端口从外部访问

# curl 10.108.207.69:8081

<!DOCTYPE html>
<html lang="en">
    <head>

......

# curl 127.0.0.1:31234

<!DOCTYPE html>
<html lang="en">
    <head>

......

二、多端口Service的实现

一个容器在某些情况下可能提供多个端口的服务,一个Service出于某些原因也可能提供多个端口映射到同一个Pod端口,于此同时,Service也可以对外提供不同四层协议(TCP和UDP)的访问方式。

1、开放两个端口的Service

apiVersion: v1
kind: Service
metadata:
 name: webapp
spec:
 ports:
 - port: 8081
   targetPort: 8081
   name: port1
 - port: 8082
   targetPort: 8082
   name: port2

 type: ClusterIp
 selector:
  app: webapp

2、端口使用不同协议的Service

apiVersion: v1
kind: Service
metadata:
 name: webapp
spec:
 ports:
 - port: 8081
   targetPort: 8080
   protocal: TCP
 - port: 8081
   targetPort: 8081
   protocal: UDP

 type: ClusterIP
 selector:
  app: webapp

三、外部服务Service的定义

在某些环境中,应用系统需要将一个外部数据库作为后端服务进行连接,或者将另一个集群或Namespace中的服务作为服务的后端,这时可以通过创建一个无Label Selector的Service实现,成为外部服务Service。

1、创建一个不带有Label Selector的Service

apiVersion: v1
kind: Service
metadata:
 name: external-svc
spec:
 type: ClusterIP
 ports:
 - name: web
   port: 80
   protocol: TCP
   targetPort: 80

2、创建一个与之同名的Endpoint

apiVersion: v1
kind: Endpoints
metadata:
 name: external-svc
subsets:
- addresses:
  - ip: 1.2.3.4          #用于指向实际的后端访问地址
  ports:
  - port: 80
             #后端访问的端口

 访问没有标签选择器的Service和带有标签选择器的Service一样,请求将会被路由到用户手动定义的后端Endpoint上

# kubectl get endpoints
NAME                  ENDPOINTS             AGE
external-svc          1.2.3.4:80            7m10s
......

# kubectl get svc
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
external-svc          ClusterIP   10.111.62.195   <none>        80/TCP     2m4s
......

发布了27 篇原创文章 · 获赞 0 · 访问量 945

猜你喜欢

转载自blog.csdn.net/qq_38093301/article/details/103638702