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
相关推荐
wuxingge3 小时前
k8s1.30.0高可用集群部署
云原生·容器·kubernetes
志凌海纳SmartX4 小时前
趋势洞察|AI 能否带动裸金属 K8s 强势崛起?
云原生·容器·kubernetes
锅总4 小时前
nacos与k8s service健康检查详解
云原生·容器·kubernetes
BUG弄潮儿4 小时前
k8s 集群安装
云原生·容器·kubernetes
意疏4 小时前
【Linux 篇】Docker 的容器之海与镜像之岛:于 Linux 系统内探索容器化的奇妙航行
linux·docker
墨鸦_Cormorant4 小时前
使用docker快速部署Nginx、Redis、MySQL、Tomcat以及制作镜像
redis·nginx·docker
Code_Artist5 小时前
Docker镜像加速解决方案:配置HTTP代理,让Docker学会科学上网!
docker·云原生·容器
何遇mirror5 小时前
云原生基础-云计算概览
后端·云原生·云计算
颜淡慕潇6 小时前
【K8S系列】kubectl describe pod显示ImagePullBackOff,如何进一步排查?
后端·云原生·容器·kubernetes
wanmei0026 小时前
Dockerfile复制目录进入镜像里
docker