kubernetes,简称K8s,是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。
现在有三台服务器,利用K8s平台去部署Milvus向量数据库集群。
如果不能联网部署国内下载很多镜像源比较慢,我有打包好的所有镜像包,当时部署的时候在线部的,很多包和镜像无法下载,费了好大的时间,避免小伙伴们走弯路了。 可以自取:pan.quark.cn/s/cffcfff51... 所有镜像如下,也有部分官方版配置文件。
镜像列表:
bash
zilliz/attu latest 73849ad58bcd 10 days ago 400MB
milvusdb/milvus-operator v1.2.6 7e269175ad7d 4 weeks ago 171MB
nginx <none> be69f2940aaf 2 months ago 192MB
nginx latest 1e5f3c5b981a 2 months ago 192MB
curlimages/curl latest e507f3e43db3 2 months ago 21.9MB
milvusdb/etcd 3.5.18-r1 3d5a605ebc2c 3 months ago 208MB
portainer/portainer-ce 2.26.1 7d3e080bece2 4 months ago 263MB
portainer/agent 2.26.1 b276075e87c2 4 months ago 169MB
milvusdb/milvus v2.4.15 278de20b4f8d 7 months ago 1.6GB
apachepulsar/pulsar 3.0.7 a8e8ebdf8cc4 8 months ago 1.17GB
calico/kube-controllers v3.28.0 428d92b02253 13 months ago 79.1MB
calico/cni v3.28.0 107014d9f4c8 13 months ago 209MB
calico/node v3.28.0 4e42b6f329bc 13 months ago 353MB
calico/cni v3.27.1 0a3c86aaae6d 16 months ago 195MB
calico/node v3.27.1 c2fe8805d436 16 months ago 343MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver v1.28.0 bb5e0dde9054 22 months ago 126MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler v1.28.0 f6f496300a2a 22 months ago 60MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager v1.28.0 4be79c38a4ba 22 months ago 122MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy v1.28.0 ea1030da44aa 22 months ago 73.1MB
quay.io/jetstack/cert-manager-webhook v1.12.3 0bb25d0572e1 23 months ago 48.9MB
calico/cni v3.26.1 9dee260ef7f5 2 years ago 210MB
calico/node v3.26.1 8065b798a4d6 2 years ago 246MB
calico/typha v3.26.0 0be6373f732b 2 years ago 70.2MB
calico/kube-controllers v3.26.0 45ae357729e3 2 years ago 77.4MB
calico/cni v3.26.0 5d6f5c26c655 2 years ago 210MB
calico/node-driver-registrar v3.26.0 f26b4a3a9c76 2 years ago 25.3MB
calico/csi v3.26.0 151c86d530ac 2 years ago 20.2MB
calico/pod2daemon-flexvol v3.26.0 d9eeedbe7ebb 2 years ago 14.8MB
calico/node v3.26.0 44f52c09dece 2 years ago 248MB
registry.cn-hangzhou.aliyuncs.com/google_containers/etcd 3.5.9-0 73deb9a3f702 2 years ago 294MB
minio/minio RELEASE.2023-03-20T20-16-18Z 400c20c8aac0 2 years ago 252MB
registry.cn-hangzhou.aliyuncs.com/google_containers/coredns v1.10.1 ead0a4a53df8 2 years ago 53.6MB
calico/cni v3.25.0 d70a5947d57e 2 years ago 198MB
calico/node v3.25.0 08616d26b8e7 2 years ago 245MB
registry.aliyuncs.com/google_containers/pause 3.9 e6f181688397 2 years ago 744kB
registry.cn-hangzhou.aliyuncs.com/google_containers/pause 3.9 e6f181688397 2 years ago 744kB
kubernetesui/dashboard v2.7.0 07655ddf2eeb 2 years ago 246MB
kubernetesui/metrics-scraper v1.0.8 115053965e86 3 years ago 43.8MB
ini
集群完成后信息:
MILVUS集群
Master:192.168.20.1 Worker:192.168.20.2/3
milvus:v2.4.15
mmilvusdb/milvus-operator:v1.2.6
Docker Engine - Community Version:26.1.3
Kubernetes:v1.28.0
http://192.168.20.1:8000
http://192.138.20.1:9000/

