Ingress配置pgAdmin需要注意的问题

当使用 Docker 或者 Docker Compose 部署 pgAdmin 来方便本地开发访问使用的时候,是不需要额外注意的,因为通常都是直接暴露端口出去

但是基于 K8s 环境下部署的时候,需要稍微注意一点地方

K8s 集群准备

K8s 的搭建方式多种多样,比如 k3d、kubeadm、kind 等,由于多年之前有裸装 Oracle 把系统搞烂的经历,对于一些软件的安装,我这边是比较谨慎的。况且后面接触了容器,能在里面跑就里面跑,什么两倍读写的问题不考虑,所以我使用的是 kind 来搭建集群

为了服务在容器外能访问,kind 创建 K8s 集群的时候还需要一些额外的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
apiServerAddress: 127.0.0.1
apiServerPort: 6443
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP

Ingress Controller 准备

K8s 暴露服务的方式也多种多样,比如 NodePort、LoadBalancer、Ingress。由于 kind 的特殊性,整个 K8s 集群都跑在容器中,所以就算 NodePort 也是容器里的端口,所以这次主要讨论 Ingress,使用的是 Nginx

使用 Ingress,首先需要在集群中安装一个 Ingress Controller,然后通过 Ingress 来进行一些配置,当 apply 的时候,Ingress Controller 会自动更新 nginx.conf 并进行 reload

如果之前配置过 Nginx,其实类比起来是很像的,一个 Ingress Controller 相当于一个 Nginx,一个 Ingress 则好比 Nginx 的配置文件

当 Ingress Controller 准备好后,会以 NodePort 的方式暴露 80 和 443 端口

1
2
3
NAME                                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller NodePort 10.96.30.54 <none> 80:30860/TCP,443:31875/TCP 3d

pgAdmin 准备

为了简单起见,使用 helm 来安装 pgAdmin

1
helm install pgadmin runix/pgadmin4 --set env.email=root@linweiyuan.com --set env.password=toor

Ingress 准备

配置好 Ingress 规则,因为想做到访问不同的 path 路由到不同的服务,所以这里用 /pgAdmin 来设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: pgadmin-ingress
spec:
rules:
- http:
paths:
- pathType: Prefix
path: "/pgAdmin"
backend:
service:
name: pgadmin-pgadmin4
port:
number: 80

但是此时访问 http://localhost/pgAdmin 的时候,会返回 404

1
2
Not Found The requested URL was not found on the server. If you entered the URL
manually please check your spelling and try again.

pgAdmin 访问解决

查看官方文档,会发现这么一句话

1
If you wish to host pgAdmin under a subdirectory rather than on the root of the server, you must specify the location and set the X-Script-Name header which tells the pgAdmin container how to rewrite paths

就是说 Nginx 的配置里要加 X-Script-Name,但是在 K8s 里要怎么加?

前面提过,其实无非是修改 Ingress 的配置,此时如果进入 Ingress Controller 的 pod 中查看配置文件,会发现当前配置

1
2
3
4
5
6
7
bash-5.1$ hostname
ingress-nginx-controller-65b4b4df7d-rhd2k
bash-5.1$ cat -n nginx.conf | grep pgAdmin
297 location /pgAdmin/ {
303 set $location_path "/pgAdmin";
415 location = /pgAdmin {
421 set $location_path "/pgAdmin";

而根据 pgAdmin 官方文档的指引,需要把配置加到 location 下,回头查看 K8s 官方文档,发现其实是配置 nginx.ingress.kubernetes.io/configuration-snippet

因此配置文件进行修改,完整配置文件如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: pgadmin-ingress
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header X-Script-Name /pgAdmin;
spec:
rules:
- http:
paths:
- pathType: Prefix
path: "/pgAdmin"
backend:
service:
name: pgadmin-pgadmin4
port:
number: 80

再 apply

1
2
kaf pgadmin-ingress.yaml
ingress.networking.k8s.io/pgadmin-ingress configured

再查看 nginx.conf,已经生效了

1
2
3
4
5
6
7
bash-5.1$ cat -n nginx.conf | grep pgAdmin
297 location /pgAdmin/ {
303 set $location_path "/pgAdmin";
409 proxy_set_header X-Script-Name /pgAdmin;
417 location = /pgAdmin {
423 set $location_path "/pgAdmin";
529 proxy_set_header X-Script-Name /pgAdmin;

此时再访问 http://localhost/pgAdmin

会自动跳转 http://localhost/pgAdmin/login?next=%2FpgAdmin%2F

用上面 helm 设置的用户名和密码即可登录进去,问题解决