Skip to content

Commit

Permalink
fix: sts usage
Browse files Browse the repository at this point in the history
  • Loading branch information
姚泰然 committed Sep 15, 2023
1 parent 85253a3 commit 3dd0f52
Show file tree
Hide file tree
Showing 26 changed files with 2,777 additions and 316 deletions.
70 changes: 70 additions & 0 deletions content/posts/StatefulSet使用思路梳理.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
title: StatefulSet使用思路梳理
description:
toc: true
authors: [“tryao"]
tags: ["k8s"]
categories: []
series: []
date: 2023-09-15T14:57:05+08:00
lastmod: 2023-09-15T14:57:05+08:00
featuredVideo:
featuredImage:
draft: false
---

一般服务都是使用deployment部署,deploy的使用非常简单,无状态,随意调度。但是各种需要持久化数据的中间件都需要使用StatefulSet来部署,这个玩意儿实际上有点复杂。

## 最简单的方法:不要使用k8s来部署有状态应用

比如在部署kafka集群、MySQL集群时,你会发现直接用docker分别在选定节点部署,是最简单的。和传统的物理机部署并无什么区别,你要做的仅仅是将配置文件和宿主机目录挂载到容器里。

如果想要自动化,就写bash脚本,分别在各个主机运行即可,也并没有那么复杂。

容器内的服务访问容器外的服务也很简单:直接用网卡的内网ip就行。

## 不要太依赖分布式存储

第一次接触Ceph或者longhorn的时候,很容易会错误的认为分布式存储本身就可以解决高可用的问题。

比如sqlite,将它放在longhorn里,理论上pod在任意节点,都可以访问到这块pv. longhorn自带的多副本策略也可以保证数据不丢失。如果宿主机节点挂掉,k8s自动调度pod到其他结点,原来的pv也依然可用。

这一切很美好,但是有两个问题:

* IO性能会变差;
* **数据可能损坏**

第一点是显而易见的,毕竟分布式存储是在文件系统的基础上又加了一层,肯定会影响性能。

第二点就比较蛋疼了,分布式存储保证文件的高可用是通过类似Dropbox这种文件同步的思路来进行的,**他并不理解文件的内容**,所以文件有可能会损坏是很容易理解的。

众所周知,MySQL主从的备份思路是通过binlog同步来增量进行的。当master节点宕机时,可能有一部分变更没来得及同步到slave节点,这就会造成数据**回档**的效果。但是如果是使用longhorn做同步,可能整个database都无法打开,导致数据完全损坏,这种肯定是完全无法接受的。

另外,longhorn支持s3/minio/nfs二次备份,这个卷备份可以实现完全备份。当出现宕机等问题时,你可以向前回溯这个备份,总能找到可用的完整数据。当然,这个回档的时间可能有点长。

所以,对于MySQL这种数据库,还是使用**应用层自带的副本方案**更靠谱。分布式存储只能用来存放一些不太重要的东西:比如文件之类的。甚至于,这个需求也可以使用minio之类的中间件来解决。可能像日志之类的数据比较适合使用,搞一块RWM的PV,所有应用都往里面写日志,方便集中查看应用日志,而且日志丢了一般影响也不大。

当然,如果你是在云端,使用云厂商提供的分布式存储,一般并不需要关心这个问题,我们这里主要还是讨论边缘端这种不稳定的场景。

## 利用亲和性来部署StatefulSet

如果回到应用程序本身的副本方案——比如MySQL主从——那么就需要手动干涉k8s的调度。使其最终和你手动在各个节点部署的结果一致(也就是你自己用docker部署)。

首先,主从应当尽量在不同的宿主机上:如果你有两台以上宿主机的话。这个主要通过Pod反亲和性来实现:如果这个节点已经有匹配的Pod,则尽量不要还在这个节点上部署第二个sts.

其次,利用节点亲和性来选择宿主机:假设你手头的宿主机配置不太一样,那就在高配置的node上加上label,然后在sts的pod上加上节点亲和,选择匹配的标签。

利用这两个方法,你可以决定pod最终被调度到哪个节点上。当然至于哪个是主哪个是从,这个仍然是随机的。如果你想保证主在某个节点,从在某个节点,那只能写两个sts,直接指定nodeName。一个sts配置2个replia,是无法实现这种需求的。

## 使用LocalPV

不使用分布式存储,那就只能用LocalPV了。如果使用k3s,使用自带的local-path就行。

在sts里面指定VolumeClaimTemplate,k8s会延迟绑定PV直到Pod被调度。

对于LocalPV,k8s在调度时就会考虑到Pod和PV必须在同一个节点,这是因为StorageClass的配置里有`volumeBindingMode: WaitForFirstConsumer`,这是LocalPV的标记。在第一次创建sts时,PV还不存在,这个流程是反过来的:k8s先根据亲和性和资源需求来决定Pod在哪个节点,然后再根据PVC来动态创建PV,将PVC绑定PV,在同一个节点创建Pod然后完成挂载。

在第二次以及之后创建sts时,此时PVC/PV都已经存在,所以k8s在调度的时候就会自动将POD创建到对应的节点了。

如果是直接用k8s,那可能没有支持动态创建PV的StorageClass. 此时需要手动创建PV,其他的流程是一样的。当然最终节点只会被调度到有PV的节点:换句话说,你无须在POD中指定节点亲和性,而是在创建PV时指定节点亲和性。

2 changes: 1 addition & 1 deletion docs/authors/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@



<meta property="og:updated_time" content="2023-09-15T09:33:41&#43;08:00" />
<meta property="og:updated_time" content="2023-09-15T14:57:05&#43;08:00" />



Expand Down
4 changes: 2 additions & 2 deletions docs/authors/index.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
<language>zh</language>
<copyright>&amp;copy; 2021 &lt;a href=&#34;https://github.com/YiuTerran&#34;&gt;tryao&lt;/a&gt;
</copyright>
<lastBuildDate>Fri, 15 Sep 2023 09:33:41 +0800</lastBuildDate><atom:link href="https://yiuterran.github.io/blog/authors/index.xml" rel="self" type="application/rss+xml" />
<lastBuildDate>Fri, 15 Sep 2023 14:57:05 +0800</lastBuildDate><atom:link href="https://yiuterran.github.io/blog/authors/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>个人介绍</title>
<link>https://yiuterran.github.io/blog/authors/tryao/</link>
<pubDate>Fri, 15 Sep 2023 09:33:41 +0800</pubDate>
<pubDate>Fri, 15 Sep 2023 14:57:05 +0800</pubDate>

<guid>https://yiuterran.github.io/blog/authors/tryao/</guid>
<description>Self Introduction 少时曾攻经史,长成却成码农。家有懒猫伏膝侧,键盘声中迷蒙。 主业后端开发,大数据、流媒体、游戏后端之类的什么都懂一点。python/golang/j</description>
Expand Down
80 changes: 60 additions & 20 deletions docs/authors/tryao/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -93,120 +93,126 @@
"itemListElement":[{
"@type":"ListItem",
"position": 1 ,
"name": "StatefulSet使用思路梳理",
"description": "一般服务都是使用deployment部署,deploy的使用非常简单,无状态,随意调度。但是各种需要持久化数据的中间件都需要使用StatefulSet",
"url": "https://yiuterran.github.io/blog/posts/statefulset%E4%BD%BF%E7%94%A8%E6%80%9D%E8%B7%AF%E6%A2%B3%E7%90%86/"
},{
"@type":"ListItem",
"position": 2 ,
"name": "Configmap挂载的几种情况",
"description": "ConfigMap挂载的用法比较多,很容易记混淆,这里简单做个梳理: 将某个key的值挂载为环境变量 apiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: containers: - name: test-container image: gcr.io/google_containers/busybox command: [ \u0026quot;/bin/sh\u0026quot;, \u0026quot;-c\u0026quot;, \u0026quot;env\u0026quot; ] env: - name: SPECIAL_LEVEL_KEY valueFrom: configMapKeyRef:",
"url": "https://yiuterran.github.io/blog/posts/configmap%E6%8C%82%E8%BD%BD%E7%9A%84%E5%87%A0%E7%A7%8D%E6%83%85%E5%86%B5/"
},{
"@type":"ListItem",
"position": 2 ,
"position": 3 ,
"name": "Sqlx备忘录",
"description": "很少用golang写增删改查,sqlx的用法和java差别很大,用的时候总是要从头看文档。这里写个备忘录方便以后查询,使用sqlx和go-sqlbui",
"url": "https://yiuterran.github.io/blog/posts/sqlx%E5%A4%87%E5%BF%98%E5%BD%95/"
},{
"@type":"ListItem",
"position": 3 ,
"position": 4 ,
"name": "边侧高可用解决方案",
"description": "边侧服务高可用其实就是当年服务还没上云的时候,使用的那套技术栈。不过稍微有些不同的是,边缘计算需要考虑完全封闭的局域网,有点像组态软件的场景。 基于域名",
"url": "https://yiuterran.github.io/blog/posts/%E8%BE%B9%E4%BE%A7%E9%AB%98%E5%8F%AF%E7%94%A8%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/"
},{
"@type":"ListItem",
"position": 4 ,
"position": 5 ,
"name": "PromQL笔记",
"description": "格式 类似influxdb,prometheus也有自己的line protocol: \u0026lt;--------------- metric ---------------------\u0026gt;\u0026lt;-timestamp -\u0026gt;\u0026lt;-value-\u0026gt; \u0026lt;---metric name---\u0026gt;{labelname=labelvalue,....} http_request_total{status=\u0026quot;200\u0026quot;, method=\u0026quot;GET\u0026quot;}@1434417560938 =\u0026gt; 94355 http_request_total{status=\u0026quot;200\u0026quot;, method=\u0026quot;GET\u0026quot;}@1434417561287 =\u0026gt; 94334 上面就表示在某个时间戳系统http GET",
"url": "https://yiuterran.github.io/blog/posts/promql%E7%AC%94%E8%AE%B0/"
},{
"@type":"ListItem",
"position": 5 ,
"position": 6 ,
"name": "解决k8s的javaSDK与jackson不兼容问题",
"description": "k8s的java sdk中json序列化使用了google自家的gosn,但是springboot中默认使用Jackson,我们的业务代码里面也习惯上使",
"url": "https://yiuterran.github.io/blog/posts/%E8%A7%A3%E5%86%B3k8s%E7%9A%84javasdk%E4%B8%8Ejackson%E4%B8%8D%E5%85%BC%E5%AE%B9%E9%97%AE%E9%A2%98/"
},{
"@type":"ListItem",
"position": 6 ,
"position": 7 ,
"name": "K3s存储插件使用笔记",
"description": "原理 k8s存储主要依赖PV和PVC的机制,前者由运维人员声明可用的存储,如: apiVersion: v1 kind: PersistentVolume metadata: name: nfs spec: storageClassName: manual capacity: storage: 10Gi accessModes: - ReadWriteMany nfs: server: 10.244.1.4 path: \u0026quot;/\u0026quot; 后者是用户(开发人员)声明的需求",
"url": "https://yiuterran.github.io/blog/posts/k3s%E5%AD%98%E5%82%A8%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8%E7%AC%94%E8%AE%B0/"
},{
"@type":"ListItem",
"position": 7 ,
"position": 8 ,
"name": "边缘服务器管理工具选型",
"description": "这里我们主要的需求是能够穿透内网管理服务器,服务器大部分情况下应当是linux,但是也可能是windows。我们的服务要通过API和这个服务器管理软件",
"url": "https://yiuterran.github.io/blog/posts/%E8%BE%B9%E7%BC%98%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AE%A1%E7%90%86%E5%B7%A5%E5%85%B7%E9%80%89%E5%9E%8B/"
},{
"@type":"ListItem",
"position": 8 ,
"position": 9 ,
"name": "Kotlin要点笔记",
"description": "实际上学习kotlin的动力一直不足,因为java is enough. 不过最近打算写一个QQ机器人玩,现在流行的框架是基于kotlin的,虽然可以用HTTP API进行",
"url": "https://yiuterran.github.io/blog/posts/kotlin%E8%A6%81%E7%82%B9%E7%AC%94%E8%AE%B0/"
},{
"@type":"ListItem",
"position": 9 ,
"position": 10 ,
"name": "KubeEdge要点笔记",
"description": "安装流程 首先要在云端安装k8s,理论上只需要master节点,可以没有worker,换句话说可以是一个单节点集群(但是要关闭NoSchedule的ta",
"url": "https://yiuterran.github.io/blog/posts/kubeedge%E8%A6%81%E7%82%B9%E7%AC%94%E8%AE%B0/"
},{
"@type":"ListItem",
"position": 10 ,
"position": 11 ,
"name": "K8s要点简记",
"description": "22年的时候需要使用CICD的时候,看了一遍k8s相关的知识点。买了一本《深入剖析Kubernetes》,大致熟悉了常用的概念。 最近因为工作调动需要做",
"url": "https://yiuterran.github.io/blog/posts/k8s%E8%A6%81%E7%82%B9%E7%AE%80%E8%AE%B0/"
},{
"@type":"ListItem",
"position": 11 ,
"position": 12 ,
"name": "Makefile要点简记",
"description": "虽然现代C/CPP一般使用cmake作为工具链,但是如果要看陈年老项目,makefile相关的知识还是要掌握一些的,不然估计很难理清编译逻辑。这也是c",
"url": "https://yiuterran.github.io/blog/posts/makefile%E8%A6%81%E7%82%B9%E7%AE%80%E8%AE%B0/"
},{
"@type":"ListItem",
"position": 12 ,
"position": 13 ,
"name": "CMake速记",
"description": "主要参考书籍《Modern CMake for C++》,以及《CMake Best Practices》,使用CMake版本3.25. 建议先看第一本,再看第二本。 使用 一般而言,",
"url": "https://yiuterran.github.io/blog/posts/cmake%E9%80%9F%E8%AE%B0/"
},{
"@type":"ListItem",
"position": 13 ,
"position": 14 ,
"name": "Tinode源码解析",
"description": "概述 有朋友需要做一个im,简单做了一下技术调研,开源的实现其实蛮多的,这里挑几个说一下: Synapse/dendrite,matrix系,客户端比较多",
"url": "https://yiuterran.github.io/blog/posts/tinode%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/"
},{
"@type":"ListItem",
"position": 14 ,
"position": 15 ,
"name": "SRE读书笔记",
"description": "SRE相关的书籍,截止目前google出了2本,分别是2016年的的《Site Reliability Engineering: How Google Runs Production Systems》和2020年的《The Site Reliability Workbook》",
"url": "https://yiuterran.github.io/blog/posts/sre%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"
},{
"@type":"ListItem",
"position": 15 ,
"position": 16 ,
"name": "Ginkgo使用笔记",
"description": "go自带的单元测试比较适合测一个小函数,如果要做一系列的流程测试,则显得较为繁琐。 推荐使用ginkgo来做流程测试,BDD风格写出来的测试代码非常容易",
"url": "https://yiuterran.github.io/blog/posts/ginkgo%E4%BD%BF%E7%94%A8%E7%AC%94%E8%AE%B0/"
},{
"@type":"ListItem",
"position": 16 ,
"position": 17 ,
"name": "Influxdb Cluster集成",
"description": "本文记录在golang项目中集成influxdb-cluster需要的知识储备。 术语 database 和MySQL中一致 batch \\n分割的多行数据,用来批量写入。 influ",
"url": "https://yiuterran.github.io/blog/posts/influxdb-cluster%E9%9B%86%E6%88%90/"
},{
"@type":"ListItem",
"position": 17 ,
"position": 18 ,
"name": "Zabbix配置记录",
"description": "安装服务 这里演示的是物理机环境监控场景,容器场景还是更推荐k8s+prom来搞。 版本是zabbix6.0 LTS,官方已经不提供CentOS7的安装包了",
"url": "https://yiuterran.github.io/blog/posts/zabbix%E9%85%8D%E7%BD%AE%E8%AE%B0%E5%BD%95/"
},{
"@type":"ListItem",
"position": 18 ,
"position": 19 ,
"name": "Golang定时器要点",
"description": "golang内置的定时器是基于多个四叉堆封装调度的,增删定时器的效率是O(lgn),所以大量定时器本身可能成为性能瓶颈。可以考虑使用开源的时间轮算法实",
"url": "https://yiuterran.github.io/blog/posts/golang%E5%AE%9A%E6%97%B6%E5%99%A8%E8%A6%81%E7%82%B9/"
},{
"@type":"ListItem",
"position": 19 ,
"position": 20 ,
"name": "Windows+wsl2后端开发环境搭建",
"description": "2023/2/2 Update: wsl已经解决了systemd和网络问题,现在已经基本无障碍使用,移除了大部分无用的配置步骤。 就我个人而言,目前感觉最理想的后端开发环境还是Int",
"url": "https://yiuterran.github.io/blog/posts/windows+wsl2%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/"
},{
"@type":"ListItem",
"position": 20 ,
"position": 21 ,
"name": "Gb28181解析",
"description": "国标GB28181(以下简称国标或者gb)文档分析的文档我去年其实写过一版,但是由于原来的电脑炸了,文档还没来得及传上去就丢了(痛苦),所以还要重写一",
"url": "https://yiuterran.github.io/blog/posts/gb28181%E8%A7%A3%E6%9E%90/"
Expand Down Expand Up @@ -244,7 +250,7 @@



<meta property="og:updated_time" content="2023-09-15T09:33:41&#43;08:00" />
<meta property="og:updated_time" content="2023-09-15T14:57:05&#43;08:00" />



Expand Down Expand Up @@ -395,6 +401,40 @@ <h2 id="self-introduction">Self Introduction</h2>
<div class="lg:w-3/4 mx-auto px-6 md:px-8 xl:px-12 py-12">
<div class="overflow-hidden divide-y">

<div class="py-6">
<div class="flex flex-col-reverse lg:flex-row justify-between">

<div class="w-full ">
<div class="mb-4">
<a href="https://yiuterran.github.io/blog/posts/statefulset%E4%BD%BF%E7%94%A8%E6%80%9D%E8%B7%AF%E6%A2%B3%E7%90%86/" class="font-bold text-xl hover:text-eureka">StatefulSet使用思路梳理</a>
</div>
<div class="content">

一般服务都是使用deployment部署,deploy的使用非常简单,无状态,随意调度。但是各种需要持久化数据的中间件都需要使用StatefulSet

</div>

<div class="flex flex-wrap flex-row items-center mt-2 text-tertiary-text">
<div class="me-6 my-2">
<i class="fas fa-calendar me-1"></i>
<span>2023-09-15</span>
</div>
<div class="me-6 my-2">
<i class="fas fa-clock me-1"></i>
<span>4分钟阅读时长</span>
</div>




</div>

</div>


</div>
</div>

<div class="py-6">
<div class="flex flex-col-reverse lg:flex-row justify-between">

Expand Down
11 changes: 10 additions & 1 deletion docs/authors/tryao/index.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,16 @@
<language>zh</language>
<copyright>&amp;copy; 2021 &lt;a href=&#34;https://github.com/YiuTerran&#34;&gt;tryao&lt;/a&gt;
</copyright>
<lastBuildDate>Fri, 15 Sep 2023 09:33:41 +0800</lastBuildDate><atom:link href="https://yiuterran.github.io/blog/authors/tryao/index.xml" rel="self" type="application/rss+xml" />
<lastBuildDate>Fri, 15 Sep 2023 14:57:05 +0800</lastBuildDate><atom:link href="https://yiuterran.github.io/blog/authors/tryao/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>StatefulSet使用思路梳理</title>
<link>https://yiuterran.github.io/blog/posts/statefulset%E4%BD%BF%E7%94%A8%E6%80%9D%E8%B7%AF%E6%A2%B3%E7%90%86/</link>
<pubDate>Fri, 15 Sep 2023 14:57:05 +0800</pubDate>

<guid>https://yiuterran.github.io/blog/posts/statefulset%E4%BD%BF%E7%94%A8%E6%80%9D%E8%B7%AF%E6%A2%B3%E7%90%86/</guid>
<description>一般服务都是使用deployment部署,deploy的使用非常简单,无状态,随意调度。但是各种需要持久化数据的中间件都需要使用StatefulSet</description>
</item>

<item>
<title>Configmap挂载的几种情况</title>
<link>https://yiuterran.github.io/blog/posts/configmap%E6%8C%82%E8%BD%BD%E7%9A%84%E5%87%A0%E7%A7%8D%E6%83%85%E5%86%B5/</link>
Expand Down
Loading

0 comments on commit 3dd0f52

Please sign in to comment.