在本地Minikube集群和AWS中拆分Horizon DNS [英] Split Horizon DNS in local Minikube cluster and AWS
问题描述
最初,我已经在AWS ECS
中部署了前端Web应用程序和所有后端APIS,每个后端API都有一个Route53
记录,并且前端已连接到.env
文件中的这些API.现在,我想从ECS
迁移到EKS
,并且尝试将所有这些应用程序部署在Minikube
本地群集中.我想保持前端应用程序中的.env
不变(对所有环境变量使用相同的URL),如果后端API没有,则应用程序应首先通过服务发现在本地集群中查找后端API.存在于群集中,它应该连接到外部服务,即ECS
中部署的API.简而言之,首先是本地(Minikube cluster
),然后是外部(AWS
).如何在Kubernetes
中实现?
Initially, I've deployed my frontend web application and all the backend APIS in AWS ECS
, each of the backend APIs has a Route53
record, and the frontend is connected to these APIs in the .env
file. Now, I would like to migrate from ECS
to EKS
and I am trying to deploy all these application in a Minikube
local cluster. I would like to keep my .env
in my frontend application unchanged(using the same URLs for all the environment variables), the application should first look for the backend API inside the local cluster through service discovery, if the backend API doesn't exist in the cluster, it should connect to the the external service, which is the API deployed in the ECS
. In short, first local(Minikube cluster
)then external(AWS
). How to implement this in Kubernetes
?
http://backendapi.learning.com->部署在pod中的后端API->如果未显示-> ECS中部署的后端API
http:// backendapi.learning.com --> backend API deployed in the pod --> if not presented --> backend API deployed in the ECS
.env
BACKEND_API_URL = http://backendapi.learning.com
代码中的一个示例,其中前端正在调用后端API
one of the example in the code in which the frontend is calling the backend API
export const ping = async _ => {
const res = await fetch(`${process.env.BACKEND_API_URL}/ping`);
const json = await res.json();
return json;
}
推荐答案
假设您的设置是:
- 基于微服务架构.
- 在Kubernetes集群(
frontend
和backend
)中部署的应用程序是Dockerized
- 应用程序能够在Kubernetes上运行.
- 等
- Basing on microservices architecture.
- Applications deployed in Kubernetes cluster (
frontend
andbackend
) areDockerized
- Applications are capable to be running on top of Kubernetes.
- etc.
您可以使用Services
配置Kubernetes集群(minikube
实例)以将您的请求中继到其他位置.
You can configure your Kubernetes cluster (minikube
instance) to relay your request to different locations by using Services
.
在Kubernetes中,术语服务"指是一种将运行在一组Pod上的应用程序公开为网络服务的抽象方法.
In Kubernetes terminology "Service" is an abstract way to expose an application running on a set of Pods as a network service.
某些Services
类型如下:
ClusterIP
:在群集内部IP上公开服务.选择此值将使该服务仅可从群集内访问.这是默认的ServiceType
.NodePort
:在静态端口(NodePort
)上在每个节点的IP上公开服务.将自动创建NodePort
服务所路由到的ClusterIP
服务.您可以通过请求<NodeIP>
:<NodePort>
从集群外部联系NodePort服务.LoadBalancer
:使用云提供商的负载平衡器在外部公开服务.会自动创建外部负载均衡器路由到的NodePort
和ClusterIP
服务.ExternalName
:通过返回带有值的CNAME
记录,将服务映射到externalName
字段的内容(例如foo.bar.example.com
).没有设置任何代理.
ClusterIP
: Exposes the Service on a cluster-internal IP. Choosing this value makes the Service only reachable from within the cluster. This is the defaultServiceType
.NodePort
: Exposes the Service on each Node's IP at a static port (theNodePort
). AClusterIP
Service, to which theNodePort
Service routes, is automatically created. You'll be able to contact the NodePort Service, from outside the cluster, by requesting<NodeIP>
:<NodePort>
.LoadBalancer
: Exposes the Service externally using a cloud provider's load balancer.NodePort
andClusterIP
Services, to which the external load balancer routes, are automatically created.ExternalName
: Maps the Service to the contents of theexternalName
field (e.g.foo.bar.example.com
), by returning aCNAME
record with its value. No proxying of any kind is set up.
https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
您可以使用Headless Service with selectors
和dnsConfig
(在Deployment
清单中)实现问题中引用的设置.
You can use Headless Service with selectors
and dnsConfig
(in Deployment
manifest) to achieve the setup referenced in your question.
让我解释更多:
让我们假设您有一个backend
:
-
nginx-one
-位于内部和外部
nginx-one
- located inside and outside
您的frontend
清单的最基本形式应如下所示:
Your frontend
manifest in most basic form should look following:
-
deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
selector:
matchLabels:
app: frontend
replicas: 1
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: ubuntu
image: ubuntu
command:
- sleep
- "infinity"
dnsConfig: # <--- IMPORTANT
searches:
- DOMAIN.NAME
具体看一下:
dnsConfig: # <--- IMPORTANT
searches:
- DOMAIN.NAME
剖析以上部分:
dnsConfig
-dnsConfig字段是可选的,它可以与任何dnsPolicy
设置一起使用.但是,当Pod的dnsPolicy
设置为"None
"时,必须指定dnsConfig
字段.
dnsConfig
- the dnsConfig field is optional and it can work with anydnsPolicy
settings. However, when a Pod'sdnsPolicy
is set to "None
", thednsConfig
field has to be specified.
searches
:用于在Pod中查找主机名的DNS搜索域的列表.此属性是可选的.指定后,提供的列表将合并到根据所选DNS策略生成的基本搜索域名中.重复的域名将被删除. Kubernetes最多允许6个搜索域.
searches
: a list of DNS search domains for hostname lookup in the Pod. This property is optional. When specified, the provided list will be merged into the base search domain names generated from the chosen DNS policy. Duplicate domain names are removed. Kubernetes allows for at most 6 search domains.
关于backends
的Services
.
-
service.yaml
:
apiVersion: v1
kind: Service
metadata:
name: nginx-one
spec:
clusterIP: None # <-- IMPORTANT
selector:
app: nginx-one
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
在Service
之上会告诉您的前端,您的backends
(nginx
)可以通过Headless service
获得(为什么Headless
会在以后出现!).默认情况下,您可以通过以下方式与之通信:
Above Service
will tell your frontend that one of your backends
(nginx
) is available through a Headless service
(why it's Headless
will come in hand later!). By default you could communicate with it by:
-
service-name
(nginx-one
) -
service-name.namespace.svc.cluster.local
(nginx-one.default.svc.cluster.local
)-仅在本地
service-name
(nginx-one
)service-name.namespace.svc.cluster.local
(nginx-one.default.svc.cluster.local
) - only locally
假设您正在使用curl
(为简单起见)将请求从frontend
发送到backend
,则对于DNS
分辨率,您将具有特定的顺序:
Assuming that you are sending the request using curl
(for simplicity) from frontend
to backend
you will have a specific order when it comes to the DNS
resolution:
- 检查集群内的
DNS
记录 - 检查在
dnsConfig
中指定的
DNS
记录
- check the
DNS
record inside the cluster - check the
DNS
record specified indnsConfig
连接到backend
的详细信息如下:
The specifics of connecting to your backend
will be following:
- 如果群集中有带有
backend
的Pod
,则DNS
分辨率将指向Pod的IP(不是ClusterIP
) - 如果由于各种原因集群中的
Pod
backend
不可用,DNS
分辨率将首先检查内部记录,然后选择在dnsConfig
中使用DOMAIN.NAME
(在minikube
). - 如果没有与特定
backend
(nginx-one
)关联的Service
,则DNS
分辨率将使用dnsConfig
中的DOMAIN.NAME
来在群集外部进行搜索.
- If the
Pod
with yourbackend
is available in the cluster, theDNS
resolution will point to the Pod's IP (notClusterIP
) - If the
Pod
backend
is not available in the cluster due to various reasons, theDNS
resolution will first check the internal records and then opt to useDOMAIN.NAME
in thednsConfig
(outside ofminikube
). - If there is no
Service
associated with specificbackend
(nginx-one
), theDNS
resolution will use theDOMAIN.NAME
in thednsConfig
searching for it outside of the cluster.
旁注!
Headless Service with selector
之所以在这里起作用,是因为它的目的是直接指向Pod
的IP,而不是ClusterIP
(只要Service
存在,它就一直存在).如果您使用的是正常" Service
,即使没有与选择器匹配的Pods
,您也将始终尝试与ClusterIP
进行通信.通过使用headless
,如果没有Pod
,则DNS
分辨率将在线下更远(外部来源).
The Headless Service with selector
comes into play here as its intention is to point directly to the Pod
's IP and not the ClusterIP
(which exists as long as Service
exists). If you used a "normal" Service
you would always try to communicate with the ClusterIP
even if there is no Pods
available matching the selector. By using a headless
one, if there is no Pod
, the DNS
resolution would look further down the line (external sources).
其他资源:
Additional resources:
您还可以查看其他选项:
You could also take a look on alternative options:
替代选项1:
- 使用CoreDNS中的重写规则插件将
backendapi.learning.com
的DNS查询重写为backendapi.default.svc.cluster.local
- Use rewrite rule plugin in CoreDNS to rewrite DNS queries for
backendapi.learning.com
tobackendapi.default.svc.cluster.local
替代选项2:
- Add hostAliases to the Frontend Pod
您还可以使用 Configmaps 重用.env
文件.
You can also use Configmaps to re-use .env
files.
这篇关于在本地Minikube集群和AWS中拆分Horizon DNS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!