助你理解并部署ingress

转  https://mritd.me/2017/03/04/how-to-use-nginx-ingress/

最近发现好多人问Ingress,同时一直也没去用Nginx的Ingress,索性鼓捣了一把,发现跟原来确实有了点变化,在这里写篇文章记录一下

一,Ingress介绍

Kubernetes暴露服务的方式目前只有三种:LoadBlancer Service,NodePort Service,Ingress;前两种估计都应该很熟悉,具体的可以参考下这篇文章 ;下面详细的唠一下这个Ingress

1.1,Ingress是个什么玩意

可能从大致印象上Ingress就是能利用Nginx,Haproxy啥的负载均衡器暴露集群内服务的工具;那么问题来了,集群内服务想要暴露出去面临着几个问题:

1.2,Pod漂移问题

众所周知Kubernetes具有强大的副本控制能力,能保证在任意副本(Pod)挂掉时自动从其他机器启动一个新的,还可以动态扩容等,总之一句话,这个Pod可能在任何时刻出现在任何节点上,也可能在任何时刻死在任何节点上;那么自然随着Pod的创建和销毁,Pod IP肯定会动态变化; 那么如何把这个动态的Pod IP暴露出去?这里借助于Kubernetes的服务机制,服务可以以标签的形式选定一组带有指定标签的Pod,并监控和自动负载他们的Pod IP,那么我们向外暴露只暴露服务IP就行了 ;这就是NodePort模式:即在每个节点上开起一个端口,然后转发到内部Pod IP上,如下图所示

NodePort

1.3,端口管理问题

采用NodePort方式暴露服务面临一个坑爹的问题是,服务一旦多起来,NodePort在每个节点上开启的端口会及其庞大,而且难以维护;这时候引出的思考问题是“能不能使用Nginx啥的只监听一个端口,比如80,然后按照域名向后转发?“这思路很好,简单的实现就是使用DaemonSet在每个节点上监听80,然后写好规则,因为Nginx外面绑定了宿主机80端口(就像NodePort),本身又在集群内,那么向后直接转发到相应服务IP就行了,如下图所示

使用nginx代理

1.4,域名分配及动态更新问题

从上面的思路,采用Nginx似乎已经解决了问题,但是其实这里面有一个很大缺陷:每次有新服务加入怎么改Nginx配置?总不能手动改或者来个滚动更新前端Nginx Pod吧?这时候“伟大而又正直勇敢的”Ingress登场,如果不算上面的Nginx,Ingress只有两大组件:Ingress Controller和Ingress

Ingress这个玩意,简单的理解就是你原来要改Nginx配置,然后配置各种域名对应哪个服务,现在把这个动作抽象出来,变成一个Ingress对象,你可以用yml创建,每次不要去改Nginx了,直接改yml然后创建/更新就行了 ;那么问题来了:“Nginx咋整?”

Ingress控制器这东西就是解决“Nginx咋整”的; Ingress Controoler通过与Kubernetes API交互,动态的去感知集群中Ingress规则变化,然后读取他,按照他自己模板生成一段Nginx配置,再写到Nginx Pod里,最后重装一下,工作流程如下图

入口

当然在实际应用中,最新版本Kubernetes已经将Nginx与Ingress Controller合并为一个组件,所以Nginx无需单独部署,只需要部署Ingress Controller即可

二,怼一个Nginx Ingress

上面啰嗦了那么多,只是为了讲明白Ingress的各种理论概念,下面实际部署很简单

2.1,部署默认后端

我们知道前端的Nginx最终要负载到后端服务上,那么如果访问不存在的域名咋整?官方给出的建议是部署一个默认后端,对于未知请求全部负载到这个默认后端上;这个后端啥也不干,就是返回404,部署如下

➜  ~ kubectl create -f default-backend.yaml
deployment "default-http-backend" created
service "default-http-backend" created

这个default-backend.yaml文件可以在官方Ingress仓库找到,由于篇幅限制这里不贴了,仓库位置如下

默认情况下,后端

2.2,部署Ingress Controller

部署完了后端就得把最重要的组件Nginx + Ingres Controller(官方统一称为Ingress Controller)部署上

➜  ~ kubectl create -f nginx-ingress-controller.yaml
daemonset "nginx-ingress-lb" created

注意:官方的Ingress Controller有个坑,至少我看了DaemonSet方式部署的有这个问题:没有绑定到宿主机80端口,也就是说前端Nginx没有监听宿主机80端口(这还玩个卵啊) ;所以需要把配置搞下来自己加hostNetwork一下,截图如下

添加hostNetwork

同样配置文件自己找一下,地址点这里,仓库截图如下

