k8s-Service

root
233
文章
0
评论
2020年10月25日03:33:44 评论 5135字阅读17分7秒

k8s-Service

Service的作用:

  • 防止pod失联(服务发现)

service解决podIP动态变化的功能

  • 定义一组pod的访问策略(负载均衡)

为什么要有Service?

在kubernetes中,Pod是有生命周期的,如果Pod重启它的IP很有可能会发生变化。如果我们的服务都是将Pod的IP地址写死,Pod挂掉或者重启,和刚才重启的pod相关联的其他服务将会找不到它所关联的Pod,为了解决这个问题,在kubernetes中定义了service资源对象,Service 定义了一个服务访问的入口,客户端通过这个入口即可访问服务背后的应用集群实例,service是一组Pod的逻辑集合,这一组Pod能够被Service访问到,通常是通过Label Selector实现的。

1、pod ip经常变化,service是pod的代理,我们客户端访问,只需要访问service,就会把请求代理到Pod

2、pod ip在k8s集群之外无法访问,所以需要创建service,这个service可以在k8s集群外访问的。

Service概述

service是一个固定接入层,客户端可以通过访问service的ip和端口访问到service关联的后端pod,这个service工作依赖于在kubernetes集群之上部署的一个附件,就是kubernetes的dns服务(不同kubernetes版本的dns默认使用的也是不一样的,1.11之前的版本使用的是kubeDNs,较新的版本使用的是coredns),service的名称解析是依赖于dns附件的,因此在部署完k8s之后需要再部署dns附件,kubernetes要想给客户端提供网络功能,需要依赖第三方的网络插件(flannel,calico等)。每个K8s节点上都有一个组件叫做kube-proxy,kube-proxy这个组件将始终监视着apiserver中有关service资源的变动信息,需要跟master之上的apiserver交互,随时连接到apiserver上获取任何一个与service资源相关的资源变动状态,这种是通过kubernetes中固有的一种请求方法watch(监视)来实现的,一旦有service资源的内容发生变动(如创建,删除),kube-proxy都会将它转化成当前节点之上的能够实现service资源调度,把我们请求调度到后端特定的pod资源之上的规则,这个规则可能是iptables,也可能是ipvs,取决于service的实现方式。

Service工作原理

k8s在创建Service时,会根据标签选择器selector(lable selector)来查找Pod,据此创建与Service同名的endpoint对象,当Pod 地址发生变化时,endpoint也会随之发生变化,service接收前端client请求的时候,就会通过endpoint,找到转发到哪个Pod进行访问的地址。(至于转发到哪个节点的Pod,由负载均衡kube-proxy决定)

[root@master01 ~]# kubectl get endpoints
NAME         ENDPOINTS                               AGE
kubernetes   192.168.1.180:6443,192.168.1.181:6443   6d5h

 

Pod与Service的关系

通过labe-selector相关联

通过Service实现 Pod的负载均衡(TCP/UDP 只支持4层负载均衡)

Service的四种IP地址

  • ClusterIP:集群内部使用

默认,分配一个稳定的IP地址,即VIP,只能在集群内部访问

生成Service的yaml文件方法

#控制器名字 [root@master01 ~]# kubectl expose deployment myapp-v1 --port=8080 --target-port=80 --name=web01 -o yaml --dry-run=client
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  name: web01
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 80
  selector:
    app: myapp
    version: v1
status:
  loadBalancer: {}

 

  • NodePort:对外暴露应用

在每个节点上启用一个端口来暴露服务,在集群外部进行访问,也会分配一个稳定内部集群IP地址,

访问地址:<NodeIP>:<NodePort>

Client----->NodeIP:NodePort----->Service Ip:ServicePort----->PodIP:ContainerPort。

[root@master01 ~]# cat nginx.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80  #pod中的容器需要暴露的端口
---
apiVersion: v1
kind: Service
metadata:
  name: web01
  namespace: default
spec:
  ports:
  - port: 80    #svc端口,可以与其他svc端口号相同,因为ip不同
    protocol: TCP
    targetPort: 80        #跟你控制器里定义的端口有关
    nodePort: 30008 #宿主机上映射的端口,比如一个Web应用需要被k8s集群之外的其他用户访问,那么需要配置type=NodePort,若配置nodePort=30001,那么其他机器就可以通过浏览器访问scheme://k8s集群中的任何一个节点ip:30001即可访问到该服务,例如http://192.168.1.63:30001。>如果在k8s中部署MySQL数据库,MySQL可能不需要被外界访问,只需被内部服务访问,那么就不需要设置NodePort
  selector:
    run: my-nginx
  type: NodePort

 

