KVM创建ubuntu20.04虚机,部署K8S,再克隆出二份,做为Worker节点加入集群,通过Helm创建2个Pod,让它们之间通过域名互访
KVM创建ubuntu20.04虚机,部署K8S,再克隆出二份,做为Worker节点加入集群,通过Helm创建2个Pod,让它们之间通过域名互访
- 一.背景
- 二.操作步骤
- 1.安装KVM
- A.在BIOS中开启VT-d
- B.修改grub,开启iommu
- 在/etc/default/grub 中 GRUB_CMDLINE_LINUX行 添加 intel_iommu=on iommu=pt
- 重新创建引导
- 重启服务器
- 验证iommu是否开启
- C.SSH开启X11-forwarding,用于可交互式安装
- 修改`/etc/ssh/sshd_config`如下:
- 重启SSH服务
- D.安装依赖
- 2.创建第一台KVM虚拟机,做为Master节点
- A.创建存储目录
- B.下载ubuntu 20.04镜像
- C.创建虚拟机
- 通过virt-install创建虚机,在界面上配置ubutnu20.04
- 重启虚机
- 通过远程桌面登录ubuntu20.04,查看IP(如:`192.168.122.140`)
- 在物理机上通过SSH登录虚机
- 修改为静态IP
- 更新apt源
- 关闭swap
- 开启网络转发
- 安装docker-ce
- 设置docker国内镜像
- 安装kubelet
- 创建K8S集群
- 关闭虚机
- 在物理机上,克隆出二台虚机,设置成不同的MAC
- 依次启动三台虚机
- 通过ssh登录ubuntu20节点,获取join命令
- 通过ssh登录ubuntu20_node1,将其加入集群
- 通过ssh登录ubuntu20_node2,将其加入集群
- 回到ubuntu20节点,获取node列表,设置node1、node2为工作节点
- 在ubuntu20上安装Helm
- 在ubuntu20上创建Helm工程
- 在ubuntu20上通过Helm命令创建pod
- 获取K8S集群的DNS服务器地址
- 进入第一个pod,配置DNS,使其能通过域名访问pod1
- 进入第二个pod,配置DNS,使能通过域名访问pod0
- 删除资源
- 3.遇到的问题及解决办法
- 三.补充知识点
- **1. Deployment**
- **特点:**
- **行为:**
- **适用场景:**
- **2. StatefulSet**
- **特点:**
- **行为:**
- **适用场景:**
- **3. 主要区别**
- **4. 具体示例**
- **Deployment 示例**
- **StatefulSet 示例**
- **5. 选择使用 Deployment 还是 StatefulSet 的指南**
- **使用 Deployment:**
- **使用 StatefulSet:**
- **6. 常见误区**
- **7. 总结**
一.背景
- 在centos7.9上安装KVM ubuntu20.04虚拟机
- 在该虚机中部署K8S单节点
- 将该虚拟机克隆出二份,设置MAC和IP,并加入到K8S集群
- 在Mastet节点安装Helm
- 通过Helm模板创建二个Pod,每个Pod一个容器,Pod之间可通过固定的域名访问
二.操作步骤
1.安装KVM
A.在BIOS中开启VT-d
B.修改grub,开启iommu
在/etc/default/grub 中 GRUB_CMDLINE_LINUX行 添加 intel_iommu=on iommu=pt
修改如下
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_DISABLE_RECOVERY="true"
GRUB_CMDLINE_LINUX="crashkernel=384M rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet intel_iommu=on iommu=pt"
重新创建引导
*EFI模式: grub2-mkconfig -o /boot/efi/EFI/bclinux/grub.cfg
*BIOS模式: grub2-mkconfig -o /boot/grub2/grub.cfg
重启服务器
sync;sync;ipmitool power cycle
验证iommu是否开启
dmesg | grep iommu -i
C.SSH开启X11-forwarding,用于可交互式安装
修改/etc/ssh/sshd_config
如下:
AddressFamily inet
AllowTcpForwarding yes
X11Forwarding yes
重启SSH服务
systemctl restart sshd
D.安装依赖
yum -y install qemu qemu-kvm libvirt libvirt-python libguestfs- \tools virt-install tigervnc virt-viewer virt-manager
systemctl enable libvirtd
systemctl start libvirtd
2.创建第一台KVM虚拟机,做为Master节点
A.创建存储目录
mkdir -p /var/lib/libvirt/boot/
mkdir -p /var/lib/libvirt/images/
B.下载ubuntu 20.04镜像
cd /var/lib/libvirt/boot/
wget https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/20.04/ubuntu-20.04.5-live-server-amd64.iso
C.创建虚拟机
通过virt-install创建虚机,在界面上配置ubutnu20.04
virt-install \--virt-type=kvm \--name ubuntu20 \--ram 21920 \--vcpus=16 \--os-type linux \--os-variant ubuntu20.04 \--console pty,target_type=serial\--connect qemu:///system \--cdrom=/var/lib/libvirt/boot/ubuntu-20.04.5-live-server-amd64.iso \--network=bridge=virbr0,model=virtio \--graphics vnc \--disk path=/var/lib/libvirt/images/ubuntu20.qcow2,size=20,bus=virtio,format=qcow2
注意事项
- 开启SSH
- Configure Proxy可选:http://mirrors.aliyun.com/ubuntu/
重启虚机
virsh shutdown ubuntu20
virsh start ubuntu20
通过远程桌面登录ubuntu20.04,查看IP(如:192.168.122.140
)
virt-viewer
在物理机上通过SSH登录虚机
ssh kvm@192.168.122.140
sudo su
修改为静态IP
cat >/etc/netplan/00-installer-config.yaml <<-'EOF'
network:version: 2renderer: networkdethernets:ens3:addresses:- 192.168.122.140/24gateway4: 192.168.122.1nameservers:addresses: [8.8.8.8,8.8.4.4]
EOF
netplan apply
更新apt源
sed -i "s@http://.*archive.ubuntu.com@http://repo.huaweicloud.com@g" /etc/apt/sources.list
sed -i "s@http://.*security.ubuntu.com@http://repo.huaweicloud.com@g" /etc/apt/sources.list
apt update
apt install net-tools -y
关闭swap
sudo sed -i 's/.*swap.*/#&/' /etc/fstab
swapoff -a
开启网络转发
bash -c "cat >> /etc/sysctl.conf" << EOF
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
安装docker-ce
sudo apt install -y apt-transport-https ca-certificates software-properties-common
sudo curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg |sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-cache madison docker-ce
dpkg -l | grep docker
apt remove --purge docker-ce*
sudo apt install docker-ce=5:19.03.15~3-0~ubuntu-focal docker-ce-cli=5:19.03.15~3-0~ubuntu-focal containerd.io -y
设置docker国内镜像
bash -c "cat >> /etc/docker/daemon.json" << EOF
{"dns": ["8.8.8.8", "8.8.4.4"],"registry-mirrors": ["https://docker.m.daocloud.io/","https://huecker.io/","https://dockerhub.timeweb.cloud","https://noohub.ru/","https://dockerproxy.com","https://docker.mirrors.ustc.edu.cn","https://docker.nju.edu.cn","https://xx4bwyg2.mirror.aliyuncs.com","http://f1361db2.m.daocloud.io","https://registry.docker-cn.com","http://hub-mirror.c.163.com"]
}
EOF
systemctl restart docker
安装kubelet
sudo curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg |sudo apt-key add -
sudo bash -c "cat > /etc/apt/sources.list.d/kubernetes.list" <<EOF
deb https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial main
EOF
sudo apt install -y kubeadm=1.20.0-00 kubelet=1.20.0-00 kubectl=1.20.0-00
systemctl enable kubelet && sudo systemctl start kubelet
创建K8S集群
rm /var/lib/etcd -rf
kubeadm reset
kubeadm init --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.20.0 --pod-network-cidr=10.244.0.0/16mkdir -p $HOME/.kube
sudo cp -f /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/configkubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl taint nodes --all node-role.kubernetes.io/master-
kubectl get pods --all-namespaces
#等待所有pod为running状态
kubectl get node
输出
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-flannel kube-flannel-ds-jvlns 1/1 Running 0 17m
kube-system coredns-7f89b7bc75-558sb 0/1 Running 0 17m
kube-system coredns-7f89b7bc75-5mhgm 0/1 Running 0 17m
kube-system etcd-111111 0/1 Running 1 17m
kube-system kube-apiserver-111111 1/1 Running 1 17m
kube-system kube-controller-manager-111111 0/1 Running 1 17m
kube-system kube-proxy-g7nsd 1/1 Running 1 17m
kube-system kube-scheduler-111111 0/1 Running 1 17m
关闭虚机
poweroff
在物理机上,克隆出二台虚机,设置成不同的MAC
virt-clone -o ubuntu20 -n ubuntu20_node1 -f /var/lib/libvirt/images/ubuntu20_node1.qcow2 --mac 52:54:00:3b:d9:17
virt-clone -o ubuntu20 -n ubuntu20_node2 -f /var/lib/libvirt/images/ubuntu20_node2.qcow2 --mac 52:54:00:3b:d9:27
依次启动三台虚机
virsh start ubuntu20_node1
virsh start ubuntu20_node2
virsh start ubuntu20
每启动一台node节点,执行以下步骤
- 修改
/etc/netplan/00-installer-config.yaml
中的IP地址,之后执行netplan apply
生效
通过ssh登录ubuntu20节点,获取join命令
kubeadm token create --print-join-command
输出
kubeadm join 192.168.122.140:6443 --token v0wuxs.cqduc5dw0t50fis6 \--discovery-token-ca-cert-hash sha256:aa14d393d6e693d6a1bea6e6b6d75c55e3bb38a29071fe7166ce9d49606b6b0e
通过ssh登录ubuntu20_node1,将其加入集群
# 修改主机名
hostnamectl set-hostname node1# join到K8S集群
kubeadm reset
rm -f /etc/kubernetes/pki/ca.crt /etc/kubernetes/kubelet.conf
kubeadm join 192.168.122.140:6443 --token v0wuxs.cqduc5dw0t50fis6 \--discovery-token-ca-cert-hash sha256:aa14d393d6e693d6a1bea6e6b6d75c55e3bb38a29071fe7166ce9d49606b6b0e
通过ssh登录ubuntu20_node2,将其加入集群
# 修改主机名
hostnamectl set-hostname node2# join到K8S集群
kubeadm reset
rm -f /etc/kubernetes/pki/ca.crt /etc/kubernetes/kubelet.conf
kubeadm join 192.168.122.140:6443 --token v0wuxs.cqduc5dw0t50fis6 \--discovery-token-ca-cert-hash sha256:aa14d393d6e693d6a1bea6e6b6d75c55e3bb38a29071fe7166ce9d49606b6b0e
回到ubuntu20节点,获取node列表,设置node1、node2为工作节点
kubectl get nodes
kubectl label nodes node1 node-role.kubernetes.io/worker=
kubectl label nodes node2 node-role.kubernetes.io/worker=
kubectl get nodes --show-labels
在ubuntu20上安装Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
在ubuntu20上创建Helm工程
# 创建工程
helm create llama-training
cd llama-training# 删除无用的文件
rm templates/deployment.yaml
rm templates/service.yaml
rm templates/ingress.yaml
rm -rf templates/tests
rm templates/hpa.yaml
rm templates/serviceaccount.yaml
rm templates/NOTES.txt# 创建 values.yaml 文件,包含可变参数
cat > values.yaml << EOF
replicaCount: 2
image:repository: ubuntutag: "20.04"pullPolicy: IfNotPresent
masterPort: "29500"
worldSize: "16"
EOF# 创建 StatefulSet 模板,为每个 Pod 分配稳定的主机名
cat > templates/statefulset.yaml <<-'EOF'
apiVersion: apps/v1
kind: StatefulSet
metadata:name: {{ include "llama-training.fullname" . }}labels:{{- include "llama-training.labels" . | nindent 4 }}
spec:serviceName: "{{ include "llama-training.fullname" . }}-headless"replicas: {{ .Values.replicaCount }}selector:matchLabels:{{- include "llama-training.selectorLabels" . | nindent 6 }}template:metadata:labels:{{- include "llama-training.selectorLabels" . | nindent 8 }}spec:containers:- name: {{ .Chart.Name }}image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"imagePullPolicy: {{ .Values.image.pullPolicy }}securityContext:allowPrivilegeEscalation: falseenv:- name: MASTER_ADDRvalue: "{{ include "llama-training.fullname" . }}-headless"- name: MASTER_PORTvalue: "{{ .Values.masterPort }}"- name: WORLD_SIZEvalue: "{{ .Values.worldSize }}"command: [ "/bin/bash", "-c", "--" ]args: [ "while true; do sleep 30; done;" ]
EOF# 创建 Headless Service,让 Pod 之间可以通过域名访问,解决 IP 地址不固定的问题
cat > templates/headless-service.yaml <<-'EOF'
apiVersion: v1
kind: Service
metadata:name: {{ include "llama-training.fullname" . }}-headlesslabels:{{- include "llama-training.labels" . | nindent 4 }}
spec:clusterIP: None # 使其成为 Headless Serviceselector:{{- include "llama-training.selectorLabels" . | nindent 4 }}
EOF# 设置网络策略,让 Pod 可以访问外网
cat > templates/networkpolicy.yaml <<-'EOF'
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:name: {{ include "llama-training.fullname" . }}-egressnamespace: {{ .Release.Namespace }}labels:{{- include "llama-training.labels" . | nindent 4 }}
spec:podSelector:matchLabels:{{- include "llama-training.selectorLabels" . | nindent 6 }}policyTypes:- Egressegress:- {}
EOF
在ubuntu20上通过Helm命令创建pod
helm install llama-training .
kubectl get pods -o wide
输出
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
llama-training-0 1/1 Running 0 15s 10.244.2.194 node1 <none> <none>
llama-training-1 1/1 Running 0 14s 10.244.1.106 master <none> <none>
获取K8S集群的DNS服务器地址
kubectl get endpoints -n kube-system -o wide|grep kube-dns
kube-dns 10.244.1.104:53,10.244.1.105:53,10.244.1.104:53 + 3 more... 63m
进入第一个pod,配置DNS,使其能通过域名访问pod1
# 进入pod
kubectl exec -it llama-training-0 -- bash# 配置DNS
cat > /etc/resolv.conf <<-'EOF'
nameserver 10.244.1.104
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
nameserver 8.8.8.8
EOF# 下载相关工具
apt update
apt install net-tools iputils-ping -y# 通过域名ping二个pod
ping llama-training-0.llama-training-headless.default.svc.cluster.local -c 2
ping llama-training-1.llama-training-headless.default.svc.cluster.local -c 2# 退出
exit
输出
64 bytes from llama-training-0.llama-training-headless.default.svc.cluster.local (10.244.2.194): icmp_seq=1 ttl=64 time=0.035 ms
64 bytes from llama-training-0.llama-training-headless.default.svc.cluster.local (10.244.2.194): icmp_seq=2 ttl=64 time=0.032 ms64 bytes from llama-training-1.llama-training-headless.default.svc.cluster.local (10.244.1.106): icmp_seq=1 ttl=62 time=0.319 ms
64 bytes from llama-training-1.llama-training-headless.default.svc.cluster.local (10.244.1.106): icmp_seq=2 ttl=62 time=0.457 ms
进入第二个pod,配置DNS,使能通过域名访问pod0
# 进入pod
kubectl exec -it llama-training-1 -- bash# 配置DNS
cat > /etc/resolv.conf <<-'EOF'
nameserver 10.244.1.104
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
nameserver 8.8.8.8
EOF# 下载相关工具
apt update
apt install net-tools iputils-ping -y# 通过域名ping二个pod
ping llama-training-0.llama-training-headless.default.svc.cluster.local -c 2
ping llama-training-1.llama-training-headless.default.svc.cluster.local -c 2# 退出
exit
输出
64 bytes from llama-training-0.llama-training-headless.default.svc.cluster.local (10.244.2.194): icmp_seq=1 ttl=64 time=0.035 ms
64 bytes from llama-training-0.llama-training-headless.default.svc.cluster.local (10.244.2.194): icmp_seq=2 ttl=64 time=0.032 ms64 bytes from llama-training-1.llama-training-headless.default.svc.cluster.local (10.244.1.106): icmp_seq=1 ttl=62 time=0.319 ms
64 bytes from llama-training-1.llama-training-headless.default.svc.cluster.local (10.244.1.106): icmp_seq=2 ttl=62 time=0.457 ms
删除资源
helm uninstall llama-training
kubectl get pods -o wide
# 等待资源释放
3.遇到的问题及解决办法
- “cni0” already has an IP address different from
ifconfig cni0 down
ip link delete cni0
- DNC异常,重启 CoreDNS
kubectl delete pod -n kube-system -l k8s-app=kube-dns
kubectl get pods -n kube-system
三.补充知识点
在 Kubernetes(k8s)中,Pod 是最小的可部署单位,它代表了在集群中运行的一个或多个容器。每个 Pod 都运行在单个节点(服务器)上,无法跨越多个节点。也就是说,一个 Pod 不能同时分布在多个服务器上运行。
如果您需要在多个服务器上运行应用程序,以实现高可用性和负载均衡,您可以使用 Deployment、ReplicaSet 或 StatefulSet 等更高级别的控制器来管理多个 Pod 实例。Kubernetes 会根据资源情况和调度策略,将这些 Pod 分布到集群中的不同节点上运行。
总结来说,Pod 本身不能跨服务器,但您可以通过创建多个 Pod,并利用 Kubernetes 的调度和管理功能,让这些 Pod 分布在不同的节点上,以满足跨服务器的需求。
在Kubernetes中,Pod之间可以通过主机名进行访问,通常是通过以下几种方式实现的:
-
直接使用Pod的DNS:每个Pod在Kubernetes集群中都有一个DNS条目,你可以直接使用Pod的名称来进行访问,不过这种方法不推荐用在生产环境,因为Pod的IP地址会随着重启发生变化。
-
使用Service进行访问:
-
ClusterIP:这是Kubernetes中Service的默认类型。Service为一组Pod提供了一个稳定的IP地址和DNS名称。你可以通过Service的名称来访问Pod,Service会自动进行负载均衡。
-
Headless Service:如果需要直接获取Pod的IP地址,可以创建一个Headless Service。通过将Service的
clusterIP
字段设置为None
来创建。这样,Kubernetes会为这个Service的每个Pod创建一个DNS记录。
-
-
StatefulSets:
- 对于有状态应用,比如ZooKeeper、Cassandra等,可以使用StatefulSets来部署。这种资源类型会为每个Pod分配稳定的主机名,格式通常为
<podname>.<headless-service-name>.<namespace>.svc.cluster.local
。
- 对于有状态应用,比如ZooKeeper、Cassandra等,可以使用StatefulSets来部署。这种资源类型会为每个Pod分配稳定的主机名,格式通常为
在 Kubernetes 中,Deployment 和 StatefulSet 是两种常用的工作负载(Workload)资源类型,它们用于管理 Pod 的部署和伸缩。虽然它们都可以用于管理应用程序的副本,但它们在处理 Pod 的方式和适用的场景上有着显著的区别。
以下将详细解释 Deployment 和 StatefulSet 的主要区别,以及它们各自的适用场景。
1. Deployment
特点:
- 无状态服务(Stateless):Deployment 主要用于管理无状态的应用程序,如 Web 前端、API 服务器等。
- Pod 的可互换性:Deployment 中的所有 Pod 都是可互换的,没有特定的身份。
行为:
- 滚动更新(Rolling Update):支持无中断地更新应用程序到新版本。
- Pods 的命名:Pod 的名称是随机生成的,不保证稳定的主机名(Hostname)或网络标识(Network Identity)。
- 副本数(Replica)管理:可以轻松地水平伸缩 Pod 的数量。
适用场景:
- 无需持久化存储的无状态应用。
- 对于应用程序的实例间没有严格的顺序或身份需求。
2. StatefulSet
特点:
- 有状态服务(Stateful):StatefulSet 用于管理有状态的应用程序,如数据库(例如 MySQL、MongoDB)、分布式系统(例如 Kafka、Zookeeper)等。
- 稳定的网络标识:每个 Pod 都有一个稳定的、唯一的网络标识(主机名),该标识在 Pod 重建或调度到其他节点时保持不变。
- 持久化存储:可以为每个 Pod 关联一个持久化的存储卷(PersistentVolume),即使 Pod 被删除或重新调度,数据也不会丢失。
行为:
- 有序部署和更新:Pod 的创建、更新和删除按照指定的顺序进行(从 0 到 N-1)。
- Pods 的命名:Pod 的名称遵循固定的模式:
<StatefulSet 名称>-<序号>
,例如my-app-0
、my-app-1
。 - 持久化存储卷的绑定:通过
VolumeClaimTemplates
,每个 Pod 都有自己的持久化存储卷。
适用场景:
- 需要持久化数据的有状态应用程序。
- 应用程序实例需要稳定的身份(例如,需要特定的主机名或 IP 地址)。
- 应用程序实例之间需要有序部署或终止。
3. 主要区别
特性 | Deployment | StatefulSet |
---|---|---|
适用应用类型 | 无状态应用程序 | 有状态应用程序 |
Pod 可互换性 | Pods 可互换,无需稳定身份 | Pods 有稳定的身份,不可互换 |
网络标识 | Pod 名称随机,无稳定的主机名或网络标识 | 每个 Pod 有稳定的主机名,网络标识长期保持不变 |
存储卷 | 通常使用共享的存储卷,或不需要存储 | 每个 Pod 关联一个专属的持久化存储卷 |
部署和更新顺序 | 无序,Pods 可并行创建、更新或删除 | 有序,按照序号顺序创建、更新或删除 Pods |
滚动更新 | 支持,更新时可同时更新多个实例 | 更新时按顺序进行,一个接一个地更新 Pods |
扩缩容 | 支持,同时创建或删除多个 Pods | 按序号增减 Pods,扩容时创建新的序号的 Pod |
4. 具体示例
Deployment 示例
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deployment
spec:replicas: 3 # 副本数,可以随意调整selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:1.21
说明:
- 部署了 3 个 Nginx 实例,Pod 名称随机生成,例如
nginx-deployment-xxxxxxxxxx-yyyyy
。 - Pods 之间没有稳定的身份或顺序,可以随意扩缩容。
StatefulSet 示例
apiVersion: apps/v1
kind: StatefulSet
metadata:name: mysql-statefulset
spec:serviceName: "mysql"replicas: 3 # 副本数,按照序号创建selector:matchLabels:app: mysqltemplate:metadata:labels:app: mysqlspec:containers:- name: mysqlimage: mysql:8.0volumeMounts:- name: mysql-datamountPath: /var/lib/mysqlvolumeClaimTemplates:- metadata:name: mysql-dataspec:accessModes: ["ReadWriteOnce"]storageClassName: "standard"resources:requests:storage: 10Gi
说明:
- 部署了 3 个 MySQL 实例,Pod 名称为
mysql-statefulset-0
、mysql-statefulset-1
、mysql-statefulset-2
。 - 每个 Pod 都有一个名为
mysql-data
的持久化存储卷,数据不会因 Pod 重建而丢失。 - Pods 的创建、更新和删除按序号进行,确保顺序性和稳定性。
5. 选择使用 Deployment 还是 StatefulSet 的指南
使用 Deployment:
- 无状态应用程序:应用程序不需要持久化数据。
- Pod 可互换:实例之间没有区别,可以随意替换。
- 无需稳定网络标识:Pods 的主机名和 IP 地址可变。
- 需要快速扩缩容:可以迅速增加或减少 Pods 数量。
- 快速滚动更新:可同时更新多个实例,减少更新时间。
使用 StatefulSet:
- 有状态应用程序:如数据库、缓存系统等,需要持久化数据。
- Pod 需要稳定身份:实例需要固定的主机名或网络标识。
- 需要持久化存储:每个 Pod 需要绑定独立的存储卷。
- 有序部署和更新:需要按照特定顺序启动或停止实例。
- 对实例间关系有要求:实例之间存在关联,需要稳定的通信。
6. 常见误区
- 误用 Deployment 管理有状态服务:可能导致数据丢失、网络通信失败等问题。
- 误用 StatefulSet 管理无状态服务:增加了不必要的复杂性,降低了部署效率。
7. 总结
- Deployment:适用于无状态、可快速扩展的应用程序,管理简单,部署效率高。
- StatefulSet:适用于有状态、需要持久化存储和稳定网络标识的应用程序,确保应用程序的可靠性和一致性。
相关文章:

