如何使用Helm在DigitalOceanKubernetes上设置Nginx入口

来自菜鸟教程
跳转至:导航、​搜索

作为 Write for DOnations 计划的一部分,作者选择了 Free and Open Source Fund 来接受捐赠。

介绍

Kubernetes Ingresses 为您提供了一种灵活的方式将流量从集群外路由到内部 Kubernetes 服务。 Ingress Resources 是 Kubernetes 中的对象,用于定义将 HTTP 和 HTTPS 流量路由到服务的规则。 要使这些工作,必须存在 Ingress Controller; 它的作用是通过接受流量(很可能通过负载均衡器)并将其路由到适当的服务来实施规则。 大多数 Ingress Controller 只为所有 Ingress 使用一个全局负载均衡器,这比为每个您希望公开的服务创建一个负载均衡器更有效。

Helm 是一个用于管理 Kubernetes 的包管理器。 将 Helm Charts 与 Kubernetes 结合使用可提供可配置性和生命周期管理,以更新、回滚和删除 Kubernetes 应用程序。

在本指南中,您将使用 Helm 设置 Kubernetes 维护的 Nginx 入口控制器 。 然后,您将创建一个入口资源以将来自您的域的流量路由到示例 Hello World 后端服务。 设置 Ingress 后,您需要将 Cert Manager 安装到您的集群,以便能够自动配置 Let's Encrypt TLS 证书以保护您的 Ingress。

先决条件

  • 一个 DigitalOcean Kubernetes 1.16+ 集群,您的连接配置配置为 kubectl 默认值。 如何配置 kubectl 的说明显示在创建集群时显示的 连接到集群 步骤下。 要了解如何在 DigitalOcean 上创建 Kubernetes 集群,请参阅 Kubernetes 快速入门
  • 安装在本地机器上的 Helm 3 包管理器。 完成 如何使用 Helm 3 包管理器 教程在 Kubernetes 集群上安装软件的 步骤 1
  • 一个完全注册的域名,有两条可用的 A 记录。 本教程将自始至终使用 hw1.your_domainhw2.your_domain。 您可以在 Namecheap 上购买一个域名,在 Freenom 上免费获得一个域名,或者使用您选择的域名注册商。

第 1 步 — 设置 Hello World 部署

在本节中,在部署 Nginx Ingress 之前,您将部署一个名为 hello-kubernetes 的 Hello World 应用程序,以提供一些您将流量路由到的服务。 为了确认 Nginx Ingress 在接下来的步骤中正常工作,您将部署它两次,每次都带有不同的欢迎消息,当您从浏览器访问它时将显示该消息。

您将在本地计算机上存储部署配置。 第一个部署配置将位于名为 hello-kubernetes-first.yaml 的文件中。 使用文本编辑器创建它:

nano hello-kubernetes-first.yaml

添加以下行:

你好-kubernetes-first.yaml

apiVersion: v1
kind: Service
metadata:
  name: hello-kubernetes-first
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: hello-kubernetes-first
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-kubernetes-first
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-kubernetes-first
  template:
    metadata:
      labels:
        app: hello-kubernetes-first
    spec:
      containers:
      - name: hello-kubernetes
        image: paulbouwer/hello-kubernetes:1.8
        ports:
        - containerPort: 8080
        env:
        - name: MESSAGE
          value: Hello from the first deployment!

此配置定义了一个部署和一个服务。 Deployment 由 paulbouwer/hello-kubernetes:1.7 映像的三个副本和一个名为 MESSAGE 的环境变量组成——当您访问应用程序时,您将看到它的值。 此处的服务定义为在端口 80 处公开集群内部署。

保存并关闭文件。

然后,通过运行以下命令在 Kubernetes 中创建 hello-kubernetes 应用程序的第一个变体:

kubectl create -f hello-kubernetes-first.yaml

您将收到以下输出:

Outputservice/hello-kubernetes-first created
deployment.apps/hello-kubernetes-first created

要验证服务的创建,请运行以下命令:

kubectl get service hello-kubernetes-first

输出将如下:

OutputNAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
hello-kubernetes-first   ClusterIP   10.245.124.46   <none>        80/TCP    7s

您会发现新创建的 Service 已分配了 ClusterIP,这意味着它工作正常。 发送到它的所有流量都将转发到端口 8080 上的选定部署。 现在您已经部署了 hello-kubernetes 应用程序的第一个变体,您将处理第二个变体。

打开一个名为 hello-kubernetes-second.yaml 的文件进行编辑:

nano hello-kubernetes-second.yaml

添加以下行:

你好-kubernetes-second.yaml

apiVersion: v1
kind: Service
metadata:
  name: hello-kubernetes-second
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: hello-kubernetes-second
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-kubernetes-second
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-kubernetes-second
  template:
    metadata:
      labels:
        app: hello-kubernetes-second
    spec:
      containers:
      - name: hello-kubernetes
        image: paulbouwer/hello-kubernetes:1.8
        ports:
        - containerPort: 8080
        env:
        - name: MESSAGE
          value: Hello from the second deployment!

保存并关闭文件。

此变体与之前的配置具有相同的结构; 唯一的区别在于部署和服务名称,以避免冲突,以及消息。

现在使用以下命令在 Kubernetes 中创建它:

kubectl create -f hello-kubernetes-second.yaml

输出将是:

Outputservice/hello-kubernetes-second created
deployment.apps/hello-kubernetes-second created

通过列出所有服务来验证第二个服务是否已启动并正在运行:

kubectl get service

输出将与此类似:

OutputNAME                      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
hello-kubernetes-first    ClusterIP   10.245.124.46    <none>        80/TCP    49s
hello-kubernetes-second   ClusterIP   10.245.254.124   <none>        80/TCP    10s
kubernetes                ClusterIP   10.245.0.1       <none>        443/TCP   65m

hello-kubernetes-firsthello-kubernetes-second都列出来了,说明Kubernetes已经创建成功了。

您已经创建了 hello-kubernetes 应用程序的两个部署以及随附的服务。 每一个在部署规范中都有不同的消息集,允许您在测试期间区分它们。 在下一步中,您将安装 Nginx 入口控制器本身。

第 2 步 — 安装 Kubernetes Nginx 入口控制器

现在,您将使用 Helm 安装 Kubernetes 维护的 Nginx 入口控制器 。 请注意,有几个 Nginx Ingresses

Nginx Ingress Controller 由 Pod 和 Service 组成。 Pod 运行控制器,控制器不断轮询集群 API 服务器上的 /ingresses 端点,以获取可用入口资源的更新。 Service 是 LoadBalancer 类型,因为您将其部署到 DigitalOcean Kubernetes 集群,集群将自动创建一个 DigitalOcean Load Balancer,所有外部流量都将通过该负载均衡器流向 Controller。 然后,控制器会将流量路由到适当的服务,如 Ingress Resources 中所定义。

只有 LoadBalancer Service 知道自动创建的负载均衡器的 IP 地址。 一些应用程序(例如ExternalDNS)需要知道它的IP地址,但只能读取一个Ingress的配置。 通过在 helm install 期间将 controller.publishService.enabled 参数设置为 true,可以将控制器配置为在每个 Ingress 上发布 IP 地址。 建议启用此设置以支持可能依赖负载均衡器 IP 地址的应用程序。

要将 Nginx Ingress Controller 安装到您的集群,您首先需要通过运行以下命令将其存储库添加到 Helm:

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

输出将是:

Output"ingress-nginx" has been added to your repositories

更新让 Helm 知道它包含什么:

helm repo update

最后,运行以下命令安装 Nginx 入口:

helm install nginx-ingress ingress-nginx/ingress-nginx --set controller.publishService.enabled=true

此命令从 stable 图表存储库安装 Nginx 入口控制器,将 Helm 版本命名为 nginx-ingress,并将 publishService 参数设置为 true

