本文最后更新于 321 天前,其中的信息可能已经过时,如有错误请发送邮件到wuxianglongblog@163.com
K8S的网络访问进阶篇
一.K8S集群的外部服务映射
1.在集群外部部署MySQL服务
(1)安装MySQL服务端
yum -y install mariadb-server
(2)启动MySQL服务并配置开机自启动
systemctl start mariadb.service && systemctl enable mariadb.service
(3)进行安全初始化,按照脚本的提示操作即可
mysql_secure_installation
(4)创建授权用户,下面的方式仅适合MySQL 5.7及以下版本,MySQL 8.0不允许下面的语法(我们课堂有说过)
GRANT ALL ON *.* TO root@'%' IDENTIFIED BY '123456';
'root'@'k8s203.oldboyedu.com'
温馨提示:
上面的用户名和密码不建议修改,因为下面我们用的tomcat案例中的配置文件已经将密码写死了!
2.准备环境,将tomcat应用部署到K8S集群
(1)部署mysql服务
cat > 01-mysql-deploy.yml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: oldboyedu-db-mysql57
spec:
replicas: 1
selector:
matchLabels:
app: oldboyedu-mysql57
template:
metadata:
labels:
app: oldboyedu-mysql57
spec:
containers:
- name: mysql
image: k8s101.oldboyedu.com:5000/mysql:5.7
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: '123456'
EOF
(2)编写mysql的svc资源
cat > 02-mysql-svc.yml << EOF
apiVersion: v1
kind: Service
metadata:
name: oldboyedu-db-mysql57-svc
spec:
ports:
- port: 3306
targetPort: 3306
selector:
app: oldboyedu-mysql57
EOF
(3)编写tomcat的资源
cat 03-tomcat-deploy.yml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: oldboyedu-web-tomcat-app
spec:
replicas: 1
selector:
matchLabels:
app: oldboyedu-tomcat-app
template:
metadata:
labels:
app: oldboyedu-tomcat-app
spec:
containers:
- name: myweb
image: k8s101.oldboyedu.com:5000/tomcat-app:v1
ports:
- containerPort: 8080
env:
- name: MYSQL_SERVICE_HOST
value: oldboyedu-db-mysql57-svc
- name: MYSQL_SERVICE_PORT
value: '3306'
EOF
(4)编写tomcat的svc
cat > 04-tomcat-svc.yml << EOF
apiVersion: v1
kind: Service
metadata:
name: oldboyedu-web-tomcat-app-svc
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30008
selector:
app: oldboyedu-tomcat-app
EOF
(5)应用配置文件
应用后,可以访问WebUI,如下图所示。
温馨提示:
上面的是我基于k8s1.22版本的案例,如果使用的是K8S1.15版本需要自行修改哟~
3.修改配置文件
(1)删除mysql的deployment和svc资源
kubectl delete -f 01-mysql-deploy.yml -f 02-mysql-svc.yml
(2)创建endpoint
cat > 01-mysql_endpoint.yaml << EOF
apiVersion: v1
kind: Endpoints
metadata:
name: oldboyedu-db-mysql57-svc
subsets:
- addresses:
- ip: 10.0.0.205
ports:
- name: mysql
port: 3306
protocol: TCP
EOF
(3)创建svc
cat > 02-mysql_svc.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
name: oldboyedu-db-mysql57-svc
spec:
ports:
- name: mysql
port: 3306
protocol: TCP
targetPort: 3306
type: ClusterIP
EOF
温馨提示:
(1)Endpoints和Service资源的名称必须一致,因为默认情况下,svc只关联同名的ep资源哟;
(2)tomcat服务指向的数据库名称必须和我们定义的svc名称也要相同哟;
二.修改kube-proxy的工作模式为ipvs模式
1.查看kube-proxy的工作模式
如上图所示,我们随机找了任意一个节点的kube proxy的pod查看其默认的yaml格式。
kubectl get pod -n kube-system kube-proxy-hb78n -o yaml
如下图所示,volumes挂载的是configMap资源哟。而configMap资源中有定义kube-proxy的网络工作模式。
如果configMap资源的"mode"为空,则kube-proxy的工作模式默认使用iptables规则哟。
温馨提示:
生产环境中建议大家使用ipvs规则来替代传统的iptables。
如下图所示,如果对上面的结果你还有所怀疑的话,别着急,各个节点的kube proxy的Pod日志也会有记录哟~
2.K8S集群所有节点安装ipvs组件并启动服务
(1)安装服务ipvs服务
yum -y install conntrack-tools ipvsadm.x86_64
(2)加载lvs内核模块
cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
(3)查看内核模式
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4
3.修改集群的工作模式为ipvs
如下图图所示,编辑名为"kube-proxy"的configMap资源,将mode的值改为"ipvs"
kubectl edit cm kube-proxy -n kube-system
4.删除旧的kube-proxy的pod
如下图所示,当我们删除旧的Pod后,会自动拉起新的Pod哟~
5.验证资源
(1)查看新启动的kube-proxy组件的Pod日志
如下图所示,我们可以通过查看Pod日志来分析。
(2)测试验证kube-proxy是否正常工作
我们可以使用curl测试访问某个web页面以观察Pod是否正常工作。
温馨提示:
(1)建议将tomcat的pod扩容先扩容为3个,然后使用curl命令进行测试比较明显哟;
(2)当然,也可以配合使用"ipvsadm -l -n"查看调度策略哟~
三.主流的Ingress控制器开源产品概述
1.Ingress和Ingress Controller概述
我们在此之前已经学习过使用service的NodePort类型实现对外部暴漏端口。但NodePort的确是存在以下两个不足之处:
(1)一个端口只能由一个服务使用,因此在生产环境中端口需要提前规划;
(2)无论是iptables还是ipvs只支持四层的负载均衡,即基于IP地址转发;
Ingress:
kubernetes中的一个抽象资源,给管理员提供一个暴露应用的入口定义方法。
Ingress Controller:
根据Ingress生成具体的路由规则,并对Pod实现负载均衡。
Ingress和service的区别:
ingress实现七层服务:
可以识别七层的服务的负载均衡,比如http协议。底层会用到service的资源。
service实现四层负载均衡:
可以实现四层服务的负载均衡。
Ingress Controller的工作原理如下所示:
(1)Ingress Controller通过与kubernetes APIServer交互,动态的去感知集群中Ingress规则变化,然后读取它;
(2)Ingress Controller将读取到的内容按照自定义的规则(就是写明了哪个域名对应哪个service,生成一段Nginx配置)应用到管理的nginx服务;
(3)然后热加载生效,以此来达到Nginx负载均衡器配置及动态更新的问题;
数据包流程:
客户端 ---> Ingress Controller(我们案例使用的是Nginx Ingress Controller) ---> 分布在各个节点的Pod
温馨提示:
(1)Ingress和Ingress Controller的关系如下图所示。Ingress公开了从集群外部到集群内服务的HTTP和HTTPS路由的规则集合,而具体实现流量路由则是由Ingress Controller负责;
(2)Ingress也支持四层的负载均会,只不过生产环境中四层的负载均会我们都习惯上使用service资源来实现,而七层的负载均会则交由Ingress来实现;
2.HAProxy Ingress controller(主要基于Go语言研发)
HAProxy是众所周知的代理服务器和负载均衡器。作为Kubernetes集群的一部分,它提供了“软”配置更新(无流量损失)、基于DNS的服务发现和通过API进行动态配置。
HAProxy还支持完全自定义配置文件模板(通过替换 ConfigMap)以及在其中使用Spring Boot函数。
GitHub地址:
github.com/jcmoraisjr/haproxy-ingress
3.Voyager Ingress controller(主要基于Go + Shell语言)
Voyager基于HAProxy,并作为一个通用的解决方案提供给大量供应商。它最具代表性的功能包括L7和L4上的流量负载均衡,其中,TCP L4流量负载均衡称得上是该解决方案最关键的功能之一。
GitHub地址:
github.com/appscode/voyager
4.Contour Ingress controller(主要基于Go语言研发)
Contour和Envoy由同一个作者开发,它基于Envoy。它最特别的功能是可以通过CRD(IngressRoute)管理 Ingress资源,对于多团队需要同时使用一个集群的组织来说,这有助于保护相邻环境中的流量,使它们免受 Ingress资源更改的影响。
它还提供了一组扩展的负载均衡算法(镜像、自动重复、限制请求率等),以及详细的流量和故障监控。对某些工程师而言,它不支持粘滞会话可能是一个严重缺陷。
GitHub地址:
https://github.com/projectcontour/contour
ENVOY是一个开源的边缘和服务代理,专为云原生应用而设计。Envoy最初是在Lyft构建的,它是一个高性能的 C++分布式代理,专为单个服务和应用程序设计,以及为大型微服务“服务网格”架构设计的通信总线和“通用数据平面”。
推荐阅读:
https://www.envoyproxy.io/
5.Istio Ingress controller(主要基于Go语言研发)
Istio是IBM、Google和Lyft的联合开发项目,它是一个全面的服务网格解决方案——不仅可以管理所有传入的外部流量(作为 Ingress 控制器),还可以控制集群内部的所有流量。
Istio将Envoy用作每种服务的辅助代理。从本质上讲,它是一个可以执行几乎所有操作的大型处理器,其中心思想是最大程度的控制、可扩展性、安全性和透明性。
通过Istio Ingress,你可以对流量路由、服务之间的访问授权、均衡、监控、金丝雀发布等进行优化。
官方网站:
https://github.com/istio/istio
什么是服务网格:
服务网格(例如开源项目 Istio)用于控制应用的不同部分之间如何共享数据。与用于管理此类通信的其他系统不同,服务网格内置于应用程序中的专用基础架构层。这个可见的基础架构层可以记录应用的不同部分是否能正常交互。因此,随着应用的不断发展,它在优化通信和避免停机方面就显得更加有用。
推荐阅读:
https://www.redhat.com/zh/topics/microservices/what-is-a-service-mesh
6.Ambassador Ingress controller(主要基于python + Go语言研发)
Ambassador也是一个基于Envoy的解决方案,它有免费版和商业版两个版本。
Ambassador被称为“Kubernetes 原生 API 微服务网关”,它与K8s原语紧密集成,拥有你所期望的从Ingress controller获得的功能包,它还可以与各种服务网格解决方案,如Linkerd、Istio等一起使用。
顺便提一下,Ambassador博客日前发布了一份基准测试结果,比较了Envoy、HAProxy和NGINX的基础性能。
GitHub地址:
https://github.com/emissary-ingress/emissary
7.Gloo Ingress controller(主要基于 Go语言研发)
Gloo是在Envoy之上构建的新软件(于 2018 年 3 月发布),由于它的作者坚持认为“网关应该从功能而不是服务中构建API”,它也被称为“功能网关”。其“功能级路由”的意思是它可以为后端实现是微服务、无服务器功能和遗留应用的混合应用路由流量。
由于拥有可插拔的体系结构,Gloo提供了工程师期望的大部分功能,但是其中一些功能仅在其商业版本(Gloo Enterprise)中可用。
GitHub地址:
https://github.com/solo-io/gloo
8.Skipper Ingress controller(主要基于 Go语言研发)
Skipper是HTTP路由器和反向代理,因此不支持各种协议。从技术上讲,它使用Endpoints API(而不是 Kubernetes Services)将流量路由到Pod。它的优点在于其丰富的过滤器集所提供的高级HTTP路由功能,工程师可以借此创建、更新和删除所有HTTP数据。
Skipper的路由规则可以在不停机的情况下更新。正如它的作者所述,Skipper可以很好地与其他解决方案一起使用,比如AWS ELB。
GitHub地址:
https://github.com/zalando/skipper
9.Kubernetes Ingress Controller(主要基于 Go语言研发)
Kubernetes的“官方”控制器(之所以称为官方,是想把它区别于NGINX公司的控制器)。
这是社区开发的控制器,它基于nginx Web服务器,并补充了一组用于实现额外功能的Lua插件。
由于NGINX十分流行,再加上把它用作控制器时所需的修改较少,它对于K8s普通工程师来说,可能是最简单和最直接的选择。
GitHub地址:
github.com/kubernetes/ingress-nginx
10.NGINX Ingress Controller(主要基于 Go + python语言研发)
这是NGINX公司开发的官方产品,它也有一个基于NGINX Plus的商业版。NGINX的控制器具有很高的稳定性、持续的向后兼容性,且没有任何第三方模块。
由于消除了Lua代码,和官方控制器相比,它保证了较高的速度,但也因此受到较大限制。相较之下,它的付费版本有更广泛的附加功能,如实时指标、JWT 验证、主动健康检查等。
NGINX Ingress重要的优势是对TCP/UDP流量的全面支持,最主要缺点是缺乏流量分配功能。
11.Kong Ingress Controller(主要基于 Go语言研发)
Kong Ingress由Kong Inc开发,有两个版本:商业版和免费版。它基于NGINX构建,并增加了扩展其功能的 Lua模块。
最初,Kong Ingress主要用作API网关,用于API请求的处理和路由。现在,它已经成为成熟的Ingress控制器,主要优点是拥有大量易于安装和配置的附加模块、插件(包括第三方插件)。它开启了控制器具备大量附加功能的先河,其内置函数也提供了许多可能性。Kong Ingress配置是用CustomResourceDefinition(简称"CRD",即用户自定义资源二次开发能力扩展的Kubernetes API)执行的。
Kong Ingress的一个重要特性是它只能在一个环境中运行(而不支持跨命名空间)。这是一个颇有争议的话题:有些人认为这是一个缺点,因为必须为每个环境生成实例;而另一些人认为这是一个特殊特性,因为它是更高级别的隔离,控制器故障的影响仅限于其所在的环境。
GitHub地址:
github.com/Kong/kubernetes-ingress-controller
12.Traefik Ingress Controller(主要基于 Go语言研发)
Traefik是一款开源的反向代理与负载均衡工具。它最大的优点是能够与常见的微服务系统直接整合,可以实现自动化动态配置。
最初,这个代理是为微服务请求及其动态环境的路由而创建的,因此具有许多有用的功能:连续更新配置(不重新启动)、支持多种负载均衡算法、Web UI、指标导出、对各种服务的支持协议、REST API、Canary 版本等。
在2019年9月发布的 Traefik v2.0 中,虽然它增加许多不错的新功能,如带有 SNI 的 TCP/SSL、金丝雀部署、流量镜像/shadowing和经过改进的Web UI。
GitHub地址:
https://github.com/traefik/traefik
推荐阅读:
https://doc.traefik.io/traefik/getting-started/quick-start/
http://www.mianshigee.com/tutorial/traefik/10.md
13.主流的控制器流行度
如果比较的是全球社区的选择趋势,那么Istio(28k+⭐)和 Traefik(超过 35k⭐)的优势就显而易见了。即使是社区官方控制器,它也明显处于下风(不到 12k⭐)。相对的,Kong Ingress(1.5k⭐) 和 HAProxy Ingress(不足1k⭐)最不热门 。
通过阅读上述的Ingress控制器,每种控制器都有其优点和缺点。
(1)社区官方的Ingress控制器成熟、易于使用,并提供了足以满足大多数情况的出色功能;
(2)如果对可靠性和功能实现的质量有很高的要求,NGINX Ingress的商业版会是一个合适的选择;
(3)Kong拥有最丰富的插件集,在其商业版本中也提供了更多功能,它还拥有基于自定义资源的动态配置;
(4)如果比较关注负载均衡和授权,请看看Traefik和HAProxy。它们是开源项目,功能已经经过社区多年验证,非常稳定,而且还在不断发展;
(5)Contour虽然只有两岁,但它已经具备Envoy之上的基础功能;
(6)基于Envoy的解决方案拥有最丰富的功能集,尤其是Istio。但这是一个复杂的解决方案,意味着工程师需要具备更多相关经验来配置、运行、操作它们;
(7)在某些其他情况下,Gloo的许多功能可能只在付费版本中提供;
(8)如果你的应用程序需要高级或经常更改的HTTP路由表,那么Skipper可能是一个很合适的解决方案;
以上内容参考连接如下:
https://blog.csdn.net/weixin_41715077/article/details/103481030
如下图所示,下表是各种Ingress控制器的摘要:
14.Ingress Controller的高可用方案
一般Ingress Controller会以"DaemonSet"控制器结合"nodeSelector"部署到几台特定Node,然后将这几台挂在到公网负载均衡器对外提供服务。你有可能会丫头如下疑问:
(1)为什么要使用"DaemonSet"控制器而不使用"Deployment"控制器呢?
答: 因为使用"Deployment"控制器很有可能将多个Pod部署在同一台工作节点上,尽管服务可以正常运行,但当访问量比较大时,磁盘I/O始终是一个不可逾越的瓶颈。
(2)既然已经使用了"DaemonSet"控制器为什么还要使用"nodeSelector"呢?
答: 因为在集群规模比较大时,有可能是几千台服务器,甚至上万台,这意味着在所有的工作节点都启用一个"Ingress Controller"的Pod,尽管都可以正常运行,但无疑是占用了多余的资源!因此我们生产环境中可能会使用"nodeSelector"选择指定的节点哟~
温馨提示:
如下图所示,我们生产环境中可能会创建多个"Ingress Controller"的Pod,但客户端实际访问时可能会使用同一的入口,因此我们需要在所有的"Ingress Controller"的Pod前面加一个负载均衡器。
有关负载均衡器的选择有很多种,比如在云运营商提供的LB产品即可,也可以使用开源的解决方案,比如Nginx,Haproxy,Lvs等技术实现负载均衡。
四.Ingress实战案例-Traefik实战案例
1.traefik ingress控制器实战案例
(1)创建基于角色的绑定的服务账号
cat > 01-rabc.yaml <<'EOF'
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: kube-system
EOF
(2)部署traefik控制器并暴露svc
cat > 02-traefik.yaml <<'EOF'
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
name: traefik-ingress-controller
namespace: kube-system
labels:
k8s-app: traefik-ingress-lb
spec:
selector:
matchLabels:
k8s-app: traefik-ingress-lb
template:
metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
hostNetwork: true
containers:
- image: k8s101.oldboyedu.com:5000/traefik:v1.7.2
imagePullPolicy: IfNotPresent
name: traefik-ingress-lb
ports:
- name: http
containerPort: 80
hostPort: 80
- name: admin
containerPort: 8080
args:
- --api
- --kubernetes
- --logLevel=INFO
---
kind: Service
apiVersion: v1
metadata:
name: traefik-ingress-service
namespace: kube-system
spec:
selector:
k8s-app: traefik-ingress-lb
ports:
- protocol: TCP
port: 80
name: web
- protocol: TCP
port: 8080
name: admin
type: NodePort
EOF
(3)执行配置文件
kubectl apply -f 01-rabc.yaml -f 02-traefik.yaml
温馨提示:
(1)如下图所示,如果部署成功了就可以直接访问对应的webUI哟;
(2)关于基于helm组件部署可参考官方文档:
https://doc.traefik.io/traefik/getting-started/install-traefik/
2.准备traefik ingress控制器的测试资源
cat > 03-deployment-nginx.yaml <<'EOF'
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: k8s101.oldboyedu.com:5000/nginx:1.14.2
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: oldboyedu-nginx
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30001
EOF
4.使用traefik ingress控制器创建Ingress规则代理资源案例
cat > 04-ingress.yaml <<'EOF'
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-myweb
annotations:
kubernetes.io/ingress.class: traefik # 指定Ingress 控制器为"traefik"
spec:
rules:
- host: myweb.oldboyedu.com
http:
paths:
- backend:
serviceName: oldboyedu-nginx
servicePort: 80
EOF
温馨提示:
Ingress资源属于局部资源,因此你要取保你进行代理的资源和你的Ingress资源处于同一个名称空间哟。
5.traefik配置证书案例
(1)"traefik"应用默认部署在"kube-system",在对应"namespace"创建"secret"资源
kubectl create secret generic traefik-cert --from-file=./5920030_aliyun.oldboyedu.com.pem --from-file=./5920030_aliyun.oldboyedu.com.key -n kube-system
(2)生成"configmap"资源
kubectl create configmap traefik-conf --from-file=./traefik.toml -n kube-system
(3)其它步骤
参考课堂笔记.
参考链接:
https://www.cnblogs.com/netonline/p/10968046.html
五.Ingress实战案例-Ingress Controller
1.部署Ingress Controller环境概述(因为只有部署了Ingress Controller才能让我们配置Ingress资源)
Ingress Controller有很多实现,我们这里采用官方维护的Nginx控制器。
项目地址:
https://github.com/kubernetes/ingress-nginx
部署方式:
https://kubernetes.github.io/ingress-nginx/deploy/
其它控制器:
https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/#additional-controllers
2.部署nginx ingress controller
cat > 01-nginx-ingress.yaml <<'EOF'
apiVersion: v1
kind: Namespace
metadata:
name: ingress-nginx
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: default-http-backend
labels:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
namespace: ingress-nginx
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
spec:
terminationGracePeriodSeconds: 60
containers:
- name: default-http-backend
# Any image is permissible as long as:
# 1. It serves a 404 page at /
# 2. It serves 200 on a /healthz endpoint
image: netonline/defaultbackend:1.4
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 5
ports:
- containerPort: 8080
resources:
limits:
cpu: 10m
memory: 20Mi
requests:
cpu: 10m
memory: 20Mi
---
apiVersion: v1
kind: Service
metadata:
name: default-http-backend
namespace: ingress-nginx
labels:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
spec:
ports:
- port: 80
targetPort: 8080
selector:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-configuration
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: tcp-services
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: udp-services
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx-ingress-serviceaccount
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: nginx-ingress-clusterrole
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- "extensions"
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- "extensions"
resources:
- ingresses/status
verbs:
- update
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
name: nginx-ingress-role
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- configmaps
- pods
- secrets
- namespaces
verbs:
- get
- apiGroups:
- ""
resources:
- configmaps
resourceNames:
# Defaults to "<election-id>-<ingress-class>"
# Here: "<ingress-controller-leader>-<nginx>"
# This has to be adapted if you change either parameter
# when launching the nginx-ingress-controller.
- "ingress-controller-leader-nginx"
verbs:
- get
- update
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: nginx-ingress-role-nisa-binding
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: nginx-ingress-role
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: nginx-ingress-clusterrole-nisa-binding
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nginx-ingress-clusterrole
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: ingress-nginx
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-ingress-controller
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
annotations:
prometheus.io/port: "10254"
prometheus.io/scrape: "true"
spec:
serviceAccountName: nginx-ingress-serviceaccount
hostNetwork: true
containers:
- name: nginx-ingress-controller
image: quay.mirrors.ustc.edu.cn/kubernetes-ingress-controller/nginx-ingress-controller:0.20.0
args:
- /nginx-ingress-controller
- --default-backend-service=$(POD_NAMESPACE)/default-http-backend
- --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:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
# www-data -> 33
runAsUser: 33
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443
livenessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
EOF
推荐阅读:
` https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal
温馨提示:
如下图所示,如果K8S 1.22及以上版本时,下载官方的控制器必须是有版本要求的哟。
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.4/deploy/static/provider/baremetal/deploy.yaml
3.查看NGINX Ingress controller的版本号
(1)如上图所示,我的环境是K8S 1.15.12版本部署的NGINX Ingress controller
kubectl exec -n ingress-nginx nginx-ingress-controller-54f67ccb58-p5gcd -- /nginx-ingress-controller --version
(2)如下图所示,我的环境是K8S 1.22.2版本部署的NGINX Ingress controller
kubectl exec -n ingress-nginx ingress-nginx-controller-6dffb7bddf-b74l4 -- /nginx-ingress-controller --version
4.创建测试的SVC案例(也可以使用traefik ingress controller的测试环境哟)
cat > 02-deployment-nginx.yaml << EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: k8s101.oldboyedu.com:5000/nginx:1.16
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: oldboyedu-nginx
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30001
EOF
温馨提示:
如果已经有相关测试的SVC,则可跳过该步骤。我推荐可以将本案例换成wordpress。
5.编写Ingress规则并验证
(1)编写Ingress控制器
cat >03-ingress.yaml <<'EOF'
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-myweb
spec:
rules:
- host: myweb.oldboyedu.com
http:
paths:
- backend:
serviceName: oldboyedu-nginx
servicePort: 80
EOF
(2)查看nginx-ingress-controller的Pod的配置文件
kubectl exec -n ingress-nginx nginx-ingress-controller-54f67ccb58-p5gcd cat /etc/nginx/nginx.conf | grep "start server myweb.oldboyedu.com" -A 30
温馨提示:
如上图所示,当我们添加了新的Ingress规则时,就会对应多出来相关的记录哟~
如下图所示,我们可以成功访问到Nginx服务啦,上课演示可以修改一下Pod容器的内容:
echo "111" > index.html
kubectl cp index.html nginx-deployment-66877c9488-rvkgd:/usr/share/nginx/html/index.html
kubectl cp index.html nginx-deployment-66877c9488-rzmtg:/usr/share/nginx/html/index.html
kubectl cp index.html nginx-deployment-66877c9488-ww9v6\:/usr/share/nginx/html/index.html
六.可能出现的错误
1.error: unable to recognize "01-mysql-deploy.yml": no matches for kind "Deployment" in version "extensions/v1beta1"
问题原因:
k8s 1.22的Deployment资源版本写错了。
解决方案:
修改配置文件,参考官方文档,对于1.22版本中,Deployment资源的版本为"apps/v1"
参考连接:
https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/
2. error validating data: ValidationError(Deployment.spec): missing required field "selector" in io.k8s.api.apps.v1.DeploymentSpec
问题原因:
报错很明显,缺少"selector"定义字段哟~
解决方案:
参考官方文档添加对应的"selector"即可。
参考连接:
https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/
3.2021/10/19 12:11:26 command traefik error: flag needs an argument: -kubernetes
问题原因:
启动traefik时参数传递错误。
解决方案:
编辑k8s的资源清单,修改配置文件,如果使用官方的镜像,则无需手动指定参数哟。
4. unknown field "serviceName" in io.k8s.api.networking.v1.IngressBackend
问题原因:
如下图所示,这是由于字段名称配置错误导致的。
解决方案:
修改配置文件重新进行解析即可。
参考连接:
https://kubernetes.io/zh/docs/concepts/services-networking/ingress/
5.Error: INSTALLATION FAILED: rendered manifests contain a resource that already exists. Unable to continue with install: ClusterRoleBind
ing "traefik" in namespace "" exists and cannot be imported into the current release: invalid ownership metadata; annotation validation error: key "meta.helm.sh/release-namespace" must equal "traefik-v2": current value is "default"
问题原因:
在default名称空间中存在了名为"traefik"的ClusterRoleBinding类型资源。
解决方案:
删除已存在的资源重新执行即可。具体操作参考如下:
kubectl delete clusterrolebindings.rbac.authorization.k8s.io traefik
6.default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
问题原因:
缺少默认的后端服务,当用户访问的域名没有对应的Ingress规则时就会走这个默认的后端节点。
解决方案:
手动创建默认的Ingress资源。
7.1 node(s) had taints that the pod didn't tolerate, 3 node(s) didn't have free ports for the requested pod port
问题原因:
我的环境有1个master节点和3个node节点,但由于之前已经部署了"traefik",因此80端口已被占用。
解决方案:
释放已经占用的80端口即可。