【Kubernetes】四层代理Service

Service四层代理

  • 一、Service概念原理
    • 1.1、为什么要有Service
    • 1.2、Service概述
    • 1.3、工作原理
    • 1.4、三类IP地址
      • 【1】Node Network(节点网络)
      • 【2】Pod network(pod 网络)
      • 【3】Cluster Network(服务网络)
  • 二、Service资源创建
    • 2.1、service资源字段
    • 2.2、service的spec字段定义
    • 2.3、Service端口
    • 2.4、Service类型
      • 【1】ClusterIP类型
      • 【2】NodePort类型
      • 【3】ExternalName类型
  • 三、k8s最佳实践:映射外部服务案例分享
  • 四、Service服务发现:coredns组件详解
    • 4.1、DNS是什么?
    • 4.2、CoreDNS是什么?
    • 4.3、验证CoreDNS

一、Service概念原理

1.1、为什么要有Service

在kubernetes中,Pod是有生命周期的,如果Pod重启它的IP很有可能会发生变化。如果我们的服务都是将Pod的IP地址写死,Pod挂掉或者重启,和刚才重启的pod相关联的其他服务将会找不到它所关联的Pod.
为了解决这个问题,在kubernetes中定义了service资源对象,Service 定义了一个服务访问的入口,客户端通过这个入口即可访问服务背后的应用集群实例,service是一组Pod的逻辑集合,这一组Pod能够被Service访问到,通常是通过Label Selector实现的。
在这里插入图片描述

  1. pod ip经常变化,service是pod的代理,我们客户端访问,只需要访问service,就会把请求代理到Pod
  2. pod ip在k8s集群之外无法访问,所以需要创建service,这个service可以在k8s集群外访问的。

1.2、Service概述

  • service是一个固定接入层,客户端可以通过访问service的ip和端口访问到service关联的后端pod。
  • 这个service工作依赖于在kubernetes集群之上部署的一个附件,就是kubernetes的dns服务(不同kubernetes版本的dns默认使用的也是不一样的,1.11之前的版本使用的是kubeDNs,较新的版本使用的是coredns)
  • service的名称解析是依赖于dns附件的,因此在部署完k8s之后需要再部署dns附件,kubernetes要想给客户端提供网络功能,需要依赖第三方的网络插件(flannel,calico等)。
  • 每个K8s节点上都有一个组件叫做kube-proxy,kube-proxy这个组件将始终监视着apiserver中有关service资源的变动信息,需要跟master之上的apiserver交互,随时连接到apiserver上获取任何一个与service资源相关的资源变动状态
  • 这种是通过kubernetes中固有的一种请求方法watch(监视)来实现的,一旦有service资源的内容发生变动(如创建,删除),kube-proxy都会将它转化成当前节点之上的能够实现service资源调度,把我们请求调度到后端特定的pod资源之上的规则,这个规则可能是iptables,也可能是ipvs,取决于service的实现方式。

1.3、工作原理

k8s在创建Service时,会根据标签选择器selector(lable selector)来查找Pod,据此创建与Service同名的endpoint对象,当Pod 地址发生变化时,endpoint也会随之发生变化,service接收前端client请求的时候,就会通过endpoint,找到转发到哪个Pod进行访问的地址。(至于转发到哪个节点的Pod,由负载均衡kube-proxy决定)

1.4、三类IP地址

【1】Node Network(节点网络)

物理节点或者虚拟节点的网络,如ens33接口上的网路地址

