这里介绍K8s Service中的Ingress Service
楔子
LoadBalance Service虽然可以对外暴露服务,但每个LoadBalance Service都需要占用一个公网IP资源。故我们可以利用Ingress Service来暴露自己的服务。事实上,Ingress Service并不是一种服务类型。其通过主机地址、路径等路由规则实现将多个内部服务整合到一个统一的集群入口当中。换言之,其可以实现在同一IP地址下公开多个服务
配置K8s集群
这里先通过Kind部署一个单节点的K8s集群,配置文件如下所示。需要注意,一方面我们给该节点设置ingress-ready=true的标签信息;另一方面,对80、443端口设置映射, 便于后续通过宿主机访问K8s节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
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 listenAddress: "127.0.0.1" - containerPort: 443 hostPort: 443 listenAddress: "127.0.0.1"
|
效果如下所示,集群创建成功
部署Ingress控制器
对于Ingress类型的资源而言,其必须依靠Ingress控制器才可以正常运行。故这里我们先部署一个Ingress控制器,事实上由于Ingress控制器有多种不同的实现。这里我们选择常用的Ingress控制器实现——Ingress NGINX。首先通过下述链接下载获取部署Ingress Nginx的配置文件
1 2
| https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
|
上述配置文件中包含3个镜像,其中有2个镜像是一样的。但由于众所周知的原因,大多数情况下我们无法正常从境外仓库拉取相应的镜像文件。故我们需要修改上述配置文件,将镜像替换为阿里云仓库的镜像。具体如下所示
1 2 3 4 5 6 7 8 9
| image: registry.k8s.io/ingress-nginx/controller:v1.2.1@sha256:5516d103a9c2ecc4f026efbd4b40662ce22dc1f824fb129ed121460aaa5c47f8
image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.2.1
image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660
image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1
|
将镜像修改为国内镜像后,就可以利用kubectl apply命令部署Ingress Nginx了。效果如下所示,可以看到当Ingress控制器的Pod为Running时。即说明部署成功了
现在我们来看下Ingress控制器Pod的详细信息,从节点选择器的标签信息其实不难看出。该Pod对于部署的节点是有要求的。这也是为什么我们在此前创建集群的时候,需要给集群节点打上相关标签的原因
最后,为了后续能够让我们成功创建相应的Ingress资源,我们还需要删除ingress-nginx-admission。具体命令如下所示
1 2 3 4 5
| kubectl get validatingwebhookconfigurations
kubectl delete -A ValidatingWebhookConfiguration ingress-nginx-admission
|
执行效果如下所示
部署应用
至此,我们就可以部署应用,包含RS、NodePort、Ingress等资源。具体如下所示,简单来说,我们通过RS部署了两个应用——foo app、bar app。并分别为这两个应用提供了相应的NodePort资源。然后创建了一个Ingress资源,用于实现访问同一域名下的不同路径时,将请求转发至两个不同的应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
apiVersion: apps/v1
kind: ReplicaSet metadata: name: my-rs-foo-app spec: replicas: 1 selector: matchLabels: app: foo-app template: metadata: labels: app: foo-app spec: containers: - name: my-foo-app image: hashicorp/http-echo:0.2.3 args: - "-text=this is foo app" ports: - containerPort: 5678
---
kind: Service apiVersion: v1 metadata: name: my-service-foo-app spec: type: NodePort selector: app: foo-app ports: - port: 11111 targetPort: 5678 nodePort: 31119
---
apiVersion: apps/v1 kind: ReplicaSet metadata: name: my-rs-bar-app spec: replicas: 1 selector: matchLabels: app: bar-app template: metadata: labels: app: bar-app spec: containers: - name: my-bar-app image: hashicorp/http-echo:0.2.3 args: - "-text=this is bar app" ports: - containerPort: 5678
---
kind: Service apiVersion: v1 metadata: name: my-service-bar-app spec: type: NodePort selector: app: bar-app ports: - port: 22222 targetPort: 5678 nodePort: 32229
---
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress spec: rules: - host: aaron.ingress.com http: paths: - pathType: Prefix path: "/foo" backend: service: name: my-service-foo-app port: number: 11111 - pathType: Prefix path: "/bar" backend: service: name: my-service-bar-app port: number: 22222
---
apiVersion: v1 kind: Pod metadata: name: my-pod-bootcamp spec: containers: - name: my-bootcamp image: jocatalin/kubernetes-bootcamp:v1 ports: - containerPort: 8080 protocol: TCP
---
|
现在利用 kubectl create 命令进行部署。如下所示,资源全部部署成功
由于我们在配置Ingress资源时,使用了一个域名:aaron.ingress.com。为了顺利在宿主机下进行测试,我们需要修改本地的DNS映射,即etc目录下的hosts文件。实现将该域名映射到本机上。如下所示
验证
上面我们还额外地部署了一个名为my-pod-bootcamp的Pod。目的就在于其内置了bash、curl等常见工具,非常方便我们开展测试验证工作
我们先分别通过NodePort的集群IP、服务端口实现对两个应用的访问,测试结果如下,符合预期
然后通过K8s节点的端口实现对两个应用的访问,测试结果如下,符合预期
至此说明我们的应用、NodePort部署是成功的。现在我们来验证下Ingress是否成功生效。在宿主机下通过curl分别访问aaron.ingress.com/bar、aaron.ingress.com/foo即可。测试结果如下,符合预期
参考文献
- Kubernetes in Action中文版 Marko Luksa著
- 深入剖析Kubernetes 张磊著