使用 Ingress Nginx 代理 Docker Hub

背景

在某些网络环境中,直接访问 Docker Hub 可能会很慢或不稳定。通过在您的 Kubernetes 集群中使用 Ingress Nginx 作为反向代理,您可以缓存镜像并加快拉取速度。

本文档将指导您如何配置 Ingress Nginx 来代理对 Docker Hub 的请求。

先决条件

  • 一个正在运行的 Kubernetes 集群。
  • 已经安装并配置了 Ingress Nginx Controller。
  • 拥有一个可以配置的域名。

配置步骤

1. 创建 ExternalName Service

首先,我们需要创建一个 ExternalName 类型的 Service,它将作为 Docker Hub 注册中心的内部 DNS 别名。

1
2
3
4
5
6
7
8
apiVersion: v1
kind: Service
metadata:
  name: docker-hub-registry
  namespace: default
spec:
  type: ExternalName
  externalName: registry-1.docker.io

这个 Service 会将 docker-hub-registry.default.svc.cluster.local 解析为 registry-1.docker.io

2. 创建 Ingress 规则

接下来,我们创建一个 Ingress 规则,将来自特定域名的流量路由到我们刚刚创建的 ExternalName Service。

请将 dockerhub.yourdomain.com 替换为您自己的域名。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: docker-hub-proxy
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
spec:
  ingressClassName: nginx
  rules:
  - host: dockerhub.yourdomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: docker-hub-registry
            port:
              number: 443
  tls:
  - hosts:
    - dockerhub.yourdomain.com
    secretName: your-domain-tls # 替换为您的 TLS 证书

2.1 (可选) 使用 cert-manager 自动生成 TLS 证书

如果您在集群中安装了 cert-manager,则可以自动管理 TLS 证书。

首先,请确保您已经安装了 cert-manager。然后,创建一个 IssuerClusterIssuer 来指定证书颁发机构。例如,使用 Let’s Encrypt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: kbsonlong@gmail.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - http01:
        ingress:
          class: nginx

然后,修改 Ingress 资源,添加 cert-manager.io/cluster-issuer 注解,并让 cert-manager 自动创建和管理 secretName

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: docker-hub-proxy
  namespace: default
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod" # 指定 Issuer
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
spec:
  ingressClassName: nginx
  rules:
  - host: dockerhub.yourdomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: docker-hub-registry
            port:
              number: 443
  tls:
  - hosts:
    - dockerhub.yourdomain.com
    secretName: your-domain-tls # cert-manager 会自动创建和管理这个 secret

注解解释:

  • nginx.ingress.kubernetes.io/backend-protocol: "HTTPS": 告诉 Ingress Nginx 后端服务使用 HTTPS。
  • nginx.ingress.kubernetes.io/proxy-body-size: "0": 允许上传任意大小的镜像层。
  • nginx.ingress.kubernetes.io/proxy-read-timeout: "600": 延长代理读取超时时间。
  • nginx.ingress.kubernetes.io/proxy-send-timeout: "600": 延长代理发送超时时间。

3. 配置 Docker 客户端

最后,您需要在 Docker 客户端上配置镜像仓库地址,以使用您的代理。

编辑 Docker 的配置文件 (/etc/docker/daemon.json 或在 Docker Desktop 的设置中),添加您的代理地址。

如果您为 Ingress 配置了有效的 TLS 证书,则无需将其添加到 insecure-registries

重启 Docker 服务后,您就可以通过您的代理拉取和推送镜像了。

例如:

1
docker pull dockerhub.yourdomain.com/library/ubuntu

4. 镜像地址转换示例

当您配置好代理后,可以将原始的 Docker Hub 镜像地址转换为通过您的代理访问的地址。假设您的代理域名是 regis.kbsonlong.com

原始地址:

1
docker.io/nginx/nginx-ingress:edge-alpine

转换后地址:

1
regis.kbsonlong.com/docker.io/nginx/nginx-ingress:edge-alpine

您可以使用转换后的地址来拉取镜像:

1
docker pull regis.kbsonlong.com/docker.io/nginx/nginx-ingress:edge-alpine
0%