在Digital Ocean托管的Kubernetes上暴露端口80,无需负载均衡器。

23

我希望能够在不使用Digital Ocean的负载均衡器的情况下,在端口80上公开我的Kubernetes托管的Digital Ocean(单节点)集群服务。这是否有可能?我该如何实现?

这基本上是一个业余项目(我正在开始学习Kubernetes),只想保持成本非常低。


如果您对成本敏感,为什么不能使用Minikube?https://kubernetes.io/docs/tasks/tools/install-minikube/ - Steephen
1
因为该应用程序仍需公开访问,所以需要像个人网站或组合型Web应用程序之类的东西。您提供的链接表明minikube只能让您在“个人计算机上的虚拟机中运行”,这还不足以实现此目标。 - Shawn
2个回答

37
你可以部署一个配置为使用主机网络和端口80/443的Ingress。
DO群集的防火墙默认情况下不会打开80/443入站。如果您编辑自动创建的防火墙规则,它们最终将重置。解决方案是创建一个单独的防火墙,也指向相同的Kubernetes工作节点:
$ doctl compute firewall create \
--inbound-rules="protocol:tcp,ports:80,address:0.0.0.0/0,address:::/0 protocol:tcp,ports:443,address:0.0.0.0/0,address:::/0" \
--tag-names=k8s:CLUSTER_UUID \
--name=k8s-extra-mycluster

从仪表板或doctl kubernetes cluster list的ID列中获取CLUSTER_UUID值。

  1. 使用主机网络创建nginx ingress。我在下面包含了helm chart配置,但您也可以通过直接安装过程完成。

编辑:上面链接中的Helm图表已被弃用,因此安装图表的正确方式(根据新文档)是:

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

在该仓库添加并更新后{{}}

# For Helm 2
$ helm install stable/nginx-ingress --name=myingress -f myingress.values.yml

# For Helm 3
$ helm install myingress stable/nginx-ingress -f myingress.values.yml

#EDIT: The New way to install in helm 3
helm install myingress ingress-nginx/ingress-nginx -f myingress.values.yaml

用于图表的myingress.values.yml

---
controller:
  kind: DaemonSet
  hostNetwork: true
  dnsPolicy: ClusterFirstWithHostNet
  daemonset:
    useHostPort: true
  service:
    type: ClusterIP
rbac:
  create: true
  1. 您应该能够通过任何工作节点IP访问集群的:80和:443端口,并且它将路由流量到您的Ingress。

  2. 由于节点IP可能会更改,因此请考虑部署external-dns来管理DNS条目以指向您的工作节点。同样,使用helm图表并假设您的DNS域由DigitalOcean托管(尽管任何受支持的DNS提供商都可以使用):

# For Helm 2
$ helm install --name=mydns -f mydns.values.yml stable/external-dns

# For Helm 3
$ helm install mydns stable/external-dns -f mydns.values.yml

mydns.values.yml用于图表:

---
provider: digitalocean
digitalocean:
  # create the API token at https://cloud.digitalocean.com/account/api/tokens
  # needs read + write
  apiToken: "DIGITALOCEAN_API_TOKEN"
domainFilters:
  # domains you want external-dns to be able to edit
  - example.com
rbac:
  create: true

创建一个 Kubernetes Ingress 资源,将请求路由到现有的 Kubernetes 服务:
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: testing123-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: testing123.example.com             # the domain you want associated
      http:
        paths:
          - path: /
            backend:
              serviceName: testing123-service  # existing service
              servicePort: 8000                # existing service port

大约一分钟后,您应该会看到DNS记录出现并且可以解析:
$ dig testing123.example.com             # should return worker IP address
$ curl -v http://testing123.example.com  # should send the request through the Ingress to your backend service

编辑:编辑自动创建的防火墙规则最终会出问题,应添加单独的防火墙。


2
非常感谢您!在找到这个好答案之前,我已经花了三天以上的时间。 - stasdeep
1
helm3 的命令是:helm install myingress stable/nginx-ingress -f myingress.values.yml - hkarask
1
能否提供这些指令而不使用像Helm这样的其他依赖项? - marked-down
2
我发现这个配置导致了集群 IP 地址出现在 DNS 中,而不是节点的可路由公共 IP。我通过对 myingress.values.yml 进行更改来解决这个问题:将 controller.publishService.enabled 设置为 false。不确定这是否是正确的做法,但它修复了 DNS。 - 46bit
1
这个答案对我帮助很大,但是 external-dns 在使用 Cloudflare 时没有起作用,因为它从 nginx ingress 中获取了内部 CluserIP 地址,而不是节点的外部 IP。我使用的解决方案是直接使用 https://github.com/calebdoxsey/kubernetes-cloudflare-sync 来同步节点的外部 IP 到类似 k8s.mydomain 的地址。然后,每当我添加新的 nginx ingress 时,我只需向此地址添加一个 CNAME。 - mcartmell
显示剩余4条评论

1

一个NodePort服务可以实现你想要的功能。就像这样:

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  type: NodePort
  selector:
    app: MyApp
  ports:
  - protocol: TCP
    nodePort: 80
    targetPort: 80

这将把节点的80端口传输重定向到您的pod的80端口,发布节点IP到DNS即可。一般来说,像这样将服务暴露给外部世界是非常糟糕的想法,因为单个节点通过所有流量到达服务既会接收不平衡的负载,也是单点故障。然而,对于单节点群集,这种考虑并不适用,因此在 LoadBalancer 和 Ingress 是容错的情况下,NodePort 最适合这种极特殊情况。

1
谢谢您的回复和示例!我读到nodePort被限制在非标准端口(30000-32767)上。在这种情况下是真的吗? - Joseph Horsch
4
你说得对,我错误地阅读了文档。我之前提出的解决方案是行不通的。 - Steve McKay
以下是在没有使用LoadBalancer的情况下将ingress controller service暴露给外部用户的唯一方法吗?当我使用NodePort时,我必须通过使用NginxApache将80绑定到NodePort(在30000〜32767之间)。 - Jinsu

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