主机配置

准备了 3 台虚拟机,用于搭建一个 kubernetes 小集群:

IP HOSTNAME OS
192.168.250.100 k8s-master Ubuntu Server 22.04
192.168.250.101 k8s-node-1 Ubuntu Server 22.04
192.168.250.102 K8s-node-2 Ubuntu Server 22.04

安装网络工具

sudo apt install net-tools inetutils-ping dnsutils

禁用 cloud-init 对网络的配置管理

创建一个禁用网络配置的文件:

sudo vim /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg

写入以下配置:

network: {config: disabled}

配置静态 IP

编辑静态网络配置文件:

sudo vim /etc/netplan/99-network-manager.yaml

写入以下配置:

K8s-master

network:
    ethernets:
        ens33:
            dhcp4: false
            addresses:
              - 192.168.250.100/24
            routes:
              - to: default
                via: 192.168.250.2
            nameservers:
                addresses:
                  - 8.8.8.8
                  - 114.114.114.114
    version: 2

K8s-node-1

network:
    ethernets:
        ens33:
            dhcp4: false
            addresses:
              - 192.168.250.101/24
            routes:
              - to: default
                via: 192.168.250.2
            nameservers:
                addresses:
                  - 8.8.8.8
                  - 114.114.114.114
    version: 2

K8s-node-2

network:
    ethernets:
        ens33:
            dhcp4: false
            addresses:
              - 192.168.250.102/24
            routes:
              - to: default
                via: 192.168.250.2
            nameservers:
                addresses:
                  - 8.8.8.8
                  - 114.114.114.114
    version: 2

禁用 cloud-init 对主机名的配置管理

编辑 /etc/cloud/cloud.cfg ,删除以下内容:

- set_hostname
- update_hostname

配置主机名

k8s-master

hostnamectl set-hostname k8s-master

k8s-node-1

hostnamectl set-hostname k8s-node-1

k8s-node-2

hostnamectl set-hostname k8s-node-2

重启生效。

配置时间同步

设置时区

timedatectl set-timezone Asia/Shanghai

同步时间

sudo apt install ntpdate
sudo ntpdate ntp.aliyun.com

配置内核转发及网桥过滤

以下操作均以 root 权限执行。

加载内核模块

cat << EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter

添加配置文件

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

安装 ipset 和 ipvsadm

sudo apt install ipset ipvsadm

配置加载 ipvsadm 模块

cat << EOF | tee /etc/modules-load.d/ipvs.conf
ip_vs
ip_vs_rr
ip_vs_sh
ip_vs_wrr
nf_conntrack
EOF

创建加载模块脚本

cat << EOF | tee ipvs.sh
#/bin/sh
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_sh
modprobe -- ip_vs_wrr
modprobe -- nf_conntrack
EOF

执行该脚本:

sh ipvs.sh

关闭 swap 分区

注释掉 /etc/fstab 中有关 swap 的行即可。

配置 DNS 解析

修改 /etc/hosts 文件如下:

192.168.250.100 k8s-master
192.168.250.101 k8s-node-1
192.168.250.102 K8s-node-2

安装容器管理工具

安装 runc

https://github.com/opencontainers/runc/releases

下载对应架构的 release 文件:

wget https://github.com/opencontainers/runc/releases/download/v1.2.4/runc.amd64

安装:

install -m 755 runc.amd64 /usr/local/sbin/runc

安装 CNI 插件

https://github.com/containernetworking/plugins/releases

下载对应架构的 release 文件:

wget https://github.com/containernetworking/plugins/releases/download/v1.6.2/cni-plugins-linux-amd64-v1.6.2.tgz

创建安装目录:

mkdir -p /opt/cni/bin

解压:

tar -zxvf cni-plugins-linux-amd64-v1.6.2.tgz -C /opt/cni/bin

安装 containerd

https://github.com/containerd/containerd/releases

下载对应架构的 release 文件:

wget https://github.com/containerd/containerd/releases/download/v2.0.2/containerd-2.0.2-linux-amd64.tar.gz

解压合并:

tar -zxvf containerd-2.0.2-linux-amd64.tar.gz -C /usr/local

配置服务自动启动:

wget https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
mkdir -p /usr/local/lib/systemd/system
mv containerd.service /usr/local/lib/systemd/system/
systemctl daemon-reload
systemctl enable --now containerd

生成默认配置文件:

mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml

安装 k8s 相关工具

  • Kubeadm 是一个快捷搭建 k 8 s 的安装工具,它提供了 kubeadm init 以及 kubeadm join 这两个命令来快速创建 kubernetes 集群;
  • Kubelet 是 kubernetes 工作节点上的一个代理组件,运行在每个节点上;
  • Kubectl 是 kubernetes 集群的命令行工具,通过 kubectl 能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署;

添加软件源:

sudo apt install apt-transport-https ca-certificates curl
sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update

安装软件:

sudo apt install kubeadm kubelet kubectl

锁定版本:

sudo apt-mark hold kubelet kubeadm kubectl

配置 cgroup 驱动程序

vim /etc/default/kubelet

写入:

KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"

启动服务:

systemctl enable kubelet

K8s 集群初始化

以下操作只在 master 节点操作。

修改配置文件

打印默认配置文件到文件中:

kubeadm config print init-defaults > kubeadm-config.yaml

修改 advertiseAddress 为 master 节点的 IP 地址,即 192.168.250.100

修改 kubernetesVersion 为与 kubeadm 一致的版本号,我这里是 1.32.1

修改 name 为 master 节点的名称,即 k8s-master

networking 字段下新增 pod 节点的网段:

podSubnet: 10.244.0.0/16  # 这是 Flannel 网络插件的默认网段

拉取基础镜像

查看镜像列表:

kubeadm config images list

拉取基础镜像:

kubeadm config images pull

查看拉取完毕的镜像:

crictl images

补充,出现警告:Image connect using default endpoints: [unix:///run/containerd/containerd.sock unix:///run/crio/crio.sock unix:///var/run/cri-dockerd.sock]. As the default settings are now deprecated, you should set the endpoint instead. 时,使用命令更新 crictl 的配置:crictl config --set runtime-endpoint=unix:///run/containerd/containerd.sock

初始化集群

kubeadm init --config kubeadm-config.yaml

得到 work 节点加入集群的命令:

kubeadm join 192.168.250.100:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:3cce21ea3c365190eb4e81e4c9a82fd85513b8739cae8059120cfe908fc05766

按照提示完成配置:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

加入集群

在 woker 节点上执行以下命令即可加入集群:

kubeadm join 192.168.250.100:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:3cce21ea3c365190eb4e81e4c9a82fd85513b8739cae8059120cfe908fc05766

安装 Flannel 网络插件

在 master 节点上执行:

wget https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
kubectl apply -f kube-flannel.yml

插件起来之后,3 个节点就都进入 ready 状态了:

验证集群可用性

检查 core-dns

kubectl get service -n kube-system

分别在 3 个节点上尝试使用这个 dns 服务:

dig -t a baidu.com @10.96.0.10

表明 core-dns 服务正常。

部署 nginx 服务并从集群外访问

编写服务部署脚本:nginx-web.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-web
  template:
    metadata:
      labels:
        app: nginx-web
    spec:
      containers:
        - name: nginx-web
          image: nginx:latest
          ports:
            - containerPort: 80

编写 service 部署脚本:nginx-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  externalTrafficPolicy: Cluster
  selector:
    app: nginx-web		# 关联容器的标签
  ports:
  - port: 80			# 容器端口
    nodePort: 30080		# nodeport映射到30080端口,便于外部主机访问
  type: NodePort		# svc类型为nodeport

执行以下命令开始部署:

kubectl apply -f nginx-web.yaml
kubectl apply -f nginx-svc.yaml

查看部署情况:

kubectl get deployment
kubectl get service

集群内可通过 10.107.44.163:80 访问 nginx 服务:

对于集群外的主机,可通过任意一个集群内节点的 IP + 30080 端口访问 nginx 服务:

master 节点:

node-1 节点:

node-2 节点: