kubernetes之service

1. service介绍

Kubernetes Service定义了这样一种抽象:逻辑上的一组Pod,一种可以访问它们的策略 —— 通常被称为微服务。这一组Pod能够被Service访问到,通常是通过selector实现的。

Service可以提供负载均衡的能力,但是使用上存在如下限制:

  • 只能提供4层负载均衡能力,而没有7层功能。有时我们可能需要更多的匹配规则来转发请求,这点上4层负载均衡是不支持的

1.1 VIP和Service代理

在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy 进程。kube-proxy 负责为 Service 实现了一种 VIP(虚拟 IP)的形式,而不是 ExternalName 的形式。

从Kubernetes v1.0开始,已经可以使用 userspace代理模式。Kubernetes v1.1添加了 iptables 代理模式,在 Kubernetes v1.2 中kube-proxy 的 iptables 模式成为默认设置。Kubernetes v1.8添加了 ipvs 代理模式。

为什么不使用 DNS 轮询?
原因如下:

  • DNS 实现的历史由来已久,它不遵守记录 TTL,并且在名称查找到结果后会对其进行缓存。
  • 有些应用程序仅执行一次 DNS 查找,并无限期地缓存结果。
  • 即使应用和库进行了适当的重新解析,DNS 记录上的 TTL 值低或为零也可能会给 DNS 带来高负载,从而使管理变得困难。

1.2 iptables 代理模式

这种模式,kube-proxy 会监视 Kubernetes 控制节点对 Service 对象和 Endpoints 对象的添加和移除。 对每个 Service,它会配置 iptables 规则,从而捕获到达该 Service 的 clusterIP 和端口的请求,进而将请求重定向到 Service 的一组 backend 中的某个上面。对于每个 Endpoints 对象,它也会配置 iptables 规则,这个规则会选择一个 backend 组合。

默认的策略是,kube-proxy 在 iptables 模式下随机选择一个 backend。

使用 iptables 处理流量具有较低的系统开销,因为流量由 Linux netfilter 处理,而无需在用户空间和内核空间之间切换。 这种方法也可能更可靠。

如果 kube-proxy 在 iptables模式下运行,并且所选的第一个 Pod 没有响应,则连接失败。 这与userspace模式不同:在这种情况下,kube-proxy 将检测到与第一个 Pod 的连接已失败,并会自动使用其他后端 Pod 重试。

我们可以使用 Pod readiness 探测器 验证后端 Pod 是否可以正常工作,以便 iptables 模式下的 kube-proxy 仅看到测试正常的后端。这样做意味着可以避免将流量通过 kube-proxy 发送到已知已失败的Pod。

1.3 IPVS 代理模式

在 ipvs 模式下,kube-proxy监视Kubernetes服务(Service)和端点(Endpoints),调用 netlink 接口相应地创建 IPVS 规则, 并定期将 IPVS 规则与 Kubernetes服务(Service)和端点(Endpoints)同步。该控制循环可确保 IPVS 状态与所需状态匹配。访问服务(Service)时,IPVS 将流量定向到后端Pod之一。

IPVS代理模式基于类似于 iptables 模式的 netfilter 挂钩函数,但是使用哈希表作为基础数据结构,并且在内核空间中工作。 这意味着,与 iptables 模式下的 kube-proxy 相比,IPVS 模式下的 kube-proxy 重定向通信的延迟要短,并且在同步代理规则时具有更好的性能。与其他代理模式相比,IPVS 模式还支持更高的网络流量吞吐量。

IPVS提供了更多选项来平衡后端Pod的流量。这些是:

  • rr: round-robin
  • lc: least connection (smallest number of open connections)
  • dh: destination hashing
  • sh: source hashing
  • sed: shortest expected delay
  • nq: never queue

注意:要在 IPVS 模式下运行 kube-proxy,必须在启动 kube-proxy 之前使 IPVS Linux 在节点上可用。 当 kube-proxy 以 IPVS 代理模式启动时,它将验证 IPVS 内核模块是否可用。 如果未检测到 IPVS 内核模块,则 kube-proxy 将退回到以 iptables 代理模式运行。

2. Service服务类型

Kubernetes 中Service有以下4中类型:

  • ClusterIP:默认类型,自动分配一个仅Cluster内部可以访问的虚拟IP
  • NodePort:通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务。以ClusterIP为基础,NodePort 服务会路由到 ClusterIP 服务。通过请求 :,可以从集群的外部访问一个集群内部的 NodePort 服务。
  • LoadBalancer:使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。
  • ExternalName:通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容(例如,foo.bar.example.com)。没有任何类型代理被创建.

