Ingress是一种Kubernetes资源,用于将外部流量路由到Kubernetes集群内的服务。与NodePort相比,它提供了更高级别的路由功能和负载平衡,可以根据HTTP请求的路径、主机名、HTTP方法等来路由流量。
因此,可以说Ingress是为了弥补NodePort在流量路由方面的不足而生的。使用NodePort,只能将流量路由到一个具体的Service,并且必须使用Service的端口号来访问该服务。但是,使用Ingress,就可以使用自定义域名、路径和其他HTTP头来定义路由规则,以便将流量路由到不同的Service。
tantianran@test-b-k8s-master:~$ kubectl api-resources | grep ingress
ingressclasses networking.k8s.io/v1 false IngressClass
ingresses ing networking.k8s.io/v1 true Ingress
此外,Ingress还可以与负载均衡器配合使用,以提供高可用性和水平扩展。这些功能使得Ingress比NodePort更适合在生产环境中使用。
刚才提到,Ingress 需要配合 Ingress Controller 使用,需要注意了,不同的 Ingress Controller 可能支持的功能和配置方式不同,需要根据实际情况进行选择和配置。
总之,Kubernetes 的 Ingress 资源对象需要配合 Ingress 控制器才能实现外部流量的转发和路由。Ingress 控制器是 Ingress 资源的实际执行者,负责根据定义的路由规则配置网络代理。
在 Kubernetes 中,有很多不同的 Ingress 控制器可以选择,例如 Nginx、Traefik、HAProxy、Envoy 等等。不同的控制器可能会提供不同的功能、性能和可靠性,可以根据实际需求来选择合适的控制器。Kubernetes生态系统中有许多不同的Ingress控制器可供选择,其中比较主流的有:
可以根据实际需要选择适当的Ingress控制器,并进行相应的配置和部署。
Ingress控制器通常建议部署在 Kubernetes 集群内部。这样可以确保 Ingress 控制器与 Kubernetes API Server 之间的网络延迟较低,并且可以通过 Kubernetes Service 来管理 Ingress 控制器的负载均衡和高可用性。在 Kubernetes 集群内部部署 Ingress 控制器通常有两种方式:
无论是哪种方式,Ingress 控制器都应该被部署在 Kubernetes 集群内部,以便与 Kubernetes API Server 进行通信,并与 Kubernetes 资源(如 Service、Pod、Endpoints 等)进行交互。
Nginx 是一个高性能的 Web 服务器和反向代理服务器,可以提供静态内容的快速响应,同时也可以通过反向代理将请求转发到后端应用程序。
Nginx Ingress 是基于 Nginx 的 Kubernetes Ingress 控制器,它可以在 Kubernetes 集群中提供负载均衡、路由和 TLS 终止等功能。它将 Kubernetes Ingress API 对象转换为 Nginx 配置,并将其应用于 Nginx 服务器。通过 Nginx Ingress,可以轻松地将 HTTP(S) 流量路由到 Kubernetes 中的不同服务。
https://kubernetes.github.io/ingress-nginx/ https://github.com/kubernetes/ingress-nginx/
安装 Nginx Ingress Controller 的方式有多种,以下是其中的一些:
无论选择哪种方式,都需要根据实际情况进行调整和配置,以确保 Nginx Ingress Controller 能够正常工作。
使用Helm安装:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
kubectl create namespace ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--set controller.publishService.enabled=true
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx
上面的命令将在命名空间中安装控制器,如果该命名空间尚不存在,则创建该命名空间ingress-nginx。 此命令是幂等的:
使用YAML安装:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/cloud/deploy.yaml
mv deploy.yaml ingress-nginx-controller.yaml
kubectl apply -f ingress-nginx-controller.yaml
# 或者直接
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/cloud/deploy.yaml
注意,可能会应网络问题无法拉取相关镜像,可以修改ingress-nginx-controller.yaml文件里image字段的仓库地址,我已经把镜像传到我的Docker Hub仓库中:
例如,修改后:
tantianran@test-b-k8s-master:~$ egrep "image" ingress-nginx-controller.yaml | grep -v imagePullPolicy
image: tantianran/ingress-controller:v1.6.4
image: tantianran/kube-webhook-certgen:v20220916-gd32f8c343
image: tantianran/kube-webhook-certgen:v20220916-gd32f8c343
tantianran@test-b-k8s-master:~$ kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-z4hlb 0/1 Completed 0 47h
ingress-nginx-admission-patch-ffbwz 0/1 Completed 0 47h
ingress-nginx-controller-5f4c9fdd9b-l55ch 1/1 Running 1 (10m ago) 47h
「有没有注意到nginx-admission-create和ingress-nginx-admission-patch这两个pod的状态是Completed?」 当这两个Pod被创建时,它将开始运行容器,执行必要的初始化和验证操作,然后尝试处理Kubernetes API server发送的请求。如果请求已经被处理完毕,容器将正常终止,并将Pod的状态设置为Completed。因此,Pod处于Completed状态并不表示有任何问题或错误,而是表示容器已经完成了它需要完成的任务并终止了运行。
需要注意的是,如果在Pod终止之前出现错误或异常,Pod的状态将会被设置为Failed,这可能需要进行进一步的故障排除和修复。
tantianran@test-b-k8s-master:~$ kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.106.241.48 <pending> 80:30806/TCP,443:30178/TCP 2d
ingress-nginx-controller-admission ClusterIP 10.109.39.65 <none> 443/TCP 2d
tantianran@test-b-k8s-master:~$
ingress-nginx-controller Service:这个Service负责将请求转发到ingress-nginx-controller Pods。它通常会将流量分发到ingress-nginx-controller的多个副本中,并确保副本集的负载平衡。这个Service可以被配置为使用NodePort、LoadBalancer或ClusterIP类型,根据需要进行暴露。
ingress-nginx-controller-admission Service:这个Service是用于 Kubernetes Admission Webhooks 的,允许在创建、更新或删除资源时,对其进行校验或修改。它提供了一个API Endpoint,用于与 Kubernetes API Server 进行通信,以便进行这些校验或修改。该Service也可以被配置为使用NodePort、LoadBalancer或ClusterIP类型,根据需要进行暴露。
通常情况下,ingress-nginx-controller和ingress-nginx-controller-admission都是在同一个Deployment中运行的,以确保它们始终具有相同的标签。这些标签允许其他Kubernetes对象(例如Ingress)可以识别哪些Pods是由ingress-nginx-controller和ingress-nginx-controller-admission负责的,并将请求路由到正确的Pods中。
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: test-goweb
name: test-goweb
spec:
replicas: 6
selector:
matchLabels:
app: test-goweb
template:
metadata:
labels:
app: test-goweb
spec:
containers:
- image: 192.168.11.247/web-demo/goweb-demo:20221229v3
name: goweb-demo
ports:
- containerPort: 8090
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
labels:
app: test-goweb
name: test-goweb
spec:
ports:
- name: 80-8090
port: 80
protocol: TCP
targetPort: 8090
selector:
app: test-goweb
type: ClusterIP
在上面的Yaml配置文件中,采用的Service类型是ClusterIP类型,ClusterIP类型的Service只能从K8S集群内部访问,因此需要将其与Ingress Controller结合使用,以便外部客户端可以访问集群中的应用程序。当客户端请求到达Ingress时,Ingress Controller会将请求路由到相应的Service,然后Service再将请求路由到Pod中运行的容器。
kubectl apply -f test-goweb.yaml
tantianran@test-b-k8s-master:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 120d
test-goweb ClusterIP 10.105.248.32 <none> 80/TCP 81m # 这个等会是要用到的,Service名称为test-goweb,端口为80
tantianran@test-b-k8s-master:~$
tantianran@test-b-k8s-master:~$ kubectl get ingressclass
NAME CONTROLLER PARAMETERS AGE
nginx k8s.io/ingress-nginx <none> 2d2h # 这个nginx控制器就是我们等会要用的
tantianran@test-b-k8s-master:~$
在k8s中,Ingress 资源对象可以用来暴露服务,将外部流量路由到内部集群服务。但是,在一个集群中,可能需要使用不同的 Ingress 控制器来满足不同的需求,而每个控制器都需要使用不同的配置和规则。这就是 IngressClass 的作用。通过定义不同的 IngressClass,可以为不同的 Ingress 控制器指定不同的配置和规则,从而更好地管理 Ingress 资源对象。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-goweb
spec:
ingressClassName: nginx
rules:
- host: "test.noblameops.local"
http:
paths:
- path: /login
pathType: Prefix
backend:
service:
name: test-goweb
port:
number: 80
- path: /home
pathType: Prefix
backend:
service:
name: test-goweb
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: test-goweb
port:
number: 80
这个 Ingress 配置了3个路径,后端为同一个Services,下面仅拿路径"/"做讲解:
开始创建
kubectl apply -f test-goweb-ingress.yaml
tantianran@test-b-k8s-master:~$ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
test-goweb nginx test.noblameops.local 10.105.254.90 80 9m32s
tantianran@test-b-k8s-master:~$
这条命令输出了一个名为 test-goweb 的 Ingress 资源,它将路由到 test.noblameops.local 这个主机名,并在端口 80 上监听请求。我们来看看输出字段的意义:
当使用K8S中的Ingress资源对象来暴露应用时,用户访问应用的入口是 Ingress Controller 的地址。Ingress Controller 会根据 Ingress 规则将请求路由到相应的服务,并将服务的响应返回给客户端。这时候就要把Ingress Controller暴露出去,暴露方式有以下几种:
接下来的场景,我们采用NodePort方式来暴露Ingress Controller。
从下面的查询结果可以看到,ingress-nginx-controller的Service类型默认是LoadBalancer,该类型可以通过云提供商的负载均衡器(如 AWS ELB、Google Cloud Load Balancer 等)来公开服务。
tantianran@test-b-k8s-master:~$ kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.106.241.48 <pending> 80:30806/TCP,443:30178/TCP 2d6h
ingress-nginx-controller-admission ClusterIP 10.109.39.65 <none> 443/TCP 2d6h
tantianran@test-b-k8s-master:~$
我的环境是本地的K8S环境,我只是需要在本地 K8S 环境中进行测试和开发而已,所以可以将其修改为 NodePort 类型,以便将服务公开到集群内的所有节点。NodePort 类型的 Service 可以将服务公开到 K8S 集群中的所有节点的固定端口,这种方式就是适用于本地测试和开发环境。
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.6.4
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
externalTrafficPolicy: Local
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- appProtocol: http
name: http
port: 80
protocol: TCP
targetPort: http
nodePort: 30080 # 增加此处
- appProtocol: https
name: https
port: 443
protocol: TCP
targetPort: https
nodePort: 30443 # 增加此处
selector:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
type: NodePort # 修改此处
修改完成后干掉原来的再重新创建:
kubectl delete -f ingress-nginx-controller.yaml
kubectl create -f ingress-nginx-controller.yaml
tantianran@test-b-k8s-master:~$ kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.100.117.82 <none> 80:30080/TCP,443:30443/TCP 9s # 成功修改为NodePort类型
ingress-nginx-controller-admission ClusterIP 10.101.46.195 <none> 443/TCP 9s
tantianran@test-b-k8s-master:~$ kubectl get pod -n ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-nginx-admission-create-ftntz 0/1 Completed 0 10m 10.244.240.43 test-b-k8s-node01 <none> <none>
ingress-nginx-admission-patch-9xvhv 0/1 Completed 1 10m 10.244.240.49 test-b-k8s-node01 <none> <none>
ingress-nginx-controller-55cbbdbf87-dq558 1/1 Running 0 10m 10.244.240.23 test-b-k8s-node01 <none> <none>
tantianran@test-b-k8s-master:~$
ingress-nginx-controller的POD只设置了1个,且当前是运行在 test-b-k8s-node01 节点上,该节点的宿主机IP就可以作为入口了,然后在系统hosts添加域名映射:
192.168.11.14 test.noblameops.local
下面使用cfssl工具给域名test.noblameops.local生成自签名证书,并在k8s中使用nginx ingress以https的方式暴露。
curl -L https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssl_1.5.0_linux_amd64 -o cfssl
curl -L https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssljson_1.5.0_linux_amd64 -o cfssljson
curl -L https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssl-certinfo_1.5.0_linux_amd64 -o cfssl-certinfo
chmod +x cfssl cfssljson cfssl-certinfo
mv cfssl cfssljson cfssl-certinfo /usr/local/bin/
cat > cert.json <<EOF
{
"hosts": [
"test.noblameops.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "GuangDong",
"L": "GuangZhou",
"O": "Noblameops",
"OU": "Noblameops",
"CN": "test.noblameops.local"
}
]
}
EOF
其中,"hosts"字段指定要包含在证书中的主机名或IP地址,这里只包含了"test.noblameops.local";"key"字段指定使用RSA算法和2048位密钥生成证书;"names"字段指定证书中的各种名称和标识,包括组织、部门和通用名称(CN)。
cfssl gencert -initca cert.json | cfssljson -bare test.noblameops.local
这将生成三个文件:test.noblameops.local.csr、test.noblameops.local-key.pem和test.noblameops.local.pem。其中,test.noblameops.local.pem是证书文件,test.noblameops.local-key.pem是证书私钥文件。
kubectl create secret tls test-noblameops-local-tls --key test.noblameops.local-key.pem --cert test.noblameops.local.pem
kubectl get secret
其中,test-noblameops-local-tls是secret对象的名称,--key参数指定私钥文件的路径,--cert参数指定证书文件的路径。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-goweb
spec:
ingressClassName: nginx
tls:
- hosts:
- test.noblameops.local
secretName: test-noblameops-local-tls
rules:
- host: "test.noblameops.local"
http:
paths:
- path: /login
pathType: Prefix
backend:
service:
name: test-goweb
port:
number: 80
- path: /home
pathType: Prefix
backend:
service:
name: test-goweb
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: test-goweb
port:
number: 80
本文转载于WX公众号:不背锅运维:https://mp.weixin.qq.com/s/2pBiTgnLgSQLrIi4yGHEew
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。