【Kubernetes】在K8s中創建StatefulSet


在K8s中創建StatefulSet

遇到的問題:

使用Deployment創建的Pod是無狀態的,當掛在Volume之后,如果該Pod掛了,Replication Controller會再run一個來保證可用性,但是由於是無狀態的,Pod掛了的時候與之前的Volume的關系就已經斷開了,新起來的Pod無法找到之前的Pod。但是對於用戶而言,他們對底層的Pod掛了沒有感知,但是當Pod掛了之后就無法再使用之前掛載的磁盤了。

解決方案

使用K8s v1.5版本推出的StatefulSet可以保留Pod的狀態。

參考博客

因為Kubernetes1.5版本發布也沒過多久,國內的資料相當的少,除了tonybai等大牛博客上有一些StatefulSet的資料外,只能去外網上搜索了。通過在google上搜索StatefulSet的創建方式,最終發現了一篇英文博客,鏈接如下。對於這種新興框架,還是要多去google啊。

https://thenewstack.io/deploy-highly-available-wordpress-instance-statefulset-kubernetes-1-5/

如何創建

在創建StatefulSet之前需要准備的東西,值得注意的是創建順序非常關鍵,創建順序如下:

  • 1、Volume
  • 2、Persistent Volume
  • 3、Persistent Volume Claim
  • 4、Service
  • 5、StatefulSet

Volume可以有很多種類型,比如nfs、glusterfs等,我們這里使用的ceph RBD來創建。

創建Volume

sudo rbd create {volume_name} --size 1024 -m {ceph-monitor-ip} -k /etc/ceph/ceph.client.admin.keyring
//禁止掉一些rdb的feature,否則掛載會失敗
rbd feature disable volume101 exclusive-lock, object-map, fast-diff, deep-flatten

創建PersistentVolume

創建pv.yaml,內容如下:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: {pv_name}
  labels:
	{label_key}:{label_value}
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  rbd:
    monitors:
      - {ceph-monitor-ip}
    pool: rbd
    image: {volume_name}
    user: admin
    secretRef:
      name: ceph-secret
    fsType: ext4
    readOnly: false
  persistentVolumeReclaimPolicy: Recycle

使用

kubectl create -f pv.yaml

來創建PV。

創建PersistentVolumeClaim

這一步非常非常的關鍵,因為如果創建的PVC的名稱和StatefulSet中的名稱沒有對應上,那么StatefulSet中的Pod就肯定創建不成功,我在這一步被卡了一天之久,還好看到上面那篇外文博客,才發現PVC和StatefulSet中的命名的規律。接下來細說一下需要注意的地方。

創建pvc.yaml如下:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: db-mysql-0
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

我們在這里創建了一個叫做db-mysql-0的PVC,這個名字是不是很奇怪,而且在這個yaml里並沒有提到PV的名字,所以PV和PVC是怎么bound起來的呢?是通過labels標簽下的key:value鍵值對來進行匹配的,我們在創建PV時指定了label的鍵值對,在PVC里通過selector可以指定label。

然后再回到這個PVC的名稱定義:db-mysql-0,為什么叫這樣一個看似有規律的名字呢,這里需要看一下下一小節創建StatefulSet中的yaml,首先我們看到StatefulSet的name叫mysql,設置的replicas為2個,volumeMounts和volumeClaimTemplates的name必須相同,為db,所以StatefulSet創建的第一個Pod的name應該為mysql-0,第二個為mysql-1。這里StatefulSet中的Pod與PVC之間的綁定關系是通過名稱來匹配的,即:

PVC_name === volumeClaimTemplates_name + "-" + pod_name

所以這個問題就有點意思了,我們要先創建PVC,但是PVC的名稱實際上是由StatefulSet來確定的。我真的是不知道K8S設計者咋想的·····而且官方文檔里創建StatefulSet的例子是直接給了個yaml文件,並沒有告訴說要先創建什么再創建什么。

創建Service 和 StatefulSet

在上一步中我們已經創建了名為db-mysql-0的PVC了,接下來創建一個service和statefulset,service的名稱可以隨意取,但是statefulset的名稱已經定死了,為mysql,並且statefulset中的volumeClaimTemplates_name必須為db,volumeMounts_name也必須為db。只有這樣,statefulset中的pod才能通過命名來匹配到PVC,否則會創建失敗。

statefulset.yaml

apiVersion: v1
kind: Service
metadata:
  name: mysql-service
  labels:
    app: mysql
spec:
  ports:
  - port: 80
    name: my-port
  clusterIP: None
  selector:
    app: mysql
---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: "mysql-service"
  replicas: 2
  template:
    metadata:
      labels:
        app: mysql
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: mysqlpod
        image: mysql:latest
        ports:
        - containerPort: 80
          name: my-port
        volumeMounts:
        - name: db
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: db
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

運行以下命令:

kubectl create -f statefulset.yaml

就可以創建statefulset了。


免責聲明!

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



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