如何使用 GKE 启用子域

Posted

技术标签:

【中文标题】如何使用 GKE 启用子域【英文标题】:How to enable subdomain with GKE 【发布时间】:2019-10-22 11:30:14 【问题描述】:

我在 GKE 中有不同的 Kubernetes 部署,我想从不同的外部子域访问它们。

我尝试使用子域“sub1”和“sub2”以及主机名“app”创建 2 个部署,另一个使用主机名“app”的部署以及在 DNS 上配置的 IP XXX.XXX.XXX.XXX 上公开它的服务app.mydomain.com 的

我想从 sub1.app.mydomain.com 和 sub2.app.mydomain.com 访问 2 个子部署

这应该是自动的,添加新部署我无法在每次 DNS 记录时都更改。 也许我以错误的方式解决问题,我是 GKE 的新手,有什么建议吗?

apiVersion:扩展/v1beta1 种类:部署 元数据: 名称:我的主机 规格: 复制品:1 战略: 模板: 元数据: 创建时间戳:空 标签: 名称:我的主机 类型:代理 规格: 主机名:应用程序 容器: - 图片:nginx:高山 名称:nginx 端口: - 名称:nginx 容器端口:80 主机端口:80 重启策略:总是 状态: --- apiVersion:扩展/v1beta1 种类:部署 元数据: 名称:我的子域-1 规格: 复制品:1 战略: 模板: 元数据: 创建时间戳:空 标签: 名称:我的子域-1 类型:应用 规格: 主机名:应用程序 子域:sub1 容器: - 图片:nginx:高山 名称:nginx 端口: - 名称:nginx 容器端口:80 主机端口:80 重启策略:总是 状态: --- apiVersion:扩展/v1beta1 种类:部署 元数据: 名称:我的子域 2 规格: 复制品:1 战略: 模板: 元数据: 创建时间戳:空 标签: 名称:我的子域 2 类型:应用 规格: 主机名:应用程序 子域:sub2 容器: - 图片:nginx:高山 名称:nginx 端口: - 名称:nginx 容器端口:80 主机端口:80 重启策略:总是 状态: --- api版本:v1 种类:服务 元数据: 名称:my-expose-dns 规格: 端口: - 端口:80 选择器: 名称:我的主机 类型:负载均衡器

【问题讨论】:

【参考方案1】:

你想要Ingress。有几个可用的选项(Istio、nginx、traefik 等)。我喜欢使用 nginx,它非常易于安装和使用。安装步骤可以在kubernetes.github.io找到。

安装 Ingress Controller 后,您需要确保已使用 type=LoadBalancer 的 Service 公开它。接下来,如果您使用的是 Google Cloud DNS,请为您的域设置一个通配符条目,其中的 A 记录指向您的 Ingress Controller 服务的外部 IP 地址。在您的情况下,它将是 *.app.mydomain.com。

因此,现在您到 app.mydomain.com 的所有流量都将流向该负载平衡器并由您的 Ingress Controller 处理,因此现在您需要为所需的任何服务添加 Service 和 Ingress Entities。

apiVersion: v1
kind: Service
metadata:
  name: my-service1
spec:
  selector:
    app: my-app-1
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP

apiVersion: v1
kind: Service
metadata:
  name: my-service2
spec:
  selector:
    app: my-app2
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: name-virtual-host-ingress
spec:
  rules:
  - host: sub1.app.mydomain.com
    http:
      paths:
      - backend:
          serviceName: my-service1
          servicePort: 80
  - host: sub2.app.mydomain.com
    http:
      paths:
      - backend:
          serviceName: my-service2
          servicePort: 80

显示的路由是基于主机的,但您可以轻松地将这些服务处理为基于路径的服务,因此到 app.mydomain.com/service1 的所有流量都将流向您的一个部署。

【讨论】:

【参考方案2】:

这可能是一个解决方案,就我而言,我需要更动态的东西。每次添加子域时,我都不会更新入口。

