提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
一、ingress 是什么?
二、ingress-nginx 概念
三、 ingress-nginx 工作流程
四、Ingress-nginx 部署案例
总结
前言
根据 kubernetes 中 Service 的定义和了解我们知道,如果 kubernetes 中的 pod 中容器想要对外部用户提供服务就需要将 pod 服务暴露至外部,让用户可以访问,而 Service 的表现形式为 ip 地址和端口号(ClusterIP:port)&(NodePort)即工作在四层 TCP/IP 层只能够通过 ip + 端口的方式访问,而在 ingress 当中可以使用七层协议(HTTP/HTTPS)的服务方式来实现负载均衡以及 k8s 集群内部服务和客户端之间的通信(既可以通过域名和主机名的方式),接下来将详细讲解 ingress-nginx 工作机制及概念;
一、ingress 是什么?
ingress 在 kubernetes 中是一个具有七层协议(HTTP/HTTPS)的路由转发机制,通过策略以及结合具体提供转发服务的 Ingress Controller 来实现基于灵活的 ingress 策略定义的服务路由功能;
二、ingress-nginx 概念
在 k8s 集群当中可以通过 Service 来对外暴露 k8s 集群当中的 pod 服务,从而使得外部请求能够访问 k8s 集群当中的 pod,而 Service 有多种暴露方式,常用的有 ClusterIP、NodePort.. ,如下通过 Service 和 ingress 做对比来更加了解 ingress-nginx 的概念:
第一种暴露方式 clusterIP 针对集群内部的端口访问,通过标签的方式将 pod 和 svc 进行关联,访问 svc 时 svc 通过策略来将请求发送至各个 pod ,只限于集群内部访问;
第二种暴露方式就是 NodePort ,该方式是基于 ClusterIP 暴露端口方式之上对集群外部进行暴露访问的一种方法,默认端口是从 30000 开始,此时集群外部就可以通过 master节点ip + 端口的方式对集群内部的 pod 服务进行访问,请求会先到达 NodePort 暴露的 ip + 端口,随后 NodePort 会和集群内的 ClusterIP 进行映射从而使得外部服务访问集群内的 pod 资源;
第三种暴露方式就是 ingress 方式,该访问方式也是基于 ClusterIP 之上建立一个暴露方式, nodeport 只能够暴露 ip+端口(四层代理) 而 ingress-nginx 可以使用域名(七层代理)的方式对外暴露服务,ingress-nginx 就相当于是一个 nginx 服务的反向代理,当创建 ingress-nginx 之后会创建一个 nginx 服务(ingress-nginx 的 pod 容器),其中 Pod 中容器 nginx.conf 配置文件则记录的是对外暴露的域名以及监听端口是都是通过 ingress 的配置自动添加的,使用 location 中的 proxy-pass 来代理 k8s 集群中的 cluster 暴露的 ip,当外部请求访问到 ingress 暴露的域名时会反向代理到对应匹配的 svc 从而实现服务的访问;
三、 ingress-nginx 工作流程
如下图,如果管理员修改了 ingress 配置则 ingress 会通过 kubernetes API Server 来监听修改的配置动作,API 会和 Store(协程)建立连接,由 Store 来监听资源变化的时间(informer 模式),最终会判断资源是否发生变化,当发生变化之后会将变更的资源写入至更新事件当中(updateChannel) 之后主程(NginxController) 会读取 updateChannel 当中的更新事件加载到主程(NginxController)并向同步队列(syncQueue)追加同步任务,之后同步队列协程(syncQueue)会拉取同步队列的信息,还有一种情况就是获取最新的 ingress/service 配置 nginx 服务必须的信息,也会加载到协程(syncQueue)当中,之后会对这些收集的信息资源进行判断是否需要 reload ,当有新配置时会触发 reload 重写 nginx 配置文件并构造 POST 数据,向 Lua Server 发送更新请求,如果判断不需要重载则直接构造 POST 数据,并向 LuaServer 发送更新请求;
四、Ingress-nginx 部署案例
1、创建 IngressContainer
[root@kube-master ~]# mkdir ingress
[root@kube-master ~]# cd ingress/
[root@kube-master ingress]# vim ingress-container.yaml
# 创建名称空间 nginx-ingress
---
apiVersion: v1
kind: Namespace
metadata:
name: nginx-ingress
# 创建 SA,用于 IngressContainer 和 kube-apiServer 进行认证
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx-ingress
namespace: nginx-ingress
# 设置集群角色策略,是否允许对 ingress-container 中的资源(pod、configmaps等)进行用户授权
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nginx-ingress
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
- update
- create
- apiGroups:
- ""
resources:
- pods
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- list
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- list
- watch
- get
- apiGroups:
- "extensions"
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- k8s.nginx.org
resources:
- virtualservers
- virtualserverroutes
- globalconfigurations
- transportservers
- policies
verbs:
- list
- watch
- get
- apiGroups:
- k8s.nginx.org
resources:
- virtualservers/status
- virtualserverroutes/status
verbs:
- update
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nginx-ingress
subjects:
- kind: ServiceAccount
name: nginx-ingress
namespace: nginx-ingress
roleRef:
kind: ClusterRole
name: nginx-ingress
apiGroup: rbac.authorization.k8s.io
# 创建 Secret 存储,用于存储加密证书信息,用于 SA 引入进行认证,类型是 Opaque;
---
apiVersion: v1
kind: Secret
metadata:
name: default-server-secret
namespace: nginx-ingress
type: Opaque
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN2akNDQWFZQ0NRREFPRjl0THNhWFhEQU5CZ2txaGtpRzl3MEJBUXNGQURBaE1SOHdIUVlEVlFRRERCWk8KUjBsT1dFbHVaM0psYzNORGIyNTBjbTlzYkdWeU1CNFhEVEU0TURreE1qRTRNRE16TlZvWERUSXpNRGt4TVRFNApNRE16TlZvd0lURWZNQjBHQTFVRUF3d1dUa2RKVGxoSmJtZHlaWE56UTI5dWRISnZiR3hsY2pDQ0FTSXdEUVlKCktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQUwvN2hIUEtFWGRMdjNyaUM3QlBrMTNpWkt5eTlyQ08KR2xZUXYyK2EzUDF0azIrS3YwVGF5aGRCbDRrcnNUcTZzZm8vWUk1Y2Vhbkw4WGM3U1pyQkVRYm9EN2REbWs1Qgo4eDZLS2xHWU5IWlg0Rm5UZ0VPaStlM2ptTFFxRlBSY1kzVnNPazFFeUZBL0JnWlJVbkNHZUtGeERSN0tQdGhyCmtqSXVuektURXUyaDU4Tlp0S21ScUJHdDEwcTNRYzhZT3ExM2FnbmovUWRjc0ZYYTJnMjB1K1lYZDdoZ3krZksKWk4vVUkxQUQ0YzZyM1lma1ZWUmVHd1lxQVp1WXN2V0RKbW1GNWRwdEMzN011cDBPRUxVTExSakZJOTZXNXIwSAo1TmdPc25NWFJNV1hYVlpiNWRxT3R0SmRtS3FhZ25TZ1JQQVpQN2MwQjFQU2FqYzZjNGZRVXpNQ0F3RUFBVEFOCkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWpLb2tRdGRPcEsrTzhibWVPc3lySmdJSXJycVFVY2ZOUitjb0hZVUoKdGhrYnhITFMzR3VBTWI5dm15VExPY2xxeC9aYzJPblEwMEJCLzlTb0swcitFZ1U2UlVrRWtWcitTTFA3NTdUWgozZWI4dmdPdEduMS9ienM3bzNBaS9kclkrcUI5Q2k1S3lPc3FHTG1US2xFaUtOYkcyR1ZyTWxjS0ZYQU80YTY3Cklnc1hzYktNbTQwV1U3cG9mcGltU1ZmaXFSdkV5YmN3N0NYODF6cFErUyt1eHRYK2VBZ3V0NHh3VlI5d2IyVXYKelhuZk9HbWhWNThDd1dIQnNKa0kxNXhaa2VUWXdSN0diaEFMSkZUUkk3dkhvQXprTWIzbjAxQjQyWjNrN3RXNQpJUDFmTlpIOFUvOWxiUHNoT21FRFZkdjF5ZytVRVJxbStGSis2R0oxeFJGcGZnPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdi91RWM4b1JkMHUvZXVJTHNFK1RYZUprckxMMnNJNGFWaEMvYjVyYy9XMlRiNHEvClJOcktGMEdYaVN1eE9ycXgrajlnamx4NXFjdnhkenRKbXNFUkJ1Z1B0ME9hVGtIekhvb3FVWmcwZGxmZ1dkT0EKUTZMNTdlT1l0Q29VOUZ4amRXdzZUVVRJVUQ4R0JsRlNjSVo0b1hFTkhzbysyR3VTTWk2Zk1wTVM3YUhudzFtMApxWkdvRWEzWFNyZEJ6eGc2clhkcUNlUDlCMXl3VmRyYURiUzc1aGQzdUdETDU4cGszOVFqVUFQaHpxdmRoK1JWClZGNGJCaW9CbTVpeTlZTW1hWVhsMm0wTGZzeTZuUTRRdFFzdEdNVWozcGJtdlFmazJBNnljeGRFeFpkZFZsdmwKMm82MjBsMllxcHFDZEtCRThCay90elFIVTlKcU56cHpoOUJUTXdJREFRQUJBb0lCQVFDZklHbXowOHhRVmorNwpLZnZJUXQwQ0YzR2MxNld6eDhVNml4MHg4Mm15d1kxUUNlL3BzWE9LZlRxT1h1SENyUlp5TnUvZ2IvUUQ4bUFOCmxOMjRZTWl0TWRJODg5TEZoTkp3QU5OODJDeTczckM5bzVvUDlkazAvYzRIbjAzSkVYNzZ5QjgzQm9rR1FvYksKMjhMNk0rdHUzUmFqNjd6Vmc2d2szaEhrU0pXSzBwV1YrSjdrUkRWYmhDYUZhNk5nMUZNRWxhTlozVDhhUUtyQgpDUDNDeEFTdjYxWTk5TEI4KzNXWVFIK3NYaTVGM01pYVNBZ1BkQUk3WEh1dXFET1lvMU5PL0JoSGt1aVg2QnRtCnorNTZud2pZMy8yUytSRmNBc3JMTnIwMDJZZi9oY0IraVlDNzVWYmcydVd6WTY3TWdOTGQ5VW9RU3BDRkYrVm4KM0cyUnhybnhBb0dCQU40U3M0ZVlPU2huMVpQQjdhTUZsY0k2RHR2S2ErTGZTTXFyY2pOZjJlSEpZNnhubmxKdgpGenpGL2RiVWVTbWxSekR0WkdlcXZXaHFISy9iTjIyeWJhOU1WMDlRQ0JFTk5jNmtWajJTVHpUWkJVbEx4QzYrCk93Z0wyZHhKendWelU0VC84ajdHalRUN05BZVpFS2FvRHFyRG5BYWkyaW5oZU1JVWZHRXFGKzJyQW9HQkFOMVAKK0tZL0lsS3RWRzRKSklQNzBjUis3RmpyeXJpY05iWCtQVzUvOXFHaWxnY2grZ3l4b25BWlBpd2NpeDN3QVpGdwpaZC96ZFB2aTBkWEppc1BSZjRMazg5b2pCUmpiRmRmc2l5UmJYbyt3TFU4NUhRU2NGMnN5aUFPaTVBRHdVU0FkCm45YWFweUNweEFkREtERHdObit3ZFhtaTZ0OHRpSFRkK3RoVDhkaVpBb0dCQUt6Wis1bG9OOTBtYlF4VVh5YUwKMjFSUm9tMGJjcndsTmVCaWNFSmlzaEhYa2xpSVVxZ3hSZklNM2hhUVRUcklKZENFaHFsV01aV0xPb2I2NTNyZgo3aFlMSXM1ZUtka3o0aFRVdnpldm9TMHVXcm9CV2xOVHlGanIrSWhKZnZUc0hpOGdsU3FkbXgySkJhZUFVWUNXCndNdlQ4NmNLclNyNkQrZG8wS05FZzFsL0FvR0FlMkFVdHVFbFNqLzBmRzgrV3hHc1RFV1JqclRNUzRSUjhRWXQKeXdjdFA4aDZxTGxKUTRCWGxQU05rMXZLTmtOUkxIb2pZT2pCQTViYjhibXNVU1BlV09NNENoaFJ4QnlHbmR2eAphYkJDRkFwY0IvbEg4d1R0alVZYlN5T294ZGt5OEp0ek90ajJhS0FiZHd6NlArWDZDODhjZmxYVFo5MWpYL3RMCjF3TmRKS2tDZ1lCbyt0UzB5TzJ2SWFmK2UwSkN5TGhzVDQ5cTN3Zis2QWVqWGx2WDJ1VnRYejN5QTZnbXo5aCsKcDNlK2JMRUxwb3B0WFhNdUFRR0xhUkcrYlNNcjR5dERYbE5ZSndUeThXczNKY3dlSTdqZVp2b0ZpbmNvVlVIMwphdmxoTUVCRGYxSjltSDB5cDBwWUNaS2ROdHNvZEZtQktzVEtQMjJhTmtsVVhCS3gyZzR6cFE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
# 创建 ConfigMap 用于对 IngressContainer 容器进行配置修改
---
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-config
namespace: nginx-ingress
data:
# 编辑 IngressContainer 容器创建,控制类型用的是 deployment;
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-ingress
namespace: nginx-ingress
spec:
replicas: 1
selector:
matchLabels:
app: nginx-ingress
template:
metadata:
labels:
app: nginx-ingress
spec:
serviceAccountName: nginx-ingress # 引入 SA 用于 pod 和 kube-apiServer 进行加密认证
containers:
- image: nginx/nginx-ingress:1.7.2
imagePullPolicy: IfNotPresent
name: nginx-ingress
ports:
- name: http
containerPort: 80
hostPort: 80
- name: https
containerPort: 443
hostPort: 443
env: # 定义变量
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
args: # 通过变量引入 secret 和 configMap
- -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
- -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret
# 保存退出后查看 nginx-ingress 名称空间下的所有资源
[root@kube-master ingress]# kubectl get cm,sa,deployment,secret -n nginx-ingress
NAME DATA AGE
configmap/kube-root-ca.crt 1 77m
configmap/nginx-config 0 77m
NAME SECRETS AGE
serviceaccount/default 1 77m
serviceaccount/nginx-ingress 1 77m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-ingress 1/1 1 1 77m
NAME TYPE DATA AGE
secret/default-server-secret Opaque 2 77m
secret/default-token-2rhp2 kubernetes.io/service-account-token 3 77m
secret/nginx-ingress-token-9k4tp kubernetes.io/service-account-token 3 77m
2、创建 Service 和 Deployment(服务)
# 创建 deployment、Service
[root@kube-master ingress]# vim test-dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: myweb
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
# 验证是否创建成功
[root@kube-master ingress]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/nginx-f8f495-8l9sd 1/1 Running 0 43m
pod/nginx-f8f495-hs49c 1/1 Running 0 43m
pod/nginx-f8f495-zhbvn 1/1 Running 0 43m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16d
service/nginx-svc ClusterIP 10.96.74.181 <none> 80/TCP 43m
3、创建 Ingress 对外进行域名代理
# 创建 ingress 的剧本文件
[root@kube-master ingress]# vim test-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress-test # 定义 ingress 名称
spec:
rules:
- host: www.zkj.com # 定义对外暴露的域名
http: # 协议为 http 协议
paths: # 定义服务访问的路径
- path: /backend # 路径指定 /backend
pathType: ImplementationSpecific # 定义路径类型为 ImplementationSpecific
backend: # 定义后端代理
service: # 定义代理的 svc 信息
name: nginx-svc # 指定 svc 的名称
port: # 定义 svc 的端口
number: 80
# 查看创建的 ingress 信息
[root@kube-master ingress]# kubectl describe ingress nginx-ingress-test
Name: nginx-ingress-test
Namespace: default
Address:
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
www.zkj.com # 暴露的域名信息
# 代理的后端服务
/backend nginx-svc:80 (10.244.1.4:80,10.244.1.5:80,10.244.2.3:80)
Annotations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal AddedOrUpdated 35s (x2 over 38m) nginx-ingress-controller Configuration for default/nginx-ingress-test was added or updated
4、查看 IngressContainer 容器中的 nginx 配置文件
# 查看 IngressContainer 容器信息
[root@kube-master ingress]# kubectl get pod -n nginx-ingress
NAME READY STATUS RESTARTS AGE
nginx-ingress-78c4c6db55-tgl4w 1/1 Running 0 3h18m
# 进入容器
[root@kube-master ~]# kubectl exec -it -n nginx-ingress nginx-ingress-78c4c6db55-tgl4w /bin/bash
nginx@nginx-ingress-78c4c6db55-tgl4w:/$ cd etc/nginx/conf.d/
# 查看配置文件
nginx@nginx-ingress-78c4c6db55-tgl4w:/etc/nginx/conf.d$ cat default-nginx-ingress-test.conf
# 负载均衡 pod ip 地址
upstream default-nginx-ingress-test-www.zkj.com-nginx-svc-8080 {
zone default-nginx-ingress-test-www.zkj.com-nginx-svc-8080 256k;
random two least_conn;
server 10.244.1.10:80 max_fails=1 fail_timeout=10s max_conns=0;
}
server {
listen 80;
server_tokens on;
server_name www.zkj.com; # 域名为 hosts 字段定义的域名
location /backend { # location 字段为 path 字段定义的路径
proxy_http_version 1.1;
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
client_max_body_size 1m;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering on;
# 定义反向代理策略
proxy_pass http://default-nginx-ingress-test-www.zkj.com-nginx-svc-8080;
}
}
总结
以上就是今天要讲的内容,本文仅仅简单介绍了 Ingress-nginx 的使用,而 Ingress-nginx 提供了七层协议访问通信功能,能够使得客户使用域名的方式来访问 kubernetes 集群内部容器服务。