K8s 网络刨析

首先考虑四个问题
思考:pod内部的容器是如何通信的?
思考:同一个节点中的pod是如何通信的?
思考:不同节点中的pod是如何通信的?
思考:pod如何对外网提供服务?

1.容器到容器(pod内部)的通信

同一个Pod内的容器(Pod内的容器是不会跨宿主机的)共享同一个网络命名空间,共享同一个Linux协议栈。所以对于网络的各类操作,就和它们在同一台机器上一样,它们甚至可以用localhost地址访问彼此的端口。
例如 如果容器2运行的是MySQL,那么容器1使用 localhost:3306就能直接访问这个运行在容器2上的MySQL了。

2.Pod之间的通信

每一个Pod都有一个真实的全局IP地址,同一个Node内的不同 Pod之间可以直接采用对方Pod的IP地址通信 。
Pod容器既有可能在同一个Node上运行,也有可能在不同的Node 上运行,所以通信也分为两类:同一个Node内Pod之间的通信和不同Node内Pod之间的通信。

2.1 同一个Node内Pod之间的通信

对于在同一台机器上的两个Pod来说,都是连接到同一个docker0网桥上,它们的IP地址IP1、IP2都是从docker0网段上动态获取的,它们和网桥本身的IP3是同一个网段的,Pod1和Pod2处于同一局域网内,它们之间可以通过docker0作为路由进行通信。
image.png
对于web app1访问web app2,他们都是连接到docker0上面的,它们是同一个网段的,web app1和web app2处于同一局域网内,它们之间可以通过docker0作为路由进行通信。

2.2 不同 Node上Pod之间的通信

image.png

image.png
那么一个网络报文请求是怎么从一个容器发送到另外一个容器的呢?例如从master1上的Container1容器(IP:10.244.0.13)访问node1上面Container2容器(IP:10.244.1.14)容器。

  • Container1容器10.244.0.13直接访问目标容器Container2的IP 10.244.1.14,请求默认通过容器内部的eth0网卡发送出去。
  • 请求报文通过Veth pair(虚拟设备对)被发送到Docker宿主机VethXXX设备上。
  • 然后查找Docker宿主机的路由表信息,同时外部容器IP的报文都会转发到Flannel0虚拟网卡,这是一个P2P的虚拟网卡,然后报文就被转发到监听在另一端的Flanneld进程。
  • 因为Flannel在Etcd中存储着子网和宿主机ip的对应关系,所以能够找到10.244.1.14对应的宿主机IP为11.101.1.3,进而开始组装UDP数据包发送数据到目的主机。
  • 这个请求得以完成的原因每个节点上都启动着一个Flanneld udp进程,都监听着8285端口,所以master1通过Flanneld进程把数据包通过宿主机的Interface网卡发送给node1的Flanneld进程的相应端口即可。
  • 请求报文到达node1之后,继续往上传输,到传输层,交给监听在8285端口的Flanneld程序处理。
  • 请求数据被解包,然后发送给Flannel0虚拟网卡。
  • 查找路由表,发现对应容器的报文要交给Docker0
  • Docker0找到连到自己的容器,把报文发送给Container2,反之同样的工作方式。

3.pod如何对外网提供服务

3.1 通过端口映射的方式直接实现pod和外界资源的联系

这种方法就是在创建容器的时候将端口进行一个映射
在访问的时候直接访问宿主机IP+端口就行

3.2 通过service访问pod

每个 Pod 都有自己的 IP 地址。当 controller 用新 Pod 替代发生故障的 Pod 时,新 Pod 会分配到新的 IP 地址。这样就产生了一个问题:
如果一组 Pod 对外提供服务(比如 HTTP),它们的 IP 很有可能发生变化,那么客户端如何找到并访问这个服务呢?Kubernetes 给出的解决方案是 Service

3.2.1 NodePort

原理是Kubernetes会在每一个Node上暴露出一个端口:nodePort,外部网络可以通过(任一Node)[NodeIP]:[NodePort]访问到后端的Service。

[root@master1 ~]# kubectl get service
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE

nginx        NodePort    10.10.127.106   <none>        88:31958/TCP   2m47s

访问192.168.1.81:31958
image.png

3.2.2 LoadBalance

将服务的类型设置成LoadBalance, NodePort类型的一 种扩展,这使得服务可以通过一个专用的负载均衡器来访问, 这是由Kubernetes中正在运行的云基础设施提供的。 负载均衡器将流量重定向到跨所有节点的节点端口。客户端通过负载均衡器的 IP 连接到服务。

3.2.3 ingress

创建一个Ingress资源, 这是一个完全不同的机制, 通过一 个IP地址公开多个服务,就是一个网关入口
下面详细介绍ingress-traefik

4.Traefik 概念

由于微服务架构以及 Docker 技术和 kubernetes 编排工具最近几年才开始逐渐流行,所以一开始的反向代理服务器比如Nginx、Apache 并未提供其支持,毕竟他们也不是先知,所以才会出现 Ingress Controller 这种东西来做 kubernetes 和前端负载均衡器如 Nginx之间做衔接。

Traefik是一款开源的反向代理与负载均衡工具。它最大的优点是能够与常见的微服务系统直接整合,可以实现自动化动态配置。

