k8s上部署及使用ingress-nginx

发布于 2022-11-01  2.1k 次阅读


在配置以及使用的ingress-nginx 之前应该先了学习并了解k8s的服务发现原理,以及常用的服务器发现规则

提供:https://kubernetes.github.io/ingress-nginx/
https://github.com/kubernetes/ingress-nginx/

用于学习了解ingress-nginx内容以及对应k8s的版本情况,建议使用github的地址去下载yaml 文件

在了解了k8s 的通信方式后,最后集群外访问集群内的时候,就需要用ingress 将域名信息或者ip转发到对应服务ip

ingress 可以提供负载均衡、ssl终结基于名称的虚拟托管

一、了解ingress,什么是ingress

Ingress 开放了从集群外部到集群内服务的 HTTP 和 HTTPS 路由,流量路由由 Ingress 资源上定义的规则控制。

Ingress 可为 Service 提供外部可访问的 URL、负载均衡流量、终止 SSL/TLS,以及基于名称的虚拟托管。Ingress 控制器通常负责通过负载均衡器来实现 Ingress,尽管它也可以配置边缘路由器或其他前端来帮助处理流量。

Ingress 不会公开任意端口或协议。将 HTTP 和 HTTPS 以外的服务公开到 Internet 时,通常使用 Service.Type=NodePort 或 Service.Type=LoadBalancer 类型的 Service。

二、ingress yaml文件配置以及优化

[root@k8s-master01 ingress-nginx]#  kubelet --version
Kubernetes v1.19.16

由于我的kubernets版本是v1.19.16,根据官网我可用使用 最新的v1.2.1nginx-ingress-controller,

ingress的下载链接如下:

https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.1/deploy/static/provider/cloud/deploy.yaml

  • 国内需要将:对应image 镜像修改为对国内的如:
    registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.2.1
    registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1

  • 修改Deployment为DaemonSet比较好,因为DaemonSet可以自动为每一台需要安装的机器都安装一份(使用标签控制);

  • Container使用主机网络,对应的dnsPolicy策略也需要改为主机网络的 (dnsPolicy: ClusterFirstWithHostNet)

  • 修改Container使用主机网络,直接在主机上开辟 80,443端口,无需中间解析,速度更快 (hostNetwork: true)

  • 修改Service为ClusterIP,无需NodePort模式了

  • 修改DaemonSet的nodeSelector: ingress-node=true 。这样只需要给node节点打上 ingress-node=true 标签,即可快速的加入/剔除 ingress-controller的数量

优化后的文件下载地址:https://blog.buwo.net/public/jyl-containers/ingress-controller.yaml

二、安装ingress-nginx

自建集群使用裸金属安装方式

2.1 优化ingress的 ymal 文件

需要如下修改:

  • 修改ingress-nginx-controller镜像为 registry.cn-hangzhou.aliyuncs.com/google_containers/ingress-nginx-controller:v0.46.0;

  • 修改Deployment为DaemonSet比较好,因为DaemonSet可以自动为每一台需要安装的机器都安装一份(使用标签控制);

  • 修改Container使用主机网络,直接在主机上开辟 80,443端口,无需中间解析,速度更快;

  • Container使用主机网络,对应的dnsPolicy策略也需要改为主机网络的;

  • 修改Service为ClusterIP,无需NodePort模式了;

  • 修改DaemonSet的nodeSelector: ingress-node=true 。这样只需要给node节点打上 node-role=ingress 标签,即可快速的加入/剔除 ingress-controller的数量

    node-role: ingress #以后只需要给某个node打上这个标签就可以部署ingress-nginx到这个节点上了

2.3 在k8s上部署ingress-nginx

检查k8s 集群master以及node节点80和443端口使用情况

[root@k8s-master01 ingress-nginx]# ss -ntpl|grep 80
[root@k8s-master01 ingress-nginx]# ss -ntpl|grep 443

使用kubectl apply部署对应的yaml文件:

