k8s安装ingress-nginx/tengine-ingress
背景
要先会各种概念,node,pods,service
术语 ingress:指定是k8s的用户业务语境,描述用户的业务流量经过的一个转发环节。是用户视角。
术语 ingress-controller:指定是k8s的实现架构语境,指k8s作为一个基础设施,他的一个组件的名称。
文档
从0到1:k8s集群从0到1安装部署
官方手册:https://kubernetes.io/docs/concepts/services-networking/ingress/
安装
第一步需要安装ingress-controller
我选ingress-nginx:https://kubernetes.github.io/ingress-nginx/deploy/
执行命令
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.0/deploy/static/provider/cloud/deploy.yaml
运行效果

部署服务
kubectl create deployment demo --image=httpd --port=80
kubectl expose deployment demo
kubectl create ingress demo-localhost --class=nginx --rule="demo.localdev.me/*=demo:80"
# 还有一个步骤在这,要添加一个external ip的静态配置,见后文。
可以看见创建了一个服务和一个ingress和一个ingress-controller service在ingress-nginx namespace中。

测试端口流量
kubectl port-forward --namespace=ingress-nginx service/ingress-nginx-controller 8080:80 // 测试手法,非生产使用。
curl --resolve demo.localdev.me:8080:127.0.0.1 http://demo.localdev.me:8080
效果:

直接访问cluster
配置cluster ip在本地是能直接访问的。

为cluster配置外部IP的方法
https://kubernetes.io/docs/concepts/services-networking/service/#external-ips
使用编辑命令 kubectl edit service my-service

添加如下行后,保存退出。
测试:

也可以用配置文件创建ingress:ingress-example.yaml
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: minimal-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: ingressClassName: nginx-example rules: - http: paths: - path: / pathType: Prefix backend: service: name: demo port: number: 80
kubectl apply -f ingress-example.yaml

红字里的 class的值代表选择什么ingress-controller。可以安装多个不同的ingress-controller,部署ingress时通过class字段进行选择。
如果用ingress-nginx,前文的nginx-example应该写成nginx。
还可以在线修改,使用如下命令,编辑即修改,保存即生效
kubectl edit ingress test
安装ingress-tengine
如果上边的步骤都成功了,安装ingress-tengine非常简单,参考官方文档
https://tengine.taobao.org/document/ingress_quickstart.html
完成前三个步骤:1 tengine-ingress Deployment, 2 Configmap, 3 权限之后,可以看见pod运行成功

第四步的ingressclass是把tengine-ingress设置为默认ingress,这步我没有做。
继续安装官方文档部署一个测试服务。
文档里的原配置使用了80端口,会报如下无权限的错误:

因为1024一下的端口需要超级权限,因为初学这块知识盲区,选择绕行,改端口为1080,配置如下:
apiVersion: apps/v1 kind: Deployment metadata: name: echo-deployment spec: selector: matchLabels: app: echo replicas: 1 template: metadata: labels: app: echo spec: containers: - name: echo image: hashicorp/http-echo:latest ports: - containerPort: 1080 args: ["-listen", ":1080", "-text", "hello world"] --- apiVersion: v1 kind: Service metadata: name: echo-service spec: ports: - name: http port: 1080 targetPort: 1080 selector: app: echo
成功后的样子:

在部署ingress之前,对比ingress-nginx的安装步骤。发现tengine文档里的yaml并不完成,系统里当前并没有安装 tengine-ingress-controller的service。
使用如下配置,创建tengine的controller service
apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: tengine-ingress app.kubernetes.io/name: tengine-ingress app.kubernetes.io/part-of: tengine-ingress name: tengine-ingress-controller spec: externalTrafficPolicy: Local externalIPs: - 192.168.56.107 ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - appProtocol: http name: http port: 80 protocol: TCP targetPort: http selector: app: tengine type: LoadBalancer
效果如下:

下一步为echo-server创建ingress 资源,示例配置如下:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-echo annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: # type: LoadBalancer ingressClassName: tengine rules: - host: echo.test.com http: paths: - path: / pathType: Prefix backend: service: name: echo-service port: number: 80
但是ingress拿不到 ADDRESS,通过查看tengine日志打印,发现是role的权限问题。

查看pod日志,有如下报错:
E0303 11:03:28.077432 7 main.go:50] “Error getting node” err=“nodes "k8s-node0" is forbidden: User "system:serviceaccount:default:default" cannot get resource "nodes" in API group "" at the cluster scope” name=“k8s-node0”
修改role配置,添加权限。增加如下行:
kubectl edit clusterrole tengine-cluster-role

测试成功:

最终效果

ConfigMap
https://kubernetes.io/docs/concepts/configuration/configmap/
是一种让镜像与配置分离的方法。回顾前文的步骤,我们在安装tengine的时候已经创建了一个configmap,通过如下命令可以查看到



常用命令
查看pods前一次崩溃的日志
kubectl logs pods/echo-deployment-7ffc89dc66-qnc67 --previous
如果一个pod里有多个container,查看一个pod下的container列表
crictl ps -a |grep echo
查看指定container的日志
kubectl logs pods/echo-deployment-7ffc89dc66-qnc67 --previous -c echo
故障排查
Q:kubectl apply之后发现大量处于被驱逐状态Evicted的pod
该情况一般是资源不足。使用命令
kubectl describe pod <pod-name> | grep "Reason:"
发现是硬盘满了。扩充硬盘后恢复正常。参考:[administrative][lvm] lvm 分区修改
Q:ingress获取不到external IP,如图

分析:
ingress的ADDRESS字段是由ingress-controller进行赋值的,需要检查ingress-controller的配置,判断为什么没有进行赋值。
ingress-controller有一个service,查看的它的externel-ip,发现处于pending状态

根据前文的步骤,手工修改yaml为service添加一个external-ip。使用kubectl edit命令
https://stackoverflow.com/questions/44110876/kubernetes-service-external-ip-pending

操作完成后,验证成功

衍生问题,loadbalancer类型的service为什么要与云提供商联动获取external ip?
个人理解:
loadbalancer类型的service就是特指有一个外部loadbalancer(4或7层)顶在前面的情况。它提供两个功能。
1 为在公有云环境下运行的k8s集群提供公网接入的能力。公网接入的管控由云平台提供,而不是k8s集群自己提供。
2 为service的多个pod节点提供高可用能力。
ingress的存在,主要作用是提供:1基于7层的分发策略,2所有service的统一收口和管理。
然后,ingress本身也是一个service,所以如果它有 a公网接入需要 b高可用需求 时,自然也需要外部LB,也就是说,ingress service也有成为loadbalancer类型的需求。
https://blog.csdn.net/g6U8W7p06dCO99fQ3/article/details/127158134
这个好:https://kubesphere.io/zh/blogs/kubesphere-loadbalance/
也好:https://chuna2.787528.xyz/binghe001/p/13166641.html
Q 创建好的service,访问端口不通,是为什么?
可以看见我得tengine pods和tengine service已经创建好了。也配置了本地clusterIP用于测试,但是服务访问不通。

查看endpoint,使用命令:kubectl get endpoints tengine-ingress-controller
验证label没有问题,使用命令:kubectl get pods -l app=tengine

如上现象代表如下情况:
service的target port与pod的container port没有匹配起来,查看配置文件,果真如此:
service的配置:

pod的配置 (下文截图中的红框是后加的,修改之前没有)

添加了红框的内容后,重新安装了pod,可以成功了

其他
hingress: https://github.com/alibaba/higress
浙公网安备 33010602011771号