KVM创建ubuntu20.04虚机,部署K8S,再克隆出二份,做为Worker节点加入集群,通过Helm创建2个Pod,让它们之间通过域名互访
KVM创建ubuntu20.04虚机,部署K8S,再克隆出二份,做为Worker节点加入集群,通过Helm创建2个Pod,让它们之间通过域名互访 一.背景二.操作步骤1.安装KVMA.在BIOS中开启VT-dB.修改grub,开启iommu在/etc/default/grub 中 GRUB_CMDLINE_LINUX行 添加 intel_iommuon iommupt重新创建引导…...

GaussDB中的Vacuum和Analyze
GaussDB中的Vacuum和Analyze 基本概念与区别手动Vacuum和Analyze查看Vacuum和Analyze记录Autovacuum配置参数 基本概念与区别 使用VACUUM、VACUUM FULL和ANALYZE命令定期对每个表进行维护,主要有以下原因: VACUUM FULL可回收已更新或已删除的数据所占据…...

IvorySQL 4.2 发布
IvorySQL 4.2 已于 2025 年 1 月 13 日正式发布。新版本全面支持 PostgreSQL 17.2,并修复了多项 bug。 增强功能 PostgreSQL 17.1 增强功能 确保当 RLS 应用于非顶级表引用时,缓存的计划会标记为依赖于调用角色使 libpq 在 SSL 或 GSS 协议协商期间丢…...

