首页 > 其他分享 >k8s网络-service

k8s网络-service

时间:2023-10-22 17:57:51浏览次数:35  
标签:Service service 访问 网络 nginx Pod k8s pod

k8s网络

Kubernetes本身并不负责网络通信,Kubernetes提供了容器网络接口CNI(Container Network Interface),具体的网络通信交给CNI插件来负责,开源的CNI插件非常多,像Flannel、Calico。

Kubernetes虽然不负责网络,但要求集群中的Pod能够互相通信,且Pod必须通过非NAT网络连接,即收到的数据包的源IP就是发送数据包Pod的IP。

同时Pod与节点之间的通信也是通过非NAT网络。

但是Pod访问集群外部时源IP会被修改成节点的IP。

Pod内部是通过虚拟Ethernet接口对(Veth pair)与Pod外部连接

Veth pair就像一根网线,一端留在Pod内部,一端在Pod之外。

而同一个节点上的Pod通过网桥(Linux Bridge)通信,如下图所示。

1.同一个node节点下的Pod通信

POD(veth) > CNI(网桥) > ens33
# 同一个节点下创建2个pod
apiVersion: v1
kind: Pod
metadata:
  name: my-nginx-2

spec:
  nodeName: k8s-node-12
  containers:
  - image: nginx:alpine
    name: container-2

image

不同节点间的网桥连接有很多种方式,这跟具体实现相关。

但集群要求Pod的地址唯一,所以跨节点的网桥通常使用不同的地址段,以防止Pod的IP地址重复。

2.跨node节点POD通信原理

# 跨节点准备好pod
apiVersion: v1
kind: Pod
metadata:
  name: my-nginx-13

spec:
  nodeName: k8s-node-11
  containers:
  - image: nginx:alpine
    name: container-3

跨节点pod通信情况

image

跨节点pod通信原理图

image

一、Service

Pod创建完成后,如何访问Pod呢?直接访问Pod会有如下几个问题:

Pod会随时被Deployment这样的控制器删除重建,那访问Pod的结果就会变得不可预知。(ip动态)
Pod的IP地址是在Pod启动后才被分配,在启动前并不知道Pod的IP地址。
应用往往都是由多个运行相同镜像的一组Pod组成,逐个访问Pod也变得不现实。(负载均衡入口)
举个例子,假设有这样一个应用程序,使用Deployment创建了前台和后台,前台会调用后台做一些计算处理

后台运行了3个Pod,这些Pod是相互独立且可被替换的,当Pod出现状况被重建时,新建的Pod的IP地址是新IP,前台的Pod无法直接感知。

1.Service解决Pod访问问题

Kubernetes中的Service对象就是用来解决上述Pod访问问题的。

Service有一个固定IP地址,Service将访问它的流量转发给Pod,具体转发给哪些Pod通过Label来选择,而且Service可以给这些Pod做负载均衡。

那么对于上面的例子,为后台添加一个Service,通过Service来访问Pod,这样前台Pod就无需感知后台Pod的变化。

image

2.创建Service资源

Service类型

https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/

[root@k8s-master-10 ~]#kubectl explain Service.spec.type

Service的类型除了ClusterIP还有NodePort、LoadBalancer和None,这几种类型的Service有着不同的用途。

  • ClusterIP:用于在集群内部互相访问的场景,通过ClusterIP访问Service。
  • NodePort:用于从集群外部访问的场景,通过节点上的端口访问Service,详细介绍请参见NodePort类型的Service
  • LoadBalancer:用于从集群外部访问的场景,其实是NodePort的扩展,通过一个特定的LoadBalancer访问Service,这个LoadBalancer将请求转发到节点的NodePort,而外部只需要访问LoadBalancer,详细介绍请参见LoadBalancer类型的Service
  • None:用于Pod间的互相发现,这种类型的Service又叫Headless Service,详细介绍请参见Headless Service

创建ClusterIP

创建一个名为“nginx”的Service,通过selector选择到标签“app:nginx”的Pod,目标Pod的端口为80,Service对外暴露的端口为8080。

访问服务只需要通过“服务名称:对外暴露的端口”接口,对应本例即“nginx:8080”。

这样,在其他Pod中,只需要通过“nginx:8080”就可以访问到“nginx”关联的Pod。
apiVersion: v1
kind: Service
metadata:
  name: nginx        # Service的名称
  namespace: test
spec:
  selector:          # Label Selector,选择包含app=nginx标签的Pod
    app: nginx
  ports:
  - name: service0
    targetPort: 80   # Pod的端口
    port: 80         # Service对外暴露的端口,也就是ClusterIP的port
    protocol: TCP    # 转发协议类型,支持TCP和UDP
  type: ClusterIP    # Service的类型

查看svc

[root@k8s-master-10 ~]#kubectl create -f svc-nginx.yml 
service/nginx created


[root@k8s-master-10 ~]#kubectl -n yuchaoit get svc -owide
NAME    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
nginx   ClusterIP   10.1.15.2    <none>        80/TCP    5s    app=nginx

