基于Ubuntu 24.04 快速部署K8S 1.31.0集群 1. K8S集群主机准备 主机操作系统版本: Ubuntu 24.04
硬件配置说明: master 2核 4G内存 20GB硬盘 node1 2核 4G内存 20GB硬盘 node2 2核 4G内存 20GB硬盘
1.1 主机名配置 master: hostnamectl set-hostname k8s-master01 node1: hostnamectl set-hostname k8s-worker01 node2: hostnamectl set-hostname k8s-worker02
1.2 主机IP地址配置 vim /etc/netplan/50-cloud-init.yaml
欲使其生效, 使用命令netplan apply
查看IP地址: ip a s
使用动态分配时, 修改hosts即可
vim /etc/hosts
1 2 3 192.168.64.15 k8s-master01192.168.64.16 k8s-worker01192.168.64.17 k8s-worker02
1.3 时间同步 apt install ntpsec-ntpdate
1 2 0 0 * * *ntpdate ntp.aliyun.com
1.4 配置内核转发和网桥过滤 如果不配置会导致K8S集群的网络通信不流畅
创建加载内核模块文件
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 modprobe overlay modprobe br_netfiltercat << EOF | tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF cat << EOF | tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 EOF sysctl --system
1.5 安装ipset和ipvsadm 后续在使用kubeproxy的代理模式时, 会用到ipvs的配置 ipset 和 ipvsadm 是用于网络流量管理和负载均衡的重要工具,特别是在 Linux 环境中 ipset 是一个用于管理 IP 集合的工具。它可以创建和维护多个 IP 地址的集合,以便于快速地在防火墙(如 iptables)中进行匹配。ipset 的主要用途包括: 性能优化:通过将多个 IP 地址组合成集合,ipset 提供了比单独规则更高效的匹配方式,减少了 iptables 规则的数量,从而提高了性能。 动态管理:可以在运行时添加、删除或修改 IP 集合,便于对大规模流量的快速响应。
ipvsadm(“IP Virtual Server Administration”) 是 IP 虚拟服务器(IPVS)的管理工具,用于实现 Linux 的负载均衡。它主要用于以下方面: 负载均衡:ipvsadm 允许用户配置和管理 IPVS,以实现对传入流量的负载均衡。通过将请求分发到多个后端服务器,提供高可用性和高性能。 调度算法:支持多种负载均衡算法(如轮询、最少连接、基于权重等),使得流量分发更加灵活。 高可用性:配合 Linux 虚拟服务器(如 LVS),能够实现高可用性架构,支持多种网络协议(如 TCP、UDP)。
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 # 安装 ipset 和 ipvsadm apt install ipset ipvsadm# 配置ipvsadm模块加载 # 添加需要加载的模块 cat << EOF | tee /etc/modules-load.d/ipvs.conf ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh nf_conntrack EOF# 创建加载模块脚本文件, 立即使用 cat << EOF | tee ipvs.sh# ! /bin/sh modprobe -- ip_vs modprobe -- ip_vs_rr modprobe -- ip_vs_wrr modprobe -- ip_vs_sh modprobe -- nf_conntrack EOF# 执行脚本 sh ipvs.sh # 查看模块加载情况 lsmod | grep "ip_vs"
1.6 关闭SWAP分区 1 2 3 4 5 6 7 8 9 # 如果不重启式的关闭swap分区, 可以临时关闭, 关闭命令为 swapoff -a# 永远关闭swap分区, 需要重启系统 vim /etc/fstab# 注释掉如下内容 # /swap.img none swap sw 0 0
2. K8S集群节点容器管理工具准备 2.1 Containerd 部署文件获取 1 2 3 4 5 6 7 8 # 通过wget命令下载 # wget https://github.com/containerd/containerd/releases/download/v1.7.20/cri-containerd-1.7.20-linux-amd64.tar.gz # 本文使用Macbook M1芯片, 所以使用arm版本 wget https://github.com/containerd/containerd/releases/download/v1.7.20/cri-containerd-1.7.20-linux-arm64.tar.gz# 解压并合并到根目录 tar xfv cri-containerd-1.7.20-linux-arm64.tar.gz -C /
Containerd配置文件生成和修改 默认情况下, 没有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 # 创建配置文件目录 mkdir /etc/containerd# 生成配置文件 containerd config default > /etc/containerd/config.toml# 修改第67行 vim /etc/containerd/config.toml sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.10" # 修改为阿里云镜像# sandbox_image = "registry.k8s.io/pause:3.9" # 修改第139行, runc的operation vim /etc/containerd/config.toml SystemdCgroup = true # 由false修改为true# containerd启动及开机自启动设计 # 设置开机自启动, 并现在启动 systemctl enable --now containerd# 验证启动成功 ls /var/run/containerd/ -l# 如果成功, 则有以下内容 # srw-rw---- 1 root root 0 Nov 4 10:17 containerd.sock # srw-rw---- 1 root root 0 Nov 4 10:17 containerd.sock.ttrpc # drwx--x--x 2 root root 40 Nov 4 10:17 io.containerd.runtime.v1.linux # drwx--x--x 2 root root 40 Nov 4 10:17 io.containerd.runtime.v2.task # 验证版本 containerd --version
3. K8S 集群部署 3.1 安装源: apt
1 2 3 4 5 6 7 8 9 10 11 12 # 下载用于Kubernetes软件包仓库的公共签名密钥, 如果没有此密钥, 则无法完成软件安装包的安装 curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg# 添加Kubernetes apt源仓库 echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list# 更新apt包索引 sudo apt-get update
3.2 Kubernetes软件安装及kubelet
配置 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 # 查看当前软件列表, 是否有kubeadm apt-cache policy kubeadm# 安装指定版本 apt install kubeadm=1.31.0-1.1 kubelet=1.31.0-1.1 kubectl=1.31.0-1.1 -y# !!!注意: 安装完成后不能立即启动 # 首先锁定这些应用的版本, 保证后续使用过程中不会自动更新, 取消锁定使用unhold sudo apt-mark hold kubeadm kubelet kubectl# 配置kubelet # 为实现Kubernetes使用的cgroup与容器运行时使用的cgroupdriver的一致性, 建议修改如下内容 vim /etc/default/kubelet KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"# 设置为开机自启动即可, 由于没有生成配置文件, 集群初始化后自动启动 systemctl enable kubelet# 准备初始化的配置文件, 只需要在master节点中准备即可 # 查看版本 kubeadm version # 生成部署配置文件 kubeadm config print init-defaults > kubeadm-config.yaml# 修改配置文件 vim kubeadm-config.yaml
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 1 apiVersion: kubeadm.k8s.io/v1beta4 2 bootstrapTokens: 3 - groups: 4 - system:bootstrappers:kubeadm:default-node-token 5 token: abcdef.0123456789abcdef 6 ttl: 24h0m0s 7 usages: 8 - signing 9 - authentication 10 kind: InitConfiguration 11 localAPIEndpoint: 12 advertiseAddress: 1.2 .3 .4 13 bindPort: 6443 14 nodeRegistration: 15 criSocket: unix:///var/run/containerd/containerd.sock 16 imagePullPolicy: IfNotPresent 17 imagePullSerial: true 18 name: k8s-master01 19 taints: null 20 timeouts: 21 controlPlaneComponentHealthCheck: 4m0s 22 discovery: 5m0s 23 etcdAPICall: 2m0s 24 kubeletHealthCheck: 4m0s 25 kubernetesAPICall: 1m0s 26 tlsBootstrap: 5m0s 27 upgradeManifests: 5m0s 28 --- 29 apiServer: {} 30 apiVersion: kubeadm.k8s.io/v1beta4 31 caCertificateValidityPeriod: 87600h0m0s 32 certificateValidityPeriod: 8760h0m0s 33 certificatesDir: /etc/kubernetes/pki 34 clusterName: kubernetes 35 controllerManager: {} 36 dns: {} 37 encryptionAlgorithm: RSA-2048 38 etcd: 39 local: 40 dataDir: /var/lib/etcd 41 imageRepository: registry.aliyuncs.com/google_containers 42 kind: ClusterConfiguration 43 kubernetesVersion: 1.31 .0 44 networking: 45 dnsDomain: cluster.local 46 serviceSubnet: 10.96 .0 .0 /12 podSubnet: 10.244 .0 .0 /16 47 proxy: {} 48 scheduler: {}
3.3 容器镜像下载 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 查看当前版本需要的镜像, 指定版本可用kubeadm config images list --kubernetes-version=1.31.0 # kubeadm config images list kubeadm config images list --kubernetes-version=1.31.0# 如果下载失败, 到阿里云上下载, 下载后更改镜像名称 kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers --kubernetes-version=1.31.0# 下载镜像 kubeadm config images pull # 实际底层使用的crictl工具下载# 查看下载的镜像 crictl images
3.4 使用 kubeadm 初始化集群
kubeadm init –config kubeadm-config.yaml –upload-certs –v=9
如果init失败, 需要通过kubeadm reset
重置操作, 并重启容器运行时sudo systemctl restart containerd
3.5 kubectl 配置 1 2 3 4 5 6 7 8 9 10 11 12 mkdir -p $HOME/.kube # 此文件夹用于存放 kubectl 的配置文件 sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config # 将 Kubernetes 集群初始化时生成的 admin.conf 文件复制到用户的 .kube/config 文件中 sudo chown $(id -u):$(id -g) $HOME/.kube/config # 更改文件的所有者,使其归当前用户所有# 完成上述操作后, 查看当前节点 kubectl get nodes# 上述命令会查看到结果: k8s-master01 NotReady control-plane 10m v1.31.0
3.6 将其余节点加入集群 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # 在主节点上获取加入命令, 包括 IP 地址、端口、token 和 --discovery-token-ca-cert-hash 参数。 kubeadm token create --print-join-command# 输出示例如下: # kubeadm join 192.168.64.15:6443 --token fhgh1q.y3lit9rx5n9g42pc --discovery-token-ca-cert-hash sha256:eb8f1b9449b52c055711922ede6da56fa6606b5e1006bf4d9c0105b34498d025 # 在新节点上执行: sudo kubeadm join 192.168.64.15:6443 --token fhgh1q.y3lit9rx5n9g42pc --discovery-token-ca-cert-hash sha256:eb8f1b9449b52c055711922ede6da56fa6606b5e1006bf4d9c0105b34498d025# 查看节点 kubectl get nodes# 获取 Kubernetes 集群中的组件状态 component statuses kubectl get cs# NAME STATUS MESSAGE ERROR # scheduler Healthy ok # etcd-0 Healthy ok # controller-manager Healthy ok
4. K8S集群网络插件部署 通过上面的步骤, 集群已经初始化完成, 但是节点都还处于not ready状态, 这是是因为scheduler组件还不能完成相关的pod调度. 而这是因为sheduler缺少一些网络插件. 以下三种网络插件可以任选其一.Flannel
: 适用于小规模集群(个位数集群), 适合快速部署和简单网络需求,易于使用,但在安全性和性能上相对较弱Calico
: (10~100), 适合需要强大网络策略和安全性的应用,适合大规模部署,但配置较为复杂
Cilium
: 多集群使用, 适合现代云原生应用,提供高性能和细粒度的安全策略,但对技术要求较高
本文使用Calico网络插件, Calico有两种安装方式, 一种是yaml, 一种是通过operator方式安装, 本文采用operator方式安装, 较为方便
4.1 Calico 安装 1 2 3 4 5 6 7 8 9 10 11 12 13 # 访问官网 https://docs.tigera.io/calico/3.28/about/ # 安装 Tigera Calico operator, 在master节点上操作 kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.2/manifests/tigera-operator.yaml# 查看calico operator是否是运行的状态, 只有是运行的状态才可进行下一步 kubectl get pods -n tigera-operator# tigera-operator-89c775547-57prb 1/1 Running 0 54s # 下载calico的自定义资源配置到本地 wget https://raw.githubusercontent.com/projectcalico/calico/v3.28.2/manifests/custom-resources.yaml# 如果无法下载, 通过浏览器访问后粘贴
修改custom-resources.yaml的第13行, 应与3.2处配置podSubnet网段保持相同
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 1 2 3 apiVersion: operator.tigera.io/v1 4 kind: Installation 5 metadata: 6 name: default 7 spec: 8 9 calicoNetwork: 10 ipPools: 11 - name: default-ipv4-ippool 12 blockSize: 26 13 cidr: 10.244 .0 .0 /16 14 encapsulation: VXLANCrossSubnet 15 natOutgoing: Enabled 16 nodeSelector: all() 17 18 --- 19 20 21 22 apiVersion: operator.tigera.io/v1 23 kind: APIServer 24 metadata: 25 name: default 26 spec: {}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # 应用配置 kubectl create -f custom-resources.yaml# 查看calico pod运行情况 kubectl get pods -n calico-system -o wide# NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES # calico-kube-controllers-74cc68955d-2smdb 1/1 Running 0 15h 10.244.69.194 k8s-worker02 <none> <none> # calico-node-h5j7d 1/1 Running 0 15h 192.168.64.17 k8s-worker02 <none> <none> # calico-node-n9765 1/1 Running 0 15h 192.168.64.16 k8s-worker01 <none> <none> # calico-node-xwbrm 1/1 Running 0 15h 192.168.64.15 k8s-master01 <none> <none> # calico-typha-5d9f58495d-6nhkt 1/1 Running 0 15h 192.168.64.17 k8s-worker02 <none> <none> # calico-typha-5d9f58495d-brgzw 1/1 Running 0 15h 192.168.64.16 k8s-worker01 <none> <none> # csi-node-driver-f8zgg 2/2 Running 0 15h 10.244.69.193 k8s-worker02 <none> <none> # csi-node-driver-qspfg 2/2 Running 0 15h 10.244.32.129 k8s-master01 <none> <none> # csi-node-driver-rtrl9 2/2 Running 0 15h 10.244.79.65 k8s-worker01 <none> <none>
5. 部署应用验证K8S集群的可用性 5.1 验证Core Dns的可用性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 查看core DNS 服务 `kubectl get service -n kube-system` # 结果 kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 17h # 测试可用性 dig -t a www.baidu.com@10.96.0.10# 如果能解析出来, 说明core DNS可用 # ;; ANSWER SECTION: # www.baidu.com\@10.96.0.10. 1INA198.18.0.36 # 否则表示core DNS目前无法使用 # 修改如下文件, 修改DNS 服务器地址 vim /etc/resolv.conf
5.2 部署应用验证 本次使用nginx部署验证
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 apiVersion: apps/v1 kind: Deployment metadata: name: nginxweb spec: selector: matchLabels: app: nginxweb replicas: 2 template: metadata: labels: app: nginxweb spec: containers: - name: nginxwebc image: nginx:latest imagePullPolicy: IfNotPresent ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginxweb-service spec: externalTrafficPolicy: Cluster selector: app: nginxweb ports: - protocol: TCP port: 80 targetPort: 80 nodePort: 30080 type: NodePort
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # 将上述yaml文件保存为nginx.yaml文件, 并使用kubectl部署 kubectl apply -f nginx.yaml# 有如下结果表示部署成功🏅 # deployment.apps/nginxweb created # service/nginxweb-service created # 查看部署的pod, 这里获取到的一个nginx pod的集群ip是10.244.69.196 kubectl get pods -o wide# 集群内访问nginx, 有nginx的页面结果, 则表示成功 curl 10.244.69.196# 集群外访问, 使用集群任意一个节点的IP加上30080端口进行访问 # 在浏览器上访问 http://192.168.64.15:30080 # 有nginx的页面结果, 则表示部署成功🏅
6 常见问题 6.1 科学网络 开启科学上网, 下载相关的依赖时, 才更加方便
使用clash代理时, 需要开启Tun Mode
6.2 ssh操作
打开ssh连接服务(慎重)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 sudo apt-get install openssh-server dpkg -l | grep ssh ps -e | grep ssh 如果看到sshd那说明ssh-server已经启动了。 如果没有则可以这样启动:sudo /etc/init.d/ssh start或sudo service ssh start PermitRootLogin yes 删除sshd_config.d中的子配置 sudo /etc/init.d/ssh stop sudo /etc/init.d/ssh start sudo service ssh restart sudo systemctl enable ssh
tips: 使用scp 命令传输文件
1 2 scp root@node2:/home/ubuntu/cni-plugins-linux-amd64-v1.3.0.tgz ./
6.3 学习路径 Kubernetes学习路径
6.4 虚拟机资源准备 安装multipass, 用于准备集群所需虚拟机: brew install multipass
6.5 kubeadm kubectl kubelet 区别
6.6 其他 kubernetes 系统各个组件调用关系:
首先要明确,一旦 kubernetes 环境启动之后,master 和 node 都会将自身的信息存储到 etcd 数据库中;
一个 nginx 服务的安装请求会首先被发送到 master 节点的 apiServer 组件;
apiServer 组件会调用 scheduler 组件来决定到底应该把这个服务安装到哪个 node 节点上,在此时,它会从 etcd 中读取各个 node 节点的信息,然后按照一定的算法进行选择,并将结果告知 apiServer;
apiServer 调用 controller-manager 去调度 Node 节点安装 nginx 服务;
kubelet 接收到指令后,会通知 docker,然后由 docker 来启动一个 nginx 的 pod,pod 是 kubernetes 的最小操作单元,容器必须跑在 pod 中;
当Pod启动后,一个 nginx 服务就运行了,如果需要访问 nginx,就需要通过 kube-proxy 来对 pod 产生访问的代理 这样,外界用户就可以访问集群中的 nginx 服务了