浅谈云计算20 | OpenStack管理模块(下)
OpenStack管理模块(下) 五、存储管理5.1 存储管理概述 5.2 架构设计5.2.1 Cinder块存储架构5.2.2 Swift对象存储架构 六、网络管理6.1 网络管理概述6.2 架构解析6.2.1 Neutron网络服务架构6.2.2 网络拓扑架构 6.3 原理与流程6.3.1 网络创建原理6.3.2 网络…...

去年社融增量超32万亿 货币信贷平稳增长-乐享数科
数据显示,2024年全年,社会融资规模增量为32.26万亿元;去年12月末,社会融资规模同比增长8.0%,广义货币供应量(M_[2])同比增长7.3%,人民币贷款同比增长7.6%,增速相比上月有…...

STM32 HAL库函数入门指南:从原理到实践
1 STM32 HAL库概述 STM32 HAL(Hardware Abstraction Layer)库是ST公司专门为STM32系列微控制器开发的一套硬件抽象层函数库。它的核心设计理念是在应用层与硬件层之间建立一个抽象层,这个抽象层屏蔽了底层硬件的具体实现细节,为开发者提供了一套统一的、…...

React封装倒计时按钮
背景 在开发过程中,经常需要使用到倒计时的场景,当用户点击后,按钮进行倒计时,然后等待邮件或者短信发送,每次都写重复代码,会让代码显得臃肿,所以封装一个组件来减少耦合 创建一个倒计时组件…...

