Featured image of post 使用reloader实现k8s热更新配置

使用reloader实现k8s热更新配置

在kubernetes中如果配置发生变化,我们如何做到无感知的配置热更新是重要的,下面我以stakater/Reloader为例解决这个问题。

Reloader是一个开源的Kubernetes工具,它可以观察 ConfigMap 和 Secret 中的变化,并对 pod 及其关联的 DeploymentConfigsDeploymentsDaemonsetsStatefulsets 和 Rollouts进行滚动升级。

原理

  • 当 Reloader 检测到 ConfigMap 发生变化的时候,会使用 SHA1 计算 ConfigMap 的哈希值(使用 SHA1 是因为它高效且不易发生冲突),计算完哈希值之后,Reloader 获取所有的 DeploymentsDaemonsetsStatefulsets 和 Rollouts 列表,并查找其 anotations 中是否配置了 Reloader 相关的注解(见下面)

  • Reloader 会查找配置了 Reloader 相关 annotations 的 DeploymentsDaemonsetsStatefulsets 中一个特殊的环境变量。

  • 如果找到这个环境变量,则获取其值并将其与前面计算的新 ConfigMap 哈希值进行比较,如果环境变量中的旧值与新哈希值不同,则 Reloader 会更新环境变量。

  • 如果环境变量不存在,那么它会从 ConfigMap 创建一个具有最新哈希值的新环境变量并更新相关的deploymentdaemonset或者statefulset

  • k8s 检测到这个环境变量发生变化,则会触发 pod 关联的 deploymentdaemonset或者statefulset 的滚动升级。

部署Reloader

1
kubectl apply -f https://raw.githubusercontent.com/stakater/Reloader/master/deployments/kubernetes/reloader.yaml

或者直接使用这个

  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
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
---
# Source: reloader/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    meta.helm.sh/release-namespace: "default"
    meta.helm.sh/release-name: "reloader"
  labels:
    app: reloader-reloader
    chart: "reloader-1.0.29"
    release: "reloader"
    heritage: "Helm"
    app.kubernetes.io/managed-by: "Helm"
  name: reloader-reloader
  namespace: default
---
# Source: reloader/templates/clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1

kind: ClusterRole
metadata:
  annotations:
    meta.helm.sh/release-namespace: "default"
    meta.helm.sh/release-name: "reloader"
  labels:
    app: reloader-reloader
    chart: "reloader-1.0.29"
    release: "reloader"
    heritage: "Helm"
    app.kubernetes.io/managed-by: "Helm"
  name: reloader-reloader-role
rules:
  - apiGroups:
      - ""
    resources:
      - secrets
      - configmaps
    verbs:
      - list
      - get
      - watch
  - apiGroups:
      - "apps"
    resources:
      - deployments
      - daemonsets
      - statefulsets
    verbs:
      - list
      - get
      - update
      - patch
  - apiGroups:
      - "extensions"
    resources:
      - deployments
      - daemonsets
    verbs:
      - list
      - get
      - update
      - patch
  - apiGroups:
      - ""
    resources:
      - events
    verbs:
      - create
      - patch
---
# Source: reloader/templates/clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1

kind: ClusterRoleBinding
metadata:
  annotations:
    meta.helm.sh/release-namespace: "default"
    meta.helm.sh/release-name: "reloader"
  labels:
    app: reloader-reloader
    chart: "reloader-1.0.29"
    release: "reloader"
    heritage: "Helm"
    app.kubernetes.io/managed-by: "Helm"
  name: reloader-reloader-role-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: reloader-reloader-role
subjects:
  - kind: ServiceAccount
    name: reloader-reloader
    namespace: default
---
# Source: reloader/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    meta.helm.sh/release-namespace: "default"
    meta.helm.sh/release-name: "reloader"
  labels:
    app: reloader-reloader
    chart: "reloader-1.0.29"
    release: "reloader"
    heritage: "Helm"
    app.kubernetes.io/managed-by: "Helm"
    group: com.stakater.platform
    provider: stakater
    version: v1.0.29
  name: reloader-reloader
  namespace: default
spec:
  replicas: 1
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: reloader-reloader
      release: "reloader"
  template:
    metadata:
      labels:
        app: reloader-reloader
        chart: "reloader-1.0.29"
        release: "reloader"
        heritage: "Helm"
        app.kubernetes.io/managed-by: "Helm"
        group: com.stakater.platform
        provider: stakater
        version: v1.0.29
    spec:
      containers:
      - image: "ghcr.io/stakater/reloader:v1.0.29"
        imagePullPolicy: IfNotPresent
        name: reloader-reloader

        ports:
        - name: http
          containerPort: 9090
        livenessProbe:
          httpGet:
            path: /live
            port: http
          timeoutSeconds: 5
          failureThreshold: 5
          periodSeconds: 10
          successThreshold: 1
          initialDelaySeconds: 10
        readinessProbe:
          httpGet:
            path: /metrics
            port: http
          timeoutSeconds: 5
          failureThreshold: 5
          periodSeconds: 10
          successThreshold: 1
          initialDelaySeconds: 10

        securityContext:
          {}
      securityContext:
        runAsNonRoot: true
        runAsUser: 65534
      serviceAccountName: reloader-reloader

ConfigMap

编辑我们的deployment加上如下注解:

1
2
3
4
5
6
7
kind: Deployment
metadata:
  annotations:
    configmap.reloader.stakater.com/reload: "foo-configmap,bar-configmap,baz-configmap"
spec:
  template: 
    metadata:

Secret

编辑我们的deployment加上如下注解:

1
2
3
4
5
6
7
kind: Deployment
metadata:
  annotations:
    secret.reloader.stakater.com/reload: "foo-secret,bar-secret,baz-secret"
spec:
  template: 
    metadata: