当前位置: 首页 > 工具软件 > external-dns > 使用案例 >

ecs和eks 比较_如何使用Kubernetes,EKS和NGINX为网站设置DNS

邹祺
2023-12-01

ecs和eks 比较

As the creator of Foo, a platform for website quality monitoring, I recently endeavored in a migration to Kubernetes and EKS (an AWS service).

作为网站质量监控平台Foo的创建者,我最近努力迁移到Kubernetes和EKS(一种AWS服务)。

Kubernetes provides a robust level of DNS support. Luckily for us, within a cluster, we can reference pods by host name as defined in a spec.

Kubernetes提供了强大的DNS支持级别。 对我们来说幸运的是,在集群中,我们可以按规范中定义的主机名引用Pod。

But what if we want to expose an app to the outside world as a website under a static domain? I thought this would be a common, well documented case, but boy was I wrong.

但是,如果我们想将应用程序作为静态站点下的网站公开给外界,该怎么办? 我以为这是一个常见且有据可查的案例,但是男孩我错了。

Assume a Service named foo in the Kubernetes namespace bar. A Pod running in namespace bar can look up this service by simply doing a DNS query for foo. A Pod running in namespace quux can look up this service by doing a DNS query for foo.bar ~ DNS for Services and Pods - Kubernetes

在Kubernetes命名空间bar假设一个名为foo的服务。 在名称空间bar运行的Pod可以通过对foo进行DNS查询来查找此服务。 在命名空间quux运行的Pod可以通过对foo.bar进行DNS查询来查找此服务〜 服务和 foo.bar DNS-Kubernetes

Yes, that's great ❤️ But this still leads to many unsolved mysteries. Let's take this one step at a time shall we?! This post will address the following items.

是的,太好了❤️但这仍然导致许多未解之谜。 让我们一次迈出这一步吧? 这篇文章将解决以下问题。

  1. How to define services

    如何定义服务

  2. How to expose multiple services under one NGINX server. No fancy schmancy "Ingress" needed

    如何在一台NGINX服务器下公开多种服务 。 无需花哨的“ Ingress

  3. How to create an external DNS and connect to a domain you've acquired through any qualified registry like GoDaddy or Google Domains, for example. We'll use Route 53 and ExternalDNS to do the heavy lifting.

    例如,如何创建外部DNS并连接到通过任何合格的注册表(例如GoDaddy或Google Domains)获得的域。 我们将使用Route 53ExternalDNS进行繁重的工作。

This post assumes a setup with EKS and eksctl as documented in "Getting started with eksctl", but many of the concepts and examples in this post could be applicable in a variety of configurations.

这篇文章假定使用“ eksctl入门 ”中介绍的EKS和eksctl进行设置,但是本文中的许多概念和示例可能适用于各种配置。

步骤1:定义服务 (Step 1: Define Services)

Connecting Applications with Services explains how to expose an NGINX application by defining a Deployment and Service. Let's go ahead and create 3 applications in the same manner: a user facing web app, an API and a reverse proxy NGINX server to expose the two apps under one host.

将应用程序与服务连接说明了如何通过定义DeploymentService来公开NGINX应用程序。 让我们以相同的方式继续创建3个应用程序:一个面向用户的Web应用程序,一个API和一个反向代理NGINX服务器,以将两个应用程序公开在一个主机下。

web-deployment.yaml
web-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        # etc, etc
web-service.yaml
web-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: web
  labels:
    app: web
spec:
  ports:
  - name: "3000"
    port: 3000
    targetPort: 3000
  selector:
    app: web
api-deployment.yaml
api-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 1
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
      - name: api
        # etc, etc
api-service.yaml
api-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: api
  labels:
    app: api
spec:
  ports:
  - name: "3000"
    port: 3000
    targetPort: 3000
  selector:
    app: api

Fair enough, let's move on!

公平地说,让我们继续前进!

步骤2:在一台NGINX服务器下公开多种服务 (Step 2: Expose Multiple Services Under One NGINX Server)

NGINX is a reverse proxy in that it proxies a request by sending it to a specified origin, fetches the response, and sends it back to the client.

NGINX是反向代理,它通过将请求发送到指定的来源来代理请求,获取响应,然后将其发送回客户端。

Going back to the bit about service names being accessible to other pods in a cluster, we can setup an NGINX configuration to look something like this.

