k8s入门:StatefulSet 简单使用

系列文章目录

第一章:✨ k8s入门:裸机部署 k8s 集群
第二章:✨ k8s入门:部署应用到 k8s 集群
第三章:✨ k8s入门:service 简单使用
第四章:✨ k8s入门:StatefulSet 简单使用
第五章:✨ k8s入门:存储(storage)
第六章:✨ K8S 配置 storageclass 使用 nfs 动态申领本地磁盘空间
第七章:✨ k8s入门:配置 ConfigMap & Secret
第八章:✨ k8s入门:k8s入门:Helm 构建 MySQL
第九章:✨ k8s入门:kubernetes-dashboard 安装
第十章:✨ k8s入门:kube-prometheus-stack 全家桶搭建(Grafana + Prometheus)



参考文章:

一、什么是 StatefulSet

StatefulSet 是用来管理有状态的应用,例如数据库。
前面我们部署的应用,都是不需要存储数据,不需要记住状态的,可以随意扩充副本,每个副本都是一样的,可替代的。
而像数据库、Redis 这类有状态的,则不能随意扩充副本。
StatefulSet 会固定每个 Pod 的名字

二、部署 StatefulSet 类型的 redis
1、创建 StatefulSet 以及 service

创建 redis-StatefulSet.yaml 文件,添加如下内容,配置文件添加了 StatefulSet 类型的 redis 以及 redis 的 service,StatefulSet 和 service 可以分开写,也可以写在一个文件中

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-statefulset
spec:
  serviceName: redis-service
  replicas: 3
  selector:
    matchLabels:
      app: redis-statefulset
  template:
    metadata:
      labels:
        app: redis-statefulset
    spec:
      containers:
        - name: redis
          image: redis:latest
          # IfNotPresent 仅本地没有镜像时才远程拉,Always 永远都是从远程拉,Never 永远只用本地镜像,本地没有则报错
          imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
  name: redis-service
spec:
  selector:
    app: redis-statefulset
  type: ClusterIP
  # HeadLess
  clusterIP: None
  ports:
    - port: 6379
      targetPort: 6379

使用 kubectl apply -f redis-StatefulSet.yaml 创建 statefulset (redis-statefulset-0、redis-statefulset-1、redis-statefulset-2) 以及 service (redis-service )

在这里插入图片描述
查看 pod 的 hostname

[root@master redis]# for i in 0 1 2; do kubectl exec redis-statefulset-$i -- sh -c 'hostname'; done
redis-statefulset-0
redis-statefulset-1
redis-statefulset-2
2、StatefulSet 特性
  • 仅当前一个 pod 启动,才会运行后一个(redis-statefulset-0 处于 running 状态,才会运行 redis-statefulset-1)
  • Pod 的名称的形式为<statefulset name>-<ordinal index>
  • Service 的 CLUSTER-IP 是空的,Pod 名字也是固定的。
  • Pod 创建和销毁是有序的,创建是顺序的,销毁是逆序的。(可以使用 kubectl scale 或者kubectl patch 来扩容/缩容测试,或者去修改 yaml 文件 replicas 参数)
  • 删除 pod,pod 会自动重建,重建不会改变Pod 的序号、主机名、SRV 条目和记录名称,IP会改变(每次删除 pod,删除 pod 的 IP 已被占用,新建时 IP 会追加),不要使用 IP 连接
3、连接 redis

访问时,如果直接使用 Service 名字连接,会随机转发请求,要连接指定 Pod,可以这样pod-name.service-name
运行一个临时 redis Pod 连接数据测试

# 新建redis pod,-rm:容器停止自动删除  --tty,分配终端 
kubectl run redis-client --rm --tty -i --restart='Never' --image redis:latest --command -- bash

通过 pod-name.service-name 连接指定的 redis

redis-cli -h redis-statefulset-0.redis-service -p 6379

如下,连接 redis-statefulset-0 成功,可以正常插入值获取值
在这里插入图片描述
通过 Service 名字连接,会随机连接一个 pod

  • 第一步: 通过pod-name.service-name 连接三个不同的 pod,插入不同的值 100、200、300 对应 redis-statefulset-0、redis-statefulset-1、redis-statefulset-2
  • 第二步:使用 service 连接,获取 key,可以发现连的的 redis-statefulset-0
    在这里插入图片描述
4、Web 应用连接 redis
①、更新镜像版本