入口控制器

当然它支持以deamonset的方式部署,这里用的就是(个人喜欢而已),所以你发现我上面截图是部署,但是链接给的却是daemonset,因为我截图截错了......

2.3,部署Ingress

这个可就厉害了,这个部署完就能装逼了

daitouzhaungbizhanxianjishu

咳咳,回到正题,从上面可以知道Ingress就是个规则,指定哪个域名转发到哪个服务,所以说首先我们得有个服务,当然服务去哪找这里就不管了;这里默认为已经有了两个可用的服务,以下以Dashboard和kibana为例

先写一个Ingress文件,语法格式啥的请参考官方文档,由于我的Dashboard和Kibana都在kube-system这个命名空间,所以要指定namespace,写之前服务分布如下

所有服务

vim dashboard-kibana-ingress.yml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: dashboard-kibana-ingress
  namespace: kube-system
spec:
  rules:
  - host: dashboard.mritd.me
    http:
      paths:
      - backend:
          serviceName: kubernetes-dashboard
          servicePort: 80
  - host: kibana.mritd.me
    http:
      paths:
      - backend:
          serviceName: kibana-logging
          servicePort: 5601

装逼成功截图如下

仪表板

Kibana

三,部署Ingress TLS

上面已经搞定了Ingress,下面就顺便把TLS怼上;官方给出的样例很简单,大致步骤就两步:创建一个含有证书的秘密,在Ingress开启证书 ;但是我不得不喷一下,文档就提那么一嘴,大坑一堆,比如多域名配置,还有下面这文档特么的是逗我玩呢

douniwan

3.1,创建证书

首先第一步当然要有个证书,由于我这个Ingress有两个服务域名,所以证书要支持两个域名;生成证书命令如下:

# 生成 CA 自签证书
mkdir cert && cd cert
openssl genrsa -out ca-key.pem 2048
openssl req -x509 -new -nodes -key ca-key.pem -days 10000 -out ca.pem -subj "/CN=kube-ca"

# 编辑 openssl 配置
cp /etc/pki/tls/openssl.cnf .
vim openssl.cnf

# 主要修改如下
[req]
req_extensions = v3_req # 这行默认注释关着的 把注释删掉
# 下面配置是新增的
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = dashboard.mritd.me
DNS.2 = kibana.mritd.me

# 生成证书
openssl genrsa -out ingress-key.pem 2048
openssl req -new -key ingress-key.pem -out ingress.csr -subj "/CN=kube-ingress" -config openssl.cnf
openssl x509 -req -in ingress.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out ingress.pem -days 365 -extensions v3_req -extfile openssl.cnf

3.2,创建秘密

创建好证书以后,需要将证书内容放到秘密中,秘密中全部内容需要base64编码,然后注意去掉换行符(变成一行);以下是我的秘密样例(上一步中ingress.pem是证书, ingress-key.pem是证书的关键)

vim ingress-secret.yml

