Kubernetes -Kubernetes中的Network组件

Network是Kubernetes体系中的重头戏,相比于其它组件来说也比较难,因为Kubernetes中所有的Pod或者服务之间一定是需要进行网络通信的,如果不能解决网络通信的问题,那可以说整个Kubernetes体系中的Pod是没有灵魂的。

所以必须要把Network这个组件搞清楚,那Network这个组件该从哪里开始入手呢?

首先,为了更好的了解Kubernetes中的Network组件,我们先回想下,在Docker中我们的网络是如何做的?
在Docker中,无非是划分成单机和多机,单机中Docker的网络可以由下图所示:
在这里插入图片描述

两个容器在同一个Centos中,为什么彼此能够ping通?是因为有docker0这样的网卡,我们都通过veth这样的一个pair对去匹配,这是最简单的一种场景,是容器之间的通信。

如果一个容器搬到了一个机器中,一个容器搬到了另外一个容器中,我们该如何解决呢?这就涉及到了Docker Swarm多机集群中的通信,可以使用overlay的网络实现,如下图所示:
在这里插入图片描述
如果没有overlay网络,两个container之间是不能进行通信的,那怎么样让两个container进行通信呢?
我们将整个container的信息,通过veth0这样一个跟互联网能够交互的网卡,把整个数据包通过overlay这样的网络发送给我们另外一端,另外一端接收到信息之后再去进行解包, 这样就能进行通信了。这是overlay网络帮我们做的实现,保证了两个容器在多机之间可以进行通信。

但是现在的问题是,我们讨论的并不是container,而讨论的是Pod,因为Pod是Kubernetes中最小的操作单元,所以Kubernetes的网络组件一定是从Pod开始入手。

在这里插入图片描述
我们可以先思考一个问题,在同一个pod中的两个container之间可以通信吗?答案是肯定的,因为同一个Pod中的container肯定会在同一个node上,可以参考单机Docker中container之间的通信。在Docker体系中,container之间通过docker0网卡进行通信;在Kubernetes中,当我们创建一个pod的时候,pod中一定会创建一个名字为pause container的容器,pod中所有的container都会连接到整个container中,这样就可以实现pod中container之间的通信
在这里插入图片描述

了解了同一个pod中container之间的通信之后,我们要思考的问题是同一个集群中pod之间如何通信。Pod之间的通信又可以划分为两个维度:

  1. 同一个Node中Pod之间的通信
  2. 不同Node中Pod之间的通信

我们通过一个例子展示:准备一个nginx-pod,一个busybox-pod

nginx-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80

busybox-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  containers:
  - name: busybox
    image: busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']

将两个pod运行起来,并且查看运行情况

在这里插入图片描述
发现:nginx-pod的ip为192.168.14.11,运行在work01节点;busybox-pod的ip为192.168.221.74,运行在worker02节点。

上面两个ip和我们虚拟机的IP是没有任何关系的,那这个IP是谁帮忙生成的呢?答案是网络插件帮忙生成的,比如calico等。
在这里插入图片描述
经测试发现,我们可以在任意Node上去访问Pod。

在worker02节点访问运行在01节点中的nginx
在这里插入图片描述

在worker01节点上ping busybox pod的ip
在这里插入图片描述

结论:通过网络插件(calico),集群中任意Node中的Pod之间可以彼此通信。
官网https://kubernetes.io/docs/concepts/cluster-administration/networking/#the-kubernetes-network-model

另外,Pod其实是很不稳定的,因为deployment随时会对Pod进行扩缩容,随时会有Pod被删除和创建(IP也会变化),也就意味着我们不能通过IP稳定的访问Pod内的服务,那要如何解决呢?能不能有一个固定的IP能够让我们去访问特定的Pod呢?答案是肯定的,我们可以通过service组件来控制,也就是在Pod的外面再添加一层service,我们只要访问service的IP,然后service帮忙去负载均衡到servic对应的Pod,如下图所示:
在这里插入图片描述
案例

  1. 创建whoami-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami-deployment
  labels:
    app: whoami
spec:
  replicas: 3
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
      - name: whoami
        image: jwilder/whoami
        ports:
        - containerPort: 8000
  1. 创建Pod
    在这里插入图片描述
    在这里插入图片描述
  2. 在任意一台机器都可以通过ip和port访问成功
    在这里插入图片描述
  3. 添加service
    先查看默认namespace下有哪些service
    在这里插入图片描述
    通过下面命令给whoami-deployment这个deployment创建service
