上一节学习了K8S的服务发现、像service、DNS、endpoint、hostport,这些都是之前搭建的K8S集群所具备的能力,也就是可以直接使用这个方案去部署服务。但是还有一种域名访问的服务,叫ingress,是目前集群还不具备的能力,同时域名访问的需求几乎是每个公司要有的,所以必须要让集群具备这个能力。
选择一个比较主流的方案,把ingress-nginx在集群中部署起来,从而让K8S集群具备服务发现的能力。
“https://kubernetes.io/docs/concepts/services-networking/ingress/”
“https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/”
#ingress介绍略。
什么是ingress controller?
通常来说,配置一个WEB服务或负载均衡器是比较麻烦的,大部分的webserver的配置是非常相似的,一些应用是比较特殊,但大部分的配置可以使用相同的逻辑,并且得到想要的结果。
ingress controller是一个daemon,作为K8S的POD来运行的,会去监听apiserver的/ingresses地址,以便实时去更新ingress resource。
部署开始
#6-6停止了6-2/3双主复制的node-2。
[root@node-1 ~]# mkdir ingress-nginx
[root@node-1 ~]# cd ingress-nginx
mandatory.yaml内容
[root@node-1 ingress-nginx]# cat mandatory.yaml
apiVersion: v1
kind: Namespace
metadata:
name: ingress-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: default-http-backend
labels:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
namespace: ingress-nginx
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
spec:
terminationGracePeriodSeconds: 60
containers:
- name: default-http-backend
# Any image is permissible as long as:
# 1. It serves a 404 page at /
# 2. It serves 200 on a /healthz endpoint
image: k8s.gcr.io/defaultbackend-amd64:1.5
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 5
ports:
- containerPort: 8080
resources:
limits:
cpu: 10m
memory: 20Mi
requests:
cpu: 10m
memory: 20Mi
---
apiVersion: v1
kind: Service
metadata:
name: default-http-backend
namespace: ingress-nginx
labels:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
spec:
ports:
- port: 80
targetPort: 8080
selector:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-configuration
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: tcp-services
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: udp-services
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx-ingress-serviceaccount
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nginx-ingress-clusterrole
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- "extensions"
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- "extensions"
resources:
- ingresses/status
verbs:
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: nginx-ingress-role
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- configmaps
- pods
- secrets
- namespaces
verbs:
- get
- apiGroups:
- ""
resources:
- configmaps
resourceNames:
# 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:
- configmaps
verbs:
- create
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: nginx-ingress-role-nisa-binding
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: nginx-ingress-role
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: nginx-ingress-clusterrole-nisa-binding
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nginx-ingress-clusterrole
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: ingress-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-ingress-controller
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
annotations:
prometheus.io/port: "10254"
prometheus.io/scrape: "true"
spec:
serviceAccountName: nginx-ingress-serviceaccount
hostNetwork: true
nodeSelector:
app: ingress
containers:
- name: nginx-ingress-controller
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.19.0
args:
- /nginx-ingress-controller
- --default-backend-service=$(POD_NAMESPACE)/default-http-backend
- --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.io
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
# www-data -> 33
runAsUser: 33
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443
livenessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
---
手工拉取镜像
#这里不用docker拉取。注意是操作的containerd的k8s.io这个命名空间。
"5-6containerd"中配置的默认容器是containerd
[root@node-1 ingress-nginx]# grep image mandatory.yaml
# Any image is permissible as long as:
image: k8s.gcr.io/defaultbackend-amd64:1.5
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.19.0
[root@node-2/3 ~]# ctr -n k8s.io i pull quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.19.0
[root@node-2/3 ~]# ctr -n k8s.io image list|grep ingress
[root@node-2/3 ~]# ctr -n k8s.io i pull registry.cn-hangzhou.aliyuncs.com/liuyi01/defaultbackend-amd64:1.5
#httpbackend是一个附属品,对主流程没有影响,当找不到页面时候会甩给它。
#公网拉取不下来的打tag
[root@node-2/3 ~]# ctr -n k8s.io i tag registry.cn-hangzhou.aliyuncs.com/liuyi01/defaultbackend-amd64:1.5 k8s.gcr.io/defaultbackend-amd64:1.5
[root@node-2/3 ~]# ctr -n k8s.io image list|grep defaultbackend
设置label
#关于ingress nginx服务暴露:hostport方式
#作用:停止一个worker节点node-2的harbor,以host的形式去运行ingress controller,然后把ingress controller调度在这个节点上。
#通过什么形式去访问这个节点呢?可以给这个节点打一个标签,在调度的时候,通过标签选择器去选择这个节点。
[root@node-1或者2 ingress-nginx]# kubectl label node node-2 app=ingress
#这里的节点名称是node-2,给node-2打的标签是ingress。
node/node-2 labeled
2、1标签对应app=ingress的配置
#这里和label挂钩,否则ingress-nginx-controller的POD一直会处于pending状态。
[root@node-1 ingress-nginx]# vim mandatory.yaml
spec:
#打完标签就可以修改配置文件了。大约在文件170行
#在serviceAccountName: nginx-ingress-serviceaccount和containers中加入下述三行!
serviceAccountName: nginx-ingress-serviceaccount
hostNetwork: true (选择)网络模式hostNetwork
nodeSelector: (加入)节点选择器
app: ingress (选择)固定的节点,节点的标签选择ingress
containers:
- name: nginx-ingress-controller
2、2停掉node-2的harbor
#这里的node-2指ingress-nginx部署到的节点,要保证此节点无80/443端口。
#这台节点部署了harbor,把它停掉,并不影响node-1代理node-3的harbor,那么6-3的双主复制暂时不用了。
[root@node-2 harbor]# docker-compose down
#释放并检查80和443端口,说明这个机器具有运行ingress controller的能力。
[root@node-2 harbor]# netstat -lntup|grep 80
[root@node-2 harbor]# netstat -lntup|grep 443
关于ingress nginx服务暴露的说明
“https://kubernetes.github.io/ingress-nginx”
“https://github.com/kubernetes/ingress-nginx/”
定义了一个service,类型是nodeport,端口是80,容器端口也是80。
那么这里使用这个NodePort是可以的,但NodePort不是一个好的方案,并且K8S默认不允许NodePort暴露80和443的,NodePort默认是从30000开始,虽然可以修改这个值,但是也不会改成80和443这么小的一个值。
还有什么方式来暴露ingress nginx的服务呢?上节服务发现内容,暴露80端口,前提是暴露出来的端口也必须是80端口,因为作为服务的入口,nginx必须是80才能域名访问,否则访问哪个域名都需要加一个端口,不合适。
那么这里使用hostport,相当于以host的形式去运行ingress controller,有几点好处,首先host模式要比桥接bridge的效率要强一些,并且没有网络的转发,如果要用nodeport,那么任何一个节点都可以访问的,不知道运行哪个节点的话,那么相当于多一次转发。
那么以hostnetwork模式运行,就出现一个问题,那么80端口只会监听在当前实例运行的机器上,所以要指定一台或几台机器,比如实例数量2,在每台节点都运行一个实例,这是一个方式。
但是鉴于目前集群的情况,只有两个worker节点,都有harbor的80端口在监听,所以暂时停掉一个harbor,释放出80端口,然后把ingress controller调度在这个节点上。
这里停止node-2这个worker节点。
并检查80和443端口,说明这个机器具有运行ingress controller的能力。
通过什么形式去访问这个节点呢?可以给这个节点打一个标签,在调度的时候,通过标签选择器去选择这个节点。
这里的节点名称是node-2,标签是ingress。
打完label标签就可以修改配置文件mandatory.yaml。
首先修改网络模式,改成hostNetwork,加入节点选择器,固定的节点。
hostNetwork: true
nodeSelector:
app: ingress
这样mandatory.yaml文件就修改好了。
创建ingress-nginx
#如遇apply错误先删除
[root@node-1 ingress-nginx]# kubectl delete -f mandatory.yaml
#创建
[root@node-1 ingress-nginx]# kubectl apply -f mandatory.yaml
#额外说明:应先不修改mandatory.yaml(不打标签),先测试"kubectl apply -f mandatory.yaml"是否成功,这里直接在一起搞了。
[root@node-1 ingress-nginx]# kubectl get all -n ingress-nginx
[root@node-1 ingress-nginx]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
node-2 Ready <none> 5d6h v1.20.2
node-3 Ready <none> 5d6h v1.20.2
[root@node-2 harbor]# netstat -lntup|grep 443
[root@node-2 harbor]# netstat -lntup|grep 80
案例测试ingress-nginx文件内容
#这里的文件可能随着K8S的升级,属性可能会有所改变。
#参考地址:
“https://github.com/kubernetes/kubernetes/pull/89778”
“https://www.cnblogs.com/dudu/p/15548461.html”
[root@node-1 ingress-nginx]# cat ingress-demo.yaml
#首先是一个Deployment,镜像是一个tomcat镜像,端口是8080,运行这个tomcat容器。
Deployment有了之后,Service通过Selector,会选中app:tomcat=demo,会选中上面的Deployment对应的POD,8080端口映射为service的80端口。
--这是一个比较标准的Deployment和Service的配置。
#deploy
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat-demo
spec:
selector:
matchLabels:
app: tomcat-demo
replicas: 1
template:
metadata:
labels:
app: tomcat-demo
spec:
containers:
- name: tomcat-demo
image: registry.cn-hangzhou.aliyuncs.com/liuyi01/tomcat:8.0.51-alpine
ports:
- containerPort: 8080
---
#service
apiVersion: v1
kind: Service
metadata:
name: tomcat-demo
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: tomcat-demo
---
#ingress
#old version: extensions/v1beta1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tomcat-demo
spec:
rules:
- host: tomcat.mooc.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: tomcat-demo
port:
number: 80
#这是新加的ingress,ingress新加的域名是tomcat.mooc.com,根路径/,所有的地址都会跳到这里,后端serviceName是上面service定义的名称,端口80。
案例测试ingress-nginx是否能用
[root@node-1 ingress-nginx]# pwd
/root/ingress-nginx
[root@node-1 ingress-nginx]# ll ingress-demo.yaml
-rw-r--r-- 1 root root 844 Aug 9 12:17 ingress-demo.yaml
[root@node-1 ingress-nginx]# grep image ingress-demo.yaml
image: registry.cn-hangzhou.aliyuncs.com/liuyi01/tomcat:8.0.51-alpine
#"5-6containerd"中配置的默认容器是containerd
[root@node-2/3 ~]# ctr -n k8s.io i pull registry.cn-hangzhou.aliyuncs.com/liuyi01/tomcat:8.0.51-alpine
[root@node-2/3 ~]# ctr -n k8s.io image list|grep tomcat
[root@node-1 ingress-nginx]# kubectl create -f ingress-demo.yaml
deployment.apps/tomcat-demo created
service/tomcat-demo created
ingress.networking.k8s.io/tomcat-demo created
#本机hosts和服务器hosts都加入
C:\Windows\System32\drivers\etc\hosts
10.0.0.22 tomcat.mooc.com
10.0.0.22 api.mooc.com
[root@node-1/2/3 ingress-nginx]# cat /etc/hosts
10.0.0.22 tomcat.mooc.com
10.0.0.22 api.mooc.com
[root@node-1 ingress-nginx]# kubectl get pod -o wide
案例测试ingress-nginx结果
#访问测试:http://api.mooc.com/
这个页面就是由default-http-backend的POD返回回来的。
404找不到对应的后端,因为并没有配置相应的ingress。
这个是由default-http-backend处理的,httpbackend是一个附属品,对主流程没有影响,当找不到页面的时候会甩给它。
#访问测试:http://tomcat.mooc.com/
#配置了相应的ingress了,也有service,但是service对应的POD处于不可用状态,所以是503。验证一下状态。
#镜像下载完成再去访问tomcat测试:http://tomcat.mooc.com/
#证明在这个域名下,所有的访问请求都会去对应的找到正确的backend。
#证明这个ingress controller可以正常工作的。
标题:Kubernetes(六)(迁移Kubernetes前准备)(6.5/6)部署ingress-nginx(上-下)(对照6-2/3)
作者:yazong
地址:https://blog.llyweb.com/articles/2022/11/11/1668107187285.html