Kuebernetes网络管理(flannel、calico)

引言

  • 一个数据中心基本上都有成百上干个容器,这么多的容器需要运维人员集中管理

  • 在云计算的世界中,计算最基础,存储最重要,网络最复杂

  • Kubernetes集群的网络依赖于第三方网络插件来实现

一、Kuebernetes网络管理

1.1 Kuebernetes网络模型

  • 设计原则

    1.每个Pod都拥有一个独立的IP地址

    2.假定所有Pod都在一个可以直接连通的、扁平的网络空间中

  • Kubernetes对集群网络的要求

    1.所有的容器都可以在不用NAT的方式下同别的容器通讯

    2.所有节点都可在不用NAT的方式下同所有容器通讯

    3.容器的地址和别人看到的地址是同一个地址

1.2 Docker网络基础

技术 作用
网络命名空间 将独立的网络协议栈割刀不同的命名空间中,处于不同命名空间的网络栈是完全隔离的,彼此之间无法通信
Veth设备对 实现不同网络命名空间的通信,可以直接将两个网络命名空间连接起来,Veth设备都是成对出现的
网桥 是一个二层网络设备,通过网桥可以将Linux支持的若干个网络端口“连接”起来,使得网络接口之间的报文能够相互转发
Iptables/Netfilter Netfilter负责在内核中执行各种挂接的规则,运行在内核模式中;Iptables是在用户模式下运行的进程,负责协助维护内核中Netfilter的各种规则表,通过二者的配合实现整个Linux网络协议栈中的灵活的数据包处理机制
路由 Linux系统包含一个完整的路由功能,当Ip层在处理数据发送或转发的时候,会使用路由表来决定发往的目的地

1.3 Kubernetes网络通信

  • Pod 内容器与容器之间的通信

在同一个 Pod 内的容器(Pod 内的容器是不会跨宿主机的)共享同一个网络命令空间, 所以对于网络的各类操作,就和它们在同一台机器上一样,甚至可以用 localhost 地址访问

  • Pod 与 Pod 之间的通信

  1. 同一个 Node 内 Pod 之间的通信

每个 Pod 都有一个真实的全局 IP 地址,同一个 Node 内的不同 Pod 之间可以直接采用对方 Pod 的 IP 地址进行通信,不需要采用其他发现机制。

  1. 不同 Node 上 Pod 之间的通信

Pod 地址与 docker0 在同一网段,docker0 网段与宿主机网卡是两个不同的网段,且不同 Node 之间的通信只能通过宿主机的物理网卡进行。要想实现不同 Node 上 Pod 之间的通信,就必须想办法通过主机的这个 IP 地址进行寻址和通信。因此不同 Node 中 Pod 间通信要满足两个条件: Pod 的 IP 不能冲突;将 Pod 的 IP 和所在的 Node 的 IP 关联起来,通过这个关联让 Pod 可以互相访问。

  • Pod 与 Service 之间的通信

Service 是一个抽象的实体,Kubernetes 在创建 Service 时,会为其分配一个虚拟 IP 地址

当外界需要访问 Pod 里的容器提供的功能时,不直接访问 Pod 的 IP 地址和端口,而是访问 Service 的虚拟 IP 地址和端口由 Service 把请求转发给它背后的 Pod。Kubernetes 在创建 Service 时,根据 Service 的标签选择器(Label Selector)来查找 Pod,据此创建与Service 同名的 EndPoints 对象。当 Pod 的地址发生变化时,EndPoints 也随之变化。Service接受到请求时,就能通过 EndPoints 找到对应的 Pod。Service 的虚拟 IP 就是由 kube-proxy 实现的

kube-proxy 有两种请求转发模式:userspace 模式和 iptables 模式。

  • 集群外部与内部组件之间的通信

