kubernetes之Service介绍

Service

Pod IP仅仅是集群内可见的虚拟IP,外部无法访问。
Pod IP会随着Pod的销毁而消失,当ReplicaSet对Pod进行动态伸缩时,Pod IP可能随时随地都会变化,这样对于我们访问这个服务带来了难度。
因此,Kubernetes中的Service对象就是解决以上问题的实现服务发现核心关键。

Service的类型
在Serivce定义时,我们需要指定spec.type字段,这个字段拥有四个选项:
● ClusterIP:默认值。给这个Service分配一个Cluster IP,它是Kubernetes系统自动分配的虚拟IP,因此只能在集群内部访问。
● NodePort:将Service通过指定的Node上的端口暴露给外部。通过此方法,访问任意一个NodeIP:nodePort都将路由到ClusterIP,
从而成功获得该服务。默认范围30000-32767。
● LoadBalancer:在 NodePort 的基础上,借助 cloud provider 创建一个外部的负载均衡器,并将请求转发到 <NodeIP>:NodePort。
此模式只能在云服务器(AWS等)上使用。
● ExternalName:将服务通过 DNS CNAME 记录方式转发到指定的域名(通过 spec.externlName 设定),
需要 kube-dns 版本在 1.7 以上。

应用场景:
    集群内部访问:ClusterIP
    集群外部访问:
           集群访问外部:ExternalName
           外部访问集群:
                私有云:NodePort
                公有云:LoadBalancer
Service的代理模式

● userspace 代理模式

● iptables 代理模式

● ipvs 代理模式:

ipvs模式,kube-proxy 会监视 Kubernetes Service 对象和 Endpoints ,调用 netlink 接口以相应地创建 ipvs 规则并定期与 Kubernetes Service 对象和Endpoints 对象同步 ipvs 规则,以确保 ipvs 状态与期望一 致。访问服务时,流量将被重定向到其中一个后端 Pod 。与 iptables 类似,ipvs 于 netfilter 的 hook 功能,但使用哈希表作为底层数据结构并在内核空间中工作。这意 味着 ipvs 可以更快地重定向流量,并且在同步代理规则时具有更好的性能。此外,ipvs 为负载均衡算法提供了更多选项,例如:
rr :轮询调度
lc :最小连接数
dh :目标哈希
sh :源哈希
sed :最短期望延迟
nq : 不排队调度

ClusterIp
apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  type: ClusterIP
  selector:
    app: myapp
    release: stabel
  ports:
  - name: http
    port: 80
    targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      release: stabel
  template:
    metadata:
      labels:
        app: myapp
        release: stabel
        env: test
    spec:
      containers:
      - name: myapp
        image: mynginx:v1
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
通过集群分配给service IP访问
$ kubectl get svc -o wide
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE   SELECTOR
kubernetes   ClusterIP   241.254.0.1      <none>        443/TCP   25d   <none>
myapp        ClusterIP   241.254.228.65   <none>        80/TCP    36h   app=myapp,release=stabel
$ kubectl get pod -o wide   
NAME                            READY   STATUS    RESTARTS   AGE   IP              NODE     NOMINATED NODE   READINESS GATES
myapp-deploy-6d4bc5cc76-7n5tn   1/1     Running   2          32h   241.255.0.122   master   <none>           <none>
myapp-deploy-6d4bc5cc76-fprjr   1/1     Running   3          32h   241.255.3.41    node1    <none>           <none>

$ ipvsadm -Ln
... 
TCP  241.254.228.65:80 rr
  -> 241.255.0.122:80             Masq    1      0          1         
  -> 241.255.3.41:80              Masq    1      0          1         
....

$ curl 241.254.228.65/hostname.html
myapp-deploy-6d4bc5cc76-fprjr
$ curl 241.254.228.65/hostname.html
myapp-deploy-6d4bc5cc76-7n5tn
通过集群分配给service域名访问

在k8s集群中每个Service都会有一个DNS名称,Services 包括两种,一种是普通的service服务,一种是headless services。 普通的service 的DNS会解析到一个服务的集群IP,headless services 则会直接解析到所包含的pod的IP。

service 域名命名一般是:<服务名>.<命名空间>.svc.cluster.local
将svc域名解析到coreDNS服务器,集群内部DNS解析可参考kubernetes集群内部DNS解析原理这篇文章

$ yum -y install bind-utils
#使用dig命令测试svc name是否解析到DNS服务器
$ dig -t -A myapp.default.svc.cluster.local. @241.254.0.10
......
;; ANSWER SECTION:
myapp.default.svc.cluster.local. 30 IN  A       241.254.228.65
....

$ kubectl get svc -n kube-system
NAME       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   241.254.0.10   <none>        53/UDP,53/TCP,9153/TCP   25d

$ kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   241.254.0.1      <none>        443/TCP   25d
myapp        ClusterIP   241.254.228.65   <none>        80/TCP    2d1h

#可使用两种访问访问
#1、在宿主机/etc/resolv.conf 添加nameserver指向kube-dns
#cat /etc/resolv.conf 
#search localdomain
#nameserver 192.168.234.2
#nameserver 241.254.0.10
$ curl myapp.default.svc.cluster.local./hostname.html
myapp-deploy-6d4bc5cc76-7n5tn
$ curl myapp.default.svc.cluster.local./hostname.html
myapp-deploy-6d4bc5cc76-fprjr
#2.由于集群内pod解析默认的是指向kube-dns,所以也可随意在某个pod内访问
#由于pod内部的resolv.conf配置search域
#search域的作用就是将域名进行后缀匹配,例如myapp myapp.default.svc.cluster.local->myapp.svc.cluster.local
#->myapp.cluster.local直到匹配为止
$ kubectl exec mypod -- curl myapp.default.svc.cluster.local./hostname.html
$ kubectl exec mypod -- curl myapp/hostname.html
$ kubectl exec mypod -- curl myapp.default/hostname.html
$ kubectl exec mypod -- curl myapp.default.svc/hostname.html
#都可以访问到结果,只是效率会降低,因为多匹配一次dns查询

小贴士:ping通service域名

如果想要ping通service 域名,就必须让kube-proxy以ipvs代理模式运行。原因如下:
1、serviceIP是虚拟的地址,没有分配给任何网络接口,当数据包传输时不会把这个IP作为数据包的源IP或目的IP。
2、kube-proxy在iptables模式下,这个IP没有被设置在任何的网络设备上,ping这个IP的时候,没有任何的网络协议栈会回应这个ping请
求。在iptables模式时,clusterIp会在iptables的PREROUTING链里面用于nat转换规则中。
3、在ipvs模式下,所有的clusterIp会被设置在node上的kube-ipvs0的虚拟网卡上,这个时候去ping是可以通的
NodePort
apiVersion: v1
kind: Service
metadata:
  name: myapp-nodeport
  namespace: default
spec:
  type: NodePort
  selector:
    app: myapp
    release: stabel
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30001
$ kubectl get svc
NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes       ClusterIP   241.254.0.1     <none>        443/TCP        176m
myapp-nodeport   NodePort    241.254.6.59    <none>        80:30001/TCP   4m10s

#通过集群内部ip访问
$ curl 241.254.6.59/hostname.html
myapp-deploy-6d4bc5cc76-lfbbh
$ curl 241.254.6.59/hostname.html
myapp-deploy2-7bddc44f9c-srgj8
#通过宿主机ip访问
$ curl 192.168.116.128:30001/hostname.html
myapp-deploy-6d4bc5cc76-hkdlr
$ curl 192.168.116.128:30001/hostname.html
myapp-deploy-6d4bc5cc76-lfbbh   
ExternalName

这种类型的 Service 通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容( 例如:hub.hongfu.com )。ExternalName Service 是 Service 的特例,它没有 selector,也没有定义任何的端口和 Endpoint。相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务

kind: Service
apiVersion: v1
metadata:
  name: myservice
  namespace: default
spec:
  type: ExternalName
  externalName: www.baidu.com
$  kubectl get svc
NAME             TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
kubernetes       ClusterIP      241.254.0.1     <none>          443/TCP        3h43m
myservice        ExternalName   <none>          www.baidu.com   <none>         6m33s

由于CoreDNS会监测apiserver,当使用kubectl命令向apiServer提交service请求时,CoreDNS会为每一个Service创建DNS记录用于域名解析,当创建type类型为ExternalName,CoreDNS会将<服务名>.<命名空间>.svc.cluster.local**解析到externalName的值,比如上例的 myservice.default.svc.cluster.local会解析到www.baidu.com

$ nslookup myservice.default.svc.cluster.local
Server:         241.254.0.10
Address:        241.254.0.10#53
myservice.default.svc.cluster.local     canonical name = www.baidu.com.
www.baidu.com   canonical name = www.a.shifen.com.
Name:   www.a.shifen.com
Address: 180.101.49.12
Name:   www.a.shifen.com
Address: 180.101.49.11
Service与Pod与关联

两者之间通过标签关联,spec.template.metadata.labels为pod打上名为mediaplus-main的标签,Service的spec.selector需要与spec.template.metadata.labels值一致

apiVersion: v1
kind: Service
metadata:
  name: mediaplus-main
  labels:
    app: mediaplus-main
spec:
..............
  selector:
    app: mediaplus-main
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mediaplus-main
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mediaplus-main
  template:
    metadata:
      labels:
        app: mediaplus-main
    spec:
      containers:
        - name: mediaplus-main
Service与Ingress关联

Service只能实现四层代理 传输层,基于IP和端口
Ingress可以实现七层代理 应用层,基于应用协议转发,例如http协议
Ingress与Service之间通过匹配serviceName绑定,metadata.labels为Service打上mediaplus-main的标签,spec.rules.backend.serviceName的值需要与mediaplus-main保持一致

apiVersion: v1
kind: Service
metadata:
  name: mediaplus-main
  labels:
    app: mediaplus-main
spec:
..............
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: name-virtual-host-ingress
spec:
  tls:
    - secretName: sign-secret
  rules:
.........
          - backend:
              serviceName: mediaplus-main
              servicePort: 3000
            path: /  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值