[root@master ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:9d:0d:9f brd ff:ff:ff:ff:ff:ff
    inet 10.32.1.147/24 brd 10.32.1.255 scope global noprefixroute ens32
       valid_lft forever preferred_lft forever
    inet6 fe80::bdc4:94e0:2ba5:e504/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

【2】Pod network(pod 网络)

创建的Pod具有的IP地址

[root@master ~]# kubectl get pods -A  -o wide
NAMESPACE     NAME                                       READY   STATUS    RESTARTS      AGE   IP               NODE     NOMINATED NODE   READINESS GATES
kube-system   calico-kube-controllers-6744f6b6d5-4vnx4   1/1     Running   0             27h   10.244.196.129   node01   <none>           <none>
kube-system   calico-node-c7hdk                          1/1     Running   0             27h   10.32.1.147      master   <none>           <none>
kube-system   calico-node-v8lg8                          1/1     Running   0             27h   10.32.1.148      node01   <none>           <none>
kube-system   calico-node-w8tkz                          1/1     Running   0             27h   10.32.1.149      node02   <none>           <none>

Node Network和Pod network这两种网络地址是我们实实在在配置的,其中节点网络地址是配置在节点接口之上,而pod网络地址是配置在pod资源之上的,因此这些地址都是配置在某些设备之上的,这些设备可能是硬件,也可能是软件模拟的

【3】Cluster Network(服务网络)

集群地址,也称为service network

这个地址是虚拟的地址(virtual ip),没有配置在某个接口上,只是出现在service的规则当中。

[root@master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   28h

二、Service资源创建

2.1、service资源字段

[root@master1 ~]# kubectl explain service
KIND:     Service
VERSION:  v1
DESCRIPTION:
     Service is a named abstraction of software service (for example, mysql)
     consisting of local port (for example 3306) that the proxy listens on, and
     the selector that determines which pods will answer requests sent through
     the proxy.
FIELDS:
   apiVersion	<string>   # service资源使用的api组
   kind	<string>           # 创建的资源类型
   metadata	<Object>       # 定义元数据
   spec	<Object>     

2.2、service的spec字段定义

[root@xianchaomaster1 ~]# kubectl explain service.spec
KIND:     Service
VERSION:  v1
RESOURCE: spec <Object>
DESCRIPTION:
     Spec defines the behavior of a service.
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
     ServiceSpec describes the attributes that a user creates on a service.
FIELDS:
   allocateLoadBalancerNodePorts	<boolean>
   clusterIP	<string>   # 动态分配的地址,也可以自己在创建的时候指定,创建之后就改不了了
   clusterIPs	<[]string> 
   externalIPs	<[]string>
   externalName	<string>
   externalTrafficPolicy	<string>
   healthCheckNodePort	<integer>
   ipFamilies	<[]string>
   ipFamilyPolicy	<string>
   loadBalancerIP	<string>
   loadBalancerSourceRanges	<[]string>
   ports	<[]Object>  # 定义service端口,用来和后端pod建立联系
   publishNotReadyAddresses	<boolean>
   selector	<map[string]string> # 通过标签选择器选择关联的pod有哪些
   sessionAffinity	<string>
   sessionAffinityConfig	<Object>
# service在实现负载均衡的时候还支持sessionAffinity?
# sessionAffinity什么意思?
# 会话联系,默认是none,随机调度的(基于iptables规则调度的);如果我们定义sessionAffinity的client ip,那就表示把来自同一客户端的IP请求调度到同一个pod上
   topologyKeys	<[]string>
   type	<string>  #定义service的类型

2.3、Service端口

kubectl explain service.spec.ports 可以查看端口相关内容

nodePort : service在物理机映射的端口,默认在 30000-32767 之间
port: service的端口,这个是k8s集群内部服务可访问的端口
targetPort: targetPort是pod上的端口,从port和nodePort上来的流量,经过kube-proxy流入到后端pod的targetPort上,最后进入容器。

2.4、Service类型

kubectl explain service.spec.type可以查看service有那几种类型

【1】ClusterIP类型

[root@master 9]# cat pod_test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80  #pod中的容器需要暴露的端口
        startupProbe:
           periodSeconds: 5
           initialDelaySeconds: 60
           timeoutSeconds: 10
           httpGet:
             scheme: HTTP
             port: 80
             path: /
        livenessProbe:
           periodSeconds: 5
           initialDelaySeconds: 60
           timeoutSeconds: 10
           httpGet:
             scheme: HTTP
             port: 80
             path: /
        readinessProbe:
           periodSeconds: 5
           initialDelaySeconds: 60
           timeoutSeconds: 10
           httpGet:
             scheme: HTTP
             port: 80
             path: /
# 更新资源清单文件
[root@master 9]# kubectl apply -f pod_test.yaml
# 查看pod ip
[root@master 9]# kubectl get pods -l run=my-nginx -o wide
NAME                       READY   STATUS    RESTARTS   AGE     IP               NODE     NOMINATED NODE   READINESS GATES
my-nginx-fc8c7b6c4-7j6hx   1/1     Running   0          2m12s   10.244.196.136   node01   <none>           <none>
my-nginx-fc8c7b6c4-h7xg6   1/1     Running   0          2m12s   10.244.140.79    node02   <none>           <none>
# curl <ip> 可以访问对应的pod

以上pod如果被删除,就会重新生成pod,pod ip也会变化,所以需要在pod前端加一个固定接入层。接下来创建Service:

# 查看pod标签
[root@master ~]# kubectl get pods --show-labels
NAME                       READY   STATUS    RESTARTS   AGE     LABELS
my-nginx-fc8c7b6c4-7j6hx   1/1     Running   0          4h53m   pod-template-hash=fc8c7b6c4,run=my-nginx
my-nginx-fc8c7b6c4-h7xg6   1/1     Running   0          4h53m   pod-template-hash=fc8c7b6c4,run=my-nginx
# 创建Service
[root@master 9]# cat service_test.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  type: ClusterIP
  ports:
  - port: 80   #service的端口,暴露给k8s集群内部服务访问
    protocol: TCP
    targetPort: 80    #pod容器中定义的端口
  selector:
    run: my-nginx  #选择拥有run=my-nginx标签的pod

上述yaml文件将创建一个 Service,具有标签run=my-nginx的Pod,目标TCP端口 80,并且在一个抽象的Service端口(targetPort:容器接收流量的端口;port:抽象的 Service 端口,可以使任何其它 Pod访问该 Service 的端口)上暴露。

[root@master 9]# kubectl apply -f service_test.yaml
service/my-nginx created
[root@master 9]# kubectl get svc -l run=my-nginx
NAME       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
my-nginx   ClusterIP   10.102.168.76   <none>        80/TCP    10s
# 在k8s控制节点访问service的ip:端口就可以把请求代理到后端pod
[root@master 9]# curl 10.102.168.76:80

通过上面可以看到请求service IP:port跟直接访问pod ip:port看到的结果一样,这就说明service可以把请求代理到它所关联的后端pod
注意:上面的10.102.168.76:80地址只能是在k8s集群内部可以访问,在外部无法访问,比方说我们想要通过浏览器访问,那么是访问不通的,如果想要在k8s集群之外访问,是需要把service type类型改成nodePort的。

[root@master ~]# kubectl describe svc my-nginx
Name:              my-nginx
Namespace:         default
Labels:            run=my-nginx
Annotations:       <none>
Selector:          run=my-nginx
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.102.168.76
IPs:               10.102.168.76
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.140.79:80,10.244.196.136:80
Session Affinity:  None
Events:            <none>
[root@master ~]#  kubectl get ep my-nginx
NAME       ENDPOINTS                            AGE
my-nginx   10.244.140.79:80,10.244.196.136:80   22m

service可以对外提供统一固定的ip地址,并将请求重定向至集群中的pod。其中“将请求重定向至集群中的pod”就是通过endpoint与selector协同工作实现。
selector是用于选择pod,由selector选择出来的pod的ip地址和端口号,将会被记录在endpoint中。endpoint便记录了所有pod的ip地址和端口号。当一个请求访问到service的ip地址时,就会从endpoint中选择出一个ip地址和端口号,然后将请求重定向至pod中。具体把请求代理到哪个pod,需要的就是kube-proxy的轮询实现的。service不会直接到pod,service是直接到endpoint资源,就是地址加端口,再由endpoint再关联到pod。

service只要创建完成,我们就可以直接解析它的服务名,每一个服务创建完成后都会在集群dns中动态添加一个资源记录,添加完成后我们就可以解析了,资源记录格式是:

SVC_NAME.NS_NAME.DOMAIN.LTD.
服务名.命名空间.域名后缀
集群默认的域名后缀是svc.cluster.local.
就像我们上面创建的my-nginx这个服务,它的完整名称解析就是

my-nginx.default.svc.cluster.local

[root@master ~]# kubectl exec -it my-nginx-fc8c7b6c4-7j6hx /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@my-nginx-fc8c7b6c4-7j6hx:/# curl my-nginx.default.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

【2】NodePort类型

[root@master 9]# cat pod_nodeport.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx-nodeport
spec:
  selector:
    matchLabels:
      run: my-nginx-nodeport
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx-nodeport
    spec:
      containers:
      - name: my-nginx-nodeport-container
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
[root@master 9]# kubectl apply -f pod_nodeport.yaml
deployment.apps/my-nginx-nodeport created
[root@master 9]#  kubectl get pods -l run=my-nginx-nodeport -owide
NAME                                 READY   STATUS    RESTARTS   AGE   IP               NODE     NOMINATED NODE   READINESS GATES
my-nginx-nodeport-7776f84758-5nxmb   1/1     Running   0          22s   10.244.196.137   node01   <none>           <none>
my-nginx-nodeport-7776f84758-qlr5z   1/1     Running   0          22s   10.244.140.80    node02   <none>           <none>

[root@master 9]# cat service_nodeport.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-nginx-nodeport
  labels:
    run: my-nginx-nodeport
spec:
  type: NodePort
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30380
  selector:
    run: my-nginx-nodeport
[root@master 9]#  kubectl apply -f service_nodeport.yaml
service/my-nginx-nodeport created
[root@master 9]# kubectl get svc -l run=my-nginx-nodeport
NAME                TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
my-nginx-nodeport   NodePort   10.107.198.159   <none>        80:30380/TCP   6s
[root@master 9]# curl 10.107.198.159
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
......

注意: 10.107.198.159是k8s集群内部的service ip地址,只能在k8s集群内部访问,在集群外无法访问。
在集群外访问servicecurl 10.107.198.159:30380

数据转发流程:

客户端请求http://10.32.1.147:30380 ->docker0虚拟网卡:172.17.0.1:30380 ->10.244.140.80:80,10.244.196.137:80

[root@master 9]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.17.0.1:30380 rr  # 172.17.0.1是docker0 网卡地址
  -> 10.244.140.80:80     # pod1 ip        Masq    1      0          0
  -> 10.244.196.137:80    # pod2 ip        Masq    1      0          0
TCP  10.32.1.147:30380 rr
  -> 10.244.140.80:80             Masq    1      0          0
  -> 10.244.196.137:80            Masq    1      0          0
......

【3】ExternalName类型

应用场景:跨名称空间访问
需求:default名称空间下的client 服务想要访问nginx-ns名称空间下的nginx-svc服务
步骤:

1、创建名为nginx的pod (指定命名空间nginx-ns )

# 在线拉取镜像(node节点上要操作)
[root@node01 ~]# ctr images pull docker.io/library/busybox:latest
[root@node01 ~]# ctr image ls|grep busy
docker.io/library/busybox:latest                     application/vnd.docker.distribution.manifest.list.v2+json sha256:1ceb872bcc68a8fcd34c97952658b58086affdcb604c90c1dee2735bde5edc2f 2.1 MiB  linux/386,linux/amd64,linux/arm/v5,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/mips64le,linux/ppc64le,linux/riscv64,linux/s390x -
You have new mail in /var/spool/mail/root

[root@master 9]# kubectl create ns nginx-ns
namespace/nginx-ns created
[root@master 9]# cat server_nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: nginx-ns
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
   metadata:
    labels:
      app: nginx
   spec:
     containers:
     - name: nginx
       image: nginx
       imagePullPolicy: IfNotPresent
[root@master 9]# kubectl apply -f server_nginx.yaml
deployment.apps/nginx created
[root@master 9]# kubectl get pods -n nginx-ns
NAME                     READY   STATUS    RESTARTS   AGE
nginx-6fb6c59b65-56sxx   1/1     Running   0          4s

2、创建名为nginx-svc的svc(指定命名空间nginx-ns )

# 创建名为nginx-svc的svc
[root@master 9]# cat nginx_svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  namespace: nginx-ns
spec:
  selector:
    app: nginx
  ports:
   - name: http
     protocol: TCP
     port: 80
     targetPort: 80
[root@master 9]# kubectl apply -f nginx_svc.yaml
service/nginx-svc created
[root@master 9]# kubectl get svc -n nginx-ns
NAME        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
nginx-svc   ClusterIP   10.104.157.106   <none>        80/TCP    24s

3、创建名为client的pod

[root@master 9]# cat client.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: busybox
  template:
   metadata:
    labels:
      app: busybox
   spec:
     containers:
     - name: busybox
       image: busybox
       imagePullPolicy: IfNotPresent
       command: ["/bin/sh","-c","sleep 36000"]
[root@master 9]# kubectl apply -f client.yaml

4、创建名为client-svc的svc

# 创建名为client-svc的svc
[root@master 9]# cat client_svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: client-svc
spec:
  type: ExternalName
  # 这里使用到了nginx-svc 的软链,让使用者感觉就好像调用自己命名空间的服务一样。
  externalName: nginx-svc.nginx-ns.svc.cluster.local
  ports:
  - name: http
    port: 80
    targetPort: 80
[root@master 9]# kubectl apply -f client_svc.yaml
service/client-svc created
[root@master 9]# kubectl get svc
NAME                TYPE           CLUSTER-IP       EXTERNAL-IP                            PORT(S)        AGE
client-svc          ExternalName   <none>           nginx-svc.nginx-ns.svc.cluster.local   80/TCP         5h4m
kubernetes          ClusterIP      10.96.0.1        <none>                                 443/TCP        2d5h
my-nginx            ClusterIP      10.102.168.76    <none>                                 80/TCP         18h
my-nginx-nodeport   NodePort       10.107.198.159   <none>                                 80:30380/TCP   17h

5、登录client pod

[root@master 9]# kubectl exec -it client-568955849b-vglmj /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ #
/ # wget -q -O - client-svc.default.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
......
/ # wget -q -O - nginx-svc.nginx-ns.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
......
# 上面两个请求的结果一样

三、k8s最佳实践:映射外部服务案例分享

k8s集群引用外部的mysql数据库

在node02节点上安装mysql数据库

[root@node02 ~]# yum install mariadb-server.x86_64 -y
[root@node02 ~]# systemctl start mariadb
[root@master 9]# cat mysql_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:   # 这里没有标签选择器,是不会关联到任何pod的
  type: ClusterIP
  ports:
  - port: 3306
[root@master 9]# kubectl apply -f mysql_service.yaml
service/mysql created
[root@master 9]# kubectl get svc | grep mysql
mysql               ClusterIP      10.104.34.181    <none>                                 3306/TCP       6s
[root@master 9]# kubectl describe svc mysql 
Name:              mysql
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          <none>
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.104.34.181
IPs:               10.104.34.181
Port:              <unset>  3306/TCP
TargetPort:        3306/TCP
Endpoints:         <none> # 没有endpoint
Session Affinity:  None
Events:            <none>

接下来,我想做的是,创建endpoint,通过访问maysql的域名或ip能代理node2节点上的mysql

# 创建endpoint资源
[root@master 9]# cat mysql_endpoint.yaml
apiVersion: v1
kind: Endpoints
metadata:
  name: mysql  # 名字必须和要关联的svc名字一致
subsets: # subsets是一个对象列表,所有后面的子内容要加 -
- addresses:
  - ip: 10.32.1.149
  ports:
  - port: 3306
[root@master 9]# kubectl apply -f mysql_endpoint.yaml
endpoints/mysql created
[root@master 9]# kubectl get ep
NAME                ENDPOINTS                            AGE
kubernetes          10.32.1.147:6443                     4d1h
my-nginx            10.244.140.79:80,10.244.196.136:80   2d14h
my-nginx-nodeport   10.244.140.80:80,10.244.196.137:80   2d13h
mysql               10.32.1.149:3306                     43h
[root@master 9]# kubectl describe svc mysql
Name:              mysql
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          <none>
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.104.34.181
IPs:               10.104.34.181
Port:              <unset>  3306/TCP
TargetPort:        3306/TCP
Endpoints:         10.32.1.149:3306 # 这个就是定义的外部数据库
Session Affinity:  None
Events:            <none>

上面配置就是将外部IP地址和服务引入到k8s集群内部,由service作为一个代理来达到能够访问外部服务的目的。

四、Service服务发现:coredns组件详解

4.1、DNS是什么?

DNS全称是Domain Name System:域名系统,是整个互联网的电话簿,它能够将可被人理解的域名翻译成可被机器理解IP地址,使得互联网的使用者不再需要直接接触很难阅读和理解的IP地址。

域名系统在现在的互联网中非常重要,因为服务器的 IP 地址可能会经常变动,如果没有了 DNS,那么可能 IP 地址一旦发生了更改,当前服务器的客户端就没有办法连接到目标的服务器了,如果我们为 IP 地址提供一个『别名』并在其发生变动时修改别名和 IP 地址的关系,那么我们就可以保证集群对外提供的服务能够相对稳定地被其他客户端访问。

DNS 其实就是一个分布式的树状命名系统,它就像一个去中心化的分布式数据库,存储着从域名到 IP 地址的映射。

4.2、CoreDNS是什么?

CoreDNS 其实就是一个 DNS 服务,而 DNS 作为一种常见的服务发现手段,所以很多开源项目以及工程师都会使用 CoreDNS 为集群提供服务发现的功能,Kubernetes 就在集群中使用 CoreDNS 解决服务发现的问题。 作为一个加入 CNCF(Cloud Native Computing Foundation)的服务, CoreDNS 的实现非常简单。

4.3、验证CoreDNS

Service完整的名称组成:
<servicename>.<namespace>.svc.cluster.local
那么k8s集群内部的服务就可以通过FQDN访问

[root@master 9]# kubectl get svc
NAME                TYPE           CLUSTER-IP       EXTERNAL-IP                            PORT(S)        AGE
client-svc          ExternalName   <none>           nginx-svc.nginx-ns.svc.cluster.local   80/TCP         2d1h
kubernetes          ClusterIP      10.96.0.1        <none>                                 443/TCP        4d2h
my-nginx            ClusterIP      10.102.168.76    <none>                                 80/TCP         2d14h
my-nginx-nodeport   NodePort       10.107.198.159   <none>                                 80:30380/TCP   2d14h
mysql               ClusterIP      10.104.34.181    <none>  
# 比如这里的client
# 完整的FQDN     : client-svc.default.svc.class.local

【1】导入镜像,运行pod

# 把dig.tar.gz上传到xianchaonode2和xianchaonode1机器上,手动解压:
[root@node01 ~]# ctr -n=k8s.io images import  dig.tar.gz
[root@node02 ~]# ctr -n=k8s.io images import  dig.tar.gz
[root@master 9]# cat dig.yaml
apiVersion: v1
kind: Pod
metadata:
  name: dig
  namespace: default
spec:
  containers:
  - name: dig
    image:  xianchao/dig:latest  # 这个镜像其实就提供了一个命令
    imagePullPolicy: IfnotPresent
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
  restartPolicy: Always
[root@master 9]# kubectl apply -f dig.yaml

【2】dns解析

# 查看默认名称空间的kubernetes服务
[root@master 9]#  kubectl get svc | grep kubernetes
kubernetes          ClusterIP      10.96.0.1        <none>                                 443/TCP        4d2h
# 查看默认名称空间的client服务
[root@master 9]#  kubectl get svc | grep client
client-svc          ExternalName   <none>           nginx-svc.nginx-ns.svc.cluster.local   80/TCP         2d2h

# 解析dns,如有以下返回说明dns安装成功
[root@master 9]# kubectl exec -it dig -- nslookup kubernetes
Server:         10.96.0.10      # kube-dns这个svc的ip
Address:        10.96.0.10#53   # 说明用的是对应cordns的pod进行域名解析

Name:   kubernetes.default.svc.cluster.local  # 域名
Address: 10.96.0.1                            # ip

[root@master 9]# kubectl exec -it dig -- nslookup client-svc
Server:         10.96.0.10
Address:        10.96.0.10#53

client-svc.default.svc.cluster.local    canonical name = nginx-svc.nginx-ns.svc.cluster.local.
Name:   nginx-svc.nginx-ns.svc.cluster.local  # 域名
Address: 10.104.157.106                       # ip

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/242169.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode 139.单词拆分

OJ链接 &#xff1a;139.单词拆分 代码&#xff1a; class Solution {public boolean wordBreak(String s, List<String> wordDict) {Set<String> set new HashSet<String>(wordDict);int n s.length();boolean[] dp new boolean[n1];dp[0] true;//初始…

现代雷达车载应用——第2章 汽车雷达系统原理 2.5节 检测基础

经典著作&#xff0c;值得一读&#xff0c;英文原版下载链接【免费】ModernRadarforAutomotiveApplications资源-CSDN文库。 2.5 检测基础 对于要测试目标是否存在的雷达测量&#xff0c;可以假定下列两个假设之一为真&#xff1a; •H0:—测量结果仅为噪声。 •H1:—测量是噪…

leaflet使用热力图报L找不到的问题ReferenceError: L is not defined at leaflet-heat.js:11:3

1.在main.js中直接引入会显示找不到L 2.解决办法 直接在组件中单独引入使用 可以直接显示出来。 至于为什么main中不能引入为全局&#xff0c;我是没找到&#xff0c;我的另外一个项目可以&#xff0c;新项目不行&#xff0c;不知哪里设置的问题

LangChain 25: SQL Agent通过自然语言查询数据库sqlite

LangChain系列文章 LangChain 实现给动物取名字&#xff0c;LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄LangChain 4用向量数据库Faiss存储&#xff0c;读取YouTube的视频文本搜索I…

多模态AI:技术深掘与应用实景解析

多模态AI&#xff1a;技术深掘与应用实景解析 在当今人工智能技术的快速发展中&#xff0c;多模态AI凭借其独特的数据处理能力&#xff0c;成为了科技创新的前沿。这项技术结合了视觉、听觉、文本等多种感知模式&#xff0c;开辟了人工智能处理和理解复杂信息的新纪元。本文旨…

NOIP2017提高组day2 - T2:宝藏

题目链接 [NOIP2017 提高组] 宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图&#xff0c;藏宝图上标出了 n n n 个深埋在地下的宝藏屋&#xff0c; 也给出了这 n n n 个宝藏屋之间可供开发的 m m m 条道路和它们的长度。 小明决心亲自前往挖掘所有宝藏屋中的宝藏。但…

HarmonyOS开发入门HelloWorld及工具安装

下载与安装DevEco Studio 在HarmonyOS应用开发学习之前&#xff0c;需要进行一些准备工作&#xff0c;首先需要完成开发工具DevEco Studio的下载与安装以及环境配置。 进入DevEco Studio下载官网&#xff0c;单击“立即下载”进入下载页面。 DevEco Studio提供了Windows版本和…

DeCap DECODING CLIP LATENTS FOR ZERO-SHOT CAPTIONING VIA TEXT-ONLY TRAINING

DeCap: DECODING CLIP LATENTS FOR ZERO-SHOT CAPTIONING VIA TEXT-ONLY TRAINING 论文&#xff1a;https://arxiv.org/abs/2303.03032 代码&#xff1a;https://github.com/dhg-wei/DeCap OpenReview&#xff1a;https://openreview.net/forum?idLt8bMlhiwx2 TL; DR&#xff…

新版Spring Security6.2案例 - Basic HTTP Authentication

前言&#xff1a; 书接上文&#xff0c;翻译官网Authentication的Username/Password这页&#xff0c;接下来继续翻译basic的这页&#xff0c;因为官网说的都是原理性的&#xff0c;这边一个小案例关于basic http authentication。 Basic Authentication 本节介绍 HTTP 基本身…

项目总结-自主HTTP实现

终于是写完了&#xff0c;花费了2周时间&#xff0c;一点一点看&#xff0c;还没有扩展&#xff0c;但是基本功能是已经实现了。利用的是Tcp为网络链接&#xff0c;在其上面又写了http的壳。没有使用epoll&#xff0c;多路转接难度比较高&#xff0c;以后有机会再写&#xff0c…

【程序人生】还记得当初自己为什么选择计算机?

✏️ 初识计算机&#xff1a; 还记得人生中第一次接触计算机编程是在高中&#xff0c;第一门编程语言是Python&#xff08;很可惜由于条件限制的原因&#xff0c;当时没能坚持学下去......现在想来有点后悔&#xff0c;没能坚持&#xff0c;唉......&#xff09;。但是&#xf…

快速上手linux | 一文秒懂Linux各种常用目录命令(上)

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 一 、命令提示符和命令的基本格式1.1 如何查看主机名称及修改 二、命令基本格式2.1 命令格式示例2.2 参数的作用…

电商类app如何进行软件测试?有必要进行第三方软件测试吗?

电商类app在开发过程中&#xff0c;软件测试是一个非常重要的环节。通过软件测试&#xff0c;可以确保app在发布和使用过程中的稳定性和安全性。那么&#xff0c;电商类app究竟如何进行软件测试?是否有必要进行第三方软件测试? 一、电商类app如何进行软件测试?   1. 内部…

【Linux】多线程编程

目录 1. 线程基础知识 2. 线程创建 3. 线程ID&#xff08;TID&#xff09; 4. 线程终止 5. 线程取消 6. 线程等待 7. 线程分离 8. 线程互斥 8.1 初始化互斥量 8.2 销毁互斥量 8.3 互斥量加锁和解锁 9. 可重入和线程安全 10. 线程同步之条件变量 10.1 初始化条件变…

Collecting Application Engine Performance Data 收集应用程序引擎性能数据

You can collect performance data of any specific SQL action of an Application Engine program to address any performance issue. 您可以收集应用程序引擎程序的任何特定SQL操作的性能数据&#xff0c;以解决任何性能问题。 You can collect performance data of the S…

IDEA中工具条中的debug按钮不能用了显示灰色

IDEA中工具条中的debug按钮不能用了显示灰色 1. 问题描述 IDEA上的DEBUG按钮突然变成了灰色&#xff1a; 2. 解决办法 一通搜索&#xff0c;终于找到解决办法 点击 File -> Project Structure如下图操作 3. 重启&#xff0c;解决 4. 参考 https://www.cnblogs.com…

【代码随想录】刷题笔记Day35

前言 日常学习&#xff0c;抵触心理5%&#xff1b;毫无指示的干活&#xff0c;抵触心理95% 122. 买卖股票的最佳时机 II - 力扣&#xff08;LeetCode&#xff09; 把整体利润拆分为每次利润&#xff0c;只要积上涨的就可以&#xff0c;so easy class Solution { public:int …

C++共享和保护——(2)生存期

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 生命如同寓言&#xff0c;其价值不在于…

lv12 uboot概述即SD卡制作

1 开发板启动过程 BL0环境初始化一下 查看拨码开关 BL0把SD卡里的内容复制到内存里面运行&#xff0c;因为直接在SD&#xff08;uboot&#xff09;里是无法运行的&#xff0c;属于外设。 uboot开始运行&#xff0c;初始化软硬件环境 把外存里的rootf、dtb、linux搬到内存&a…

xtu oj 1194 Recipient

题目描述 快递小哥每天都辛苦的送快递&#xff0c;今天他需要送N份快递给N个收件人&#xff0c;第i份快递需要送给第i个收件人。 请问其中发生恰好K个送错了的情况数是多少&#xff1f; 输入 存在多样例。 每行输入两个整数N和K&#xff0c;1≤N≤1000,0≤K≤N。 如果两个都…