如何使用HAProxy Ingress,unicorn / puma和Web套接字部署Ruby on Rails应用程序

经过几个月的测试,我们终于将Ruby on Rails应用程序移植到带有Kubernetes集群的生产环境中。


在本文中,我将向您展示如何使用HAProxy Ingress控制器为Kubernetes中的Ruby on Rails应用程序配置基于路径的路由。


图片


假设您对Kubernetes中有哪些Pod部署服务配置映射Ingress有所 了解


通常在Rails应用程序中提供诸如独角兽/美洲狮,sidekiq /延迟工作/ resque,Web套接字和一些特殊API服务之类的服务。 我们通过平衡器打开了一个Web服务,并且一切正常。 但是流量增加了,因此有必要通过URL或Path进行路由。


Kubernetes没有用于平衡此类负载的交钥匙解决方案。 已经为它开发了一个白平衡控制器 ,但它仍未处于Alpha阶段并用于生产。


对于基于路径的路由,最好使用Ingress控制器


我们研究了该问题,发现k8s对于Ingress具有不同的解决方案。



我们对nginx-ingress和HAProxy进行了试验,并选择了HAProxy-它更适合我们在项目中使用的Rails Web套接字。


我将逐步向您展示如何将HAProxy Ingress附加到Rails应用程序。


使用HAProxy Ingress控制器设置Rails应用程序


这是我们将要做的:


  • 让我们创建具有不同服务和部署的Rails应用程序。
  • 为SSL创建TLS机密。
  • 创建一个HAProxy Ingress配置图。
  • 创建一个HAProxy Ingress控制器。
  • 让我们通过LoadBalancer之类的服务打开对Ingress的访问。
  • 让我们为Ingress服务配置DNS应用程序。
  • 为基于路径的路由创建不同的入口规则。
  • 测试基于路径的路由。

让我们创建一个清单,用于为各种服务(Web(独角兽),后台任务(sidekiq),Web套接字(红宝石瘦身),API(独角兽专用))部署Rails应用程序。


这是我们的部署Web应用程序和服务模板。


--- apiVersion: v1 kind: Deployment metadata: name: test-production-web labels: app: test-production-web namespace: test spec: template: metadata: labels: app: test-production-web spec: containers: - image: <your-repo>/<your-image-name>:latest name: test-production imagePullPolicy: Always env: - name: POSTGRES_HOST value: test-production-postgres - name: REDIS_HOST value: test-production-redis - name: APP_ENV value: production - name: APP_TYPE value: web - name: CLIENT value: test ports: - containerPort: 80 imagePullSecrets: - name: registrykey --- apiVersion: v1 kind: Service metadata: name: test-production-web labels: app: test-production-web namespace: test spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: test-production-web 

这是后台应用程序部署和服务模板。


 --- apiVersion: v1 kind: Deployment metadata: name: test-production-background labels: app: test-production-background namespace: test spec: template: metadata: labels: app: test-production-background spec: containers: - image: <your-repo>/<your-image-name>:latest name: test-production imagePullPolicy: Always env: - name: POSTGRES_HOST value: test-production-postgres - name: REDIS_HOST value: test-production-redis - name: APP_ENV value: production - name: APP_TYPE value: background - name: CLIENT value: test ports: - containerPort: 80 imagePullSecrets: - name: registrykey --- apiVersion: v1 kind: Service metadata: name: test-production-background labels: app: test-production-background namespace: test spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: test-production-background 

这是部署Web应用程序套接字和服务模板。


 --- apiVersion: v1 kind: Deployment metadata: name: test-production-websocket labels: app: test-production-websocket namespace: test spec: template: metadata: labels: app: test-production-websocket spec: containers: - image: <your-repo>/<your-image-name>:latest name: test-production imagePullPolicy: Always env: - name: POSTGRES_HOST value: test-production-postgres - name: REDIS_HOST value: test-production-redis - name: APP_ENV value: production - name: APP_TYPE value: websocket - name: CLIENT value: test ports: - containerPort: 80 imagePullSecrets: - name: registrykey --- apiVersion: v1 kind: Service metadata: name: test-production-websocket labels: app: test-production-websocket namespace: test spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: test-production-websocket 

