17

所以我将 Kubernetes 用于一个副项目,它很棒。运行一个像我这样的小项目更便宜(一个 3-5 个实例的小集群基本上可以满足我在 GCP 上每月大约 30 美元所需的一切)。

我唯一苦苦挣扎的领域是尝试使用 kubernetes Ingress 资源映射到集群并分散到我的微服务(它们是小型 Go 或 Node 后端)。我有入口的配置设置以映射到不同的服务,那里没有问题。

我知道当您创建入口资源时,您可以很容易地让 GCP 启动 LoadBalancer。这很好,但它也代表了另外 20 美元/月,这增加了项目的成本。一旦/如果这件事得到了一些关注,那可能会被忽略,但现在以及为了更好地理解 Kubernetes,我想做以下事情:

  • 从 GCP 获取静态 IP,
  • 与入口资源一起使用
  • 在同一集群中托管负载均衡器(使用 nginx 负载均衡器)
  • 避免为外部负载均衡器付费

有什么方法可以使用 Kubernetes 和入口资源来完成吗?

谢谢!

4

4 回答 4

8

是的,这是可能的。部署您的入口控制器,并使用 NodePort 服务部署它。例子:

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress-controller
  namespace: kube-system
  labels:
    k8s-app: nginx-ingress-controller
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 32080
    protocol: TCP
    name: http
  - port: 443
    targetPort: 443
    nodePort: 32443
    protocol: TCP
    name: https
  selector:
    k8s-app: nginx-ingress-controller

现在,使用 DNS 条目创建一个入口:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: my-app-service #obviously point this to a valid service + port
          servicePort: 80

现在,假设您的静态 IP 连接到任何运行 kube-proxy 的 kubernetes 节点,已更新 DNS 以指向静态 IP,您应该能够访问myapp.example.com:32080并且入口会将您映射回您的应用程序。

一些额外的事情:

如果您想使用低于 32080 的端口,请记住,如果您使用的是 CNI 网络,那么您将在使用 hostport 时遇到问题。建议在端口 80 上监听负载均衡器,我想你可以只设置 nginx 来进行代理传递,但这变得很困难。这就是为什么建议使用您的云提供商的负载均衡器:)

于 2017-04-03T17:26:17.457 回答
4

TLDR:如果您想在 3000 以下的端口上提供您的网站/网络服务,那么不,这是不可能的。如果有人找到一种方法来做到这一点,我很想知道怎么做。

我尝试在低于 3000 的端口上提供服务时使用的两种主要方法包括:

  • nginx-ingress将控制器服务安装为 类型NodePort,侦听端口 80 和 443。但是,这会导致以下错误:
    Error: UPGRADE FAILED: Service "nginx-ingress-controller" is invalid:
    spec.ports[0].nodePort: Invalid value: 80: provided port is not in the
    valid range. The range of valid ports is 30000-32767
    
    解决此错误的方法是更改--service-node-port-range​​启动时使用的标志kube-apiserver。但是,无法在 GCP 上访问此配置。如果您想自己尝试,可以在此处查看说明:Kubernetes 服务节点端口范围
  • 按照线程Expose port 80 and 443 on Google Container Engine without load balancer中的步骤操作。这依赖于使用附加到 a的externalIP属性。乍一看,这似乎是一个理想的解决方案。但是,该属性的工作方式存在错误。它不接受外部静态 IP,而是接受内部临时 IP。如果您在现场硬编码一个内部的临时 IP,然后通过 GCP Console 将一个外部的静态 IP 附加到集群中的一个节点,请求就会成功路由。但是,这不是一个可行的解决方案,因为您现在已经在您的servicetype: ClusterIPexternalIPexternalIPservice定义,因此随着节点内部 IP 的变化,您的网站将不可避免地离线。

如果您可以在 3000 以上的端口上提供服务,请参阅下面的说明。


如何删除 LoadBalancer(仅允许在大于 3000 的端口上提供服务)

我试过删除我的 LoadBalancer,这是我能想到的最好的解决方案。它有以下缺陷:

  • 用于访问网页的端口不是通常的 80 和 443,因为从节点公开这些端口并非易事。如果我弄清楚了,我稍后会更新。

以及以下好处:

  • 没有负载平衡器。
  • 网站/网络服务的 IP 是静态的。
  • 它依赖于流行的nginx-ingress舵图。
  • 它使用ingress, 允许完全控制如何services根据请求的路径将请求路由到您。

1.安装入口服务和控制器

假设您已经安装了 Helm(如果您不按照此处的步骤操作:在 GKE 上安装 Helm),请nginx-ingress使用type.NodePort