[root@k8s-master01 ingress-nginx]# kubectl apply -f ingress-controller.yaml 
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
configmap/ingress-nginx-controller created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
service/ingress-nginx-controller-admission created
service/ingress-nginx-controller created
daemonset.apps/ingress-nginx-controller created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
serviceaccount/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created

给需要的node节点上部署ingress-controller:

因为我们使用的是DaemonSet模式,所以理论上会为所有的节点都安装,但是由于我们的selector使用了筛选标签:node-role=ingress ,所以此时所有的node节点都没有被执行安装;

[root@k8s-master01 ingress-nginx]# kubectl get ds -n ingress-nginx 
NAME                       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR       AGE
ingress-nginx-controller   0         0         0       0            0           node-role=ingress   5m9s

当我们需要为所有的node节点安装ingress-controller的时候,只需要为对应的节点打上标签:node-role=ingress

[root@k8s-master01 ingress-nginx]# kubectl label node k8s-node01  node-role=ingress
[root@k8s-master01 ingress-nginx]# kubectl label node k8s-node02  node-role=ingress

查看k8s 上ingress-nginx的信息

[root@k8s-master01 ingress-nginx]# kubectl get all -n ingress-nginx
NAME                                       READY   STATUS      RESTARTS   AGE
pod/ingress-nginx-admission-create-628r6   0/1     Completed   0          104d
pod/ingress-nginx-admission-patch-w2js2    0/1     Completed   0          104d
pod/ingress-nginx-controller-s6nx6         1/1     Running     4          104d
pod/ingress-nginx-controller-tthn5         1/1     Running     3          104d

NAME                                         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/ingress-nginx-controller             ClusterIP   10.97.116.179    <none>        80/TCP,443/TCP   104d
service/ingress-nginx-controller-admission   ClusterIP   10.108.175.254   <none>        443/TCP          104d

NAME                                      DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR       AGE
daemonset.apps/ingress-nginx-controller   2         2         2       2            2           node-role=ingress   104d

NAME                                       COMPLETIONS   DURATION   AGE
job.batch/ingress-nginx-admission-create   1/1           1s         104d
job.batch/ingress-nginx-admission-patch    1/1           1s         104d

[root@k8s-master01 ingress-nginx]# kubectl get pod -n ingress-nginx -o wide
NAME                                   READY   STATUS      RESTARTS   AGE    IP               NODE         NOMINATED NODE   READINESS GATES
ingress-nginx-admission-create-628r6   0/1     Completed   0          105d   10.244.58.200    k8s-node02   <none>           <none>
ingress-nginx-admission-patch-w2js2    0/1     Completed   0          105d   10.244.58.201    k8s-node02   <none>           <none>
ingress-nginx-controller-4ht4c         1/1     Running     0          28m    192.168.232.71   k8s-node01   <none>           <none>
ingress-nginx-controller-m5vk4         1/1     Running     0          28m    192.168.232.72   k8s-node02   <none>           <none>

到这里就部署成功了

三、使用ingress-nginx

先创建一个验证测试的Deployment

#namespace
apiVersion: v1
kind: Namespace
metadata:
  name: tomcat-demo
  labels:
    name: tomcat-demo
    app: tomcat-demo
---
#deploy
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-demo
  namespace: tomcat-demo
spec:
  selector:
    matchLabels:
      app: tomcat-demo
  replicas: 2
  template:
    metadata:
      labels:
        app: tomcat-demo
    spec:
      hostname: k8s-node01
      containers:
      - name: tomcat-demo
        image: registry.cn-hangzhou.aliyuncs.com/liuyi01/tomcat:8.0.51-alpine
        ports:
        - containerPort: 8080
---
#service
apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
  namespace: tomcat-demo
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: tomcat-demo

验证这个pod 可以正常通过svc 访问:
file

curl -l 10.102.44.103 

到在master 中能正常访问 clusterip ,后面就是通过ingress 把域名指向对应的svc

###
[root@k8s-master01 test]# cat tomcat-demo-ingress.yaml
apiVersion: extensions/v1beta1 #可替换成networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: tomcat-demo-ingress
  namespace: tomcat-demo
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: www.ericejia.net
    http:
      paths:
      - path: /
        backend:
          serviceName: tomcat-service  
          servicePort: 80     # 不过需要注意大部分Ingress controller都不是直接转发到Service
                            # 而是只是通过Service来获取后端的Endpoints列表,直接转发到Pod,这样可以减少网络跳转,提高性能

