【问题标题】:Kubernetes Service unreachableKubernetes 服务无法访问
【发布时间】:2021-07-16 23:46:45
【问题描述】:

我在 2 个 Rasberry Pi(Model 3 和 3B+)上创建了一个 Kubernetes 集群,用作 Kubernetes 游乐场。

我已经部署了一个 postgresql 和一个 spring boot 应用程序(称为 meal-planer)来玩。 Meal-Planer 应该从 postgresql 读取和写入数据。

但是,应用无法访问数据库。

这里是 postgresql 的部署描述符:

kind: Service
apiVersion: v1
metadata:
  name: postgres
  namespace: home
  labels:
    app: postgres
spec:
  selector:
    app: postgres
  ports:
  - port: 5432
    targetPort: 5432
    name: postgres
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: postgres
  namespace: home
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:13.2
          imagePullPolicy: IfNotPresent
          env:
            - name: POSTGRES_USER
              valueFrom:
                secretKeyRef:
                  name: dev-db-secret
                  key: username
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: dev-db-secret
                  key: password
            - name: POSTGRES_DB
              value: home
          ports:
            - containerPort: 5432
          volumeMounts:
            - mountPath: /var/lib/postgresql/data
              name: postgres-data
      volumes:
        - name: postgres-data
          persistentVolumeClaim:
            claimName: postgres-pv-claim
---

这里是餐盘的部署描述符

kind: Service
apiVersion: v1
metadata:
  name: meal-planner
  namespace: home
  labels:
    app: meal-planner
spec:
  type: ClusterIP
  selector:
    app: meal-planner
  ports:
    - port: 8080
      name: meal-planner
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: meal-planner
  namespace: home
spec:
  replicas: 1
  selector:
    matchLabels:
      app: meal-planner
  template:
    metadata:
      labels:
        app: meal-planner
    spec:
      containers:
        - name: meal-planner
          image: 08021986/meal-planner:v1
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
---

meal-planer 映像是运行 jar 文件的 arm32v7 映像。 在集群内部,meal-planer 使用连接字符串 jdbc:postgresql://postgres:5432/home 连接到数据库。

我绝对确定,数据库凭据是正确的,因为我可以在端口转发服务时访问数据库。

在部署这两个应用程序时,我可以kubectl exec -it <<podname>> -n home -- bin/sh 进入它。如果我从那里拨打wget -O- postgreswget -O- postgres.home,我总是会收到Connecting to postgres (postgres)|10.43.62.32|:80... failed: Network is unreachable

我不知道,为什么网络无法访问,我不知道我能做些什么。

【问题讨论】:

  • 为了帮助您找到根本原因,您能否包括以下内容:1) kubectl logs <<postgres_pod_name>> 2) kubectl exec -it <<postgres_pod_name>> -- sh -c 'exec pg_isready --host <<pod_ip>> 3) kubectl exec -it <<postgres_pod_name>> -- cat /var/lib/postgresql/data/pg_hba.conf
  • 我关注了另一个SO question,有一句话让我觉得这与您尝试播放的图像不符 - I tried using a busybox, but it behaves differently, pinging the db successfully.。我会去检查DNS troubleshooting

标签: kubernetes networking raspberry-pi arm


【解决方案1】:

首先,不要将部署工作负载用于需要保存状态的应用程序。这可能会给您带来一些麻烦,甚至数据丢失。 为此,您应该使用statefulset

StatefulSet 是用于管理有状态的工作负载 API 对象 应用程序。

管理一组 Pod 的部署和扩展,并提供 保证这些 Pod 的顺序和唯一性。

与 Deployment 一样,StatefulSet 管理基于 相同的容器规格。与 Deployment 不同,StatefulSet 维护 每个 Pod 的粘性标识。这些 pod 是从 相同的规范,但不可互换:每个都有一个持久的 它在任何重新安排期间维护的标识符。

同样对于数据库,存储应尽可能靠近引擎(由于延迟),最好是hostpath storageClassReadWriteOnce

现在关于您的问题,我的猜测是您在应用程序中连接数据库的方式有问题,或者远程连接可能被 pg_hba.conf 中的定义拒绝

