一、集群实验规划 master1: 192.168.101.11
master2: 192.168.101.12
node1: 192.168.101.21
node2: 192.168.101.22
Pod网段 :10.0.0.0/16
Service网段 :10.255.0.0/16
角色
Ip
主机名
安装的组件
Master
192.168.101.11
master1
apiserver、controller-manager、scheduler、etcd、容器运行时、keepalived、nginx
Master
192.168.101.12
master2
apiserver、controller-manager、scheduler、etcd、容器运行时、keepalived、nginx
Node
192.168.101.21
Node1
kubelet、kube-proxy、容器运行时、calico、coredns
Node
192.168.101.22
Node2
kubelet、kube-proxy、容器运行时、calico、coredn
Vip
192.168.101.100
二、初始化集群安装环境 1、修改主机名设置固定ip 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 hostnamectl set-hostname master1 nmcli con add con-name eth0-static ifname eth0 type ethernet ipv4.method manual ipv4.addresses 192.168.101.11/24 ipv4.gateway 192.168.101.2 ipv4.dns 114.114.114.114 connection.autoconnect yes nmcli con up eth0-static;nmcli con delete eth0 hostnamectl set-hostname master2 nmcli con add con-name eth0-static ifname eth0 type ethernet ipv4.method manual ipv4.addresses 192.168.101.12/24 ipv4.gateway 192.168.101.2 ipv4.dns 114.114.114.114 connection.autoconnect yes nmcli con up eth0-static;nmcli con delete eth0 hostnamectl set-hostname node1 nmcli con add con-name eth0-static ifname eth0 type ethernet ipv4.method manual ipv4.addresses 192.168.101.21/24 ipv4.gateway 192.168.101.2 ipv4.dns 114.114.114.114 connection.autoconnect yes nmcli con up eth0-static;nmcli con delete eth0 hostnamectl set-hostname node2 nmcli con add con-name eth0-static ifname eth0 type ethernet ipv4.method manual ipv4.addresses 192.168.101.22/24 ipv4.gateway 192.168.101.2 ipv4.dns 114.114.114.114 connection.autoconnect yes nmcli con up eth0-static;nmcli con delete eth0
2、配置主机host文件(在所有主机上) 1 2 3 4 5 6 7 8 cat > /etc/hosts<<END 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.101.11 master1 192.168.101.12 master2 192.168.101.21 node1 192.168.101.22 node2 END
3、配置主机间的免密登录(所有主机相同操作) 1 2 3 4 5 ssh-keygen ssh-copy-id master1 ssh-copy-id master2 ssh-copy-id node1 ssh-copy-id node2
4、关闭swap分区提升性能 Swap是交换分区,如果机器内存不够,会使用swap分区,但是swap分区的性能较低,k8s设计的时候为了能提升性能,默认是不允许使用交换分区的。Kubeadm初始化的时候会检测swap是否关闭,如果没关闭,那就初始化失败。如果不想要关闭交换分区,安装k8s的时候可以指定–ignore-preflight-errors=Swap来解决。
5、 修改主机内核参数(所有主机上) 1 2 3 4 5 6 7 8 9 10 11 modprobe br_netfilterecho 'modprobe br_netfilter' >> /etc/profile cat > /etc/sysctl.d/k8s.conf<<END net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 END sysctl -p /etc/sysctl.d/k8s.conf chmod +x /etc/rc.d/rc.local echo "sysctl -p /etc/sysctl.d/k8s.conf" >> /etc/rc.d/rc.localecho "modprobe br_netfilter" >> /etc/rc.d/rc.local
6、 关闭防火墙与selinux(所有主机上) 1 2 3 4 5 6 systemctl disable firewalld --now sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config setenforce 0 sed -i "s/^#ClientAliveInterval.*/ClientAliveInterval 600/" /etc/ssh/sshd_config sed -i "s/^#ClientAliveCountMax.*/ClientAliveCountMax 10/" /etc/ssh/sshd_config systemctl restart sshd
7、配置repo源(所有主机上) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 yum install -y yum-utils yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo cat > /etc/yum.repos.d/kubernetes.repo<<END [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch enabled=1 gpgcheck=0 #repo_gpgcheck=0 #gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg #exclude=kubelet kubeadm kubectl END
8、配置时间同步(所有主机上) 1 2 3 4 yum install chrony -y sed -i 's/^server.*//' /etc/chrony.conf sed -i 's/# Please.*/server ntp.aliyun.com iburst/' /etc/chrony.conf systemctl enable chronyd --now
9、 开启ipvs(所有主机上) ipvs是什么?
ipvs (IP Virtual Server) 实现了传输层负载均衡,也就是我们常说的4层LAN交换,作为 Linux 内核的一部分。ipvs运行在主机上,在真实服务器集群前充当负载均衡器。ipvs可以将基于TCP和UDP的服务请求转发到真实服务器上,并使真实服务器的服务在单个 IP 地址上显示为虚拟服务。
ipvs和iptable对比分析
kube-proxy支持 iptables 和 ipvs 两种模式, 在kubernetes v1.8 中引入了 ipvs 模式,在 v1.9 中处于 beta 阶段,在 v1.11 中已经正式可用了。iptables 模式在 v1.1 中就添加支持了,从 v1.2 版本开始 iptables 就是 kube-proxy 默认的操作模式,ipvs 和 iptables 都是基于netfilter的,但是ipvs采用的是hash表,因此当service数量达到一定规模时,hash查表的速度优势就会显现出来,从而提高service的服务性能。那么 ipvs 模式和 iptables 模式之间有哪些差异呢?
1、ipvs 为大型集群提供了更好的可扩展性和性能
2、ipvs 支持比 iptables 更复杂的复制均衡算法(最小负载、最少连接、加权等等)
3、ipvs 支持服务器健康检查和连接重试 等功能
1 2 3 4 5 6 7 8 9 10 11 cat > /etc/sysconfig/modules/ipvs.modules<<END #!/bin/bash ipvs_modules="ip_vs ip_vs_lc ip_vs_wlc ip_vs_rr ip_vs_wrr ip_vs_lblc ip_vs_lblcr ip_vs_dh ip_vs_sh ip_vs_nq ip_vs_sed ip_vs_ftp nf_conntrack" for kernel_module in \${ipvs_modules}; do /sbin/modinfo -F filename \${kernel_module} > /dev/null 2>&1 if [ 0 -eq 0 ]; then /sbin/modprobe \${kernel_module} fi done END bash /etc/sysconfig/modules/ipvs.modules
10、 安装基础软件包(所有主机上) 1 yum install -y yum-utils device-mapper-persistent-data lvm2 wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo libaio-devel vim ncurses-devel autoconf automake zlib-devel epel-release openssh-server socat ipvsadm conntrack telnet ipvsadm bash-completion rsync
11、安装containerd服务 11.1 安装containerd 1 yum install containerd.io-1.6.6 -y
11.2 生成containerd的配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 mkdir -p /etc/containerd mkdir /etc/containerd/certs.d/docker.io/ -p containerd config default > /etc/containerd/config.toml sed -i s/"SystemdCgroup = false" /"SystemdCgroup = true" / /etc/containerd/config.toml sed -i s/'sandbox_image = "k8s.gcr.io\/pause:3.6"' /'sandbox_image = "registry.aliyuncs.com\/google_containers\/pause:3.7"' / /etc/containerd/config.toml sed -i s/config_path.*/'config_path = "\/etc\/containerd\/certs.d"' / /etc/containerd/config.toml mkdir -p /etc/containerd/certs.d/docker.io cat > /etc/containerd/certs.d/docker.io/hosts.toml << EOF server = "https://docker.io" [host."https://hub.792588.xyz"] capabilities = ["pull", "resolve"] EOF mkdir -p /etc/containerd/certs.d/registry.k8s.io tee /etc/containerd/certs.d/registry.k8s.io/hosts.toml << 'EOF' server = "https://registry.k8s.io" [host."https://k8s.792588.xyz" ] capabilities = ["pull" , "resolve" , "push" ] EOF mkdir -p /etc/containerd/certs.d/docker.elastic.co tee /etc/containerd/certs.d/docker.elastic.co/hosts.toml << 'EOF' server = "https://docker.elastic.co" [host."https://elastic.792588.xyz" ] capabilities = ["pull" , "resolve" , "push" ] EOF mkdir -p /etc/containerd/certs.d/gcr.io tee /etc/containerd/certs.d/gcr.io/hosts.toml << 'EOF' server = "https://gcr.io" [host."https://gcr.792588.xyz" ] capabilities = ["pull" , "resolve" , "push" ] EOF mkdir -p /etc/containerd/certs.d/ghcr.io tee /etc/containerd/certs.d/ghcr.io/hosts.toml << 'EOF' server = "https://ghcr.io" [host."https://ghcr.792588.xyz" ] capabilities = ["pull" , "resolve" , "push" ] EOF mkdir -p /etc/containerd/certs.d/k8s.gcr.io tee /etc/containerd/certs.d/k8s.gcr.io/hosts.toml << 'EOF' server = "https://k8s.gcr.io" [host."https://k8sgcr.792588.xyz" ] capabilities = ["pull" , "resolve" , "push" ] EOF mkdir -p /etc/containerd/certs.d/mcr.microsoft.com tee /etc/containerd/certs.d/mcr.microsoft.com/hosts.toml << 'EOF' server = "https://mcr.microsoft.com" [host."https://mcr.792588.xyz" ] capabilities = ["pull" , "resolve" , "push" ] EOF mkdir -p /etc/containerd/certs.d/nvcr.io tee /etc/containerd/certs.d/nvcr.io/hosts.toml << 'EOF' server = "https://nvcr.io" [host."https://nvcr.792588.xyz" ] capabilities = ["pull" , "resolve" , "push" ] EOF mkdir -p /etc/containerd/certs.d/quay.io tee /etc/containerd/certs.d/quay.io/hosts.toml << 'EOF' server = "https://quay.io" [host."https://quay.792588.xyz" ] capabilities = ["pull" , "resolve" , "push" ] EOF
11.3 启动containerd服务,并做开机自启 1 systemctl enable containerd --now
11.4 修改/etc/crictl.yaml配置文件 1 2 3 4 5 6 7 cat > /etc/crictl.yaml <<EOF runtime-endpoint: unix:///run/containerd/containerd.sock image-endpoint: unix:///run/containerd/containerd.sock timeout: 10 debug: false EOF systemctl restart containerd
12、安装docker服务 备注: docker也要安装,docker跟containerd不冲突,安装docker是为了能基于dockerfile构建镜像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 yum install docker-ce -y mkdir -p /etc/docker mkdir -p /data/docker IP=`ip a s| grep eth0 | grep inet | awk {'print $2' }|awk -F "/" {'print $1' } | awk -F "." {'print $4' }` cat > /etc/docker/daemon.json<<END { "data-root":"/data/docker", "registry-mirrors": ["https://oym4jkot.mirror.aliyuncs.com"], "insecure-registries":["registry.access.redhat.com","quay.io"], "bip":"172.101.$IP.1/24", "live-restore":true, "exec-opts": ["native.cgroupdriver=systemd"] } END
三、安装初始化k8s需要的软件包 1 2 3 yum install -y kubelet-1.25.0 kubeadm-1.25.0 kubectl-1.25.0 systemctl enable kubelet --now && systemctl status kubelet
注:每个软件包的作用
Kubeadm: kubeadm是一个工具,用来初始化k8s集群的
kubelet: 安装在集群所有节点上,用于启动Pod的,kubeadm安装k8s,k8s控制节点和工作节点的组件,都是基于pod运行的,只要pod启动,就需要kubelet
kubectl: 通过kubectl可以部署和管理应用,查看各种资源,创建、删除和更新各种组件
四、kubeadm初始化k8s集群 1、设置容器运行时 1 crictl config runtime-endpoint /run/containerd/containerd.sock
2、生成默认配置文件
3、修改配置文件 根据我们自己的需求修改配置,比如修改 imageRepository 的值,kube-proxy 的模式为 ipvs,需要注意的是由于我们使用的containerd作为运行时,所以在初始化节点的时候需要指定cgroupDriver为systemd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 [root@master1 ~] apiVersion: kubeadm.k8s.io/v1beta3 bootstrapTokens: - groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authentication kind: InitConfiguration localAPIEndpoint: advertiseAddress: 192.168.101.11 bindPort: 6443 nodeRegistration: criSocket: unix:///var/run/containerd/containerd.sock imagePullPolicy: IfNotPresent name: master1 taints: null --- apiServer: timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta3 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controllerManager: {} dns: {} etcd: local : dataDir: /var/lib/etcd imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers kind: ClusterConfiguration kubernetesVersion: 1.25.0 networking: dnsDomain: cluster.local podSubnet: 10.0.0.0/16 serviceSubnet: 10.255.0.0/16 scheduler: {} --- apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration mode: ipvs --- apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration cgroupDriver: systemd
4、使用kubeadm init
5、生成工作节点加入链接
6、查看加入的节点 1 2 3 4 5 [root@master1 ~] NAME STATUS ROLES AGE VERSION master1 NotReady control-plane 2d23h v1.25.0 node1 NotReady <none> 2d13h v1.25.0 node2 NotReady <none> 6m25s v1.25.0
7、将node节点打上标签 1 2 3 4 5 6 7 8 9 10 11 [root@master1 ~] node/node1 labeled [root@master1 ~] node/node2 labeled [root@master1 ~] NAME STATUS ROLES AGE VERSION master1 NotReady control-plane 2d23h v1.25.0 node1 NotReady work 2d13h v1.25.0 node2 NotReady work 16m v1.25.0
五、安装kubernetes网络组件-Calico 1、导入calico镜像 1 ctr -n=k8s.io images import calico.tar.gz
2、apply caclico文件 注:在线下载配置文件地址是: https://docs.projectcalico.org/manifests/calico.yaml
1 2 3 4 5 6 7 8 [root@master1 ~] [root@master1 ~] NAME STATUS ROLES AGE VERSION master1 Ready control-plane 3d16h v1.25.0 master2 Ready control-plane 7m33s v1.25.0 node1 Ready work 3d5h v1.25.0 node2 Ready work 16h v1.25.0
3、caclico架构图
Calico网络模型主要工作组件:
1.Felix: 运行在每一台 Host 的 agent 进程,主要负责网络接口管理和监听、路由、ARP 管理、ACL 管理和同步、状态上报等。保证跨主机容器网络互通。
2.etcd: 分布式键值存储,相当于k8s集群中的数据库,存储着Calico网络模型中IP地址等相关信息。主要负责网络元数据一致性,确保 Calico 网络状态的准确性;
3.BGP Client(BIRD) :Calico 为每一台 Host 部署一个 BGP Client,即每台host上部署一个BIRD。 主要负责把 Felix 写入 Kernel 的路由信息分发到当前 Calico 网络,确保 Workload 间的通信的有效性;
4.BGP Route Reflector :在大型网络规模中,如果仅仅使用 BGP client 形成 mesh 全网互联的方案就会导致规模限制,因为所有节点之间俩俩互联,需要 N^2 个连接,为了解决这个规模问题,可以采用 BGP 的 Router Reflector 的方法,通过一个或者多个 BGP Route Reflector 来完成集中式的路由分发。
4、calico网络插件配置文件说明 4.1 Daemonset配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 …… containers: - name: calico-node image: docker.io/calico/node:v3.18.0 …… env: - name: DATASTORE_TYPE value: "kubernetes" - name: CLUSTER_TYPE value: "k8s,bgp" - name: IP value: "autodetect" - name: CALICO_IPV4POOL_CIDR value: "10.244.0.0/16" - name: CALICO_IPV4POOL_IPIP value: "Always"
calico-node服务的主要参数如下:
CALICO_IPV4POOL_IPIP :是否启用IPIP模式。启用IPIP模式时,Calico将在Node上创建一个名为tunl0的虚拟隧道。IP Pool可以使用两种模式:BGP或IPIP。使用IPIP模式时,设置CALICO_IPV4POOL_IPIP=”Always”,不使用IPIP模式时,设置CALICO_IPV4POOL_IPIP=”Off”,此时将使用BGP模式。
IP_AUTODETECTION_METHOD :获取Node IP地址的方式,默认使用第1个网络接口的IP地址,对于安装了多块网卡的Node,可以使用正则表达式选择正确的网卡,例如”interface=eth.*”表示选择名称以eth开头的网卡的IP地址。
1 2 - name: IP_AUTODETECTION_METHOD value: "interface=ens33"
4.2 calico的IPIP模式和BGP模式对比分析 1)IPIP
把一个IP数据包又套在一个IP包里,即把IP层封装到IP层的一个 tunnel,它的作用其实基本上就相当于一个基于IP层的网桥,一般来说,普通的网桥是基于mac层的,根本不需要IP,而这个ipip则是通过两端的路由做一个tunnel,把两个本来不通的网络通过点对点连接起来;
calico以ipip模式部署完毕后,node上会有一个tunl0的网卡设备,这是ipip做隧道封装用的,也是一种overlay模式的网络。当我们把节点下线,calico容器都停止后,这个设备依然还在,执行 rmmodipip命令可以将它删除。
2)BGP
BGP模式直接使用物理机作为虚拟路由路(vRouter),不再创建额外的tunnel
边界网关协议(BorderGateway Protocol, BGP)是互联网上一个核心的去中心化的自治路由协议。它通过维护IP路由表或‘前缀’表来实现自治系统(AS)之间的可达性,属于矢量路由协议。BGP不使用传统的内部网关协议(IGP)的指标,而是基于路径、网络策略或规则集来决定路由。因此,它更适合被称为矢量性协议,而不是路由协议,通俗的说就是将接入到机房的多条线路(如电信、联通、移动等)融合为一体,实现多线单IP;
BGP 机房的优点:服务器只需要设置一个IP地址,最佳访问路由是由网络上的骨干路由器根据路由跳数与其它技术指标来确定的,不会占用服务器的任何系统;
官方提供的calico.yaml模板里,默认打开了ip-ip功能,该功能会在node上创建一个设备tunl0,容器的网络数据会经过该设备被封装一个ip头再转发。这里,calico.yaml中通过修改calico-node的环境变量:CALICO_IPV4POOL_IPIP来实现ipip功能的开关:默认是Always,表示开启;Off表示关闭ipip。
1 2 3 4 5 6 7 8 - name: CLUSTER_TYPE value: "k8s,bgp" - name: IP value: "autodetect" - name: CALICO_IPV4POOL_IPIP value: "Always"
总结:
calico BGP通信是基于TCP协议的,所以只要节点间三层互通即可完成,即三层互通的环境bird就能生成与邻居有关的路由。但是这些路由和flannel host-gateway模式一样,需要二层互通才能访问的通,因此如果在实际环境中配置了BGP模式生成了路由但是不同节点间pod访问不通,可能需要再确认下节点间是否二层互通。
为了解决节点间二层不通场景下的跨节点通信问题,calico也有自己的解决方案——IPIP模式
5、测试在k8s创建pod是否可以正常访问网络 5.1 解压镜像到node节点 1 2 [root@node1 ~] [root@node2 ~]
5.2 新建容器进行测试网络 测试成功,注意busybox不能用最新版本,会出现解析不到dns和ip的情况
1 2 3 4 5 6 7 8 9 10 11 12 13 [root@master1 ~] If you don't see a command prompt, try pressing enter. / # ping www.baidu.com PING www.baidu.com (36.152.44.96): 56 data bytes 64 bytes from 36.152.44.96: seq=0 ttl=55 time=2.713 ms 64 bytes from 36.152.44.96: seq=1 ttl=55 time=2.818 ms / # nslookup kubernetes.default.svc.cluster.local Server: 10.255.0.10 Address 1: 10.255.0.10 kube-dns.kube-system.svc.cluster.local Name: kubernetes.default.svc.cluster.local Address 1: 10.255.0.1 kubernetes.default.svc.cluster.local
六、ctr与crictl的区别 背景:在部署k8s的过程中,经常要对镜像进行操作(拉取、删除、查看等)
问题:使用过程中会发现ctr和crictl有很多相同功能,也有些不同,那区别到底在哪里?
说明:
1.ctr是containerd自带的CLI命令行工具,crictl是k8s中CRI(容器运行时接口)的客户端,k8s使用该客户端和containerd进行交互;
2.ctr和crictl命令具体区别如下,也可以–help查看。crictl缺少对具体镜像的管理能力,可能是k8s层面镜像管理可以由用户自行控制,能配置pod里面容器的统一镜像仓库,镜像的管理可以有habor等插件进行处理。