[root@k8s-master01 test]#  kubectl apply -f tomcat-demo-ingress.yaml
[root@k8s-master01 test]# kubectl get ingress -A
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
NAMESPACE     NAME                  CLASS    HOSTS              ADDRESS   PORTS   AGE
tomcat-demo   tomcat-demo-ingress   <none>   www.ericejia.net             80      9m8s

file

由于一下特性

特性 extensions/v1beta1 networking.k8s.io/v1beta1 networking.k8s.io/v1
状态 ❌ 已弃用 ❌ 已弃用 ✅ 稳定版
K8s 版本 v1.14+ 弃用 v1.22+ 移除 v1.19+ 弃用 v1.22+ 移除 v1.19+ 稳定
path 配置 简单格式 简单格式 结构化格式
pathType 不支持 不支持 必需字段
向后兼容 长期支持

networking.k8s.io/v1 版本和networking.k8s.io/v1 上文中有extensions/v1beta1版本

kubectl delete ingress -ntomcat-demo   tomcat-demo
[root@k8s-master01 test]# kubectl get ingree -A
error: the server doesn't have a resource type "ingree"

####networking.k8s.io/v1 版本
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tomcat-demo-ingress
  namespace: tomcat-demo
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: www.ericejia.net  # 将域名映射到 my-nginx 服务
    http:
      paths:
      - path: /
        backend:
          service:
            name: tomcat-service  # 将所有请求发送到 my-nginx 服务的 80 端口
            port:
              number: 80     # 不过需要注意大部分Ingress controller都不是直接转发到Service
        pathType: Prefix     # 而是只是通过Service来获取后端的Endpoints列表,直接转发到Pod,这样可以减少网络跳转,提高性能

补充说明pathType:
Exact: 精确匹配路径。如 path: /foo,只匹配请求路径与之完全相同的 /foo。
Prefix: 前缀匹配路径。如 path: /foo,匹配请求路径以 /foo 开始的所有路径,如 /foo、/foo/bar 等。
ImplementationSpecific: 特定 Ingress controller 的匹配方式。如 Nginx Ingress controller 忽略路径类型,作
在 networking.k8s.io/v1 API 中,pathType 必须是首字母大写的格式
三种写法均证明可以行。
file

记录下报错问题:

file
MountVolume.SetUp failed for volume "webhook-cert" : secret "ingress-nginx-admission" not found

kubectl get secret ingress-nginx-admission -n ingress-nginx
.......
Events:
  Type     Reason       Age                From                      Message
  ----     ------       ----               ----                      -------
  Normal   Scheduled    10m                default-scheduler         Successfully assigned ingress-nginx/ingress-nginx-controller-s4dtb to k8s-node01
  Warning  FailedMount  10m (x2 over 10m)  kubelet                   MountVolume.SetUp failed for volume "webhook-cert" : secret "ingress-nginx-admission" not found
  Normal   Pulled       10m                kubelet                   Container image "registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.2.1" already present on machine
  Normal   Created      10m                kubelet                   Created container controller
  Normal   Started      10m                kubelet                   Started container controller
  Normal   RELOAD       10m                nginx-ingress-controller  NGINX reload triggered due to a change in configuration

通过查询一共有两种办法
方案一:
此时需要执行如下命令,删除对应的admission,以为之前我安装失败后重新刷新部署并没有删除对应的验证器配置,所以会导致上面问题。

kubectl get ValidatingWebhookConfiguration
kubectl delete -A ValidatingWebhookConfiguration ingress-nginx-admission
kubectl apply -f tomcat-demo-ingress.yaml

验证重新创建ingress 绑定域名是可行的

更多 ingress-nginx 高级用法可以参看阿里的文档:
https://help.aliyun.com/zh/ack/serverless-kubernetes/user-guide/advanced-ingress-configurations#58e42304f4ccc