这是应用程序API部署和服务信息。


 --- `apiVersion: v1 kind: Deployment metadata: name: test-production-api labels: app: test-production-api namespace: test spec: template: metadata: labels: app: test-production-api spec: containers: - image: <your-repo>/<your-image-name>:latest name: test-production imagePullPolicy: Always env: - name: POSTGRES_HOST value: test-production-postgres - name: REDIS_HOST value: test-production-redis - name: APP_ENV value: production - name: APP_TYPE value: api - name: CLIENT value: test ports: - containerPort: 80 imagePullSecrets: - name: registrykey --- apiVersion: v1 kind: Service metadata: name: test-production-api labels: app: test-production-api namespace: test spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: test-production-api 

让我们使用kubectl apply运行清单。


 $ kubectl apply -f test-web.yml -f test-background.yml -f test-websocket.yml -f test-api.yml deployment "test-production-web" created service "test-production-web" created deployment "test-production-background" created service "test-production-background" created deployment "test-production-websocket" created service "test-production-websocket" created deployment "test-production-api" created service "test-production-api" created 

部署并启动应用程序后,您将需要创建HAProxy Ingress。 但是首先,让我们使用SSL密钥和证书创建TLS机密。


他将允许HTTPS作为应用程序URL,并在L7上终止它。


$ kubectl create secret tls tls-certificate --key server.key --cert server.pem


server.key是我们的SSL密钥, server.pem是我们的pem格式的SSL证书。


现在创建HAProxy控制器的资源。


HAProxy配置图


在此处查看HAProxy的所有可用配置选项。


 apiVersion: v1 data: dynamic-scaling: "true" backend-server-slots-increment: "4" kind: ConfigMap metadata: name: haproxy-configmap namespace: test 

HAProxy入口控制器部署


具有至少两个副本的Ingress控制器的部署模式,用于管理顺序部署。


 apiVersion: extensions/v1beta1 kind: Deployment metadata: labels: run: haproxy-ingress name: haproxy-ingress namespace: test spec: replicas: 2 selector: matchLabels: run: haproxy-ingress template: metadata: labels: run: haproxy-ingress spec: containers: - name: haproxy-ingress image: quay.io/jcmoraisjr/haproxy-ingress:v0.5-beta.1 args: - --default-backend-service=$(POD_NAMESPACE)/test-production-web - --default-ssl-certificate=$(POD_NAMESPACE)/tls-certificate - --configmap=$(POD_NAMESPACE)/haproxy-configmap - --ingress-class=haproxy ports: - name: http containerPort: 80 - name: https containerPort: 443 - name: stat containerPort: 1936 env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace 

在此清单中,我们对传递给控制器​​的参数特别感兴趣。
--default-backend-service是在没有规则与请求匹配的情况下应用程序将使用的服务。


我们有这个test-production-web ,但是它可以是自定义404页面或类似的东西-您可以决定。


--default-ssl-certificate是我们刚刚创建的SSL秘密。 它将终止L7上的SSL,并且可以通过HTTPS从外部访问该应用程序。


HAProxy入口服务


这是一种LoadBalancer服务,它允许客户端流量访问我们的Ingress控制器。


LoadBalancer可以访问公共网络和Kubernetes内部网络,并在L7上将流量路由到Ingress控制器。


 apiVersion: v1 kind: Service metadata: labels: run: haproxy-ingress name: haproxy-ingress namespace: test spec: type: LoadBalancer ports: - name: http port: 80 protocol: TCP targetPort: 80 - name: https port: 443 protocol: TCP targetPort: 443 - name: stat port: 1936 protocol: TCP targetPort: 1936 selector: run: haproxy-ingress 

让我们应用所有HAProxy清单。


 $ kubectl apply -f haproxy-configmap.yml -f haproxy-deployment.yml -f haproxy-service.yml configmap "haproxy-configmap" created deployment "haproxy-ingress" created service "haproxy-ingress" created 

当所有资源都在运行时,请指定LoadBalancer的端点。


 $ kubectl -n test get svc haproxy-ingress -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR haproxy-ingress LoadBalancer 100.67.194.186 a694abcdefghi11e8bc3b0af2eb5c5d8-806901662.us-east-1.elb.amazonaws.com 80:31788/TCP,443:32274/TCP,1936:32157/TCP 2m run=ingress 

将DNS映射到应用程序URL


在为Ingress服务指定ELB端点后,我们将需要映射服务的DNS和请求URL(例如test-rails-app.com )。


入口实施


最困难的部分在后面,是时候配置基于入口和基于路径的规则了。


我们需要以下规则。


https://test-rails-app.com的请求将由test-production-web


https://test-rails-app.com/websocket的请求将由test-production-websocket


https://test-rails-app.com/api的请求将由test-production-api


让我们用所有这些规则创建一个Ingress清单。


 --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress namespace: test spec: tls: - hosts: - test-rails-app.com secretName: tls-certificate rules: - host: test-rails-app.com http: paths: - path: / backend: serviceName: test-production-web servicePort: 80 - path: /api backend: serviceName: test-production-api servicePort: 80 - path: /websocket backend: serviceName: test-production-websocket servicePort: 80 

如果配置发生更改,我们将为Ingress资源提供注释


如预期的那样,默认情况下,我们/的流量/路由到test-production-web/api /路由到test-production-api ,并且/websocket路由到test-production-websocket


我们在Kubernetes的L7上需要基于路径的路由和SSL终止,而Ingress的实现解决了这个问题。

Source: https://habr.com/ru/post/zh-CN424789/


All Articles