一、Ingress介绍
Ingress是Kubernetes中负责将外部请求引导到集群内部服务的机制,通过将服务映射到集群外的URL,实现服务的外部可访问性。Ingress支持配置集群内的Service,使其可以通过外部URL访问,同时提供流量负载均衡和基于域名的虚拟主机等功能。
简单理解Ingress就是将原本需要手动修改Nginx配置、配置域名与服务映射的繁琐步骤,抽象成一个Ingress对象。通过使用YAML文件创建和更新Ingress对象,我们不再需要手动操作Nginx配置文件,而是通过更方便的方式管理域名与服务的关系。
然而,这引发了一个问题:“Nginx应该如何处理这些变化?”这时候,Ingress Controller登场,专门解决Nginx处理方式的问题。Ingress Controller与Kubernetes API进行交互,实时感知集群中Ingress规则的变化。一旦有变化,Ingress Controller会读取这些规则,并根据自己的模板生成相应的Nginx配置。随后,它将这段配置写入Nginx Pod,最后触发Nginx的重载操作,确保配置的生效。
通过Ingress和Ingress Controller的配合,我们在管理外部访问时变得更加灵活和便捷,摆脱了手动修改Nginx配置的烦恼,让我们能够更专注于服务与域名的映射关系,提升了Kubernetes集群的可维护性。
1.Ingress Controller介绍
Ingress Controller是一种七层负载均衡调度器,它作为客户端请求的第一站,接收并处理所有外部请求。在这个七层负载均衡调度器的作用下,请求会经过反向代理,最终被路由到后端的Pod。常见的七层负载均衡器包括nginx、traefik等。以我们熟悉的nginx为例,当请求到达nginx时,nginx会通过upstream配置反向代理到后端Pod应用。
Ingress Controller
然而,后端Pod的IP地址是动态变化的,为了解决这个问题,我们引入了Service。这个Service并非实际的服务,而是起到了对后端Pod的分组作用。因此,在配置upstream时,我们只需要填写Service的地址即可,而不需要关心后端Pod的具体IP地址。
通过这样的设计,Ingress Controller能够灵活处理后端Pod的变化,保证请求能够正确地路由到集群中的服务。这种模式使得我们能够更方便地管理后端服务的变化,而不必担心Pod的IP地址的不断变化所带来的问题。
2.Ingress资源
一个最小的 Ingress 资源示例:
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:/testpath
pathType:Prefix
backend:
service:
name:test
port:
number:80
Ingress 需要指定 apiVersion、kind、 metadata和 spec 字段。Ingress 对象的命名必须是合法的 DNS 子域名名称[1]。
3.Ingress Controller代理k8s内部应用的流程
- 部署Ingress controller,我们ingress controller使用的是nginx
- 创建Pod应用,可以通过控制器创建pod
- 创建Service,用来分组pod
- 创建Ingress http,测试通过http访问应用
- 创建Ingress https,测试通过https访问应用
必须具有 ingress 控制器,才能满足 Ingress 的要求。仅创建 Ingress 资源无效。
Ingress
(1) 部署ingress-nginx
这里同样使用killercoda平台进行测试,该平台部署的是最新版V1.29.0的K8S环境。
由于该环境没有部署Ingress。以下通过部署ingress-nginx[2]为例。通过查阅ingress-nginx官方,了解V1.29.0对应的是Ingress-NGINX 的V1.10.0或v1.9.6。如下:
Ingress-NGINX的版本列表
通过执行如下命令部署Ingress-NGINX 的V1.10.0。
kubectl apply -f \
https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.0/deploy/static/provider/cloud/deploy.yaml
执行完上述命令,输出如下结果:
通过如下命令查看部署情况:
controlplane $ kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-d69wp 0/1 Completed 0 102s
ingress-nginx-admission-patch-hkv66 0/1 Completed 0 102s
ingress-nginx-controller-7dcdbcff84-gfqcs 1/1 Running 0 102s
controlplane $ kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.98.23.38 <pending> 80:30770/TCP,443:31444/TCP 3m57s
ingress-nginx-controller-admission ClusterIP 10.102.219.183 <none> 443/TCP 3m57s
(2) 部署后端tomcat服务
通过部署tomcat服务测试Ingress HTTP代理k8s内部站点,编写如下资源清单:
apiVersion:v1
kind:Service
metadata:
name:tomcat
namespace:default
spec:
selector:
app:tomcat
release:canary
ports:
-name:scport
targetPort:8080
port:8009
---
apiVersion:apps/v1
kind:Deployment
metadata:
name:tomcat-deploy
namespace:default
spec:
replicas:2
selector:
matchLabels:
app:tomcat
release:canary
template:
metadata:
labels:
app:tomcat
release:canary
spec:
containers:
-name:tomcat
image:tomcat:8.5.34-jre8-alpine
imagePullPolicy:IfNotPresent
ports:
-name:containerport
containerPort:8080
name:ajp
containerPort:8009
查看pod是否部署成功:
controlplane $ kubectl apply -f ingress-demo.yaml
service/tomcat created
deployment.apps/tomcat-deploy created
controlplane $ kubectl get pod
NAME READY STATUS RESTARTS AGE
tomcat-deploy-7c67c4d459-5s859 1/1 Running 0 11m
tomcat-deploy-7c67c4d459-bvp2k 1/1 Running 0 11m
(3) 编写Ingress规则
apiVersion:networking.k8s.io/v1
kind:Ingress
metadata:
name:ingress-myapp
namespace:default
annotations:
nginx.ingress.kubernetes.io/rewrite-target:/
spec:
ingressClassName:nginx
rules:# 定义后端的转发规则
-host:tomcat.test.com# 通过域名进行转发
http:
paths:
-path:/#配置访问路径,如果通过url进行转发。需要修改,空的默认访问路径是"/"
pathType:Prefix
backend:# 配置后端服务
service:
name:tomcat# 配置关联的serverce
port:
number:8080# service暴露的端口
ingressClassName:这个值可以通过kubectl get ingressclasses。
查看ingress-myapp的详细信息:
controlplane $ kubectl apply -f ingress-myapp.yaml
ingress.networking.k8s.io/ingress-myapp created
controlplane $ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-myapp nginx tomcat.test.com 80 8s
controlplane $ kubectl describe ingress ingress-myapp
Name: ingress-myapp
Labels: <none>
Namespace: default
Address:
Ingress Class: nginx
Default backend: <default>
Rules:
Host Path Backends
---- ---- --------
tomcat.test.com
/ tomcat:8080 ()
Annotations: nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 62s nginx-ingress-controller Scheduled for sync
查看ingress-nginx部署到那个节点上,如下图:
通上图可知ingress-nginx部署到node1上,并且SVC方式是通过LoadBalancer方式部署。如果,要访问到这个后端tomcat服务,需要做域名的解析。如下:
...省略..
172.30.2.2 tomcat.test.com
正常访问如下:
4.CKA真题
(1) 真题截图
(2) 中文解析
切换 k8s 集群环境:kubectl config use-context k8s
Task:
如下创建一个新的 nginx lngress资源:
名称:pong Namespace:ing-internal
使用服务端口 5678 在路径 /hi 上公开服务hi
可以使用以下命令检查服务 hi 的可用性,该命令应返回 hi, curl -kL/hi
(3) 官方参考文档
Ingress[3]
(4) 解题作答
切换 k8s 集群环境:
kubectl config use-context k8s
创建一个名为pong.yaml。资源内容如下:
apiVersion:networking.k8s.io/v1
kind:Ingress
metadata:
name:pong
namespace:ing-internal
annotations:
nginx.ingress.kubernetes.io/rewrite-target:/
spec:
ingressClassName:nginx-example
rules:
-http:
paths:
-path:/hi
pathType:Prefix
backend:
service:
name:hi
port:
number:5678
- ingressClassName的值,建议在考试的时候通过kubectl get ingressclasses
- service.name的值,题目中没有告诉,建议在考试时候可以通过kubectl get svc 查看
提交资源清单:
kubectl apply -f pong.yaml
通过curl -kL<INTERNAL_IP>/hi验证,看是否返回hi。
参考资料:
- [1]DNS 子域名名称: https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/names#dns-subdomain-names
- [2]ingress-nginx: https://github.com/kubernetes/ingress-nginx
- [3]Ingress: https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/