百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

Kubernetns LB:无需云厂商的动态DNS和负载均衡

bigegpt 2024-09-12 11:25 9 浏览

译者:祝祥

我们经常谈论托管Kubernetes或在云中运行的Kubernetes,但我们也在非云的环境(例如VMware或裸机服务器)上运行Kubernetes。

您可能还会听到很多有关云供应商集成的经典案例:您可以获取无密码凭据来访问托管服务,无需手动干预即可配置云负载均衡器,自动创建DNS条目等。

在本地运行时,通常无法使用这些集成功能,除非您使用的是受支持的云平台(如 OpenStack)。那么当在裸机或VM上运行时,如何获得Cloud Native环境的自动化优势?

所以让我们一步一步去看我们所想实现的功能。

本文中使用的所有清单均可在github项目中(https://github.com/clusterfrak-dynamics/gitops-template)获取。

GitOps

与往常一样,我们使用GitOps和FluxCD将我们的资源部署到集群中,无论它们是在云上还是在本地。你可以参考跟多我们关于Flux的文章。

首先,您可以使用我们的GitOps模板,并根据需要对其进行自定义。kubectl如果更合适,您也可以直接部署清单 。

以下让我们深入研究我们的组件。

负载均衡

在云上运行kubernetns时,通常可以立即使用Load Balancer。在裸机或VM上运行时,负载均衡器保持pending不可用状态。

因此,首先,我们希望我们的服务类型LoadBalancer不处于pending不可用状态,并且能够在需要时提供动态负载平衡器,而无需手动配置haproxy或其他类似的服务。

metallb可以提供两种模式的虚拟负载均衡器的实现:

  • BGP协议
  • ARP


后者更简单,因为它可以在几乎任何二层网络上工作,而无需进一步配置。

在ARP模式下,metallb的配置非常简单。您只需要给它提供一些可以使用的IP就可以了。

配置清单可在此处或官方文件中找到。要配置所需的IP地址,可以使用ConfigMap完成。

metallb-config.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 10.10.39.200-10.10.39.220

您还需要生成一个密钥来加密Metallb组件通信,您可以使用以下脚本来生成Kubernetes secret yaml:

kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" -o yaml --dry-run=client > metallb-secret.yaml

部署完所有内容后,您应该在metallb-system namespace内看到相应的pods :

NAME                          READY   STATUS    RESTARTS   AGE
controller-57f648cb96-tvr9q   1/1     Running   0          2d1h
speaker-7rd8p                 1/1     Running   0          2d1h
speaker-7t7rg                 1/1     Running   0          2d1h
speaker-8qm2t                 1/1     Running   0          2d1h
speaker-bks4s                 1/1     Running   0          2d1h
speaker-cz6bc                 1/1     Running   0          2d1h
speaker-h8b54                 1/1     Running   0          2d1h
speaker-j6bss                 1/1     Running   0          2d1h
speaker-phvv7                 1/1     Running   0          2d1h
speaker-wdwjc                 1/1     Running   0          2d1h
speaker-xj25p                 1/1     Running   0          2d1h

现在,我们准备测试负载均衡器。为此,我们直接进入下一个主题。

Ingress controller

在云上运行时,除了经典的4层负载均衡器以外,您有时还可以在GCP和AWS上获得7层负载均衡器(例如,应用程序负载均衡器)。但是它们的功能有限,而且成本效益不高,而且您经常需要一个ingress controller来管理来自Kubernetes集群的流量。

这个ingress controller通常通过服务类型为LoadBalancer在外部发布。这就是为什么我们以前的metallb部署会派上用场。

第一个也是最常用的ingress controller之一是nginx-ingress,它可以轻松地与Helm一起部署。

由于我们将Flux与Helm Operator结合使用,因此根据我们使用的Helm,您可以参考以下values.yaml配置:

因为我们将Flux与Helm Operator结合使用,所以我们使用了一个Helm Release 的版本,您可以从中得到values.yaml,以下展示了我们的配置:

apiVersion: helm.fluxcd.io/v1
kind: HelmRelease
metadata:
  name: nginx-ingress
  namespace: nginx-ingress
spec:
  releaseName: nginx-ingress
  chart:
    repository: https://kubernetes-charts.storage.googleapis.com
    version: 1.36.3
    name: nginx-ingress
  values:
    controller:
      publishService:
        enabled: true
      kind: "DaemonSet"
      service:
        enabled: true
        externalTrafficPolicy: Local
      daemonset:
        hostPorts:
          http: 80
          https: 443
    defaultBackend:
      replicaCount: 2
    podSecurityPolicy:
      enabled: true

没有什么特别之处,我们使用的是DaemonSet,默认情况下是使用的服务类型为LoadBalancer。

如果我们检查新部署的版本:

nbsp;kubectl -n nginx-ingress get helmreleases.helm.fluxcd.io
NAME            RELEASE         PHASE       STATUS     MESSAGE                                                                       AGE
nginx-ingress   nginx-ingress   Succeeded   deployed   Release was successful for Helm release 'nginx-ingress' in 'nginx-ingress'.   2d1h

or

nbsp;helm -n nginx-ingress ls
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
nginx-ingress   nginx-ingress   2               2020-05-12 15:06:25.832403094 +0000 UTC deployed        nginx-ingress-1.36.3    0.30.0

nbsp;kubectl -n nginx-ingress get svc
NAME                            TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)                      AGE
nginx-ingress-controller        LoadBalancer   10.108.113.212   10.10.39.200   80:31465/TCP,443:30976/TCP   2d1h
nginx-ingress-default-backend   ClusterIP      10.102.217.148   <none>         80/TCP                       2d1h

我们可以看到,我们的服务是LoadBalancer类型,外部IP是我们在之前metallb的ConfigMap中定义的。

让我们创建一个demo namespace并检查创建ingress时的行为:

nbsp;kubectl create namespace demo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: demo
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: demo
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
  name: nginx
  namespace: demo
spec:
  rules:
  - host: nginx.test.org
    http:
      paths:
      - backend:
          serviceName: nginx
          servicePort: 80

nginx-ingress 能够在默认情况下发布服务,这意味着它可以向ingress对象报告负载平衡器IP地址:

nbsp;kubectl -n demo get ingress

NAME    CLASS    HOSTS            ADDRESS        PORTS     AGE
nginx   <none>   nginx.test.org   10.10.39.200   80, 443   47h

我们可以看到,LoadBalancer IP地址已嵌入到ingress中。这是能够使用external DNS的要求之一,这也是我们的下一个主题。

External DNS

现在我们已经有了4层负载平衡器(metallb),它们可以将流量传送到群集中的7层负载平衡器(nginx-ingress),我们如何动态管理DNS?一个常用的工具是 external-dns(https://github.com/kubernetes-sigs/external-dns)使Kubernetes Services和Ingress与DNS平台保持同步。

如果您正在使用一种广泛使用的DNS平台(AWS Route53或 Google Cloud DNS),这将非常简单易用。External DNS还支持其他DNS供应商,但是如果您没有使用直接支持的DNS供应商,您可能就会比较麻烦。

比方说,您的本地DNS由Active Directory管理,因为External DNS无法直接写入Active Directory DNS,所以最终导致DNS解析不可用。

那么我们如何才能获得动态DNS功能呢?当然,你可以使用一个通配符DNS记录并将其指向到nginx-ingress负载平衡器IP,这是一种方法。如果您只使用一个LoadBalancer作为集群的入口,但如果您希望使用HTTP或其他类型LoadBalancer服务以外的协议,则仍需要手动更新一些DNS记录。

另一个解决方案是为您的群集指定DNS zone。

External DNS支持CoreDNS作为后端,因此我们可以将active directory的DNS Zone指派给Kubernetes中运行的CoreDNS服务器。

注意事项

听起来很简单,但是当深入研究external-dns/CoreDNS部分时,我们注意到与External DNS一起使用的CoreDNS唯一受支持的后端是Etcd。所以我们需要一个Etcd集群。您可能还注意到readme依赖于etcd-operator,它现在已被弃用,而且它也不不支持加密与etcd的通信。

我们发布了最新指南。首先,我们将使用Cilium的etcd-operator来配置3个节点的etcd集群并生成TLS。

Etcd operator

首先,我们应用etcd的 Custom Resource Definition:(https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/):

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: etcdclusters.etcd.database.coreos.com
spec:
  additionalPrinterColumns:
  - JSONPath: .metadata.creationTimestamp
    description: 'CreationTimestamp is a timestamp representing the server time when
      this object was created. It is not guaranteed to be set in happens-before order
      across separate operations. Clients may not set this value. It is represented
      in RFC3339 form and is in UTC. Populated by the system. Read-only. Null for
      lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata'
    name: Age
    type: date
  group: etcd.database.coreos.com
  names:
    kind: EtcdCluster
    listKind: EtcdClusterList
    plural: etcdclusters
    shortNames:
    - etcd
    singular: etcdcluster
  scope: Namespaced
  version: v1beta2
  versions:
  - name: v1beta2
    served: true
    storage: true

然后我们可以部署Etcd operator。

很快我们就可以得到etcd pod和secrets了:

nbsp;kubectl -n external-dns get pods

NAME                                    READY   STATUS    RESTARTS   AGE
cilium-etcd-mnphzk2tjl                  1/1     Running   0          2d1h
cilium-etcd-operator-55d89bbff7-cw8rc   1/1     Running   0          2d1h
cilium-etcd-tsxm5rsckj                  1/1     Running   0          2d1h
cilium-etcd-wtnqt22ssg                  1/1     Running   0          2d1h
etcd-operator-6c57fff6f5-g92pc          1/1     Running   0          2d1h

nbsp;kubectl -n external-dns get secrets
NAME                                 TYPE                                  DATA   AGE
cilium-etcd-client-tls               Opaque                                3      2d1h
cilium-etcd-operator-token-zmjcl     kubernetes.io/service-account-token   3      2d1h
cilium-etcd-peer-tls                 Opaque                                3      2d1h
cilium-etcd-sa-token-5dhtn           kubernetes.io/service-account-token   3      2d1h
cilium-etcd-secrets                  Opaque                                3      2d1h
cilium-etcd-server-tls               Opaque                                3      2d1h

CoreDNS

然后,我们可以使用官方Helm chat部署CoreDNS 。

就像以前一样,我们的资源是*HelmRelease*(https://github.com/clusterfrak-dynamics/gitops-template/blob/master/flux/resources/external-dns/coredns.yaml)。如果需要values.yaml,您可以从中获取:

apiVersion: helm.fluxcd.io/v1
kind: HelmRelease
metadata:
  name: coredns
  namespace: external-dns
spec:
  releaseName: coredns
  chart:
    repository: https://kubernetes-charts.storage.googleapis.com
    version: 1.10.1
    name: coredns
  values:
    serviceType: "NodePort"
    replicaCount: 2
    serviceAccount:
      create: true
    rbac:
      pspEnable: true
    isClusterService: false
    extraSecrets:
    - name: cilium-etcd-client-tls
      mountPath: /etc/coredns/tls/etcd
    servers:
      - zones:
        - zone: .
        port: 53
        plugins:
        - name: errors
        - name: health
          configBlock: |-
            lameduck 5s
        - name: ready
        - name: prometheus
          parameters: 0.0.0.0:9153
        - name: forward
          parameters: . /etc/resolv.conf
        - name: cache
          parameters: 30
        - name: loop
        - name: reload
        - name: loadbalance
        - name: etcd
          parameters: test.org
          configBlock: |-
            stubzones
            path /skydns
            endpoint https://cilium-etcd-client.external-dns.svc:2379
            tls /etc/coredns/tls/etcd/etcd-client.crt /etc/coredns/tls/etcd/etcd-client.key /etc/coredns/tls/etcd/etcd-client-ca.crt

重要的几行如下:

extraSecrets:
- name: cilium-etcd-client-tls
  mountPath: /etc/coredns/tls/etcd

and

- name: etcd
  parameters: test.org
  configBlock: |-
    stubzones
    path /skydns
    endpoint https://cilium-etcd-client.external-dns.svc:2379
    tls /etc/coredns/tls/etcd/etcd-client.crt /etc/coredns/tls/etcd/etcd-client.key /etc/coredns/tls/etcd/etcd-client-ca.crt

我们正在安装并使用etcd secret与etcd进行TLS通信。

External DNS

最后,我们可以打包并安装external DNS。和往常一样,我们将使用官方的Helm chat(https://github.com/helm/charts/tree/master/stable/external-dns)和HelmRelease(https://github.com/clusterfrak-dynamics/gitops-template/blob/master/flux/resources/external-dns/external-dns.yaml):

apiVersion: helm.fluxcd.io/v1
kind: HelmRelease
metadata:
  name: external-dns
  namespace: external-dns
spec:
  releaseName: external-dns
  chart:
    repository: https://charts.bitnami.com/bitnami
    version: 2.22.4
    name: external-dns
  values:
    provider: coredns
    policy: sync
    coredns:
      etcdEndpoints: "https://cilium-etcd-client.external-dns.svc:2379"
      etcdTLS:
        enabled: true
        secretName: "cilium-etcd-client-tls"
        caFilename: "etcd-client-ca.crt"
        certFilename: "etcd-client.crt"
        keyFilename: "etcd-client.key"

这里,与以前一样,我们提供了etcd TLS的secret名称和路径,以确保通信安全,并且我们启用了coredns。

这是我们的最终external-dns namespace:

nbsp;kubectl -n external-dns get svc
NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                     AGE
cilium-etcd          ClusterIP   None           <none>        2379/TCP,2380/TCP           2d2h
cilium-etcd-client   ClusterIP   10.105.37.25   <none>        2379/TCP                    2d2h
coredns-coredns      NodePort    10.99.62.135   <none>        53:31071/UDP,53:30396/TCP   2d1h
external-dns         ClusterIP   10.103.88.97   <none>        7979/TCP                    2d1h

nbsp;kubectl -n external-dns get pods
NAME                                    READY   STATUS    RESTARTS   AGE
cilium-etcd-mnphzk2tjl                  1/1     Running   0          2d2h
cilium-etcd-operator-55d89bbff7-cw8rc   1/1     Running   0          2d2h
cilium-etcd-tsxm5rsckj                  1/1     Running   0          2d2h
cilium-etcd-wtnqt22ssg                  1/1     Running   0          2d2h
coredns-coredns-5c86dd5979-866s2        1/1     Running   0          2d
coredns-coredns-5c86dd5979-vq86w        1/1     Running   0          2d
etcd-operator-6c57fff6f5-g92pc          1/1     Running   0          2d2h
external-dns-96d9fbc64-j22pf            1/1     Running   0          2d1h

如果您回头看一下我们的ingress:

---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
  name: nginx
  namespace: demo
spec:
  rules:
  - host: nginx.test.org
    http:
      paths:
      - backend:
          serviceName: nginx
          servicePort: 80
nbsp;kubectl -n demo get ingress

NAME    CLASS    HOSTS            ADDRESS        PORTS     AGE
nginx   <none>   nginx.test.org   10.10.39.200   80, 443   2d

让我们检查此ingress是否已被external dns接收并插入etcd数据库:

nbsp;kubectl -n external-dns logs -f external-dns-96d9fbc64-j22pf
time="2020-05-12T15:23:52Z" level=info msg="Add/set key /skydns/org/test/nginx/4781436c to Host=10.10.39.200, Text=\"heritage=external-dns,external-dns/owner=default,external-dns/resource=ingress/demo/nginx\", TTL=0"

External DNS似乎正在发挥作用。现在,让我们看看是否可以直接从CoreDNS解析查询,因为它应该是从同一etcd服务器读取的。

CoreDNS正在监听NodePort服务,这意味着我们可以查询该服务上的任何节点NodePort:

nbsp;kubectl -n external-dns get svc coredns-coredns
NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                     AGE
coredns-coredns      NodePort    10.99.62.135   <none>        53:31071/UDP,53:30396/TCP   2d1h

53/UDP端口映射到端口31071/UDP。让我们选择一个随机节点:

NAME STATUS   ROLES    AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
m1   Ready    master   15d   v1.18.2   10.10.40.10    <none>        Ubuntu 18.04.3 LTS   4.15.0-99-generic   containerd://1.3.4
n1   Ready    <none>   15d   v1.18.2   10.10.40.110   <none>        Ubuntu 18.04.3 LTS   4.15.0-99-generic   containerd://1.3.4
n2   Ready    <none>   15d   v1.18.2   10.10.40.120   <none>        Ubuntu 18.04.3 LTS   4.15.0-74-generic   containerd://1.3.4

并尝试使用以下方式进行DNS查询dig:

root@inf-k8s-epi-m5:~# dig -p 31071 nginx.test.org @10.10.40.120

; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> -p 31071 nginx.test.org @10.10.40.120
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61245
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: ef8ff2732b2dc6fd (echoed)
;; QUESTION SECTION:
;nginx.test.org.                        IN      A

;; ANSWER SECTION:
nginx.test.org.         30      IN      A       10.10.39.200

;; Query time: 2 msec
;; SERVER: 10.10.40.120#31071(10.10.40.120)
;; WHEN: Thu May 14 16:26:07 UTC 2020
;; MSG SIZE  rcvd: 85

我们可以看到CoreDNS正在使用MetalLB负载均衡器IP进行回复。

快速启动并运行

在本指南中,我们配置了CoreDNS,External DNS,Nginx Ingress和MetalLB,以提供与Cloud架构一样的动态体验。如果您想快速入门,请查看我们的Flux github仓库地址,其中包含用于此演示的所有清单以及更多内容(https://github.com/clusterfrak-dynamics/gitops-template/tree/master/flux)。

原文:https://particule.io/en/blog/k8s-no-cloud/

相关推荐

当Frida来“敲”门(frida是什么)

0x1渗透测试瓶颈目前,碰到越来越多的大客户都会将核心资产业务集中在统一的APP上,或者对自己比较重要的APP,如自己的主业务,办公APP进行加壳,流量加密,投入了很多精力在移动端的防护上。而现在挖...

服务端性能测试实战3-性能测试脚本开发

前言在前面的两篇文章中,我们分别介绍了性能测试的理论知识以及性能测试计划制定,本篇文章将重点介绍性能测试脚本开发。脚本开发将分为两个阶段:阶段一:了解各个接口的入参、出参,使用Python代码模拟前端...

Springboot整合Apache Ftpserver拓展功能及业务讲解(三)

今日分享每天分享技术实战干货,技术在于积累和收藏,希望可以帮助到您,同时也希望获得您的支持和关注。架构开源地址:https://gitee.com/msxyspringboot整合Ftpserver参...

Linux和Windows下:Python Crypto模块安装方式区别

一、Linux环境下:fromCrypto.SignatureimportPKCS1_v1_5如果导包报错:ImportError:Nomodulenamed'Crypt...

Python 3 加密简介(python des加密解密)

Python3的标准库中是没多少用来解决加密的,不过却有用于处理哈希的库。在这里我们会对其进行一个简单的介绍,但重点会放在两个第三方的软件包:PyCrypto和cryptography上,我...

怎样从零开始编译一个魔兽世界开源服务端Windows

第二章:编译和安装我是艾西,上期我们讲述到编译一个魔兽世界开源服务端环境准备,那么今天跟大家聊聊怎么编译和安装我们直接进入正题(上一章没有看到的小伙伴可以点我主页查看)编译服务端:在D盘新建一个文件夹...

附1-Conda部署安装及基本使用(conda安装教程)

Windows环境安装安装介质下载下载地址:https://www.anaconda.com/products/individual安装Anaconda安装时,选择自定义安装,选择自定义安装路径:配置...

如何配置全世界最小的 MySQL 服务器

配置全世界最小的MySQL服务器——如何在一块IntelEdison为控制板上安装一个MySQL服务器。介绍在我最近的一篇博文中,物联网,消息以及MySQL,我展示了如果Partic...

如何使用Github Action来自动化编译PolarDB-PG数据库

随着PolarDB在国产数据库领域荣膺桂冠并持续获得广泛认可,越来越多的学生和技术爱好者开始关注并涉足这款由阿里巴巴集团倾力打造且性能卓越的关系型云原生数据库。有很多同学想要上手尝试,却卡在了编译数据...

面向NDK开发者的Android 7.0变更(ndk android.mk)

订阅Google官方微信公众号:谷歌开发者。与谷歌一起创造未来!受Android平台其他改进的影响,为了方便加载本机代码,AndroidM和N中的动态链接器对编写整洁且跨平台兼容的本机...

信创改造--人大金仓(Kingbase)数据库安装、备份恢复的问题纪要

问题一:在安装KingbaseES时,安装用户对于安装路径需有“读”、“写”、“执行”的权限。在Linux系统中,需要以非root用户执行安装程序,且该用户要有标准的home目录,您可...

OpenSSH 安全漏洞,修补操作一手掌握

1.漏洞概述近日,国家信息安全漏洞库(CNNVD)收到关于OpenSSH安全漏洞(CNNVD-202407-017、CVE-2024-6387)情况的报送。攻击者可以利用该漏洞在无需认证的情况下,通...

Linux:lsof命令详解(linux lsof命令详解)

介绍欢迎来到这篇博客。在这篇博客中,我们将学习Unix/Linux系统上的lsof命令行工具。命令行工具是您使用CLI(命令行界面)而不是GUI(图形用户界面)运行的程序或工具。lsoflsof代表&...

幻隐说固态第一期:固态硬盘接口类别

前排声明所有信息来源于网络收集,如有错误请评论区指出更正。废话不多说,目前固态硬盘接口按速度由慢到快分有这几类:SATA、mSATA、SATAExpress、PCI-E、m.2、u.2。下面我们来...

新品轰炸 影驰SSD多款产品登Computex

分享泡泡网SSD固态硬盘频道6月6日台北电脑展作为全球第二、亚洲最大的3C/IT产业链专业展,吸引了众多IT厂商和全球各地媒体的热烈关注,全球存储新势力—影驰,也积极参与其中,为广大玩家朋友带来了...