当前位置: 首页 > news >正文

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之间可以通过主机名进行访问,通常是通过以下几种方式实现的:

  1. 直接使用Pod的DNS:每个Pod在Kubernetes集群中都有一个DNS条目,你可以直接使用Pod的名称来进行访问,不过这种方法不推荐用在生产环境,因为Pod的IP地址会随着重启发生变化。

  2. 使用Service进行访问

    • ClusterIP:这是Kubernetes中Service的默认类型。Service为一组Pod提供了一个稳定的IP地址和DNS名称。你可以通过Service的名称来访问Pod,Service会自动进行负载均衡。

    • Headless Service:如果需要直接获取Pod的IP地址,可以创建一个Headless Service。通过将Service的clusterIP字段设置为None来创建。这样,Kubernetes会为这个Service的每个Pod创建一个DNS记录。

  3. StatefulSets

    • 对于有状态应用,比如ZooKeeper、Cassandra等,可以使用StatefulSets来部署。这种资源类型会为每个Pod分配稳定的主机名,格式通常为<podname>.<headless-service-name>.<namespace>.svc.cluster.local

在 Kubernetes 中,DeploymentStatefulSet 是两种常用的工作负载(Workload)资源类型,它们用于管理 Pod 的部署和伸缩。虽然它们都可以用于管理应用程序的副本,但它们在处理 Pod 的方式和适用的场景上有着显著的区别。

以下将详细解释 DeploymentStatefulSet 的主要区别,以及它们各自的适用场景。


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-0my-app-1
  • 持久化存储卷的绑定:通过 VolumeClaimTemplates,每个 Pod 都有自己的持久化存储卷。

适用场景:

  • 需要持久化数据的有状态应用程序。
  • 应用程序实例需要稳定的身份(例如,需要特定的主机名或 IP 地址)。
  • 应用程序实例之间需要有序部署或终止。

3. 主要区别

特性DeploymentStatefulSet
适用应用类型无状态应用程序有状态应用程序
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-0mysql-statefulset-1mysql-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命令定期对每个表进行维护&#xff0c;主要有以下原因&#xff1a; VACUUM FULL可回收已更新或已删除的数据所占据…...

IvorySQL 4.2 发布

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

浅谈云计算20 | OpenStack管理模块(下)

OpenStack管理模块&#xff08;下&#xff09; 五、存储管理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万亿 货币信贷平稳增长-乐享数科

数据显示&#xff0c;2024年全年&#xff0c;社会融资规模增量为32.26万亿元&#xff1b;去年12月末&#xff0c;社会融资规模同比增长8.0%&#xff0c;广义货币供应量&#xff08;M_[2]&#xff09;同比增长7.3%&#xff0c;人民币贷款同比增长7.6%&#xff0c;增速相比上月有…...

STM32 HAL库函数入门指南:从原理到实践

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

React封装倒计时按钮

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

深入探究Linux树状目录结构

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

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:图的遍历——广度优先搜索

题目描述 广度优先搜索遍历类似于树的按层次遍历的过程。其过程为&#xff1a;假设从图中的某顶点v出发&#xff0c;在访问了v之后依次访问v的各个未曾被访问过的邻接点&#xff0c;然后分别从这些邻接点出发依次访问它们的邻接点&#xff0c;并使“先被访问的顶点的邻接点”先…...

基于 STM32 的多功能时间管理器项目

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

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、后台管理系统注册模型&#xff0c;…...

Jmeter 简单使用、生成测试报告(一)

一、下载Jmter 去官网下载&#xff0c;我下载的是apache-jmeter-5.6.3.zip&#xff0c;解压后就能用。 二、安装java环境 JMeter是基于Java开发的&#xff0c;运行JMeter需要Java环境。 1.下载JDK、安装Jdk 2.配置java环境变量 3.验证安装是否成功&#xff08;java -versio…...

手摸手实战前端项目CI CD

由于图片和格式解析问题&#xff0c;为了更好阅读体验可前往 阅读原文 CI/CD 是 持续集成&#xff08;Continuous Integration&#xff09; 和 持续交付/部署&#xff08;Continuous Delivery/Continuous Deployment&#xff09; 的缩写&#xff0c;是现代软件开发中的一种自动…...

【Elasticsearch】搜索类型介绍,以及使用SpringBoot实现,并展现给前端

Elasticsearch 提供了多种查询类型&#xff0c;每种查询类型适用于不同的搜索场景。以下是八种常见的 Elasticsearch 查询类型及其详细说明和示例。 1. Match Query 用途&#xff1a;用于全文搜索&#xff0c;会对输入的文本进行分词&#xff0c;并在索引中的字段中查找这些分…...

K8S中的Pod调度之亲和性调度

亲和性调度 亲和性调度是一种比硬性指定节点&#xff08;使用 nodeName 或 nodeSelector&#xff09;更灵活的调度策略&#xff0c;它允许定义一组规则&#xff0c;根据这些规则&#xff0c;调度器会尝试将 Pod 调度到最合适的节点上&#xff0c;但如果找不到完全匹配的节点&a…...

高等数学学习笔记 ☞ 不定积分的积分法

1. 第一换元积分法 1. 基础概念&#xff1a;形如的过程&#xff0c;称为第一换元积分法。 2. 核心思想&#xff1a;通过对被积函数的观察(把被积函数的形式与积分表的积分公式进行比较)&#xff0c;把外部的部分项拿到的内部(求原函数)&#xff0c; 然后进行拼凑&#xff0c;…...

【HTTP】详解

目录 HTTP 基本概念啥是HTTP&#xff0c;有什么用&#xff1f;一次HTTP请求的过程当你在浏览器中输入一个浏览器地址&#xff0c;它会发送什么 &#xff1f;---&#xff08;底层流程&#xff09;HTTP的协议头请求头&#xff08;对应客户端&#xff09;一些请求头请求方法 响应头…...

cursor重构谷粒商城01——为何要重构谷粒商城

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

如何在 ASP.NET Core 中实现速率限制?

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

STM32-笔记43-低功耗

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

Facebook 隐私风波:互联网时代数据安全警钟

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

Java 中的 ZoneOffset

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

amis模板语法、数据映射与表达式

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

频域增强通道注意力机制EFCAM模型详解及代码复现

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

GitLab 国际站中国大陆等地区停服,如何将数据快速迁移到云效

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

BPG图像库和实用程序(译)

1)快速介绍 编辑Makefile以更改编译选项&#xff08;默认编译选项对于Linux应该是OK的&#xff09;。输入make来编译&#xff0c;输入make install来安装编译后的二进制文件。bpgview&#xff1a;为了编译它&#xff0c;你需要安装SDL和SDL_image库。Emscripten的使用&#xff…...

简述1个业务过程:从客户端调用接口,再到调用中间件(nacos、redis、kafka、feign),数据库的过程

以下是一个常见的业务过程示例&#xff0c;展示了从客户端调用接口&#xff0c;再到调用中间件&#xff08;Nacos、Redis、Kafka、Feign&#xff09;和数据库的过程&#xff1a; 假设我们有一个电商系统&#xff0c;客户端要查询某个商品的详细信息&#xff0c;这个商品信息可…...