apiVersion: v1
data:
  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM5akNDQWQ2Z0F3SUJBZ0lKQU5TR2dNNnYvSVd5TUEwR0NTcUdTSWIzRFFFQkJRVUFNQkl4RURBT0JnTlYKQkFNTUIydDFZbVV0WTJFd0hoY05NVGN3TXpBME1USTBPRFF5V2hjTk1UZ3dNekEwTVRJME9EUXlXakFYTVJVdwpFd1lEVlFRRERBeHJkV0psTFdsdVozSmxjM013Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUUM2dkNZRFhGSFpQOHI5Zk5jZXlkV015VVlELzAwQ2xnS0M2WjNpYWZ0QlRDK005TmcrQzloUjhJUE4KWW00cjZOMkw1MmNkcmZvQnBHZXovQVRIT0NJYUhJdlp1K1ZaTzNMZjcxZEVLR09nV21LMTliSVAzaGpSeDZhWQpIeGhEVWNab3ZzYWY1UWJHRnUydEF4L2doMTFMdXpTZWJkT0Y1dUMrWHBhTGVzWWdQUjhFS0cxS0VoRXBLMDFGCmc4MjhUU1g2TXVnVVZmWHZ1OUJRUXExVWw0Q2VMOXhQdVB5T3lMSktzbzNGOEFNUHFlaS9USWpsQVFSdmRLeFYKVUMzMnBtTHRlUFVBb2thNDRPdElmR3BIOTZybmFsMW0rMXp6YkdTemRFSEFaL2k1ZEZDNXJOaUthRmJnL2NBRwppalhlQ01xeGpzT3JLMEM4MDg4a0tjenJZK0JmQWdNQkFBR2pTakJJTUM0R0ExVWRFUVFuTUNXQ0VtUmhjMmhpCmIyRnlaQzV0Y21sMFpDNXRaWUlQYTJsaVlXNWhMbTF5YVhSa0xtMWxNQWtHQTFVZEV3UUNNQUF3Q3dZRFZSMFAKQkFRREFnWGdNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNFN1ByRzh6MytyaGJESC8yNGJOeW5OUUNyYVM4NwphODJUUDNxMmsxUUJ1T0doS1pwR1N3SVRhWjNUY0pKMkQ2ZlRxbWJDUzlVeDF2ckYxMWhGTWg4MU9GMkF2MU4vCm5hSU12YlY5cVhYNG16eGNROHNjakVHZ285bnlDSVpuTFM5K2NXejhrOWQ1UHVaejE1TXg4T3g3OWJWVFpkZ0sKaEhCMGJ5UGgvdG9hMkNidnBmWUR4djRBdHlrSVRhSlFzekhnWHZnNXdwSjlySzlxZHd1RHA5T3JTNk03dmNOaQpseWxDTk52T3dNQ0h3emlyc01nQ1FRcVRVamtuNllLWmVsZVY0Mk1yazREVTlVWFFjZ2dEb1FKZEM0aWNwN0sxCkRPTDJURjFVUGN0ODFpNWt4NGYwcUw1aE1sNGhtK1BZRyt2MGIrMjZjOVlud3ROd24xdmMyZVZHCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
  tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBdXJ3bUExeFIyVC9LL1h6WEhzblZqTWxHQS85TkFwWUNndW1kNG1uN1FVd3ZqUFRZClBndllVZkNEeldKdUsramRpK2RuSGEzNkFhUm5zL3dFeHpnaUdoeUwyYnZsV1R0eTMrOVhSQ2hqb0ZwaXRmV3kKRDk0WTBjZW1tQjhZUTFIR2FMN0duK1VHeGhidHJRTWY0SWRkUzdzMG5tM1RoZWJndmw2V2kzckdJRDBmQkNodApTaElSS1N0TlJZUE52RTBsK2pMb0ZGWDE3N3ZRVUVLdFZKZUFuaS9jVDdqOGpzaXlTcktOeGZBREQ2bm92MHlJCjVRRUViM1NzVlZBdDlxWmk3WGoxQUtKR3VPRHJTSHhxUi9lcTUycGRadnRjODJ4a3MzUkJ3R2Y0dVhSUXVhelkKaW1oVzRQM0FCb28xM2dqS3NZN0RxeXRBdk5QUEpDbk02MlBnWHdJREFRQUJBb0lCQUJtRmIzaVVISWVocFYraAp1VkQyNnQzVUFHSzVlTS82cXBzenpLVk9NTTNLMk5EZUFkUHhFSDZhYlprYmM4MUNoVTBDc21BbkQvMDdlQVRzClU4YmFrQ2FiY2kydTlYaU5uSFNvcEhlblFYNS8rKys4aGJxUGN6cndtMzg4K0xieXJUaFJvcG5sMWxncWVBOW0KVnV2NzlDOU9oYkdGZHh4YzRxaUNDdmRETDJMbVc2bWhpcFRKQnF3bUZsNUhqeVphdGcyMVJ4WUtKZ003S1p6TAplYWU0bTJDR3R0bmNyUktodklaQWxKVmpyRWoxbmVNa3RHODFTT3QyN0FjeDRlSnozbmcwbjlYSmdMMHcwU05ZCmlwd3I5Uk5PaDkxSGFsQ3JlWVB3bDRwajIva0JIdnozMk9Qb2FOSDRQa2JaeTEzcks1bnFrMHBXdUthOEcyY00KLzY4cnQrRUNnWUVBN1NEeHRzRFFBK2JESGdUbi9iOGJZQ3VhQ2N4TDlObHIxd2tuTG56VVRzRnNkTDByUm1uZAp5bWQ4aU95ME04aUVBL0xKb3dPUGRRY240WFdWdS9XbWV5MzFVR2NIeHYvWlVSUlJuNzgvNmdjZUJSNzZJL2FzClIrNVQ1TEMyRmducVd2MzMvdG0rS0gwc0J4dEM3U2tSK3Y2UndVQk1jYnM3c0dUQlR4NVV2TkVDZ1lFQXlaaUcKbDBKY0dzWHhqd1JPQ0FLZytEMlJWQ3RBVmRHbjVMTmVwZUQ4bFNZZ3krZGxQaCt4VnRiY2JCV0E3WWJ4a1BwSAorZHg2Z0p3UWp1aGN3U25uOU9TcXRrZW04ZmhEZUZ2MkNDbXl4ZlMrc1VtMkxqVzM1NE1EK0FjcWtwc0xMTC9GCkIvK1JmcmhqZW5lRi9BaERLalowczJTNW9BR0xRVFk4aXBtM1ZpOENnWUJrZGVHUnNFd3dhdkpjNUcwNHBsODkKdGhzemJYYjhpNlJSWE5KWnNvN3JzcXgxSkxPUnlFWXJldjVhc0JXRUhyNDNRZ1BFNlR3OHMwUmxFMERWZWJRSApXYWdsWVJEOWNPVXJvWFVYUFpvaFZ0U1VETlNpcWQzQk42b1pKL2hzaTlUYXFlQUgrMDNCcjQ0WWtLY2cvSlplCmhMMVJaeUU3eWJ2MjlpaWprVkVMRVFLQmdRQ2ZQRUVqZlNFdmJLYnZKcUZVSm05clpZWkRpNTVYcXpFSXJyM1cKSEs2bVNPV2k2ZlhJYWxRem1hZW1JQjRrZ0hDUzZYNnMyQUJUVWZLcVR0UGxKK3EyUDJDd2RreGgySTNDcGpEaQpKYjIyS3luczg2SlpRY2t2cndjVmhPT1Z4YTIvL1FIdTNXblpSR0FmUGdXeEcvMmhmRDRWN1R2S0xTNEhwb1dQCm5QZDV0UUtCZ0QvNHZENmsyOGxaNDNmUWpPalhkV0ZTNzdyVFZwcXBXMlFoTDdHY0FuSXk5SDEvUWRaOXYxdVEKNFBSanJseEowdzhUYndCeEp3QUtnSzZmRDBXWmZzTlRLSG01V29kZUNPWi85WW13cmpPSkxEaUU3eFFNWFBzNQorMnpVeUFWVjlCaDI4cThSdnMweHplclQ1clRNQ1NGK0Q5NHVJUmkvL3ZUMGt4d05XdFZxCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
