在同一个pod中的容器时共享资源和网络。使用同一个网络命名空间。可以直接通信
每个pod都有一个全局的真实IP地址。同一个node节点之间的不同pod可以直接使用对方pod的IP地址进行通信。
例如:pod1和pod2时通过docker0的网桥来进行通信。
cni插件:cni在k8s中是一个标准接口,在容器运行时调用网络插件,配置容器网络。负责设置容器的网络命名空间,IP地址。路由等等一系列的参数。
flannel:这是一个插件或者说组件。是cni插件中的一个组件。
它可以让集群中不同节点的docker容器具有全集群唯一的虚拟IP地址。
在底层物理网络的基础之上,创建一个逻辑的网络层。属于二层+三层的集合。二层是物理网络而三层是逻辑上的网络层。
overlay网络也是一种网络虚拟化的技术。
默认模式,应用转发、配置简单但是性能最差。默认就是UDP
UDP:基于应用转发,flannel提供路由表,flannel封装数据包,解封装。
UDP基于应用层。走用户态
UDP模式使用的网卡是flannel.0
UDP模式的工作流程:
封装过程:
pod将数据通过 docker 0 网桥将数据转发的flannel.0网卡
node节点上都会有一个flannel的虚拟网卡负责封装和解封装。
网卡:flannel.0。封装数据包。通过自身flannel插件的路由表转发。
转发到部署在k8s上的pod。flanneld上。
每个node节点都有一个IP地址。在封装的过程中,会封装两层
第一层信息是源IP地址和目的IP地址
第二层是容器内的信息源内部容器的IP到目的内部容器的IP地址。使用的是UDP协议
数据包封装好了之后会转发到20的pod节点flannel。
解封装过程:
先到flannel.0网卡。由网卡来转发。通过docker0的网桥把数据流量转发到指定的容器内部。发送到指定的pod上。
在封装和解封装之后,信息会保存在etcd中。下次转发,可以直接请求etcd
基于内核转发,是最常用的网络类型。
一般的小集群都是用vxlan模式。
vxlan使用的overlay的虚拟隧道通信技术。二层+三层
flannel提供路由表,内核实现封装和解封装。
vxlan使用的网卡是flannel1.1网卡
vxlan模式的工作流程:
封装:
pod基于 docker 0 的网桥将数据传输至flannel.1网卡。会生成一个VTEP虚拟网络隧道。
VTEP:virul tunel endpoint 虚拟网络隧道
由网卡将发送至对方的网卡
通过VTEP来实现数据封装。
源IP地址和目的IP地址还会生成vni。类似于vlanid。这些vni对应的是内部容器的源IP和目的iIP。
这些信息也会保存到etcd中
通过隧道模式转发
解封装:
数据发送到对方的网卡。
由内核解封装数据包。并传递给flannel.1网卡,通过数据包内的目的vni地址。
依次向下传递通过 docker 0 找到指定pod内容器的IP地址。
封装过程类似于三层交换机
这里的flannel就需要负责识别对应的VNI的IP地址即可
这些信息也会保存到etcd中
总结:flannel提供VNI,在封装过程中会绑定VNI和目标IP地址进行绑定。由内核封装解封装。通过数据包内的目的vni地址。 找到指定pod内容器的IP地址。
性能最好,但是配置麻烦。
flannel将每个发向容器的数据包进行封装。vxlan通过vtep打包数据。由内核封装成数据包。转发到目的node节点。到了目标节点,还有个解封装的过程。再发送目标pod,性能是有一定影响的。
在 node01 节点上操作
上传 cni-plugins-linux-amd64-v0.8.6.tgz 和 flannel.tar 到 /opt 目录中
在主节点上传入flannel的yml文件
cd /opt/
docker load -i flannel.tar
mkdir -p /opt/cni/bin
tar zxvf cni-plugins-linux-amd64-v0.8.6.tgz -C /opt/cni/bin
#解压插件源码包放到指定的目录中。
node02节点上相同操作
在 master01 节点上操作上传入flannel的yml文件 部署 CNI 网络
cd /opt/k8s
kubectl apply -f kube-flannel.yml
#自动拉起pod节点
kubectl get pods -n kube-system
#查看是否拉起成功
kubectl get -o wide pods -n kube-system
#查看node使用的IP地址是什么
calico:采用直接路由的方式。BGP路由。不需要修改报文,统一直接通过路由表转发。路由表会很复杂。对运行维护的要求比较高。
BGP模式的特点:交换路由信息的外部网关协议,可以连接不同的node节点。这些node节点可能不是一个网段。BGP实现可靠的、最佳的、动态的路由选择。自动识别相邻的路由设备(自动识别需要手动配置)。
可靠:安全
最佳:最佳路径
动态:自动识别自动选择
calico不使用重叠网络,也不需要交换,直接通过虚拟路由实现。每一台虚拟路由都通过BGP转发到不同的节点。
felix:也是运行再主机上一个个pod,可以理解为一个个进程。在k8s中通过daemonset的方式部署pod。
daemontset会在每个node节点上以后台运行方式部署相同的pod。
负责在宿主机上插入规则。维护calico所需的网络设备。例如:管理、监听网络接口。路由转发等等。
BGP client:就是BIRD。是BGP的客户端、专门负责在集群当中分发路由规则的信息。每一个节点都会有一个BGP client。
BGP协议广播方式通知掐他节点,分发路由规则。实现网络互通
etcd:保存路由信息。负责网络元数据的一致性。
etcd保存元数据的作用就是保证整个网络状态的一致和准确。
calico插件的工作:
通过路由表维护每个pod之间的通信。
一旦创建好pod之后,会添加一个设备cali。生成veth pair设备
veth pair设备:是一对设备,虚拟的以太网设备。一头连接在容器的网络命名空间(eth0)。另一头连接宿主机的网络命名空间(cali)
IP地址分配:veth pair连接容器的部分给容器分配一个IP地址。这个IP地址是唯一标识。宿主机也会被veth pair分配一个calico网络的内部IP地址。用于和其他节点上的容器进行通信。
veth设备,容器发出的IP地址通过veth pair设备到宿主机。宿主机根据路由规则的下一跳地址发送到网关。也就是目标宿主机。
数据包到达目标宿主机,通过veth pari设备。目标宿主机也是根据路由规则。下一跳地址。转发的目标容器。
calico是路由转发,直接转发。一头连接容器,一头连接宿主机。通过bgp协议自动发现对方设备。直接通过路由规则转发。
ipip模式:会生成一个tunnel。所有的数据包封装都在tunnel内部打包。封装宿主机IP、容器内部的IP地址。
在 master01 节点上操作上传 calico.yaml 文件到 /opt/k8s 目录中,部署 CNI 网络
cd /opt/k8s
vim calico.yaml
-----3878行-----
修改里面定义 Pod 的网络(CALICO_IPV4POOL_CIDR),需与前面 kube-controller-manager 配置文件指定的 cluster-cidr 网段一样
- name: CALICO_IPV4POOL_CIDR
value: "10.244.0.0/16"
#Calico 默认使用的网段为 192.168.0.0/16
kubectl apply -f calico.yaml
#执行部署calico的yaml文件
kubectl get pods -n kube-system
#查看节点是否部署成功
#有一个总控制网络负责控制两个节点网络
kubectl get nodes
kubectl create deployment nginx1 --image=nginx:1.22 --replicas=3
#每创建一个pod就会生成一个calico网卡
ip route
#可以查看路由表
靠路由规则和路由条目转发。但是路由表数量太多,反而会影响转发效率。可以手动删除pod,它会自动清空路由表和路由条目。
flannel:配置简单。功能简单。基于overlay叠加网络实现。在物理层的网络封装一个虚拟的网络。
vxlan是虚拟三层网络。
UDP是默认模式一般不用。
flannel使用最多的就是vxlan模式。它是通过vni+ip进行转发,flannel提供路由表,由内核封装和解封装。
由于封装和解封装的过程。对数据传输的性能会有影响。同时不具备网络策略配置的能力。
host-gw配置太过于复杂。
calico:功能强大,基于路由表转发。没有封装和解封装的过程。具备网络策略和配置能力。但是路由表维护起来比较复杂。
calico有两种模式:ipip、BGP
BGP:通过为ip路由表的前缀来实现目标主机的可达性。对比ipip模式,BGP模式没有隧道。BGP模式下,pod的数据包直接通过网卡,发送到目的地。
ipip的隧道:隧道进行数据包的封装。外层是宿主机的IP----内部是容器的IP
如果是简单的小集群使用flannel即可。
如果考虑到扩容、配置网络策略建议使用calico。
我们公司集群比较小使用flannel插件使用vxlan模式,但是calico我也知道。
可以在集群当中的为service资源创建一个域名和IP进行对应解析的关系。
service是对外提供访问的地址。现在加入DNS机制之后,可以直接访问服务名。
在所有 node 节点上操作
上传 coredns.tar 到 /opt 目录
cd /opt
docker load -i coredns.tar
在 master01 节点上操作
上传 coredns.yaml 文件到 /opt/k8s 目录中,部署 CoreDNS
cd /opt/k8s
kubectl apply -f coredns.yaml
#一件拉起执行配置文件
kubectl get pods -n kube-system
kubectl run -it --rm dns-test --image=busybox:1.28.4 sh
#--rm:一旦退出容器就会被销毁
nslookup kubernetes
exit
开始master02 节点部署
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -x
#清空iptables的所有策略
master01、node01、node02关闭swap交换分区
swapoff -a
#关闭swap交换分区
#k8s在涉及时,为了提升性能,默认不使用swap交换分区,k8s在初始化的时候会自动检测swap
开始给主机改名
hostnamectl set-hostname master02
cat >> /etc/hosts << EOF
20.0.0.32 master01
20.0.0.33 master02
20.0.0.34 node01
20.0.0.35 node02
EOF
每台主机都加入映射
优化参数:
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv6.conf.all.disable_ipv6=1
net.ipv4.ip_forward=1
EOF
systemctl --system
#让配置文件生效
进行时间同步:
yum install ntpdate -y ntpdate ntp.aliyun.com
从 master01 节点上拷贝证书文件、各master组件的配置文件和服务管理文件到 master02 节点
scp -r /opt/etcd/ [email protected]:/opt/
scp -r /opt/kubernetes/ [email protected]:/opt
scp -r /root/.kube [email protected]:/root
scp /usr/lib/systemd/system/{kube-apiserver,kube-controller-manager,kube-scheduler}.service [email protected]:/usr/lib/systemd/system/
修改配置文件kube-apiserver中的IP
vim /opt/kubernetes/cfg/kube-apiserver
----修改第五行和第七行----
#改成本机的IP地址20.0.0.33
开启组件:
systemctl start kube-apiserver.service
systemctl enable kube-apiserver.service
#开启apiserver
systemctl start kube-controller-manager.service
systemctl enable kube-controller-manager.service
#开启运行管理器
systemctl start kube-scheduler.service
systemctl enable kube-scheduler.service
#开启资源调度组件
查看node节点状态:
ln -s /opt/kubernetes/bin/* /usr/local/bin/
#创建软连接让系统可以识别
kubectl get nodes
kubectl get nodes -o wide
此时node节点并没有和master02并没有真正建立通信。是etcd里存储的信息。
负载均衡部署
配置nginx的官方在线yum源,配置本地nginx的yum源
在两个nginx主机上操作36、37
cat > /etc/yum.repos.d/nginx.repo << 'EOF'
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
EOF
yum install nginx -y
修改nginx配置文件,配置四层反向代理负载均衡,指定k8s群集2台master的节点ip和6443端口
vim /etc/nginx/nginx.conf
events {
worker_connections 1024;
}
#添加
stream {
log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';
#日志记录格式
#$remote_addr: 客户端的 IP 地址。
#$upstream_addr: 上游服务器的地址。
#[$time_local]: 访问时间,使用本地时间。
#$status: HTTP 响应状态码。
#$upstream_bytes_sent: 从上游服务器发送到客户端的字节数。
access_log /var/log/nginx/k8s-access.log main;
upstream k8s-apiserver {
server 20.0.0.32:6443;
server 20.0.0.33:6443;
}
server {
listen 6443;
proxy_pass k8s-apiserver;
}
}
检查配置文件语法
nginx -t
启动nginx服务,查看已监听6443端口
systemctl start nginx
systemctl enable nginx
netstat -natp | grep nginx
部署keepalived服务
yum install keepalived -y
修改keepalived配置文件
vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
# 接收邮件地址
notification_email {
[email protected]
[email protected]
[email protected]
}
# 邮件发送地址
notification_email_from [email protected]
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id NGINX_MASTER
#lb01节点的为 NGINX_MASTER,lb02节点的为 NGINX_BACKUP
#vrrp_strict #注释掉
}
添加一个周期性执行的脚本
vrrp_script check_nginx {
script "/etc/nginx/check_nginx.sh"
#指定检查nginx存活的脚本路径
}
vrrp_instance VI_1 {
state MASTER
#lb01节点的为 MASTER,lb02节点的为 BACKUP
interface ens33
#指定网卡名称 ens33
virtual_router_id 51
#指定vrid,两个节点要一致
priority 100
#lb01节点的为 100,lb02节点的为 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
20.0.0.100/24
#指定 VIP
}
track_script {
check_nginx
#指定vrrp_script配置的脚本
}
}
创建nginx状态检查脚本
vim /etc/nginx/check_nginx.sh
#!/bin/bash
/usr/bin/curl -I http://localhost &>/dev/null
if [ $? -ne 0 ];then
#/etc/init.d/keepalived stop
systemctl stop keepalived
fi
chmod +x /etc/nginx/check_nginx.sh
启动keepalived服务(一定要先启动了nginx服务,再启动keepalived服务)
systemctl start nginx
systemctl enable nginx
systemctl start keepalived
systemctl enable keepalived
修改node节点上的bootstrap.kubeconfig,kubelet.kubeconfig配置文件为VIP:
cd /opt/kubernetes/cfg/
vim bootstrap.kubeconfig
server: https://20.0.0.100:6443
vim kubelet.kubeconfig
server: https://20.0.0.100:6443
vim kube-proxy.kubeconfig
server: https://20.0.0.100:6443
重启kubelet和kube-proxy服务:
systemctl restart kubelet.service
systemctl restart kube-proxy.service
在 lb01 上查看 nginx 和 node 、 master 节点的连接状态
netstat -natp | grep nginx
netstat -natp | grep 6443
在 master01 节点上操作:
测试创建pod
kubectl run nginx --image=nginx
查看Pod的状态信息
kubectl get pods
kubectl get pods -o wide
在对应网段的node节点上操作,可以直接使用浏览器或者curl命令访问
curl 172.17.36.2
kubectl exec -it nginx bash
这时在master01节点上查看nginx日志
kubectl logs nginx-dbddb74b8-nf9sk
相当于是仪表盘是基于Web的Kubernetes用户界面。您可以使用仪表板将容器化应用程序部署到Kubernetes集群
在 master01 节点上操作
#上传 recommended.yaml 文件到 /opt/k8s 目录中
cd /opt/k8s
vim recommended.yaml
kubectl apply -f recommended.yaml
创建service account并绑定默认cluster-admin管理员集群角色:
kubectl create serviceaccount dashboard-admin -n kube-system
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
获取token值:
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
使用输出的token登录Dashboard
https://20.0.0.34:30001
将token的值复制出来到浏览器登录即可。
实验搭建完成!
[root@k8s-master1 ~]# kubectl get cs
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-1 Healthy {"health":"true"}
etcd-0 Healthy {"health":"true"}
etcd-2 Unhealthy HTTP probe failed with statuscode: 503
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.233.91:2379,https://192.168.233.93:2379,https://192.168.233.94:2379" endpoint health --write-out=table
1.将有故障的etcd节点remove出集群:
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.233.91:2379,https://192.168.233.93:2379,https://192.168.233.94:2379" --write-out=table member list
cf4f326398a30bd2
86ec40d44e54cf0a
/opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.233.91:2379,https://192.168.233.93:2379,https://192.168.233.94:2379" member remove 故障节点的id
2、来到故障节点
rm -rf /var/lib/etcd/default.etcd/member/
修改etcd配置文件,将下面new修改为:
vim /opt/etcd/cfg/etcd
修改前:
ETCD_INITIAL_CLUSTER_STATE="new"
修改后:
ETCD_INITIAL_CLUSTER_STATE="existing"
3、重新加入etcd集群:
/opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.233.91:2379,https://192.168.233.93:2379,https://192.168.233.94:2379" member add etcd-2 --peer-urls=https://192.168.233.94:2380
4、重启etcd故障节点即可