容器化应用系统上生产的最佳实践

本文最后更新于:2024年7月24日 晚上

前言

最近忙的要死, 👻👻👻. 上一周来了一次比 996 更猛的 907. 这周二终于有点遭不住了, 调休一天, 稍微歇息一下.

同时手痒的不行, 把筹备了好久的重磅文章发上来哈哈. 😆😆😆

不过时间还是有点仓促, 所以这次就先开个头, 后面有时间再细化.

img

容器化应用系统上生产的最佳实践

  1. 检查镜像、容器是否是用 root 启动以及配置其他特权. 如无必要, 一律使用普通用户.
  2. 检查镜像 LANG 配置: LANG = en_US.UTF-8. 目的: 避免生产出现 乱码等问题
  3. 检查镜像时区配置: TZ=Asia/Shanghai 目的: 避免生产出现时区不一致的问题
  4. 配置外部化. 外部化手段有多种.
    1. ConfigMap/Secret
    2. 配置中心
    3. Env
  5. 同一个镜像, 从测试流转到生产. 给镜像打 ${version}${gitCommitId}这一类的标签. 目的: 通过版本号或 commit id, 保证正确地的版本流转到生产
  6. 讨论每个组件的
    1. 日志输出优化:
      1. 日志到标准输出还是到目录?
      2. 日志采用 JSON 格式输出
      3. 禁止 DEBUG 日志
      4. 如果到目录, 目录是否需要持久化? 是否共享? 要注意日志命名冲突.
  7. (可选) 根据需要, 安装 redis/kafka/rabbitmq 集群(并配置 exporter 监控)
  8. 确定每个服务(Deployment/Statefulset):
    1. Node Selector: zone/rack/arch…
    2. 资源用量: CPU/Memory 的 Requests/Limits
    3. 更新策略: rolling 还是 recreate 还是其他更高阶策略
  9. 微服务参数优化:
    1. JVM Heap/NonHeap 参数优化
    2. 是否有其他 java 参数要配置: JAVA_OPTIONS或者CATALINA_OPTS
    3. 其他…
  10. 制作 DEV, TEST, UAT, Pre-PROD, PROD 的 DevOps pipeline.
  11. 配置 Readiness 和 Liveness 探针.
  12. 增加 Metric(如 JMX-exporter) 监控和 Tracing 监控.
  13. NGINX conf 建议增加: worker_processes 1; 然后按需调节副本数.
  14. (可选)配置 PDB, 指定升级或重启过程中:maxUnavailableminAvailable(特别适用于: 有状态应用. 典型如: redis, kafka, zookeeper 等)
  15. 配置反亲和性podAntiAffinity. 保证同一组微服务 / 应用 / 组件尽可能打散在不同 node 上.

8 操作步骤:

1
2
nodeSelector:
zone: DMZ

11 步示例如下:

1
2
3
4
5
6
7
8
9
10
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 60
readinessProbe:
httpGet:
path: /myapp/services/
port: 8080
scheme: HTTP
initialDelaySeconds: 60

14 步示例如下: (注意关键词: maxUnavailableminAvailable)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
kind: PodDisruptionBudget
apiVersion: policy/v1beta1
metadata:
name: kafka-prod-kafka
labels:
app.kubernetes.io/instance: kafka-prod
app.kubernetes.io/managed-by: strimzi-cluster-operator
app.kubernetes.io/name: strimzi
strimzi.io/cluster: kafka-prod
strimzi.io/kind: Kafka
strimzi.io/name: kafka-prod-kafka
spec:
selector:
matchLabels:
strimzi.io/cluster: kafka-prod
strimzi.io/kind: Kafka
strimzi.io/name: kafka-prod-kafka
maxUnavailable: 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
kind: PodDisruptionBudget
apiVersion: policy/v1beta1
metadata:
name: redis-cluster-redis
namespace: myapp
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/managed-by: redis-operator
app.kubernetes.io/name: redis
app.kubernetes.io/part-of: redis-cluster
redis.kun/v1beta1: myapp_redis
spec:
minAvailable: 2
selector:
matchLabels:
app.kubernetes.io/component: redis
app.kubernetes.io/managed-by: redis-operator
app.kubernetes.io/name: redis
app.kubernetes.io/part-of: redis-cluster
redis.kun/v1beta1: myapp_redis

15 步骤示例如下: (注意关键词: podAntiAffinity)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
kind: StatefulSet
apiVersion: apps/v1
metadata:
name: redis-cluster-redis
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/managed-by: redis-operator
app.kubernetes.io/name: redis
app.kubernetes.io/part-of: redis-cluster
redis.kun/v1beta1: myapp_redis
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/component: redis
app.kubernetes.io/managed-by: redis-operator
app.kubernetes.io/name: redis
app.kubernetes.io/part-of: redis-cluster
redis.kun/v1beta1: myapp_redis
template:
metadata:
creationTimestamp: null
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/managed-by: redis-operator
app.kubernetes.io/name: redis
app.kubernetes.io/part-of: redis-cluster
redis.kun/v1beta1: myapp_redis
spec:
containers:
<...>
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app.kubernetes.io/component: redis
app.kubernetes.io/managed-by: redis-operator
app.kubernetes.io/name: redis
app.kubernetes.io/part-of: redis-cluster
redis.kun/v1beta1: myapp_redis
topologyKey: kubernetes.io/hostname
...

🎉🎉🎉


容器化应用系统上生产的最佳实践
https://ewhisper.cn/posts/14417/
作者
东风微鸣
发布于
2020年10月22日
许可协议