实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
k8s version:v1.22.2
containerd://1.5.5
无
我们已经了解了 Ingress 资源对象只是一个路由请求描述配置文件,要让其真正生效还需要对应的 Ingress 控制器才行。Ingress 控制器有很多,这里我们先介绍使用最多的 ingress-nginx,它是基于 Nginx 的 Ingress 控制器。
ingress-nginx
控制器主要是用来组装一个 nginx.conf
的配置文件,当配置文件发生任何变动的时候就需要重新加载 Nginx 来生效,但是并不会只在影响 upstream
配置的变更后就重新加载 Nginx,控制器内部会使用一个 lua-nginx-module
来实现该功能。
我们知道 Kubernetes 控制器使用控制循环模式来检查控制器中所需的状态是否已更新或是否需要变更,所以 ingress-nginx
需要使用集群中的不同对象来构建模型,比如 Ingress、Service、Endpoints、Secret、ConfigMap 等可以生成反映集群状态的配置文件的对象,控制器需要一直 Watch 这些资源对象的变化,但是并没有办法知道特定的更改是否会影响到最终生成的 nginx.conf
配置文件,所以一旦 Watch 到了任何变化,控制器都必须根据集群的状态重建一个新的模型,并将其与当前的模型进行比较,如果模型相同则就可以避免生成新的 Nginx 配置并触发重新加载,否则还需要检查模型的差异是否只和端点有关,如果是这样,则然后需要使用 HTTP POST 请求将新的端点列表发送到在 Nginx 内运行的 Lua 处理程序,并再次避免生成新的 Nginx 配置并触发重新加载,如果运行和新模型之间的差异不仅仅是端点,那么就会基于新模型创建一个新的 Nginx 配置了,这样构建模型最大的一个好处就是在状态没有变化时避免不必要的重新加载,可以节省大量 Nginx 重新加载。
下面简单描述了需要重新加载的一些场景:
对于集群规模较大的场景下频繁的对Nginx进行重新加载显然会造成大量的性能消耗,所以要尽可能减少出现重新加载的场景。
由于 ingress-nginx
所在的节点需要能够访问外网,这样域名可以解析到这些节点上直接使用,所以需要让 ingress-nginx
绑定节点的 80 和 443 端口,所以可以使用 hostPort (hostwork也是可以的)来进行访问。当然对于线上环境来说为了保证高可用,一般是需要运行多个ingress-nginx 实例的,然后可以用一个 nginx/haproxy 作为入口,通过 keepalived 来访问边缘节点的 vip 地址。
⚠️ 边缘节点:所谓的边缘节点即集群内部用来向集群外暴露服务能力的节点,集群外部的服务通过该节点来调用集群内部的服务,边缘节点是集群内外交流的一个 Endpoint。
这里我们使用 Helm Chart(后面会详细讲解)的方式来进行安装:
# 如果你不喜欢使用 helm chart 进行安装也可以使用下面的命令`一键安装`
# kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.0/deploy/static/provider/cloud/deploy.yaml
➜ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
➜ helm repo update
➜ helm fetch ingress-nginx/ingress-nginx
➜ tar -xvf ingress-nginx-4.0.13.tgz && cd ingress-nginx
➜ tree .
.
├── CHANGELOG.md
├── Chart.yaml
├── OWNERS
├── README.md
├── ci
│ ├── controller-custom-ingressclass-flags.yaml
│ ├── daemonset-customconfig-values.yaml
│ ├── daemonset-customnodeport-values.yaml
│ ├── daemonset-headers-values.yaml
│ ├── daemonset-internal-lb-values.yaml
│ ├── daemonset-nodeport-values.yaml
│ ├── daemonset-podannotations-values.yaml
│ ├── daemonset-tcp-udp-configMapNamespace-values.yaml
│ ├── daemonset-tcp-udp-values.yaml
│ ├── daemonset-tcp-values.yaml
│ ├── deamonset-default-values.yaml
│ ├── deamonset-metrics-values.yaml
│ ├── deamonset-psp-values.yaml
│ ├── deamonset-webhook-and-psp-values.yaml
│ ├── deamonset-webhook-values.yaml
│ ├── deployment-autoscaling-behavior-values.yaml
│ ├── deployment-autoscaling-values.yaml
│ ├── deployment-customconfig-values.yaml
│ ├── deployment-customnodeport-values.yaml
│ ├── deployment-default-values.yaml
│ ├── deployment-headers-values.yaml
│ ├── deployment-internal-lb-values.yaml
│ ├── deployment-metrics-values.yaml
│ ├── deployment-nodeport-values.yaml
│ ├── deployment-podannotations-values.yaml
│ ├── deployment-psp-values.yaml
│ ├── deployment-tcp-udp-configMapNamespace-values.yaml
│ ├── deployment-tcp-udp-values.yaml
│ ├── deployment-tcp-values.yaml
│ ├── deployment-webhook-and-psp-values.yaml
│ ├── deployment-webhook-resources-values.yaml
│ └── deployment-webhook-values.yaml
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── _params.tpl
│ ├── admission-webhooks
│ │ ├── job-patch
│ │ │ ├── clusterrole.yaml
│ │ │ ├── clusterrolebinding.yaml
│ │ │ ├── job-createSecret.yaml
│ │ │ ├── job-patchWebhook.yaml
│ │ │ ├── psp.yaml
│ │ │ ├── role.yaml
│ │ │ ├── rolebinding.yaml
│ │ │ └── serviceaccount.yaml
│ │ └── validating-webhook.yaml
│ ├── clusterrole.yaml
│ ├── clusterrolebinding.yaml
│ ├── controller-configmap-addheaders.yaml
│ ├── controller-configmap-proxyheaders.yaml
│ ├── controller-configmap-tcp.yaml
│ ├── controller-configmap-udp.yaml
│ ├── controller-configmap.yaml
│ ├── controller-daemonset.yaml
│ ├── controller-deployment.yaml
│ ├── controller-hpa.yaml
│ ├── controller-ingressclass.yaml
│ ├── controller-keda.yaml
│ ├── controller-poddisruptionbudget.yaml
│ ├── controller-prometheusrules.yaml
│ ├── controller-psp.yaml
│ ├── controller-role.yaml
│ ├── controller-rolebinding.yaml
│ ├── controller-service-internal.yaml
│ ├── controller-service-metrics.yaml
│ ├── controller-service-webhook.yaml
│ ├── controller-service.yaml
│ ├── controller-serviceaccount.yaml
│ ├── controller-servicemonitor.yaml
│ ├── default-backend-deployment.yaml
│ ├── default-backend-hpa.yaml
│ ├── default-backend-poddisruptionbudget.yaml
│ ├── default-backend-psp.yaml
│ ├── default-backend-role.yaml
│ ├── default-backend-rolebinding.yaml
│ ├── default-backend-service.yaml
│ ├── default-backend-serviceaccount.yaml
│ └── dh-param-secret.yaml
└── values.yaml
4 directories, 81 files
Helm Chart 包下载下来后解压就可以看到里面包含的模板文件,其中的 ci
目录中就包含了各种场景下面安装的 Values 配置文件,values.yaml
文件中包含的是所有可配置的默认值,我们可以对这些默认值进行覆盖。
我们这里测试环境就将 master1 节点看成边缘节点,所以我们就直接将 ingress-nginx
固定到 master1 节点上,采用 hostNetwork 模式(生产环境可以使用 LB + DaemonSet hostNetwork 模式),为了避免创建的错误 Ingress 等资源对象影响控制器重新加载,所以⚠️我们也强烈建议大家开启准入控制器,ingess-nginx
中会提供一个用于校验资源对象的 Admission Webhook,我们可以通过 Values 文件进行开启。
然后新建一个名为 ci/daemonset-prod.yaml
的 Values 文件,用来覆盖 ingress-nginx 默认的 Values 值。
注意:当然你有多个边缘节点的话,可以对这些边缘节点打上一个label,然后把ingress-nginx给固定到上面去,然后采用hostNetwork模式。
⚠️注意:为了避免创建的错误 Ingress 等资源对象影响控制器重新加载,所以我们也强烈建议大家开启准入控制器,
ingess-nginx
中会提供一个用于校验资源对象的 Admission Webhook,我们可以通过 Values 文件进行开启。设置成true之后,当我们去创建Ingress资源对象的时候,它会用这里的admission Webhooks去做一个校验,就是你不是一个正确的Ingress资源对象的话,那它就会拒绝掉。那你拒绝掉之后,我们这个Ingress-controller它就不会去重新加载了,或多或少它可以它可以避免控制器重新加载之类的情况。
[root@master1 ci]#/root/ingress-nginx/ci/deployment-webhook-values.yaml
对应的 Values 配置文件如下所示:
#注意:以下配置参数不是随便设置的,一定要是values.yaml里面有的才可以的哦;
vim ci/daemonset-prod.yaml
# ci/daemonset-prod.yaml
controller:
name: controller
image:
repository: cnych/ingress-nginx #老师这里是转存过的。
tag: "v1.1.0"
digest:
dnsPolicy: ClusterFirstWithHostNet
hostNetwork: true
publishService: # hostNetwork 模式下设置为false,通过节点IP地址上报ingress status数据
enabled: false
# 是否需要处理不带 ingressClass 注解或者 ingressClassName 属性的 Ingress 对象
# 设置为 true 会在控制器启动参数中新增一个 --watch-ingress-without-class 标注
watchIngressWithoutClass: false
kind: DaemonSet
tolerations: # kubeadm 安装的集群默认情况下master是有污点,需要容忍这个污点才可以部署
- key: "node-role.kubernetes.io/master"
operator: "Equal"
effect: "NoSchedule"
nodeSelector: # 固定到master1节点
kubernetes.io/hostname: master1
service: # HostNetwork 模式不需要创建service
enabled: false
admissionWebhooks: # 强烈建议开启 admission webhook
enabled: true
createSecretJob:
resources:
limits:
cpu: 10m
memory: 20Mi
requests:
cpu: 10m
memory: 20Mi
patchWebhookJob:
resources:
limits:
cpu: 10m
memory: 20Mi
requests:
cpu: 10m
memory: 20Mi
patch:
enabled: true
image:
repository: cnych/ingress-nginx-webhook-certgen #老师做了镜像转存
tag: v1.1.1
digest:
defaultBackend: # 配置默认后端
enabled: true
name: defaultbackend
image:
repository: cnych/ingress-nginx-defaultbackend #老师做了镜像转存
tag: "1.5"
[root@master1 ingress-nginx]#vim /root/ingress-nginx/values.yaml
注意:部署成deployment和daemonset有什么区别?
假如说你的Ingress想要部署成多个副本,或者说是部署在多个节点上面,那么的话,肯定用daemonset形式。
因为你这个Ingress-nignx只需要一个节点部署一个副本就可以啊,你给他部署多个有什么意义吗?而且我们这里准备使用hostnetwork模式,因为你hostNetwork模式,你一个节点能部署多个副本吗?肯定不行的啦。如果你部署超过一个节点以上,那你就用daemonset模式吧。
这里大家就直接统一用我们的daemonset吧。
注意:我这里是打算只在master1节点上部署ingress-nginx。如果我想在node1和node2个节点行部署ingress-nginx的话,可以给这2个节点打上个label,例如 role=lb
,然后只需要把这个label写到 nodeSelector
下面就好。
Admission Webhook:这个里面的内容是什么鬼。。。
然后使用如下命令安装 ingress-nginx
应用到 ingress-nginx
的命名空间中:
[root@master1 ci]# kubectl create ns ingress-nginx
namespace/ingress-nginx created
[root@master1 ingress-nginx]#helm upgrade --install ingress-nginx . -f ./ci/daemonset-prod.yaml --namespace ingress-nginx
Release "ingress-nginx" does not exist. Installing it now.
NAME: ingress-nginx
LAST DEPLOYED: Sun Jan 2 15:59:35 2022
NAMESPACE: ingress-nginx
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The ingress-nginx controller has been installed.
It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status by running 'kubectl --namespace ingress-nginx get services -o wide -w ingress-nginx-controller'
An example Ingress that makes use of the controller:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example
namespace: foo
spec:
ingressClassName: nginx
rules:
- host: www.example.com
http:
paths:
- backend:
service:
name: exampleService
port:
number: 80
path: /
# This section is only required if TLS is to be enabled for the Ingress
tls:
- hosts:
- www.example.com
secretName: example-tls
If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided:
apiVersion: v1
kind: Secret
metadata:
name: example-tls
namespace: foo
data:
tls.crt: <base64 encoded cert>
tls.key: <base64 encoded key>
type: kubernetes.io/tls
[root@master1 ingress-nginx]#
部署完成后查看 Pod 的运行状态:
➜ kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller-admission ClusterIP 10.96.15.99 <none> 443/TCP 11m
ingress-nginx-defaultbackend ClusterIP 10.97.250.253 <none> 80/TCP 11m
➜ kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-controller-5dfdd4659c-9g7c2 1/1 Running 0 11m
ingress-nginx-defaultbackend-84854cd6cb-xb7rv 1/1 Running 0 11m
➜ POD_NAME=$(kubectl get pods -l app.kubernetes.io/name=ingress-nginx -n ingress-nginx -o jsonpath='{.items[0].metadata.name}')
➜ kubectl exec -it $POD_NAME -n ingress-nginx -- /nginx-ingress-controller --version
kubectl logs -f ingress-nginx-controller-5dfdd4659c-9g7c2 -n ingress-nginxW1216 08:51:22.179213 7 client_config.go:615] Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work.
I1216 08:51:22.179525 7 main.go:223] "Creating API client" host="https://10.96.0.1:443"
-------------------------------------------------------------------------------
NGINX Ingress controller
Release: v1.1.0
Build: cacbee86b6ccc45bde8ffc184521bed3022e7dee
Repository: https://github.com/kubernetes/ingress-nginx
nginx version: nginx/1.19.9
-------------------------------------------------------------------------------
I1216 08:51:22.198221 7 main.go:267] "Running in Kubernetes cluster" major="1" minor="22" git="v1.22.2" state="clean" commit="8b5a19147530eaac9476b0ab82980b4088bbc1b2" platform="linux/amd64"
I1216 08:51:22.200478 7 main.go:86] "Valid default backend" service="ingress-nginx/ingress-nginx-defaultbackend"
I1216 08:51:22.611100 7 main.go:104] "SSL fake certificate created" file="/etc/ingress-controller/ssl/default-fake-certificate.pem"
I1216 08:51:22.627386 7 ssl.go:531] "loading tls certificate" path="/usr/local/certificates/cert" key="/usr/local/certificates/key"
I1216 08:51:22.651187 7 nginx.go:255] "Starting NGINX Ingress controller"
当看到上面的信息证明 ingress-nginx
部署成功了,这里我们安装的是最新版本的控制器。安装完成后会自动创建一个 名为 nginx
的 IngressClass
对象:
[root@master1 ingress]#kubectl get ingressclass
NAME CONTROLLER PARAMETERS AGE
nginx k8s.io/ingress-nginx <none> 4h58m
[root@master1 ingress]#kubectl get ingressclass nginx -oyaml
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
annotations:
meta.helm.sh/release-name: ingress-nginx
meta.helm.sh/release-namespace: ingress-nginx
creationTimestamp: "2022-01-02T08:00:44Z"
generation: 1
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/version: 1.1.0
helm.sh/chart: ingress-nginx-4.0.13
name: nginx
resourceVersion: "1155600"
uid: e2be0a67-ee5c-4bcb-9733-fd65b63e3d14
spec:
controller: k8s.io/ingress-nginx
不过这里我们只提供了一个 controller
属性,如果还需要配置一些额外的参数,则可以在安装的 values 文件中进行配置。
查看过程
# 查看pod和svc
[root@master1 ingress-nginx]#kubectl get po -ningress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-controller-hq8cq 1/1 Running 0 3m49s
ingress-nginx-defaultbackend-84854cd6cb-zct8c 1/1 Running 0 3m49s
[root@master1 ingress-nginx]#kubectl get svc -ningress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller-admission ClusterIP 10.99.58.123 <none> 443/TCP 4m11s
ingress-nginx-defaultbackend ClusterIP 10.108.217.65 <none> 80/TCP 4m11s
# 查看下ingress-nginx-controller-admission这个svc的详细信息
[root@master1 ingress-nginx]#kubectl describe svc ingress-nginx-controller-admission -ningress-nginx
Name: ingress-nginx-controller-admission
Namespace: ingress-nginx
Labels: app.kubernetes.io/component=controller
app.kubernetes.io/instance=ingress-nginx
app.kubernetes.io/managed-by=Helm
app.kubernetes.io/name=ingress-nginx
app.kubernetes.io/version=1.1.0
helm.sh/chart=ingress-nginx-4.0.13
Annotations: meta.helm.sh/release-name: ingress-nginx
meta.helm.sh/release-namespace: ingress-nginx
Selector: app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.99.58.123
IPs: 10.99.58.123
Port: https-webhook 443/TCP
TargetPort: webhook/TCP
Endpoints: 172.29.9.51:8443
Session Affinity: None
Events: <none>
#查看下ingress-nginx-controller-hq8cq的信息
[root@master1 ingress-nginx]#kubectl get po ingress-nginx-controller-hq8cq -ningress-nginx -oyaml
……
containers:
- args: #这里是最终的一个启动参数。
- /nginx-ingress-controller
- --default-backend-service=$(POD_NAMESPACE)/ingress-nginx-defaultbackend
- --election-id=ingress-controller-leader
- --controller-class=k8s.io/ingress-nginx
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
- --validating-webhook=:8443
- --validating-webhook-certificate=/usr/local/certificates/cert
- --validating-webhook-key=/usr/local/certificates/key
……
ports: #这里使用的是hostnetwork模式
- containerPort: 80
hostPort: 80
name: http
protocol: TCP
- containerPort: 443
hostPort: 443
name: https
protocol: TCP
- containerPort: 8443
hostPort: 8443
name: webhook #给webhook使用的
protocol: TCP
……
#查看下这个ingress-controller pod的日志
[root@master1 ingress-nginx]#kubectl logs ingress-nginx-controller-hq8cq -ningress-nginx
-------------------------------------------------------------------------------
NGINX Ingress controller
Release: v1.1.0
Build: cacbee86b6ccc45bde8ffc184521bed3022e7dee
Repository: https://github.com/kubernetes/ingress-nginx
nginx version: nginx/1.19.9
-------------------------------------------------------------------------------
W0102 08:01:15.484487 7 client_config.go:615] Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work.
I0102 08:01:15.485077 7 main.go:223] "Creating API client" host="https://10.96.0.1:443"
I0102 08:01:15.573525 7 main.go:267] "Running in Kubernetes cluster" major="1" minor="22" git="v1.22.2" state="clean" commit="8b5a19147530eaac9476b0ab82980b4088bbc1b2" platform="linux/amd64"
I0102 08:01:15.618268 7 main.go:86] "Valid default backend" service="ingress-nginx/ingress-nginx-defaultbackend"
I0102 08:01:16.328944 7 main.go:104] "SSL fake certificate created" file="/etc/ingress-controller/ssl/default-fake-certificate.pem" #fake 相当于是一个自动生成的证书。
I0102 08:01:16.500957 7 ssl.go:531] "loading tls certificate" path="/usr/local/certificates/cert" key="/usr/local/certificates/key"
I0102 08:01:16.537831 7 nginx.go:255] "Starting NGINX Ingress controller"
I0102 08:01:16.702547 7 event.go:282] Event(v1.ObjectReference{Kind:"ConfigMap", Namespace:"ingress-nginx", Name:"ingress-nginx-controller", UID:"3a692b3f-5179-4c10-9d85-c0aea470358e", APIVersion:"v1", ResourceVersion:"1155577", FieldPath:""}): type: 'Normal' reason: 'CREATE' ConfigMap ingress-nginx/ingress-nginx-controller
I0102 08:01:17.847762 7 store.go:420] "Ignoring ingress because of error while validating ingress class" ingress="default/demo-ingress" error="ingress does not contain a valid IngressClass"
I0102 08:01:17.940230 7 nginx.go:297] "Starting NGINX process"
I0102 08:01:17.941600 7 leaderelection.go:248] attempting to acquire leader lease ingress-nginx/ingress-controller-leader...
I0102 08:01:17.942438 7 nginx.go:317] "Starting validation webhook" address=":8443" certPath="/usr/local/certificates/cert" keyPath="/usr/local/certificates/key"
I0102 08:01:17.949407 7 controller.go:155] "Configuration changes detected, backend reload required"
I0102 08:01:17.999391 7 leaderelection.go:258] successfully acquired lease ingress-nginx/ingress-controller-leader
I0102 08:01:18.000439 7 status.go:84] "New leader elected" identity="ingress-nginx-controller-hq8cq"
I0102 08:01:18.116727 7 status.go:215] "POD is not ready" pod="ingress-nginx/ingress-nginx-controller-hq8cq" node="master1"
I0102 08:01:18.813106 7 controller.go:172] "Backend successfully reloaded"
I0102 08:01:18.813225 7 controller.go:183] "Initial sync, sleeping for 1 second"
I0102 08:01:18.813633 7 event.go:282] Event(v1.ObjectReference{Kind:"Pod", Namespace:"ingress-nginx", Name:"ingress-nginx-controller-hq8cq", UID:"400302fc-0586-4e10-8808-19816c0e287d", APIVersion:"v1", ResourceVersion:"1155726", FieldPath:""}): type: 'Normal' reason: 'RELOAD' NGINX reload triggered due to a change in configuration
[root@master1 ingress-nginx]#
#看下ingress-nginx-controller configmap
[root@master1 ingress-nginx]#kubectl get cm ingress-nginx-controller -ningress-nginx -oyaml
# 可以看到,这里configmap的data是空的,如果后续想要对全局的ingress-controller做配置,就可以在这里配置confgimap。
apiVersion: v1
data:
allow-snippet-annotations: "true"
kind: ConfigMap
metadata:
annotations:
meta.helm.sh/release-name: ingress-nginx
meta.helm.sh/release-namespace: ingress-nginx
creationTimestamp: "2022-01-02T08:00:44Z"
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/version: 1.1.0
helm.sh/chart: ingress-nginx-4.0.13
name: ingress-nginx-controller
namespace: ingress-nginx
resourceVersion: "1155577"
uid: 3a692b3f-5179-4c10-9d85-c0aea470358e
[root@master1 ingress-nginx]#
通过日志我们可以看到一个报错:default/demo-ingress里面没配置IngressClass属性
I0102 08:01:17.847762 7 store.go:420] “Ignoring ingress because of error while validating ingress class” ingress=“default/demo-ingress” error=“ingress does not contain a valid IngressClass”
我们来查看下:
[root@master1 ingress-nginx]#kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
demo-ingress <none> * 80 24h
[root@master1 ingress-nginx]#kubectl get ingress demo-ingress -oyaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
……
spec: #上面报错,是因为这里没有一个a valid IngressClass。
rules:
- http:
paths:
- backend:
service:
name: test
port:
number: 80
path: /testpath
pathType: Prefix
status:
loadBalancer: {}
[root@master1 ingress-nginx]#
我们如何看当前有哪些ingress-controller呢?
[root@master1 ingress-nginx]#kubectl get ingressclass #可以看到这里有一个ingress-class
NAME CONTROLLER PARAMETERS AGE
nginx k8s.io/ingress-nginx <none> 22m
[root@master1 ingress-nginx]#pwd
/root/ingress-nginx
[root@master1 ingress-nginx]#ls
CHANGELOG.md Chart.yaml ci OWNERS README.md templates values.yaml
[root@master1 ingress-nginx]#cat templates/controller-ingressclass.yaml
{{- if .Values.controller.ingressClassResource.enabled -}} #这里是true
# We don't support namespaced ingressClass yet
# So a ClusterRole and a ClusterRoleBinding is required
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
labels:
{{- include "ingress-nginx.labels" . | nindent 4 }}
app.kubernetes.io/component: controller
{{- with .Values.controller.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
name: {{ .Values.controller.ingressClassResource.name }}
{{- if .Values.controller.ingressClassResource.default }}
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
{{- end }}
spec:
controller: {{ .Values.controller.ingressClassResource.controllerValue }}
{{ template "ingressClass.parameters" . }} #这里
{{- end }}
[root@master1 ingress-nginx]#cat values.yaml
ingressClassResource:
name: nginx
enabled: true
default: false
controllerValue: "k8s.io/ingress-nginx"
# Parameters is a link to a custom resource containing additional
# configuration for the controller. This is optional if the controller
# does not require extra parameters.
parameters: {} #这里
如果想让没配置ingressclass的ingress也是用这个ingress-controller,该怎么办呢?
[root@master1 ingress-nginx]#vim templates/controller-ingressclass.yaml
[root@master1 ingress-nginx]#vim values.yaml 要记得把这里的false改为true。
ingress里面的 backend
内容
[root@master1 ingress-nginx]#kubectl get ingress demo-ingress -oyaml
注意,生成的这个deafultbackend你可以理解为一个404页面提供的内容。
安装成功后,现在我们来为一个 nginx 应用创建一个 Ingress 资源,如下所示:
[root@master1 ingress]#vim first-ingress.yaml
# my-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
app: my-nginx
template:
metadata:
labels:
app: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
app: my-nginx
spec:
ports:
- port: 80
protocol: TCP
name: http
selector:
app: my-nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-nginx
namespace: default
spec:
ingressClassName: nginx # 使用 nginx 的 IngressClass(关联的 ingress-nginx 控制器)
rules:
- host: ngdemo.qikqiak.com # 将域名映射到 my-nginx 服务
http:
paths:
- path: /
pathType: Prefix
backend:
service: # 将所有请求发送到 my-nginx 服务的 80 端口
name: my-nginx
port:
number: 80
# 不过需要注意大部分Ingress控制器都不是直接转发到Service,而是只是通过Service来获取后端的Endpoints列表(因此这里的svc只起到了一个服务发现的作用),直接转发到Pod,这样可以减少网络跳转,提高性能!!!
⚠️ 注意:
upstream里面可以配置很多的负载策略,并且可以让nginx去帮我们做一个可定制的负载;
直接创建上面的资源对象:
[root@master1 ingress]#kubectl apply -f first-ingress.yaml
deployment.apps/my-nginx created
service/my-nginx created
ingress.networking.k8s.io/my-nginx created
[root@master1 ingress]#kubectl get po
NAME READY STATUS RESTARTS AGE
my-nginx-7c4ff94949-lwvjf 1/1 Running 0 8s
nginx-5d59d67564-kgd4q 1/1 Running 0 4d19h
nginx-5d59d67564-lxnt2 1/1 Running 2 (8h ago) 4d19h
test-node-local-dns 1/1 Running 23 (46m ago) 4d20h
[root@master1 ingress]#kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 63d
my-nginx ClusterIP 10.110.207.185 <none> 80/TCP 18s
nginx-service ClusterIP 10.106.35.68 <none> 5000/TCP 5d1h
记得在本地pc里配置下域名解析:
C:\WINDOWS\System32\drivers\etc
172.29.9.51 ngdemo.qikqiak.com
[root@master1 ingress]#kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
demo-ingress <none> * 80 31h
my-nginx nginx ngdemo.qikqiak.com 172.29.9.51 80 5h10m
在上面的 Ingress 资源对象中我们使用配置 ingressClassName: nginx
指定让我们安装的 ingress-nginx
这个控制器来处理我们的 Ingress 资源,配置的匹配路径类型为前缀的方式去匹配 /
,将来自域名 ngdemo.qikqiak.com
的所有请求转发到 my-nginx
服务的后端 Endpoints 中去。
上面资源创建成功后,然后我们可以将域名 ngdemo.qikqiak.com
解析到 ingress-nginx
所在的边缘节点中的任意一个,当然也可以在本地 /etc/hosts
中添加对应的映射也可以,然后就可以通过域名进行访问了。
(本地测试这里直接配置了hosts,但线上的还一般就是用dns了;)
http://ngdemo.qikqiak.com/
下图显示了客户端是如何通过 Ingress 控制器连接到其中一个 Pod 的流程,客户端首先对 ngdemo.qikqiak.com
执行 DNS 解析,得到 Ingress 控制器所在节点的 IP,然后客户端向 Ingress 控制器发送 HTTP 请求,然后根据 Ingress 对象里面的描述匹配域名,找到对应的 Service 对象,并获取关联的 Endpoints 列表,将客户端的请求转发给其中一个 Pod。
前面我们也提到了 ingress-nginx
控制器的核心原理就是将我们的 Ingress
这些资源对象映射翻译成 Nginx 配置文件 nginx.conf
,我们可以通过查看控制器中的配置文件来验证这点:
[root@master1 ingress]#kubectl exec ingress-nginx-controller-hq8cq -ningress-nginx -- cat /etc/nginx/nginx.conf
......
upstream upstream_balancer {
server 0.0.0.1; # placeholder
balancer_by_lua_block {
balancer.balance()
}
keepalive 320;
keepalive_timeout 60s;
keepalive_requests 10000;
}
......
## start server ngdemo.qikqiak.com
server {
server_name ngdemo.qikqiak.com ;
listen 80 ;
listen [::]:80 ;
listen 443 ssl http2 ;
listen [::]:443 ssl http2 ;
set $proxy_upstream_name "-";
ssl_certificate_by_lua_block {
certificate.call()
}
location / {
set $namespace "default";
set $ingress_name "my-nginx";
set $service_name "my-nginx";
set $service_port "80";
set $location_path "/";
set $global_rate_limit_exceeding n;
......
proxy_next_upstream_timeout 0;
proxy_next_upstream_tries 3;
proxy_pass http://upstream_balancer #这里
proxy_redirect off;
}
}
## end server ngdemo.qikqiak.com
......
我们可以在 nginx.conf
配置文件中看到上面我们新增的 Ingress 资源对象的相关配置信息,不过需要注意的是:⚠️现在并不会为每个 backend 后端都创建一个 upstream
配置块,现在是使用 Lua 程序进行动态处理的,所以我们没有直接看到后端的 Endpoints 相关配置数据(以前的版本是可以看到的)。
详细解析过程如下:
hostnetwork模式部署的ingress-controller:
helm version
那我现在有个问题:
helm repo list
helm.sh
我们现在都是用v3版本:
helm和kubectl一样,都是去读取的这个kubeconfig文件。
⚠️
也就是说你的kubectl在哪个地方可以使用,那么你的heml就可以在哪个地方使用。
我们把nginx一般就当作流量的入口。
比如说你的客户端client请求到我们的nginx,这里的话,就是ingress-nigx。
客户端一般是通过域名解析(例如这里的www.qikqiak.com),到达这里的ingress-nginx,它为什么能到呢?肯定是你有一个域名解析的,它解析到了我这个ingress-nginx所在的节点,这是最简单的方式;
那如果你是http访问的话,那你肯定是访问80端口的,如果是https的话,肯定是访问443端口的;
所以说,你的nginx要把80和443端口给放开;
当然如果你的域名解析(www.qikqiak.com)有可能不是直接解析到你的nginx这里来的,有可能解析到云上面slb上(那你slb上面肯定要把80|443端口给放开来的),然后这个请求给分发到哪里去呢?那么就看你slb要把请求分发到哪里去呢?可以把它分发到你后面的这个ingress-nginx,比如说分发到她的一个30080| 30443,这样也可以。
所以它的一个安装的场景,是要看你自己的。
我们现在是最简单的,直接通过域名解析到ingress-nginx所在的节点上去的;
在helm3之前的版本里,它由客户端helm和服务端tiller组成,而helm3.0之后它去掉了tiller,而直接与k8s通讯,可以说在部署上更简单了。
参考链接:csdn文章 https://blog.csdn.net/weixin_38320674/article/details/106515349 (包含2版本如何安装)
helm安装
Helm相当于linux环境下的yum包管理工具。helm是k8s中的一个命令行客户端工具,helm是tiller的客户端,tiller是一个守护进程,接收helm的请求,helm把请求交给tiller,tiler和apiserver交互,由apiserver负责完成创建,我们用哪个chart需要下载到本地,基于本地这个chart部署实例,这个部署的实例叫做release。
1.chart是什么?
一个helm程序包,比方说我们部署nginx,需要deployment的yaml,需要service的yaml,这两个清单文件就是一个helm程序包,在k8s中把这些yaml清单文件叫做chart图表
2.values.yaml文件
values.yaml文件为模板中的文件赋值,可以实现我们自定义安装,如果是chart开发者需要自定义模板,如果是chart使用者只需要修改values.yaml即可。
3.helm可理解如下
helm把kubernetes资源打包到一个chart中,制作并完成各个chart和chart本身依赖关系并利用chart仓库实现对外分发,而helm还可实现可配置的对外发布,通过values.yaml文件完成可配置的发布,如果chart版本更新了,helm自动支持滚更更新机制,还可以一键回滚,但是不是适合在生产环境使用,除非具有定义自制chart的能力,helm属于kubernetes一个项目,下载地址:
https://github.com/helm/helm/releases
找这个checksum的,解压之后按下面解压即可
helm官方网站:
https://helm.sh/
helm 官方的chart站点:
https://hub.kubeapps.com/
4.repository、release、chart关系
repository:存放chart图表的仓库,提供部署k8s应用程序需要的那些yaml清单文件
release:特定的chart部署于目标集群上的一个实例
chart—>通过values.yaml这个文件赋值–>生成release实例
helm也是go语言开发的。
自己尝试下安装helm(安装成功)
helm安装方法:
当前环境:
k8s v1.22.2(containerd://1.5.5)
helm-v3.7.2
[root@master1 ~]#ll
-rw-r--r-- 1 root root 13870692 Jan 2 08:54 helm-v3.7.2-linux-amd64.tar.gz
[root@master1 ~]#tar zxvf helm-v3.7.2-linux-amd64.tar.gz
linux-amd64/
linux-amd64/helm
linux-amd64/LICENSE
linux-amd64/README.md
[root@master1 ~]#cd linux-amd64/
[root@master1 linux-amd64]#ls
helm LICENSE README.md
[root@master1 linux-amd64]#cp helm /usr/local/bin
[root@master1 linux-amd64]#helm version
version.BuildInfo{Version:"v3.7.2", GitCommit:"663a896f4a815053445eec4153677ddc24a0a361", GitTreeState:"clean", GoVersion:"go1.16.10"}
这个是go开发都 软件包,直接放到PATH路径下就可以使用了!完美。
部署ingress-nginx:
[root@master1 ~]#helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
"ingress-nginx" has been added to your repositories
[root@master1 ~]#helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "ingress-nginx" chart repository
Update Complete. ⎈Happy Helming!⎈
[root@master1 ~]#helm repo list
NAME URL
ingress-nginx https://kubernetes.github.io/ingress-nginx
[root@master1 ~]#helm fetch ingress-nginx/ingress-nginx
[root@master1 ~]#ll
-rw-r--r-- 1 root root 27766 Jan 2 09:06 ingress-nginx-4.0.13.tgz
[root@master1 ~]#tar -xvf ingress-nginx-4.0.13.tgz && cd ingress-nginx
ingress-nginx/Chart.yaml
ingress-nginx/values.yaml
ingress-nginx/templates/NOTES.txt
ingress-nginx/templates/_helpers.tpl
ingress-nginx/templates/_params.tpl
ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml
ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml
ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml
ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml
ingress-nginx/templates/admission-webhooks/job-patch/psp.yaml
ingress-nginx/templates/admission-webhooks/job-patch/role.yaml
ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml
ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml
ingress-nginx/templates/admission-webhooks/validating-webhook.yaml
ingress-nginx/templates/clusterrole.yaml
ingress-nginx/templates/clusterrolebinding.yaml
ingress-nginx/templates/controller-configmap-addheaders.yaml
ingress-nginx/templates/controller-configmap-proxyheaders.yaml
ingress-nginx/templates/controller-configmap-tcp.yaml
ingress-nginx/templates/controller-configmap-udp.yaml
ingress-nginx/templates/controller-configmap.yaml
ingress-nginx/templates/controller-daemonset.yaml
ingress-nginx/templates/controller-deployment.yaml
ingress-nginx/templates/controller-hpa.yaml
ingress-nginx/templates/controller-ingressclass.yaml
ingress-nginx/templates/controller-keda.yaml
ingress-nginx/templates/controller-poddisruptionbudget.yaml
ingress-nginx/templates/controller-prometheusrules.yaml
ingress-nginx/templates/controller-psp.yaml
ingress-nginx/templates/controller-role.yaml
ingress-nginx/templates/controller-rolebinding.yaml
ingress-nginx/templates/controller-service-internal.yaml
ingress-nginx/templates/controller-service-metrics.yaml
ingress-nginx/templates/controller-service-webhook.yaml
ingress-nginx/templates/controller-service.yaml
ingress-nginx/templates/controller-serviceaccount.yaml
ingress-nginx/templates/controller-servicemonitor.yaml
ingress-nginx/templates/default-backend-deployment.yaml
ingress-nginx/templates/default-backend-hpa.yaml
ingress-nginx/templates/default-backend-poddisruptionbudget.yaml
ingress-nginx/templates/default-backend-psp.yaml
ingress-nginx/templates/default-backend-role.yaml
ingress-nginx/templates/default-backend-rolebinding.yaml
ingress-nginx/templates/default-backend-service.yaml
ingress-nginx/templates/default-backend-serviceaccount.yaml
ingress-nginx/templates/dh-param-secret.yaml
ingress-nginx/.helmignore
ingress-nginx/CHANGELOG.md
ingress-nginx/OWNERS
ingress-nginx/README.md
ingress-nginx/ci/controller-custom-ingressclass-flags.yaml
ingress-nginx/ci/daemonset-customconfig-values.yaml
ingress-nginx/ci/daemonset-customnodeport-values.yaml
ingress-nginx/ci/daemonset-headers-values.yaml
ingress-nginx/ci/daemonset-internal-lb-values.yaml
ingress-nginx/ci/daemonset-nodeport-values.yaml
ingress-nginx/ci/daemonset-podannotations-values.yaml
ingress-nginx/ci/daemonset-tcp-udp-configMapNamespace-values.yaml
ingress-nginx/ci/daemonset-tcp-udp-values.yaml
ingress-nginx/ci/daemonset-tcp-values.yaml
ingress-nginx/ci/deamonset-default-values.yaml
ingress-nginx/ci/deamonset-metrics-values.yaml
ingress-nginx/ci/deamonset-psp-values.yaml
ingress-nginx/ci/deamonset-webhook-and-psp-values.yaml
ingress-nginx/ci/deamonset-webhook-values.yaml
ingress-nginx/ci/deployment-autoscaling-behavior-values.yaml
ingress-nginx/ci/deployment-autoscaling-values.yaml
ingress-nginx/ci/deployment-customconfig-values.yaml
ingress-nginx/ci/deployment-customnodeport-values.yaml
ingress-nginx/ci/deployment-default-values.yaml
ingress-nginx/ci/deployment-headers-values.yaml
ingress-nginx/ci/deployment-internal-lb-values.yaml
ingress-nginx/ci/deployment-metrics-values.yaml
ingress-nginx/ci/deployment-nodeport-values.yaml
ingress-nginx/ci/deployment-podannotations-values.yaml
ingress-nginx/ci/deployment-psp-values.yaml
ingress-nginx/ci/deployment-tcp-udp-configMapNamespace-values.yaml
ingress-nginx/ci/deployment-tcp-udp-values.yaml
ingress-nginx/ci/deployment-tcp-values.yaml
ingress-nginx/ci/deployment-webhook-and-psp-values.yaml
ingress-nginx/ci/deployment-webhook-resources-values.yaml
ingress-nginx/ci/deployment-webhook-values.yaml
[root@master1 ingress-nginx]#ls
CHANGELOG.md Chart.yaml ci OWNERS README.md templates values.yaml
[root@master1 ingress-nginx]#
[root@master1 ~]#cd ingress-nginx/
[root@master1 ingress-nginx]#ls
CHANGELOG.md Chart.yaml ci OWNERS README.md templates values.yaml
[root@master1 ingress-nginx]#vim templates/controller-ingressclass.yaml
#这个其实是go模板渲染的;可能说,大家对这个golang 的template不熟悉,现在让大家去写这个模板,可能有难度。
[root@master1 ingress-nginx]#vim values.yaml
再看一个:
[root@master1 templates]#ls
admission-webhooks controller-serviceaccount.yaml
clusterrolebinding.yaml controller-service-internal.yaml
clusterrole.yaml controller-service-metrics.yaml
controller-configmap-addheaders.yaml controller-servicemonitor.yaml
controller-configmap-proxyheaders.yaml controller-service-webhook.yaml
controller-configmap-tcp.yaml controller-service.yaml
controller-configmap-udp.yaml default-backend-deployment.yaml
controller-configmap.yaml default-backend-hpa.yaml
controller-daemonset.yaml default-backend-poddisruptionbudget.yaml
controller-deployment.yaml default-backend-psp.yaml
controller-hpa.yaml default-backend-rolebinding.yaml
controller-ingressclass.yaml default-backend-role.yaml
controller-keda.yaml default-backend-serviceaccount.yaml
controller-poddisruptionbudget.yaml default-backend-service.yaml
controller-prometheusrules.yaml dh-param-secret.yaml
controller-psp.yaml _helpers.tpl
controller-rolebinding.yaml NOTES.txt
controller-role.yaml _params.tpl
[root@master1 templates]#vim controller-deployment.yaml
[root@master1 ingress-nginx]#vim values.yaml
其中的 ci
目录中就包含了各种场景下面安装的 Values 配置文件,values.yaml
文件中包含的是所有可配置的默认值,我们可以对这些默认值进行覆盖。
[root@master1 ci]#pwd
/root/ingress-nginx/ci
[root@master1 ci]#vim deployment-tcp-values.yam
[root@master1 ingress-nginx]#pwd
/root/ingress-nginx
[root@master1 ingress-nginx]#vim values.yam
我的博客主旨:我希望每一个人拿着我的博客都可以做出实验现象,先把实验做出来,然后再结合理论知识更深层次去理解技术点,这样学习起来才有乐趣和动力。并且,我的博客内容步骤是很完整的,也分享源码和实验用到的软件,希望能和大家一起共同进步!
各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人免费帮您解决问题:
个人微信二维码:x2675263825 (舍得), qq:2675263825。
个人博客地址:www.onlyonexl.cn
个人微信公众号:云原生架构师实战
个人csdn
https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421
好了,关于ingress-nginx实验就到这里了,感谢大家阅读,最后贴上我女神的photo,祝大家生活快乐,每天都过的有意义哦,我们下期见!