K8S - livenessProbe - 如果另一个 pod 未准备好/工作则重新启动 pod (MySql)

K8S - livenessProbe - Restart pod if another pod is not ready / working ( MySql)

新年快乐,我有 2 个部署,MySQL 和应用程序,我的应用程序依赖于 MySQL pod,我有 initContainers 确保应用程序在 MySQL pod fully app and ready ,但我正在努力使下一个场景正常工作。

我希望应用程序 pod 检查 MySQL pod,如果端口 3306 不可用,则应用程序 pod 自己将重新启动,这将一直发生,直到 MySQL pod完全准备好了。

我在应用程序部署/pod 中使用它

livenessProbe:
  httpGet:
    host: ???
    path: /
    port: 3306

但我不知道我需要写什么而不是“???”,因为,我知道我不能写他们的 DNS 名称,我被告知 livenessProbe 不适用于 DNS,所以我尝试为 ENV 输入此 IP 地址,但仍然无法正常工作。

我该怎么做?

SQL 部署 yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Values.deployment.mysql.name }}
  namespace: {{ .Values.namespace }}
spec:
  selector:
    matchLabels:
      app: {{ .Values.deployment.mysql.name }}
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: {{ .Values.deployment.mysql.name }}
    spec:
      containers:
      - image: {{ .Values.deployment.mysql.image }}
        name: {{ .Values.deployment.mysql.name }}
        env:
         - name: MYSQL_ROOT_PASSWORD
           valueFrom: 
             secretKeyRef:
              name: mysql-secret
              key: mysql-root-password   
        ports:
        - containerPort: {{ .Values.deployment.mysql.port }}
          name: {{ .Values.deployment.mysql.name }} 
        volumeMounts:
        - name: sqlvol
          mountPath: /var/lib/mysql/
          readOnly: false
        # - name: db
        #   mountPath: /etc/notebook-db/
        # command:
        #   - mysql < /etc/notebook-db/crud.sql
        livenessProbe:
          tcpSocket:
            port: 3306
          initialDelaySeconds: 15
          periodSeconds: 20
      initContainers:
      - name: init-myservice
        image: busybox:1.28
        command: ['sh', '-c', "sleep 10"]
      volumes:
      - name: sqlvol
        persistentVolumeClaim:
          claimName: mysqlvolume
          readOnly: false

应用程序部署 yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Values.deployment.nodejs.name }}
  namespace: {{ .Values.namespace }}
  labels:
    app: {{ .Values.deployment.nodejs.name }}
    name: {{ .Values.deployment.nodejs.name }}
spec:
  replicas: 1
  selector:
    matchLabels:
      app: {{ .Values.deployment.nodejs.name }}
  template:
    metadata:
      labels:
        app: {{ .Values.deployment.nodejs.name }}
    spec:
      containers:
      - name: {{ .Values.deployment.nodejs.name }}
        image: {{ .Values.deployment.nodejs.image }}:{{ .Values.deployment.nodejs.tag }}
        ports:
        - containerPort: {{ .Values.deployment.nodejs.targetPort }}
         livenessProbe:
           httpGet:
             host: $MYSQL_CLUSTERIP_SERVICE_HOST
             path: /
             port: 3306
      initContainers:
        - name: init-myservice
          image: busybox:1.28
          command: ['sh', '-c', "sleep 60"]

$MYSQL_CLUSTERIP_SERVICE_HOST - 这是 ENV(这种方式对我不起作用)。

那么如果 pod mysql 没有准备好,我该如何重启 pod 应用程序?

  • 为MySQL部署创建服务,这样可以解决两个问题
    • 服务IP不变
    • dns 查找和反向查找与服务配合良好
Example: 
kubectl get svc -n default
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
nginx        ClusterIP   10.104.97.252   <none>        8080/TCP   33m

FQDN of the above service (in the fomat : <nameoftheservice>.<namespace>.cluster.local ):
nginx.default.svc.cluster.local

  • 然后在应用程序部署的 livenessProbe 中使用服务的 FQDN 作为 host
liveness probe for with respect above service: 

livenessProbe:
  httpGet:
    host: nginx.default.svc.cluster.local
    path: /
    port: 8080

如果 MySQL 没有准备好,您的应用程序会崩溃吗?如果是这种情况,因为您的应用程序是 Deployment,Kubernetes 将应用自我修复,因此您的 Pod 将重新启动,直到重新启动正常(实际上您可以配置最大重试次数)。

TL;DR

DNS 不适用于 liveness 探测,kubelet 网络 space 基本上无法解析任何 in-cluster DNS。

您可以考虑将您的两个服务放在一个 pod 中作为 sidecar。这样他们将共享相同的地址 space 如果一个容器失败然后整个 pod 将重新启动。

另一种选择是为您的 pods/application 创建一个操作员,基本上让它通过 in-cluster DNS 分别检查两个 pods 的活跃度并重新启动 pods通过 Kubernetes API.

您也可以在 pod 中创建自己的脚本,该脚本仅调用 curl 来检查 200 OK 并调用 kubectl 来重启您的 pod(如果您遇到其他问题)。

请注意,对于上述 2 个选项,您需要确保 Coredns 稳定可靠,否则您的健康检查可能无法使您的服务有潜在的停机时间。

来自 :