kkwen

kubernetes之service
kubernetes上的对象(如pod)被重启后可能IP地址会发生变化,于是在此弹性管理之下,service资源用...
扫描右侧二维码阅读全文
14
2019/03

kubernetes之service

kubernetes上的对象(如pod)被重启后可能IP地址会发生变化,于是在此弹性管理之下,service资源用于为此类pod提供一个固定、统一的访问入口以及负载均衡能力,并借助于DNS系统的服务发现功能,解决发现并访问容器花应用的难题

Service也是kubernetes的标准资源对象之一,本质上是iptables或ipvs之上的一条DNAT或SNAT规则而已,它的IP地址并没有配置于某个网卡之上

Service工作代理模式:

  • userspace:1.1-
    service工作模式userspace.png
请求到达service ip之后。先转到本地监听在某个套接字上的kube-proxy(用户空间)上做处理,处理完之后再转给service ip
Service ip再将其转发至目标pod,实现调度。
由工作在用户空间的kube-proxy负责调度,service需要和用户空间kube-proxy交互,效率很低
  • iptables:1.10-
    service工作模式iptables.png
客户端请求直接请求service ip,后被本地内核空间中的service规则截取,从而直接调度给相关的pod
  • ipvs:1.11+
    ipvs.png
客户端请求直接请求service ip,后被本地内核空间中的ipvs直接调度给相关的pod
若有pod资源变化,会将信息同步到api-service中,kube-proxy会watch到这种变化,将其反应在iptables(ipvs)规则之中

Service类型:

  1. ClusterIp 默认,仅用于集群内通信
port:service上的端口
targetPort:pod上的端口
无头Service:
    当service的clusterIP为None时
  1. NodePort: 接入集群外部流量
  2. LoadBalancer: 云环境支持lbaas
  3. ExternalName:把集群外部流量引入集群内部

Service相关操作

  • Service资源清单示例
[root@ _37_ ~/k8s]# cat redis-svc.yaml
apiVersion: v1
kind: Service
metadata:
    name: redis
    namespace: default
spec:
    selector:
      app: redis
      role: logstor
    clusterIP: 10.96.97.97
    type: ClusterIP
    ports:
    - port: 6379
      targetPort: 6379
  • 查看其Service
