Kubernetes 服务无法访问

Kubernetes Service unreachable

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

我已经部署了一个 postgresql 和一个 spring 启动应用程序(称为 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
---

餐盘镜像是一个 arm32v7 镜像 运行 一个 jar 文件。 在集群内部,膳食规划器使用连接字符串 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.

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

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

StatefulSet is the workload API object used to manage stateful applications.

Manages the deployment and scaling of a set of Pods, and provides guarantees about the ordering and uniqueness of these Pods.

Like a Deployment, a StatefulSet manages Pods that are based on an identical container spec. Unlike a Deployment, a StatefulSet maintains a sticky identity for each of their Pods. These pods are created from the same spec, but are not interchangeable: each has a persistent identifier that it maintains across any rescheduling.

同样对于数据库,存储应该尽可能靠近引擎(由于延迟)最好是 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,它将具有 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 <<postgres_pod_name>>
  2. kubectl logs <<postgres_pod_name>> 理想情况下,您已尝试连接到它
  3. kubectl exec -it <<postgres_pod_name>> -- cat /var/lib/postgresql/data/pg_hba.conf

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