• SVC服务的发现


    服务的发现

    发现的方式

    服务的发现说的就是svc的ip只有集群内的资源可以访问到,比如集群内的节点,pod
    到底说的是什么意思呢?我们可以来看看LNMP架构(Linux + Nginx + Mysql + php)搭建的wordpress
    首先wordpress是需要对接数据库的,那么wordpress部署在集群里如何去对接后端的数据库存储数据呢?这也就是服务的发现
    也就是说你要通过什么方式去让前端的wordpress去对接后端的数据库

    1. ClusterIP

    每个pod被创建出来之后,都会被分配一个IP地址,但是这个IP地址只有集群内部可以访问到,那么既然他都有IP地址了,为什么要通过这个ClusterIP呢?
    我们来仔细分析这句话,每个Pod都会被分配IP地址,那万一这个Pod是被deployment管理的,这个pod被意外删除了,那么控制器会重新启一个pod,那么这个pod会有一个新的IP,这个时候你的wordpress指定的数据库地址还是之前的那个地址,然而那个地址已经不存在,那么你的wordpress就会报数据库连接失败的错误
    我们来看看是不是这样

    copy
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    # 我们创建一个控制器,副本数为1,看看IP,然后我们手动删除他创建出来的那个pod,然后我们再看看这个新的Pod的IP
    [root@master ~]# kubectl create deployment test01 --image nginx
    deployment.apps/test01 created
    [root@master ~]# kubectl get pods -o wide
    NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    test01-994bb76cb-2qd5g 1/1 Running 0 33s 10.244.104.59 node2
    # 我们现在看到,这个Pod的IP是 10.244.104.59,删除这个pod
    [root@master ~]# kubectl delete pod/test01-994bb76cb-2qd5g
    pod "test01-994bb76cb-2qd5g" deleted
    [root@master ~]# kubectl get pods -o wide
    NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    test01-994bb76cb-4vtkw 1/1 Running 0 25s 10.244.166.182 node1

    我们通过这个小实验可以看到,IP是会变动的,那么我们使用以前的IP访问现在的Pod肯定是不行的,那么有没有一种办法就是给他们一个浮动IP呢,我每次只需要访问这个浮动IP,他会自动帮我把流量转发到pod下面呢?有的
    这个就是ClusterIP的作用
    再来看一个实验 还是这个控制器,我们给这个控制器创建一个svc,然后通过svc的浮动IP去访问pod

    copy
    • 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
    # 由于刚刚的deployment并没有删除,那我现在接着做
    [root@master ~]# kubectl expose deployment test01 --port 80 --target-port 80
    # 这里的--port 是svc暴露的端口,可以随意修改、
    # --target-port 是指的pod内的服务端口,你的pod开放什么端口这里就要写什么,写错了服务就访问不到的
    [root@master ~]# kubectl expose deployment test01 --port 80 --target-port 80
    service/test01 exposed
    [root@master ~]# kubectl get svc
    # 我不是在默认的命名空间下,如果你是在默认的命名空间下还会有一个默认的Kubernets的svc
    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    test01 ClusterIP 10.98.54.158 80/TCP 3s
    # 我们通过这个ip地址来访问一下nginx看看
    [root@master ~]# curl 10.98.54.158
    <head>
    Welcome to nginx!
    …… 省略部分信息
    # 可以访问到nginx的首页,我们删除这个pod,然后再来使用这个IP地址看看
    [root@master ~]# kubectl delete pods/test01-994bb76cb-4vtkw
    pod "test01-994bb76cb-4vtkw" deleted
    [root@master ~]# kubectl get pods -o wide
    NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    test01-994bb76cb-ntwjn 1/1 Running 0 15s 10.244.104.55 node2
    # 他的pod的IP地址已经变了,我们来看看svc的地址能否继续访问到
    [root@master ~]# curl 10.98.54.158
    <head>
    Welcome to nginx!
    ……省略部分信息

    通过这个实验我们看到了,我们可以通过这这种方式来给这些个pod一个浮动的IP,无论你Pod的IP地址怎么变动,我只要访问你的浮动IP就可以了。并不需要知道或者固定你的IP

    2. 通过变量

    学习这个之前你得先能搞懂ClusterIP!!!
    在K8S集群里面,每个被创建出来的pod都会去加载当前命名空间下的所有的SVC并注册成环境变量,注意,是所有,大概的流程就是这样的
    pod1 pod2 pod3

    svc1 svc2 svc3
    ----------------------------------->时间线
    这个图的意思就是在创建一个pod1的时候,他会把svc1注册成他的一个环境变量,创建pod2的时候会把svc1和svc2都注册,pod3则会把svc1,svc2和svc3全部注册到环境变量里面
    pod1不会加载svc2和svc3,因为在创建pod1的时候svc2和svc3还没有被创建出来
    大概就是这样一个流程,我们来看看是不是这样

    copy
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    [root@master wordpress]# kubectl get svc
    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    test01 ClusterIP 10.98.54.158 80/TCP 16m
    # 我们先进入刚刚的nginx看看环境变量
    [root@master wordpress]# kubectl exec -it pods/test01-994bb76cb-ntwjn -- bash
    root@test01-994bb76cb-ntwjn:/# env |grep -i test01
    HOSTNAME=test01-994bb76cb-ntwjn
    TEST01_SERVICE_PORT=80
    TEST01_PORT_80_TCP_PROTO=tcp
    TEST01_PORT_80_TCP_ADDR=10.98.54.158
    TEST01_PORT=tcp://10.98.54.158:80
    TEST01_PORT_80_TCP=tcp://10.98.54.158:80
    TEST01_SERVICE_HOST=10.98.54.158
    TEST01_PORT_80_TCP_PORT=80

    我们可以看到他确实有这些变量,而且有一个变量是TEST01_SERVICE_HOST 这个不就是浮动IP地址吗
    我们再来创建一个新的pod,叫做pod02,给这个pod也创建一个svc,最后我们创建一个pod03,进入到pod03里面看看是不是有svc1和svc2的变量

    copy
    • 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
    [root@master wordpress]# kubectl run pod02 --image nginx --image-pull-policy IfNotPresent
    pod/pod02 created
    [root@master wordpress]# kubectl expose pod pod02 --port 80 --target-port 80
    service/pod02 exposed
    [root@master wordpress]# kubectl get svc
    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    pod02 ClusterIP 10.105.166.129 80/TCP 10s
    test01 ClusterIP 10.98.54.158 80/TCP 21m
    # 现在有pod02的svc和test01的svc
    # 创建新的pod,直接进去里面看看环境变量
    [root@master wordpress]# kubectl run pod03 --image nginx --image-pull-policy IfNotPresent
    pod/pod03 created
    [root@master wordpress]# kubectl exec -it pods/pod03 -- bash
    root@pod03:/# env |grep -i pod02
    POD02_PORT_80_TCP_PROTO=tcp
    POD02_PORT_80_TCP_ADDR=10.105.166.129
    POD02_PORT=tcp://10.105.166.129:80
    POD02_SERVICE_HOST=10.105.166.129
    POD02_PORT_80_TCP_PORT=80
    POD02_PORT_80_TCP=tcp://10.105.166.129:80
    POD02_SERVICE_PORT=80
    # pod02是有的,再来看看test01
    root@pod03:/# env |grep -i test01
    TEST01_SERVICE_PORT=80
    TEST01_PORT_80_TCP_PROTO=tcp
    TEST01_PORT_80_TCP_ADDR=10.98.54.158
    TEST01_PORT=tcp://10.98.54.158:80
    TEST01_PORT_80_TCP=tcp://10.98.54.158:80
    TEST01_SERVICE_HOST=10.98.54.158
    TEST01_PORT_80_TCP_PORT=80

    我们可以发现,确实跟我们说的一样,他会pod创建之前就存在的svc全都注册到环境变量里面
    那么通过这一特性,我们可以在给pod传参的时候就不用写IP地址了,直接写上变量,这种方式的场景是什么呢?
    是这样的,虽然我们现在有浮动IP了,那万一这个svc被删除了又被重新创建出来了呢,浮动IP是不是变动了,那么就可以使用这个方式

    copy
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    # 我直接拿wordpress的一段代码过来给你们对比一下
    # 之前的方式
    containers:
    - image: wordpress
    imagePullPolicy: IfNotPresent
    name: wordpress
    resources: {}
    volumeMounts:
    - name: web
    mountPath: /var/www/html
    env:
    - name: WORDPRESS_DB_HOST
    value: "10.110.98.28"

    变量的方式

    copy
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    containers:
    - image: wordpress
    imagePullPolicy: IfNotPresent
    name: wordpress
    resources: {}
    volumeMounts:
    - name: web
    mountPath: /var/www/html
    env:
    - name: WORDPRESS_DB_HOST
    value: $(TEST01_SERVICE_HOST)

    我们直接在这个地方指定他去获取环境变量,那么他自动就能拿到svc的浮动IP了,并且只要SVC的名字不变,他是能一直拿到的,当然,这个pod要重新创建

    3. 通过DNS(推荐)

    这种方式更加简单,我们使用控制器创建出来的pod,然后再创建一个pod使用busybox,我们直接使用wget + svc名字

    copy
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    # 我们先看看svc
    [root@master wordpress]# kubectl get svc
    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    test01 ClusterIP 10.98.54.158 80/TCP 65m
    # 我们使用busybox来看看
    [root@master wordpress]# kubectl run busybox --image busybox -- sleep 3600
    pod/busybox created
    # 进入pod
    [root@master wordpress]# kubectl exec -it busybox -- sh
    / #
    / # wget test01
    Connecting to test01 (10.98.54.158:80)
    saving to 'index.html'
    index.html 100% |**************************************************************| 615 0:00:00 ETA
    'index.html' saved
    / # ls
    bin etc index.html lib64 root tmp var
    dev home lib proc sys usr

    看到这里我们直接使用wget+ svc的名字他就把index.html文件下载了,说明是能访问到的
    这种方式只能方式同一命名空间下的svc,如果要哦访问不同的命令空间下的svc也很简单
    只需要在svc名字后面加上. 命名空间名字

    比如
    我现在需要访问hehe命令空间下的svc01,那么就是这样的
    wget svc01.hehe 这样就好了

    本文作者:FuShudi

    本文链接:https://www.cnblogs.com/fsdstudy/p/18015156

    版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

  • 相关阅读:
    金融行业的CFA、CPA和FRM你了解吗?中国人民大学与加拿大女王大学金融硕士需要吗?
    AUGMENTING LOGICAL REASONING CAPABILITIES WITH LARGE LANGUAGE MODELS
    自动控制原理5.2---典型环节与开环系统的频率特性
    Java第三方登录封装工具类
    Conda常用命令
    如何修改rpm包
    ROS1云课→20迷宫不惑之A*大法(一种虽古老但实用全局路径规划算法)
    前后端分离前端部署方案是什么?
    React之render
    ExecutorService、Callable、Future实现有返回结果的多线程原理解析
  • 原文地址:https://www.cnblogs.com/fsdstudy/p/18015156