陈同学
微服务
Accelerator
About
# K8s 有状态应用控制:StatefulSet 本文介绍 StatefulSet 相关知识。 业务应用往往是无状态的(Stateless),便于进行横向拓展。 部分软件高可用部署时往往存在状态,如MySQL主从、Redis Sentinel、注册服务的主备等,这些应用启动时有先后关系之分。 ## 通过 Service 访问 Pod 方式  上图是通过 Service 访问 Pod 的两种方式,StatefulSet 有利用这个能力。 * **VIP(虚拟IP)方式**:通过访问Normal Service 的VIP从而访问任意无状态的Pod,自动实现了负载均衡 * **Service DNS方式**: * 对于 Normal Service,通过 `svc-name.namespace-name.svc.cluster.local` 可解析到 Service 的VIP * 对于 Headless Service,通过 `pod-name.service-name.namespace-name.svc.cluster.local` 直接访问Pod,没有VIP。 而 StatefulSet 作为控制器,主要起到如下作用: * 确保Pod创建时名字正确编号,如:`-0、-1、-N` * 确保Pod逐一健康创建,因此要配置好 livenessProbe 和 readinessProbe,只有上一个Pod Running + Ready 后,后续 Pod 才会运行,否则会一直处于 Pending 状态。 * 确保Pod被重新创建时,能正常恢复状态(如name) StatefulSet 利用 Headless Service 可通过DNS直接访问特定Pod的特性,结合给Pod规则编号+状态保持,从而达到 **稳定访问特定Pod** 的效果。 ## Headless Service Demo 先创建 nginx Pod。 ```yaml apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx-container image: nginx ``` 再创建 **clusterIP: None** 的Service,没有VIP即表示 **Headless Service**。通过 app=nginx 选择器筛选Pod. ```yaml apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: ports: - port: 80 clusterIP: None selector: app: nginx ``` ## StatefulSet Demo ```yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: proxy spec: serviceName: "nginx" replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 ``` 下面是 Pod 的创建顺序,proxy-0 未 `Running `之前 proxy-1 一直处于 `Pending` ```bash $ kubectl get pods -w -l app=nginx NAME READY STATUS RESTARTS AGE proxy-0 0/1 ContainerCreating 0 11s proxy-0 1/1 Running 0 16s proxy-1 0/1 Pending 0 0s proxy-1 0/1 Pending 0 0s proxy-1 0/1 ContainerCreating 0 0s proxy-1 1/1 Running 0 11s ``` 自动创建的Pod遵循 proxy-0、proxy-1 的命名规则。 ```bash $ kubectl get pods -l app=nginx NAME READY STATUS RESTARTS AGE proxy-0 1/1 Running 0 2m7s proxy-1 1/1 Running 0 111s ``` 启动一个工具应用测试可通过DNS方式访问 `proxy-0`。 ``` kubectl run -it --image busybox sf-test --restart=Never --rm /bin/sh ``` 下面是 ping `proxy-0`,已经可以正常解析。 ```bash $ ping proxy-0.nginx.default.svc.cluster.local PING proxy-0.nginx.default.svc.cluster.local (10.244.0.28): 56 data bytes 64 bytes from 10.244.0.28: seq=0 ttl=64 time=0.062 ms ``` 此时删除proxy-0,StatefulSet 使用原先的顺序恢复了proxy-0。 ```bash $ kubectl delete pod proxy-0 pod "proxy-0" deleted $ kubectl get pod -w -l app=nginx NAME READY STATUS RESTARTS AGE proxy-0 0/1 Pending 0 0s proxy-1 1/1 Running 0 11m proxy-0 0/1 ContainerCreating 0 0s proxy-0 1/1 Running 0 11s ``` ## Stateful 搭建 Redis 主动Demo ```yaml apiVersion: v1 kind: Service metadata: name: redis labels: app: redis spec: ports: - port: 6379 clusterIP: None selector: app: redis --- apiVersion: apps/v1 kind: StatefulSet metadata: name: redis spec: serviceName: "redis" replicas: 2 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - name: redis image: daocloud.io/library/redis ports: - containerPort: 6379 ``` 等待正常Running. ```bash $ kubectl get pods -w -l app=redis NAME READY STATUS RESTARTS AGE redis-0 1/1 Running 0 11s redis-1 1/1 Running 0 9s ``` 手工配置下主从关系即可。 ```bash $ kubectl exec -it redis-1 redis-cli 127.0.0.1:6379> SLAVEOF redis-0.redis 6379 OK 127.0.0.1:6379> info replication # Replication role:slave master_host:redis-0.redis master_port:6379 master_link_status:up master_last_io_seconds_ago:8 master_sync_in_progress:0 ```
本文由
cyj
创作,可自由转载、引用,但需署名作者且注明文章出处。
文章标题:
K8s 有状态应用控制:StatefulSet
文章链接:
https://chenyongjun.vip/articles/155
扫码或搜索 cyjrun 关注微信公众号, 结伴学习, 一起努力