Kubernetes 集群部署
虚拟机配置
网络配置
NAT模式
-
NAT(Network Address Translation)
-
虚拟机网络的NAT模式
- 当NAT用在虚拟机领域的时候,原理是类似的。只不过一台PC上的若干虚拟机相当于若干内网用户,而宿主机PC充当路由器的角色,虚拟机会在PC上虚拟化一个网络环境:也就是每个虚拟机通过一个无形的网线连接到了无形的路由器上,仅此而已。每个虚拟机实例会通过PC上的虚拟路由器获取DHCP分配的局域网IP,但是这只是本机虚拟出来的局域网,并不是物理局域网。那么,现在虚拟机想访问外网,只需要配置默认网关为PC上虚拟路由器,那么数据包经过虚拟路由器的时候,会将源IP修改为PC的物理网卡的物理局域网IP,发送给物理路由器,之后的事情和之前描述的一样。上面的虚拟路由器其实是宿主机上一张虚拟的网卡,而虚拟机则将默认网关指向了这张网卡,从而有机会进行IP篡改。NAT模式实际是虚拟了一个网卡出来,虚拟机直接链接这个虚拟网卡,每次访问和交互通过这个虚拟网卡交换数据。
- 虚拟机发送数据给宿主机:虚拟机系统->虚拟机网卡->宿主机系统
- 虚拟机访问外网:虚拟机系统->虚拟机网卡->宿主机系统->物理网卡->路由器->外网
-
注意
- 宿主机上的若干虚拟机之间,可以互相通讯,中介就是虚拟路由器。
- 虚拟机可以访问外网,也可以访问物理局域网,但是无法访问其他宿主机上的虚拟机。
- 外部(物理局域网其他主机)无法直接访问虚拟机,这和物理路由器外网的用户无法直接访问内网用户一个道理。(反向进入内网需要DNAT)
- 虚拟机可以访问宿主机的物理IP,流程是先经过宿主NAT修改源IP和源PORT,通过物理网卡发出到局域网络中,又被物理网卡接收处理。
- 宿主机无法访问虚拟机,这是因为宿主机的物理网卡和内网其他网卡的角色一样,对于虚拟路由器来说都是”外部”。
桥接模式
-
网桥(Network Bridge)
-
虚拟机网络的桥接模式
- 桥接模式下,虚拟出来的操作系统就像是局域网中的一台独立的主机,它可以访问网内任何一台机器。 **在桥接模式下,需要手工为虚拟系统配置IP地址、子网掩码,而且还要和宿主机器处于同一网段,这样虚拟系统才能和宿主机器进行通信。**同时,由于这个虚拟系统是局域网中的一个独立的主机系统,那么就可以手工配置它的TCP/IP配置信息,以实现通过局域网的网关或路由器访问互联网。使用桥接模式的虚拟系统和宿主机器的关系,就像连接在同一个Hub上的两台电脑。想让它们相互通讯,你就需要为虚拟系统配置IP地址和子网掩码,否则就无法通信。
- 假设br0是一个网桥,br0相当于虚拟交换机,物理网卡eth0和虚拟机网卡vnet0都通过虚拟的网线连接到br0上,这样eth0和vnet0之间可以互相交换数据。我们把br0叫做桥,其实在宿主机上也是一张虚拟的网卡,作为虚拟交换机角色,而传统交换机本身就是按目标的mac地址将数据转发到正确的网线出口上,并不会做什么事情。配置虚拟机采用桥接模式并指定br0后,数据从虚拟机的网卡vnet0发出到br0,br0会将数据转发给另一端的eth0,源mac是虚拟机的随机MAC地址,源IP是虚拟机的IP地址,桥并没有做中间修改,数据仅仅通过eth0网卡直接发到链路上,eth0只是充当一个发送的物理介质。当应答回来的时候,物理网卡eth0会在混杂模式捕获包并交给br0处理,如果目标mac地址等于eth0或者vnet0,则进一步处理。如果是eth0的包那么直接宿主机处理,如果是vnet0的包则转发给虚拟机处理,整个过程无需对包做出修改,因为br0仅仅是一个交换机,而eth0和vnet0是连在上面的2个网卡而已。
- 虚拟机发送数据给宿主机:虚拟机系统->虚拟机网卡->网桥->物理网卡->路由器->物理网卡->宿主机系统
- 虚拟机访问外网:虚拟机系统->虚拟机网卡->网桥->物理网卡->路由器->外网
-
注意
- 无论是虚拟机还是物理机,大家都在一个网段里,都指向同一个默认网关(物理路由器)。
- 虚拟机通过桥,可以向物理路由器申请dhcp,分配得到局域网IP。
- 挂在桥上的虚拟机,可以直接被局域网其他用户访问,因为eth0混杂模式+桥可以转发到虚拟机。
- 混杂模式的网卡只是一个物理介质,它监听所有的包,只留下自己关注的包(比如目的mac地址是eth0h或者vnet0的包),也可以发送任意的包,无论包的源mac地址到底是不是物理网卡自身的(vnet0的假mac地址)
-
配置网桥
需要将物理网卡添加到网桥上,并将物理网卡的ip转移到网桥上(学校服务器ip不能变),同时添加mac地址,具体原因见:Linux虚拟网络设备之bridge(桥)#!/bin/bash if [ "$#" -ne 2 ]; then exit 1 fi br="$1" dev="$2" sudo ip link add $br type bridge sudo ip link set $dev master $br dev_ip=$(ip addr show $dev | awk '/inet / {print $2}') sudo ip addr del $dev_ip dev $dev sudo ip addr add $dev_ip dev $br dev_mac=$(ip link show $dev | awk '/ether/ {print $2}') sudo ip link set dev $br address $dev_mac sudo ip link set dev $br up sudo ip route add default via 10.10.1.1 dev $br sleep 5m sudo ip link set dev $br down sudo ip link delete $br type bridge sudo ip addr add $dev_ip dev $dev -
Vagrant桥接模式创建虚拟机
config.vm.network :public_network, dev: "vagrant-br0", mode: "bridge", type: "bridge", auto_config: true -
Ubuntu22.04虚拟机配置静态IP
进入/etc/netplan/,找到某个yaml文件,按下面的例子进行修改
--- network: version: 2 renderer: networkd ethernets: eth1: dhcp4: false addresses: # - [宿主机网络号].[虚拟机主机号]/[子网掩码位数] - 10.10.1.233/24sudo netplan apply
其他配置
apt换源
mv /etc/apt/sources.list /etc/apt/sources.list.bak
vim /etc/apt/sources.list
- 阿里镜像源:链接
容器运行时
介绍
- Docker
- Docker 利用Linux核心中的资源分离机制,例如cgroups,以及Linux核心命名空间(namespaces),来建立独立的容器(containers)。这可以在单一Linux实体下运作,避免启动一个虚拟机造成的额外负担。Linux核心对命名空间的支持完全隔离了工作环境中应用程序的视野,包括行程树、网络、用户ID与挂载文件系统,而核心的cgroup提供资源隔离,包括CPU、存储器、block I/O与网络。从0.9版本起,Dockers在使用抽象虚拟是经由libvirt的LXC与systemd - nspawn提供界面的基础上,开始包括libcontainer函式库做为以自己的方式开始直接使用由Linux核心提供的虚拟化的设施。
- CRI-O
- Containerd
配置
Docker添加镜像源
sudo echo "{\"registry-mirrors\": [\"https://dockerhub.icu\"]}" > /etc/docker/daemon.json
sudo systemctl daemon-reload
sudo systemctl restart docker.service
Kubeadm、Kubectl、Kubelet
Kubeadm:安装工具
- Kubeadm 是一个提供了
kubeadm init和kubeadm join的工具, 作为创建 Kubernetes 集群的 “快捷途径” 的最佳实践。 - kubeadm 通过执行必要的操作来启动和运行最小可用集群。 按照设计,它只关注启动引导,而非配置机器。同样的, 安装各种 “锦上添花” 的扩展,例如 Kubernetes Dashboard、 监控方案、以及特定云平台的扩展,都不在讨论范围内。
- 相反,我们希望在 kubeadm 之上构建更高级别以及更加合规的工具, 理想情况下,使用 kubeadm 作为所有部署工作的基准将会更加易于创建一致性集群。
Kubectl:命令行工具
- Kubernetes 提供 kubectl 是使用 Kubernetes API 与 Kubernetes 集群的控制面进行通信的命令行工具。这个工具叫做
kubectl。 - 针对配置信息,
kubectl在$HOME/.kube目录中查找一个名为config的配置文件。 你可以通过设置KUBECONFIG环境变量或设置--kubeconfig
Kubelet:节点上的代理
-
kubelet 是在每个节点上运行的主要 “节点代理”。它可以使用以下方式之一向 API 服务器注册:
- 主机名(hostname);
- 覆盖主机名的参数;
- 特定于某云驱动的逻辑。
-
kubelet 是基于 PodSpec 来工作的。每个 PodSpec 是一个描述 Pod 的 YAML 或 JSON 对象。 kubelet 接受通过各种机制(主要是通过 apiserver)提供的一组 PodSpec,并确保这些 PodSpec 中描述的容器处于运行状态且运行状况良好。 kubelet 不管理不是由 Kubernetes 创建的容器。除了来自 API 服务器的 PodSpec 之外,还可以通过以下两种方式将容器清单(manifest)提供给 kubelet。
- 文件(File):利用命令行参数传递路径。kubelet 周期性地监视此路径下的文件是否有更新。 监视周期默认为 20s,且可通过参数进行配置。
- HTTP 端点(HTTP endpoint):利用命令行参数指定 HTTP 端点。 此端点的监视周期默认为 20 秒,也可以使用参数进行配置。
初始化控制面、工作节点加入
准备
-
主机重命名
sudo hostnamectl set-hostname NAME -
修改hosts文件:hosts文件记录主机IP与主机名映射,其中主机IP会作为该节点在集群中的IP
127.0.0.1 localhost 127.0.1.1 ubuntu.localdomain [your IP] [your NAME] -
开放端口
#!/bin/bash ports=(6443 2379 2380 10250 10259 10257 10248) for port in "${ports[@]}"; do sudo iptables -A INPUT -p tcp --dport $port -j ACCEPT done sudo iptables -A INPUT -p tcp --match multiport --dports 30000:32767 -j ACCEPT -
关闭swap分区
sudo swapoff -a
初始化控制面:kubeadm init
常用参数
-
--apiserver-advertise-address [string]
API 服务器所公布的其正在监听的 IP 地址。如果未设置,则使用默认网络接口。
-
--image-repository [string]
选择用于拉取控制平面镜像的容器仓库,默认值:"registry.k8s.io",可以修改为阿里镜像源:"registry.aliyuncs.com/google_containers"。
-
--cri-socket [string]
要连接的 CRI 套接字的路径。如果为空,则 kubeadm 将尝试自动检测此值; 仅当安装了多个 CRI 或具有非标准 CRI 套接字时,才使用此选项。
-
--pod-network-cidr [string]
指明 Pod 网络可以使用的 IP 地址段。如果设置了这个参数,控制平面将会为每一个节点自动分配 CIDR。
-
--token [string]
这个令牌用于建立控制平面节点与工作节点间的双向通信。 格式为 [a-z0-9]{6}.[a-z0-9]{16} - 示例:abcdef.0123456789abcdef
-
--token-ttl [duration]
令牌被自动删除之前的持续时间(例如 1s,2m,3h),默认值:24h0m0s。如果设置为 '0',则令牌将永不过期。
例
su root
kubeadm reset --cri-socket /var/run/dockershim.sock
kubeadm init --cri-socket /var/run/dockershim.sock \
--apiserver-advertise-address 10.10.1.231 \
--image-repository registry.aliyuncs.com/google_containers \
--pod-network-cidr 10.244.0.0/16 \
--token fedcba.0123456789abcdef \
--token-ttl 0
配置集群网络:
使用Calico配置
Calico介绍
- Calico是一个联网和网络安全解决方案,可以让K8s负载或者非K8s/传统负载之间进行无缝且安全地通信
- Calico两大组件:Calico CNI、Calico network policy suite
- Calico CNI 是一个控制面,可以对多个数据平面进行编程,它是一种L3/L4层网络解决方案,可以确保容器、K8s集群、虚拟机和主机本地负载的安全。
- Calico network policy suite 是 Calico CNI 的接口,其中包含数据平面要执行的规则。
Calico安装
- 方法一:官方
- 方法二:在K8s控制面执行
kubectl apply -f https://docs.tigera.io/archive/v[version]/manifests/calico.yaml
工作节点加入:kubeadm join
例
kubeadm join 10.10.1.231:6443 \
--token fedcba.0123456789abcdef \
--discovery-token-ca-cert-hash [hash] \
--cri-socket /var/run/dockershim.sock
查看集群状况
查看集群节点状况
sudo kubectl get nodes -n kube-system -o wide
查看集群pod状况
sudo kubectl get pods -n kube-system -o wide
可能遇到的问题
ImagePullBackOff
- 意思:拉取镜像失败,正尝试重新拉取
- 解决:去相应节点手动拉取镜像
-
查找失败镜像名
kubectl describe pod [NAME] -n kube-system | grep Image: -
拉取镜像(以docker为例)
docker pull [IMAGE NAME]
-
控制面系统内核更新重启后kubelet无法启动
- 解决:重置集群
Pod因为/run/xtables.lock is not a file问题无法启动
- 解决:手动创建/run/xtables.lock,如果原来是文件夹就删除
先前运行的虚拟机无法连接,状态为paused,无法恢复
- 可能的问题:宿主机磁盘空间不足
- 原因:使用Vagrant通过libvirt创建的虚拟机默认存储在/var/lib/libvirt/images/,因此该区域挂载的磁盘空间不足时会导致虚拟机无法正常运行
- 解决:迁移虚拟机
评论区