有状态负载(StatefulSet)是 Kubernetes 中的一种常见资源, 和无状态负载(Deployment)类似,主要用于管理 Pod 集合的部署和伸缩。二者的主要区别在于, Deployment 是无状态的,不保存数据,而 StatefulSet 是有状态的,主要用于管理有状态应用。此外,StatefulSet 中的 Pod 具有永久不变的 ID,便于在匹配存储卷时识别对应的 Pod。
通过 d.run 的容器管理模块,可以基于相应的角色权限轻松管理多云多集群上的工作负载,包括对有状态工作负载的创建、更新、删除、弹性扩缩、重启、版本回退等全生命周期管理。
在使用镜像创建有状态负载之前,需要满足以下前提条件:
参考以下步骤,使用镜像创建一个有状态负载。
点击左侧导航栏上的 集群列表 ,然后点击目标集群的名称,进入 集群详情 。
点击左侧导航栏的 工作负载 -> 有状态负载 ,然后点击右上角 镜像创建 按钮。
依次填写基本信息、容器配置、服务配置、高级配置后,在页面右下角点击 确定 完成创建。
系统将自动返回 有状态工作负载 列表,等待工作负载状态变为 运行中 。如果工作负载状态出现异常,请查看具体异常信息,可参考工作负载状态。
点击新建工作负载列右侧的 ︙ ,可以对工作负载执行执行更新、删除、弹性扩缩、重启、版本回退等操作。
容器配置分为基本信息、生命周期、健康检查、环境变量、数据存储、安全设置六部分,点击下方的相应页签可查看各部分的配置要求。
容器配置仅针对单个容器进行配置,如需在一个容器组中添加多个容器,可点击右侧的 + 添加多个容器。
在配置容器相关参数时,必须正确填写容器的名称、镜像参数,否则将无法进入下一步。参考以下要求填写配置后,点击 确认 。
GPU 独享:为容器配置 GPU 用量,仅支持输入正整数。GPU 配额设置支持为容器设置独享整张 GPU 卡或部分 vGPU。例如,对于一张 8 核心的 GPU 卡,输入数字 8 表示让容器独享整长卡,输入数字 1 表示为容器配置 1 核心的 vGPU。
设置 GPU 独享之前,需要管理员预先在集群节点上安装 GPU 卡及驱动插件,并在集群设置中开启 GPU 特性。
设置容器启动时、启动后、停止前需要执行的命令。详情可参考容器生命周期配置。
用于判断容器和应用的健康状态。有助于提高应用的可用性。详情可参考容器健康检查配置。
配置 Pod 内的容器参数,为 Pod 添加环境变量或传递配置等。详情可参考容器环境变量配置。
配置容器挂载数据卷和数据持久化的设置。详情可参考容器数据存储配置。
通过 Linux 内置的账号权限隔离机制来对容器进行安全隔离。您可以通过使用不同权限的账号 UID(数字身份标记)来限制容器的权限。例如,输入 0 表示使用 root 账号的权限。
为有状态负载配置服务(Service),使有状态负载能够被外部访问。
点击 创建服务 按钮。
参考创建服务,配置服务参数。
点击 确定 ,点击 下一步 。
高级配置包括负载的网络配置、升级策略、调度策略、标签与注解四部分,可点击下方的页签查看各部分的配置要求。
如在集群中部署了 SpiderPool 和 Multus 组件,则可以在网络配置中配置容器网卡。详情参考工作负载使用 IP 池。
DNS 配置:应用在某些场景下会出现冗余的 DNS 查询。Kubernetes 为应用提供了与 DNS 相关的配置选项,能够在某些场景下有效地减少冗余的 DNS 查询,提升业务并发量。
DNS 策略
域名服务器:填写域名服务器的地址,例如 10.6.175.20 。
Kubernetes v1.7 及其之后的版本可以通过 .spec.podManagementPolicy 设置 Pod 的管理策略,支持以下两种方式:
按序策略(OrderedReady) :默认的 Pod 管理策略,表示按顺序部署 Pod,只有前一个 Pod 部署 成功完成后,有状态负载才会开始部署下一个 Pod。删除 Pod 时则采用逆序,最后创建的最先被删除。
并行策略(Parallel) :并行创建或删除容器,和 Deployment 类型的 Pod 一样。StatefulSet 控制器并行地启动或终止所有的容器。启动或者终止其他 Pod 前,无需等待 Pod 进入 Running 和 ready 或者完全停止状态。 这个选项只会影响扩缩操作的行为,不影响更新时的顺序。
具体详情请参考调度策略。
可以点击 添加 按钮为工作负载和容器组添加标签和注解。
除了通过镜像方式外,还可以通过 YAML 文件更快速地创建创建有状态负载。
点击左侧导航栏上的 集群列表 ,然后点击目标集群的名称,进入 集群详情 页面。
在集群详情页面,点击左侧导航栏的 工作负载 -> 有状态负载 ,然后点击页面右上角的 YAML 创建 按钮。
输入或粘贴事先准备好的 YAML 文件,点击 确定 即可完成创建。
kind: StatefulSet
apiVersion: apps/v1
metadata:
name: test-mysql-123-mysql
namespace: default
uid: d3f45527-a0ab-4b22-9013-5842a06f4e0e
resourceVersion: '20504385'
generation: 1
creationTimestamp: '2022-09-22T09:34:10Z'
ownerReferences:
- apiVersion: mysql.presslabs.org/v1alpha1
kind: MysqlCluster
name: test-mysql-123
uid: 5e877cc3-5167-49da-904e-820940cf1a6d
controller: true
blockOwnerDeletion: true
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/managed-by: mysql.presslabs.org
app.kubernetes.io/name: mysql
mysql.presslabs.org/cluster: test-mysql-123
template:
metadata:
creationTimestamp: null
labels:
app.kubernetes.io/component: database
app.kubernetes.io/instance: test-mysql-123
app.kubernetes.io/managed-by: mysql.presslabs.org
app.kubernetes.io/name: mysql
app.kubernetes.io/version: 5.7.31
mysql.presslabs.org/cluster: test-mysql-123
annotations:
config_rev: '13941099'
prometheus.io/port: '9125'
prometheus.io/scrape: 'true'
secret_rev: '13941101'
spec:
volumes:
- name: conf
emptyDir: {}
- name: init-scripts
emptyDir: {}
- name: config-map
configMap:
name: test-mysql-123-mysql
defaultMode: 420
- name: data
persistentVolumeClaim:
claimName: data
initContainers:
- name: init
image: docker.m.daocloud.io/bitpoke/mysql-operator-sidecar-5.7:v0.6.1
args:
- clone-and-init
envFrom:
- secretRef:
name: test-mysql-123-mysql-operated
env:
- name: MY_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: MY_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: MY_POD_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
- name: MY_SERVICE_NAME
value: mysql
- name: MY_CLUSTER_NAME
value: test-mysql-123
- name: MY_FQDN
value: $(MY_POD_NAME).$(MY_SERVICE_NAME).$(MY_NAMESPACE)
- name: MY_MYSQL_VERSION
value: 5.7.31
- name: BACKUP_USER
valueFrom:
secretKeyRef:
name: test-mysql-123-mysql-operated
key: BACKUP_USER
optional: true
- name: BACKUP_PASSWORD
valueFrom:
secretKeyRef:
name: test-mysql-123-mysql-operated
key: BACKUP_PASSWORD
optional: true
resources: {}
volumeMounts:
- name: conf
mountPath: /etc/mysql
- name: config-map
mountPath: /mnt/conf
- name: data
mountPath: /var/lib/mysql
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
containers:
- name: mysql
image: docker.m.daocloud.io/mysql:5.7.31
ports:
- name: mysql
containerPort: 3306
protocol: TCP
env:
- name: MY_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: MY_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: MY_POD_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
- name: MY_SERVICE_NAME
value: mysql
- name: MY_CLUSTER_NAME
value: test-mysql-123
- name: MY_FQDN
value: $(MY_POD_NAME).$(MY_SERVICE_NAME).$(MY_NAMESPACE)
- name: MY_MYSQL_VERSION
value: 5.7.31
- name: ORCH_CLUSTER_ALIAS
value: test-mysql-123.default
- name: ORCH_HTTP_API
value: http://mysql-operator.mcamel-system/api
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: test-mysql-123-secret
key: ROOT_PASSWORD
optional: false
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: test-mysql-123-secret
key: USER
optional: true
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: test-mysql-123-secret
key: PASSWORD
optional: true
- name: MYSQL_DATABASE
valueFrom:
secretKeyRef:
name: test-mysql-123-secret
key: DATABASE
optional: true
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: 100m
memory: 512Mi
volumeMounts:
- name: conf
mountPath: /etc/mysql
- name: data
mountPath: /var/lib/mysql
livenessProbe:
exec:
command:
- mysqladmin
- '--defaults-file=/etc/mysql/client.conf'
- ping
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 5
successThreshold: 1
failureThreshold: 3
readinessProbe:
exec:
command:
- /bin/sh
- '-c'
- >-
test $(mysql --defaults-file=/etc/mysql/client.conf -NB -e
'SELECT COUNT(*) FROM sys_operator.status WHERE
name="configured" AND value="1"') -eq 1
initialDelaySeconds: 5
timeoutSeconds: 5
periodSeconds: 2
successThreshold: 1
failureThreshold: 3
lifecycle:
preStop:
exec:
command:
- bash
- /etc/mysql/pre-shutdown-ha.sh
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
- name: sidecar
image: docker.m.daocloud.io/bitpoke/mysql-operator-sidecar-5.7:v0.6.1
args:
- config-and-serve
ports:
- name: sidecar-http
containerPort: 8080
protocol: TCP
envFrom:
- secretRef:
name: test-mysql-123-mysql-operated
env:
- name: MY_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: MY_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: MY_POD_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
- name: MY_SERVICE_NAME
value: mysql
- name: MY_CLUSTER_NAME
value: test-mysql-123
- name: MY_FQDN
value: $(MY_POD_NAME).$(MY_SERVICE_NAME).$(MY_NAMESPACE)
- name: MY_MYSQL_VERSION
value: 5.7.31
- name: XTRABACKUP_TARGET_DIR
value: /tmp/xtrabackup_backupfiles/
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: 10m
memory: 64Mi
volumeMounts:
- name: conf
mountPath: /etc/mysql
- name: data
mountPath: /var/lib/mysql
readinessProbe:
httpGet:
path: /health
port: 8080
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 5
periodSeconds: 5
successThreshold: 1
failureThreshold: 3
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
- name: metrics-exporter
image: prom/mysqld-exporter:v0.13.0
args:
- '--web.listen-address=0.0.0.0:9125'
- '--web.telemetry-path=/metrics'
- '--collect.heartbeat'
- '--collect.heartbeat.database=sys_operator'
ports:
- name: prometheus
containerPort: 9125
protocol: TCP
env:
- name: MY_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: MY_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: MY_POD_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
- name: MY_SERVICE_NAME
value: mysql
- name: MY_CLUSTER_NAME
value: test-mysql-123
- name: MY_FQDN
value: $(MY_POD_NAME).$(MY_SERVICE_NAME).$(MY_NAMESPACE)
- name: MY_MYSQL_VERSION
value: 5.7.31
- name: USER
valueFrom:
secretKeyRef:
name: test-mysql-123-mysql-operated
key: METRICS_EXPORTER_USER
optional: false
- name: PASSWORD
valueFrom:
secretKeyRef:
name: test-mysql-123-mysql-operated
key: METRICS_EXPORTER_PASSWORD
optional: false
- name: DATA_SOURCE_NAME
value: $(USER):$(PASSWORD)@(127.0.0.1:3306)/
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 10m
memory: 32Mi
livenessProbe:
httpGet:
path: /metrics
port: 9125
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 30
periodSeconds: 30
successThreshold: 1
failureThreshold: 3
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
- name: pt-heartbeat
image: docker.m.daocloud.io/bitpoke/mysql-operator-sidecar-5.7:v0.6.1
args:
- pt-heartbeat
- '--update'
- '--replace'
- '--check-read-only'
- '--create-table'
- '--database'
- sys_operator
- '--table'
- heartbeat
- '--utc'
- '--defaults-file'
- /etc/mysql/heartbeat.conf
- '--fail-successive-errors=20'
env:
- name: MY_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: MY_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: MY_POD_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
- name: MY_SERVICE_NAME
value: mysql
- name: MY_CLUSTER_NAME
value: test-mysql-123
- name: MY_FQDN
value: $(MY_POD_NAME).$(MY_SERVICE_NAME).$(MY_NAMESPACE)
- name: MY_MYSQL_VERSION
value: 5.7.31
resources:
limits:
cpu: 100m
memory: 64Mi
requests:
cpu: 10m
memory: 32Mi
volumeMounts:
- name: conf
mountPath: /etc/mysql
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
securityContext:
runAsUser: 999
fsGroup: 999
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app.kubernetes.io/component: database
app.kubernetes.io/instance: test-mysql-123
app.kubernetes.io/managed-by: mysql.presslabs.org
app.kubernetes.io/name: mysql
app.kubernetes.io/version: 5.7.31
mysql.presslabs.org/cluster: test-mysql-123
topologyKey: kubernetes.io/hostname
schedulerName: default-scheduler
volumeClaimTemplates:
- kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: data
creationTimestamp: null
ownerReferences:
- apiVersion: mysql.presslabs.org/v1alpha1
kind: MysqlCluster
name: test-mysql-123
uid: 5e877cc3-5167-49da-904e-820940cf1a6d
controller: true
spec:
accessModes:
- ReadWriteOnce
resources:
limits:
storage: 1Gi
requests:
storage: 1Gi
storageClassName: local-path
volumeMode: Filesystem
status:
phase: Pending
serviceName: mysql
podManagementPolicy: OrderedReady
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
revisionHistoryLimit: 10
status:
observedGeneration: 1
replicas: 1
readyReplicas: 1
currentReplicas: 1
updatedReplicas: 1
currentRevision: test-mysql-123-mysql-6b8f5577c7
updateRevision: test-mysql-123-mysql-6b8f5577c7
collisionCount: 0
availableReplicas: 1