# 一、服务器信息
1.确保/空间不少于 200G
三台服务器部署龙蜥8.10系统(欧拉也可以,软件仓库略不同)
主要服务业务:k8s-master nfs-server portainer-server attu-server
IP 192.168.20.1 k8s-node1
192.168.20.2 k8s-node2
192.168.20.3 k8s-node3
## 二、部署步骤
## 1.服务初始化(三台均执行)
配置网卡为 bond4
```shell
cd /etc/sysconfig/network-scripts/
vi ifcfg-bond0
DEVICE=bond0
NAME=bond0
TYPE=Bond
BONDING_MASTER=yes
IPADDR=192.168.20.1
NETMASK=255.255.255.0
GATEWAY=192.168.20.254
ONBOOT=yes
BOOTPROTO=static
BONDING_OPTS="mode=1 miimon=100"
vi ifcfg-ens1f1
##增加
MASTER=bond0
SLAVE=yes
vi ifcfg-ens1f0
##增加
MASTER=bond0
SLAVE=yes
service network restart
shell
sed -i 's/^#UseDNS yes/UseDNS no/g' /etc/ssh/sshd_config
systemctl restart sshd ##关闭 SSH 的 DNS 反向解析功能,以此加快 SSH 连接的速度。
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config ##暂时关闭 SELinux,并对配置文件进行修改,使 SELinux 在系统重启之后仍保持禁用状态。
yum -y install wget net-tools ntpdate
ntpdate ntp.aliyun.com ##安装网络工具和时间同步工具,并且进行一次时间同步操作。
# 创建或更新Docker仓库配置文件
cat > /etc/yum.repos.d/docker-ce.repo << EOF
[docker-ce-stable]
name=Docker CE Stable - \$basearch
baseurl=https://download.docker.com/linux/centos/8/\$basearch/stable
enabled=1
gpgcheck=1
gpgkey=https://download.docker.com/linux/centos/gpg
EOF
# 清理并重建缓存
yum clean all
yum makecache
# 安装Docker CE
yum install -y docker-ce docker-ce-cli containerd.io
##yum install container-selinux
##yum install libcgroup
##yum install containerd.io
# 启动并启用Docker服务
systemctl start docker
systemctl enable docker
yum install -y docker-engine
mkdir -p /etc/docker
cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://dockerproxy.net/"]
}
EOF
systemctl restart docker
yum install -y yum-utils device-mapper-persistent-data lvm2 cifs-utils nfs-utils
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo(centos7)
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo(centos 8)
# 替换仓库文件中的路径
sed -i 's/\$releasever/8/g' /etc/yum.repos.d/docker-ce.repo
yum install -y docker-ce-20.10.24-3.el7 docker-ce-cli-20.10.24-3.el7 containerd.io-1.5.11-3.1.el7
yum clean all
yum makecache
# 安装最新版本(推荐)
yum install -y docker-ce docker-ce-cli containerd.io
这个命令安装的是 Docker 官方社区版(Docker CE) 的核心组件:
docker-ce
Docker 主服务(守护进程 dockerd)
提供完整的容器运行时环境
包含 REST API 接口、网络管理、存储管理等功能
版本号格式:3:26.1.3-1.el8(当前最新版)
docker-ce-cli
Docker 命令行工具(docker 命令)
用于与 Docker 守护进程交互
执行 docker run/build/pull 等操作
containerd.io
容器运行时核心引擎(containerd 守护进程)
管理容器的生命周期(创建/启动/停止容器)
处理镜像下载和存储
提供标准的 CRI(容器运行时接口)
✅ 完整工作流:
docker cli → dockerd → containerd → 运行容器
systemctl start docker
systemctl enable /usr/lib/systemd/system/docker.service ##安装 Docker 相关组件,添加 Docker 官方仓库,然后安装特定版本的 Docker。
yum install -y iptables iptables-services
systemctl stop iptables.service && systemctl disable iptables.service
systemctl stop firewalld.service && systemctl mask firewalld.service
systemctl restart docker ##停用 CentOS 的默认防火墙,防止其与 Docker 的网络配置产生冲突。
systemctl start docker
docker --version
# 应显示:Docker version 20.10.24, build 297e128
补充说明:
Anolis OS 8 完全兼容 RHEL 8/CentOS 8,因此使用 RHEL 8 的 Docker 包是安全的
如果遇到依赖问题,可先安装:
bash
yum install -y device-mapper-persistent-data lvm2
如果防火墙开启,记得开放 Docker 端口:
bash
firewall-cmd --add-port=2375/tcp --permanent
firewall-cmd --reload
关闭 SWAP 分区
shell
sed -ri 's/.*swap.*/#&/' /etc/fstab
修改linux的内核采纳数,添加网桥过滤和地址转发功能
shell
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
vm.swappiness = 0
EOF
# 加载br_netfilter模块
modprobe br_netfilter
# 查看是否加载
lsmod | grep br_netfilter
# 生效
sysctl --system
磁盘raid5 初始化
bash
sudo wipefs -a /dev/md124
sudo parted /dev/md124 mklabel gpt # 创建GPT分区表
Information: You may need to update /etc/fstab.
# sudo parted /dev/md124 mkpart primary xfs 0% 100% # 创建完整分区
Information: You may need to update /etc/fstab.
# sudo mkfs.xfs /dev/md124p1 #格式化分区
meta-data=/dev/md124p1 isize=512 agcount=32, agsize=41756248 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=0
= reflink=1 bigtime=1 inobtcount=0
data = bsize=4096 blocks=1336199936, imaxpct=5
= sunit=8 swidth=24 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=521728, version=2
= sectsz=512 sunit=8 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
sudo mkfs.xfs -f /dev/md124p1 #格式化分区
# sudo mkdir /data
# sudo mount /dev/md124p1 /data
# sudo blkid -s UUID -o value /dev/md124p1 # 查看新文件系统UUID
vi /etc/fstab
UUID=820e32b8-c461-4ebe-869a-d38da5ef0e0d /data xfs defaults 0 0
修改服务器对应主机名
shell
hostnamectl set-hostname k8s-node1 ##主机1上执行
hostnamectl set-hostname k8s-node2 ##主机2上执行
hostnamectl set-hostname k8s-node3 ##主机3上执行
vi /etc/hosts ##三台机器均进行修改
192.168.20.1 k8s-node1
192.168.20.2 k8s-node2
192.168.20.3 k8s-node3
安装cri-docker
shell
cri-dockerd 是一个 Kubernetes CRI(容器运行时接口)适配器,主要作用:
解决 Kubernetes 与 Docker 的兼容问题
Kubernetes 从 v1.24 版本开始移除了内置的 dockershim
使得 Kubernetes 无法直接使用 Docker 作为容器运行时
核心功能
实现 Kubernetes CRI 接口
将 Kubernetes 的指令翻译成 Docker 能理解的命令
允许 Kubernetes 继续使用 Docker 引擎运行容器
如果只需运行 Docker 容器 → 只需 Docker CE
如果要在 Kubernetes 集群中使用 Docker → 需要 Docker CE + cri-dockerd
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.2/cri-dockerd-0.3.2-3.el8.x86_64.rpm(centos 8)
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.2/cri-dockerd-0.3.2-3.el7.x86_64.rpm(centos 7)
yum install tar
rpm -ivh cri-dockerd-0.3.2-3.el7.x86_64.rpm
# 配置 Kubernetes 使用 cri-dockerd
kubeadm init --cri-socket unix:///var/run/cri-dockerd.sock
##编辑 /etc/yum.repos.d/docker-ce.repo 文件,确保配置正确并且尝试使用 HTTP 协议(如果 SSL 连接仍然有问题):
##bash
##sudo vi /etc/yum.repos.d/docker-ce.repo
##如果无法访问 github
cd ~/k8s ##提前将安装包拷贝至~下
rpm -ivh cri-dockerd-0.3.2-3.el7.x86_64.rpm
修改docker镜像源
shell
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://dockerproxy.net/"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
# 检查Docker是否使用镜像源
sudo systemctl restart NetworkManager
docker info | grep Mirrors -A 1
导入k8s及milvus常用镜像
shell
cd ~/k8s
修改cri-docker服务依赖镜像,并设置开机自启动
shell
vi /usr/lib/systemd/system/cri-docker.service
##修改第十行
10 ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9
11 ......
systemctl daemon-reload
systemctl start cri-docker
systemctl enable cri-docker
配置阿里云的k8s源
bash
2. 配置 Kubernetes 仓库
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
EOF
shell
vi /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
安装 kubeadm 和 kubelet
shell
yum install -y kubeadm-1.28.0 kubelet-1.28.0
systemctl enable kubelet
2.部署 k8s
主机 k8s 初始化
shell
自加:设置内核参数:
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system 自加
kubeadm init \
--apiserver-advertise-address=192.168.20.1 \
--image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--kubernetes-version=v1.28.0 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.96.0.0/12 \
--cri-socket=unix:///var/run/cri-dockerd.sock
部署完后按照提示配置
shell
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
export KUBECONFIG=/etc/kubernetes/admin.conf
####
###### mkdir -p $HOME/.kube:
这个命令会在你的用户主目录下创建一个名为 .kube 的目录(如果该目录不存在的话)。-p 选项表示如果父目录不存在则创建父目录,这样可以确保目录结构正确创建。
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config:
此命令使用 sudo 以管理员权限运行,将 /etc/kubernetes/admin.conf 文件复制到 $HOME/.kube/config。-i 选项表示在覆盖目标文件之前进行提示,但由于你使用的是 $HOME/.kube/config 这个文件名(假设该文件之前不存在),所以不会有提示直接复制。这个 admin.conf 文件包含了与 Kubernetes 集群进行通信所需的认证和配置信息。
sudo chown $(id -u):$(id -g) $HOME/.kube/config:
该命令同样使用 sudo 以管理员权限运行,将 $HOME/.kube/config 文件的所有者和所属组设置为当前用户。$(id -u) 获取当前用户的用户 ID,$(id -g) 获取当前用户的组 ID。这样可以确保你作为普通用户也能访问和使用这个配置文件。
export KUBECONFIG=/etc/kubernetes/admin.conf:
这个命令将 KUBECONFIG 环境变量设置为 /etc/kubernetes/admin.conf。KUBECONFIG 环境变量用于告诉 kubectl 工具使用哪个配置文件来连接到 Kubernetes 集群。在这一步中,你是 root 用户(因为只有 root 用户才有权限访问 /etc/kubernetes/admin.conf),通过设置这个环境变量,后续运行 kubectl 命令时,它会读取这个配置文件来与集群交互。
##执行位置:
这些命令需要在Master 节点(控制平面节点)上执行,因为只有 Master 节点才会在/etc/kubernetes/admin.conf路径下生成集群管理员配置文件。
为什么 Worker 节点不需要执行这些命令?
Worker 节点的主要职责是运行 Pod,不需要直接操作集群 API(除非特殊需求)。
kubectl是 Kubernetes 的命令行工具,通常只在需要管理集群的节点上安装和配置(如 Master 节点或开发人员的工作站)。
echo 'export KUBECONFIG=/etc/kubernetes/admin.conf' >> ~/.bashrc
source ~/.bashrc
备机执行加入主机操作
powershell
# sysctl --system --dry-run | grep ip_forwardnet.ipv4.ip_forward = 0
net.ipv4.ip_forward = 1
net.ipv4.ip_forward = 0
```shell
net.ipv4.ip_forward=1 这个修改为1
css
```powershell
sysctl --system --dry-run | grep ip_forward # 应该只看到 net.ipv4.ip_forward = 1
shell
kubeadm join 192.168.20.1:6443 --token xxxxxxxx --discovery-token-ca-cert-hash sha256:xxxxxxx \
--cri-socket=unix:///var/run/cri-dockerd.sock
修改对应 token 和 hash
## k8s 考虑安全性, "kubeadm join" 命令中 token 有效时间为 24 小时,过期后不可以再使用,但是可以使用 " kubeadm token create --print-join-command " 命令来创建新的 Token ,以添加新的 node 节点。
powershell
主节点执行 kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-node1 Ready control-plane 21h v1.28.0
k8s-node2 Ready <none> 81s v1.28.0
k8s-node3 Ready <none> 71s v1.28.0
在部署 Kubernetes 集群时,主机(Master 节点)和备机(Worker 节点)需要执行不同的操作。有一部分是所有节点(包括 Master 和 Worker)都需要执行的,而另一部分则仅适用于 Master 节点。确定将 Pod(应用的运行单元)。
所有节点(Master 和 Worker)都需要执行的操作
这些操作是集群节点的基础环境配置,必须在所有机器上执行:
bash
bash
# 1. 加载必要的内核模块
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 2. 配置系统参数
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
# 3. 关闭Swap分区(Kubernetes要求)
sudo swapoff -a
sudo sed -i '/swap/d' /etc/fstab
# 4. 安装容器运行时(如Docker + cri-dockerd)
# 5. 安装kubeadm、kubelet和kubectl
仅 Master 节点需要执行的操作
这些命令用于初始化集群,不要在 Worker 节点上执行:
bash
bash
# 初始化Master节点(仅在主控制平面节点执行)
kubeadm init \
--apiserver-advertise-address=192.168.20.1 \
--image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--kubernetes-version=v1.28.0 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.96.0.0/12 \
--cri-socket=unix:///var/run/cri-dockerd.sock
Worker 节点(备机)需要执行的操作
Worker 节点在完成基础环境配置后,需要通过kubeadm join命令加入集群。这个命令的参数由 Master 节点初始化后输出,类似这样:
bash
bash
# 从Master节点初始化输出中获取token和哈希值
# 示例命令(实际参数以Master节点输出为准)
kubeadm join 192.168.20.1:6443 --token xxxxxxxx --discovery-token-ca-cert-hash sha256:xxxxxxx \
--cri-socket=unix:///var/run/cri-dockerd.sock
注意事项
-
kubeadm init的输出会包含 Worker 节点加入所需的命令,务必妥善保存。 -
如果丢失了 join 命令,可以在 Master 节点上重新生成 token:
bash
bashkubeadm token create --print-join-command -
确保所有节点之间网络互通,特别是 Master 节点的 API 服务器地址(
192.168.20.1)可访问。
部署网络插件(仅在主机执行)
shell
cd ~/k8s
##通过如下命令下载
##wget https://raw.githubusercontent.com/projectcalico/calico/v3.26.0/manifests/tigera-operator.yaml
kubectl create -f tigera-operator.yaml
cd ~/k8s/yaml
##通过如下命令下载
##wget https://raw.githubusercontent.com/projectcalico/calico/v3.26.0/manifests/custom-resources.yaml
kubectl create -f custom-resources.yaml
注意需要修改此配置文件
10.244.0.0/16 # 匹配 kubeadm 的 pod-network-cidr
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml (这个正确)
注意:
1、无论是calico-3.27.3.yaml还是calico-custom-resources.yaml都必须使用create不要使用apply生效创建资源,否则会报错
官方文档有写:Due to the large size of the CRD bundle, kubectl apply might exceed request limits. Instead, use kubectl create or kubectl replace.
允许master节点参与任务调度(如果worker节点多的话 可以不执行)
shell
kubectl taint nodes mam-milvus-11 node-role.kubernetes.io/control-plane:NoSchedule-
## node/mam-milvus-11 untainted
###kubectl taint nodes MAM-MILVUS-11 node-role.kubernetes.io/control-plane:NoSchedule- 这条命令用于从名为 MAM-MILVUS-11 的节点上去除 node-role.kubernetes.io/control-plane:NoSchedule 这个污点(taint)。
下面详细解释:
kubectl taint nodes:这是 kubectl 用于管理节点污点的命令,taint 操作涉及到节点的污点设置,而 nodes 指明操作对象是节点。
MAM-MILVUS-11:表示要操作的节点名称,即对名为 MAM-MILVUS-11 的节点进行操作。
node-role.kubernetes.io/control-plane:NoSchedule:这是一个污点的键值对及效果描述。node-role.kubernetes.io/control-plane 是污点的键(key),NoSchedule 是污点的值(effect),NoSchedule 意味着默认情况下 Pod 不会被调度到带有这个污点的节点上。
-:在污点键值对后面的 - 表示删除指定的污点,即从 MAM-MILVUS-11 节点上移除 node-role.kubernetes.io/control-plane:NoSchedule 这个污点。
一般来说,在 Kubernetes 中,控制平面节点(control-plane node)会被打上 node-role.kubernetes.io/control-plane:NoSchedule 污点,以防止普通的 Pod 被调度到这些节点上,确保控制平面组件有足够的资源运行。当你想要在控制平面节点上调度普通 Pod 等情况时,就需要移除这个污点,上述命令就是用于完成这个操作的。
部署 k8s dashbard
shell
cd ~/k8s/yaml
##通过如下命令下载
##wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
##下载后修改 40 行类型为 NodePort,增加 nodePort 端口为 30001
##【spec:
type: NodePort # 修改服务类型为NodePort
ports:
- port: 443
targetPort: 8443
nodePort: 30001 # 增加nodePort字段并指定端口为30001
selector:
k8s-app: kubernetes-dashboard
】
kubectl apply -f recommended.yaml
kubectl create serviceaccount admin-user -n kubernetes-dashboard
kubectl create clusterrolebinding admin-user --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:admin-user
kubectl create token admin-user -n kubernetes-dashboard
kubectl create serviceaccount admin-user -n kubernetes-dashboard serviceaccount/admin-user created kubectl create clusterrolebinding admin-user --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:admin-user clusterrolebinding.rbac.authorization.k8s.io/admin-user created
powershell
```powershell
# kubectl create token admin-user -n kubernetes-dashboard
powershell
# 部署Calico CRDs(v3.28.0)
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/crds.yaml
# 部署Calico核心组件
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/calico.yaml
# 验证Calico组件状态(等待所有Pod Running)
watch kubectl get pods -n kube-system -l k8s-app=calico-node
``
重启kubelet
powershell
systemctl restart kubelet
下载最新Dashboard配置(v2.7.0)
powershell
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml -O dashboard.yaml
# 部署Dashboard
修改 40 行类型为 NodePort,增加 nodePort 端口为 30001
##【spec:
type: NodePort # 修改服务类型为NodePort
ports:
- port: 443
targetPort: 8443
nodePort: 30001 # 增加nodePort字段并指定端口为30001
selector:
k8s-app: kubernetes-dashboard
】
kubectl apply -f dashboard.yaml
# 验证Dashboard状态(等待Pod Running)
watch kubectl get pods -n kubernetes-dashboard
# 查看Calico IP池状态
kubectl get ippool default-ipv4-ippool -o yaml
# 查看Dashboard日志(确保无错误)
kubectl logs -n kubernetes-dashboard <dashboard-pod-name>
# 测试Dashboard访问(端口转发)
kubectl port-forward -n kubernetes-dashboard service/kubernetes-dashboard 8080:443
通过浏览器访问 https://localhost:8080(忽略证书警告)
``
常用命令
powershell
kubectl get pods -A ##查看所有pods运行情况
kubectl get pods -n kubernetes-dashboard ##查看k8s面板运行情况
kubectl get nodes ##查看所有节点运行情况
kubectl get svc ##查看所有服务运行情况
kubectl create token admin-user -n kubernetes-dashboard ##获取dashboard新的token
3.部署milvus
master节点创建nfs共享
shell
yum install nfs-utils
systemctl enable --now nfs-server.service #enable --now 会同时启用(开机自启)并立即启动服务。
mkdir -p /data/share
chmod -R 777 /data/share
vi /etc/exports
/data/share 192.168.20.0/24(rw,sync,no_subtree_check,no_root_squash)
systemctl restart nfs-server.service
创建nfs组件
shell
cd ~/k8s/yaml
##通过如下命令下载
##错误的wget https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner/blob/master/deploy/rbac.yaml
wget https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner/blob/master/deploy/rbac.yaml 这条命令下载的可能不是真正的 YAML 文件内容,而是网页内容,因为 github.com 上的 blob 页面是网页展示,不是直接提供原始文件下载。
正确的下载方式是使用 raw.githubusercontent.com 来获取原始文件
wget https://raw.githubusercontent.com/kubernetes-sigs/nfs-subdir-external-provisioner/master/deploy/rbac.yaml
kubectl apply -f rbac.yaml
作用:配置基于角色的访问控制 (RBAC)
包含资源:
ServiceAccount:为供应器创建一个专用身份
ClusterRole:定义供应器需要的权限(如管理 PV/PVC)
ClusterRoleBinding:将权限绑定到服务账号
部署 NFS 客户端供应器:创建实际运行的供应器 Deployment。
配置 StorageClass:定义如何动态创建存储卷。
wget https://raw.githubusercontent.com/kubernetes-sigs/nfs-subdir-external-provisioner/master/deploy/deployment.yaml
wget https://raw.githubusercontent.com/kubernetes-sigs/nfs-subdir-external-provisioner/master/deploy/class.yaml
编辑 deployment.yaml,替换其中的 NFS 服务器和共享目录信息:
# 修改以下两行,指向你的 NFS 服务器和共享目录
args:
- "-nfs-server=YOUR_NFS_SERVER_IP" # 替换为你的 NFS 服务器 IP
- "-nfs-path=/YOUR_SHARED_DIRECTORY" # 替换为你的 NFS 共享目录路径
应用配置
# 部署 NFS 客户端供应器
kubectl apply -f deployment.yaml
用:部署供应器本身(核心组件)
关键配置:
yaml
args:
- "-nfs-server=192.168.1.100" # 替换为你的 NFS 服务器 IP
- "-nfs-path=/share/milvus-data" # 替换为你的 NFS 共享路径
包含资源:
Deployment:运行供应器的 Pod
通过环境变量指定供应器名称(如 PROVISIONER_NAME=nfs-client)
为什么需要:
这是实际运行在集群中的组件,负责动态创建 NFS 子目录并绑定到 PV
# 创建 StorageClass
kubectl apply -f class.yaml
# 检查 Pod 是否运行
在 deployment.yaml 的 Pod 模板中,明确定义了标签:
yaml
metadata:
labels:
app: nfs-client-provisioner # 关键标签
因此,必须使用 app=nfs-client-provisioner 作为筛选条件,才能正确匹配到 Pod。
验证当前状态(用户当前环境)
根据用户之前的输出:
bash
kubectl get deployment nfs-client-provisioner -n default
# 显示 READY 1/1,说明 Pod 已正常运行
# 检查 StorageClass 是否创建
kubectl get storageclass
测试动态存储卷
创建一个简单的 PVC(PersistentVolumeClaim)测试:
# test-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: nfs-client # 使用你创建的 StorageClass 名称
resources:
requests:
storage: 1Gi
应用并验证:
kubectl apply -f test-pvc.yaml
# 检查 PVC 状态
kubectl get pvc test-pvc
如果状态变为 Bound,说明动态存储卷创建成功!
其中:deployment.yaml,修改对应的nfs信息
shell
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
# 镜像地址国内访问不到,需要更换为其他地址
#image: k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
image: willdockerhub/nfs-subdir-external-provisioner:v4.0.2
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
# provisioner的名字,可以自定义,要和class.yaml中保持一致
- name: PROVISIONER_NAME
value: k8s-sigs.io/nfs-subdir-external-provisioner
# nfs服务器的地址
- name: NFS_SERVER
value: 192.168.20.1
# nfs共享的目录
- name: NFS_PATH
value: /data/share
volumes:
- name: nfs-client-root
nfs:
# nfs服务器的地址
server: 192.168.20.1
# nfs共享的目录
path: /data/share
创建storageclass.yaml
自己创建 storageclass.yaml 文件,你可以参考以下示例创建一个针对 nfs-client 的 StorageClass 配置(确保 nfs-client 存储类的 Provisioner 配置正确):
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-client provisioner: k8s-sigs.io/nfs-subdir-external-provisioner parameters: archiveOnDelete: "false" reclaimPolicy: Delete volumeBindingMode: Immediate allowVolumeExpansion: false
shell
kubectl apply -f storageclass.yaml
- rbac.yaml 👉 先执行:
kubectl apply -f rbac.yaml📌 原因:供应器需要权限才能运行 - deployment.yaml 👉 其次执行:
kubectl apply -f deployment.yaml📌 原因:启动供应器 Pod,但需要 RBAC 权限 - class.yaml 👉 最后执行:
kubectl apply -f class.yaml📌 原因:存储类依赖于供应器已就绪
设置nfs-client为默认sc
shell
kubectl patch storageclass nfs-client -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
Milvus Operator 使用 cert-manager(opens in a new tab) 为 webhook 服务器提供证书。运行以下命令安装 cert-manager。
shell
##也可以执行如下操作:
cd ~/k8s/yaml
建议使用 Cert-Manager v1.12.3(当前稳定版本),它与 Kubernetes 1.28 完全兼容:
# 安装最新稳定版 Cert-Manager
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.12.3/cert-manager.yaml
kubectl apply -f cert-manager.yaml
# kubectl get pods -n cert-manager
# kubectl get pods -n cert-manager
NAME READY STATUS RESTARTS AGE
cert-manager-679895f5-5hnps 1/1 Running 0 29s
cert-manager-cainjector-b78544fd4-dd42z 1/1 Running 0 29s
cert-manager-webhook-cd8bbbd67-9gz57 1/1 Running 0 29s
安装Milvus Operator
通过kubectl apply -f deployment.yaml来部署Operator,通常,Operator的部署需要先应用CRD,然后再部署Operator的Deployment。
bash
vi milvus-crd.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: milvuses.milvus.io
spec:
group: milvus.io
names:
kind: Milvus
listKind: MilvusList
plural: milvuses
singular: milvus
scope: Namespaced
versions:
- name: v1beta1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
x-kubernetes-preserve-unknown-fields: true
status:
type: object
x-kubernetes-preserve-unknown-fields: true
shell
kubectl apply -f https://raw.githubusercontent.com/zilliztech/milvus-operator/main/deploy/manifests/deployment.yaml
##也可以执行如下操作:
cd ~/k8s
wget https://raw.githubusercontent.com/zilliztech/milvus-operator/main/deploy/manifests/deployment.yaml
kubectl apply -f deployment.yaml
推荐使用 Helm 方式安装,因为它会自动处理依赖关系和镜像下载
ruby
```powershell
# 下载 Helm 安装脚本
```powershell
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
``
```bash
helm upgrade --install milvus-operator -n milvus-operator --create-namespace https://github.com/zilliztech/milvus-operator/releases/download/v1.2.6/milvus-operator-1.2.6.tgz
ruby
根据文档,Milvus Operator 的镜像托管在 GitHub 上:[1](https://milvus.io/docs/install_cluster-milvusoperator.md#Install-Milvus-Operator)[2](https://github.com/zilliztech/milvus-operator/tree/main/docs)
- **GitHub Releases**: `https://github.com/zilliztech/milvus-operator/releases/download/v1.2.0/milvus-operator-1.2.0.tgz` [1](https://milvus.io/docs/install_cluster-milvusoperator.md#Install-Milvus-Operator)
- **GitHub 部署清单**: `https://raw.githubusercontent.com/zilliztech/milvus-operator/main/deploy/manifests/deployment.yaml`
-
部署milvus默认集群
```shell
kubectl apply -f https://raw.githubusercontent.com/zilliztech/milvus-operator/main/config/samples/milvus_cluster_default.yaml
##也可以执行如下操作:
cd /k8s/yaml
wget https://raw.githubusercontent.com/zilliztech/milvus-operator/main/config/samples/milvus_cluster_default.yaml
kubectl apply -f milvus_cluster_default.yaml
基于实际情况调整milvus集群
shell
使用 Milvus Sizing Tool 根据你的实际数据大小调整配置,然后下载相应的 YAML 文件。要了解有关配置参数的更多信息,请参阅 Milvus 系统配置清单。
选择配置后下载 yml 文件至服务器的/root/k8s/yaml 下
https://milvus.io/zh/tools/sizing 选择Milvus操作员进行下载yml配置文件。
cd ~/k8s/yaml
kubectl apply -f operatorConfigYml.yml
我将两个配置文档整合到了一个yml文件里,我是用的服务器性能比较高,所以各有不同。
bash
apiVersion: milvus.io/v1beta1
kind: Milvus
metadata:
name: my-release
labels:
app: milvus
spec:
mode: cluster
components:
# 指定 Milvus 2.4 版本镜像
image: milvusdb/milvus:v2.4.15
# 组件配置
mixCoord:
replicas: 1
resources:
limits:
cpu: 1
memory: 4Gi
indexNode:
replicas: 1
resources:
limits:
cpu: 2
memory: 8Gi
proxy:
replicas: 1
resources:
limits:
cpu: 1
memory: 4Gi
dataNode:
replicas: 2
resources:
limits:
cpu: 2
memory: 8Gi
queryNode:
replicas: 2
resources:
limits:
cpu: 2
memory: 8Gi
config: {}
dependencies:
etcd:
external: false
inCluster:
deletionPolicy: Retain
pvcDeletion: false
values:
autoCompactionMode: revision
autoCompactionRetention: "1000"
extraEnvVars:
- name: ETCD_QUOTA_BACKEND_BYTES
value: "4294967296"
- name: ETCD_HEARTBEAT_INTERVAL
value: "500"
- name: ETCD_ELECTION_TIMEOUT
value: "25000"
- name: ETCD_SNAPSHOT_COUNT
value: "10000"
- name: ETCD_ENABLE_PPROF
value: "true"
persistence:
accessMode: ReadWriteOnce
enabled: true
size: 20Gi
storageClass: "nfs-client"
replicaCount: 3
resources:
limits:
cpu: 1
memory: 4Gi
requests:
cpu: 1
memory: 4Gi
pulsar:
external: false
inCluster:
deletionPolicy: Retain
pvcDeletion: false
values:
proxy:
replicaCount: 2
configData:
httpNumThreads: "100"
zookeeper:
replicaCount: 3
volumes:
persistence: true
data:
name: data
size: 30Gi
storageClassName: "nfs-client"
resources:
requests:
memory: 2Gi
cpu: 0.5
bookkeeper:
replicaCount: 3
volumes:
journal:
name: journal
size: 1.5Gi
storageClassName: "nfs-client"
ledgers:
name: ledgers
size: 20Gi
storageClassName: "nfs-client"
resources:
requests:
memory: 8Gi
cpu: 1
broker:
component: broker
podMonitor:
enabled: false
replicaCount: 2
resources:
requests:
memory: 4Gi
cpu: 1
storage:
external: false
type: "MinIO"
inCluster:
deletionPolicy: Retain
pvcDeletion: false
values:
mode: distributed
resources:
limits:
cpu: 1
memory: 8Gi
persistence:
storageClass: "nfs-client"
accessMode: ReadWriteOnce
size: 30Gi
将milvus集群转发至外部端口
shell
19530:Milvus 的主要 gRPC 和 RESTful API 端口 1
9091:管理端口,用于指标收集、性能分析和健康检查 1
关于端口 9091 和 32575 的作用
根据文档,Milvus 支持两个端口:1
端口 19530:用于 gRPC 和 RESTful API,这是使用不同 Milvus SDK 或 HTTP 客户端连接到 Milvus 服务器时的默认端口 1
端口 9091:管理端口,用于在 Kubernetes 中进行指标收集、pprof 性能分析和健康探测 1
建议使用的配置
建议使用更完整的配置:
cat milvus-nodeport-service.yaml
apiVersion: v1
kind: Service
metadata:
name: milvus-nodeport
spec:
type: NodePort
selector:
app.kubernetes.io/name: milvus
app.kubernetes.io/instance: my-release
component: proxy
ports:
- name: milvus
port: 19530
targetPort: 19530
nodePort: 32574
protocol: TCP
- name: webui
port: 9091
targetPort: 9091
nodePort: 32575
protocol: TCP
修正:
yaml
apiVersion: v1
kind: Service
metadata:
name: milvus-nodeport-correct
spec:
type: NodePort
selector:
app.kubernetes.io/name: milvus
app.kubernetes.io/instance: my-release
app.kubernetes.io/component: proxy
ports:
- name: milvus
port: 19530
targetPort: 19530
nodePort: 32574
protocol: TCP
- name: webui
port: 9091
targetPort: 9091
nodePort: 32575
protocol: TCP
1
NodePort 端口由 kube-proxy 负责管理,通过 iptables/ipvs 规则转发流量,而非直接监听端口。
查看 iptables 规则:
bash
iptables -t nat -L KUBE-NODEPORTS -n | grep 32574
步骤 1:验证环境
bash
# 检查 Milvus Operator 状态
kubectl get pods -n milvus-operator
# 检查存储类
kubectl get sc
步骤 2:部署 Milvus 集群1
bash
kubectl apply -f milvus-cluster.yaml
1
步骤 3:部署 NodePort 服务2
bash
kubectl apply -f milvus-nodeport-service.yaml
2
步骤 4:检查部署状态1
bash
# 检查 Milvus 集群状态
kubectl get milvus my-release -o yaml
# 等待所有 pods 就绪
kubectl get pods
# 检查服务状态
kubectl get svc
1
步骤 5:等待部署完成2
等待所有组件启动,您应该看到类似这样的输出:2
NAME READY STATUS RESTARTS AGE
my-release-etcd-0 1/1 Running 0 14m
my-release-etcd-1 1/1 Running 0 14m
my-release-etcd-2 1/1 Running 0 14m
my-release-milvus-datanode-5c686bd65-wxtmf 1/1 Running 0 6m
my-release-milvus-indexnode-5b9787b54-xclbx 1/1 Running 0 6m
my-release-milvus-proxy-84f67cdb7f-pg6wf 1/1 Running 0 6m
my-release-milvus-querynode-5bcb59f6-nhqqw 1/1 Running 0 6m
my-release-milvus-mixcoord-fdcccfc84-9964g 1/1 Running 0 6m
2
kubectl describe pod查看某个pod的错误信息
步骤 6:测试连接3
使用 Python SDK 测试连接:3
python
from pymilvus import MilvusClient
client = MilvusClient(
uri="http://your-server-ip:32574"
)
3
4. 验证部署
检查端口转发是否正确配置:
bash
kubectl get svc milvus-nodeport
您应该看到端口 32574 映射到 19530,现在可以通过任意一台服务器的 IP:32574 端口访问您的 Milvus 2.4 集群了。
kubectl apply -f nodeport.yaml
##将集群内 milvus19530 端口转发至32574端口
检查:
kubectl get service milvus-service
输出:
kubectl get service milvus-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
milvus-service NodePort 10.107.5.60 <none> 19530:32574/TCP 22s
部署attu监测软件 在k8s的master节点上
shell
docker run -d --name=attu -p 8000:3000 -e MILVUS_URL=192.168.20.1:32574 zilliz/attu:latest
bash
检查容器是否正在运行:
bash
docker ps | grep attu
# 预期输出(示例):
# fc341dda2b6b zilliz/attu:latest "/tini -- /usr/loca..." 2分钟前 Up 2分钟 0.0.0.0:8000->3000/tcp attu
若状态为 Up 且端口映射正确,说明容器已正常启动。
查看容器日志:
bash
docker logs attu
# 关键日志示例:
# Attu server is running on port 3000
# Connecting to Milvus at 10.200.152.111:32574...
# Success: Milvus connection established
若日志中出现 Milvus connection established,说明 attu 已成功连接到 Milvus 集群。
二、验证 Web 界面访问
访问 attu 界面:
在浏览器中输入:http://<服务器IP>:8000
若网络配置正确,应看到 attu 的可视化管理界面(默认无需登录)。
界面功能验证:
查看集群状态:在左侧菜单中选择 Clusters,确认 Milvus 集群是否显示为 Connected。
创建集合:尝试创建一个测试集合(Collection),验证数据插入和查询功能。
三、检查 Milvus 连接有效性
确认环境变量配置:
# 使用 nc 测试端口连通性
nc -vz 192.168.20.1 32574
# 预期输出:
# Connection to 192.168.201 32574 port [tcp/*] succeeded!
若连接失败,需排查:
Kubernetes 服务端口是否正确。
服务器防火墙是否开放 32574 端口(可临时关闭防火墙测试:systemctl stop firewalld)。
四、常见问题排查
界面无法访问:
检查端口映射:
bash
docker inspect attu | grep -i "8000->3000"
测试本地访问:
bash
curl http://localhost:8000
# 若返回 HTML 内容,说明容器内部服务正常,需检查服务器外网访问权限。
Milvus 连接失败:
查看 attu 日志:
bash
docker logs attu | grep -i error
# 若出现 "Connection refused",需确认 Milvus 服务是否已启动。
重启 attu 容器:
bash
docker restart attu
五、后续操作建议
设置开机自启动:
bash
docker update attu --restart=always
bash
kubectl apply -f milvus-nodeport-correct.yaml
验证服务配置 1
bash
kubectl describe svc milvus-nodeport-correct
kubectl get endpoints milvus-nodeport-correct
应该看到 Endpoints 不再为空,而是显示 proxy pod 的 IP。
测试连接
bash
nc -vz 192.168.20.1 32574
重新启动 Attu 2
bash
docker stop attu
docker rm attu
docker run -d --name=attu -p 8000:3000 -e MILVUS_URL=192.168.20.1:32574 zilliz/attu:latest
2
验证 Attu 连接 2
bash
docker logs attu
打开浏览器访问:
bash
http://192.168.20.1:8000
访问 Milvus WebUI 3 您还可以通过内置的 WebUI 访问:
bash
http://192.168.20.1:32575/webui/
部署portainer插件
shell
Portainer 的作用:Portainer 是一个可视化容器管理工具,支持 Docker 和 Kubernetes 集群的管理,包括容器、服务、网络、卷等的可视化操作,方便用户通过 Web 界面管理容器环境,而不需要频繁使用命令行。
Portainer 插件的核心功能
Portainer 是一款可视化容器管理工具,主要功能包括:
Docker 管理:通过 Web 界面直观管理 Docker 容器、镜像、网络和卷
Kubernetes 集成:支持连接和管理 Kubernetes 集群,查看 Pod、服务、部署等资源
安全认证:提供用户认证和权限管理,支持 LDAP/AD 集成
监控与日志:查看容器运行状态、资源使用情况和日志
模板部署:通过模板快速部署复杂应用(如 Milvus、Attu 等)
docker run -d -p 9000:9000 -p 9443:9443 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer-ce:2.20.2
##本地运行 portainer,浏览器访问9000 端口后设置管理员密码
Mam@xt_2025!!
##安装 portainer k8s代理
kubectl create namespace portainer
namespace/portainer created
[root@MAM-MILVUS-11 yaml]# kubectl apply -f portainer-agent-k8s-nodeport.yaml
deployment.apps/portainer-agent created
service/portainer-agent created
cd ~/k8s/yaml
kubectl apply -f portainer-agent-k8s-nodeport.yaml
s浏览器访问查看
shell
http://192.168.20.1:8000/#/system
bash
Portainer 插件功能与部署步骤解析
一、Portainer 插件的核心功能
Portainer 是一款可视化容器管理工具,主要功能包括:
Docker 管理:通过 Web 界面直观管理 Docker 容器、镜像、网络和卷
Kubernetes 集成:支持连接和管理 Kubernetes 集群,查看 Pod、服务、部署等资源
安全认证:提供用户认证和权限管理,支持 LDAP/AD 集成
监控与日志:查看容器运行状态、资源使用情况和日志
模板部署:通过模板快速部署复杂应用(如 Milvus、Attu 等)
二、部署步骤正确性验证
1. 部署 Portainer CE 服务
##当前的部署方式是在单个节点上运行 Portainer 容器,然后通过 Kubernetes 代理连接到集群。
接下来,Kubernetes 代理的部署:用户使用 kubectl apply 命令在 portainer 命名空间中部署了 portainer-agent。这里需要注意的是,Kubernetes 的部署是集群范围的,一旦在 master 节点执行 kubectl apply,部署会被分发到所有符合条件的节点。因此,代理的部署只需要在 master 节点执行一次,Kubernetes 会自动处理在其他节点上的运行。
Portainer 容器是作为单个节点上的服务运行的,因此只需要在一个节点(比如 master)上执行 docker run 命令即可。其他节点不需要运行 Portainer 容器,因为代理会连接到该 Portainer 实例。
master 节点上执行 Portainer 容器的部署命令(包含数据卷),而 Kubernetes 代理的部署只需要在 master 节点执行一次,Kubernetes 会自动处理其他节点的代理实例。其他节点不需要执行 docker run 命令,只需确保代理部署正确即可。
还需要注意,Portainer 容器运行在单个节点上,如果该节点故障,Portainer 服务会不可用。如果需要高可用性,可能需要考虑将 Portainer 部署为 Kubernetes 中的 StatefulSet 或使用 Docker Swarm 模式,但用户当前的部署方式是单节点,所以需要注意这一点。
当前部署方式中,Portainer 容器运行在单节点,若该节点故障,服务会不可用。如需高可用,可考虑:
将 Portainer 部署为 Docker Swarm 服务(使用 Replication 或 Global 模式)。
或在 K8s 中通过 StatefulSet + Service 部署 Portainer(需额外配置)。
-v /var/run/docker.sock:/var/run/docker.sock:让 Portainer 获取本地 Docker 的管理权限,用于管理当前主机的 Docker 服务。
-v portainer_data:/data:创建名为portainer_data的命名卷,用于持久化存储 Portainer 的配置数据(如用户信息、连接配置等)。如果不添加此卷,容器删除后数据会丢失;添加后,数据会被保存在 Docker 管理的卷中,支持容器重建后数据恢复。
创建了一个命名卷(named volume),Docker 会自动管理这个卷的存储位置。命名卷的好处是可以跨容器共享数据,并且 Docker 会负责数据的持久化。
一、数据卷 -v portainer_data:/data 的本质作用
Portainer 的 /data 目录存储以下关键数据:
用户认证信息:管理员密码、LDAP/AD 配置、多用户权限设置
集群连接配置:Kubernetes 集群连接信息、Docker 环境连接凭证
部署模板与历史记录:通过 Portainer 部署的 Stack 模板、操作日志
证书与安全配置:HTTPS 证书、TLS 配置、访问控制规则
2. 部署 K8s 代理
bash
kubectl create namespace portainer
kubectl apply -f portainer-agent-k8s-nodeport.yaml
功能说明:portainer-agent 是 Portainer 用于连接 K8s 集群的代理组件,通过 nodeport.yaml 以 NodePort 方式暴露服务,便于外部访问
验证方法:
bash
# 检查代理 Pod 状态
kubectl get pods -n portainer
# 检查服务端口
kubectl get svc -n portainer portainer-agent
预期输出:
plaintext
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
portainer-agent NodePort 10.100.XX.XX <none> 9443:30778/TCP 10m
```bash
docker run -d -p 9000:9000 -p 9443:9443 --name=portainer --restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:2.26.1
访问 http://服务器IP:9000,设置管理员密码 xxxx
Portainer 本身是 Docker 容器化的管理工具,其核心服务只需在一个节点运行,通过 docker.sock 挂载即可管理本地 Docker 环境,或通过 K8s 代理连接到集群。多节点集群中,Portainer 服务本身不需要分布式部署,只需一个入口点。
外部用户 --> Master节点:32574 (Milvus) │ ├── Attu 监控 (Master节点:8000) └── Portainer (Master节点:9000) │ └── 管理 Kubernetes 集群 via Agent (NodePort 30778)
bash
# 检查 30778 端口是否开放
sudo firewall-cmd --list-ports | grep 30778
# 如果未开放,执行:
sudo firewall-cmd --permanent --add-port=30778/tcp
sudo firewall-cmd --reload
bash
bash
正式部署使用# portainer-agent-k8s-nodeport.yaml
apiVersion: v1
kind: Namespace
metadata:
name: portainer
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: portainer-agent
rules:
# 核心API组(空字符串表示核心组)
- apiGroups: [""]
resources:
- "pods"
- "services"
- "nodes"
- "namespaces"
- "configmaps"
- "secrets"
- "serviceaccounts"
- "persistentvolumes"
- "persistentvolumeclaims"
- "events"
- "resourcequotas" # 解决resourcequotas权限问题
- "endpoints"
- "limitranges"
- "replicationcontrollers"
verbs: ["get", "list", "watch"]
# 应用API组(Deployments, StatefulSets等)
- apiGroups: ["apps"]
resources:
- "deployments"
- "daemonsets"
- "statefulsets"
- "replicasets"
- "controllerrevisions"
verbs: ["get", "list", "watch"]
# 网络API组(Ingress等)
- apiGroups: ["networking.k8s.io"]
resources:
- "ingresses"
- "networkpolicies"
- "ingressclasses"
verbs: ["get", "list", "watch"]
# 存储API组
- apiGroups: ["storage.k8s.io"]
resources:
- "storageclasses"
- "volumeattachments"
- "csinodes"
verbs: ["get", "list", "watch"]
# 自动扩缩容API组(HPA)
- apiGroups: ["autoscaling"]
resources:
- "horizontalpodautoscalers" # 解决HPA权限问题
verbs: ["get", "list", "watch"]
# 批处理API组(Jobs, CronJobs)
- apiGroups: ["batch"]
resources:
- "jobs"
- "cronjobs"
verbs: ["get", "list", "watch"]
# 权限控制API组(RBAC)
- apiGroups: ["rbac.authorization.k8s.io"]
resources:
- "roles"
- "rolebindings"
- "clusterroles"
- "clusterrolebindings"
verbs: ["get", "list", "watch"]
# 策略API组(PodDisruptionBudget)
- apiGroups: ["policy"]
resources:
- "poddisruptionbudgets"
verbs: ["get", "list", "watch"]
# 证书API组
- apiGroups: ["certificates.k8s.io"]
resources:
- "certificatesigningrequests"
verbs: ["get", "list", "watch"]
# 指标API组(用于资源使用情况)
- apiGroups: ["metrics.k8s.io"]
resources:
- "pods"
- "nodes"
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: portainer-agent
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: portainer-agent
subjects:
- kind: ServiceAccount
name: portainer-agent
namespace: portainer
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: portainer-agent
namespace: portainer
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: portainer-agent
namespace: portainer
spec:
replicas: 1
selector:
matchLabels:
app: portainer-agent
template:
metadata:
labels:
app: portainer-agent
spec:
serviceAccountName: portainer-agent
containers:
- name: portainer-agent
image: portainer/agent:2.26.1 # 确保版本与Portainer Server匹配
imagePullPolicy: IfNotPresent
env:
- name: AGENT_CLUSTER_ADDR
value: "0.0.0.0"
# 必须的环境变量(用于Kubernetes平台)
- name: KUBERNETES_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
ports:
- containerPort: 9001
protocol: TCP
# 存活探针
livenessProbe:
httpGet:
path: /ping
port: 9001
scheme: HTTPS
initialDelaySeconds: 5
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: portainer-agent
namespace: portainer
spec:
type: NodePort
ports:
- port: 9001
targetPort: 9001
nodePort: 30778 # 确保该端口在30000-32767之间且未被占用
selector:
app: portainer-agent
4.部署完成
业务可访问任意k8s节点的32574端口访问milvus集群
日常检查项
1.检查pods运行情况
shell
##确保没有异常的 pods
kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
calico-apiserver calico-apiserver-77fb7b89c8-95hkd 1/1 Running 0 15h
calico-apiserver calico-apiserver-77fb7b89c8-zvtlv 1/1 Running 0 15h
calico-system calico-kube-controllers-5745db8b8f-pphfz 1/1 Running 1 (15h ago) 15h
calico-system calico-node-68fr8 1/1 Running 0 15h
calico-system calico-node-m2s29 1/1 Running 0 15h
calico-system calico-node-pl8nk 1/1 Running 0 15h
calico-system calico-typha-65878ffbd7-db4bz 1/1 Running 0 15h
calico-system calico-typha-65878ffbd7-rzbwn 1/1 Running 0 15h
calico-system csi-node-driver-gzvvl 2/2 Running 0 15h
calico-system csi-node-driver-nzcqh 2/2 Running 0 15h
calico-system csi-node-driver-rkr8n 2/2 Running 0 15h
cert-manager cert-manager-679895f5-ccq2r 1/1 Running 0 62m
cert-manager cert-manager-cainjector-b78544fd4-qbsfc 1/1 Running 0 62m
cert-manager cert-manager-webhook-cd8bbbd67-d6m2s 1/1 Running 0 62m
default my-release-etcd-0 1/1 Running 0 59m
default my-release-etcd-1 1/1 Running 0 59m
default my-release-etcd-2 1/1 Running 0 59m
default my-release-milvus-datanode-785dd5446f-rxxw7 1/1 Running 0 40m
default my-release-milvus-indexnode-7bbbffd64f-xh8wm 1/1 Running 0 40m
default my-release-milvus-mixcoord-5f784f8575-zmmnb 1/1 Running 0 40m
default my-release-milvus-proxy-5f577b6667-tkf5x 1/1 Running 0 40m
default my-release-milvus-querynode-0-84c5fc9f56-qk6zb 1/1 Running 0 40m
default my-release-minio-0 1/1 Running 0 59m
default my-release-minio-1 1/1 Running 0 59m
default my-release-minio-2 1/1 Running 0 59m
default my-release-minio-3 1/1 Running 0 59m
default my-release-pulsar-bookie-0 1/1 Running 0 59m
default my-release-pulsar-bookie-1 1/1 Running 0 59m
default my-release-pulsar-bookie-2 1/1 Running 0 59m
default my-release-pulsar-bookie-init-4r2hj 0/1 Completed 0 59m
default my-release-pulsar-broker-0 1/1 Running 0 10m
default my-release-pulsar-broker-1 1/1 Running 0 11m
default my-release-pulsar-proxy-0 1/1 Running 0 59m
default my-release-pulsar-proxy-1 1/1 Running 0 11m
default my-release-pulsar-pulsar-init-ss5f5 0/1 Completed 0 59m
default my-release-pulsar-recovery-0 1/1 Running 0 59m
default my-release-pulsar-zookeeper-0 1/1 Running 0 59m
default my-release-pulsar-zookeeper-1 1/1 Running 0 43m
default my-release-pulsar-zookeeper-2 1/1 Running 0 42m
default nfs-client-provisioner-757f598948-xvgc9 1/1 Running 0 15h
kube-system coredns-6554b8b87f-mj6ls 1/1 Running 0 15h
kube-system coredns-6554b8b87f-rggj9 1/1 Running 0 15h
kube-system etcd-k8s-node1 1/1 Running 2 (15h ago) 15h
kube-system kube-apiserver-k8s-node1 1/1 Running 2 (15h ago) 15h
kube-system kube-controller-manager-k8s-node1 1/1 Running 2 (15h ago) 15h
kube-system kube-proxy-ccddf 1/1 Running 2 (15h ago) 15h
kube-system kube-proxy-lx2xb 1/1 Running 1 (15h ago) 15h
kube-system kube-proxy-xn74j 1/1 Running 1 (15h ago) 15h
kube-system kube-scheduler-k8s-node1 1/1 Running 2 (15h ago) 15h
kubernetes-dashboard dashboard-metrics-scraper-5657497c4c-h9k2s 1/1 Running 0 15h
kubernetes-dashboard kubernetes-dashboard-78f87ddfc-9krnm 1/1 Running 0 15h
milvus-operator milvus-operator-6cbccd76fc-vszwf 1/1 Running 0 61m
milvus-operator milvus-operator-checker-2nkhs 0/1 Completed 0 61m
tigera-operator tigera-operator-689d868448-7scd2 1/1 Running 0 15h
2.检查服务器情况
shell
free -h
df -h
##k8s master节点做的nfs server,所有milvus数据均存储在k8s-node1 的/data/share 路径下,确保空间可用
3.检查集群情况
shell
4.k8s常用命令
shell
kubectl get pods -A ##查看所有pods运行情况
kubectl get pods -n kubernetes-dashboard ##查看k8s面板运行情况
kubectl get nodes ##查看所有节点运行情况
kubectl get svc ##查看所有服务运行情况
kubectl create token admin-user -n kubernetes-dashboard ##获取dashboard新的token
核心概念解释
"生产环境直接使用 containerd 作为 Kubernetes 运行时" 的含义:
- 架构演进 :
- 旧架构:Kubernetes → dockershim → Docker → containerd → 容器
- 新架构:Kubernetes → containerd → 容器(无需 Docker 中间层)
- 为什么是最佳实践 :
- 性能提升:减少一层调用(Docker引擎),容器启动速度提高 20-30%
- 资源占用更低:移除 Docker 守护进程,节省 100-200MB 内存
- 更稳定:减少组件依赖,降低故障点
- 官方支持:Kubernetes 1.20+ 官方推荐使用 containerd/CRI-O
- 安全增强:减少攻击面(Docker 有更大的攻击面)
🔧 需要改进的安装步骤
原始步骤的问题:
bash
# 安装Docker(包含不必要的组件)
yum install -y docker-ce docker-ce-cli containerd.io
# 安装cri-dockerd(冗余的适配层)
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.2/cri-dockerd-0.3.2-3.el7.x86_64.rpm
rpm -ivh cri-dockerd-0.3.2-3.el7.x86_64.rpm
bash
# 1. 仅安装必要组件(跳过Docker引擎)
yum install -y containerd.io
# 2. 配置containerd
containerd config default > /etc/containerd/config.toml
# 3. 启用systemd cgroup驱动(K8s必需)
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
# 4. 启动containerd服务
systemctl enable --now containerd
# 5. 安装CRI工具(用于调试)
yum install -y cri-tools
# 6. 验证containerd
crictl version
ruby
### 📊 架构对比
| **组件** | **传统方案** | **优化方案** | **优势** |
| :----------- | :------------------ | :-------------- | :----------- |
| **运行时** | Docker → containerd | 直接 containerd | 减少调用层级 |
| **CRI适配** | cri-dockerd | 原生支持 | 无需额外组件 |
| **内存占用** | 200-300MB | 50-100MB | 节省资源 |
| **启动速度** | 较慢 | 更快 | 提高效率 |
| **K8s兼容** | 需适配器 | 原生支持 | 更稳定 |
### ⚙️ Kubernetes 集成改进
**原始方式(kubeadm初始化)**:
kubeadm init --cri-socket unix:///var/run/cri-dockerd.sock
markdown
**优化后方式**:
containerd 默认使用 /run/containerd/containerd.sock
kubeadm init
csharp
# 查看容器运行时
kubectl get nodes -o wide
# 应显示类似:
# NAME STATUS ROLES ... CONTAINER-RUNTIME
# node-01 Ready master ... containerd://1.6.32
💡 为什么需要这些改进?
- Docker 在 K8s 中的角色已变化 :
- Docker 不再是 Kubernetes 的必需组件
- Containerd 是 Docker 的底层运行时,K8s 现在直接使用它
- cri-dockerd 是临时方案 :
- 仅用于过渡期(K8s 1.20-1.23)
- 官方已停止维护 dockershim
- 生产环境要求 :
- 更轻量:减少不必要的进程
- 更安全:减少 CVE 暴露面
- 更高效:直接调用容器运行时
📝 总结改进要点
- 移除冗余:跳过 Docker 引擎和 cri-dockerd 安装
- 直接使用:让 K8s 直接对接 containerd
- 简化配置:无需额外适配器配置
- 资源优化:节省内存和CPU资源
注意:如果您有特定需求必须使用 Docker(如依赖 Docker 特定功能),传统方案仍可用。但对于纯 Kubernetes 环境,直接使用 containerd 是当前行业标准做法。
这样改进后,您的 Kubernetes 集群将更加高效、稳定,并且符合云原生计算基金会(CNCF)的最佳实践标准。
后记:离线部署有了镜像相对简单一些,使用脚本导入导出执行就可以。
备份镜像和拉取镜像
bash
(1) 打包镜像
bash
# 创建保存目录
mkdir -p ~/docker_images
cd ~/docker_images
docker save -o all_images.tar $(docker images -q)
输出文件:~/docker_images/all_images.tar
(2) 下载到本地
(3) 在目标机器加载镜像
docker load -i /本地/保存路径/all_images.tar
总包中包含docker、attu 、milvus-operator、milvusdb/etcd、calico/cni、kubernetesui/dashboard、coredns、milvusdb/milvus、portainer/portainer-ce各离线镜像。
K8s部署Mil...据库集群」,复制整段内容,打开最新版「夸克APP」即可获取。 畅享原画,免费5倍速播放,支持AI字幕和投屏,更有网盘TV版。 动作蒴鹬㐈胶木多好 /8a9136zMRU :/ 链接:pan.quark.cn/s/cffcfff51...
有新版及时更新及时交流,新版可以支持GPU跑服务了。过几天测试部署,会及时分享GPU部署情况。