作者:祝祥 翻译  2020-08-31 07:14:03
云计算 我们经常谈论托管Kubernetes或在云中运行的Kubernetes,但我们也在非云的环境(例如VMware或裸机服务器)上运行Kubernetes。

本文转载自微信公众号「新钛云服」,作者祝祥 翻译 。转载本文请联系新钛云服公众号。
我们经常谈论托管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可以提供两种模式的虚拟负载均衡器的实现:
后者更简单,因为它可以在几乎任何二层网络上工作,而无需进一步配置。
在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。
如果我们检查新部署的版本:
- $ 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
 - $ 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
 - $ 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
 80/TCP 
我们可以看到,我们的服务是LoadBalancer类型,外部IP是我们在之前metallb的ConfigMap中定义的。
让我们创建一个demo namespace并检查创建ingress时的行为:
- $ 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地址:
- $ kubectl -n demo get ingress
 - NAME CLASS HOSTS ADDRESS PORTS AGE
 - nginx
 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了:
- $ 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
 - $ 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:
- $ kubectl -n external-dns get svc
 - NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
 - cilium-etcd ClusterIP None
 2379/TCP,2380/TCP 2d2h - cilium-etcd-client ClusterIP 10.105.37.25
 2379/TCP 2d2h - coredns-coredns NodePort 10.99.62.135
 53:31071/UDP,53:30396/TCP 2d1h - external-dns ClusterIP 10.103.88.97
 7979/TCP 2d1h - $ 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
 - $ kubectl -n demo get ingress
 - NAME CLASS HOSTS ADDRESS PORTS AGE
 - nginx
 nginx.test.org 10.10.39.200 80, 443 2d 
让我们检查此ingress是否已被external dns接收并插入etcd数据库:
- $ 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:
- $ kubectl -n external-dns get svc coredns-coredns
 - NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
 - coredns-coredns NodePort 10.99.62.135
 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
 Ubuntu 18.04.3 LTS 4.15.0-99-generic containerd://1.3.4 - n1 Ready
 15d v1.18.2 10.10.40.110 Ubuntu 18.04.3 LTS 4.15.0-99-generic containerd://1.3.4 - n2 Ready
 15d v1.18.2 10.10.40.120 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/
                新闻标题:Kubernetns LB方案:无需云厂商的动态DNS和负载均衡
                
                URL链接:http://www.csdahua.cn/qtweb/news23/349923.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网