基本概念
Kubernetes 暴露服务的方式:
支持四种暴露服务的方式,前三种方式都是在service的维度提供的,service的作用体现在两个方面,对集群内部它不断跟踪pod变化,更新endpoint中对应的pod的对象,提供IP不断变化的pod的服务发现机制;
对集群外部,它类似负载均衡器,可以在集群内外对pod进行访问。但是单独使用service暴露服务的方式,在实际生产环境中不太适应。而ingress相当于service的service,可以将外部请求通过不同规则的筛选后转发到不同的service
- NodePort:后期维护困难,不支持虚拟路径
- LoadBlancer:需要云厂商支持,有局限性
- ClusterIP:只能在集群内部访问
-
ingress与ingress-controller
ingress-controller并不是k8s自带的组件,实际上它只是一个统称,用户可以选择不同的ingress-controller来实现功能。说白了就有点类似我们常规的服务部署。ingress-nginx就是我们的nginx中,其中由k8s官方维护的是nginx-ingress。
ingress是k8s中的一个api对象,一般用yaml配置。作用是定义请求转发的规则,可以理解为配置模板或者配置文件。ingress-controller是具体实现反向代理及负载均衡的程序,通过对ingress中定义的规则进行解析,根据其规则来实现转发。就类似于我们nginx中的conf文件,比如下面的配置demo ```nginx server { listen 443 ssl;server_name api.jimusanwei.dev;
ssl_certificate /etc/nginx/ssl/_wildcard.jimusanwei.dev.pem; ssl_certificate_key /etc/nginx/ssl/_wildcard.jimusanwei.dev-key.pem;
ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on;
location / {
client_max_body_size 50m;proxy_pass http://aaa;
} }
upstream aaa { server 192.168.1.110:30020; }
```yamlserver {listen 80;server_name aaa;//浏览器输入了http://aaa 代理到proxy_passlocation / {proxy_read_timeout 300;proxy_connect_timeout 300;proxy_redirect off;proxy_set_header Host $http_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-Proto $scheme;proxy_set_header X-Frame-Options SAMEORIGIN;proxy_pass http://aaa; # 这里代理到k8s的nginx-ingress.yaml配置的host}error_page 500 502 503 504 /50x.html;location = /50x.html {root /usr/share/nginx/html;}}
配置方式
1、Deployment+LoadBalancer模式的Service
如果要把ingress部署在公有云,那用这种方式比较合适。用Deployment部署ingress-controller,创建一个type为LoadBalancer的service关联这组pod。大部分公有云,都会为LoadBalancer的service自动创建一个负载均衡器,通常还绑定了公网地址。只要把域名解析指向该地址,就实现了集群服务的对外暴露
2、Deployment+NodePort模式的Service
同样用deployment模式部署ingress-controller,并创建对应的服务,但是type为NodePort。这样,ingress就会暴露在集群节点ip的特定端口上。由于nodeport暴露的端口是随机端口,一般会在前面再搭建一套负载均衡器来转发请求。该方式一般用于宿主机是相对固定的环境ip地址不变的场景。NodePort方式暴露ingress虽然简单方便,但是NodePort多了一层NAT,在请求量级很大时可能对性能会有一定影响
3、DaemonSet+HostNetwork+nodeSelector
用DaemonSet结合nodeselector来部署ingress-controller到特定的node上(也可结合affinity亲和性部署到多个节点),然后使用HostNetwork直接把该pod与宿主机node的网络打通,直接使用宿主机的80/433端口就能访问服务。这时,ingress-controller所在的node机器就很类似传统架构的边缘节点,比如机房入口的nginx服务器。该方式整个请求链路最简单,性能相对NodePort模式更好。缺点是由于直接利用宿主机节点的网络和端口,一个node只能部署一个ingress-controller pod。比较适合大并发的生产环境使用。
三、部署实例
基本概念
RBAC(Role-Based Access Control,基于角色的访问控制)在k8s v1.5中引入,在v1.6版本时升级为Beta版本,并成为kubeadm安装方式下的默认选项,相对于其他访问控制方式,新的RBAC具有如下优势:
- 对集群中的资源和非资源权限均有完整的覆盖
- 整个RBAC完全由几个API对象完成,同其他API对象一样,可以用kubectl或API进行操作
- 可以在运行时进行调整,无需重启API Server
- 要使用RBAC授权模式,需要在API Server的启动参数中加上—authorization-mode=RBAC
(1)RBAC的API资源对象说明,参数说明:
apiGroup:支持的API组列表,例如:APIVersion: batch/v1、APIVersion: extensions:v1、apiVersion:apps/v1等
- resources:支持的资源对象列表,例如:pods、deployments、jobs等
- verbs:对资源对象的操作方法列表,例如:get、watch、list、delete、replace、patch等
(2)角色(Role):
一个角色就是一组权限的集合,这里的权限都是许可形式的,不存在拒绝的规则。在一个命名空间中,可以用角色来定义一个角色,如果是集群级别的,就需要使用ClusterRole了。角色只能对命名空间内的资源进行授权
集群角色(ClusterRole):
集群角色除了具有和角色一致的命名空间内资源的管理能力,因其集群级别的范围,还可以用于以下特殊元素的授权。
- 集群范围的资源,例如Node
- 非资源型的路径,例如/healthz
- 包含全部命名空间的资源,例如pods
角色绑定(RoleBinding)和集群角色绑定(ClusterRoleBinding):角色绑定或集群角色绑定用来把一个角色绑定到一个目标上,绑定目标可以是User、Group或者Service Account。使用RoleBinding为某个命名空间授权, ClusterRoleBinding为集群范围内授权。RoleBinding可以引用Role进行授权,RoleBinding也可以引用ClusterRole,对属于同一命名空间内ClusterRole定义的资源主体进行授权。一种常见的做法是集群管理员为集群范围预先定义好一组角色(ClusterRole),然后在多个命名空间中重复使用这些ClusterRole。
集群角色绑定中的角色只能是集群角色,用于进行集群级别或者对所有命名空间都生效的授权。
部署
yaml文件
我这里直接使用第三种方式实现负载均衡,这种负载无需配置service,是直接通过HostNetwork直接把该pod与宿主机node的网络打通,直接使用宿主机的80/433端口就能访问服务。由于IP和端口固定,我们可以将pod直接暴露给外部的负载均衡使用。这种方式没有经过nodePort的NAT,而是直接利用宿主机节点的网络和端口,性能会更高些。比较适合大并发的生产环境使用。
配置文件可以从:mandatory.yaml 此地址获取,然后执行kubectl apply -f ./当前文件,但是由于它默认使用的是Deployment方式,由于mandatory.yaml中定义副本数为1,因此存在单点故障。虽然我们可以将副本数改为2或多个解决单点问题,但是由于pod的端口固定为80//443,当pod调度分配到同一个节点时,会出现端口分配问题,这也正是Deployment类型的副本数默认为1的原因。种情况我们可以通过将pod设置为DaemonSet解决,利用DaemonSet特性,保证每个节点运行pod。所以我们需要更改下这个地址下的deployment.yaml为
apiVersion: v1kind: Namespacemetadata:name: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx---kind: ConfigMapapiVersion: v1metadata:name: nginx-configurationnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx---kind: ConfigMapapiVersion: v1metadata:name: tcp-servicesnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx---kind: ConfigMapapiVersion: v1metadata:name: udp-servicesnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx---apiVersion: v1kind: ServiceAccountmetadata:name: nginx-ingress-serviceaccountnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx---apiVersion: rbac.authorization.k8s.io/v1 #解决高版本报错,原版是v1beta1 我改成了v1kind: ClusterRolemetadata:name: nginx-ingress-clusterrolelabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxrules:- apiGroups:- ""resources:- configmaps- endpoints- nodes- pods- secretsverbs:- list- watch- apiGroups:- ""resources:- nodesverbs:- get- apiGroups:- ""resources:- servicesverbs:- get- list- watch- apiGroups:- ""resources:- eventsverbs:- create- patch- apiGroups:- "extensions"- "networking.k8s.io"resources:- ingressesverbs:- get- list- watch- apiGroups:- "extensions"- "networking.k8s.io"resources:- ingresses/statusverbs:- update---apiVersion: rbac.authorization.k8s.io/v1 #原版是v1beta1 我改成了v1kind: Rolemetadata:name: nginx-ingress-rolenamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxrules:- apiGroups:- ""resources:- configmaps- pods- secrets- namespacesverbs:- get- apiGroups:- ""resources:- configmapsresourceNames:# Defaults to "<election-id>-<ingress-class>"# Here: "<ingress-controller-leader>-<nginx>"# This has to be adapted if you change either parameter# when launching the nginx-ingress-controller.- "ingress-controller-leader-nginx"verbs:- get- update- apiGroups:- ""resources:- configmapsverbs:- create- apiGroups:- ""resources:- endpointsverbs:- get---apiVersion: rbac.authorization.k8s.io/v1 #原版是v1beta1 我改成了v1kind: RoleBindingmetadata:name: nginx-ingress-role-nisa-bindingnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxroleRef:apiGroup: rbac.authorization.k8s.iokind: Rolename: nginx-ingress-rolesubjects:- kind: ServiceAccountname: nginx-ingress-serviceaccountnamespace: ingress-nginx---apiVersion: rbac.authorization.k8s.io/v1 #原版是v1beta1 我改成了v1kind: ClusterRoleBindingmetadata:name: nginx-ingress-clusterrole-nisa-bindinglabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxroleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: nginx-ingress-clusterrolesubjects:- kind: ServiceAccountname: nginx-ingress-serviceaccountnamespace: ingress-nginx---apiVersion: apps/v1kind: DaemonSet #TODO更改了的,并且去掉了metadata:name: nginx-ingress-controllernamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxspec:#replicas: 1 #TODO更改了的,并且去掉了selector:matchLabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxtemplate:metadata:labels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxannotations:prometheus.io/port: "10254"prometheus.io/scrape: "true"spec:hostNetwork: true# wait up to five minutes for the drain of connectionsterminationGracePeriodSeconds: 300serviceAccountName: nginx-ingress-serviceaccountnodeSelector:kubernetes.io/os: linuxcontainers:- name: nginx-ingress-controllerimage: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0args:- /nginx-ingress-controller- --configmap=$(POD_NAMESPACE)/nginx-configuration- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services- --udp-services-configmap=$(POD_NAMESPACE)/udp-services- --publish-service=$(POD_NAMESPACE)/ingress-nginx- --annotations-prefix=nginx.ingress.kubernetes.iosecurityContext:allowPrivilegeEscalation: truecapabilities:drop:- ALLadd:- NET_BIND_SERVICE# www-data -> 101runAsUser: 101env:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespaceports:- name: httpcontainerPort: 80protocol: TCP- name: httpscontainerPort: 443protocol: TCPlivenessProbe:failureThreshold: 3httpGet:path: /healthzport: 10254scheme: HTTPinitialDelaySeconds: 10periodSeconds: 10successThreshold: 1timeoutSeconds: 10readinessProbe:failureThreshold: 3httpGet:path: /healthzport: 10254scheme: HTTPperiodSeconds: 10successThreshold: 1timeoutSeconds: 10lifecycle:preStop:exec:command:- /wait-shutdown---apiVersion: v1kind: LimitRangemetadata:name: ingress-nginxnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxspec:limits:- min:memory: 90Micpu: 100mtype: Container
并且使用DaemonSet,当集群新加入新的node节点时会自动创建新的pod,保证每个node节点有一个ingress-controller,可通过在master节点执行查看当前ingress-controller的pod信息。
我这里不知道为什么健康检查探针没通过,一直报错重启6次结束。目前还没时间找出问题,暂时把部署探针注释掉了。
Liveness probe failed: Get http://10.244.1.2:10254/healthz: dial tcp 10.244.1.2:10254: connect: connection refused
kubectl get pod -n ingress-nginx -o wide

部署完成ingress-controller后,我们来部署个前端服务,由于之前我是通过传统的deployment+service(nodeport)实现,没有加ingress,现在加上,需要注意的是我前端vue项目service容器端口是
9527对外访问的nodeport是30027,ingress使用的是service的容器端口而不是对外的端口,需要注意一下。然后再到我的windows的host文件添加 192.168.1.110 aaa对应dns解析即可实现访问,并且它会屏蔽具体服务器访问的端口,非常的银杏。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: aaa #Ingress的名称
namespace: default
spec:
rules:
- host: k8s.simone.getway # 通过Ingress映射的地址
http:
paths:
- path: /
backend:
serviceName: vue-element-admin # 这里对应着service的名字,我之前部署前端用的是这个名字
servicePort: 9527 # 对应着需要映射的service的端口
我在用v1.22.1上面无法创建,请参照我下面这种格式创建yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-simone-app
namespace: sit
spec:
rules:
- host: k8s.simone.app
http:
paths:
- pathType: ImplementationSpecific
backend:
service:
name: simone-app
port:
number: 30021

参考自: https://blog.csdn.net/lkolkolkol/article/details/110232605 https://blog.csdn.net/yanggd1987/article/details/107507216 https://segmentfault.com/a/1190000019908991