[root@master01 ~]# kubectl get endpoints
NAME         ENDPOINTS                               AGE
kubernetes   192.168.1.180:6443,192.168.1.181:6443   6d22h
web01        172.16.196.151:80,172.16.196.152:80     27m
  • LoadBanlancer:对外暴露应用,适用公有云

与NodePort类似,在每个节点上启用一个端口来爆率服务,除此之外,kubernetes会请求底层云平台上的负载均衡器,将每个Node作为后端添加进去

  • ExternalName:

适用于k8s集群内部容器访问外部资源,它没有selector,也没有定义任何的端口和Endpoint。

 应用场景:不同命名空间下的容器实现跨命名空间访问

#需求:default名称空间下的client 服务想要访问nginx-ns名称空间下的nginx-svc服务

  • 只要有一个ns里的svc专门做代理类型为ExternalName,对应其他ns的全指向域名就可以
//这个svc没有定义标签选择器,就是不是给特定pod使用的,它就是单纯的svc
apiVersion: v1
kind: Service
metadata:
  name: client-svc
  namespace: default
spec:
  type: ExternalName
  externalName: nginx-svc.nginx-ns.svc.cluster.local
  ports:
  - name: http
    port: 80
    targetPort: 80

namespace:nginx-ns的svc

[root@master1 -]# kubectl create ns nginx-ns
[root@master1 exter]# cat server_nginx.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: nginx-ns
spec: 
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
   metadata:
    labels:
      app: nginx
   spec:
     containers:
     - name: nginx
       image: nginx
       imagePullPolicy: IfNotPresent
[root@master1 exter]# cat nginx_svc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  namespace: nginx-ns
spec:
  selector:
    app: nginx
  ports:
   - name: http
     protocol: TCP
     port: 80
     targetPort: 80
  type: ClusterIP

 

当查询主机 my-service.prod.svc.cluster.local 时,群集DNS将返回值为my.database.example.com的CNAME记录。

service的FQDN是: <service_name>.<namespace>.svc.cluster.local

                                  my-service.prod. svc.cluster.local

                                  SVC名字.ns名字.svc.cluster.local

SVc要是想要在主机通过域名访问pod,需要把svc的ip对应的全地址解析写到/etc/hosts文件中

自定义Endpoint资源

作用:

  • 将外部IP地址和服务引入到k8s集群内部,由service作为一个代理来达到能够访问k8s集群外部服务的目的。

k8s最佳实践:映射外部服务案例分享

  • 场景1:k8s集群引用外部的mysql数据库

在node1上安装mysql数据库:

创建mysql的svc

[root@master1 mysql]# cat mysql_service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  type: ClusterIP
  ports:
  - port: 3306

查看Endpoint资源

[root@xianchaomaster1 mysql]# kubectl describe svc mysql
Name:              mysql
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          <none>
Type:              ClusterIP
IP Families:       <none>
IP:                10.107.232.103
IPs:               10.107.232.103
Port:              <unset>  3306/TCP
TargetPort:        3306/TCP
Endpoints:         <none>  #还没有endpoint
Session Affinity:  None
Events:            <none>

创建mysql对应Endpoint资源

[root@master1 mysql]# cat mysql_endpoint.yaml 
apiVersion: v1
kind: Endpoints
metadata:
  name: mysql            ##要是svc中定义的名字一致
subsets:
- addresses:
  - ip: 192.168.1.182
  ports:
  - port: 3306

再次查看mysql的svc

[root@master1 mysql]# kubectl describe svc mysql
Name:              mysql
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          <none>
Type:              ClusterIP
IP Families:       <none>
IP:                10.107.232.103
IPs:               10.107.232.103
Port:              <unset>  3306/TCP
TargetPort:        3306/TCP
Endpoints:         192.168.1.62:3306  #这个就是定义的外部数据库
Session Affinity:  None
Events:            <none>

 

 

继续阅读
weinxin
我的微信
这是我的微信扫一扫
  • 文本由 发表于 2020年10月25日03:33:44
  • 除非特殊声明,本站文章均为原创,转载请务必保留本文链接
k8s-Service Account Kubernetes

k8s-Service Account

k8s-Service Account的授权管理 Service Account也是一种账号,是给运行在Pod里的进程提供了必要的身份证明。需要在Pod定义中指明引用的Service Account,...
k8s-RBAC Kubernetes

k8s-RBAC

k8s-RBAC认证授权策略 RBAC介绍 在Kubernetes中,所有资源对象都是通过API进行操作,他们保存在etcd里。而对etcd的操作我们需要通过访问 kube-apiserver 来实现...
k8s-Secret Kubernetes

k8s-Secret

配置管理中心Secret Secret是什么? Configmap一般是用来存放明文数据的,如配置文件,对于一些敏感数据,如密码、私钥等数据时,要用secret类型 Secret解决了密码、token...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: