k8s控制器:StatefulSet


k8s控制器:StatefulSet

一、Statefulset控制器概述

StatefulSet是為了管理有狀態服務的問題而設計的

1.1、有狀態/無狀態服務

1)有狀態服務:StatefulSet是有狀態的集合,管理有狀態的服務,它所管理的Pod的名稱不能隨意變化。數據持久化的目錄也是不一樣,每一個Pod都有自己獨有的數據持久化存儲目錄。比如MySQL主從、redis集群等

2)無狀態服務:RC、Deployment、DaemonSet都是管理無狀態的服務,它們所管理的Pod的IP、名字,啟停順序等都是隨機的。個體對整體無影響,所有pod都是共用一個數據卷的,部署的tomcat就是無狀態的服務,tomcat被刪除,在啟動一個新的tomcat,加入到集群即可,跟tomcat的名字無關。

1.2、Headless service

1.2.1、什么是Headless service

Headless service不分配clusterIP,headless service可以通過解析service的DNS,返回所有Pod的dns和ip地址 (statefulSet部署的Pod才有DNS),普通的service,只能通過解析service的DNS返回service的ClusterIP。

1.2.2、為什么要用headless service

在使用Deployment時,創建的Pod名稱是沒有順序的,是隨機字符串,在用statefulset管理pod時要求pod名稱必須是有序的 ,每一個pod不能被隨意取代,pod重建后pod名稱還是一樣的。因為pod IP是變化的,所以要用Pod名稱來識別。pod名稱是pod唯一性的標識符,必須持久穩定有效。這時候要用到無頭服務,它可以給每個Pod一個唯一的名稱。

1)headless service會為service分配一個域名:<service name>.$<namespace name>.svc.cluster.local

2)StatefulSet會為關聯的Pod保持一個不變的Pod Name:$(StatefulSet name)-$(pod序號)

3)StatefulSet會為關聯的Pod分配一個dnsName:$<Pod Name>.$<service name>.$<namespace name>.svc.cluster.local

1.3、volumeClaimTemplate

對於有狀態應用都會用到持久化存儲,比如mysql主從,由於主從數據庫的數據是不能存放在一個目錄下的,每個mysql節點都需要有自己獨立的存儲空間。而在deployment中創建的存儲卷是一個共享的存儲卷,多個pod使用同一個存儲卷,它們數據是同步的,而statefulset定義中的每一個pod都不能使用同一個存儲卷,這就需要使用volumeClainTemplate,當在使用statefulset創建pod時,volumeClainTemplate會自動生成一個PVC,從而請求綁定一個PV,每一個pod都有自己專用的存儲卷。Pod、PVC和PV對應的關系圖如下:

image-20210711080852884

二、Statefulset使用案例:部署web站點

# 創建存儲類
[root@k8s-master1 ~]# cat class-web.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-web
provisioner: example.com/nfs

# 更新資源清單文件
[root@k8s-master1 ~]# kubectl apply -f class-web.yaml
[root@k8s-master1 ~]# kubectl get storageclass
NAME      PROVISIONER       RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-web   example.com/nfs   Delete          Immediate           false                  30s

# 編寫一個Statefulset資源清單文件
[root@k8s-master1 ~]# cat statefulset.yaml 
apiVersion: v1
kind: Service
metadata: 
  name: nginx
  labels:
     app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata: 
  name: web
spec:
  selector:
    matchLabels:
      app: nginx
  serviceName: "nginx"
  replicas: 2
  template:
    metadata: 
     labels:
       app: nginx
    spec: 
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "nfs-web"
      resources:
        requests: 
          storage: 1Gi

# 更新資源清單文件
[root@k8s-master1 ~]# kubectl apply -f statefulset.yaml 
service/nginx created
statefulset.apps/web created

# 查看無頭服務
[root@k8s-master1 ~]# kubectl describe svc nginx 
Name:              nginx
Namespace:         default
Labels:            app=nginx
Annotations:       <none>
Selector:          app=nginx
Type:              ClusterIP
IP Families:       <none>
IP:                None
IPs:               None
Port:              web  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.36.122:80,10.244.36.123:80
Session Affinity:  None
Events:            <none>

# 查看statefulset是否創建成功
[root@k8s-master1 ~]# kubectl get statefulset
NAME   READY   AGE
web    2/2     13s 

# 查看pod: 可以看到創建的pod是有序的
[root@k8s-master1 ~]# kubectl get pods -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          35s
web-1   1/1     Running   0          29s

# 查看headless service
[root@k8s-master1 ~]# kubectl get pods -l app=nginx -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP              NODE        NOMINATED NODE   READINESS GATES
web-0   1/1     Running   0          4m22s   10.244.36.122   k8s-node1   <none>           <none>
web-1   1/1     Running   0          4m16s   10.244.36.123   k8s-node1   <none>           <none>

# 查看pvc
[root@k8s-master1 ~]# kubectl get pvc
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-web-0     Bound    pvc-de5c7090-9d53-4597-b292-233f27534764   1Gi        RWO            nfs-web        92s
www-web-1     Bound    pvc-b3a2c509-f011-448e-9091-afa76726ef40   1Gi        RWO            nfs-web        87s

# 查看pv
[root@k8s-master1 ~]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGE
pvc-b3a2c509-f011-448e-9091-afa76726ef40   1Gi        RWO            Delete           Bound    default/www-web-1     nfs-web                 2m2s
pvc-de5c7090-9d53-4597-b292-233f27534764   1Gi        RWO            Delete           Bound    default/www-web-0     nfs-web                 2m8s
                    
# 查看pod主機名
[root@k8s-master1 ~]# for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname';done 
web-0
web-1

# 使用kubectl run運行一個提供nslookup命令的容器的,這個命令來自於dnsutils包,通過對pod主機名執行nslookup,可以檢查它們在集群內部的DNS地址:
[root@k8s-master1 ~]# kubectl exec -it web-1 -- /bin/bash
root@web-1:/# apt-get update
root@web-1:/# apt-get install dnsutils -y

root@web-1:/# nslookup web-0.nginx.default.svc.cluster.local  
Server:		10.96.0.10
Address:	10.96.0.10#53
Name:	web-0.nginx.default.svc.cluster.local 

# statefulset創建的pod也是有dns記錄的
Address: 10.244.36.122  #解析的是pod的ip地址

root@web-1:/# nslookup nginx.default.svc.cluster.local
Server:		10.96.0.10
Address:	10.96.0.10#53

Name:	nginx.default.svc.cluster.local  #查詢service dns,會把對應的pod ip解析出來
Address: 10.244.36.123

Name:	nginx.default.svc.cluster.local
Address: 10.244.36.122

root@web-1:/# dig -t A nginx.default.svc.cluster.local @10.96.0.10
; <<>> DiG 9.11.5-P4-5.1+deb10u5-Debian <<>> -t A nginx.default.svc.cluster.local @10.96.0.10
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57675
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 01450c2da9081da1 (echoed)
;; QUESTION SECTION:
;nginx.default.svc.cluster.local. IN	A

;; ANSWER SECTION:
nginx.default.svc.cluster.local. 30 IN	A	10.244.36.123
nginx.default.svc.cluster.local. 30 IN	A	10.244.36.122

;; Query time: 1 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Sun Jul 11 00:34:04 UTC 2021
;; MSG SIZE  rcvd: 166

三、Statefulset管理pod

3.1、實現Pod的擴縮容

方式一:修改配置文件里的replicas,然后kubectl apply

方式二:kubectl edit sts web修改replicas

3.2、實現Pod的版本更新

方式一:修改配置文件里的image,然后kubectl apply

方式二:kubectl edit sts web修改image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM