3

SVC服务的发现 - FuShudi

 7 months ago
source link: https://www.cnblogs.com/fsdstudy/p/18015156
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

服务的发现

发现的方式

服务的发现说的就是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就会报数据库连接失败的错误
我们来看看是不是这样

# 我们创建一个控制器,副本数为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   <none>           <none>
# 我们现在看到,这个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   <none>           <none>

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

# 由于刚刚的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   <none>        80/TCP    3s
# 我们通过这个ip地址来访问一下nginx看看
[root@master ~]# curl 10.98.54.158
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
…… 省略部分信息
# 可以访问到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   <none>           <none>
# 他的pod的IP地址已经变了,我们来看看svc的地址能否继续访问到
[root@master ~]# curl 10.98.54.158
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
……省略部分信息

通过这个实验我们看到了,我们可以通过这这种方式来给这些个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还没有被创建出来
大概就是这样一个流程,我们来看看是不是这样

[root@master wordpress]# kubectl get svc
NAME     TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
test01   ClusterIP   10.98.54.158   <none>        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的变量

[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   <none>        80/TCP    10s
test01   ClusterIP   10.98.54.158     <none>        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是不是变动了,那么就可以使用这个方式

# 我直接拿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"

变量的方式

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名字

# 我们先看看svc
[root@master wordpress]# kubectl get svc
NAME     TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
test01   ClusterIP   10.98.54.158   <none>        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 这样就好了


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK