K8S精进之路-控制器StatefulSet有状态控制 -(2)

状态说明

  在进行StatefulSet部署之前,我们首先可能要了解一下,什么是"有状态应用"和"无状态应用"。无状态应用就是pod无论部署在哪里,在哪台服务器上提供服务,都是一样的结果,比如经常用的nginx。有状态应用中,最经常用的那就属数据库了,因为数据库一般都是绑定了网络状态和存储状态。特别是主从数据库,哪些是主数据库,哪些是从数据库,都有明显的状态标识。离开标识的这台机器,可能就用不了了。

那在K8S中主要表现的状态有哪些呢,如果抽象成现实应用中,一般就是网络拓扑状态和存储状态。

网络拓扑:这意味着在k8s中运行中的应用对应的各个pod实例,都会有固定的启动顺序,而且不管实例pod销毁后新建,网络标识还是原来的网络标识,其它应用要找到它,还是通过原来的网络标识一样能找到。

存储状态:比如,当数据库实例销毁重建后,我存储的数据还是照样是原来的那份数据。数据库存储的数据是有状态的,是直接和这个应用绑定的,不论你pod实例重建多少次都会取到这份自己的数据。

我们先看看StatefulSet是怎样固定网络拓扑状态的。在网络中一般要标识一个地址,都是通过IP地址或者是域名。但是IP地址是不方便被记忆的,所以用一个域名是非常方便的。在K8S中,通过系统的Service DNS是可以确定一个POD的网络标识的。

固定网络拓扑

我们新建一个Headless的Service和nginx

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:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.22.1
        ports:
        - containerPort: 80
          name: web

创建之后发现两个Pod运行,分别为web-0,web-1,IP地址分别是10.244.3.18,10.244.2.20。虽然分配了ip但是ip是动态,唯一固定的是这两个pod的域名和它们创建启动的顺序,先创建web-0,然后是web-1。我们通过<pod-name>.<svc-name>.<namespace>.svc.cluster.local的方式来固定这两个pod的地址。

我们通过web-0.nginx.default.svc.cluster.local和web-1.nginx.default.svc.cluster.local可以在集群内部访问到这两个Pod。我们接下来通过k8s的coredns来解析这两个域名。先找到coredns的ip地址,然后通过dig来解析。

解析后发现pod的域名刚好指向这两个pod的ip地址。我现在删除上面的pod,然后重建,再解析他们的域名,发现ip地址变了,但是域名还是那个域名。

bash 复制代码
kubectl delete -f teststatefulpod.yaml ; kubectl apply -f teststatefulpod.yaml

固定存储状态

对于应用的存储,这里用pvc来固定应用的存储位置。相对开发人员这里只要熟悉pvc的配置即可,pv的配置一般由运维人员去配置安装。这里我们用分布式存储Rook+Ceph,安装方式可以参考这篇文章<<Centos7.9在K8s安装生产级别的分布式存储Rook+Ceph>>。

我们创建一个带存储的nginx配置

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
   storage: 1Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.22.1
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      storageClassName: rook-ceph-block
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi

创建完成后,会出现两个自动创建的pvc,而且是根据pod名创建的。

我们分别对这两个nginx的首页加上特殊标志。

bash 复制代码
kubectl exec web-0 -- sh -c 'echo hello $(hostname) > /usr/share/nginx/html/index.html'
kubectl exec web-1 -- sh -c 'echo hello $(hostname) > /usr/share/nginx/html/index.html'

然后通过ip分别访问这两个nginx.各自首页分别返回了内容,一个是web-0,一个web-1.

然后删除这两个pod应用,再重建,发现pod虽然重建ip也变了,但是挂载的磁盘还是原来的,内容也没有变。存储状态也是一直保存着的。

bash 复制代码
kubectl delete -f teststatefulpod.yaml
kubectl apply -f teststatefulpod.yaml
相关推荐
虎头金猫1 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
分布式存储与RustFS1 天前
MinIO 官方 Docker 镜像被移除:依赖它的项目该怎么办
docker·云原生·devops·对象存储·minio·分布式存储
codeejun1 天前
每日一Go·MySQL-5、锁机制全解析
云原生·golang
此冬歌咏1 天前
K8s 节点故障实战:优雅驱逐 31 秒,硬故障 331 秒,以及那个永远 Pending 的 Pod
运维·k8s
玉&心1 天前
通过Arthas在线诊断K8S中的内存及JVM等使用情况
docker·k8s·arthas
xing-xing1 天前
Docker容器中Nginx站点根目录网页配置访问
nginx·docker
赵文宇(温玉)1 天前
CoreDNS的hosts插件的缺行配置导致k8s集群异常
容器·kubernetes·rancher
guo_wen_qiang1 天前
上传本地镜像到harbor中
docker·容器·持续部署
张洛闻Eren1 天前
k8s云原生【第十课】:水平 Pod 自动扩缩容
运维·数据库·云原生·kubernetes·github
流烟默1 天前
K8s StatefulSet 详解:有状态应用的“身份证”与“固定住址”
k8s·statefulset