helm install \
  --name nginx-ingress \
  stable/nginx-ingress \
  --set rbac.create=true \
  --set controller.publishService.enabled=true \
  --set controller.service.type=NodePort \
  --set controller.service.nodePorts.http=30080 \
  --set controller.service.nodePorts.https=30443

2. 创建入口资源

为您的路由创建入口定义。

# my-ingress-resource.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: reverse-proxy
  namespace: production # Namespace must be the same as that of target services below.
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "false" # Set to true once SSL is set up.
spec:
  rules:
  - http:
      paths:
      - path: /api
        backend:
          serviceName: backend
          servicePort: 3000
      - path: /
        backend:
          serviceName: frontend
          servicePort: 80

然后安装它

kubectl apply -f my-ingress-resource.yaml

3.创建防火墙规则

找到您的集群的标签。

gcloud compute instances list

如果您的集群实例的名称类似于

gke-cluster-1-pool-1-fee097a3-n6c8
gke-cluster-1-pool-1-fee097a3-zssz

那么你的集群标签是gke-cluster-1-pool-1-fee097a3.

转到GCP 防火墙页面确认您在导航栏中选择了正确的项目。

单击“创建防火墙规则”。给规则起一个像样的名字。您可以将大部分设置保留为默认值,但在“目标标签”下超过您的集群标签。将源 IP 范围设置为0.0.0.0/0。在协议和端口下,将“全部允许”更改为“指定的协议和端口”。选中 TCP 框,然后30080, 30443输入输入字段。点击“创建”。

4.创建静态IP

转到https://console.cloud.google.com/networking/addresses/并单击“保留静态地址”。给它一个描述性的名称,然后选择正确的区域。选择正确的区域后,您应该能够单击“附​​加到”下拉菜单并选择您的 Kubernetes 节点之一。点击“预订”。

5.测试配置

保留静态 IP 后,通过查看外部 IP 地址列表找出授予了哪个静态 IP 。

将其复制到浏览器中,然后添加一个端口(<your-ip>:30080用于 HTTP 或https://<your-ip>:30443HTTPS)。您应该看到您的网页。

于 2019-12-26T23:21:38.677 回答
0

您还可以制作一个 nginx-ingress 图表,让它拉一个临时 IP,然后将其升级为静态。这将为您留下一个 L7 单区域负载均衡器。

本指南将通过它。如果你使用 kube-lego,你可以忽略 TLS 的东西,它和 nginx-ingress 一样好用

https://github.com/kubernetes/ingress-nginx/tree/master/docs/examples/static-ip

于 2018-01-17T16:19:24.523 回答
0

原始来源,但它包含我从未使用过的 Digital Ocean 详细信息。老实说,它挽救了我的生命,并且可以使用 3000 以下的端口,但老实说,我不确定它是如何工作的。

我的设置是使用这个Nginx 入口控制器。使用 helm 安装它,并提供一个配置文件:

$ helm install my-nginx ingress-nginx/ingress-nginx -f config.yaml

配置文件应包含:

controller:
  kind: DaemonSet
  hostNetwork: true
  dnsPolicy: ClusterFirstWithHostNet
  daemonset:
    useHostPort: true
  service:
    type: ClusterIP
rbac:
  create: true

您可以在此处找到默认值,但我不知道如何理解该配置。

之后,您可以创建入口 yaml:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: web-app
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/proxy-body-size: "100m"
    cert-manager.io/cluster-issuer: "letsencrypt"
    nginx.ingress.kubernetes.io/server-alias: "example.com"
  labels:
    app: web-app
spec:
  tls:
    - hosts:
      - example.com
      secretName: prod-certs
  rules:
    - host: example.com
      http: 
        paths:
        - backend:
            serviceName: myservice
            servicePort: 443

这是我的,可能对你不起作用,但试试吧!

它指向的服务入口规则是NodePort类型:

apiVersion: v1
kind: Service
metadata:
  name: myservice
  labels:
    app: myservice
spec:
  type: NodePort
  ports:
  - port: 443
    targetPort: 80

但我相信ClusterIP也有效。

除此之外,其中一个虚拟机有一个公共静态 IP,我们使用该 IP 作为我们的域名。

所以我相信的过程是。域名转换为该静态 IP。然后流量到达 Ingress 控制器,我不知道它是如何工作的,但是你的流量会匹配到某个规则,并被重定向到服务。端口是在 Ingress 中定义的,因此您也可以使用 3000 个以下的端口,但我不知道这个“解决方案”如何在性能方面发挥作用,我也不知道 Ingress 控制器如何在未公开的情况下接受流量。

设置 Ingress 可能是我经历过的最糟糕的经历之一,实际上我采用了这种混乱的方法,因为使用LoadBalancer服务类型更糟糕。祝你好运!

于 2021-01-17T12:45:32.707 回答