[技术干货] Service基础应用

[复制链接]
乐维 发表于 2021-8-9 11:26:23 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
一.1  什么是Service?
Service可以简单的理解为逻辑上的一组Pod。一种可以访问Pod的策略,而且其他Pod可以通过这个Service访问到这个Service代理的Pod。相对于Pod而言,它会有一个固定的名称,一旦创建就固定不变。
图片1.png
一.1.1.1  基本概念
Service主要用于Pod之间的通信,对于PodIP地址而言,Service是提前定义好并且是不变的资源类型。
Kubernetes Pod具有生命周期的概念,它可以被创建、删除、销毁,一旦被销毁就意味着生命周期的结束。通过ReplicaSet能够动态地创建和销毁Pod,例如进行扩缩容和执行滚动升级。每个Pod都会获取到它自己的IP地址,但是这些IP地址不总是稳定和可依赖的,这样就会导致一个问题:在Kubernetes集群中,如果一组Pod(比如后端的Pod)为其他Pod(比如前端的Pod)提供服务,那么如果它们之间使用PodIP地址进行通信,在Pod重建后,将无法再进行连接。
为了解决上述问题,Kubernetes引用了Service这样一种抽象概念:逻辑上的一组Pod即一种可以访问Pod的策略——通常称为微服务。这一组Pod能够被Service访问到,通常是通过Label Selector(标签选择器)实现的。
举个例子,有一个用作图片处理的backend(后端),运行了3个副本,这些副本是可互换的,所以frontend(前端)不需要关心它们调用了哪个backend副本,然而组成这一组backend程序的Pod实际上可能会发生变化,即便这样frontend也没有必要知道,而且也不需要跟踪这一组backend的状态,因为Service能够解耦这种关联。
对于Kubernetes集群中的应用,Kubernetes提供了简单的Endpoints API,只要Service中的一组Pod发生变更,应用程序就会被更新。对非Kubernetes集群中的应用,Kubernetes提供了基于VIP的网桥的方式访问Service,再由Service重定向到backend Pod
一.1  创建一个Service
先用deployment创建2pod
# cat nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  progressDeadlineSeconds: 600
  replicas: 2
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: nginx
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.15.2
        imagePullPolicy: IfNotPresent
        name: nginx
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
[root@master01 ~]# kubectl create -f nginx-deploy.yaml
[root@master01 ~]# kubectl get pods -l app=nginx
图片2.png
# cat nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-svc
  name: nginx-svc
spec:
  ports:
  - name: http # Service端口的名称
    port: 80 # Service自己的端口, servicea --> serviceb http://serviceb,  http://serviceb:8080
    protocol: TCP # UDP TCP SCTP default: TCP
    targetPort: 80 # 后端应用的端口
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
  selector:
    app: nginx
  sessionAffinity: None
  type: ClusterIP
[root@master01 ~]# kubectl create -f nginx-svc.yaml
service/nginx-svc created
图片3.png
访问svc测试,可以访问到后端的pod
[root@master01 ~]# curl http://10.20.65.127   #但是不建议使用ip,因为svc再删除之后ip会变
进入busybox容器之后,用svc名称访问
[root@master01 ~]# kubectl exec -it busybox -- sh
/ # wget http://nginx-svc
Connecting to nginx-svc (10.20.65.127:80)
index.html           100% |*****************************|   612   0:00:00 ETA
/ # cat index.html
单独删除pod之后,并不影响svc的访问,因为pod所有的ip地址和端口号都会被记录到endpoint,endpoint在创建svc时自动创建,endpoint会动态的将svcpod结合起来
图片4.png
定义Service
一个ServiceKubernetes中是一个REST对象,和Pod类似。像所有REST对象一样,Service的定义可以基于POST方式,请求APIServer创建新的实例。例如,假定有一组Pod,它们暴露了9376端口,同时具有app=MyApp标签。此时可以定义Service如下:
kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
上述配置创建一个名为my-serviceService对象,它会将请求代理到TCP端口为9376并且具有标签app=MyAppPod上。这个Service会被分配一个IP地址,通常称为ClusterIP,它会被服务的代理使用。
需要注意的是,Service能够将一个接收端口映射到任意的targetPort。默认情况下,targetPort将被设置为与Port字段相同的值。targetPort可以设置为一个字符串,引用backend Pod的一个端口的名称。
定义没有SelectorService
Service抽象了该如何访问Kubernetes Pod,但也能够抽象其他类型的backend,例如:
l 希望在生产环境中访问外部的数据库集群。
l 希望Service指向另一个NameSpace中或其他集群中的服务。
l 正在将工作负载转移到Kubernetes集群,和运行在Kubernetes集群之外的backend
在任何这些场景中,都能定义没有SelectorService
kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
由于这个Service没有Selector,就不会创建相关的Endpoints对象,可以手动将Service映射到指定的Endpoints
kind: Endpoints
apiVersion: v1
metadata:
  name: my-service