输出将如下:

OutputNAME: nginx-ingress
LAST DEPLOYED: Fri Apr  3 17:39:05 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
...

Helm 已经记录了它在 Kubernetes 中创建的资源,作为图表安装的一部分。

您可以通过运行以下命令查看负载均衡器变得可用:

kubectl --namespace default get services -o wide -w nginx-ingress-ingress-nginx-controller

你已经安装了 Kubernetes 社区维护的 Nginx Ingress。 它将 HTTP 和 HTTPS 流量从负载均衡器路由到适当的后端服务,在 Ingress Resources 中配置。 在下一步中,您将使用入口资源公开 hello-kubernetes 应用程序部署。

第 3 步 — 使用 Ingress 公开应用程序

现在您将创建一个 Ingress Resource 并使用它在您想要的域中公开 hello-kubernetes 应用程序部署。 然后,您将通过从浏览器访问它来测试它。

您将把 Ingress 存储在一个名为 hello-kubernetes-ingress.yaml 的文件中。 使用您的编辑器创建它:

nano hello-kubernetes-ingress.yaml

将以下行添加到您的文件中:

你好-kubernetes-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-kubernetes-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: "hw1.your_domain_name"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-kubernetes-first
            port:
              number: 80
  - host: "hw2.your_domain_name"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-kubernetes-second
            port:
              number: 80

您定义一个名为 hello-kubernetes-ingress 的入口资源。 然后,您指定两个主机规则,以便 hw1.your_domain 被路由到 hello-kubernetes-first 服务,而 hw2.your_domain 从第二个部署([X159X ])。

接下来,您需要确保您的两个域通过 A 记录指向负载均衡器。 这是通过您的 DNS 提供商完成的。 要在 DigitalOcean 上配置 DNS 记录,请参阅 如何管理 DNS 记录

请记住用您自己的域替换突出显示的域,然后保存并关闭文件。

通过运行以下命令在 Kubernetes 中创建它:

kubectl apply -f hello-kubernetes-ingress.yaml

您现在可以在浏览器中导航到 hw1.your_domain。 您将看到以下内容:

第二个变体 (hw2.your_domain) 将显示不同的消息:

有了这个,您已经验证了 Ingress Controller 正确地路由请求; 在这种情况下,从您的两个域到两个不同的服务。

您已经创建并配置了一个入口资源来为您的域中的 hello-kubernetes 应用程序部署提供服务。 在下一步中,您将设置 Cert-Manager,因此您将能够使用 Let's Encrypt 提供的免费 TLS 证书保护您的 Ingress 资源。

第 4 步 — 使用 Cert-Manager 保护 Ingress

为了保护您的 Ingress 资源,您将安装 Cert-Manager,为生产创建 ClusterIssuer,并修改 Ingress 的配置以利用 TLS 证书。 ClusterIssuers 是 Kubernetes 中的 Cert-Manager 资源,为整个集群提供 TLS 证书。 安装和配置后,您的应用程序将在 HTTPS 后运行。

在通过 Helm 将 Cert-Manager 安装到集群之前,您将通过运行以下命令手动为其创建命名空间:

kubectl create namespace cert-manager

您需要将 Jetstack Helm 存储库 添加到托管 Cert-Manager 图表的 Helm。 为此,请运行以下命令:

helm repo add jetstack https://charts.jetstack.io

Helm 将显示以下输出:

Output"jetstack" has been added to your repositories

然后,更新 Helm 的图表缓存:

helm repo update

最后,通过运行以下命令将 Cert-Manager 安装到 cert-manager 命名空间中:

helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v1.2.0 --set installCRDs=true

您将看到以下输出:

OutputNAME: cert-manager
LAST DEPLOYED: Sun Dec 13 11:29:32 2020
NAMESPACE: cert-manager
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
cert-manager has been deployed successfully!
...

