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:適用于有狀態、需要持久化存儲和穩定網絡標識的應用程序,確保應用程序的可靠性和一致性。