第9章:Ingress
9.1 Ingress为弥补NodePort不足而生
1 单独用service暴露服务的方式,在实际生产环境中不太合适
ClusterIP 只能在集群内部访问。
NodePort 方式的话,测试环境使用还行,当有几十上百的服务在集群中运行时,NodePort的端口管理是灾难。
LoadBalance 方式受限于云平台,且通常在云平台部署ELB还需要额外的费用。
2 ingress与ingress-controller
ingress对象: 指的是k8s中的一个api对象,一般用yaml配置。作用是定义请求如何转发到service的规则,可以理解为配置模板。
ingress-controller:具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发。简单来说,ingress-controller才是负责具体转发的组件,通过各种方式将它暴露在集群入口,外部对集群的请求流量会先到ingress-controller,而ingress对象是用来告诉ingress-controller该如何转发请求,比如哪些域名哪些path要转发到哪些服务等等。Ingress Controller会动态感知集群中的Ingress的规则变化,然后读取,动态生成Nginx的配置文件,最后注入到运行nginx的pod的中,然后会自动reload,配置生效。
3 k8s真正提供服务的是pod,为了负载均衡,为了使用域名, service 诞生了,然后 ingress 诞生了,那么Ingress的作用如下
(1) 帮助位于集群中的Service能够有一个对外可达的url,即让集群外的客户端也可以访问到自己。(对于这一点,NodePort类型的Service可以实现,只支持4层负载均衡,一个端口只能一个服务使用,端口需提前规划
)
(2) 做专业的负载均衡,毕竟Service的负载均衡还是很初级的
4 Ingress工作流程
如下图所示,流量到达外部负载均衡器(externalLB
)后,首先转发至Service
资源Ingres-nginx
上,然后通过Ingress
控制器基于Ingress
资源定义的规则将客户端请求流量直接转发至与Service
对应的后端Pod
资源之上。这种转发机制会绕过Service
资源(app Service
;api Service
),从而省去了由kube-proxy
实现的端口代理开销。Ingress
规则需要由一个Service
资源对象辅助识别相关的所有Pod
资源。如下Ingress
通过app service
资源去匹配后端的pod1
和pod2
;这个app service
只是起到一个辅助识别功能。
user -> 域名 -> node ip:80/443 -> ingress controller -> 域名分流 –> pod
ingress controller pod -> 获取service(apiserver)关联的pod -> 应用到本地nginx(提供七层负载均衡)
因为是DaemoSet方式部署的ingress controller, 所以除master节点外每个从node节点都会部署一个ingress controller的pod并监听80和443端口。
9.2 Pod与Ingress的关系
通过Service相关联
通过Ingress Controller实现Pod的负载均衡
支持TCP/UDP 4层和HTTP 7层
9.3 Ingress Controller
为了使Ingress资源正常工作,集群必须运行一个Ingress Controller(负载均衡实现)。
所以要想通过ingress暴露你的应用,大致分为两步:
部署Ingress Controller
创建Ingress规则
整体流程如下:
Ingress Controller有很多实现,我们这里采用官方维护的Nginx控制器。
其他主流控制器:(1) Traefik: HTTP反向代理、负载均衡工具 (2) Istio:服务治理,控制入口流量
部署文档:https://github.com/kubernetes/ingress-nginx/blob/nginx-0.30.0/docs/deploy/index.md
# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
注意事项:
- 镜像地址修改成国内的(国外的源无法连接):lizhenliang/nginx-ingress-controller:0.20.0
- 使用宿主机网络(提高网络转发性能):hostNetwork: true
# vim mandatory.yaml
......
spec:
hostNetwork: true
serviceAccountName: nginx-ingress-serviceaccount
containers:
- name: nginx-ingress-controller
image: lizhenliang/nginx-ingress-controller:0.20.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
......
# kubectl apply -f mandatory.yaml
# kubectl get pods -n ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-ingress-controller-9r25t 1/1 Running 0 5m16s 172.16.1.71 k8s-node1
nginx-ingress-controller-p8g66 1/1 Running 0 5m16s 172.16.1.72 k8s-node2
# 查看ingress-controller中的nginx配置文件
# kubectl exec -it nginx-ingress-controller-9r25t sh -n ingress-nginx
$ ls /etc/nginx/nginx.conf
/etc/nginx/nginx.conf
$
# 此时在任意Node上就可以看到该控制监听的80和443端口,80和443端口就是接收来自外部访问集群中应用流量,转发对应的Pod上
# netstat -natp |egrep ":80|:443"
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 83841/nginx: master
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 83841/nginx: master
9.4 Ingress
接下来,就可以创建ingress规则了。
在ingress里有三个必要字段:
host: 访问该应用的域名,也就是域名解析
serverName: 应用的service名称
serverPort: service端口
1、HTTP访问
# vim http.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-lc-ingress
spec:
rules:
- host: example.lc.com
http:
paths:
- path: /
backend:
serviceName: nginx
servicePort: 80# kubectl apply -f http.yaml
# kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
example-lc-ingress example.lc.com 80 47s
# 添加windows本地hosts解析
C:\Windows\System32\drivers\etc\hosts
172.16.1.71 example.lc.com
# 使用域名访问
http://example.lc.com/
注意:
(1) 生产环境:example.lc.com 域名是在你购买域名的运营商上进行解析,A记录值为K8S Node的公网IP(该Node必须运行了Ingress controller)。
(2) 测试环境:可以绑定hosts模拟域名解析("C:\Windows\System32\drivers\etc\hosts"),对应IP是K8S Node的内网IP。例如:
172.16.1.71 example.lc.com
2、HTTPS访问
# vim sslhttp.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: sslexample-lc-ingress
spec:
tls:
- hosts:
- sslexample.lc.com
secretName: sslexample-lc-com
rules:
- host: sslexample.lc.com
http:
paths:
- path: /
backend:
serviceName: nginx
servicePort: 80# kubectl apply -f sslhttp.yaml
# kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
sslexample-lc-ingress sslexample.lc.com 80, 443 8s
里面用到了secret名为example-lc-com,用于保存https证书。这里使用cfssl工具自签证书用于测试,先下载cfssl工具:
# cat cfssl.sh
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl*
mv cfssl_linux-amd64 /usr/bin/cfssl
mv cfssljson_linux-amd64 /usr/bin/cfssljson
mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo
# cat certs.sh
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF cat > ca-csr.json <<EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"ST": "Beijing"
}
]
}
EOF cfssl gencert -initca ca-csr.json | cfssljson -bare ca - cat > sslexample.lc.com-csr.json <<EOF
{
"CN": "sslexample.lc.com",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing"
}
]
}
EOF cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes sslexample.lc.com-csr.json | cfssljson -bare sslexample.lc.com执行certs.sh脚本,生成证书:
# sh certs.sh
# ls *.pem
ca-key.pem ca.pem sslexample.lc.com-key.pem sslexample.lc.com.pem
将证书保存在secret里:
# kubectl create secret tls sslexample-lc-com --cert=sslexample.lc.com.pem --key=sslexample.lc.com-key.pem
# kubectl get secret
NAME TYPE DATA AGE
default-token-wc5fp kubernetes.io/service-account-token 3 13d
sslexample-lc-com kubernetes.io/tls 2 16s
# kubectl describe secrets sslexample-lc-com
这样,ingress就能通过secret名称拿到要用的证书了,然后绑定本地hosts,就可以https访问了:https://sslexample.lc.com/
3、根据URL路由到多个服务
# vim url.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: url-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: foobar.lc.com
http:
paths:
- path: /foo
backend:
serviceName: service1
servicePort: 80
- host: foobar.lc.com
http:
paths:
- path: /bar
backend:
serviceName: service2
servicePort: 80工作流程:
foobar.lc.com -> 172.16.1.71 -> /foo service1:80
/bar service2:80
4、基于名称的虚拟主机
# vim vhost.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.lc.com
http:
paths:
- backend:
serviceName: service1
servicePort: 80
- host: bar.lc.com
http:
paths:
- backend:
serviceName: service2
servicePort: 80工作流程:
foo.lc.com --| |-> service1:80
| 172.16.1.71 |
bar.lc.com --| |-> service2:80
9.5 Annotations对Ingress个性化配置
HTTP:配置Nginx常用参数
# vim nginx_parameter.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-ingress
annotations:
kubernetes.io/ingress.class: "nginx“
nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
spec:
rules:
- host: example.lc.com
http:
paths:
- path: /
backend:
serviceName: nginx
servicePort: 80HTTPS:禁止访问HTTP强制跳转到HTTPS(创建https后通过http访问默认会跳转到https)
# vim redirect_https.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: tls-example-ingress
annotations:
kubernetes.io/ingress.class: "nginx“
nginx.ingress.kubernetes.io/ssl-redirect: 'true'
spec:
tls:
- hosts:
- sslexample.lc.com
secretName: secret-tls
rules:
- host: sslexample.lc.com
http:
paths:
- path: /
backend:
serviceName: nginx
servicePort: 80
9.6 Ingress Controller高可用方案
如果域名只解析到一台Ingress controller,是存在单点的,挂了就不能提供服务了。这就需要具备高可用,有两种常见方案:
左边:双机热备,选择两台Node专门跑Ingress controller,然后通过keepalived对其做主备。用户通过VIP访问。
固定ingress controller到两个node上(daemonset+nodeselector),user -> 域名 -> vip(keepalived) ha -> pod
右边:高可用集群(推荐),前面加一个负载均衡器,转发请求到后端多台Ingress controller。
固定ingress controller到两个node上(daemonset+nodeselector),user -> 域名 -> LB(nginx、lvs、haproxy)-> ingress controller -> pod
第9章:Ingress的更多相关文章
- 【译文连载】 理解Istio服务网格(第一章 概述)
书籍英文版下载链接为 https://developers.redhat.com/books/introducing-istio-service-mesh-microservices/,作者 Burr ...
- 【译文连载】 理解Istio服务网格(第三章 流控)
第3章 流控.............................................................................................. ...
- 【译文连载】 理解Istio服务网格(第七章 安全)
全书目录 第一章 概述 第二章 安装 第三章 流控 第四章 服务弹性 第五章 混沌测试 第六章 可观测性 本文目录 第7章 安全 7.1 身份认证 7.1.1 Kubernetes上的Istio的身份 ...
- 第一章 Kubernetes入门
第一章 Kubernetes入门 kubernetes是基于容器技术的分布式架构领先方案,是一个完备的分布式系统支撑平台. kubernetes带来的好处:1)全面拥抱微服务:2)统可以随时随地整体“ ...
- k8s ingress - traefik
前面提到过 k8s 的 ingress 有 ingress-nginx,traefik,haproxy 等多种.今天来实践一下 tarefik. 闲言少叙,直接上代码. # cat traefik.y ...
- kubernetes进阶(四)服务暴露-ingress控制器之traefik
上一章我们测试了在集群内部解析service名称, 下面我们测试在集群外部解析: 根本解析不到,因为我们外部用的dns是10.4.7.11,也就是我们的自建bind dns,这个DNS服务器上也没有响 ...
- 云原生入门 第五章:kubernetes学习实践
1. 简介 在本章中,我们将学习不同的Kubernetes对象,它们的用途以及如何与它们交互. 在设置集群或使用现有集群之后,我们可以开始部署一些工作负载.Kubernetes中最小的计算单元不是一个 ...
- 《Streaming Systems》第三章: Watermarks
定义 对于一个处理无界数据流的 pipeline 而言,非常需要一个衡量数据完整度的指标,用于标识什么时候属于某个窗口的数据都已到齐,窗口可以执行聚合运算并放心清理,我们暂且就给它起名叫 waterm ...
- 云原生之旅 - 9)云原生时代网关的后起之秀Envoy Proxy 和基于Envoy 的 Emissary Ingress
前言 前一篇文章讲述了基于Nginx代理的Kuberenetes Ingress Nginx[云原生时代的网关 Ingress Nginx]这次给大家介绍下基于Envoy的 Emissary Ingr ...
随机推荐
- [Qt] Librecad 源码分析
libraries jwwlib libdxfrw:一个免费的C++库,用于读写文本格式或二进制格式的DXF文件(C++ library to read and write DXF/DWG files ...
- QT windows 应用程序 exe ,设置详细信息并解决中文乱码问题
原博主:https://blog.csdn.net/xiezhongyuan07/article/details/87691490 1.新创建一个.rc文件,随意命名,例如叫app.rc 并编辑 1 ...
- Installing SFTP/SSH Server on Windows using OpenSSH
Installing SFTP/SSH Server 1. On Windows 10 version 1803 and newer In Settings app, go to Apps > ...
- Linux_控制服务与守护进程
一.systemd 1.systemd简介 1️⃣:systemd是用户空间的第一个应用程序,即/sbin/init 2️⃣:init程序的类型: SysV风格:init(centos5),实现系统初 ...
- 云计算OpenStack核心组件---nova计算服务(7)
一.nova介绍 Nova 是 OpenStack 最核心的服务,负责维护和管理云环境的计算资源.OpenStack 作为 IaaS 的云操作系统,虚拟机生命周期管理也就是通过 Nova 来实现的. ...
- dd命令详解-(转自dkcndk)
Linux-dd命令详解 dd 是 Linux/UNIX 下的一个非常有用的命令,作用是用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换.名称: dd 使用权限: 所有使用者dd 这个指令在 ...
- lua table的遍历
--ordered table iterator sorted by key function pairsByKeys(t) local a = {} for n in pairs(t) do a[# ...
- 贪心算法leetcode-763
int[] lastShow = new int[26]; var list = new LinkedList<Integer>(); for (int i = 0; i < s.l ...
- TODO不实现会报错
kotlin.NotImplementedError: An operation is not implemented: Not yet implemented 会发生--当你 override fu ...
- LIN总线多从机与主机通信(控制+反馈)
概念 首先要明确以下两点: LIN 总线通信方式为主从机通信,属于异步通信 "帧头 + 数据帧"才算一完整报文 设计方案 多从机与主机通信数据流(控制+反馈)如下: 一号从机: 第 ...