基本概念

Kubernetes 暴露服务的方式:

支持四种暴露服务的方式,前三种方式都是在service的维度提供的,service的作用体现在两个方面,对集群内部它不断跟踪pod变化,更新endpoint中对应的pod的对象,提供IP不断变化的pod的服务发现机制;
对集群外部,它类似负载均衡器,可以在集群内外对pod进行访问。但是单独使用service暴露服务的方式,在实际生产环境中不太适应。而ingress相当于service的service,可以将外部请求通过不同规则的筛选后转发到不同的service

  • NodePort:后期维护困难,不支持虚拟路径
  • LoadBlancer:需要云厂商支持,有局限性
  • ClusterIP:只能在集群内部访问
  • Ingress:灵活,无依赖

    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 / {

    1. client_max_body_size 50m;
    2. proxy_pass http://aaa;

    } }

upstream aaa { server 192.168.1.110:30020; }

  1. ```yaml
  2. server {
  3. listen 80;
  4. server_name aaa;//浏览器输入了http://aaa 代理到proxy_pass
  5. location / {
  6. proxy_read_timeout 300;
  7. proxy_connect_timeout 300;
  8. proxy_redirect off;
  9. proxy_set_header Host $http_host;
  10. proxy_set_header X-Real-IP $remote_addr;
  11. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  12. proxy_set_header X-Forwarded-Proto $scheme;
  13. proxy_set_header X-Frame-Options SAMEORIGIN;
  14. proxy_pass http://aaa; # 这里代理到k8s的nginx-ingress.yaml配置的host
  15. }
  16. error_page 500 502 503 504 /50x.html;
  17. location = /50x.html {
  18. root /usr/share/nginx/html;
  19. }
  20. }

配置方式

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为

  1. apiVersion: v1
  2. kind: Namespace
  3. metadata:
  4. name: ingress-nginx
  5. labels:
  6. app.kubernetes.io/name: ingress-nginx
  7. app.kubernetes.io/part-of: ingress-nginx
  8. ---
  9. kind: ConfigMap
  10. apiVersion: v1
  11. metadata:
  12. name: nginx-configuration
  13. namespace: ingress-nginx
  14. labels:
  15. app.kubernetes.io/name: ingress-nginx
  16. app.kubernetes.io/part-of: ingress-nginx
  17. ---
  18. kind: ConfigMap
  19. apiVersion: v1
  20. metadata:
  21. name: tcp-services
  22. namespace: ingress-nginx
  23. labels:
  24. app.kubernetes.io/name: ingress-nginx
  25. app.kubernetes.io/part-of: ingress-nginx
  26. ---
  27. kind: ConfigMap
  28. apiVersion: v1
  29. metadata:
  30. name: udp-services
  31. namespace: ingress-nginx
  32. labels:
  33. app.kubernetes.io/name: ingress-nginx
  34. app.kubernetes.io/part-of: ingress-nginx
  35. ---
  36. apiVersion: v1
  37. kind: ServiceAccount
  38. metadata:
  39. name: nginx-ingress-serviceaccount
  40. namespace: ingress-nginx
  41. labels:
  42. app.kubernetes.io/name: ingress-nginx
  43. app.kubernetes.io/part-of: ingress-nginx
  44. ---
  45. apiVersion: rbac.authorization.k8s.io/v1 #解决高版本报错,原版是v1beta1 我改成了v1
  46. kind: ClusterRole
  47. metadata:
  48. name: nginx-ingress-clusterrole
  49. labels:
  50. app.kubernetes.io/name: ingress-nginx
  51. app.kubernetes.io/part-of: ingress-nginx
  52. rules:
  53. - apiGroups:
  54. - ""
  55. resources:
  56. - configmaps
  57. - endpoints
  58. - nodes
  59. - pods
  60. - secrets
  61. verbs:
  62. - list
  63. - watch
  64. - apiGroups:
  65. - ""
  66. resources:
  67. - nodes
  68. verbs:
  69. - get
  70. - apiGroups:
  71. - ""
  72. resources:
  73. - services
  74. verbs:
  75. - get
  76. - list
  77. - watch
  78. - apiGroups:
  79. - ""
  80. resources:
  81. - events
  82. verbs:
  83. - create
  84. - patch
  85. - apiGroups:
  86. - "extensions"
  87. - "networking.k8s.io"
  88. resources:
  89. - ingresses
  90. verbs:
  91. - get
  92. - list
  93. - watch
  94. - apiGroups:
  95. - "extensions"
  96. - "networking.k8s.io"
  97. resources:
  98. - ingresses/status
  99. verbs:
  100. - update
  101. ---
  102. apiVersion: rbac.authorization.k8s.io/v1 #原版是v1beta1 我改成了v1
  103. kind: Role
  104. metadata:
  105. name: nginx-ingress-role
  106. namespace: ingress-nginx
  107. labels:
  108. app.kubernetes.io/name: ingress-nginx
  109. app.kubernetes.io/part-of: ingress-nginx
  110. rules:
  111. - apiGroups:
  112. - ""
  113. resources:
  114. - configmaps
  115. - pods
  116. - secrets
  117. - namespaces
  118. verbs:
  119. - get
  120. - apiGroups:
  121. - ""
  122. resources:
  123. - configmaps
  124. resourceNames:
  125. # Defaults to "<election-id>-<ingress-class>"
  126. # Here: "<ingress-controller-leader>-<nginx>"
  127. # This has to be adapted if you change either parameter
  128. # when launching the nginx-ingress-controller.
  129. - "ingress-controller-leader-nginx"
  130. verbs:
  131. - get
  132. - update
  133. - apiGroups:
  134. - ""
  135. resources:
  136. - configmaps
  137. verbs:
  138. - create
  139. - apiGroups:
  140. - ""
  141. resources:
  142. - endpoints
  143. verbs:
  144. - get
  145. ---
  146. apiVersion: rbac.authorization.k8s.io/v1 #原版是v1beta1 我改成了v1
  147. kind: RoleBinding
  148. metadata:
  149. name: nginx-ingress-role-nisa-binding
  150. namespace: ingress-nginx
  151. labels:
  152. app.kubernetes.io/name: ingress-nginx
  153. app.kubernetes.io/part-of: ingress-nginx
  154. roleRef:
  155. apiGroup: rbac.authorization.k8s.io
  156. kind: Role
  157. name: nginx-ingress-role
  158. subjects:
  159. - kind: ServiceAccount
  160. name: nginx-ingress-serviceaccount
  161. namespace: ingress-nginx
  162. ---
  163. apiVersion: rbac.authorization.k8s.io/v1 #原版是v1beta1 我改成了v1
  164. kind: ClusterRoleBinding
  165. metadata:
  166. name: nginx-ingress-clusterrole-nisa-binding
  167. labels:
  168. app.kubernetes.io/name: ingress-nginx
  169. app.kubernetes.io/part-of: ingress-nginx
  170. roleRef:
  171. apiGroup: rbac.authorization.k8s.io
  172. kind: ClusterRole
  173. name: nginx-ingress-clusterrole
  174. subjects:
  175. - kind: ServiceAccount
  176. name: nginx-ingress-serviceaccount
  177. namespace: ingress-nginx
  178. ---
  179. apiVersion: apps/v1
  180. kind: DaemonSet #TODO更改了的,并且去掉了
  181. metadata:
  182. name: nginx-ingress-controller
  183. namespace: ingress-nginx
  184. labels:
  185. app.kubernetes.io/name: ingress-nginx
  186. app.kubernetes.io/part-of: ingress-nginx
  187. spec:
  188. #replicas: 1 #TODO更改了的,并且去掉了
  189. selector:
  190. matchLabels:
  191. app.kubernetes.io/name: ingress-nginx
  192. app.kubernetes.io/part-of: ingress-nginx
  193. template:
  194. metadata:
  195. labels:
  196. app.kubernetes.io/name: ingress-nginx
  197. app.kubernetes.io/part-of: ingress-nginx
  198. annotations:
  199. prometheus.io/port: "10254"
  200. prometheus.io/scrape: "true"
  201. spec:
  202. hostNetwork: true
  203. # wait up to five minutes for the drain of connections
  204. terminationGracePeriodSeconds: 300
  205. serviceAccountName: nginx-ingress-serviceaccount
  206. nodeSelector:
  207. kubernetes.io/os: linux
  208. containers:
  209. - name: nginx-ingress-controller
  210. image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
  211. args:
  212. - /nginx-ingress-controller
  213. - --configmap=$(POD_NAMESPACE)/nginx-configuration
  214. - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
  215. - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
  216. - --publish-service=$(POD_NAMESPACE)/ingress-nginx
  217. - --annotations-prefix=nginx.ingress.kubernetes.io
  218. securityContext:
  219. allowPrivilegeEscalation: true
  220. capabilities:
  221. drop:
  222. - ALL
  223. add:
  224. - NET_BIND_SERVICE
  225. # www-data -> 101
  226. runAsUser: 101
  227. env:
  228. - name: POD_NAME
  229. valueFrom:
  230. fieldRef:
  231. fieldPath: metadata.name
  232. - name: POD_NAMESPACE
  233. valueFrom:
  234. fieldRef:
  235. fieldPath: metadata.namespace
  236. ports:
  237. - name: http
  238. containerPort: 80
  239. protocol: TCP
  240. - name: https
  241. containerPort: 443
  242. protocol: TCP
  243. livenessProbe:
  244. failureThreshold: 3
  245. httpGet:
  246. path: /healthz
  247. port: 10254
  248. scheme: HTTP
  249. initialDelaySeconds: 10
  250. periodSeconds: 10
  251. successThreshold: 1
  252. timeoutSeconds: 10
  253. readinessProbe:
  254. failureThreshold: 3
  255. httpGet:
  256. path: /healthz
  257. port: 10254
  258. scheme: HTTP
  259. periodSeconds: 10
  260. successThreshold: 1
  261. timeoutSeconds: 10
  262. lifecycle:
  263. preStop:
  264. exec:
  265. command:
  266. - /wait-shutdown
  267. ---
  268. apiVersion: v1
  269. kind: LimitRange
  270. metadata:
  271. name: ingress-nginx
  272. namespace: ingress-nginx
  273. labels:
  274. app.kubernetes.io/name: ingress-nginx
  275. app.kubernetes.io/part-of: ingress-nginx
  276. spec:
  277. limits:
  278. - min:
  279. memory: 90Mi
  280. cpu: 100m
  281. type: 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

image.png
部署完成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

image.png

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