subsets:
  - addresses:
      - ip: 1.2.3.4
    ports:
      - port: 9376
Endpoint IP 地址不能是 loopback127.0.0.0/8)、link-local169.254.0.0/16)或者link-local 多播地址224.0.0.0/24)。
访问没有SelectorService与有SelectorService的原理相同。请求将被路由到用户定义的Endpoint,该示例为1.2.3.4:9376。
ExternalName ServiceService的特例,它没有Selector,也没有定义任何端口和Endpoint,它通过返回该外部服务的别名来提供服务。
比如当查询主机my-service.prod.svc时,集群的DNS服务将返回一个值为my.database.example.comCNAME记录:
kind: Service
apiVersion: v1
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com
同一namespace下,直接访问http://nginx-svc就可以访问,不同namespace下访问Pod可以通过http://nginx-svc.namespace(名称)就可以访问
一.1  使用Service代理k8s外部应用
使用场景:
Ø 希望在生产环境中使用某个固定的名称而非IP地址进行访问外部的中间件服务
Ø 希望Service指向另一个Namespace中或其他集群中的服务
Ø 某个项目正在迁移至k8s集群,但是一部分服务仍然在集群外部,此时可以使用service代理至k8s集群外部的服务
# cat nginx-svc-external.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-svc-external
  name: nginx-svc-external
spec:
  ports:
  - name: http # Service端口的名称
    port: 80 # Service自己的端口, servicea --> serviceb http://serviceb,  http://serviceb:8080
    protocol: TCP # UDP TCP SCTP default: TCP
    targetPort: 80 # 后端应用的端口
  sessionAffinity: None
  type: ClusterIP
[root@master01 ~]# kubectl create -f nginx-svc-external.yaml
service/nginx-svc-external created
图片5.png
查看是否有同名的endpoint
图片6.png
创建没有selectorsvc是不会创建同名的endpoint
# cat nginx-ep-external.yaml
apiVersion: v1
kind: Endpoints
metadata:
  labels:
    app: nginx-svc-external
  name: nginx-svc-external    #ep名称要和svc的名称一致
  namespace: default
subsets:
- addresses:
  - ip: 182.61.200.6    #代理外部服务的ip地址,此处可以填写百度的IP地址
  ports:
  - name: http             #端口名称要和svc的名称一致
    port: 80                #代理外部服务的端口号
    protocol: TCP
[root@master01 ~]# kubectl create -f nginx-ep-external.yaml
endpoints/nginx-svc-external created
图片7.png
测试访问百度
图片8.png
访问svc测试
图片9.png
要代理至其它服务,可直接修改epip地址
一.1  使用Service反代域名
无需endpoint,service中也无需selector
# cat nginx-externalName.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-externalname
  name: nginx-externalname
spec:
  type: ExternalName
  externalName: www.baidu.com
[root@master01 ~]# kubectl apply -f nginx-externalName.yaml
service/nginx-externalname created
图片10.png
一.1  Service类型
Ø ClusterIP:在集群内部使用,也是默认值。
Ø ExternalName:通过返回定义的CNAME别名。
Ø NodePort:在所有安装了kube-proxy的节点上打开一个端口,此端口可以代理至后端Pod,然后集群外部可以使用节点的IP地址和NodePort的端口号访问到集群Pod的服务。NodePort端口范围默认是30000-32767。
Ø LoadBalancer:使用云提供商的负载均衡器公开服务。
svc的类型由ClusterIP修改为NodePort
图片11.png
[root@master01 ~]# kubectl edit svc nginx-svc
图片12.png
图片13.png
访问任何一台宿主机的31000端口
图片14.png





上一篇:ubuntu/debian PHP编译问题处理
下一篇:启动tomcat报JAVA_HOME环境不存在问题处理
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝0

帖子377

发布主题
最新发布

版权所有 © 2016-2021 九一乐维丨粤ICP备17007026号