连接上文
notready是因为没有网络,因此无法创建pod
k8s的CNI网络插件模式
在同一个pod中的容器共享资源和网络,使用同一个网络命名空间。
每个pod都有一个全局的真实IP地址,同一个node之间的不同pod可以直接使用对方pod的ip地址进行通信。
pod1和pod2是通过docker0的网桥来进行通信。
Pod 地址与 docker0 在同一网段,docker0 网段与宿主机网卡是两个不同的网段,且不同 Node 之间的通信只能通过宿主机的物理网卡进行。
要想实现不同 Node 上 Pod 之间的通信,就必须想办法通过主机的物理网卡 IP 地址进行寻址和通信。因此要满足两个条件:Pod 的 IP 不能冲突;将 Pod 的 IP 和所在的 Node 的 IP 关联起来,通过这个关联让不同 Node 上 Pod 之间直接通过内网 IP 地址通信。
cni插件
cni是一个标准接口,用于容器运行时调用网络插件,配置容器网络,复制设置容器的网络命名空间,IP地址,路由等参数
功能就是让集群之中不同节点的docker容器具有全集群唯一的虚拟IP地址。
在底层物理网络的基础之上,创建一个逻辑的网络层。二层+三层的集合 二层是物理网络,三层是逻辑上的网络层
overlay网络也是一种网络虚拟化的技术。
flannel支持的数据转发方式:
默认模式,应用转发,配置简单,但是性能最差。
基于应用层,用户态
工作流程图:
基于内核转发,也是最常用的网络类型(小集群都是用这个)
Calico网络插件
flannel:每个发向容器的数据包进行封装,vxlan通过vtep打包数据,由内核封装数据包----》再转发到目标node节点。还有一个解封装的过程。再发送到目标pod。性能是有一定影响的。
Calico:采用直接路由的方式。BGP路由。不需要修改报文,同意直接通过路由表转发,路由表会相当复杂,运行维护的要求比较高。
BGP模式的特点:交换路由信息的外部网关协议,可以连接不同的节点。node节点可能不是一个网段,BGP实现可靠的,最佳的,动态的路由选择。自动识别相邻的路由设备
calico 不使用 overlay,也不需要交换,直接通过虚拟路由实现,每一台虚拟路由都通过BGP转发。
核心组件:
felix:也是运行在主机上的一个个pod,一个进程,k8s daemonset的方式部署pod.
daemont set 会在每个节点部署相同的Pod,后台的运行方式。
负责宿主机上插入路由规则,维护calico需要的网络设备。网络接口管理,监听,路由等等。
BGP Client:bird BGP的客户端,专门负责在集群中分发路由规则的信息。每一个节点都会有一个BGP Client。
BGP协议广播方式通知其他节点的,分发路由的规则。实现网络互通。
etcd:保存路由信息,负责网络元数据的一致性。保证网络状态的一致和准确。
路由表来维护每个pod之间的通信。
创建好pod之后,添加一个设备cali veth pair设备。
虚拟网卡: veth pair是一对设备,虚拟的以太网设备。
一头连接在容器的网络命名空间
另一头连接宿主机的网络命名空间 cali
ip地址分配: veth pair连接容器的部分给容器分配一个IP地址,这个IP地址是唯一标识,宿主机也会被veth pair分配一个calico网络的内部IP地址。和其他节点上的容器进行通信。
veth设备:容器发出的IP通过veth pair设备到宿主机,宿主机根据路由规则的下一跳地址,发送到网关(目标宿主机)。数据包到达目标宿主机,veth pair设备,目标宿主机也是根据路由规则,下一跳地址,转发到目标容器。
ipip模式:会生成一个tunnel,数据包都在tunnel内部打包。封装:宿主机ip 容器内部的IP
常用的有flannel和calico
flannel的特点:配置简单,功能简单,基于overlay叠加网络实现,在物理层的网络层上再封装一个网络层
vxlan:是虚拟三层网络。最多的模式。vni+ip进行转发,flannel提供路由表,内核来封装和解封装。
host-gw():
由于封装和解封装的过程,对数据传输的性能会有影响。没有网络策略配置的能力。
udp:是默认模式
calico:功能强大,基于路由表进行转发,没有封装和解封装的过程。具备网络策略的配置能力。但是路由表维护起来复杂。
模式:ipip BGP
BGP:通过为ip路由表的前缀来实现目标主机的可达性。对比ipip模式,BGP模式没有隧道,BGP模式下,POD的数据包直接通过网卡发送到目的地。
ipip的隧道:隧道进行数据包的封装 ipv4----ipv4.
简单的小集群:flannel
扩容,配置网络策略:calico
部署coreDNS
//在所有 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
NAME READY STA
TUS RESTARTS AGE
coredns-5ffbfd976d-j6shb 1/1 Running 0 32s
#DNS 解析测试
kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous
kubectl run -it --rm dns-test --image=busybox:1.28.4 sh
If you don't see a command prompt, try pressing enter.
/ # nslookup kubernetes
Server: 10.0.0.2
Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local
Name: kubernetes
Address 1: 10.0.0.1 kubernetes.default.svc.cluster.local
exit
---------- master02 节点部署 ----------
//从 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
KUBE_APISERVER_OPTS="--logtostderr=true \
--v=4 \
--etcd-servers=https://192.168.233.91:2379,https://192.168.233.93:2379,https://192.168.233.94:2379 \
--bind-address=192.168.233.92 \ #修改
--secure-port=6443 \
--advertise-address=192.168.233.92 \ #修改
......
//在 master02 节点上启动各服务并设置开机自启
systemctl start kube-apiserver.service
systemctl enable kube-apiserver.service
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 #-o=wide:输出额外信息;对于Pod,将输出Pod所在的Node名
//此时在master02节点查到的node节点状态仅是从etcd查询到的信息,
而此时node节点实际上并未与master02节点建立通信连接,因此需要使用一个VIP把node节点与master节点都关联起来
部署flannel
//在 node01 节点上操作
#上传 cni-plugins-linux-amd64-v0.8.6.tgz 和 flannel.tar 到 /opt 目录中
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
//在 master01 节点上操作
#上传 kube-flannel.yml 文件到 /opt/k8s 目录中,部署 CNI 网络
cd /opt/k8s
kubectl apply -f kube-flannel.yml
kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-hjtc7 1/1 Running 0 7s
kubectl get nodes
NAME STATUS ROLES AGE VERSION
192.168.80.11 Ready 81m v1.20.11
部署负载均衡
---------- master02 节点部署 ----------
//从 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
KUBE_APISERVER_OPTS="--logtostderr=true \
--v=4 \
--etcd-servers=https://192.168.233.91:2379,https://192.168.233.93:2379,https://192.168.233.94:2379 \
--bind-address=192.168.233.92 \ #修改
--secure-port=6443 \
--advertise-address=192.168.233.92 \ #修改
......
//在 master02 节点上启动各服务并设置开机自启
systemctl start kube-apiserver.service
systemctl enable kube-apiserver.service
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 #-o=wide:输出额外信息;对于Pod,将输出Pod所在的Node名
//此时在master02节点查到的node节点状态仅是从etcd查询到的信息,
而此时node节点实际上并未与master02节点建立通信连接,因此需要使用一个VIP把node节点与master节点都关联起来
------------------------------ 负载均衡部署 ------------------------------
//配置load balancer集群双机热备负载均衡(nginx实现负载均衡,keepalived实现双机热备)
##### 在lb01、lb02节点上操作 #####
//配置nginx的官方在线yum源,配置本地nginx的yum源
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.61:6443;
server 20.0.0.62:6443;
}
server {
listen 6443;
proxy_pass k8s-apiserver;
}
}
http {
......
//检查配置文件语法
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 {
192.168.233.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 keepalived
systemctl enable keepalived
ip a #查看VIP是否生成
//修改node节点上的bootstrap.kubeconfig,kubelet.kubeconfig配置文件为VIP
cd /opt/kubernetes/cfg/
vim bootstrap.kubeconfig
server: https://192.168.233.100:6443
vim kubelet.kubeconfig
server: https://192.168.233.100:6443
vim kube-proxy.kubeconfig
server: https://192.168.233.100:6443
//重启kubelet和kube-proxy服务
systemctl restart kubelet.service
systemctl restart kube-proxy.service
//在 lb01 上查看 nginx 和 node 、 master 节点的连接状态
netstat -natp | grep nginx
tcp 0 0 0.0.0.0:6443 0.0.0.0:* LISTEN 44904/nginx: master
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 44904/nginx: master
tcp 0 0 192.168.80.100:6443 192.168.80.12:46954 ESTABLISHED 44905/nginx: worker
tcp 0 0 192.168.80.14:45074 192.168.80.10:6443 ESTABLISHED 44905/nginx: worker
tcp 0 0 192.168.80.14:53308 192.168.80.20:6443 ESTABLISHED 44905/nginx: worker
tcp 0 0 192.168.80.14:53316 192.168.80.20:6443 ESTABLISHED 44905/nginx: worker
tcp 0 0 192.168.80.100:6443 192.168.80.11:48784 ESTABLISHED 44905/nginx: worker
tcp 0 0 192.168.80.14:45070 192.168.80.10:6443 ESTABLISHED 44905/nginx: worker
tcp 0 0 192.168.80.100:6443 192.168.80.11:48794 ESTABLISHED 44905/nginx: worker
tcp 0 0 192.168.80.100:6443 192.168.80.12:46968 ESTABLISHED 44905/nginx: worker
##### 在 master01 节点上操作 #####
//测试创建pod
kubectl run nginx --image=nginx
//查看Pod的状态信息
kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-dbddb74b8-nf9sk 0/1 ContainerCreating 0 33s #正在创建中
kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-dbddb74b8-nf9sk 1/1 Running 0 80s #创建完成,运行中
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
nginx-dbddb74b8-26r9l 1/1 Running 0 10m 172.17.36.2 192.168.80.15
//READY为1/1,表示这个Pod中有1个容器
//在对应网段的node节点上操作,可以直接使用浏览器或者curl命令访问
curl 172.17.36.2
kubectl exec -it nginx bash
//这时在master01节点上查看nginx日志
kubectl logs nginx-dbddb74b8-nf9sk
------------------------------ 部署 Dashboard ------------------------------
//在 master01 节点上操作
#上传 recommended.yaml 文件到 /opt/k8s 目录中
cd /opt/k8s
vim recommended.yaml
#默认Dashboard只能集群内部访问,修改Service为NodePort类型,暴露到外部:
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
ports:
- port: 443
targetPort: 8443
nodePort: 30001 #添加
type: NodePort #添加
selector:
k8s-app: kubernetes-dashboard
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.63:30001