Ingress学习笔记
Ingress
我们已经知道,Service对集群之外暴露服务的主要方式有两种:NodePort和LoadBalancer,但是这两种方式,都有一定的缺点:
- NodePort方式的缺点是会占用很多集群机器的端口,那么当集群服务变多的时候,这个缺点就愈发明显。
- LoadBalancer的缺点是每个Service都需要一个LB,浪费,麻烦,并且需要Kubernetes之外的设备的支持。
基于这种现状,Kubernetes提供了Ingress资源对象,Ingress只需要一个NodePort或者一个LB就可以满足暴露多个Service的需求,工作机制大致如下图所示:

实际上,Ingress相当于一个七层的负载均衡器,是Kubernetes对反向代理的一个抽象,它的工作原理类似于Nginx,可以理解为Ingress里面建立了诸多映射规则,Ingress Controller通过监听这些配置规则并转化为Nginx的反向代理配置,然后对外提供服务。
- Ingress:Kubernetes中的一个对象,作用是定义请求如何转发到Service的规则。
- Ingress Controller:具体实现反向代理及负载均衡的程序,对Ingress定义的规则进行解析,根据配置的规则来实现请求转发,实现的方式有很多,比如Nginx,Contour,Haproxy等。
NGINX Ingress Controller
NGINX Ingress Controller 是使用 Kubernetes Ingress 资源对象构建的,用 ConfigMap 来存储 Nginx 配置的一种 Ingress Controller 实现。
要使用 Ingress 对外暴露服务,就需要提前安装一个 Ingress Controller,我们这里就先来安装 NGINX Ingress Controller,由于 nginx-ingress 所在的节点需要能够访问外网,这样域名可以解析到这些节点上直接使用,所以需要让 nginx-ingress 绑定节点的 80 和 443 端口,所以可以使用 hostPort 来进行访问,当然对于线上环境来说为了保证高可用,一般是需要运行多个 nginx-ingress 实例的,然后可以用一个 nginx/haproxy 作为入口,通过 keepalived 来访问边缘节点的 vip 地址。
边缘节点
所谓的边缘节点即集群内部用来向集群外暴露服务能力的节点,集群外部的服务通过该节点来调用集群内部的服务,边缘节点是集群内外交流的一个Endpoint。
接下来我们准备资源清单文件:(点击直接获取资源文件)
$ wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
$ vim mandatory.yaml
......
spec:
# wait up to five minutes for the drain of connections
terminationGracePeriodSeconds: 300
serviceAccountName: nginx-ingress-serviceaccount
tolerations: # 由于我这里的边缘节点只有master一个节点,所有需要加上容忍
- operator: "Exists"
nodeSelector:
kubernetes.io/hostname: master # master节点
containers:
- name: nginx-ingress-controller
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
args:
- /nginx-ingress-controller
- --configmap=$(POD_NAMESPACE)/nginx-configuration
- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
- --udp-services-configmap=$(POD_NAMESPACE)/udp-services
- --publish-service=$(POD_NAMESPACE)/ingress-nginx
- --annotations-prefix=nginx.ingress.kubernetes.io
securityContext:
allowPrivilegeEscalation: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
# www-data -> 101
runAsUser: 101
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- name: http
hostPort: 80 # 使用hostPort
containerPort: 80
protocol: TCP
- name: https
hostPort: 443 # 使用hostPort
containerPort: 443
protocol: TCP
......
$ kubectl apply -f mandatory.yaml
安装后,会将 NGINX Ingress Controller 安装在一个统一的 ingress-nginx 的 namespace 下面:
$ kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-5c5b7696df-mt47r 1/1 Running 0 6m23s
安装完成后,我们可以在 controller 的 Pod 所在节点,也就是master节点上使用如下方式进行验证:
$ curl 127.0.0.1
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.17.8</center>
</body>
</html>
出现了上面的信息证明 Ingress Controller 已经安装成功。
Ingress
安装成功后,现在我们来为一个 nginx 应用创建一个 Ingress 资源,如下所示:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
app: my-nginx
template:
metadata:
labels:
app: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
app: my-nginx
spec:
ports:
- port: 80
protocol: TCP
name: http
selector:
app: my-nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-nginx
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: ngdemo.negan.com # 将域名映射到 my-nginx 服务
http:
paths:
- path: /
backend:
serviceName: my-nginx # 将所有请求发送到 my-nginx 服务的 80 端口
servicePort: 80 # 不过需要注意大部分Ingress controller都不是直接转发到Service
# 而是只是通过Service来获取后端的Endpoints列表,直接转发到Pod,这样可以减少网络跳转
# 提高性能
注意我们在 Ingress 资源对象中添加了一个 annotations:kubernetes.io/ingress.class: "nginx",这就是指定让这个 Ingress 通过 nginx-ingress 来处理。
上面资源创建成功后,然后我们可以将域名ngdemo.negan.com解析到nginx-ingress所在的边缘节点中的任意一个,当然也可以在本地/etc/hosts中添加对应的映射也可以,然后就可以通过域名进行访问了。