Traefik 天生就是提供了对 kubernetes 的支持,也就是说 Traefik本身就能跟 kubernetes API 交互,感知后端变化,因此可以得知: 在使用 traefik 时,Ingress Controller 已经没有用

4.1 Traefik布置

4.1.1 Traefik rbac验证配置

---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: traefik-ingress-controller
rules:
  - apiGroups:
      - ""
    resources:
      - services
      - endpoints
      - secrets
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
    - extensions
    resources:
    - ingresses/status
    verbs:
    - update
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: traefik-ingress-controller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
  name: traefik-ingress-controller
  namespace: kube-system

[root@master1 Traefik]# kubectl apply -f rbac.yaml 
clusterrolebinding.rbac.authorization.k8s.io/traefik-ingress-controller created

4.2 创建traefik

traefik-deployment.yaml

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: traefik-ingress-controller
  namespace: kube-system
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: traefik-ingress-controller
  namespace: kube-system
  labels:
    k8s-app: traefik-ingress-lb
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: traefik-ingress-lb
  template:
    metadata:
      labels:
        k8s-app: traefik-ingress-lb
        name: traefik-ingress-lb
    spec:
      serviceAccountName: traefik-ingress-controller
      terminationGracePeriodSeconds: 60
      containers:
      - image: traefik:v1.7
        name: traefik-ingress-lb
        ports:
        - name: http
          containerPort: 80
        - name: admin
          containerPort: 8080
        args:
        - --api
        - --kubernetes
        - --logLevel=INFO
---
kind: Service
apiVersion: v1
metadata:
  name: traefik-ingress-service
  namespace: kube-system
spec:
  type: NodePort
  selector:
    k8s-app: traefik-ingress-lb
  ports:
    - protocol: TCP
      port: 80
      name: web
      targetPort: 80
    - protocol: TCP
      port: 8080
      name: admin

[root@master1 Traefik]# kubectl apply -f traefik-deployment.yaml 
serviceaccount/traefik-ingress-controller created
deployment.apps/traefik-ingress-controller created
service/traefik-ingress-service created
[root@master1 Traefik]# 

[root@master1 Traefik]# kubectl get pods --namespace=kube-system|grep tra
traefik-ingress-controller-6b7f594d46-6q68w   1/1     Running   0          93s
[root@master1 Traefik]# 
[root@master1 Traefik]# kubectl get service --namespace=kube-system
NAME                      TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)                       AGE
traefik-ingress-service   NodePort    10.10.55.63   <none>        80:62629/TCP,8080:11046/TCP   2m
[root@master1 Traefik]# 

[root@master1 Traefik]# kubectl get svc --namespace=kube-system
NAME                      TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)                       AGE
kube-dns                  ClusterIP   10.10.0.10    <none>        53/UDP,53/TCP,9153/TCP        27h
traefik-ingress-service   NodePort    10.10.55.63   <none>        80:62629/TCP,8080:11046/TCP   6m9s
[root@master1 Traefik]# 

4.3 部署 Ingress规则

实现域名对应Service名称

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: v1-net 
spec:
  rules:
    - host: v1.net 
      http:
        paths:
        - path: /
          backend:
            serviceName: v1-net 
            servicePort: 80
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: v2-net 
spec:
  rules:
    - host: v2.net 
      http:
        paths:
        - path: /
          backend:
            serviceName: v2-net 
            servicePort: 80

[root@master1 Traefik]# kubectl apply -f traefik-ingress.yaml 
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.extensions/v1-net created
ingress.extensions/v2-net created
[root@master1 Traefik]# 

5.创建pod容器并配置service

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: v1-net
  name: v1-net
spec:
  replicas: 1
  selector:
    matchLabels:
      app: v1-net
  template:
    metadata:
      labels:
        app: v1-net
    spec:
      containers:
      - image: nginx:alpine
        name: nginx
---
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: v1-net
  name: v1-net
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: v1-net
status:
  loadBalancer: {}

[root@master1 yaml]# kubectl get pods 
NAME                          READY   STATUS    RESTARTS   AGE
ngx-795b46448d-d49mg          1/1     Running   0          20h
v1-net-89cffdd7-x97kl   1/1     Running   0          10m
[root@master1 yaml]# 

6.查看traefik-ingress-service 的端口映射

[root@master1 yaml]# kubectl get svc --namespace=kube-system
NAME                      TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)                       AGE
kube-dns                  ClusterIP   10.10.0.10    <none>        53/UDP,53/TCP,9153/TCP        28h
traefik-ingress-service   NodePort    10.10.55.63   <none>        80:62629/TCP,8080:11046/TCP   44m
[root@master1 yaml]# 

7.域名的绑定


192.168.199.120 v1.net  v2.net

实现了在客户端的访问 但是必须访问的是映射后的端口

8.修改端口

查看如上Service,Nodeport端口为62629,即访问虚拟主机需要带上该端口,如何将其端口修改为80端口呢。
vim /etc/kubernetes/manifests/kube-apiserver.yaml
在 command下添加 如下代码即可;

  • –service-node-port-range=1-65535
    重启apiserver服务即可:
    docker ps |grep apiserver |awk ‘{print $1}’|xargs docker restart
    image.png
 kubectl edit svc  traefik-ingress-service  --namespace=kube-system

image.png
image.png

猜你喜欢

转载自blog.csdn.net/xiaolong1155/article/details/130188518