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 Serviceapi Service),从而省去了由kube-proxy实现的端口代理开销。Ingress规则需要由一个Service资源对象辅助识别相关的所有Pod资源。如下Ingress通过app service资源去匹配后端的pod1pod2;这个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暴露你的应用,大致分为两步:

  1. 部署Ingress Controller

  2. 创建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个性化配置

参考文档 :https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md

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: 80

HTTPS:禁止访问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的更多相关文章

  1. 【译文连载】 理解Istio服务网格(第一章 概述)

    书籍英文版下载链接为 https://developers.redhat.com/books/introducing-istio-service-mesh-microservices/,作者 Burr ...

  2. 【译文连载】 理解Istio服务网格(第三章 流控)

    第3章 流控.............................................................................................. ...

  3. 【译文连载】 理解Istio服务网格(第七章 安全)

    全书目录 第一章 概述 第二章 安装 第三章 流控 第四章 服务弹性 第五章 混沌测试 第六章 可观测性 本文目录 第7章 安全 7.1 身份认证 7.1.1 Kubernetes上的Istio的身份 ...

  4. 第一章 Kubernetes入门

    第一章 Kubernetes入门 kubernetes是基于容器技术的分布式架构领先方案,是一个完备的分布式系统支撑平台. kubernetes带来的好处:1)全面拥抱微服务:2)统可以随时随地整体“ ...

  5. k8s ingress - traefik

    前面提到过 k8s 的 ingress 有 ingress-nginx,traefik,haproxy 等多种.今天来实践一下 tarefik. 闲言少叙,直接上代码. # cat traefik.y ...

  6. kubernetes进阶(四)服务暴露-ingress控制器之traefik

    上一章我们测试了在集群内部解析service名称, 下面我们测试在集群外部解析: 根本解析不到,因为我们外部用的dns是10.4.7.11,也就是我们的自建bind dns,这个DNS服务器上也没有响 ...

  7. 云原生入门 第五章:kubernetes学习实践

    1. 简介 在本章中,我们将学习不同的Kubernetes对象,它们的用途以及如何与它们交互. 在设置集群或使用现有集群之后,我们可以开始部署一些工作负载.Kubernetes中最小的计算单元不是一个 ...

  8. 《Streaming Systems》第三章: Watermarks

    定义 对于一个处理无界数据流的 pipeline 而言,非常需要一个衡量数据完整度的指标,用于标识什么时候属于某个窗口的数据都已到齐,窗口可以执行聚合运算并放心清理,我们暂且就给它起名叫 waterm ...

  9. 云原生之旅 - 9)云原生时代网关的后起之秀Envoy Proxy 和基于Envoy 的 Emissary Ingress

    前言 前一篇文章讲述了基于Nginx代理的Kuberenetes Ingress Nginx[云原生时代的网关 Ingress Nginx]这次给大家介绍下基于Envoy的 Emissary Ingr ...

随机推荐

  1. jQ的显式迭代和隐式迭代

    jQ的显示迭代 隐式迭代 let lis = document.querySelector('li') lis.forEach(function (value, index) { value.styl ...

  2. golang:Channel协程间通信

    channel是Go语言中的一个核心数据类型,channel是一个数据类型,主要用来解决协程的同步问题以及协程之间数据共享(数据传递)的问题.在并发核心单元通过它就可以发送或者接收数据进行通讯,这在一 ...

  3. [bug] IDEA:application context not configured for this file

    参考 https://blog.csdn.net/a772304419/article/details/79680833

  4. [bug] Python AttributeError: module 'web' has no attribute 'application'

    原因 文件名是web.py,与包名web冲突 解决 重命名文件,再运行

  5. head元素的内容

    一.head元素 head元素的内容用来向浏览器提供一些文档信息,此外还可以包含js脚本和css层叠样式单.head中一般包含title.meta.css.js等内容,head中元素的内容在浏览器中不 ...

  6. 安装SpecCPU2006 on Linux of CentOS6.3, gcc4.4.7

    安装SpecCPU2006 on Linux of CentOS6.3, gcc4.4.7 由于在tools/bin目录中只有ia64-linux,所以在直接运行./install.sh脚本时,系统会 ...

  7. Linux_搭建NFS服务(基础)

    [RHEL8]-NFSserver :[Centos7]-NFSclient !!!测试环境我们首关闭防火墙和selinux(NFSserver和NFSclient都需要) [root@localho ...

  8. Jmeter(四十九) - 从入门到精通高级篇 - jmeter使用监视器结果监控tomcat性能(详解教程)

    1.简介 上一篇宏哥讲解了利用jmeter的插件来监控服务器资源,这一篇讲解分享如何使用jmeter的监视器结果监控tomcat性能. 2.准备工作 文章标题中提到jmeter和tomcat,那么只需 ...

  9. git&nodejs安装教程

    git https://www.cnblogs.com/ximiaomiao/p/7140456.html nodejs https://jingyan.baidu.com/article/e7505 ...

  10. Docker学习(4) 守护式容器

    守护式容器 stop - 等待信号 kill - 直接干死