我几乎用这样的 nginx 代理解决了:

 apiVersion: extensions/v1beta1
    种类:部署
    元数据:
    名称:我的子域-1
    规格:
    复制品:1
    战略: 
    模板:
        元数据:
        创建时间戳:空
        标签:
            名称:我的子域-1
            类型:应用
        规格:
        主机名:sub1
        子域:我的内部主机
        容器:
            - 图片:nginx:高山
            名称:nginx
            端口:
                - 名称:nginx
                容器端口:80
                主机端口:80
        重启策略:总是
    状态: 
    ---
    apiVersion:扩展/v1beta1
    种类:部署
    元数据:
    名称:我的子域 2
    规格:
    复制品:1
    战略: 
    模板:
        元数据:
        创建时间戳:空
        标签:
            名称:我的子域 2
            类型:应用
        规格:
        主机名:sub2
        子域:我的内部主机
        容器:
            - 图片:nginx:高山
            名称:nginx
            端口:
                - 名称:nginx
                容器端口:80
                主机端口:80
        重启策略:总是
    状态: 
    ---
    api版本:v1
    种类:ConfigMap
    元数据:
    名称:nginx-config-dns-file
    数据:
    nginx.conf:|
        服务器 
        听 80;
        server_name ~^(?.*?)\.;

        地点 / 
            proxy_pass http://$subdomain.my-internal-host;
            根 /usr/share/nginx/html;
            索引 index.html 索引.htm;
        

        error_page 500 502 503 504 /50x.html;
        位置 = /50x.html 
            根 /usr/share/nginx/html;
        
        
    ---
    apiVersion:扩展/v1beta1
    种类:部署
    元数据:
    名称:我的代理
    规格:
    复制品:1
    战略: 
    模板:
        元数据:
        创建时间戳:空
        标签:
            名称:我的代理
            类型:应用
        规格:
        子域:我的内部主机
        容器:
            - 图片:nginx:高山
            名称:nginx
            卷装:
                - 名称:nginx-config-dns-file
                挂载路径:/etc/nginx/conf.d/default.conf.test
                子路径:nginx.conf
            端口:
                - 名称:nginx
                容器端口:80
                主机端口:80
        卷:
            - 名称:nginx-config-dns-file
            配置映射:
                名称:nginx-config-dns-file
        重启策略:总是
    状态: 
    ---
    api版本:v1
    种类:服务
    元数据:
    名称:我的内部主机
    规格:
    选择器:
        类型:应用
    集群IP:无
    端口:
        - 名称:sk-port
        端口:80
        目标端口:80
    ---
    api版本:v1
    种类:服务
    元数据:
    名称:sk-expose-dns
    规格:
    端口:
        - 端口:80
    选择器:
        名称:我的代理
    类型:负载均衡器

我确实明白我需要“my-internal-host”服务来允许所有部署在内部相互查看。 现在的问题只是nginx的proxy_pass,如果我用'proxy_pass http://sub1.my-internal-host;'来改变它它有效,但不适用于正则表达式。

问题与 nginx 解析器有关。

【讨论】:

您似乎正在尝试将 Ingress 构建到您的应用程序中。从关注点分离的角度来看,这并不是很好。 你能解释一下吗?我想在外部自动提供新的子域 如果通过“自动”您说您不愿意像我在回答中显示的那样向 Kubernetes Ingress 实体添加新规则,那么我没有适合您的解决方案。听起来您正在寻找类似大使功能请求的内容:github.com/datawire/ambassador/issues/377。我会关注这个话题,看看对话的去向。 是的!我只是在寻找这样的东西【参考方案3】:

解决了!

这是正确的 nginx 配置:

server 
  listen       80;
  server_name ~^(?<subdomain>.*?)\.;
  resolver kube-dns.kube-system.svc.cluster.local valid=5s;

  location / 
      proxy_pass         http://$subdomain.my-internal-host.default.svc.cluster.local;
      root   /usr/share/nginx/html;
      index  index.html index.htm;
  

  error_page   500 502 503 504  /50x.html;
  location = /50x.html 
      root   /usr/share/nginx/html;
  

【讨论】:

以上是关于如何使用 GKE 启用子域的主要内容,如果未能解决你的问题,请参考以下文章

如何在 GKE 中通过入口启用 Cors

如何使用 terraform gke 模块启用 gce_persistent_disk_csi_driver_config

在 GKE 中启用审核日志记录

如何单独为子域名启用 SSL,即使用 HTTPS 访问

如何单独为子域名启用 SSL,即使用 HTTPS 访问

如何在具有默认 istio beta 功能的 GKE 中安装带有 prometheus 的 Kiali Dashboard?