如何使用GKE启用子域名

4
我在GKE中有不同的Kubernetes部署,希望可以从不同的外部子域名访问它们。我尝试创建两个部署,子域名为"sub1"和"sub2",主机名为"app";另外一个部署使用主机名"app",并且有一个服务将其暴露在IP XXX.XXX.XXX.XXX上,在app.mydomain.com的DNS中配置。我希望可以从sub1.app.mydomain.com和sub2.app.mydomain.com访问这两个子部署。这应该是自动的,每次添加新的部署时,我不能每次更改DNS记录。也许我错误地解决了问题,我是GKE的新手,有什么建议吗?
apiVersion:extensions/v1beta1 
kind:Deployment
metadata:
  name:my-host
spec:
  replicas:1
  strategy:{}
  template:
    metadata:
      creationTimestamp:null
      labels:
        name:my-host
        type:proxy
    spec:
      hostname:app
      containers:
        - image:nginx:alpine
          name:nginx
          ports:
            - name:nginx
              containerPort:80
              hostPort:80
      restartPolicy:Always
status:{}
---
apiVersion:extensions/v1beta1 
kind:Deployment
metadata:
  name:my-subdomain-1
spec:
  replicas:1
  strategy:{}
  template:
    metadata:
      creationTimestamp:null
      labels:
        name:my-subdomain-1
        type:app
    spec:
      hostname:app
      subdomain:sub1
      containers:
        - image:nginx:alpine
          name:nginx
          ports:
            - name:nginx
              containerPort:80
              hostPort:80
      restartPolicy:Always
status:{}
---
apiVersion:extensions/v1beta1 
kind:Deployment
metadata:
  name:my-subdomain-2
spec:
  replicas:1
  strategy:{}
  template:
    metadata:
      creationTimestamp:null
      labels:
        name:my-subdomain-2
        type:app
    spec:
      hostname:app
      subdomain:sub2
      containers:
        - image:nginx:alpine
          name:nginx
          ports:
            - name:nginx
              containerPort:80
              hostPort:80
      restartPolicy:Always
status:{}
---
apiVersion:v1 
kind:Service
metadata:
  name:my-expose-dns
spec:
  ports:
    - port:80
  selector:
    name:my-host
  type:LoadBalancer
3个回答

5

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

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

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

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配置:

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;
  }
}

0

这可能是一个解决方案,但对于我的情况,我需要更加动态的东西。我不想每次添加子域时都更新入口。

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

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-subdomain-1
spec:
  replicas: 1
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        name: my-subdomain-1
        type: app
    spec:
      hostname: sub1
      subdomain: my-internal-host
      containers:
        - image: nginx:alpine
          name: nginx
          ports:
            - name: nginx
              containerPort: 80
              hostPort: 80
      restartPolicy: Always
  status: {}
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-subdomain-2
spec:
  replicas: 1
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        name: my-subdomain-2
        type: app
    spec:
      hostname: sub2
      subdomain: my-internal-host
      containers:
        - image: nginx:alpine
          name: nginx
          ports:
            - name: nginx
              containerPort: 80
              hostPort: 80
      restartPolicy: Always
  status: {}
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config-dns-file
data:
  nginx.conf: |
    server {
      listen       80;
      server_name ~^(?.*?)\.;
location / { proxy_pass http://$subdomain.my-internal-host; 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; } } --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: my-proxy spec: replicas: 1 strategy: {} template: metadata: creationTimestamp: null labels: name: my-proxy type: app spec: subdomain: my-internal-host containers: - image: nginx:alpine name: nginx volumeMounts: - name: nginx-config-dns-file mountPath: /etc/nginx/conf.d/default.conf.test subPath: nginx.conf ports: - name: nginx containerPort: 80 hostPort: 80 volumes: - name: nginx-config-dns-file configMap: name: nginx-config-dns-file restartPolicy: Always status: {} --- apiVersion: v1 kind: Service metadata: name: my-internal-host spec: selector: type: app clusterIP: None ports: - name: sk-port port: 80 targetPort: 80 --- apiVersion: v1 kind: Service metadata: name: sk-expose-dns spec: ports: - port: 80 selector: name: my-proxy type: LoadBalancer

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

问题与nginx解析器有关。


看起来你正在尝试将Ingress集成到你的应用中。从关注点分离的角度来看,这并不是一个好的做法。 - frankd
你能否更好地解释一下吗?我想要自动地在外部提供新的子域名。 - Luca Carducci
如果你所说的“自动化”是指你不想像我在答案中展示的那样向Kubernetes Ingress实体添加新规则,那么我没有一个很好的解决方案。听起来你正在寻找像Ambassador功能请求中描述的那样的东西:https://github.com/datawire/ambassador/issues/377。我会关注这个话题,看看讨论会走向何方。 - frankd
是的!我正好在找这样的东西。 - Luca Carducci

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接