k8s笔记18--快速入门ingress和ingress controller
1 介绍
Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源上定义的规则控制。
下面是一个将所有流量都发送到同一 Service 的简单 Ingress 示例:
Ingress 不会公开任意端口或协议。 将 HTTP 和 HTTPS 以外的服务公开到 Internet 时,通常使用 Service.Type=NodePort 或 Service.Type=LoadBalancer 类型的 Service。
为了让 Ingress 资源工作,集群必须有一个正在运行的 Ingress 控制器。当controller运行后,每次新增一个 ingress 资源,都会在cotroller 的nginx 配置 nginx.conf 中新增记录,告诉nginx 将请求转发指定的服务中。
当前有很多中ingress controller, 很多云厂商也会定制 一些自己的控制器,本文基于最经典的 ingress-nginx controller 来做相关实验,具体包括部署controller、测试ingress 实例,以及解决常见注意事项。
2 部署 ingress-nginx controller
在 github.com/kubernetes/ingress-nginx/tree/main/deploy/static/provider/baremetal 中找到自己需要的版本,然后 kubectl apply 即可。
$ kubectl apply -f deploy.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
部署成功后,会拉起一个controller的pod和对应的 svc,如下所示:
xghome:~/.kube$ kubectl -n ingress-nginx get deploy,svc
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ingress-nginx-controller 1/1 1 1 3h36m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingress-nginx-controller NodePort 10.108.105.39 <none> 80:30080/TCP,443:30443/TCP 3h36m
service/ingress-nginx-controller-admission ClusterIP 10.105.5.181 <none> 443/TCP 3h36m
此外还会创建一个 IngressClass, 后续新建ingress 的时候需要指定 ingressClassName
xghome:~/.kube$ kubectl get IngressClass
NAME CONTROLLER PARAMETERS AGE
nginx k8s.io/ingress-nginx <none> 3h51m
3 测试
- 准备一个基础镜像 py:hostname
Dockerfile
app.pyFROM python:3.8-slim RUN pip3 install Flask==2.1.2 RUN mkdir -p /home WORKDIR /home USER nobody COPY app.py /home/ CMD python3 -u app.py
打包镜像from flask import Flask app = Flask(__name__) def get_hostname(): hostname = '' with open('/etc/hostname', 'r') as f: line = f.readline() hostname = line.replace('\n', '') return hostname @app.route('/') @app.route('/<service>') def hello_world(service=None): # put application's code here hostname = get_hostname() if service is None: return f'Hello {hostname}\n' else: return f'Hello {hostname}, from {service}\n' if __name__ == '__main__': app.run(port=80, host="0.0.0.0")
docker build -t py:hostname .
- 部署服务test01 和 test02
test01.yaml
test02.yamlapiVersion: apps/v1 kind: Deployment metadata: labels: app: test01 name: test01 spec: replicas: 1 selector: matchLabels: app: test01 template: metadata: labels: app: test01 spec: containers: - image: py:hostname name: test01 --- apiVersion: v1 kind: Service metadata: labels: app: test01 name: test01 spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: test01
apiVersion: apps/v1 kind: Deployment metadata: labels: app: test02 name: test02 spec: replicas: 1 selector: matchLabels: app: test02 template: metadata: labels: app: test02 spec: containers: - image: py:hostname name: test02 --- apiVersion: v1 kind: Service metadata: labels: app: test02 name: test02 spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: test02
- 部署 ingress
test-ingress.yamlapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: test spec: ingressClassName: nginx rules: - host: "test.xg.com" http: paths: - pathType: Prefix path: "/test01" backend: service: name: test01 port: number: 80 - host: "test.xg.com" http: paths: - pathType: Prefix path: "/test02" backend: service: name: test02 port: number: 80
- 前端测试
如下图, test01 刚好进入到test01 的pod中,/test02 刚好进入到test02 的pod中,测试符合预期
注意:
这里配置 nginx-ingress-controller 的 80端口为30080, 因此此处需要加上30080, 若在ingress controller 的外层加一个lb, 那么直接访问lb的ip即可。
此时 test.xg.com 直接指向nginx controller的ip。若需要实现局域网|PC虚拟机之间的dns,可以参考ubuntu小技巧27–基于dnsmasq快速搭建局域网dns服务器
4 注意事项
-
笔者自己的服务器上没有专用的 lb, 因此直接将服务的域名指向 controller 的 ip; 实际项目中一般都会有专用 lb,lb 会对接到ingress controller 的多个节点,配置域名的时候直接指向 lb 的 ip 即可。
-
指定ingress | 设置默认ingress
方法1:创建ingress的时候需要指定 spec.ingressClassName: nginx
方法2: 配置默认ingress1) 在ingress-controller 中加参数 --watch-ingress-without-class=true 2) 配置默认的 IngressClass, 在 annotations 中新增 ingressclass.kubernetes.io/is-default-class: "true"
-
解决无法拉国外镜像的问题
若拉不下来,更改为阿里云的镜像即可(按需更改前缀即可,截至2023-08已经可以使用1.8.1了) registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.8.1 registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v20230407
5 说明
软件环境:
ubuntu server 18.04
k8s 1.23.6
ingress controller v1.2.0
参考文档:
Kubernetes 文档/概念/服务、负载均衡和联网/Ingress
Kubernetes 文档/概念/服务、负载均衡和联网/Ingress控制器
ngress-nginx/master/deploy/static/mandatory.yaml
nginx-0.30.0/deploy/static/mandatory.yaml
github ingress
kubernetes 创建ingress不生效
ubuntu小技巧27–基于dnsmasq快速搭建局域网dns服务器