ingress-nginx 部署及访问策略 基于NodePort(一)

Kubernetes / 2022-12-16

ingress-nginx简介

为了使Kubernetes外部的用户能够访问集群内的服务,Kubernetes 目前提供了以下几种方案:

  • NodePort:最简单,用命令kubectl expose deployment [deply_name] --type=NodePort直接配置就可以
  • LoadBalancer:云服务商专属,下一篇详细介绍
  • Ingress:k8s推荐用ingress-nginx,本篇详细介绍ingress-nginx

ingress-nginx组成

  • ingress controller:将新加入的Ingress转化成Nginx的配置文件并使之生效
  • ingress服务:将Nginx的配置抽象成一个Ingress对象,每添加一个新的服务只需写一个新的Ingress的yaml文件即可

ingress-nginx工作原理

  1. ingress controller通过和kubernetes api交互,动态的去感知集群中ingress规则变化,然后读取它;
  2. 按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置;
  3. 写到nginx-ingress-control的pod里,这个Ingress controller的pod里运行着一个Nginx服务;
  4. 控制器会把生成的nginx配置写入/etc/nginx.conf文件中,然后reload一下使配置生效。
  5. 达到域名分配置和动态更新的问题。

解决问题

  • 动态配置服务
      如果按照传统方式, 当新增加一个服务时, 我们可能需要在流量入口加一个反向代理指向我们新的k8s服务. 而如果用了Ingress, 只需要配置好这个服务, 当服务启动时, 会自动注册到Ingress的中, 不需要额外的操作。
  • 减少不必要的端口暴露
      配置过k8s的都清楚, 第一步是要关闭防火墙的, 主要原因是k8s的很多服务会以NodePort方式映射出去, 这样就相当于给宿主机打了很多孔, 既不安全也不优雅. 而Ingress可以避免这个问题, 除了Ingress自身服务可能需要映射出去, 其他服务都不要用NodePort方式

部署

mkdir -p nginx-ingress
cd nginx-ingress
curl -O https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/cloud/deploy.yaml

因为里面的2个镜像在k8s.gcr.io上,需要科学上网才能正常下载,否则无法正常安装k8s.gcr.io/ingress-nginx/controller:v1.2.0
k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1

kubectl apply -f deploy.yaml 

测试

  1. 部署测试应用
kubectl create deploy echoserver --image=cilium/echoserver --replicas=2

echoserver会简单输出hostname,本次只使用到这一功能

  1. 部署service
# 创建svc,默认以ClusterIP模式创建,只允许集群内部访问
kubectl expose deployment echoserver --port=80

#查看服务,正常两个hostname随机显示 curl http://ClusterIP

  1. 查看ingress-nginx svc
[root@cka-1 ingress-nginx]# kubectl get svc -n ingress-nginx
NAME                                 TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.109.134.0      <pending>     80:32456/TCP,443:32350/TCP   12m
ingress-nginx-controller-admission   ClusterIP      172.18.162.225   <none>        443/TCP                      12m

使用NodePort测试,`kubectl edit svc -n ingress-nginx ingress-nginx-controller修改LoadBalancer为NodePort

  1. 生成nginx策略
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-echoserver-test
spec:
  rules:
  - host: echoserver.test # 域名
    http:
      paths:
      - path: /	# 代理目录
        pathType: Prefix	#path类型,下面
        backend:
          service:
            name: echoserver	# 对应service名称
            port:
              number: 80		# service 端口
  ingressClassName: nginx		# 指定选择的 Ingress Controller
ingress支持的path类型:

ImplementationSpecific:对于这种path类型,匹配取决于IngressClass。可以将其视为一个单独的pathType或者将其认为和Prefix或者Exact路径类型一样。

Exact:精确匹配URL路径,并且区分大小写

Prefix:根据URL中的,被/分割的前缀进行匹配。匹配区分大小写并且按照元素对路径进行匹配。path元素指的是路径中由/分隔符分隔的标签列表。

注意:如果路径的最后一个元素是请求路径中最后一个元素的子字符串,那么这个是不匹配的。

【举例:/foo/bar匹配/foo/bar/baz,但是不匹配/foo/barbaz】

kubectl apply -f ingress-echoserver-test.yaml 

kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-echoserver-test nginx echoserver.test 10.109.134.0 80 20s

  1. 结果

    curl -H "Host: echoserver.test" http://192.168.3.30:32217

    Hostname: echoserver-8585bfb456-f859x

此时还是虽然已经具备nginx规则,但还是需要加上端口,下一篇使用LoadBalancer解决这个问题