如何解析K8S中Service 的Ingress意义与部署
这篇文章给大家介绍如何解析K8S中Service 的Ingress意义与部署,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
前言
ingress 可以理解为 Service 的 Service,即在现有 Service 的前面再搭建一层 Service,作为外部流量的统一入口,进行请求路由的转发。
说白了就是在前端搭建一个 nginx或者haproxy,将不同 host 或 url 转发到对应的后端 Service,再由 Service 转给 Pod。只不过 ingress 对 nginx/haproxy 进行了一些解耦和抽象。
Ingress 的意义
ingress 弥补了默认 Service 暴露外网访问时候的一些缺陷,如不能进行统一入口处的7层 URL 规则,如一个默认 Service 只能对应一种后端服务。
通常说的 ingress 包含 ingress-controller 和 ingress 对象两部分。
ingress-controller 对应 nginx/haproxy 程序,以 Pod 形式运行。
ingress 对象 对应 nginx/haproxy 配置文件。
ingress-controller 使用 ingress 对象中描述的信息修改自身 Pod 中 nginx/haproxy 的规则。
部署 ingress
准备测试资源
部署2个服务,访问服务1,返回 Version 1访问服务2,返回 Version 2
两个服务的程序配置
# cat deployment.yaml apiVersion: apps/v1kind: Deploymentmetadata: name: hello-v1.0spec: selector: matchLabels: app: v1.0 replicas: 3 template: metadata: labels: app: v1.0 spec: containers: - name: hello-v1 image: anjia0532/google-samples.hello-app:1.0 ports: - containerPort: 8080---apiVersion: apps/v1kind: Deploymentmetadata: name: hello-v2.0spec: selector: matchLabels: app: v2.0 replicas: 3 template: metadata: labels: app: v2.0 spec: containers: - name: hello-v2 image: anjia0532/google-samples.hello-app:2.0 ports: - containerPort: 8080---apiVersion: v1kind: Servicemetadata: name: service-v1spec: selector: app: v1.0 ports: - port: 8081 targetPort: 8080 protocol: TCP---apiVersion: v1kind: Servicemetadata: name: service-v2spec: selector: app: v2.0 ports: - port: 8081 targetPort: 8080 protocol: TCP
让容器运行在 8080 上,service 运行在 8081 上。
启动两个服务和对应的 Pod
# kubectl apply -f deployment.yaml deployment.apps/hello-v1.0 createddeployment.apps/hello-v2.0 createdservice/service-v1 createdservice/service-v2 created
查看启动情况,每个服务对应3个 Pod
# kubectl get pod,service -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESpod/hello-v1.0-6594bd8499-lt6nn 1/1 Running 0 37s 192.10.205.234 work01pod/hello-v1.0-6594bd8499-q58cw 1/1 Running 0 37s 192.10.137.190 work03 pod/hello-v1.0-6594bd8499-zcmf4 1/1 Running 0 37s 192.10.137.189 work03 pod/hello-v2.0-6bd99fb9cd-9wr65 1/1 Running 0 37s 192.10.75.89 work02 pod/hello-v2.0-6bd99fb9cd-pnhr8 1/1 Running 0 37s 192.10.75.91 work02 pod/hello-v2.0-6bd99fb9cd-sx949 1/1 Running 0 37s 192.10.205.236 work01 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTORservice/service-v1 ClusterIP 192.20.92.221 8081/TCP 37s app=v1.0service/service-v2 ClusterIP 192.20.255.0 8081/TCP 36s app=v2.0
查看 Service 后端 Pod 挂载情况
[root@master01 ~]# kubectl get ep service-v1NAME ENDPOINTS AGEservice-v1 192.10.137.189:8080,192.10.137.190:8080,192.10.205.234:8080 113s[root@master01 ~]# kubectl get ep service-v2NAME ENDPOINTS AGEservice-v2 192.10.205.236:8080,192.10.75.89:8080,192.10.75.91:8080 113s
可以看到两个服务均成功挂载了对应的 Pod。
下面部署前端 ingress-controller。
首先指定 work01/work02 两台服务器运行 ingress-controller
kubectl label nodes work01 ingress-ready=truekubectl label nodes work02 ingress-ready=true
ingress-controller 使用官方 nginx 版本
wget -O ingress-controller.yaml https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/kind/deploy.yaml
修改为启动 2 个 ingress-controller
# vim ingress-controller.yamlapiVersion: apps/v1kind: Deployment 。。。。。。 。。。。。。 revisionHistoryLimit: 10 replicas: 2 # 新增该行
修改为国内镜像
# vim ingress-controller.yaml spec: dnsPolicy: ClusterFirst containers: - name: controller #image: us.gcr.io/k8s-artifacts-prod/ingress-nginx/controller:v0.34.1@sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:0.32.0 imagePullPolicy: IfNotPresent
部署 ingress-controller
kubectl apply -f ingress-controller.yaml
查看运行情况
# kubectl get pod,service -n ingress-nginx -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESpod/ingress-nginx-admission-create-ld4nt 0/1 Completed 0 15m 192.10.137.188 work03pod/ingress-nginx-admission-patch-p5jmd 0/1 Completed 1 15m 192.10.75.85 work02 pod/ingress-nginx-controller-75f89c4965-vxt4d 1/1 Running 0 15m 192.10.205.233 work01 pod/ingress-nginx-controller-75f89c4965-zmjg2 1/1 Running 0 15m 192.10.75.87 work02 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTORservice/ingress-nginx-controller NodePort 192.20.105.10 192.168.10.17,192.168.10.17 80:30698/TCP,443:31303/TCP 15m app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginxservice/ingress-nginx-controller-admission ClusterIP 192.20.80.208 443/TCP 15m app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
可以看到 work01/02 上运行了 ingress-nginx-controller Pod。
编写访问请求转发规则
# cat ingress.yaml apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata: name: nginx-ingressspec: rules: - host: test-v1.com http: paths: - path: / backend: serviceName: service-v1 servicePort: 8081 - host: test-v2.com http: paths: - path: / backend: serviceName: service-v2 servicePort: 8081
启用规则
# kubectl apply -f ingress.yamlingress.networking.k8s.io/nginx-ingress created
可以看到 ingress-controller Pod 里面 nginx 配置已经生效了
# kubectl exec ingress-nginx-controller-75f89c4965-vxt4d -n ingress-nginx -- cat /etc/nginx/nginx.conf | grep -A 30 test-v1.com server { server_name test-v1.com ; listen 80 ; listen 443 ssl http2 ; set $proxy_upstream_name "-"; ssl_certificate_by_lua_block { certificate.call() } location / { set $namespace "default"; set $ingress_name "nginx-ingress"; set $service_name "service-v1"; set $service_port "8081"; set $location_path "/";
我们在集群外部访问测试。
首先解析域名到work01
# cat /etc/hosts192.168.10.15 test-v1.com192.168.10.15 test-v2.com
访问测试
# curl test-v1.comHello, world!Version: 1.0.0Hostname: hello-v1.0-6594bd8499-svjnf# curl test-v1.comHello, world!Version: 1.0.0Hostname: hello-v1.0-6594bd8499-zqjtm# curl test-v1.comHello, world!Version: 1.0.0Hostname: hello-v1.0-6594bd8499-www76# curl test-v2.comHello, world!Version: 2.0.0Hostname: hello-v2.0-6bd99fb9cd-h8862# curl test-v2.comHello, world!Version: 2.0.0Hostname: hello-v2.0-6bd99fb9cd-sn84j
可以看到不同域名的请求去到了正确的 Service 下面的不同 Pod 中。
再请求 work02
# cat /etc/hosts192.168.10.16 test-v1.com192.168.10.16 test-v2.com# curl test-v1.comHello, world!Version: 1.0.0Hostname: hello-v1.0-6594bd8499-www76# curl test-v1.comHello, world!Version: 1.0.0Hostname: hello-v1.0-6594bd8499-zqjtm# curl test-v2.comHello, world!Version: 2.0.0Hostname: hello-v2.0-6bd99fb9cd-sn84j# curl test-v2.comHello, world!Version: 2.0.0Hostname: hello-v2.0-6bd99fb9cd-h8862
也没问题。
如何高可用
在 work01 / work02 前面再挂2台 LVS+keepalived 就可以实现对 work01/02 的高可用访问了。也可以在 work01 / work02 上直接使用 keepalived 漂一个VIP,不需要额外机器,这样节约成本。
用 Deployment 管理 ingress-controller 的 Pod,使用 NodePort 方式暴露 ingress Service。
查看 ingress service
# kubectl get service -o wide -n ingress-nginxNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTORingress-nginx-controller NodePort 192.20.105.10 192.168.10.17,192.168.10.17 80:30698/TCP,443:31303/TCP 22m app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
可以看到对外暴露了 30698 端口,访问任何节点的 30698 端口即可访问到 v1/v2 版本的 Pod。
但该端口是随机的,并且重建后会变化,我们可以直接访问运行 ingress-controller Pod 的 work01/02 的 80 端口。
work01/02前面再弄一套 LVS+keepalived 进行高可用负载。
work01/02 上使用 iptables -t nat -L -n -v 可以看到 80 端口是通过 NAT 模式开放的,高流量会有瓶颈。
可以使用 DaemonSet + HostNetwork 的方式来部署 ingress-controller。
这样 work01/02 上暴露的 80 端口直接使用宿主机的网络,不走NAT映射,可以避免性能问题。
关于如何解析K8S中Service 的Ingress意义与部署就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。