这是一个可以帮助您入门的最小工作示例:

kind: Namespace
apiVersion: v1
metadata:
  name: test
  labels:
    name: test
---
kind: Service
apiVersion: v1
metadata:
  name: postgres-so-test
  namespace: test
  labels:
    app: postgres-so-test
spec:
  selector:
    app: postgres-so-test
  ports:
  - port: 5432
    targetPort: 5432
    name: postgres-so-test
---
kind: StatefulSet
apiVersion: apps/v1
metadata:
  namespace: test
  name: postgres-so-test
spec:
  replicas: 1
  serviceName: postgres-so-test
  selector:
    matchLabels:
      app: postgres-so-test
  template:
    metadata:
      labels:
        app: postgres-so-test
    spec:
      containers:
        - name: postgres
          image: postgres:13.2
          imagePullPolicy: IfNotPresent
          env:
            - name: POSTGRES_USER
              value: johndoe
            - name: POSTGRES_PASSWORD
              value: thisisntthepasswordyourelokingfor
            - name: POSTGRES_DB
              value: home
          ports:
            - containerPort: 5432

现在让我们测试一下。注意:我还将从 Postgres 映像创建一个部署,只是为了在此命名空间中有一个 pod,该 pod 将具有 pg_isready 二进制文件,以便测试与创建的数据库的连接。

pi@rsdev-pi-master:~/test $ kubectl apply -f test_db.yml 
namespace/test created
service/postgres-so-test created
statefulset.apps/postgres-so-test created
pi@rsdev-pi-master:~/test $ kubectl apply -f test_container.yml 
deployment.apps/test-container created
pi@rsdev-pi-master:~/test $ kubectl get pods -n test
NAME                             READY   STATUS    RESTARTS   AGE
postgres-so-test-0               1/1     Running   0          19s
test-container-d77d75d78-cgjhc   1/1     Running   0          12s
pi@rsdev-pi-master:~/test $ sudo kubectl get all -n test
NAME                                 READY   STATUS    RESTARTS   AGE
pod/postgres-so-test-0               1/1     Running   0          26s
pod/test-container-d77d75d78-cgjhc   1/1     Running   0          19s

NAME                       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/postgres-so-test   ClusterIP   10.43.242.51   <none>        5432/TCP   30s

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/test-container   1/1     1            1           19s

NAME                                       DESIRED   CURRENT   READY   AGE
replicaset.apps/test-container-d77d75d78   1         1         1       19s

NAME                                READY   AGE
statefulset.apps/postgres-so-test   1/1     27s

pi@rsdev-pi-master:~/test $ kubectl exec -it test-container-d77d75d78-cgjhc -n test -- /bin/bash
root@test-container-d77d75d78-cgjhc:/# pg_isready -d home -h postgres-so-test -p 5432 -U johndoe
postgres-so-test:5432 - accepting connections

如果您仍然无法连接到数据库,请附上以下内容:

  1. kubectl describe pod &lt;&lt;postgres_pod_name&gt;&gt;
  2. kubectl logs &lt;&lt;postgres_pod_name&gt;&gt; 最好是在您尝试连接到它之后
  3. kubectl exec -it &lt;&lt;postgres_pod_name&gt;&gt; -- cat /var/lib/postgresql/data/pg_hba.conf

也是K8s算子的研究课题。它们对于部署更复杂的生产就绪应用程序堆栈非常有用(例如,带有主数据库 + 副本 + LB 的数据库)

【讨论】:

  • 感谢您的精彩解释。我已经将我的部署更改为有状态集,但我正在努力获得一个运行 pg_isready 的 pod,因为 pi 的 ARMv7 架构并不容易。我会继续尝试并稍后回答
  • 这成功了。老实说,我不确定为什么它现在可以工作,但是在将 postgres 更改为有状态集之后,我遵循了 pg_isready 部分并且它工作了。我更新了我的后端以再次与 postgres 对话,现在也可以使用了。非常感谢!
猜你喜欢
  • 2020-03-04
  • 1970-01-01
  • 2021-10-04
  • 2021-06-27
  • 1970-01-01
  • 2017-06-29
相关资源
最近更新 更多