深入探究Linux树状目录结构
Linux 作为一款广泛使用的开源操作系统,其目录结构采用了树状设计,这种结构清晰、有条理,便于用户和系统进行文件管理与操作。 一、根目录(/) 根目录是整个 Linux 文件系统的起始点,就像一棵大树的根部&…...

Realsense相机驱动安装及其ROS通讯配置——机器人抓取系统基础系列(四)
文章目录 概要1 Realsense相机驱动安装Method1: 使用Intel服务器预编译包Method2: 使用ROS服务器预编译包Method3: 使用SDK源代码方法对比总结 2 Realsense-ROS通讯配置与使用2.1 Realsense-ROS包安装2.2 ROS节点启动 小结Reference 概要 本文首先阐述了Realsense相机驱动安装…...

linux安装nvm
下载命令 wget https://github.com/nvm-sh/nvm/archive/refs/tags/v0.39.1.tar.gz当前盘打开终端后的nvm文件夹中 mkdir -p /nvm/.nvm如果树根不够就用加sudo 解压文件 tar xvf v0.39.1.tar.gz输入pwd 确定当前文件完成路径 在当前文件中写入。bashrc文件及代码回车进入编辑…...

图论1-问题 C: 算法7-6:图的遍历——广度优先搜索
题目描述 广度优先搜索遍历类似于树的按层次遍历的过程。其过程为:假设从图中的某顶点v出发,在访问了v之后依次访问v的各个未曾被访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先…...

