我们一起学习 Kubernetes 的 Ingress 服务发现吧!
Kubernetes
中为了实现服务实例间的负载均衡和不同服务间的服务发现,创造了 Service
对象,同时又为从集群外部访问集群创建了 Ingress
对象。
1. 原理介绍
介绍关于 K8S 中 Ingress 的基本知识和要点!
我们都知道传统的 SVC
只支持四层上面的代码,而对于七层上的代码而无能为力。比如:我们使用 K8S
集群对外提供 HTTPS
的服务,为了方便和便捷,我们需要在对外的 Nginx
服务上面配置 SSL
加密,但是将请求发送给后端服务的时候,进行证书卸载的操作,后续都是用 HTTP
的协议进行处理。而面对此问题,K8S
中给出了使用 Ingress
(K8S
在1.11
版本中推出了)来进行处理。
Kubernetes Workstation
+---------------------------------------------------+ +------------------+
| | | |
| +-----------+ apiserver +------------+ | | +------------+ |
| | | proxy | | | | | | |
| | apiserver | | ingress | | | | ingress | |
| | | | controller | | | | controller | |
| | | | | | | | | |
| | | | | | | | | |
| | | service account/ | | | | | | |
| | | kubeconfig | | | | | | |
| | +<-------------------+ | | | | | |
| | | | | | | | | |
| +------+----+ kubeconfig +------+-----+ | | +------+-----+ |
| |<--------------------------------------------------------| |
| | | |
+---------------------------------------------------+ +------------------+
2. 服务安装
介绍关于 Ingress 服务的安装方式!
安装 Ingress-Nginx
首先需要在官网下载对应的安装 yaml
文件,如果你也是 Mac
用户的话,可以使用该 下载文件 进行安装。
安装的过程中,根据部署文件其会自行定义一个名为 ingress-nginx
的名称空间,由来保存其对应的 Pod
和内容。而 Deployments
中会自动部署一个名为 nginx-ingress-controller
的服务,用于管理和控制 Ingress
服务。当然,还有对应 Deployment
的 ingress-nginx
的 SVC
也会一同创建的。同时,还有相关的角色、ConfigMap
等等。
# 直接运行即可安装
$ kubectl apply -f deploy.yaml
可以看到其底层的暴露类型就是 NodePort
模式,会在每个 Node
节点上面开放的 80
端口和 443
端口映射的地址。
# 查看对应SVC服务
$ kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.97.243.161 <none> 80:31345/TCP,443:31802/TCP 22s
# 查看对应POD服务
$ kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-761212d12f-11864 1/1 Running 0 54s
3. 配置 HTTP 代理
配置关于 Ingress 服务的 HTTP 代理访问!
- Deployment/Service/Ingress
- 我们这里可以使用
kubectl apply -f ingress-http.yml
来直接部署服务。
- 我们这里可以使用
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-app
spec:
replicas: 2
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: escape/nginx:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Service
metadata:
name: nginx-svc
spec:
selector:
name: nginx
ports:
- port: 80
targetPort: 80
protocol: TCP
---
apiVersion: apps/v1
kind: Ingress
metadata:
name: nginx-test
spec:
rules:
- host: test.escape.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
- 测试效果
- 如果我们没有自己的独立域名的话,可以通过修改
Hosts
配置文件来访问。 - 然后通过域名进行访问,但是需要使用
Ingress
的服务端口,比如31345
端口。
- 如果我们没有自己的独立域名的话,可以通过修改
# /etc/hosts
192.168.66.10 test.escape.com
# 查看对应SVC服务
$ kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.97.243.161 <none> 80:31345/TCP,443:31802/TCP 3m
# 为后续测试而删除服务
$ kubectl delete svc nginx-svc
$ kubectl delete svc nginx-test
$ kubectl delete pod nginx-app
4. 配置 HTTP 代理
根据不同的域名实现访问对应的虚拟主机!
- 服务配置图示
- 网站 1:Deployment/Service/Ingress
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-nginx-1
spec:
replicas: 2
template:
metadata:
labels:
name: nginx-1
spec:
containers:
- name: nginx-1
image: escape/nginx:v2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Service
metadata:
name: svc-nginx-1
spec:
selector:
name: nginx-1
ports:
- port: 80
targetPort: 80
protocol: TCP
---
apiVersion: apps/v1
kind: Ingress
metadata:
name: nginx-web1
spec:
rules:
- host: web1.escape.com
http:
paths:
- path: /
backend:
serviceName: svc-nginx-1
servicePort: 80
- 网站 2:Deployment/Service/Ingress
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-nginx-2
spec:
replicas: 2
template:
metadata:
labels:
name: nginx-2
spec:
containers:
- name: nginx-2
image: escape/nginx:v2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Service
metadata:
name: svc-nginx-2
spec:
selector:
name: nginx-2
ports:
- port: 80
targetPort: 80
protocol: TCP
---
apiVersion: apps/v1
kind: Ingress
metadata:
name: nginx-web2
spec:
rules:
- host: web2.escape.com
http:
paths:
- path: /
backend:
serviceName: svc-nginx-2
servicePort: 80
- 测试效果
- 如果我们没有自己的独立域名的话,可以通过修改
Hosts
配置文件来访问。 - 然后通过域名进行访问,但是需要使用
Ingress
的服务端口,比如31345
端口。
- 如果我们没有自己的独立域名的话,可以通过修改
# 查看对应POD服务
$ kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-761212d12f-11864 1/1 Running 0 5m
# Ingress容器里面查看Nginx配置
$ kubectl -it exec nginx-ingress-controller-761212d12f-11864 -n ingress-nginx -- /bin/bash
# 查看Ingress规则
$ kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
nginx-web1 web1.escape.com 80 9m8s
nginx-web2 web2.escape.com 80 9m10s
# /etc/hosts
192.168.66.10 test.escape.com
192.168.66.10 web1.escape.com
192.168.66.10 web2.escape.com
5. 配置 HTTPS 代理
配置关于 Ingress 服务的 HTTPS 代理访问
- 创建证书,以及
cert
存储方式。
# 生成自签名证书(365天有效期)
# Key: tls.key 证书: tls.crt
$ openssl req -x509 -sha256 -nodes \
-days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
Generating a 2048 bit RSA private key
................+++
................+++
writing new private key to 'tls.key'
# 在K8S中创建一个名称为tls-secret的secret格式的证书信息
$ kubectl create secret tls tls-secret --key tls.key --cert tls.crt
secret "tls-secret" created
- Deployment/Service/Ingress
- 我们这里可以使用
kubectl apply -f ingress-https.yml
来直接部署服务。
- 我们这里可以使用
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-nginx-3
spec:
replicas: 2
template:
metadata:
labels:
name: nginx-3
spec:
containers:
- name: nginx-3
image: escape/nginx:v3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Service
metadata:
name: svc-nginx-3
spec:
selector:
name: nginx-3
ports:
- port: 80
targetPort: 80
protocol: TCP
---
apiVersion: apps/v1
kind: Ingress
metadata:
name: nginx-3
spec:
tls:
- hosts:
- web3.escape.com
secretName: tls-secret
rules:
- host: web3.escape.com
http:
paths:
- path: /
backend:
serviceName: svc-nginx-3
servicePort: 80
- 测试效果
- 如果我们没有自己的独立域名的话,可以通过修改
Hosts
配置文件来访问。 - 然后通过域名进行访问,但是需要使用
Ingress
的服务端口,比如31802
端口。
- 如果我们没有自己的独立域名的话,可以通过修改
# /etc/hosts
192.168.66.10 test.escape.com
192.168.66.10 web1.escape.com
192.168.66.10 web2.escape.com
192.168.66.10 web3.escape.com
# 查看对应SVC服务
$ kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.97.243.161 <none> 80:31345/TCP,443:31802/TCP 3m
6. 基础认证
介绍 Ingress 服务的 BasicAuth 认证方式!
- 前提准备
# 安装httpd工具
$ yum install -y httpd
# 设置基础认证密码
# 创建文件为auth;用户名为escape;密码连输入两次
$ htpasswd -c auth escape
# k8s配置认证
$ kubectl create secret generic basic-auth --from-file=auth
- 配置文件
apiVersion: apps/v1
kind: Ingress
metadata:
name: ingress-with-auth
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: "Authentication Required - escape"
spec:
rules:
- host: auth.escape.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
# /etc/hosts
192.168.66.10 test.escape.com
192.168.66.10 web1.escape.com
192.168.66.10 web2.escape.com
192.168.66.10 web3.escape.com
192.168.66.10 auth.escape.com
7. 规则重写
介绍 Ingress 的进行规则重写的方式!
apiVersion: apps/v1
kind: Ingress
metadata:
name: nginx-test
annotations:
nginx.ingress.kubernetes.io/rewrite-target: http://web3.escape.com:31802/hostname.html
spec:
rules:
- host: web4.escape.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
# /etc/hosts
192.168.66.10 test.escape.com
192.168.66.10 web1.escape.com
192.168.66.10 web2.escape.com
192.168.66.10 web3.escape.com
192.168.66.10 auth.escape.com
192.168.66.10 web4.escape.com