我们一起学习 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