kubectl expose deployment whoami-deployment

在这里插入图片描述
可以看到我们为whoami-deployment创建了一个ip为10.100.145.244的service。在任意节点通过这个ip去访问whoami,发现都可以访问成功,并且可以做负载均衡。
在这里插入图片描述
注意:这个IP只能在集群内访问,集群外访问不了。

service组件是如何实现这个功能的呢?可以通过下面命令查看service的详细信息

kubectl describe svc whoami-deployment

在这里插入图片描述
可以看到所有Pod的IP信息都在service得到endpoints中。
结论: Cluster IP类型的service的IP可以供集群内访问,并且对很多deployment进行负载均衡。

上面了解了集群内各个Node中Pod之间的通信,那么集群内和集群外面是如何通信的呢?
集群外面访问集群内Pod

方案一:NodePort类型的service

  1. 根据whoami-deployment.yaml创建Pod
    在这里插入图片描述
    此时,我们只能在集群内通过IP去访问。
  2. 创建NodePort类型的service
kubectl expose deployment whoami-deployment --type=NodePort

在这里插入图片描述
可以看到,创建了一个IP为10.104.253.245,类型为NodePort的service,并且把8000端口映射到宿主机上的30448端口。现在我们在集群外面访问30448端口:
在这里插入图片描述
这种类型的service会有一个潜在的问题,那就是端口可能会被占用,随着我们的service越来越多,宿主机的端口可能不够用,所以这种方式不建议在生产环境中使用。

方案二:Loadbalance 类型的service
这种service需要结合第三方供应商帮忙提供域名,并且有一定的约束性,所以也不常用。

方案三:Ingress 类型的网络
官网https://kubernetes.io/docs/concepts/services-networking/ingress/
通过官网可以发现,Ingress就是帮助我们访问集群内的服务的。不过在看Ingress之前,我们还是先以一个案例出发。很简单,在K8S集群中部署tomcat
浏览器想要访问这个tomcat,也就是外部要访问该tomcat,用之前的Service-NodePort的方式是可以的,比如暴露一个32008端口,只需要访问192.168.0.61:32008即可。显然,Service-NodePort的方式生产环境不推荐使用,那接下来就基于上述需求,使用Ingress实现访问tomcat的需求。

官网Ingress:https://kubernetes.io/docs/concepts/services-networking/ingress/

GitHub Ingress Nginx:https://github.com/kubernetes/ingress-nginx

Nginx Ingress Controller:<https://kubernetes.github.io/ingress-nginx/

  1. 创建tomcat-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-deployment
  labels:
    app: tomcat
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
      - name: tomcat
        image: tomcat
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
spec:
  ports:
  - port: 80   
    protocol: TCP
    targetPort: 8080
  selector:
    app: tomcat
  1. 通过yaml创建pod
    在这里插入图片描述
  2. 该Pod为Ingress Nginx Controller,要想让外界访问,可以通过Service的NodePort或者HostPort方式,这里选择HostPort,比如指定worker01运行
#确保nginx-controller运行到w1节点上
kubectl label node w1 name=ingress   

#mandatory.yaml下载地址
https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.26.2/deploy/static/mandatory.yaml
修改mandatory.yaml
    spec:
      # wait up to five minutes for the drain of connections
      terminationGracePeriodSeconds: 300
      serviceAccountName: nginx-ingress-serviceaccount
      hostNetwork: true
      nodeSelector:
        name: ingress
        kubernetes.io/os: linux
      containers:

#使用HostPort方式运行,需要增加配置
hostNetwork: true

#搜索nodeSelector,并且要确保w1节点上的80和443端口没有被占用,镜像拉取需要较长的时间,这块注意一下哦
kubectl apply -f mandatory.yaml  
kubectl get all -n ingress-nginx
  1. 创建Ingress以及定义转发规则nginx-ingress.yaml
#ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-ingress
spec:
  rules:
  - host: tomcat.demo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: tomcat-service
          servicePort: 80

kubectl apply -f nginx-ingress.yaml
kubectl get ingress
kubectl describe ingress nginx-ingress

在这里插入图片描述
5. 修改win的hosts文件,添加dns解析

192.168.0.61   tomcat.demo.com
  1. 打开浏览器,访问tomcat.demo.com

总结:如果以后想要使用Ingress网络,其实只要定义ingress,service和pod即可,前提是要保证nginx ingress controller已经配置好了。

  • 18
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无法无天过路客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值