可以看到Service有个Cluster IP,这个IP是固定不变的,除非Service被删除,所以也可以使用ClusterIP在集群内部访问Service。

此时ClusterIP也只是集群内的IP,只能在集群内访问到后端Pod。

图解Service和pod关系

下面创建一个Pod并进入容器,使用ClusterIP访问Pod,可以看到能直接返回内容。

[root@k8s-master-10 ~]#kubectl -n test run -it --image nginx:alpine test-pod --rm /bin/sh

image

3.服务发现原理

1.k8s内置DNS插件CoreDNS,实现在k8s集群中以DNS服务提供名称解析
2.CoreDNS为每一个pod提供Service的名称解析服务
- 可以查看每一个pod的dns解析文件,查看nameserver,其实就是CoreDNS自己的ClusterIp
- 是因为安装了CoreDNS集群后,在kubelet配置文件里,默认添加了参数
[root@k8s-master-10 ~]#cat /var/lib/kubelet/config.yaml 
clusterDNS:
- 10.1.0.10
clusterDomain: cluster.local

因此每一个pod在被创建时,默认使用该DNS服务器。

在每一个pod中都可以基于如下规则,访问Service

servicename.default.svc.cluster.local
servicename.namespace
servicename

使用ServiceName访问Service

k8s集群内默认提供了DNS解析插件coredns

在kube-system命名空间下可以查看到CoreDNS的Pod。

[root@k8s-master-10 ~]#kubectl get po -n kube-system --show-labels  -l k8s-app=kube-dns
NAME                       READY   STATUS    RESTARTS   AGE    LABELS
coredns-6d56c8448f-g6m9z   1/1     Running   1          7d6h   k8s-app=kube-dns,pod-template-hash=6d56c8448f
coredns-6d56c8448f-ws7rb   1/1     Running   1          7d6h   k8s-app=kube-dns,pod-template-hash=6d56c8448f
CoreDNS安装成功后会成为DNS服务器,当创建Service后,CoreDNS会将Service的名称与IP记录起来,这样Pod就可以通过向CoreDNS查询Service的名称获得Service的IP地址。

访问时通过nginx.test.svc.cluster.local访问,其中nginx为Service的名称,test为命名空间名称,svc.cluster.local为域名后缀

在实际使用中,在同一个命名空间下可以省略.svc.cluster.local,直接使用ServiceName即可。

例如上面创建的名为nginx的Service,直接通过“nginx:80”就可以访问到Service,进而访问后台Pod。

使用ServiceName的方式有个主要的优点就是可以在开发应用程序时可以将ServiceName写在程序中,这样无需感知具体Service的IP地址。

下面创建一个Pod并进入容器,查询nginx域名的地址,可以发现是解析出nginx这个Service的IP地址10.1.15.2

同时访问Service的域名,可以看到能直接返回内容。

image

图中使用的dns服务器地址,是默认的kube-dns Service地址
[root@k8s-master-10 ~]#kubectl -n kube-system get svc -owide
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE    SELECTOR
kube-dns   ClusterIP   10.1.0.10    <none>        53/UDP,53/TCP,9153/TCP   7d7h   k8s-app=kube-dns

4.Service怎么找到后端pod?

试试修改deployment部署的pod副本数,可以看到,pod变化后,service自动发现了pod更新的数量,都是基于label选择器发现的pod。

[root@k8s-master-10 ~]#
[root@k8s-master-10 ~]#kubectl -n yuchaoit describe service nginx 
Name:              nginx
Namespace:         yuchaoit
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx
Type:              ClusterIP
IP:                10.1.15.2
Port:              service0  80/TCP
TargetPort:        80/TCP
Endpoints:         10.2.2.50:80,10.2.2.58:80
Session Affinity:  None
Events:            <none>

Endpoints资源

Endpoints也是一种资源,k8s通过该资源监控pod的IP,实现让Service能发现Pod,记录的就是Pod的IP。

[root@k8s-master-10 ~]#kubectl -n test get endpoints
NAME    ENDPOINTS                   AGE
nginx   10.2.2.50:80,10.2.2.58:80   59m

[root@k8s-master-10 ~]#kubectl -n test describe endpoints nginx
Name:         nginx
Namespace:    yuchaoit
Labels:       <none>
Annotations:  <none>
Subsets:
  Addresses:          10.2.2.50,10.2.2.58
  NotReadyAddresses:  <none>
  Ports:
    Name      Port  Protocol
    ----      ----  --------
    service0  80    TCP

Events:  <none>

5.Service访问原理

image

6.NodePort类型的Service

NodePort类型的Service可以让Kubemetes集群每个节点上保留一个相同的端口, 外部访问连接首先访问节点IP:Port,然后将这些连接转发给服务对应的Pod。

image

下面是一个创建NodePort类型的Service。创建完成后,可以通过节点的IP:Port访问到后台Pod。

# 集群里每一个节点都会暴露30120端口。
apiVersion: v1
kind: Service
metadata:
  name: nodeport-service
  namespace: yuchaoit
