将裸机 kubernetes 集群暴露到互联网
Exposing bare metal kubernetes cluster to internet
我正在尝试在裸机专用服务器上设置自己的单节点 kubernetes 集群。我在开发运营方面经验不足,但我需要为自己的项目部署一些服务。我已经使用 juju
和 conjure-up kubernetes
在 LXD
上进行了集群设置。我有 运行ning 集群很好。
$ juju status
Model Controller Cloud/Region Version SLA Timestamp
conjure-canonical-kubern-3b3 conjure-up-localhost-db9 localhost/localhost 2.4.3 unsupported 23:49:09Z
App Version Status Scale Charm Store Rev OS Notes
easyrsa 3.0.1 active 1 easyrsa jujucharms 195 ubuntu
etcd 3.2.10 active 3 etcd jujucharms 338 ubuntu
flannel 0.10.0 active 2 flannel jujucharms 351 ubuntu
kubeapi-load-balancer 1.14.0 active 1 kubeapi-load-balancer jujucharms 525 ubuntu exposed
kubernetes-master 1.13.1 active 1 kubernetes-master jujucharms 542 ubuntu
kubernetes-worker 1.13.1 active 1 kubernetes-worker jujucharms 398 ubuntu exposed
Unit Workload Agent Machine Public address Ports Message
easyrsa/0* active idle 0 10.213.117.66 Certificate Authority connected.
etcd/0* active idle 1 10.213.117.171 2379/tcp Healthy with 3 known peers
etcd/1 active idle 2 10.213.117.10 2379/tcp Healthy with 3 known peers
etcd/2 active idle 3 10.213.117.238 2379/tcp Healthy with 3 known peers
kubeapi-load-balancer/0* active idle 4 10.213.117.123 443/tcp Loadbalancer ready.
kubernetes-master/0* active idle 5 10.213.117.172 6443/tcp Kubernetes master running.
flannel/1* active idle 10.213.117.172 Flannel subnet 10.1.83.1/24
kubernetes-worker/0* active idle 7 10.213.117.136 80/tcp,443/tcp Kubernetes worker running.
flannel/4 active idle 10.213.117.136 Flannel subnet 10.1.27.1/24
Entity Meter status Message
model amber user verification pending
Machine State DNS Inst id Series AZ Message
0 started 10.213.117.66 juju-b03445-0 bionic Running
1 started 10.213.117.171 juju-b03445-1 bionic Running
2 started 10.213.117.10 juju-b03445-2 bionic Running
3 started 10.213.117.238 juju-b03445-3 bionic Running
4 started 10.213.117.123 juju-b03445-4 bionic Running
5 started 10.213.117.172 juju-b03445-5 bionic Running
7 started 10.213.117.136 juju-b03445-7 bionic Running
我还部署了 Hello world 应用程序以在 pod 内的端口 8080
上输出一些 hello,并 nginx-ingress
用于将流量重新路由到指定主机上的此服务。
NAME READY STATUS RESTARTS AGE
pod/hello-world-696b6b59bd-fznwr 1/1 Running 1 176m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/example-service NodePort 10.152.183.53 <none> 8080:30450/TCP 176m
service/kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 10h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/hello-world 1/1 1 1 176m
NAME DESIRED CURRENT READY AGE
replicaset.apps/hello-world-696b6b59bd 1 1 1 176m
当我按预期执行 curl localhost
时,我得到了 connection refused
,它看起来仍然很好,因为它没有暴露在群集中。当我在端口 30450
上使用 public 地址 10.213.117.136
卷曲 kubernetes-worker/0
(我从 kubectl get all
获得)
$ curl 10.213.117.136:30450
Hello Kubernetes!
一切都像一个魅力(这是显而易见的)。当我做
curl -H "Host: testhost.com" 10.213.117.136
Hello Kubernetes!
它再次发挥魅力!这意味着入口控制器成功地根据 host
规则路由端口 80 以更正服务。在这一点上,我 100% 确定集群正常工作。
现在我正尝试通过 Internet 从外部访问此服务。当我加载 <server_ip>
时,显然没有任何加载,因为它位于自己的 lxd
子网中。因此我在考虑从服务器 eth0
转发端口 80
到这个 IP。所以我将这条规则添加到 iptables
sudo iptables -t nat -A PREROUTING -p tcp -j DNAT --to-destination 10.213.117.136
(为了举例,让我们路由所有内容,而不仅仅是端口 80)。现在,当我在计算机上打开 http://<server_ip>
时,它会加载!
所以真正的问题是如何在生产中做到这一点?我应该在 iptables 中设置此转发规则吗?这是正常的方法还是 hacky 解决方案,我缺少 "standard" 的东西?问题是添加带有 static worker
节点的规则将使集群完全静态。 IP最终会改变,我可以remove/add单位给工人,它会停止工作。我正在考虑编写脚本,它将像这样从 juju
获取此 IP 地址:
$ juju status kubernetes-worker/0 --format=json | jq '.machines["7"]."dns-name"'
"10.213.117.136"
并将其添加到 IP 表中,这是比硬编码 IP 更好的解决方案,但我仍然觉得这很棘手,必须有更好的方法。
作为最后一个想法,我在集群外 运行 HAProxy
直接在机器上,只是将流量转发给所有可用的工作人员。这最终可能也会奏效。但是我仍然不知道答案什么是 correct
解决方案以及在这种情况下通常使用什么。谢谢!
So the real question is how to do that on production?
在生产系统中执行此操作的正常方法是使用 Service.
最简单的情况是您只希望您的应用程序可以从您的节点上的外部访问。在这种情况下,您可以使用 Type NodePort 服务。这将创建将流量从主机 IP 地址转发到提供服务的 pod 所需的 iptables 规则。
如果您只有一个节点(不建议在生产中使用!),此时您已准备就绪。
如果您的 Kubernetes 集群中有多个节点,所有这些节点都将由 Kubernetes 配置以提供对服务的访问(您的客户端可以使用其中任何一个来访问该服务)。但是,您必须解决客户端如何知道可以联系哪些节点的问题...
有几种方法可以解决这个问题:
使用客户端理解的协议发布当前可用的IP地址(例如DNS),
使用由您的 Kubernetes 节点上的某些软件管理的浮动(故障转移、虚拟、HA)IP 地址(例如 pacemaker/corosync),并将客户端定向到该地址,
使用单独配置的外部负载均衡器将流量转发到一些运行节点,
使用外部负载均衡器,由 Kubernetes 使用云提供商集成脚本(通过使用 Type LoadBalancer 服务)自动配置,将流量转发到一些运行节点。
我正在尝试在裸机专用服务器上设置自己的单节点 kubernetes 集群。我在开发运营方面经验不足,但我需要为自己的项目部署一些服务。我已经使用 juju
和 conjure-up kubernetes
在 LXD
上进行了集群设置。我有 运行ning 集群很好。
$ juju status
Model Controller Cloud/Region Version SLA Timestamp
conjure-canonical-kubern-3b3 conjure-up-localhost-db9 localhost/localhost 2.4.3 unsupported 23:49:09Z
App Version Status Scale Charm Store Rev OS Notes
easyrsa 3.0.1 active 1 easyrsa jujucharms 195 ubuntu
etcd 3.2.10 active 3 etcd jujucharms 338 ubuntu
flannel 0.10.0 active 2 flannel jujucharms 351 ubuntu
kubeapi-load-balancer 1.14.0 active 1 kubeapi-load-balancer jujucharms 525 ubuntu exposed
kubernetes-master 1.13.1 active 1 kubernetes-master jujucharms 542 ubuntu
kubernetes-worker 1.13.1 active 1 kubernetes-worker jujucharms 398 ubuntu exposed
Unit Workload Agent Machine Public address Ports Message
easyrsa/0* active idle 0 10.213.117.66 Certificate Authority connected.
etcd/0* active idle 1 10.213.117.171 2379/tcp Healthy with 3 known peers
etcd/1 active idle 2 10.213.117.10 2379/tcp Healthy with 3 known peers
etcd/2 active idle 3 10.213.117.238 2379/tcp Healthy with 3 known peers
kubeapi-load-balancer/0* active idle 4 10.213.117.123 443/tcp Loadbalancer ready.
kubernetes-master/0* active idle 5 10.213.117.172 6443/tcp Kubernetes master running.
flannel/1* active idle 10.213.117.172 Flannel subnet 10.1.83.1/24
kubernetes-worker/0* active idle 7 10.213.117.136 80/tcp,443/tcp Kubernetes worker running.
flannel/4 active idle 10.213.117.136 Flannel subnet 10.1.27.1/24
Entity Meter status Message
model amber user verification pending
Machine State DNS Inst id Series AZ Message
0 started 10.213.117.66 juju-b03445-0 bionic Running
1 started 10.213.117.171 juju-b03445-1 bionic Running
2 started 10.213.117.10 juju-b03445-2 bionic Running
3 started 10.213.117.238 juju-b03445-3 bionic Running
4 started 10.213.117.123 juju-b03445-4 bionic Running
5 started 10.213.117.172 juju-b03445-5 bionic Running
7 started 10.213.117.136 juju-b03445-7 bionic Running
我还部署了 Hello world 应用程序以在 pod 内的端口 8080
上输出一些 hello,并 nginx-ingress
用于将流量重新路由到指定主机上的此服务。
NAME READY STATUS RESTARTS AGE
pod/hello-world-696b6b59bd-fznwr 1/1 Running 1 176m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/example-service NodePort 10.152.183.53 <none> 8080:30450/TCP 176m
service/kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 10h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/hello-world 1/1 1 1 176m
NAME DESIRED CURRENT READY AGE
replicaset.apps/hello-world-696b6b59bd 1 1 1 176m
当我按预期执行 curl localhost
时,我得到了 connection refused
,它看起来仍然很好,因为它没有暴露在群集中。当我在端口 30450
上使用 public 地址 10.213.117.136
卷曲 kubernetes-worker/0
(我从 kubectl get all
获得)
$ curl 10.213.117.136:30450
Hello Kubernetes!
一切都像一个魅力(这是显而易见的)。当我做
curl -H "Host: testhost.com" 10.213.117.136
Hello Kubernetes!
它再次发挥魅力!这意味着入口控制器成功地根据 host
规则路由端口 80 以更正服务。在这一点上,我 100% 确定集群正常工作。
现在我正尝试通过 Internet 从外部访问此服务。当我加载 <server_ip>
时,显然没有任何加载,因为它位于自己的 lxd
子网中。因此我在考虑从服务器 eth0
转发端口 80
到这个 IP。所以我将这条规则添加到 iptables
sudo iptables -t nat -A PREROUTING -p tcp -j DNAT --to-destination 10.213.117.136
(为了举例,让我们路由所有内容,而不仅仅是端口 80)。现在,当我在计算机上打开 http://<server_ip>
时,它会加载!
所以真正的问题是如何在生产中做到这一点?我应该在 iptables 中设置此转发规则吗?这是正常的方法还是 hacky 解决方案,我缺少 "standard" 的东西?问题是添加带有 static worker
节点的规则将使集群完全静态。 IP最终会改变,我可以remove/add单位给工人,它会停止工作。我正在考虑编写脚本,它将像这样从 juju
获取此 IP 地址:
$ juju status kubernetes-worker/0 --format=json | jq '.machines["7"]."dns-name"'
"10.213.117.136"
并将其添加到 IP 表中,这是比硬编码 IP 更好的解决方案,但我仍然觉得这很棘手,必须有更好的方法。
作为最后一个想法,我在集群外 运行 HAProxy
直接在机器上,只是将流量转发给所有可用的工作人员。这最终可能也会奏效。但是我仍然不知道答案什么是 correct
解决方案以及在这种情况下通常使用什么。谢谢!
So the real question is how to do that on production?
在生产系统中执行此操作的正常方法是使用 Service.
最简单的情况是您只希望您的应用程序可以从您的节点上的外部访问。在这种情况下,您可以使用 Type NodePort 服务。这将创建将流量从主机 IP 地址转发到提供服务的 pod 所需的 iptables 规则。
如果您只有一个节点(不建议在生产中使用!),此时您已准备就绪。
如果您的 Kubernetes 集群中有多个节点,所有这些节点都将由 Kubernetes 配置以提供对服务的访问(您的客户端可以使用其中任何一个来访问该服务)。但是,您必须解决客户端如何知道可以联系哪些节点的问题...
有几种方法可以解决这个问题:
使用客户端理解的协议发布当前可用的IP地址(例如DNS),
使用由您的 Kubernetes 节点上的某些软件管理的浮动(故障转移、虚拟、HA)IP 地址(例如 pacemaker/corosync),并将客户端定向到该地址,
使用单独配置的外部负载均衡器将流量转发到一些运行节点,
使用外部负载均衡器,由 Kubernetes 使用云提供商集成脚本(通过使用 Type LoadBalancer 服务)自动配置,将流量转发到一些运行节点。