0. 简介
前面我们介绍过k8s Service,Service 虽然可以对外暴露服务,比如 NodePort 类型,但是每个服务都会占用一个机器端口,这在服务数量增多后是不可接受的。因此,k8s 设计了 Ingress 用于将内部服务暴露到外部。Ingress 工作在 OSI模型的第七层。
后续 k8s 基于实际现状和需求,提出了 Gateway API 作为 Ingress 的继任者。
Ingress
Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。
Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。
Ingress 目前已停止更新。新的功能正在集成至网关 API 中。
Ingress 控制器
为了让 Ingress 资源工作,集群必须有一个正在运行的 Ingress 控制器。
Kubernetes 作为一个项目,目前支持和维护 AWS、 GCE 和 Nginx Ingress 控制器。
这里需要注意的是:
- ingress-nginx 是由Kubernetes社区基于Nginx Web服务器开发的,并补充了一组用于实现额外功能的Lua插件,作为"官方"默认控制器支持当然最优。
- nginx-ingress 是 Nginx 官方社区开发产品,Nginx ingress 具有很高的稳定性,持续的向后兼容性,没有任何第三方模块,并且由于消除了 Lua 代码而保证了较高的速度。
1. Kind 部署 Ingress
1.1 部署 ingress-nginx controller
可以参考kind/ingress,下载:
bash
~ wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
--2023-12-19 20:28:52-- https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
正在解析主机 raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.109.133, 185.199.108.133, 185.199.110.133, ...
正在连接 raw.githubusercontent.com (raw.githubusercontent.com)|185.199.109.133|:443... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:16613 (16K) [text/plain]
正在保存至: "deploy.yaml"
deploy.yaml 100%[=========================================================================================================================================>] 16.22K --.-KB/s 用时 0.007s
2023-12-19 20:28:53 (2.13 MB/s) - 已保存 "deploy.yaml" [16613/16613])
然后应用:
bash
~ 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
networkpolicy.networking.k8s.io/ingress-nginx-admission created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
arduino
kubectl get pods --namespace ingress-nginx
这个时候会发现 ingress-nginx-controller 一直处于Pending状态,describe 后发现是 node 的 label 设置不准确,原因是我们没有按照指示文档设置 node 的label,如下:
yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
- role: worker
- role: worker
- role: worker
然后我们就得重新创建一遍 kind,并且执行以上的命令,最后可以看到 controller 在运行状态:
bash
kubectl get pod --namespace ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-nginx-admission-create-lwqr8 0/1 Completed 0 18m 10.244.1.2 multi-worker <none> <none>
ingress-nginx-admission-patch-nn7r8 0/1 Completed 2 18m 10.244.3.2 multi-worker3 <none> <none>
ingress-nginx-controller-d9b6d7bf5-p6dsq 1/1 Running 0 18m 10.244.0.5 multi-control-plane <none> <none>
1.2 创建 Ingress
创建服务
和3. k8s Service中类似,我们创建两个 ClusterIP 类型的服务及其 Deployment:
yaml
# custom
kind: Deployment
apiVersion: apps/v1
metadata:
name: custom
spec:
selector:
matchLabels:
app: custom
replicas: 2
template:
metadata:
labels:
app: custom
spec:
containers:
- name: custom
image: k8s_service
imagePullPolicy: Never
---
apiVersion: v1
kind: Service
metadata:
name: custom
spec:
ports:
- name: http
port: 9090 # image默认输出5678
targetPort: 9090
selector:
app: custom
# echo
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: http-echo
spec:
selector:
matchLabels:
app: echo
replicas: 2
template:
metadata:
labels:
app: echo
spec:
containers:
- name: http-echo
image: hashicorp/http-echo:latest
args:
- "-listen=:9090"
---
apiVersion: v1
kind: Service
metadata:
name: echo
spec:
ports:
- name: http
port: 9090 # image默认输出5678
targetPort: 9090
selector:
app: echo
然后 kubectl apply -f
执行文件即可,可以发现:
bash
~ kubectl get pod
NAME READY STATUS RESTARTS AGE
custom-5c5c478dcb-pbmqc 1/1 Running 0 2m19s
custom-5c5c478dcb-w4z6q 1/1 Running 0 2m19s
http-echo-5b5cff99fc-2cs8z 1/1 Running 0 2m19s
http-echo-5b5cff99fc-54x6n 1/1 Running 0 2m19s
~ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
custom ClusterIP 10.96.40.245 <none> 9090/TCP 2m39s
echo ClusterIP 10.96.250.90 <none> 9090/TCP 2m39s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14h
创建 Ingress
以上实现的是两个 ClusterIP 的服务,我们在集群外部无法访问,需要创建 Ingress,首先创建ingress.yaml
:
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
spec:
rules:
- host: iguochan.org
http:
paths:
- pathType: Prefix
path: "/custom"
backend:
service:
name: custom
port:
number: 9090
- pathType: Prefix
path: "/echo"
backend:
service:
name: echo
port:
number: 9090
在 rules 中,我们通过路径来路由到指定的 Service,比如 /custom
路由到 custom
的 Service,而 \echo
路由到 echo
的 Service。
同时设定了一个 iguochan.org
的 host,所以我们需要到/etc/hosts
文件中添加下面一条:
bash
127.0.0.1 iguochan.org
然后运行:
bash
~ kubectl apply -f ingress.yaml
~ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
nginx-ingress <none> iguochan.org localhost 80 21m
这时候可以看一下 ingress 的描述:
bash
~ kubectl describe ingress nginx-ingress
Name: nginx-ingress
Labels: <none>
Namespace: default
Address: localhost
Ingress Class: <none>
Default backend: <default>
Rules:
Host Path Backends
---- ---- --------
iguochan.org
/custom custom:9090 (10.244.2.6:9090,10.244.3.7:9090)
/echo echo:9090 (10.244.1.7:9090,10.244.2.7:9090)
Annotations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 34m (x2 over 34m) nginx-ingress-controller Scheduled for sync
即发现已经通过路径和不同的 Service 绑定,并且标注了 Service 对应的 Pod 的 ip:port
。
最后我们可以验证:
bash
~ curl iguochan.org/custom
hello, I am custom-5c5c478dcb-pbmqc!
~ curl iguochan.org/custom
hello, I am custom-5c5c478dcb-w4z6q!
~ curl iguochan.org/echo
hello-world