在集群内部,我们可以通过服务名字访问到不同的服务,指定连接第一个:redis-statefulset-0.redis-service

springboot 添加两个访问 redis 的接口,新增和查询

  • 新增 key
    在这里插入图片描述
  • 查询 key
    在这里插入图片描述

修改 springboot 项目的 application.yaml 配置文件 spring.redis.host=redis-statefulset-0.redis-service

spring:
  redis:
    database: 0
    host: redis-statefulset-0.redis-service
    password: 123456
    port: 6379
    client-type: lettuce
    lettuce:
      pool:
        max-active: 8   #最大连接数据库连接数,设 0 为没有限制
        max-idle: 8     #最大等待连接中的数量,设 0 为没有限制
        max-wait: -1ms  #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
        min-idle: 0     #最小等待连接中的数量,设 0 为没有限制
    # url: redis://user:password@example.com:6379

将项目打包上传镜像到阿里云私人仓库 registry.cn-zhangjiakou.aliyuncs.com/k8s-private/springboot:1.3,版本为1.3

②、集群测试

aliyun-private-springboot-deployment.yaml,利用 Deployment 创建三个副本(上面上传阿里云仓库的镜像)

apiVersion: apps/v1
kind: Deployment
metadata:
  # 部署名字
  name: test-k8s-deployment
spec:
  replicas: 3
  # 用来查找关联的 Pod,所有标签都匹配才行
  selector:
    matchLabels:
      app: test-k8s-deployment
  # 定义 Pod 相关数据
  template:
    metadata:
      labels:
        app: test-k8s-deployment
    spec:
      # 定义容器,可以多个
      containers:
        - name: springboot-deployment # 容器名字
          image: registry.cn-zhangjiakou.aliyuncs.com/k8s-private/springboot:1.3 # 阿里云私人镜像
      imagePullSecrets:
        - name: mysecret

test-k8s-deployment-service-NodePort-many.yaml,创建一个可暴露多个端口的 NodePort 类型的 service,为上面 deployment 创建的 pod 暴露端口

apiVersion: v1
kind: Service
metadata:
  # 必须小写
  name: test-k8s-deployment-service-nodeport-many
spec:
  selector:
    # 对应 deployment 名字
    app: test-k8s-deployment
  type: NodePort
  ports:
    - port: 8080        # 本 Service 的端口
      name: default     # 必须配置
      targetPort: 8080  # 容器端口
      nodePort: 30001   # 节点端口,范围固定 30000 ~ 32767
    - port: 8088
      name: other
      targetPort: 8088
      nodePort: 30002

创建 deployment 和 service,使用 kubectl apply -f **.yaml 命令即可

在这里插入图片描述
service 使用的 NodePort 类型,节点端口 30001,使用 http://192.168.25.100:30001/redis/select?key=test 测试,其中 192.168.25.100 是 master 节点

  • 新增 key
    在这里插入图片描述
  • 查询 key
    在这里插入图片描述

如上测试成功,可以在连接 redis-statefulset-0 测试

# 新建redis pod
kubectl run redis-client --rm --tty -i --restart='Never' --image redis:latest --command -- bash
# 连接指定的 redis-statefulset-0
redis-cli -h redis-statefulset-0.redis-service -p 6379

如下,调用插入 key 接口后,查询 key 成功

在这里插入图片描述

三、删除 StatefulSet

StatefulSet 同时支持级联和非级联删除。

  • 非级联删除:删除 StatefulSet 时,StatefulSet 的 Pod 不会被删除。
  • 级联删除:删除 StatefulSet 时,StatefulSet 和它的 Pod 都会被删除。(默认级联删除)
1、非级联删除

非级联删除,默认 --cascade=true,即不写 --cascade 参数默认为级联删除

kubectl delete statefulset redis-statefulset --cascade=false

非级联删除 statefulset ,pod 还会存在,手动删除 pod,pod 不会新建
在这里插入图片描述

2、级联删除

因为上面删除了 statefulset,下面先重建,在级联删除

kubectl apply -f redis-StatefulSet.yaml
kubeclt delete statefulset redis-statefulset

级联删除会删除 StatefulSet 和它的 Pod,但它并不会删除和 StatefulSet 关联的 Service
在这里插入图片描述

四、问题

pod 重建后,数据库的内容丢失了
下节,我们讲解使用数据持久化解决这个问题。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值