类型 通信实现
ClusterIP 类型 这种类型的 Service 只会得到虚拟的IP 和端口,只能在 Kubernetes集群内部被访问,此模型是为默认类型
NodePort 类型 这种类型的 Service 除了会得到虚拟的 IP 和端口,Kubernetes 还 会 在 所 有 Node 节 点 上 为 其 分 配 端 口 。 分 配 的 端 口 的 值 可 以 通 过spec.ports[*].nodePort 指定,或由 Kubernetes 在配置好的区间里分配(默认为30000-32767)。这种 Service 即可以从 Kubernetes 集群通过虚拟 IP:端口访问, 也可以从集群外部通过 Node 节点的 IP:nodePort 访问
LoadBalancer 类型 这种类型的 Service 除了会得到虚拟的IP 和端口,Kubernetes还会在所有 Node 节点上为其分配端口,然后为其开通负载均衡。这种 Service 即可以从 Kubernetes 集群通过虚拟 IP:端口访问,也可以从集群外部通过 Node 节点的 IP:nodePort 访问,还可以通过负载均衡的 IP 访问

1.4 K8S 网络插件

  • K8S 网络的实现不是集群内部自己实现,而是依赖于第三方网络插件----CNI(Container Network Interface),例如 Flannel、Calico 等。下面分别介绍这两种网络插件。

1.4.1 Flannel网络插件

  • flannel概述

    • Flannel 是 CoreOS 团队针对 Kubernetes 设计的一个网络规划服务

    • 目的是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址

    • 是一种 ”覆盖网络(overlay network)“

    • 目前支持UDP、VXLAN、AWS VPC和GCE路由等数据转发方式

    • 节点间默认的数据通信方式是UDP转发

1.4.2 Calico网络插件

  • Calico概述

Calico 是一种基于 BGP 的、纯三层的、容器间互通的网络方案。与 OpenStack、Kubenetes、AWS、GCE 等云平台都能够良好的集成。在虚拟化平台中,如 OpenStack、Docker 等都需要实现 workloads 之间互连,但同时也需要对容器做隔离控制,就像在Internet 中的服务仅开放 80 端口、公有云的多租户一样,提供隔离和管控机制。

  • Calico网络模型工作组件

工作组件 作用
Felix Calico Agent,运行在每个Node上,负责为容器设置Ip地址、路由规则、IP tables规则等网络资源,保证跨主机容器网络互通
etcd Calico使用的后端存储
BGP Client(BIRD) 负责把Felix在各Node上设置的路由信息通过BGP协议广播到Calico网络
BGP Route Reflector 通过一个或多个BGP Route Reflector来完成大规模集群的分级路由分发
CalicoCtl Calico 命令行管理工具
IPIP 相当于一个基于 IP 层的网桥.一般来说,普通的网桥是基于 mac 层的, 根本不需 IP,而这个 ipip 则是通过两端的路由做一个 tunnel,把两个本来不通的网络通过点对点连接起来
BGP 边界网关协议(Border Gateway Protocol, BGP)是互联网上一个核心的去中心化自治路由协议。它通过维护 IP 路由表或‘前缀’表来实现自治系统(AS)之间的可达性,属于矢量路由协议。BGP,通俗的讲就是讲接入到机房的多条线路(如电信、联通、移动等)融合为一体,实现多线单 IP。 BGP 机房的优点:服务器只需要设置一个 IP 地址,最佳访问路由是由网络上的骨干路由器根据路由跳数与其它技术指标来确定的,不会占用服务器的任何系统。
  • IPIP 和 BDP 是Calico网络之间的两种网络

  • Calico网络架构

Kuebernetes网络管理(flannel、calico)_第1张图片

 

二、部署k8s Calico网络插件,实现服务间的通信

资源列表

操作系统 配置 主机名/IP
Centos 7.9 2G2C master/172.16.10.10
Centos 7.9 2G2C node01/172.16.10.11
Centos 7.9 2G2C node02/172.16.10.12

2.1 实验环境

  • k8s集群所有节点都执行

2.1.1 修改主机名

 hostnamectl set-hostname master
 hostnamectl set-hostname node01
 hostnamectl set-hostname node02

2.1.2 关闭防火墙

 systemctl stop firewalld
 systemctl disable firewalld

2.1.3 关闭selinux安全机制

 sed -i "s/.*SELINUX=.\*/SELINUX=disabled/g" /etc/selinux/config
 # 重启系统
 reboot

2.1.4 关闭swap交换分区

 # 关闭swap分区
 swapoff -a
 # 关闭开启自启
 vim /etc/fstab 
 ##swap分区前加上注释“#”
 #/dev/mapper/cl-swap     swap     swap    defaults     0  0  