kind: Secret
metadata:
  name: ingress-secret
  namespace: kube-system
type: Opaque

创建完成后创一下就可

➜  ~ kubectl create -f ingress-secret.yml
secret "ingress-secret" created

其实这个配置比如证书转码啥的没必要手动去做,可以直接使用下面的命令创建,这里写这么多只是为了把步骤写清晰

kubectl create secret tls ingress-secret --key cert/ingress-key.pem --cert cert/ingress.pem

3.3,重新部署Ingress

生成完成后需要在Ingress中开启TLS,Ingress修改后如下

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: dashboard-kibana-ingress
  namespace: kube-system
spec:
  tls:
  - hosts:
    - dashboard.mritd.me
    - kibana.mritd.me
    secretName: ingress-secret
  rules:
  - host: dashboard.mritd.me
    http:
      paths:
      - backend:
          serviceName: kubernetes-dashboard
          servicePort: 80
  - host: kibana.mritd.me
    http:
      paths:
      - backend:
          serviceName: kibana-logging
          servicePort: 5601

注意:一个Ingress只能使用一个秘密(secretName段只能有一个),也就是说只能用一个证书,更直白的说就是如果你在一个Ingress中配置了多个域名,那么使用TLS的话必须保证证书支持该Ingress下所有域名;并且这个secretName一定要放在上面域名列表最后位置,否则会报错did not find expected key无法创建;同时上面的hosts段下域名必须跟下面的rules中完全匹配

更需要注意一点:之所以这里单独开一段就是因为有大坑; Kubernetes Ingress默认情况下,当你不配置证书时,会默认给你一个TLS证书的,也就是说你Ingress中配置错了,比如写了2个secretName,或者hosts段中缺了某个域名,对于那么写了多个secretName的情况,所有域名全会走默认证书;对于hosts缺了某个域名的情况,缺失的域名将会走默认证书,部署时一定要验证一下证书,不能“有了就行”;更新Ingress证书可能需要等一段时间才会生效

最后重新部署一下即可

➜  ~ kubectl delete -f dashboard-kibana-ingress.yml
ingress "dashboard-kibana-ingress" deleted
➜  ~ kubectl create -f dashboard-kibana-ingress.yml
ingress "dashboard-kibana-ingress" created

注意:部署TLS后80端口会自动重定向到443,最终访问截图如下

Ingress TLS

入口TLS证书

历时5个小时鼓捣,到此结束

转载请注明出处,本文采用CC4.0协议授权


 
原文地址:https://www.cnblogs.com/fyy-hhzzj/p/9698307.html