• k8s的service自动发现服务:实战版


    Service服务发现的必要性:

    对于kubernetes整个集群来说,Pod的地址也可变的,也就是说如果一个Pod因为某些原因退出了,而由于其设置了副本数replicas大于1,那么该Pod就会在集群的任意节点重新启动,这个重新启动的Pod的IP地址与原IP地址不同,这对于业务来说,就不能根据Pod的IP作为业务调度。kubernetes就引入了Service的概念,它为Pod提供一个入口,主要通过Labels标签来选择后端Pod,这时候不论后端Pod的IP地址如何变更,只要Pod的Labels标签没变,那么 业务通过service调度就不会存在问题。

    当声明Service的时候,会自动生成一个cluster IP,这个IP是虚拟IP。我们就可以通过这个IP来访问后端的Pod,当然,如果集群配置了DNS服务,比如现在的CoreDNS,那么也可以通过Service的名字来访问,它会通过DNS自动解析Service的IP地址。

    Service的模式有三种,user space,iptables,ipvs:
    1、userspace模式
    客户端请求到内核空间后,由iptables规则将其转发到用户空间的 kube-proxy,kube-proxy 将其调度到各个node上的目标Pod。这种模式需要多次切换用户空间和内核空间,性能很差,生产环境不再使用。

    在这里插入图片描述

    2、iptables模式
    iptables模式中,客户端的请求进入内核态后,直接由iptables将请求转发到各个pod上,这种模式中随着iptables规则的增加,性能越来越差,而且iptables规则查看和管理难度很大,生产环境中尽量少用。

    在这里插入图片描述

    3、ipvs模式
    ipvs模式中,客户端的请求进入内核态后,直接由ipvs规则将请求转发到各个pod上,这种模式相当于内嵌一套lvs集群,性能比iptables强大,更重要的是支持lvs中调度算法,生产环境中ipvs模式优先考虑使用。ipvs内部时使用ipset维护映射关系,由于是hash链表,因此查询速度远远大于iptables的遍历速度。

    在这里插入图片描述

    Service的类型有四种:Cluster IP,LoadBalance,NodePort,ExternalName

    其中Cluster IP是默认的类型。
    (1)、Cluster IP:通过 集群内部IP暴露服务,默认是这个类型,选择该值,这个Service服务只能通过集群内部访问;
    (2)、LoadBalance:使用云提供商的负载均衡器,可以向外部暴露服务,选择该值,外部的负载均衡器可以路由到NodePort服务和Cluster IP服务;
    (3)、NodePort:顾名思义是Node基本的Port,如果选择该值,这个Service可以通过NodeIP:NodePort访问这个Service服务,NodePort会路由到Cluster IP服务,这个Cluster IP会通过请求自动创建;
    (4)、ExternalName:通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容,没有任何类型代理被创建,可以用于访问集群内其他没有Labels的Pod,也可以访问其他NameSpace里的Service。

    今天我主要介绍两种类型的用法Cluster IP和NodePort

    开始实验

    代码我还是用上个实验的tomcat+mysql项目zrlog

    mysql的service用Cluster IP类型,因为mysql只通过集群内部访问也可以了

    tomcat的service用NodePort类型,因为tomcat要和mysq通信,也要和外部通信

    k8s集群的安装这里就不讲了 前面的文章有详细的写了,没装好的可以去看看

    首先配置好系统环境

    [root@server153 test]#  modprobe  ip_va
    [root@server153 test]#  echo "ip_vs" >> /etc/modules-load.d/k8s.conf
    
    • 1
    • 2

    然后创建一个空目录

    开始编写yaml文件,如果不想手写那么多代码的,可以生成一个模板,我上一篇文章也有介绍了

    tomcat和mysql的代码其实也可以写在一个文件里,用—分开就可以了,但是那样太长了,所以我分两个文件写

    先写tomcat的yaml文件

    [root@server153 test]# cat tomcat-deploy.yaml 
    apiVersion: v1
    kind: Service  # 声明版本为Service
    metadata:
      name: tomcat-service   # 定义Service的名字
      labels:
        name: show-tomcat-pod    # 定义Service的标签
    spec:
      type: NodePort   # 定义Service的类型,自动分配一个集群serviceip
      selector:
        app: tomcat-deploy   #定义标签选择器,会代理后端app=tomcat-deploy的Pod
      ports:
      - port: 80   #内部暴露的端口    
        targetPort: 8080  #代理的pod的端口 
        nodePort: 31111 #暴露给主机外部访问的端口(default: 30000-32767)
    
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: tomcat-deploy
      name: tomcat-deploy
      namespace: default
    spec:
      progressDeadlineSeconds: 600
      replicas: 1
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          app: tomcat-deploy
      strategy:
        rollingUpdate:
          maxSurge: 25%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          labels:
            app: tomcat-deploy
        spec:
          #创建init容器
          initContainers:
            #代码镜像
          - image: www.test.com/mytest/zrlog:v1
            #init容器名字
            name: init
            #将代码复制到匿名数据卷
            command: ["cp","-r","/tmp/ROOT.war","/www"]
            #将匿名数据卷挂载到容器中的/www目录下
            volumeMounts:
            - mountPath: /www
              name: tomcat-volume
          #创建tomcat容器
          containers:
          - image: oxnme/tomcat
            imagePullPolicy: Always
            name: tomcat
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
            #将数据卷挂载到tomcat的代码目录下
            volumeMounts:
            - mountPath: /usr/local/tomcat/webapps/
              name: tomcat-volume
          dnsPolicy: ClusterFirst
          restartPolicy: Always
          schedulerName: default-scheduler
          terminationGracePeriodSeconds: 10
    
          #创建匿名数据卷
          volumes:
          - name: tomcat-volume
            emptyDir: {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    然后是mysql的yaml文件,有些是一样的字段,所以我就不写注释了

    本来mysql这种有状态的pod应该用StatefulSet控制器的,但是现在主要是实验service

    所以我就用简单的pod来代替了

    [root@server153 test]# cat mysql-pod.yaml 
    apiVersion: v1
    kind: Service
    metadata:
      name: mysql-headless-service
      labels:
        name: svc-mysql-pod
    spec:
      type: ClusterIP
      selector:
        run: mysql-pod
      ports:
      - port: 3306   #内部的暴露端口
        targetPort: 3306  #代理的pod的端口,这里不用暴露给外部网络访问,所以不用写nodePort了
    
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        run: mysql-pod
      name: mysql-pod
      namespace: default
    spec:
      containers:
      - image: mysql:5.7
        imagePullPolicy: IfNotPresent
        name: mysql-pod
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        env:
        - name: MYSQL_ROOT_PASSWORD #定义mysql的初始密码
          value: MySQL@666
        - name: MYSQL_DATABASE     #初始化是创建一个zrlog数据库
          value: Zrlog
      dnsPolicy: ClusterFirst
      enableServiceLinks: true
      preemptionPolicy: PreemptLowerPriority
      restartPolicy: Always
      schedulerName: default-scheduler
      serviceAccount: default
      serviceAccountName: default
      terminationGracePeriodSeconds: 30
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    配置文件写好以后就可以启动服务了

    [root@server153 test]# kubectl apply -f mysql-pod.yaml 
    service/mysql-headless-service created
    pod/mysql-pod created
    [root@server153 test]# kubectl apply -f tomcat-deploy.yaml 
    service/tomcat-service created
    deployment.apps/tomcat-deploy created
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    看运行结果可以看到service和pod都被创建了,然后去查看pod和service的情况

    [root@server153 test]# kubectl get pods
    NAME                             READY   STATUS    RESTARTS   AGE
    mysql-pod                        1/1     Running   0          104s
    tomcat-deploy-555479bdf4-bj7mt   1/1     Running   0          96s
    [root@server153 test]# kubectl get service
    NAME                     TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
    kubernetes               ClusterIP   10.1.0.1      <none>        443/TCP        4d3h
    mysql-headless-service   ClusterIP   10.1.50.178   <none>        3306/TCP       2m13s
    tomcat-service           NodePort    10.1.7.229    <none>        80:31111/TCP   2m5s
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    可以看到情况是正常的

    然后我们去看service的详细情况

    [root@server153 ~]# kubectl describe services
    
    • 1

    在这里插入图片描述

    然后我们去浏览器访问刚才我们定义的外部端口31111

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    可以看到是能访问的,不需要像上次那样又查看变化的ip又要nginx代理才能访问了

    就像docker端口映射一样,现在就可以通过端口访问了

    然后我们连接数据库安装

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    然后我们的service实验就完成了

    pod之间的访问通过名称和端口就可以了,service是通过标签名来自动发现的,所以ip再怎么变也没有关系

    这就解决了pod重建ip会变的问题了

    希望对大家的学习有帮助

  • 相关阅读:
    《Android Gradle》权威指南笔记
    Elasticsearch 安装-Windows
    【Java 进阶篇】JSTL 详解
    安装MMRotate流程
    HarmonyOS应用开发Web组件基本属性应用和事件
    .NET Core Web APi类库如何内嵌运行?
    【C++】模板
    《HelloGitHub》第 98 期
    封神工具:腾讯云服务器价格计算器_好工具分享
    NCCL P2P与共享内存SHM的差异
  • 原文地址:https://blog.csdn.net/m0_58833554/article/details/134390673