需要注意的是:Service 能够将一个接收 port 映射到任意的 targetPort。默认情况下,targetPort 将被设置为与 port 字段相同的值。

Service域名格式:( s e r v i c e n a m e ) . (service name).(servicename).(namespace).svc.cluster.local,其中 cluster.local 为指定的集群的域名

Deoployment的资源清单

[root@master test]# cat test.yml 
---
apiVersion: v1
kind: Pod
metadata:
  name: test
  labels: 
    app: test
spec:
  containers:
  - image: nginx
    name: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: test
spec:
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30001
  selector:
    app: test
  type: NodePort

[root@master test]# kubectl apply -f deploy.yml 
deployment.apps/deploy created

[root@master test]# kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP            NODE                NOMINATED NODE   READINESS GATES
deploy-585449566-lkdnn   1/1     Running   0          24s   10.244.2.68   node2.example.com   <none>           <none>
deploy-585449566-ngbwj   1/1     Running   0          24s   10.244.1.75   node1.example.com   <none>           <none>
deploy-585449566-nlnpl   1/1     Running   0          24s   10.244.1.76   node1.example.com   <none>           <none>

[root@master test]# curl 10.244.2.68
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

[root@master test]# curl 10.244.1.75
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

[root@master test]# curl 10.244.1.76
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

2.1 ClusterIP类型

[root@master test]# cat svc.yml 
apiVersion: v1
kind: Service
metadata:
  name: svc
spec:
  selector:
    app: nginx
  ports:
  - name: nginx
    port: 80
    targetPort: 80

[root@master test]# kubectl apply -f svc.yml 
service/svc created