2.1.5 修改内核机制

 # 修改内核机制
 vim /etc/sysctl.d/k8s.conf
 net.bridge.bridge-nf-call-ip6tables = 1
 net.bridge.bridge-nf-call-iptables = 1
 # 刷新
 sysctl --system

2.1.6 添加hosts映射

 vim /etc/hosts
 172.16.10.10 master
 172.16.10.11 node01
 172.16.10.12 node02

2.1.7 安装及配置docker-ce-18.09.9

 # 安装并启动docker
 yum -y install wget
 wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
 yum -y install docker-ce-18.09.9-3.el7
 # 启动docker,并设置docker开机自启
 systemctl start docker
 systemctl enable docker
 ​
 # 添加docker加速器及驱动
 cat > /etc/docker/daemon.json < 
  

2.1.8 配置k8s yum源

 # 配置k8s yum源
 cat > /etc/yum.repos.d/kubernetes.repo << EOF
 [kubernetes]
 name=Kubernetes
 baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
 enabled=1
 gpgcheck=0
 repo_gpgcheck=0
 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
 EOF

2.2 部署k8s集群

2.2.1 安装k8s-1.18.0版本

# 这里指定了k8s-1.18.0版本号,若需要其他版本的可自行更改(集群所有节点执行)
yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0
# 设置开启自启
systemctl enable kubelet
# 初始化k8s(仅master节点执行)
kubeadm init \
 --apiserver-advertise-address=172.16.10.10 \
 --image-repository registry.aliyuncs.com/google_containers \
 --kubernetes-version v1.18.0 \
 --service-cidr=10.1.0.0/16 \
 --pod-network-cidr=10.244.0.0/16
##执行后会报以下信息 
 Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:
## 使用K8S的话,必行执行以下3条命令
  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:
##节点加入集群要执行下面的命令
kubeadm join 172.16.10.10:6443 --token sw1lqg.guily84o5q87lmv8 \
    --discovery-token-ca-cert-hash sha256:6315a98f2ab7e63a1780ccecaa94227e9b16bc91d9e32f812fd65b694a3a82b3 

2.2.2 安装calico网络插件

# 上传calico 配置文件 calico-3.13.1.yaml
# 应用calico 网络插件
kubectl apply -f calico-3.13.1.yaml
# 实时监控pod 状态
watch kubectl get pod -A
##当所有容器为running 状态时表示所有容器正常运行

2.3 部署nginx服务,并可以访问

# 创建命名空间
kubectl create ns policy-demo

# 查看命名空间
kubectl get ns

# 应用加载nginx yaml文件,创建生成容器
kubectl apply -f nginx-deployment.yaml

# 查看pod
kubectl get pod -n policy-demo

# 创建service ,暴露服务
kubectl expose -n policy-demo deployment nginx --port=80

# 查看service
kubectl get svc -n policy-demo

# 查看deployment
kubectl get deployment -n policy-demo
kubectl get deploy -n policy-demo

# 使用kubectl run 创建busybox容器,并访问nginx
kubectl run -n policy-demo access -it --rm --image busybox /bin/sh
/ # wget -q nginx -O -

2.4 kubectl 集群管理相关操作

# 创建命名空间
kubectl create ns policy-demo

# 查看命名空间
kubectl get ns

# 删除命名空间
kubectl delete ns policy-demo

# 应用加载nginx yaml文件,创建生成容器
kubectl apply -f nginx-deployment.yaml
# 删除已加载的yaml文件
kubectl delete -f nginx-deployment.yaml

# 查看pod
kubectl get pod -n policy-demo
# 查看pod标签
kubectl get pod -n policy-demo --show-labels

# 查看deployment
kubectl get deployment -n policy-demo
kubectl get deploy -n policy-demo
# 查看某个deployment 的详细信息
kubectl describe deploy nginx -n policy-demo

# 创建service ,暴露服务
kubectl expose -n policy-demo deployment nginx --port=80

# 查看service
kubectl get svc

# 使用kubectl run 创建busybox容器,并访问nginx
kubectl run -n policy-demo access -it --rm --image busybox /bin/sh
/ # wget -q nginx -O -

2.5 kubectl 服务网络策略

# kubectl 服务网络策略
kubectl create -f - < 
 

你可能感兴趣的:(k8s,docker,运维,linux,k8s)