基于 STM32 的多功能时间管理器项目
引言 在快节奏的生活中,时间管理显得尤为重要。本项目旨在通过 STM32 开发一个多功能时间管理器,功能包括计时器、闹钟和日历。用户可以方便地设置不同的提醒和计时任务,以更好地管理日常生活和工作。 项目名称 多功能时间管理器 环境准备 …...

Java工程结构:二方库依赖规约
文章目录 I jar 包分类一方库:二方库:三方库:II 专有名词GAV(GroupId、ArtifactId、Version):Maven 坐标III GAV 规则GroupId 格式ArtifactId 格式二方库版本号命名方式:主版本号.次版本号.修订号I jar 包分类 一方库: 本工程内部子项目模块依赖的库(jar 包)。 二…...

Django自带admin管理系统使用
1、admin路径地址 localhost:8000/admin 2、使用命令行创建超级管理员 python manage.py createsuperuser 之后按照提示一步一步往下走就好了。 3、修改管理员密码 python manage.py changepassword admin admin是超级管理员的账号 4、后台管理系统注册模型,…...

Jmeter 简单使用、生成测试报告(一)
一、下载Jmter 去官网下载,我下载的是apache-jmeter-5.6.3.zip,解压后就能用。 二、安装java环境 JMeter是基于Java开发的,运行JMeter需要Java环境。 1.下载JDK、安装Jdk 2.配置java环境变量 3.验证安装是否成功(java -versio…...

手摸手实战前端项目CI CD
由于图片和格式解析问题,为了更好阅读体验可前往 阅读原文 CI/CD 是 持续集成(Continuous Integration) 和 持续交付/部署(Continuous Delivery/Continuous Deployment) 的缩写,是现代软件开发中的一种自动…...

【Elasticsearch】搜索类型介绍,以及使用SpringBoot实现,并展现给前端
Elasticsearch 提供了多种查询类型,每种查询类型适用于不同的搜索场景。以下是八种常见的 Elasticsearch 查询类型及其详细说明和示例。 1. Match Query 用途:用于全文搜索,会对输入的文本进行分词,并在索引中的字段中查找这些分…...

K8S中的Pod调度之亲和性调度
亲和性调度 亲和性调度是一种比硬性指定节点(使用 nodeName 或 nodeSelector)更灵活的调度策略,它允许定义一组规则,根据这些规则,调度器会尝试将 Pod 调度到最合适的节点上,但如果找不到完全匹配的节点&a…...
高等数学学习笔记 ☞ 不定积分的积分法
1. 第一换元积分法 1. 基础概念:形如的过程,称为第一换元积分法。 2. 核心思想:通过对被积函数的观察(把被积函数的形式与积分表的积分公式进行比较),把外部的部分项拿到的内部(求原函数), 然后进行拼凑,…...

【HTTP】详解
目录 HTTP 基本概念啥是HTTP,有什么用?一次HTTP请求的过程当你在浏览器中输入一个浏览器地址,它会发送什么 ?---(底层流程)HTTP的协议头请求头(对应客户端)一些请求头请求方法 响应头…...

cursor重构谷粒商城01——为何要重构谷粒商城
前言:这个系列将使用最前沿的cursor作为辅助编程工具,来快速开发一些基础的编程项目。目的是为了在真实项目中,帮助初级程序员快速进阶,以最快的速度,效率,快速进阶到中高阶程序员。 本项目将基于谷粒商城…...

如何在 ASP.NET Core 中实现速率限制?
在 ASP.NET Core 中实现速率限制(Rate Limiting)中间件可以帮助你控制客户端对 API 的请求频率,防止滥用和过载。速率限制通常用于保护服务器资源,确保服务的稳定性和可用性。 ASP.NET Core 本身并没有内置的速率限制中间件&…...

STM32-笔记43-低功耗
一、什么是低功耗? 低功耗是指通过优化设计和采用特定的技术手段,降低电子设备在运行过程中消耗的能量,从而延长电池寿命、提高性能和减少发热。低功耗设计主要从芯片设计和系统设计两个方面进行,旨在减少所有器件的功率损耗&am…...

Facebook 隐私风波:互联网时代数据安全警钟
在社交媒体飞速发展的今天,个人数据的隐私保护已成为全球关注的焦点。作为全球最大的社交平台之一,Facebook面临的隐私问题,尤其是数据泄露事件,频繁引发公众的广泛讨论。从用户信息被滥用到数据泄漏,Facebook的隐私挑…...

Java 中的 ZoneOffset
介绍 在我们的这个世界上因为地球是圆的,所以每个国家都会有自己特定的时区。 时区在我们对时间的使用上扮演了非常重要的角色。但又因为时区的存在,又给我们带来了很多的麻烦,比如北美地区使用的夏令时和中国统一使用东 8 区的时间等。 当…...

amis模板语法、数据映射与表达式
模板字符串 表达式中获取变量 可以支持在普通文本中,使用数据映射语法:${xxx} 获取数据域中变量的值 "Hello ${text}"渲染 html 使用数据映射语法:${xxx} 获取数据域中变量的值,并渲染 HTML "<h1>Hello<…...

频域增强通道注意力机制EFCAM模型详解及代码复现
背景与动机 在深度学习领域,如何有效处理时间序列数据一直是一个重要的研究方向。近年来, 频域分析技术 在时间序列处理中展现出了巨大潜力,特别是离散余弦变换(DCT)因其能够高效捕捉低频信息并避免高频噪声干扰而受到广泛关注。 FECAM模型的开发正是基于这一背景,旨在…...

GitLab 国际站中国大陆等地区停服,如何将数据快速迁移到云效
代码托管平台 GitLab 国际站(GitLab.com)近日发布公告,官宣即将停止对中国大陆、香港、澳门地区的用户账号提供服务,并提供 60 天过渡期自行迁移账户数据,超期未迁移的账号可能会被 GitLab 清除。这一重要决策引起了全…...

BPG图像库和实用程序(译)
1)快速介绍 编辑Makefile以更改编译选项(默认编译选项对于Linux应该是OK的)。输入make来编译,输入make install来安装编译后的二进制文件。bpgview:为了编译它,你需要安装SDL和SDL_image库。Emscripten的使用ÿ…...

简述1个业务过程:从客户端调用接口,再到调用中间件(nacos、redis、kafka、feign),数据库的过程
以下是一个常见的业务过程示例,展示了从客户端调用接口,再到调用中间件(Nacos、Redis、Kafka、Feign)和数据库的过程: 假设我们有一个电商系统,客户端要查询某个商品的详细信息,这个商品信息可…...