[root@master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   9d
svc          ClusterIP   10.96.69.194   <none>        80/TCP    8s

[root@master ~]# curl 10.96.69.194
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

2.2 NodePort类型

[root@master test]# cat svc-nodeport.yml 
apiVersion: v1
kind: Service
metadata:
  name: svc-nodeport
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
  - name: nginx1
    port: 80
    targetPort: 80
    nodePort: 30001

[root@master test]# kubectl apply -f svc-nodeport.yml
service/svc-nodeport created

[root@master test]# kubectl get svc
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP        9d
svc-nodeport   NodePort    10.109.130.221   <none>        80:30001/TCP   95s

[root@master test]# curl 10.109.130.221:30001
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

[root@master test]# curl 10.109.130.221
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

2.3 LoadBalancer类型

在使用支持外部负载均衡器的云提供商的服务时,设置 type 的值为 “LoadBalancer”, 将为 Service 提供负载均衡器。 负载均衡器是异步创建的,关于被提供的负载均衡器的信息将会通过 Service 的 status.loadBalancer 字段发布出去。

apiVersion: v1
kind: Service
metadata:
  name: test1
spec:
  selector:
    app: test1
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
  clusterIP: 10.106.217.38
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
      - ip: 192.15.8.127


来自外部负载均衡器的流量将直接重定向到后端 Pod 上,不过实际它们是如何工作的,这要依赖于云提供商。

某些云提供商允许设置 loadBalancerIP。 在这些情况下,将根据用户设置的 loadBalancerIP 来创建负载均衡器。 如果没有设置 loadBalancerIP 字段,将会给负载均衡器指派一个临时 IP。 如果设置了 loadBalancerIP,但云提供商并不支持这种特性,那么设置的 loadBalancerIP 值将会被忽略掉。

3. 案例

在这里插入图片描述

3.1 创建一个deployment副本数为3,然后滚动更新镜像版本,并记录这个更新记录,最后再回滚到上一个版本

[root@master test]# cat test.yml 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test
  labels: 
    app: test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: test
  template:
    metadata:
      labels:
        app: test
    spec: 
      containers:
      - image: dockerimages123/httpd:v0.1
        name: test
        imagePullPolicy: IfNotPresent


[root@master test]# kubectl apply -f test.yml 
deployment.apps/test created

[root@master haproxy]# kubectl get pod
NAME                    READY   STATUS    RESTARTS   AGE
test-85cd869cd6-7524t   1/1     Running   0          4m49s
test-85cd869cd6-8khgw   1/1     Running   0          4m49s
test-85cd869cd6-kc7fw   1/1     Running   0          4m49s

// 滚动更新
[root@master haproxy]# kubectl set image deploy/test test=dockerimage123/httpd:v2.0
deployment.apps/test image updated

[root@master haproxy]# kubectl get pod
NAME                    READY   STATUS        RESTARTS   AGE
test-6cfbd9b7f-5dxjk    1/1     Running       0          13s
test-6cfbd9b7f-8kbs8    1/1     Running       0          11s
test-6cfbd9b7f-sv9km    1/1     Running       0          14s
test-85cd869cd6-7524t   1/1     Terminating   0          9m24s
test-85cd869cd6-8khgw   1/1     Terminating   0          9m24s
test-85cd869cd6-kc7fw   1/1     Terminating   0          9m24s

[root@master haproxy]# kubectl get pod
NAME                   READY   STATUS    RESTARTS   AGE
test-6cfbd9b7f-5dxjk   1/1     Running   0          103s
test-6cfbd9b7f-8kbs8   1/1     Running   0          101s
test-6cfbd9b7f-sv9km   1/1     Running   0          104s


[root@master haproxy]# kubectl rollout history deploy test
deployment.apps/test 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>

[root@master haproxy]# kubectl rollout history deploy test --revision=3    
deployment.apps/test with revision #3  //查看上一个版本的信息
Pod Template:
  Labels:       app=test
        pod-template-hash=6cfbd9b7f
  Containers:
   test:
    Image:      dockerimages123/httpd:v2.0
    Port:       <none>
    Host Port:  <none>
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>
  
[root@master haproxy]# kubectl rollout undo deploy test  //回滚到上一个版本
deployment.apps/test rolled back

[root@master haproxy]# kubectl get pod
NAME                    READY   STATUS             RESTARTS   AGE
test-6cfbd9b7f-5dxjk    1/1     Running            0          32m
test-6cfbd9b7f-8kbs8    1/1     Running            0          32m
test-6cfbd9b7f-sv9km    1/1     Running            0          32m

3.2 给一个应用扩容副本数为3

[root@master test]# kubectl create deploy test --image nginx
deployment.apps/test1 created

[root@master test]# kubectl get pod
test1-6d5588f8cc-4hgnt   1/1     Running             0          6m33s

[root@master test]# kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
test-5f6778868d-4t9xd    1/1     Running   0          2m23s
test1-6d5588f8cc-4hgnt   1/1     Running   0          8m51s
test1-6d5588f8cc-b9qsw   1/1     Running   0          49s
test1-6d5588f8cc-vkvh5   1/1     Running   0          49s

3.3 创建一个pod,其中运行着nginx、redis、mamcached

[root@master test]# cat test.yml 
---
apiVersion: v1
kind: Pod
metadata:
  name: test
  labels: 
    app: test
spec:
  containers:
  - image: nginx
    name: nginx
  - image: redis
    name: redis
  - image: memcached
    name: memcached



[root@master test]# kubectl apply -f test.yml 
pod/test created

[root@master test]# kubectl get pod
NAME   READY   STATUS             RESTARTS   AGE
test3   3/3     Running            0         18m


3.4 给一个pod创建一个service,并可以通过Cluster/NodePort访问

[root@master test]# cat test.yml 
---
apiVersion: v1
kind: Pod
metadata:
  name: test
  labels: 
    app: test
spec:
  containers:
  - image: nginx
    name: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: test1
spec:
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30001
  selector:
    app: test1
  type: NodePort


[root@master test]# kubectl apply -f test.yml
pod/test unchanged
service/test created

[root@master test]# kubectl get pod,svc
NAME        READY   STATUS    RESTARTS   AGE
pod/test   1/1     Running   0          50s

NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP        7d1h
service/test4        NodePort    10.110.1100.198   <none>        80:30001/TCP   50s

[root@master test]# curl 10.110.1100.198 
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

[root@master test]# curl 192.168.182.150:30001
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

3.5 创建deployment和service,使用busybox容器nslookup解析service

[root@master test]# kubectl run test2 --image busybox -- sleep 500
pod/test2 created

[root@master test]# kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
test2   1/1     Running   0          22s

[root@master test]# kubectl exec -it test2 -- /bin/sh
/ # nslookup kubernetes
Server:         10.96.0.10
Address:        10.96.0.10:53

Name:   kubernetes.default.svc.cluster.local
Address: 10.96.0.1

*** Can't find kubernetes.svc.cluster.local: No answer
*** Can't find kubernetes.cluster.local: No answer
*** Can't find kubernetes.example.com: No answer
*** Can't find kubernetes.default.svc.cluster.local: No answer
*** Can't find kubernetes.svc.cluster.local: No answer
*** Can't find kubernetes.cluster.local: No answer
*** Can't find kubernetes.example.com: No answer



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彭宇栋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值