回到关于服务名称可以被集群中其他Pod访问的地方,我们可以设置NGINX配置看起来像这样。

sites-enabled/www.example.com.conf
网站启用/www.example.com.conf
upstream api {
  server api:3000;
}

upstream web {
  server web:3000;
}

server {
  listen 80;

  server_name www.example.com;

  location / {
    proxy_pass http://web;
  }

  location /api {
    proxy_pass http://api;
  }
}

Note how we can reference origin hosts like web:3000 and api:300. Niiiice!

注意我们如何引用原始主机,例如web:3000api:300 。 Niiii​​ce!

nginx-deployment.yaml
nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
nginx-service.yaml
nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  annotations:
    # this part will make more sense later
    external-dns.alpha.kubernetes.io/hostname: www.example.com
  labels:
    app: nginx
spec:
  type: LoadBalancer
  ports:
  - name: "80"
    port: 80
    targetPort: 80
  selector:
    app: nginx

...and, we're done! Right? In my experience, initially I thought so. The LoadBalancer provides an externally-accessible IP. You can confirm by running kubectl get svc and sure enough you'll find a host name listed in the EXTERNAL-IP column.

...而且,我们完成了! 对? 根据我的经验,最初我是这么认为的。 LoadBalancer提供了一个外部可访问的IP。 您可以通过运行kubectl get svc进行确认,并确保您会在EXTERNAL-IP列中找到列出的主机名。

Assuming you've acquired a domain from a provider that offers an interface to manage DNS settings, you could simply add this URL as a CNAME and you're good, right? Well, kinda... but not so much.

假设您已从提供接口的提供商处获取了一个域来管理DNS设置,则只需将此URL添加为CNAME就可以了,对吗? 好吧...不过不是很多。

Kubernetes Pods are considered to be relatively ephemeral (rather than durable) entities. Find more on this in "Pod Lifecycle - Kubernetes".

Kubernetes Pod被认为是相对短暂的(而不是持久的)实体。 在“ Pod生命周期-Kubernetes ”中找到更多相关信息。

With that said, anytime a significant change has been made in the lifecycle of a service, in our case the NGINX app, we will have a different IP address which will in turn cause significant downtime in our app which defeats a main purpose of Kubernetes - to help establish a "highly available" application.

话虽如此,每当服务的生命周期发生重大变化时(在我们的示例中为NGINX应用程序),我们将拥有一个不同的IP地址,这将导致我们的应用程序出现大量停机,从而无法达到Kubernetes的主要目的-帮助建立“高度可用”的应用程序。

Okay, don't panic - we'll get through this 

好吧,不要惊慌-我们会解决这个问题

步骤3:创建外部DNS服务以动态指向NGINX (Step 3: Create an External DNS Service to Dynamically Point NGINX)

In the previous step, with our LoadBalancer spec coupled with EKS we actually created an Elastic Load Balancer (for better or worse).

在上一步中,结合我们的LoadBalancer规范和EKS,我们实际上创建了一个Elastic Load Balancer (无论好坏)。

In this section we'll create a DNS service that points our load balancer via "ALIAS record". This ALIAS record is essentially dynamic in that a new one is created whenever our service changes. The stability is established in the name server records.

在本部分中,我们将创建一个DNS服务,该服务通过“ ALIAS记录”指向负载均衡器。 该ALIAS记录本质上是动态的,因为只要我们的服务发生更改,就会创建一个新记录。 稳定性在名称服务器记录中建立。

The tl;dr for the remaining portion is simply follow the documentation for using ExternalDNS with Route 53. Route 53 is "cloud Domain Name System (DNS) web service".

其余部分的tl; dr仅需遵循将外部DNS与Route 53结合使用文档即可。 路线53是“ 云域名系统(DNS)Web服务 ”。

Below were things I had to do that weren't obvious from the documentation. Hold on to your horses, this gets a little scrappy.