下图显示了客户端是如果通过 Ingress Controller 连接到其中一个 Pod 的流程,客户端首先对 ngdemo.negan.com 执行 DNS 解析,得到 Ingress Controller 所在节点的 IP,然后客户端向 Ingress Controller 发送 HTTP 请求,然后根据 Ingress 对象里面的描述匹配域名,找到对应的 Service 对象,并获取关联的 Endpoints 列表,将客户端的请求转发给其中一个 Pod。

HTTPS
如果我们需要用 HTTPS 来访问我们这个应用的话,就需要监听 443 端口了,同样用 HTTPS 访问应用必然就需要证书,这里我们用 openssl 来创建一个自签名的证书:
$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=BJ/L=BJ/O=nginx/CN=negan.com"
然后通过 Secret 对象来引用证书文件:
$ kubectl create secret tls tls-secret --key tls.key --cert tls.crt
secret/tls-secret created
这个时候我们就可以创建一个 HTTPS 访问应用的:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-https
spec:
rules:
- host: foo.negan.com
http:
paths:
- path: /
backend:
serviceName: my-nginx
servicePort: 80
tls:
- hosts:
- foo.negan.com
secretName: tls-secret
创建完成后进行查看:
$ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-https <none> foo.negan.com 80, 443 27s
my-nginx <none> ngdemo.negan.com 80 50m
$ kubectl describe ingress ingress-https
Name: ingress-https
Namespace: default
Address:
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
TLS:
tls-secret terminates foo.negan.com
Rules:
Host Path Backends
---- ---- --------
foo.negan.com
/ my-nginx:80 (10.244.1.9:80)
Annotations: Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal CREATE 102s nginx-ingress-controller Ingress default/ingress-https
同样我们可以将域名foo.negan.com在本地/etc/hosts中添加对应的映射,然后就可以通过域名进行访问了。

Basic Auth
同样我们还可以在 Ingress Controller 上面配置一些基本的 Auth 认证,比如 Basic Auth,可以用 htpasswd 生成一个密码文件来验证身份验证。
$ htpasswd -c auth foo
New password:
Re-type new password:
Adding password for user foo
然后根据上面的 auth 文件创建一个 secret 对象:
$ kubectl create secret generic basic-auth --from-file=auth
secret/basic-auth created
$ kubectl get secret basic-auth -o yaml
apiVersion: v1
data:
auth: Zm9vOiRhcHIxJGRiQ3ZFd3JFJFp4UDhkSXltZFNWV3RlQlVOa0RJby8K
kind: Secret
metadata:
creationTimestamp: "2022-01-06T14:32:25Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:auth: {}
f:type: {}
manager: kubectl
operation: Update
time: "2022-01-06T14:32:25Z"
name: basic-auth
namespace: default
resourceVersion: "88611"
selfLink: /api/v1/namespaces/default/secrets/basic-auth
uid: 7578bd2f-a75d-4ae6-b081-41c7524340a0
type: Opaque
对上面的 my-nginx 应用创建一个具有 Basic Auth 的 Ingress 对象:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-with-auth
annotations:
# 认证类型
nginx.ingress.kubernetes.io/auth-type: basic
# 包含 user/password 定义的 secret 对象名
nginx.ingress.kubernetes.io/auth-secret: basic-auth
# 要显示的带有适当上下文的消息,说明需要身份验证的原因
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo'
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /
backend:
serviceName: my-nginx
servicePort: 80
直接创建上面的资源对象,在浏览器中直接打开配置的域名:

输入我们设置的用户名和密码进行访问:

