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

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: 2
  renderer: networkd
  ethernets:
    ens3:
      addresses:
        - 192.168.122.140/24
      gateway4: 192.168.122.1
      nameservers:
        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/16

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

kubectl 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: ubuntu
  tag: "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: false
          env:
            - name: MASTER_ADDR
              value: "{{ include "llama-training.fullname" . }}-headless"
            - name: MASTER_PORT
              value: "{{ .Values.masterPort }}"
            - name: WORLD_SIZE
              value: "{{ .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" . }}-headless
  labels:
    {{- include "llama-training.labels" . | nindent 4 }}
spec:
  clusterIP: None  # 使其成为 Headless Service
  selector:
    {{- 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" . }}-egress
  namespace: {{ .Release.Namespace }}
  labels:
    {{- include "llama-training.labels" . | nindent 4 }}
spec:
  podSelector:
    matchLabels:
      {{- include "llama-training.selectorLabels" . | nindent 6 }}
  policyTypes:
    - Egress
  egress:
    - {}
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 ms

64 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 ms

64 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: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: 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: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        volumeMounts:
          - name: mysql-data
            mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: mysql-data
    spec:
      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:适用于有状态、需要持久化存储和稳定网络标识的应用程序,确保应用程序的可靠性和一致性。


http://www.kler.cn/a/506079.html

相关文章:

  • 01.02、判定是否互为字符重排
  • 【后端面试总结】tls中.crt和.key的关系
  • SpringCloud源码-Ribbon
  • 如何优化Elasticsearch大文档查询?
  • Js:正则表达式及正则表达式方法
  • 【C语言】线程----同步、互斥、条件变量
  • 解锁转型密码:不同方向的技能与素质修炼手册
  • PHP与HTML、CSS、JavaScript、jQuery的关系**
  • 主动出击,在去中心化世界中成为连接中心
  • 线性变换与矩阵的关系及其在机器学习中的应用
  • GoLang教程004:流程控制和if语句介绍
  • 微信小程序在使用页面栈保存页面信息时,如何避免数据丢失?
  • C#局部函数 VS Lambda表达式
  • LLMs之RAG:《EdgeRAG: Online-Indexed RAG for Edge Devices》翻译与解读
  • 使用 JUnit 和 SuiteRunner 测试私有方法
  • AI辅助编程:快速构建软件原型,开启高效开发新纪元
  • 《探秘火焰目标检测开源模型:智能防火的科技利刃》
  • SpringBoot 集成 Gitee 实现三方登录
  • 5套经典行业原型-含生鲜电商、旅游社交、O2O美食、汽车美容行业
  • python-应用自动化操作方法集合
  • 漫话架构师|什么是系统架构设计师(开篇)
  • 【Mysql进阶知识】
  • MyBatis-Plus6--MyBatis中的分页插件
  • 物联网网关Web服务器--lighttpd服务器部署与应用测试
  • 【深度学习基础】线性神经网络 | 图像分类数据集
  • 读书笔记~管理修炼-101℃理论:在绝境中找到新的生机