K8s Nginx Ingress 介绍

作者:漠然,原文发布于2017年3月4日,原文链接

一、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 的 Service 机制,Service 可以以标签的形式选定一组带有指定标签的 Pod,并监控和自动负载他们的 Pod IP,那么我们向外暴露只暴露 Service IP 就行了;这就是 NodePort 模式:即在每个节点上开起一个端口,然后转发到内部 Pod IP 上,如下图所示

1.3、端口管理问题

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

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

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

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

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

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

二、怼一个 Nginx Ingress

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

2.1、部署默认后端

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

$ kubectl create-f default-backend.yamldeployment
default-http-backend"createdservice
default-http-backend"created

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

2.2、部署 Ingress Controller

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

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

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

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

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

2.3、部署 Ingress

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

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

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

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

装逼成功截图如下

三、部署 Ingress TLS

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

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、创建 secret

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

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

创建完成后 create 一下就可。

$  ~ 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 只能使用一个 secret(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 。

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

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

原文地址:https://www.cnblogs.com/k8s/p/12235515.html

时间: 2024-10-10 20:38:36

K8s Nginx Ingress 介绍的相关文章

k8s nginx ingress配置TLS

在没有配置任何nginx下,k8s的nginx默认只支持TLS1.2,不支持TLS1.0和TLS1.1 默认的 nginx-config(部分可能叫 nginx-configuration)的配置如下: apiVersion: v1 data: allow-backend-server-header: 'true' enable-underscores-in-headers: 'true' generate-request-id: 'true' http-redirect-code: '301'

Kubernetes 部署 Nginx Ingress Controller

开始天真地以为只要写一个 ingress 配置文件并部署好就行了. apiVersion: extensions/v1beta1 kind: Ingress metadata: name: cnblogs-ingress spec: rules: - host: q.cnblogs.com http: paths: - backend: serviceName: q-web servicePort: 80 # kubectl apply -f cnblogs-ingress.yaml # kub

同一k8s集群中多nginx ingress controller

同一k8s集群中多nginx ingress controller同一k8s集群中,若有多个项目(对应多个namespace)共用一个nginx ingress controller,因此任意注册到ingress的服务有变更都会导致controller配置重载,当更新频率越来越高时,此controller压力会越来越大,理想的解决方案就是每个namespace对应一个nginx ingress controller,各司其职. NGINX ingress controller提供了ingress

见异思迁:K8s 部署 Nginx Ingress Controller 之 kubernetes/ingress-nginx

前天才发现,区区一个 nginx ingress controller 竟然2个不同的实现.一个叫 kubernetes/ingress-nginx ,是由 kubernetes 社区维护的,对应的容器镜像是 quay.io/kubernetes-ingress-controller/nginx-ingress-controller ,namespace 是 ingress-nginx :一个叫 nginxinc/kubernetes-ingress ,是由 nginx 公司与社区共同维护的,对

Kubernetes使用Nginx Ingress暴露Dashboard

Kubernetes使用Nginx Ingress暴露Dashboard [TOC] 1. 环境说明 可用的kubernetes集群 可用的nginx ingress controller 可用的dashboard 关于kubernetes.dashboard和nginx ingress在前面文章中,已有介绍. <centos7使用kubeadm安装kubernetes 1.11版本多主高可用> <kubernetes 1.11配置使用nginx ingress> 也可以使用hel

[系统集成] 用 Kubernetes Nginx Ingress 实现 HTTP 服务发布与负载均衡

用户在 Kubernetes 上部署的服务一般运行于私有网络,Pod和Service 提供了 hostPort,NodePort等参数用于暴露这些服务端口到K8S节点上,供使用者访问.这样的方法有明显缺点: 1)容易占用过多的主机端口: 2)服务端口暴露到多台主机会增加防火墙和安全配置的难度 3)默认的hostPort,NodePort方式没有负载均衡的作用 K8S的 Ingress 资源提供了另一种服务暴露的方法,它可以获取各个服务的状态,传递给nginx等工具进行配置修改.重新加载等工作,实

kubernetes nginx ingress 使用记录

前言 ingress是一种可以暴露k8s集群内部service的方式,用户编辑配置文件定义一个ingress资源即可实现外部网络访问内网service. ingress controller是来管理所有的Ingress的对象,ingress controller内部其实是一个nginx的容器,当ingress controll 通过与 Kubernetes API 交互,感知集群中Ingress规则变化时会按照模板文件生成nginx.conf文件,然后reload该配置文件. 相对于kubern

k8s部署ingress及http、https-实战篇

一.简介ingress:ingress-nginx #用于实现反代https://kubernetes.github.io/ingress-nginx/deploy/#generic-deployment kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yamlhttps://kubernetes.github.io/ingress-nginx/

k8s的ingress使用

ingress 可以配置一个入口来提供k8s上service从外部来访问的url.负载平衡流量.终止SSL和提供基于名称的虚拟主机. 配置ingress的yaml: 要求域名解析无误 要求service对应的pod正常 一.test1.domain.com   -->  service1:8080 apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test-ingress namespace: test spec: rule