spec:
  type: NodePort
  ports:
  - port: 8080        # service的8080端口
    targetPort: 80    # 目标pod的端口
    nodePort: 30120   # 宿主机暴露的端口
    name: service1  # 若不指定,svc里显示unset
  selector:           # 标签选择器
    app: nginx

访问NodePort类型SVC

先修改pod的nginx页面,容易对比效果
[root@k8s-master-10 ~]#kubectl -n yuchaoit get po
NAME                     READY   STATUS    RESTARTS   AGE
nginx-56d58c56c7-frwxx   1/1     Running   0          104m
nginx-56d58c56c7-pndzz   1/1     Running   0          56m
[root@k8s-master-10 ~]#
[root@k8s-master-10 ~]#kubectl -n yuchaoit exec -it nginx-56d58c56c7-frwxx -- bash -c 'echo frwxx > /usr/share/nginx/html/index.html'
[root@k8s-master-10 ~]#kubectl -n yuchaoit exec -it nginx-56d58c56c7-pndzz -- bash -c 'echo pndzz > /usr/share/nginx/html/index.html'

浏览器访问任意一个节点的:30120端口即可。

image

标签:Service,service,访问,网络,nginx,Pod,k8s,pod
From: https://www.cnblogs.com/chunjeh/p/17780766.html

相关文章

  • 网络层协议
    目录网络层协议1.网络层功能2.IP数据包格式3.ICMP协议3.1为什么需要用ICMP协议?3.2ping命令3.3ping的类型和状态码3.4tracert命令3.5冲突域3.6广播域4.ARP协议4.1为什么需要用ARP协议?4.2什么是ARP协议?4.3ARP协议的工作原理网络层协议1.网络层功能最佳路径选择2.......
  • Yarn on K8S可行性调研
    1.背景一般离线Hadoop集群和在线Hadoop集群都是分开部署的,他们的计算资源互相隔离。离线集群一般0:00~08:00作业较多,集群压力大,其他时间段集群较为空闲。实时集群高峰期一般为10:00~20:00,其他时间段较为空闲。空闲时资源利用率低,是对资源的浪费,而离线/实时集群在高峰期资源紧张时......
  • 无线网络
       ......
  • 软件定义网络-OpenvSwitch
    软件定义网络(SDN)。它主要有以下三个特点:编辑控制与转发分离:转发平面就是一个个虚拟或者物理的网络设备,就像小区里面的一条条路。控制平面就是统一的控制中心,就像小区物业的监控室。它们原来是一起的,物业管理员要从监控室出来,到路上去管理设备,现在是分离的,路就是走人的,控制都在监控......
  • k8s-pod版本更新
    pod版本更新⭐️⭐️在实际应用中,升级是一个常见的场景,Deployment能够很方便的支撑应用升级。Deployment可以设置不同的升级策略,有如下两种。RollingUpdate:滚动升级,即逐步创建新Pod再删除旧Pod,为默认策略。Recreate:替换升级,即先把当前Pod删掉再重新创建Pod。Deployment的升级可......
  • 2023-10-21:用go语言,一共有三个服务A、B、C,网络延时分别为a、b、c 并且一定有:1 <= a <= b
    2023-10-21:用go语言,一共有三个服务A、B、C,网络延时分别为a、b、c并且一定有:1<=a<=b<=c<=10^9但是具体的延时数字丢失了,只有单次调用的时间一次调用不可能重复使用相同的服务,一次调用可能使用了三个服务中的某1个、某2个或者全部3个服务比如一个调用的时间,T=100100的延时......
  • ServiceA不应该直接调用ServiceB派生的Dao方法
    ServiceA不应该直接调用ServiceB派生的Dao方法背景    服务层单元测试是指针对应用程序中服务层代码的测试。服务层通常包含业务逻辑和数据处理代码,因此服务层单元测试的目标是验证这些代码的正确性和可靠性。通过编写针对服务层方法的测试用例,并模拟服务层的依赖项,我们可......
  • umich cv-4-2 经典卷积网络架构
    这节课中主要讨论了卷积神经网络的发展历史以及几种经典结构是如何构建的卷积网络经典结构AlexNetVGGGoogleNetResidualNetworkAlexNet在2012年的时候,Alexnet神经网络提出,这时网络的架构比如说各个层之间要如何排列组合,使用多少卷积层池化层,每个层又如何设置超参数其......
  • 2023-10-21:用go语言,一共有三个服务A、B、C,网络延时分别为a、b、c 并且一定有:1 <= a <= b
    2023-10-21:用go语言,一共有三个服务A、B、C,网络延时分别为a、b、c并且一定有:1<=a<=b<=c<=10^9但是具体的延时数字丢失了,只有单次调用的时间一次调用不可能重复使用相同的服务,一次调用可能使用了三个服务中的某1个、某2个或者全部3个服务比如一个调用的时间,T=100100......
  • 网络tcp与udp协议
    TCP协议TCP(transportcontrolprotocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然......