以下是我必须执行的操作,这些操作在文档中并不明显。 抓紧你的马,这会变得有点杂乱。

  • eksctl utils associate-iam-oidc-provider --cluster=your-cluster-name per eksctl service accounts documentation.

    eksctl utils associate-iam-oidc-provider --cluster=your-cluster-name每个eksctl服务帐户文档)

  • When creating the IAM policy document per the ExternalDNS documentation, I actually had to do it via CLI vs online in my account. I kept getting this error: WebIdentityErr: failed to retrieve credentials\ncaused by: AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity\n\tstatus code: 403. When I created the policy via CLI the issue went away. Below is the full command you should be able to literally copy and execute if you have the AWS CLI installed.

    根据ExternalDNS文档创建IAM策略文档时,实际上我必须通过CLI而不是通过帐户在线进行。 我一直收到此错误: WebIdentityErr: failed to retrieve credentials\ncaused by: AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity\n\tstatus code: 403 。 当我通过CLI创建策略时,问题就消失了。 如果您已安装AWS CLI,则以下是您应该能够完整复制并执行的完整命令。

aws iam create-policy \
  --policy-name AllowExternalDNSUpdates \
  --policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":["route53:ChangeResourceRecordSets"],"Resource":["arn:aws:route53:::hostedzone/*"]},{"Effect":"Allow","Action":["route53:ListHostedZones","route53:ListResourceRecordSets"],"Resource":["*"]}]}'
  • Use the policy ARN output above to create an IAM role bound to the ExternalDNS service account with a command that will look something like eksctl create iamserviceaccount --cluster=your-cluster-name --name=external-dns --namespace=default --attach-policy-arn=arn:aws:iam::123456789:policy/AllowExternalDNSUpdates.

    使用上面的策略ARN输出,使用类似于eksctl create iamserviceaccount --cluster=your-cluster-name --name=external-dns --namespace=default --attach-policy-arn=arn:aws:iam::123456789:policy/AllowExternalDNSUpdates的命令,创建绑定到ExternalDNS服务帐户的IAM角色eksctl create iamserviceaccount --cluster=your-cluster-name --name=external-dns --namespace=default --attach-policy-arn=arn:aws:iam::123456789:policy/AllowExternalDNSUpdates

  • We should now have a new role from the above that we can see in the IAM console which will have a name of something like eksctl-foo-addon-iamserviceaccount-Role1-abcdefg. Click on the role from the list and at the top of the next screen make note of the "Role ARN" as something like arn:aws:iam::123456789:role/eksctl-foo-addon-iamserviceaccount-Role1-abcdefg.

    现在,我们应该在IAM控制台中看到一个以上的新角色,其名称类似于eksctl-foo-addon-iamserviceaccount-Role1-abcdefg 。 单击列表中的角色,然后在下一个屏幕顶部记录“角色ARN”,如arn:aws:iam::123456789:role/eksctl-foo-addon-iamserviceaccount-Role1-abcdefg

  • Follow these steps to create a "hosted zone" in Route 53.

    请按照以下步骤在Route 53中创建“托管区域”。

  • You can confirm things in the Route 53 console.

    您可以在Route 53控制台中确认情况。

  • If your domain provider allows you to manage DNS settings, add the 4 name server records from the output of the command you ran to create a "hosted zone".

    如果您的域提供商允许您管理DNS设置,请从运行“创建托管区域”的命令的输出中添加4个名称服务器记录。
  • Deploy ExternalDNS by following the instructions. Afterwards, you can tail the logs with kubectl logs -f name-of-external-dns-pod. You should see a line like this at the end: time="2020-05-05T02:57:31Z" level=info msg="All records are already up to date"

    按照说明部署ExternalDNS。 之后,您可以使用kubectl logs -f name-of-external-dns-pod 。 您应该在末尾看到这样的一行: time="2020-05-05T02:57:31Z" level=info msg="All records are already up to date"

Easy, right?! Okay, maybe not... but at least you didn't have to figure all of that out alone  There could be some gaps above, but hopefully it helps guide you through your process.

容易吧? 好的,也许不是……但是至少您不必独自解决所有问题above上面可能存在一些差距,但是希望它可以指导您完成整个过程。

结论 (Conclusion)

Although this post may have some grey areas, if it helps you establish dynamic DNS resolution as part of a highly available application, you've got something really special 

尽管这篇文章可能有一些灰色区域,但是如果它可以帮助您建立动态DNS解析作为高可用性应用程序的一部分,那么您会发现一些特别的东西

Please add comments if I can help clear up anything or correct my terminology!

如果我可以帮助您清除任何内容或更正我的术语,请添加评论!

翻译自: https://www.freecodecamp.org/news/how-to-setup-dns-for-a-website-using-kubernetes-eks-and-nginx/

ecs和eks 比较

 类似资料: