使用NGINX Plus负载均衡Kubernetes服务
来自: http://dockone.io/article/957
【编者的话】此篇文章是Nginx的Michael Pleshakov发表在Nginx官方博客的一篇博文,通过这篇文章概括回顾了Kubernetes暴露服务相关的解决方案,并对最新的Ingreess API进行了说明,最后给出了Kubernetes通过集成NGINX Plus来暴露服务到互联网的解决方案。这个方案解决了目前Kubernetes暴露服务的短板,整个实现过程也比较简单,步骤清晰,具有很强的参考性。我们华三目前也在调研这方面的工作,希望此文能对大家有所帮助。
Kubernetes是由谷歌开发的一个开源系统,用于在集群内运行和管理以容器微服务为基础的应用。使用Kubernetes的人经常需要确保可以从Kubernetes集群外部访问在Kubernetes内创建的服务。
虽然Kubernetes提供了内置暴露服务解决方案,正像在下面Kubernetes内置暴露服务解决方案中所描述的,这些解决方案会局限你在4层负载均衡或循环HTTP负载平衡。
这篇文章会告诉你如何使用NGINX Plus作为高级7层负载均衡解决方案,用于暴露Kubernetes服务到互联网上,无论你是在云服务还是在自有基础设施上运行Kubernetes。
我们假定你对Kubernetes有所了解(pods, services, replication controllers, and labels)并且有一个运行的Kubernetes集群。要了解更多Kubernetes,请访问官方Kubernetes用户指南。
Kubernetes内置暴露服务解决方案
Kubernetes为暴露服务提供了多种选择。其中两种是NodePort和负载平衡器,分别对应不同类型的服务。Ingress API在Kubernetes1.1版本开始作为beta测试版供使用,已经成为第三种选择。NodePort
指定服务类型为NodePort,会使得服务在每个Kubernetes节点上在相同的端口可用。为了暴露服务到互联网,你在这个端口上暴露一个或多个节点。为了高可用性,你可以暴露多个节点并使用基于DNS的负载均衡在它们中分布流量,或者你把这些节点放在你选择的负载均衡后。当传入流量访问端口的一个节点时,它会被在服务的pods之间负载平衡。负载平衡由每个节点上的Kubernetes代理完成,并且仅限于TCP/UDP负载均衡。
LoadBalancer
指定服务类型为负载平衡会分配用于在服务pods之间分布传入流量的云负载平衡器。只有特定的云服务供应商和Google Container Engineand支持负载均衡器解决方案,如果你在你自己的基础设施上运行Kubernetes,它是不可用的。此外,Kubernetes只允许你配置循环TCP负载均衡,即使云负载均衡器有高级功能,例如会话持久或请求映射。
Ingress API
创建Ingress资源使得你可以通过自定义URL(例如,服务A在URL /foo和服务B在URL /bar)和多个虚拟主机名(例如,一组服务是foo.example.com而另一组服务是bar.example.com)暴露服务到互联网。Ingress控制器依赖Ingress资源并建立一个外部负载平衡器。Ingress控制器不是Kubernetes标准部署的一部分:你需要选择最适合你的控制器或自己实现一个,并把它添加到你的Kubernetes集群。预计很快会出现各种各样的控制器,但目前唯一可用的还是Google Compute Engine HTTP负载平衡控制器,而且是只有当你在Google Compute Engine或者Google Container Engine中运行Kubernetes时。Ingress API仅支持循环HTTP负载均衡,即使实际负载均衡器支持高级功能。
在撰写本文时,无论是Ingress API还是Google Compute Engine HTTP Load Balancer控制器都还在测试阶段。
尽管上面提到的解决方案配置简单并且马上就可以使用,他们没有提供任何高级功能,特别是7层负载均衡相关的功能。
使用NGINX Plus暴露Kubernetes服务
为了集成NGINX Plus到Kubernetes上,我们需要确保NGINX Plus配置与Kubernetes保持同步,可以反映像pods添加或删除这样的Kubernetes服务变更。 使用开源的NGINX软件,你需要手动修改NGINX配置文件并重新加载配置。使用NGINX Plus,有两种方法动态更新配置:
With APIs – 此方法使用NGINX Plus的on-the-fly reconfiguration API 添加和删除Kubernetes pods在NGINX Plus配置中的条目,并使用Kubernetes API来获取pods的IP地址。这种方法需要我们写一些代码,这里我们也不进行深入讨论。有关详细信息,可以看Kelsey Hightower的网络研讨会,Bringing Kubernetes to the Edge with NGINX Plus,他在其中探讨了API并新建了利用他们的应用。
通过重新解析DNS名称 -这个方法像在以下章节描述的一样仅仅需要对NGINX Plus的一次恰当配置。
Utilizing DNS-Based Reconfiguration
我们假设你已经有一个正在运行的Kubernetes集群并有一个可以使用kubectl工具的主机用于管理集群;有关说明,请参阅有关你群集类型的Kubernetes入门指南。你还需要编译一个NGINX Plus容器镜像,创建的命令就在这篇博客文章。下面是我们怎么做的一个概括:
- 配置一个NGINX Plus pod用于暴露和负载均衡我们在步骤2中创建的服务。
- 创建一个提供静态网页的简单服务,。
- 扩展或者缩减服务,查看NGINX Plus如何自动重新配置。
> 注:我们使用运行在Google Compute Engine的Kubernetes 1.0.6版本测试了这个博客所描述的解决方案,而我们下面使用的是一个本地配置的Vagrant。
在命令的斜体字中,你Kubernetes设置中的值可能不同。
配置 NGINX Plus Pod
我们把NGINX Plus放在要暴露到互联网节点的Kubernetes pod内。我们的pod通过复制控制器创建,我们同样进行配置。我们Kubernetes相关的NGINX Plus配置文件放在NGINX Plus pod和节点的共享目录内,这样更加方便维护。选择运行NGINX Plus Pod的节点
为了指定NGINX Plus pod运行的节点,我们添加一个标签到该节点。运行下面命令,查询运行的所有节点列表:$ kubectl get nodes
NAME LABELS STATUS
10.245.1.3 Kubernetes.io/hostname=10.245.1.3 Ready
10.245.1.4 Kubernetes.io/hostname=10.245.1.4 Ready
10.245.1.5 Kubernetes.io/hostname=10.245.1.5 Ready
我们选择第一个节点,并通过下面命令添加一个标签给它:
$ kubectl label node 10.245.1.3 role=nginxplus
为NGINX Plus Pod配置Replication Controller
我们不会直接创建NGINX Plus pod而是通过复制控制器。我们在Kubernetes的nginxplus-rc.yaml文件配置NGINX Plus pod 复制控制器。- 我们设置replicas的数量是1,就是说Kubernetes会确保始终有1个NGINX Plus pod在运行:如果pod出现故障,它会被新的pod替换。
- 在nodeSelector处我们指定NGINX Plus pod在标记角色: nginxplus的节点上创建。
- 我们的NGINX Plus容器暴露两个端口,80和8080,并且我们配置他们与节点端口80和8080之间的映射。
- 我们的NGINX Plus容器共享节点的/etc/nginx/conf.d文件夹。作为下面配置NGINX Plus的进一步解释,共享文件夹让我们可以不用重建容器镜像而重新配置NGINX Plus。
apiVersion: v1 kind: ReplicationController metadata: name: nginxplus-rc spec: replicas: 1 selector: app: nginxplus template: metadata: labels: app: nginxplus spec: nodeSelector: role: nginxplus containers: - name: nginxplus image: nginxplus ports: - name: http containerPort: 80 hostPort: 80 - name: http-alt containerPort: 8080 hostPort: 8080 volumeMounts: - mountPath: "/etc/nginx/conf.d" name: etc-nginx-confd volumes: - hostPath: path: "/etc/nginx/conf.d" name: etc-nginx-confd
使NGINX Plus Docker Image可用
正如我们上面所说,我们已经建立了一个NGINX Plus Docker镜像。 现在我们让它可用。为简单起见,我们不使用私有Docker repository,我们只是手动加载镜像。在我们编译Docker镜像的主机上,运行以下命令将镜像保存成文件:
$ docker save -o nginxplus.tar nginxplus
我们把nginxplus.tar传送到节点,运行以下命令从文件加载镜像:
$ docker load -i nginxplus.tar
配置NGINX Plus
在NGINX Plus容器的/etc/nginx文件夹中,我们保留随NGINX Plus包默认的主nginx.conf中的配置文件。 在默认文夹include指令读取来自/etc/nginx/conf.d文件夹中的其他配置文件。正向在NGINX Plus复制控制器文件(nginxplus-rc.yaml)中表明的一样,我们与NGINX Plus节点上的容器共享/etc/nginx/conf.d文件夹。 共享意味着我们可以修改存储在文件夹(节点上)中的配置文件,而无需重建NGINX Plus容器镜像,而如果我们直接在容器中创建的文件夹这是我们必须做的。我们把我们的Kubernetes特定配置文件(backend.conf)放在共享目录。首先,让我们创建/etc/nginx/conf.d文件夹。
$ mkdir /etc/nginx/conf.d
然后,我们创建backend.conf文件,其中包括以下指令:
- resolver -定义Kubernetes DNS解析的IP地址,使用默认的IP地址,10.0.0.10。valid参数告诉NGINX Plus每五秒钟解析所有DNS名称。 您的Kubernetes DNS服务IP地址可能会有所不同。运行此命令查看:
$ kubectl get svc kube-dns --namespace=kube-system
- upstream -创建一个名为后端的Kubernetes服务,我们揭露上游组。我们确定了服务器在上游组主机名,包括了resolve指令告诉NGINX重新解析主机名在运行时。
- server (两次) -定义两个虚拟服务器:
- 第一个服务器监听端口80并且负载均衡在我们服务pods中的/nginx-service传入请求。我们还配置积极的健康检查 。
- 第二个服务器监听端口8080。这里的我们成立了现场活动的监控NGINX Plus。稍后我们将用它来检查 NGINX Plus 是否被正确地重新配置。
resolver 10.0.0.10 valid=5s; upstream backend { zone upstream-backend 64k; server nginx-service.default.svc.cluster.local resolve; } server { listen 80; status_zone backend-servers; location /nginx-service/ { proxy_pass http://backend/; health_check; } } server { listen 8080; root /usr/share/nginx/html; location = /status.html { } location /status { status; } }
创建Replication Controller
现在,我们已经准备好在我们的节点上运行此命令创建复制器:$ kubectl create -f nginxplus-rc.yaml
为了验证创建NGINX Plus pod,运行:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginxplus-rc-0ts5t 1/1 Running 0 17s
我们在本地Vagrant 设定运行Kubernetes,所以我们知道,我们的节点的外部IP地址为10.245.1.3,在这个例子中的剩下部分我们将使用该地址。如果你在一个云服务提供商运行Kubernetes,您可以通过运行下面命令得到您节点的外部IP地址:
$ kubectl get nodes node-name -o json | grep -i externalIP -A 1 "type": "ExternalIP", "address": XXX.XXX.XXX.XXX
如果您在云服务中运行,别忘了设置防火墙规则允许NGINX Plus节点接收传入的流量。请参阅您的云服务提供商文档。
通过查看NGINX Plus实时活动监控仪表板可以检查我们的NGINXPlus pod是否 起来并运行了,它节点的外部IP地址在端口8080上是否可用(在我们的例子中是http://10.245.1.3:8080/status.html)。 如果我们这时候访问,不过我们是看不到我们服务的任何服务器,因为我们还没有创建它。
创建一个简单Kubernetes Service
现在是时候创建Kubernetes服务了。我们的服务包括两个(开源)NGINX 服务器提供静态web页面。为服务创建Replication Controller
首先,我们创建一个Replication Controller,这样Kubernetes会确保指定数量的NGINX Web服务器副本(pods)始终在群集中运行。以下是声明文件(nginx-rc.yaml):apiVersion: v1
kind: ReplicationController
metadata:
name: nginx-rc
spec:
replicas: 2
selector:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
我们的控制器由两个NGINX Web服务器组成。我们声明一个控制器包含单个NGINX容器pods用于暴露端口80。Nginx的镜像将从Docker Hub下载。
要创建复制控制器,我们运行以下命令:
$ kubectl create -f nginx-rc.yaml
要检查是否已创建pods,我们可以运行下面的命令。我们使用标签选择app=nginx获得仅在上一步的replication controller中创建的pods:
$ kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
nginx-rc-544f1 1/1 Running 0 2m
nginx-rc-uk6pm 1/1 Running 0 2m
创建Service
接下来,我们为replication controller创建的pods创建服务。我们使用下列文件(nginx-service.yaml)创建服务:apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
ClusterIP: None
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
app: nginx
这里我们通过设置ClusterIP字段为None来声明一个特殊的headless service。通过这类服务,不会分配集群的IP地址并且通过kube代理也无法使用服务。DNS查询Kubernetes DNS会返回多个A记录(我们pods的IP地址)。
通过设置selector field为app: nginx,我们声明该pods属于服务,即使用NGINX replication controller 创建的pods(在nginx-rc.yaml中定义)。
我们运行下面的命令创建服务:
$ kubectl create -f nginx-service.yaml
现在,如果我们刷新仪表盘页面,并单击右上角的Upstreams tab,我们可以看到新加的两台服务器。
我们还可以检查NGINX Plus是否已经在pods的服务间负载均衡流量。如果是,当我们在浏览器中访问http://10.245.1.3/nginx-service/时,我们可以看到默认NGINX的欢迎页面。
如果我们刷新此页面几次,并查看仪表盘状态,我们可以看到请求是如何分布在两个上游服务器上的。
扩展Kubernetes服务
现在,让我们再添加两个pods到我们的服务并确保NGINX Plus配置会再次自动更新。我们运行此命令扩展replication controller 把pods数量更改为4:$ kubectl scale rc nginx-rc --replicas=4
scaled
要检查NGINX Plus是否重新配置,我们可以再查看仪表盘,但这次我们使用NGINX Plus状态的API来替代。在我们的节点运行下面的命令,10.245.1.3是我们的NGINX Plus节点外部IP地址。为了格式化JSON输出,我们管道输出到jq。
$ curl -s 10.245.1.3:8080/status/upstreams/backend | jq . { "peers": [ { "id": 1, "server": "10.0.0.1:80", "backup": false, "weight": 1, "state": "unhealthy", "active": 0, "requests": 1, "responses": { "1xx": 0, "2xx": 0, "3xx": 0, "4xx": 0, "5xx": 0, "total": 0 }, "sent": 0, "received": 0, "fails": 0, "unavail": 0, "health_checks": { "checks": 1, "fails": 1, "unhealthy": 1, "last_passed": false }, "downtime": 33965, "downstart": 1445378182275, "selected": 1445378131000 }, { "id": 2, "server": "10.246.1.6:80", ... }, { "id": 3, "server": "10.246.3.2:80", ... { "id": 4, "server": "10.0.0.2:80", ... } ], "keepalive": 0 }
在peers中的JSON输出数组正好有四个元素,对应每个NGINX Web服务器。
现在,让我们减少pods的数量从4到1,再次检查NGINX Plus状态:
$ kubectl scale rc nginx-rc --replicas=1
scaled
$ curl -s 10.245.1.3:8080/status/upstreams/backend | jq .
现在peers中的JSON输出数组只包含一个元素。
现在,我们已经把NGINX Plus运行起来,我们就可以开始利用其高级功能,如会话持久性,SSL终止,请求路由,高级监控和更多。
总结
NGINX Plus的on-the-fly reconfiguration让你的Kubernetes集成更轻松:不管是通过API编程还是完全使用DNS的方式。使用NGINX Plus暴露Kubernetes服务到互联网提供了许多当前Kubernetes内置负载均衡解决方案缺乏的功能。原文链接:Load Balancing Kubernetes Services with NGINX Plus (翻译:朱高校)
本文由用户 123tt 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
转载本站原创文章,请注明出处,并保留原始链接、图片水印。
本站是一个以用户分享为主的开源技术平台,欢迎各类分享!