014、K8S的网络访问进阶篇
本文最后更新于 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版本需要自行修改哟~

image-20211014133842243

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名称也要相同哟;

image-20211014140749250

二.修改kube-proxy的工作模式为ipvs模式

1.查看kube-proxy的工作模式

image-20211014164525938

如上图所示,我们随机找了任意一个节点的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。

image-20211014163803842

如下图所示,如果对上面的结果你还有所怀疑的话,别着急,各个节点的kube proxy的Pod日志也会有记录哟~

image-20211014165100595

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

image-20211014175209956

3.修改集群的工作模式为ipvs

如下图图所示,编辑名为"kube-proxy"的configMap资源,将mode的值改为"ipvs"
    kubectl edit cm kube-proxy -n kube-system

image-20211014175637915

4.删除旧的kube-proxy的pod

如下图所示,当我们删除旧的Pod后,会自动拉起新的Pod哟~

image-20211014180852857

5.验证资源

image-20211014181454063

(1)查看新启动的kube-proxy组件的Pod日志
    如下图所示,我们可以通过查看Pod日志来分析。

(2)测试验证kube-proxy是否正常工作
    我们可以使用curl测试访问某个web页面以观察Pod是否正常工作。

温馨提示:
    (1)建议将tomcat的pod扩容先扩容为3个,然后使用curl命令进行测试比较明显哟;
    (2)当然,也可以配合使用"ipvsadm -l -n"查看调度策略哟~

image-20211014183505697

三.主流的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来实现;

image-20211101225149641

2.HAProxy Ingress controller(主要基于Go语言研发)

    HAProxy是众所周知的代理服务器和负载均衡器。作为Kubernetes集群的一部分,它提供了“软”配置更新(无流量损失)、基于DNS的服务发现和通过API进行动态配置。 

    HAProxy还支持完全自定义配置文件模板(通过替换 ConfigMap)以及在其中使用Spring Boot函数。

    GitHub地址:
        github.com/jcmoraisjr/haproxy-ingress

image-20211019092000726

3.Voyager Ingress controller(主要基于Go + Shell语言)

    Voyager基于HAProxy,并作为一个通用的解决方案提供给大量供应商。它最具代表性的功能包括L7和L4上的流量负载均衡,其中,TCP L4流量负载均衡称得上是该解决方案最关键的功能之一。

    GitHub地址:
        github.com/appscode/voyager

image-20211019092432559

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/

image-20211019092725217

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

image-20211019094402779

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

image-20211019095256131

7.Gloo Ingress controller(主要基于 Go语言研发)

    Gloo是在Envoy之上构建的新软件(于 2018 年 3 月发布),由于它的作者坚持认为“网关应该从功能而不是服务中构建API”,它也被称为“功能网关”。其“功能级路由”的意思是它可以为后端实现是微服务、无服务器功能和遗留应用的混合应用路由流量。

    由于拥有可插拔的体系结构,Gloo提供了工程师期望的大部分功能,但是其中一些功能仅在其商业版本(Gloo Enterprise)中可用。

    GitHub地址:
        https://github.com/solo-io/gloo

image-20211019095736910

8.Skipper Ingress controller(主要基于 Go语言研发)

    Skipper是HTTP路由器和反向代理,因此不支持各种协议。从技术上讲,它使用Endpoints API(而不是 Kubernetes Services)将流量路由到Pod。它的优点在于其丰富的过滤器集所提供的高级HTTP路由功能,工程师可以借此创建、更新和删除所有HTTP数据。

    Skipper的路由规则可以在不停机的情况下更新。正如它的作者所述,Skipper可以很好地与其他解决方案一起使用,比如AWS ELB。

    GitHub地址:
        https://github.com/zalando/skipper

image-20211019100145927

9.Kubernetes Ingress Controller(主要基于 Go语言研发)

    Kubernetes的“官方”控制器(之所以称为官方,是想把它区别于NGINX公司的控制器)。

    这是社区开发的控制器,它基于nginx Web服务器,并补充了一组用于实现额外功能的Lua插件。

    由于NGINX十分流行,再加上把它用作控制器时所需的修改较少,它对于K8s普通工程师来说,可能是最简单和最直接的选择。

    GitHub地址:
        github.com/kubernetes/ingress-nginx

image-20211019103208634

10.NGINX Ingress Controller(主要基于 Go + python语言研发)

    这是NGINX公司开发的官方产品,它也有一个基于NGINX Plus的商业版。NGINX的控制器具有很高的稳定性、持续的向后兼容性,且没有任何第三方模块。

    由于消除了Lua代码,和官方控制器相比,它保证了较高的速度,但也因此受到较大限制。相较之下,它的付费版本有更广泛的附加功能,如实时指标、JWT 验证、主动健康检查等。

    NGINX Ingress重要的优势是对TCP/UDP流量的全面支持,最主要缺点是缺乏流量分配功能。

image-20211019103638746

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

image-20211019104127139

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

image-20211019105351335

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控制器的摘要:

image-20211019100801522

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等技术实现负载均衡。

image-20211102100325723

四.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/

image-20211117213831712

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资源处于同一个名称空间哟。

image-20211117223728155

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

image-20211102202351930

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

image-20211102203147805

3.查看NGINX Ingress controller的版本号

image-20211117230740263

(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

image-20211105170703450

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规则并验证

image-20211117231557549

(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

image-20211117232135321

六.可能出现的错误

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/

image-20211014112801809

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/

image-20211014113003612

3.2021/10/19 12:11:26 command traefik error: flag needs an argument: -kubernetes

问题原因:
    启动traefik时参数传递错误。

解决方案:
    编辑k8s的资源清单,修改配置文件,如果使用官方的镜像,则无需手动指定参数哟。

image-20211019122245434

4. unknown field "serviceName" in io.k8s.api.networking.v1.IngressBackend

问题原因:
    如下图所示,这是由于字段名称配置错误导致的。

解决方案:
    修改配置文件重新进行解析即可。

参考连接:
    https://kubernetes.io/zh/docs/concepts/services-networking/ingress/

image-20211019175250080

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

image-20211101205402227

6.default-http-backend:80 (<error: endpoints "default-http-backend" not found>)

问题原因:
    缺少默认的后端服务,当用户访问的域名没有对应的Ingress规则时就会走这个默认的后端节点。

解决方案:
    手动创建默认的Ingress资源。

image-20211105182631228

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端口即可。

image-20211117224751622

谨此笔记,记录过往。凭君阅览,如能收益,莫大奢望。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