[root@ _81_ ~/k8s]# kubectl describe svc redis
Name:              redis
Namespace:         default
Labels:            <none>
Annotations:       kubectl.kubernetes.io/last-applied-configuration:
                     {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"redis","namespace":"default"},"spec":{"clusterIP":"10.96.97.97","...
Selector:          app=redis,role=logstor
Type:              ClusterIP
IP:                10.96.97.97
Port:              <unset>  6379/TCP
TargetPort:        6379/TCP
Endpoints:         10.244.1.65:6379
Session Affinity:  None
Events:            <none>
  • Service和Endpoints以及pod
    service-endpoint-pod.png
service在关联pod时并不是直接关联pod,而是通过关联endpoints,endpoints再去关联目标pod
  • Service资源记录
资源记录:访问service完整的地址如下格式,在pod中访问会默认加上后缀
    SVC_NAME.NS_NAME.DOMAIN.LTD.
    svc.cluster.local.
    redis.default.svc.cluster.local.
  • Service的NodePort类型配置清单
[root@ _30_ ~/k8s]# cat redis-svc-nodeport.yaml 
apiVersion: v1
kind: Service
metadata:
    name: myapp
    namespace: default
spec:
    selector:
      app: myapp
      release: canary
    clusterIP: 10.96.97.96
    type: NodePort
    ports:
    - port: 80
      targetPort: 80
      nodePort: 30080
  • 查看Service,service简写为svc
此时若service类型为NodePort,可以发现在所有节点之上,该端口都被打开,若有的节点已经使用该端口,则service强制被应用到这个端口之上,之前监听该端口的应用程序失效
[root@ _88_ ~/k8s]# kubectl get svc 
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        61d
myapp        NodePort    10.96.97.96   <none>        80:30080/TCP   4m41s
redis        ClusterIP   10.96.97.97   <none>        6379/TCP       23h
  • 集群外部访问该service资源
$ curl -s 192.168.1.11:30080
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
$ 
$ curl -s 192.168.1.12:30080
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>

LoadBalancer:

  • 调用底层云服务的的iaas(lbas),创建一个软负载均衡器,外部用户访问该软负载均衡,由其调度至集群中的某一node
  • 再由node通过service反代给多个pod中的某一个
  • 此为两级调度

ExternalName

ExternalName.png

service特性之sessionAffinity

  • svc.spec.sessionAffinity 回话粘性,用于负载均衡调度,
ClinetIP  基于ClientIP调度
None  随机调度
  • 修改sessionAffinity为ClientIP,实现基于源ip的回话粘性调度
[root@ _127_ ~/k8s]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        63d
myapp        NodePort    10.96.97.96   <none>        80:30080/TCP   25h
myapp-svc    ClusterIP   None          <none>        80/TCP         32m
redis        ClusterIP   10.96.97.97   <none>        6379/TCP       2d
[root@ _128_ ~/k8s]# kubectl describe svc myapp
Name:                     myapp
Namespace:                default
Labels:                   <none>
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"myapp","namespace":"default"},"spec":{"clusterIP":"10.96.97.96","...
Selector:                 app=myapp,release=canary
Type:                     NodePort
IP:                       10.96.97.96
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30080/TCP
Endpoints:                10.244.1.69:80,10.244.1.70:80,10.244.1.71:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
  • 打补丁修该sessionAffinity为ClusterIP
kubectl patch svc myapp -p '{"spec":{"sessionAffinity":"ClientIP"}}'

无头service

  • 当service的clusterIP为None时
  • 无头service配置清单
[root@ _123_ ~/k8s]# cat myapp-svc-headless.yaml 
apiVersion: v1
kind: Service
metadata:
    name: myapp-svc
    namespace: default
spec:
    selector:
      app: myapp
      release: canary
    clusterIP: None
    ports:
    - port: 80
      targetPort: 80
  • 此时service没有ip,使用该service名称访问的请求直接被转发至后端EndPoints端点
  • 查看该service
[root@ _115_ ~/k8s]# kubectl apply -f myapp-svc-headless.yaml
service/myapp-svc created
[root@ _116_ ~/k8s]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        62d
myapp        NodePort    10.96.97.96   <none>        80:30080/TCP   24h
myapp-svc    ClusterIP   None          <none>        80/TCP         5s
redis        ClusterIP   10.96.97.97   <none>        6379/TCP       47h
  • 查看kube-dns的ip
[root@ _118_ ~/k8s]# kubectl get svc -n kube-system
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP   62d
  • 解析该service地址
[root@ _119_ ~/k8s]# dig -t A myapp-svc.default.svc.cluster.local. @10.96.0.10
;
; <<>> DiG 9.9.4-RedHat-9.9.4-29.el7 <<>> -t A myapp-svc.default.svc.cluster.local. @10.96.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18759
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
;
;; QUESTION SECTION:
;myapp-svc.default.svc.cluster.local. IN        A
;
;; ANSWER SECTION:
myapp-svc.default.svc.cluster.local. 5 IN A     10.244.1.71
myapp-svc.default.svc.cluster.local. 5 IN A     10.244.1.70
myapp-svc.default.svc.cluster.local. 5 IN A     10.244.1.69
;
;; Query time: 642 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Wed Mar 13 08:57:13 CST 2019
;; MSG SIZE  rcvd: 206

service之前的七层调度工具

  • treafik
  • nginx
  • service mesh => envoy
  • haproxy
最后修改:2019 年 03 月 15 日 08 : 25 AM
如果觉得我的文章对你有用,请随意赞赏

发表评论