无法通过 postgres 容器本身的服务访问 postgres
Can't access postgres via service from the postgres container itself
我正在尝试验证我的 postgres pod 是否可以通过我刚刚设置的服务访问。截至目前,我无法验证这一点。我能做的是登录容器 运行 postgres 本身,并尝试通过服务的 IP 与 postgres 服务器通信。这不会成功。但是,我不确定这是否是集群中其他 pods 是否可以通过服务与 postgres 通信的有效测试,或者我的测试方式是否存在问题,或者是否存在我的服务或 pod 配置中的基本问题。
我在一个 minikube 集群上做这一切。
设置 pod 和服务:
$> kubectl create -f postgres-pod.yml
$> kubectl create -f postgres-service.yml
postgres-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: postgres
labels:
env: prod
creation_method: manual
domain: infrastructure
spec:
containers:
- image: postgres:13-alpine
name: kubia-postgres
ports:
- containerPort: 5432
protocol: TCP
env:
- name: POSTGRES_PASSWORD
value: dave
- name: POSTGRES_USER
value: dave
- name: POSTGRES_DB
value: tmp
# TODO:
# volumes:
# - name: postgres-db-volume
postgres-service.yml
apiVersion: v1
kind: Service
metadata:
name: postgres-service
spec:
ports:
- port: 5432
targetPort: 5432
selector:
name: postgres
检查服务是否启动kubectl get services
:
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 35d
postgres-service ClusterIP 10.110.159.21 <none> 5432/TCP 71m
然后,登录postgres容器:
$> kubectl exec --stdin --tty postgres -- /bin/bash
从那里,尝试访问 服务 的 IP:
bash-5.1# psql -U dave -h 10.110.159.21 -p 5432 tmp
psql: error: could not connect to server: Connection refused
Is the server running on host "10.110.159.21" and accepting
TCP/IP connections on port 5432?
所以使用这种方法我无法使用服务的 IP 连接到 postgres 服务器。
我不确定此过程中的几个步骤:
- 服务配置yaml中的selecting by name块是否正确?
- 您能否从服务“背后”的 pods 访问服务的 IP?
- 事实上,这是验证数据库服务器是否可通过服务访问的有效方法,还是有其他方法?
您好,希望您开启 Kubernetes 之旅!
我想在本地集群(docker 中的 Kubernetes)集群上尝试这个。这就是我所做的:
首先,我使用此配置在本地设置了一个类集群(此处信息:https://kind.sigs.k8s.io/docs/user/quick-start/):
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: so-cluster-1
nodes:
- role: control-plane
image: kindest/node:v1.23.5
- role: control-plane
image: kindest/node:v1.23.5
- role: control-plane
image: kindest/node:v1.23.5
- role: worker
image: kindest/node:v1.23.5
- role: worker
image: kindest/node:v1.23.5
- role: worker
image: kindest/node:v1.23.5
在此之后,我使用以下命令创建了我的集群:
kind create cluster --config=config.yaml
接下来,我创建了一个测试命名空间(通过以下方式获得的清单:kubectl create ns so-tests -o yaml --dry-run):
apiVersion: v1
kind: Namespace
metadata:
name: so-tests
从那里开始,我设置了我的环境,所以我不得不在上面部署一个 postgres,但这里是我所做的更改:
1- 我没有创建单例 pod,而是创建了一个有状态集(目的是部署数据库)
2- 我决定继续使用您的 docker 图像“postgres:13-alpine”,并以本机 postgres 用户(不是 dave,也不是 root)向 运行 添加了一个安全上下文——要知道 postgres 用户的 ID 是什么,我首先部署了没有安全上下文的 statefulset 并执行了这个命令:
❯ k exec -it postgres-0 -- bash
bash-5.1# whoami
root
bash-5.1# id
uid=0(root) gid=0(root) groups=1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
bash-5.1# id postgres
uid=70(postgres) gid=70(postgres) groups=70(postgres),70(postgres)
bash-5.1# exit
所以,一旦我知道 postgres 用户的 ID 是 70,我就在 statefulset 清单中添加了这个:
securityContext:
runAsUser: 70
fsGroup: 70
3- 我决定创建一个 secret 和一个 configmap,而不是将配置和 secrets 作为环境变量直接添加到 statefulset 的 pod 配置中:
首先让我们用你的密码创建一个 kubernetes 秘密,这是清单(从这个命令获得:“k create secret generic --from-literal password=dave postgres-secret -o yaml --dry-run=客户端"):
apiVersion: v1
data:
password: ZGF2ZQ==
kind: Secret
metadata:
name: postgres-secret
在此之后我创建了一个 configmap 来存储我们的 postgres 配置,这是清单(通过 运行ning 获得:kubectl create configmap postgres-config --from-literal user=dave - -from-literal db=tmp --dry-run=client -o yaml )
apiVersion: v1
data:
db: tmp
user: dave
kind: ConfigMap
metadata:
name: postgres-config
因为这只是为了测试目的,我没有为 statefulset 设置动态卷配置,pre-provisionned 卷也没有。相反,我配置了一个简单的 emptyDir 来存储 postgres 数据 (/var/lib/postgresql/data)。
N.B.: 默认情况下,emptyDir 卷存储在支持节点的任何介质上 - 可能是磁盘、SSD 或网络存储,具体取决于您的环境。但是,您可以将 emptyDir.medium 字段设置为“Memory”,以告诉 Kubernetes 为您挂载一个 tmpfs(RAM-backed 文件系统)。 (这来自这里Create a new volume when pod restart in a statefulset)
由于它是有状态集,因此必须由无头 kubernetes 服务公开 (https://kubernetes.io/fr/docs/concepts/services-networking/service/#headless-services)
清单如下:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: "postgres"
replicas: 2
selector:
matchLabels:
env: prod
domain: infrastructure
template:
metadata:
labels:
env: prod
domain: infrastructure
spec:
terminationGracePeriodSeconds: 20
securityContext:
runAsUser: 70
fsGroup: 70
containers:
- name: kubia-postgres
image: postgres:13-alpine
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
- name: POSTGRES_USER
valueFrom:
configMapKeyRef:
name: postgres-config
key: user
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: postgres-config
key: db
ports:
- containerPort: 5432
protocol: TCP
volumeMounts:
- name: postgres-test-volume
mountPath: /var/lib/postgresql
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
volumes:
- name: postgres-test-volume
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: postgres-service
labels:
env: prod
domain: infrastructure
spec:
ports:
- port: 5432
protocol: TCP
targetPort: 5432
name: pgsql
clusterIP: None
selector:
env: prod
domain: infrastructure
---
apiVersion: v1
data:
password: ZGF2ZQ==
kind: Secret
metadata:
name: postgres-secret
---
apiVersion: v1
data:
db: tmp
user: dave
kind: ConfigMap
metadata:
name: postgres-config
---
我使用以下方式部署:
kubectl apply -f postgres.yaml
我测试连接到 postgres-0 pod 以使用 $POSTGRES_USER 和 $POSTGRES_PASSWORD 凭据连接我的数据库:
❯ k exec -it pod/postgres-0 -- bash
bash-5.1$ psql --username=$POSTGRES_USER -W --host=localhost --port=5432 --dbname=tmp
Password:
psql (13.6)
Type "help" for help.
tmp=#
我列出了数据库:
tmp=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+-------+----------+------------+------------+-------------------
postgres | dave | UTF8 | en_US.utf8 | en_US.utf8 |
template0 | dave | UTF8 | en_US.utf8 | en_US.utf8 | =c/dave +
| | | | | dave=CTc/dave
template1 | dave | UTF8 | en_US.utf8 | en_US.utf8 | =c/dave +
| | | | | dave=CTc/dave
tmp | dave | UTF8 | en_US.utf8 | en_US.utf8 |
(4 rows)
我连接到“tmp”数据库:
tmp=# \c tmp
Password:
You are now connected to database "tmp" as user "dave".
成功。
我也试过使用IP连接数据库,如你所试:
bash-5.1$ ip a | grep /24
inet 10.244.4.8/24 brd 10.244.4.255 scope global eth0
bash-5.1$ psql --username=$POSTGRES_USER -W --host=10.244.4.8 --port=5432 --dbname=tmp
Password:
psql (13.6)
Type "help" for help.
tmp=#
成功。
然后我下载了 dbeaver(从这里 https://dbeaver.io/download/ )来测试从集群外部的访问:
使用 kubectl port-forward:
kubectl port-forward statefulset/postgres 5432:5432
Forwarding from 127.0.0.1:5432 -> 5432
Forwarding from [::1]:5432 -> 5432
我在 dbeaver 上创建了连接,并且可以使用 dave:dave 凭据
从 localhost:5361 轻松访问数据库“tmp”
kubectl port-forward statefulset/postgres 5432:5432
Forwarding from 127.0.0.1:5432 -> 5432
Forwarding from [::1]:5432 -> 5432
Handling connection for 5432
Handling connection for 5432
完美。
和以前一样(使用 dbeaver),我尝试使用端口转发连接数据库,不是 pod 的,而是服务的:
❯ kubectl port-forward service/postgres-service 5432:5432
Forwarding from 127.0.0.1:5432 -> 5432
Forwarding from [::1]:5432 -> 5432
Handling connection for 5432
Handling connection for 5432
效果也不错!
我还创建了一个独立的 pod,基于我们的配置来访问另一个 pod 中的数据库(通过服务名称作为主机名),这是 pod 的清单:
apiVersion: v1
kind: Pod
metadata:
name: postgres
labels:
app: test
spec:
terminationGracePeriodSeconds: 20
securityContext:
runAsUser: 70
fsGroup: 70
containers:
- name: kubia-postgres
image: postgres:13-alpine
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
- name: POSTGRES_USER
valueFrom:
configMapKeyRef:
name: postgres-config
key: user
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: postgres-config
key: db
ports:
- containerPort: 5432
protocol: TCP
volumeMounts:
- name: postgres-test-volume
mountPath: /var/lib/postgresql
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
volumes:
- name: postgres-test-volume
emptyDir: {}
这是 podtest 内部的连接结果:
bash-5.1$ psql --username=$POSTGRES_USER -W --host=postgres-service --port=5432 --dbname=tmp
Password:
psql (13.6)
Type "help" for help.
tmp=#
- 以下是从 pod/namespace 外部访问它的方法(确保没有阻止连接的网络规则):
StatefulSetName-Ordinal.Service.Namespace.svc.cluster.local
i.e: postgres-0.postgres-service.so-tests.svc.cluster.local
- 从集群外部访问有状态集工作负载是一个好的开始:
希望这对您有所帮助。谢谢你的问题。
B猜
如果只有一 (1) 个副本,您不能(至少使用 minikube)从该服务“背后”的 pod 访问该服务的 IP。
我正在尝试验证我的 postgres pod 是否可以通过我刚刚设置的服务访问。截至目前,我无法验证这一点。我能做的是登录容器 运行 postgres 本身,并尝试通过服务的 IP 与 postgres 服务器通信。这不会成功。但是,我不确定这是否是集群中其他 pods 是否可以通过服务与 postgres 通信的有效测试,或者我的测试方式是否存在问题,或者是否存在我的服务或 pod 配置中的基本问题。
我在一个 minikube 集群上做这一切。
设置 pod 和服务:
$> kubectl create -f postgres-pod.yml
$> kubectl create -f postgres-service.yml
postgres-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: postgres
labels:
env: prod
creation_method: manual
domain: infrastructure
spec:
containers:
- image: postgres:13-alpine
name: kubia-postgres
ports:
- containerPort: 5432
protocol: TCP
env:
- name: POSTGRES_PASSWORD
value: dave
- name: POSTGRES_USER
value: dave
- name: POSTGRES_DB
value: tmp
# TODO:
# volumes:
# - name: postgres-db-volume
postgres-service.yml
apiVersion: v1
kind: Service
metadata:
name: postgres-service
spec:
ports:
- port: 5432
targetPort: 5432
selector:
name: postgres
检查服务是否启动kubectl get services
:
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 35d
postgres-service ClusterIP 10.110.159.21 <none> 5432/TCP 71m
然后,登录postgres容器:
$> kubectl exec --stdin --tty postgres -- /bin/bash
从那里,尝试访问 服务 的 IP:
bash-5.1# psql -U dave -h 10.110.159.21 -p 5432 tmp
psql: error: could not connect to server: Connection refused
Is the server running on host "10.110.159.21" and accepting
TCP/IP connections on port 5432?
所以使用这种方法我无法使用服务的 IP 连接到 postgres 服务器。
我不确定此过程中的几个步骤:
- 服务配置yaml中的selecting by name块是否正确?
- 您能否从服务“背后”的 pods 访问服务的 IP?
- 事实上,这是验证数据库服务器是否可通过服务访问的有效方法,还是有其他方法?
您好,希望您开启 Kubernetes 之旅!
我想在本地集群(docker 中的 Kubernetes)集群上尝试这个。这就是我所做的:
首先,我使用此配置在本地设置了一个类集群(此处信息:https://kind.sigs.k8s.io/docs/user/quick-start/):
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: so-cluster-1
nodes:
- role: control-plane
image: kindest/node:v1.23.5
- role: control-plane
image: kindest/node:v1.23.5
- role: control-plane
image: kindest/node:v1.23.5
- role: worker
image: kindest/node:v1.23.5
- role: worker
image: kindest/node:v1.23.5
- role: worker
image: kindest/node:v1.23.5
在此之后,我使用以下命令创建了我的集群:
kind create cluster --config=config.yaml
接下来,我创建了一个测试命名空间(通过以下方式获得的清单:kubectl create ns so-tests -o yaml --dry-run):
apiVersion: v1
kind: Namespace
metadata:
name: so-tests
从那里开始,我设置了我的环境,所以我不得不在上面部署一个 postgres,但这里是我所做的更改:
1- 我没有创建单例 pod,而是创建了一个有状态集(目的是部署数据库)
2- 我决定继续使用您的 docker 图像“postgres:13-alpine”,并以本机 postgres 用户(不是 dave,也不是 root)向 运行 添加了一个安全上下文——要知道 postgres 用户的 ID 是什么,我首先部署了没有安全上下文的 statefulset 并执行了这个命令:
❯ k exec -it postgres-0 -- bash
bash-5.1# whoami
root
bash-5.1# id
uid=0(root) gid=0(root) groups=1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
bash-5.1# id postgres
uid=70(postgres) gid=70(postgres) groups=70(postgres),70(postgres)
bash-5.1# exit
所以,一旦我知道 postgres 用户的 ID 是 70,我就在 statefulset 清单中添加了这个:
securityContext:
runAsUser: 70
fsGroup: 70
3- 我决定创建一个 secret 和一个 configmap,而不是将配置和 secrets 作为环境变量直接添加到 statefulset 的 pod 配置中:
首先让我们用你的密码创建一个 kubernetes 秘密,这是清单(从这个命令获得:“k create secret generic --from-literal password=dave postgres-secret -o yaml --dry-run=客户端"):
apiVersion: v1
data:
password: ZGF2ZQ==
kind: Secret
metadata:
name: postgres-secret
在此之后我创建了一个 configmap 来存储我们的 postgres 配置,这是清单(通过 运行ning 获得:kubectl create configmap postgres-config --from-literal user=dave - -from-literal db=tmp --dry-run=client -o yaml )
apiVersion: v1
data:
db: tmp
user: dave
kind: ConfigMap
metadata:
name: postgres-config
因为这只是为了测试目的,我没有为 statefulset 设置动态卷配置,pre-provisionned 卷也没有。相反,我配置了一个简单的 emptyDir 来存储 postgres 数据 (/var/lib/postgresql/data)。
N.B.: 默认情况下,emptyDir 卷存储在支持节点的任何介质上 - 可能是磁盘、SSD 或网络存储,具体取决于您的环境。但是,您可以将 emptyDir.medium 字段设置为“Memory”,以告诉 Kubernetes 为您挂载一个 tmpfs(RAM-backed 文件系统)。 (这来自这里Create a new volume when pod restart in a statefulset)
由于它是有状态集,因此必须由无头 kubernetes 服务公开 (https://kubernetes.io/fr/docs/concepts/services-networking/service/#headless-services)
清单如下:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: "postgres"
replicas: 2
selector:
matchLabels:
env: prod
domain: infrastructure
template:
metadata:
labels:
env: prod
domain: infrastructure
spec:
terminationGracePeriodSeconds: 20
securityContext:
runAsUser: 70
fsGroup: 70
containers:
- name: kubia-postgres
image: postgres:13-alpine
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
- name: POSTGRES_USER
valueFrom:
configMapKeyRef:
name: postgres-config
key: user
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: postgres-config
key: db
ports:
- containerPort: 5432
protocol: TCP
volumeMounts:
- name: postgres-test-volume
mountPath: /var/lib/postgresql
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
volumes:
- name: postgres-test-volume
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: postgres-service
labels:
env: prod
domain: infrastructure
spec:
ports:
- port: 5432
protocol: TCP
targetPort: 5432
name: pgsql
clusterIP: None
selector:
env: prod
domain: infrastructure
---
apiVersion: v1
data:
password: ZGF2ZQ==
kind: Secret
metadata:
name: postgres-secret
---
apiVersion: v1
data:
db: tmp
user: dave
kind: ConfigMap
metadata:
name: postgres-config
---
我使用以下方式部署:
kubectl apply -f postgres.yaml
我测试连接到 postgres-0 pod 以使用 $POSTGRES_USER 和 $POSTGRES_PASSWORD 凭据连接我的数据库:
❯ k exec -it pod/postgres-0 -- bash
bash-5.1$ psql --username=$POSTGRES_USER -W --host=localhost --port=5432 --dbname=tmp
Password:
psql (13.6)
Type "help" for help.
tmp=#
我列出了数据库:
tmp=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+-------+----------+------------+------------+-------------------
postgres | dave | UTF8 | en_US.utf8 | en_US.utf8 |
template0 | dave | UTF8 | en_US.utf8 | en_US.utf8 | =c/dave +
| | | | | dave=CTc/dave
template1 | dave | UTF8 | en_US.utf8 | en_US.utf8 | =c/dave +
| | | | | dave=CTc/dave
tmp | dave | UTF8 | en_US.utf8 | en_US.utf8 |
(4 rows)
我连接到“tmp”数据库:
tmp=# \c tmp
Password:
You are now connected to database "tmp" as user "dave".
成功。
我也试过使用IP连接数据库,如你所试:
bash-5.1$ ip a | grep /24
inet 10.244.4.8/24 brd 10.244.4.255 scope global eth0
bash-5.1$ psql --username=$POSTGRES_USER -W --host=10.244.4.8 --port=5432 --dbname=tmp
Password:
psql (13.6)
Type "help" for help.
tmp=#
成功。
然后我下载了 dbeaver(从这里 https://dbeaver.io/download/ )来测试从集群外部的访问:
使用 kubectl port-forward:
kubectl port-forward statefulset/postgres 5432:5432
Forwarding from 127.0.0.1:5432 -> 5432
Forwarding from [::1]:5432 -> 5432
我在 dbeaver 上创建了连接,并且可以使用 dave:dave 凭据
从 localhost:5361 轻松访问数据库“tmp”kubectl port-forward statefulset/postgres 5432:5432
Forwarding from 127.0.0.1:5432 -> 5432
Forwarding from [::1]:5432 -> 5432
Handling connection for 5432
Handling connection for 5432
完美。
和以前一样(使用 dbeaver),我尝试使用端口转发连接数据库,不是 pod 的,而是服务的:
❯ kubectl port-forward service/postgres-service 5432:5432
Forwarding from 127.0.0.1:5432 -> 5432
Forwarding from [::1]:5432 -> 5432
Handling connection for 5432
Handling connection for 5432
效果也不错!
我还创建了一个独立的 pod,基于我们的配置来访问另一个 pod 中的数据库(通过服务名称作为主机名),这是 pod 的清单:
apiVersion: v1
kind: Pod
metadata:
name: postgres
labels:
app: test
spec:
terminationGracePeriodSeconds: 20
securityContext:
runAsUser: 70
fsGroup: 70
containers:
- name: kubia-postgres
image: postgres:13-alpine
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
- name: POSTGRES_USER
valueFrom:
configMapKeyRef:
name: postgres-config
key: user
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: postgres-config
key: db
ports:
- containerPort: 5432
protocol: TCP
volumeMounts:
- name: postgres-test-volume
mountPath: /var/lib/postgresql
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
volumes:
- name: postgres-test-volume
emptyDir: {}
这是 podtest 内部的连接结果:
bash-5.1$ psql --username=$POSTGRES_USER -W --host=postgres-service --port=5432 --dbname=tmp
Password:
psql (13.6)
Type "help" for help.
tmp=#
- 以下是从 pod/namespace 外部访问它的方法(确保没有阻止连接的网络规则):
StatefulSetName-Ordinal.Service.Namespace.svc.cluster.local
i.e: postgres-0.postgres-service.so-tests.svc.cluster.local
- 从集群外部访问有状态集工作负载是一个好的开始:
希望这对您有所帮助。谢谢你的问题。 B猜
如果只有一 (1) 个副本,您不能(至少使用 minikube)从该服务“背后”的 pod 访问该服务的 IP。