Ingress学习笔记的更多相关文章
- OpenFlow Switch学习笔记(五)——Group Table、Meter Table及Counters
本文主要详述OpenFlow Switch的另外两个主要组件——Group Table和Meter Table,它们在整个OpenFlow Swtich Processing中也起到了重要作用. 1. ...
- OpenFlow Switch学习笔记(四)——Matching
这次我们着重详述来自于网络中的数据包在OpenFlow Switch中与Flow Entries的具体匹配过程,以及当出现Table Miss时的处理方式,下面就将从这两方面说起. 1.Matchin ...
- OpenFlow Switch学习笔记(一)——基础概念
OpenFlow Switch v1.4.0规范是在2013年10月14号发布,规范涵盖了OpenFlow Switch各个组件的功能定义.Controller与Switch之间的通信协议Open F ...
- Docker技术入门与实战 第二版-学习笔记-8-网络功能network-3-容器访问控制和自定义网桥
1)容器访问控制 容器的访问控制,主要通过 Linux 上的 iptables防火墙来进行管理和实现. iptables是 Linux 上默认的防火墙软件,在大部分发行版中都自带. 容器访问外部网络 ...
- Contour 学习笔记(一):使用 Contour 接管 Kubernetes 的南北流量
原文链接:Contour 学习笔记(一):使用 Contour 接管 Kubernetes 的南北流量 在 Kubernetes 中运行大规模以 Web 为中心的工作负载,最关键的需求之一就是在 L7 ...
- Kubernetes 学习笔记(一):基础概念
个人笔记,仅本人查阅使用,不保证正确. 零.微服务 微服务架构专注于应用解耦合,通过将应用彻底地组件化和服务化,每个微服务只包含一个非常小的功能,比如权限管理.日志收集等等.由这一组微服务组合起来,提 ...
- Docker Stack 学习笔记
该文为<深入浅出Docker>的学习笔记,感谢查看,如有错误,欢迎指正 一.简介 Docker Stack 是为了解决大规模场景下的多服务部署和管理,提供了期望状态,滚动升级,简单易用,扩 ...
- Kubernetes学习笔记(四):服务
服务介绍 服务是一种为一组相同功能的pod提供单一不变接入点的资源.当服务存在时,他的IP和端口不会改变.客户端通过IP和端口建立连接,这些连接会被路由到任何一个pod上.如此,客户端不需要知道每个单 ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
随机推荐
- 鸿蒙WebSocket的使用竟如此简单
使用WebSocket建立服务器与客户端的双向连接,需要先通过createWebSocket()方法创建WebSocket对象,然后通过connect()方法连接到服务器.当连接成功后,客户端会收到o ...
- css px em rem % vw vh vm 区别
前言 在传统项目开发中,我们只会用到 px.%.em 这几个单位长度,它们可以适用大部分项目的开发,并且拥有较好的兼容性. 而从 css3 开始,浏览器对逻辑单位的支持又提升了新的境界,增加了 rem ...
- 一款HTML转Markdown格式的工具
Markdown格式不仅对写博客的人非常友好和方便,对AI也是如此. 目前AI大语言模型的输出基本都是Markdown格式,这就意味着AI是能充分理解Markdown格式的,这一点非常重要. Mark ...
- Joker 智能开发平台:低代码开发的革新力量
在软件开发领域,开发效率与灵活性始终是开发者们追求的核心目标.随着技术的迅猛发展,低代码开发平台逐渐成为行业焦点,而 Joker 智能开发平台凭借其卓越的性能和创新的功能,脱颖而出,为开发者们带来了前 ...
- 变异凯撒-python脚本调整ascii码转字符串
题目: 加密密文:afZ_r9VYfScOeO_UL^RWUc 格式:flag{ } 结合题目变异凯撒,第一个字符a到f加了5,第二个字符f到l加了6,推断每个字符都在前一个字符基础上+1. 编写py ...
- 使用键盘控制gazebo小车模型运动
博客地址:https://www.cnblogs.com/zylyehuo/ gazebo小车模型创建详见另一篇博客 博客地址:gazebo小车模型(附带仿真环境) - zylyehuo - 博客园 ...
- Crealens.ai 免费体验GPT-4o 生图+吉卜力风格化
自己的一张日常照片,能在几秒内变身为一幅充满童话感的吉卜力风插画?90%的人不知道,如今只需一句话,就能在 ChatGPT 里实现"AI 生图"--这就是 GPT-4o 生图功能的 ...
- AI数字人Heygem:口播与唇形同步的福音,无需docker,无需配置环境,一键整合包来了
介绍 短短72小时,硅基智能在GitHub开源的数字人模型Heygem.ai便突破1,300颗Star,迅速成为全球技术社区瞩目的焦点.这一现象级的增长速度不仅彰显了Heygem.ai的技术领先性,更 ...
- 【ESP32】移植 Arduino 库到 idf 项目中
今天咱们要聊的内容非常简单,所以先扯点别的.上一篇水文中,老周没能将 TinyUSB 的源码编译进 Arduino 中,心有两百万个不甘,于是清明节的时候再试了一次,居然成功了,已经在 esp32 开 ...
- 基于AST实现国际化文本提取
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:霜序 前言 在阅读本文之前,需要读者有一些 babel 的 ...