输出显示安装成功。 如输出中的 NOTES 中所列,您需要设置颁发者来颁发 TLS 证书。

您现在将创建一个颁发 Let's Encrypt 证书的证书,并将其配置存储在一个名为 production_issuer.yaml 的文件中。 创建它并打开它进行编辑:

nano production_issuer.yaml

添加以下行:

production_issuer.yaml

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    # Email address used for ACME registration
    email: your_email_address
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      # Name of a secret used to store the ACME account private key
      name: letsencrypt-prod-private-key
    # Add a single challenge solver, HTTP01 using nginx
    solvers:
    - http01:
        ingress:
          class: nginx

此配置定义了一个 ClusterIssuer,它与 Let's Encrypt 联系以颁发证书。 您需要将 your_email_address 替换为您的电子邮件地址,以便接收有关证书安全性和到期的可能紧急通知。

保存并关闭文件。

kubectl 推出:

kubectl apply -f production_issuer.yaml

您将看到以下输出:

Outputclusterissuer.cert-manager.io/letsencrypt-prod created

安装 Cert-Manager 后,您就可以将证书引入上一步中定义的 Ingress 资源了。 打开hello-kubernetes-ingress.yaml进行编辑:

nano hello-kubernetes-ingress.yaml

添加突出显示的行:

你好-kubernetes-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-kubernetes-ingress
annotations:
  kubernetes.io/ingress.class: nginx
  cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
  - hosts:
    - hw1.your_domain
    - hw2.your_domain
    secretName: hello-kubernetes-tls
  rules:
  - host: "hw1.your_domain_name"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-kubernetes-first
            port:
              number: 80
  - host: "hw2.your_domain_name"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-kubernetes-second
            port:
              number: 80

spec 下的 tls 块定义了您网站的证书(在 hosts 下列出)将存储其证书的秘密,这些证书由 letsencrypt-prod ClusterIssuer 颁发。 对于您创建的每个 Ingress,这必须是不同的。

请记住将 hw1.your_domainhw2.your_domain 替换为您自己的域。 完成编辑后,保存并关闭文件。

通过运行以下命令将此配置重新应用到您的集群:

kubectl apply -f hello-kubernetes-ingress.yaml

您将看到以下输出:

Outputingress.networking.k8s.io/hello-kubernetes-ingress configured

您需要等待几分钟,让 Let's Encrypt 服务器为您的域颁发证书。 同时,您可以通过检查以下命令的输出来跟踪其进度:

kubectl describe certificate hello-kubernetes-tls

输出的结尾将与此类似:

OutputEvents:
  Type    Reason     Age   From          Message
  ----    ------     ----  ----          -------
  Normal  Issuing    26s   cert-manager  Issuing certificate as Secret does not exist
  Normal  Generated  26s   cert-manager  Stored new private key in temporary Secret resource "hello-kubernetes-tls2-nfsgp"
  Normal  Requested  26s   cert-manager  Created new CertificateRequest resource "hello-kubernetes-tls2-wzl8z"
  Normal  Issuing    24s   cert-manager  The certificate has been successfully issued

当您的最后一行输出显示为 The certificate has been successfully issued 时,您可以按 CTRL + C 退出。 在浏览器中导航到您的域之一进行测试。 您会在浏览器的地址栏左侧找到挂锁,表示您的连接是安全的。

在这一步中,您已经使用 Helm 安装了 Cert-Manager 并创建了 Let's Encrypt ClusterIssuer。 之后,您更新了 Ingress 资源以利用颁发者生成 TLS 证书。 最后,您已通过在浏览器中导航到您的域之一来确认 HTTPS 正常工作。

结论

您现在已经使用 Helm 在您的 DigitalOcean Kubernetes 集群上成功设置了 Nginx Ingress Controller 和 Cert-Manager。 您现在可以使用 Let's Encrypt TLS 证书在您的域中向 Internet 公开您的应用程序。

有关 Helm 包管理器的更多信息,请阅读这篇 介绍文章