K8S ingress 初体验 - ingress-ngnix 的安装与使用

准备环境

先把 google 的vm 跑起来…
在这里插入图片描述

gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-user$ kubectl get nodes
NAME         STATUS     ROLES                  AGE    VERSION
k8s-master   Ready      control-plane,master   124d   v1.23.6
k8s-node0    Ready      <none>                 124d   v1.23.6
k8s-node1    NotReady   <none>                 124d   v1.23.6
k8s-node3    Ready      <none>                 104d   v1.23.6

当前的环境是干净的

gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-user$ kubectl get all -o wide
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   81d   <none>





准备1个 micro-service 和 1个clusterIP

在这里插入图片描述
大概框架如上图:

组件

micro service

我会先构建1个 微服务 bq-api-service 并部署到集群, 设成4个pods

clusterIP

我会构建1个 ClusterIP service: clusterip-bq-api-service 作为上面微服务的loadbanlance 和 revserse proxy

测试pod dns-test

因为没有nodePort 和 ingress, 只能用测试POD 去尝试通过 clusterip service 链接 bq-api-serivce

部署bq-api-service

deployment-bq-api-service.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels: # label of this deployment
    app: bq-api-service # custom defined
    author: nvd11
  name: deployment-bq-api-service # name of this deployment
  namespace: default
spec:
  replicas: 4            # desired replica count, Please note that the replica Pods in a Deployment are typically distributed across multiple nodes.
  revisionHistoryLimit: 10 # The number of old ReplicaSets to retain to allow rollback
  selector: # label of the Pod that the Deployment is managing,, it's mandatory, without it , we will get this error 
            # error: error validating data: ValidationError(Deployment.spec.selector): missing required field "matchLabels" in io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector ..
    matchLabels:
      app: bq-api-service
  strategy: # Strategy of upodate
    type: RollingUpdate # RollingUpdate or Recreate
    rollingUpdate:
      maxSurge: 25% # The maximum number of Pods that can be created over the desired number of Pods during the update
      maxUnavailable: 25% # The maximum number of Pods that can be unavailable during the update
  template: # Pod template
    metadata:
      labels:
        app: bq-api-service # label of the Pod that the Deployment is managing. must match the selector, otherwise, will get the error Invalid value: map[string]string{"app":"bq-api-xxx"}: `selector` does not match template `labels`
    spec:
      containers:
      - image: europe-west2-docker.pkg.dev/jason-hsbc/my-docker-repo/bq-api-service:1.1.7 # image of the container
        imagePullPolicy: IfNotPresent
        name: bq-api-service-container
        env: # set env varaibles
        - name: APP_ENVIRONMENT
          value: prod
      restartPolicy: Always # Restart policy for all containers within the Pod
      terminationGracePeriodSeconds: 10 # The period of time in seconds given to the Pod to terminate gracefully


---
apiVersion: v1
kind: Service
metadata:
  name: clusterip-bq-api-service
spec:
  selector:
    app: bq-api-service # for the pods that have the label app: bq-api-service
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
  type: ClusterIP

执行命令:

gateman@MoreFine-S500:~/projects/coding/k8s-s/ingress/test$ kubectl apply -f bq-api-service.yml 
deployment.apps/deployment-bq-api-service created
service/clusterip-bq-api-service unchanged
gateman@MoreFine-S500:~/projects/coding/k8s-s/ingress/test$ kubectl get ep -o wide
NAME                       ENDPOINTS                                                         AGE
clusterip-bq-api-service   10.244.1.70:8080,10.244.1.71:8080,10.244.2.141:8080 + 1 more...   36s
kubernetes                 192.168.0.3:6443                                                  83d
gateman@MoreFine-S500:~/projects/coding/k8s-s/ingress/test$ kubectl get pods -o wide
NAME                                         READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
deployment-bq-api-service-6f6ffc7866-2mn5n   1/1     Running   0          27s   10.244.2.141   k8s-node0   <none>           <none>
deployment-bq-api-service-6f6ffc7866-74bcq   1/1     Running   0          27s   10.244.1.70    k8s-node1   <none>           <none>
deployment-bq-api-service-6f6ffc7866-l2xzb   1/1     Running   0          27s   10.244.1.71    k8s-node1   <none>           <none>
deployment-bq-api-service-6f6ffc7866-lwxt7   1/1     Running   0          27s   10.244.3.82    k8s-node3   <none>           <none>

看起来没什么问题

测试cluster ip 的连接

先进入dns-test

gateman@MoreFine-S500:~/projects/coding/k8s-s/ingress/test$ kubectl run dns-test --image=odise/busybox-curl --restart=Never -- /bin/sh -c "while true; do echo hello docker; sleep 1; done"
pod/dns-test created
gateman@MoreFine-S500:~/projects/coding/k8s-s/ingress/test$ kubectl exec -it dns-test -- /bin/sh
/ # 

测试调用clusterip service

/ # curl clusterip-bq-api-service:8080/actuator/info
{"app":"Sales API","version":"1.1.7","hostname":"deployment-bq-api-service-6f6ffc7866-2mn5n","description":"This is a simple Spring Boot application to demonstrate the use of BigQuery in GCP."}/ # 
/ # curl clusterip-bq-api-service:8080/actuator/info
/ # curl clusterip-bq-api-service:8080/actuator/info
{"app":"Sales API","version":"1.1.7","hostname":"deployment-bq-api-service-6f6ffc7866-l2xzb","description":"This is a simple Spring Boot application to demonstrate the use of BigQuery in GCP."}/ # 

看来 reverse proxy 和 loadbalance 都生效~





安装helm

下载:
https://github.com/helm/helm/releases

配置~/.bashrc 就好

export PATH=$PATH:/home/gateman/devtools/helm

测试version

gateman@MoreFine-S500:~/projects/coding/k8s-s/ingress/test$ helm version
version.BuildInfo{
   Version:"v3.15.2", GitCommit:"1a500d5625419a524fdae4b33de351cc4f58ec35", GitTreeState:"clean", GoVersion:"go1.22.4"}





通过helm 安装 ingress-nginx controller

把 ingress-ngnix 的repo 添加到helm
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

查看repo list

gateman@MoreFine-S500:~/projects/coding/k8s-s/ingress/test$  helm repo list
NAME         	URL                                       
ingress-nginx	https://kubernetes.github.io/ingress-nginx
helm 下载 ingress-nginx package

helm pull <package-name>

helm pull ingress-nginx/ingress-nginx

这时, 会下载1个tgz 文件 ingress-nginx-4.10.1.tgz

解压:

gateman@MoreFine-S500:~/projects/coding/k8s-s/ingress/ingress-nginx/helm/ingress-nginx$ ls -l
total 132
drwxrwxr-x 2 gateman gateman  4096  625 01:26 changelog
-rw-r--r-- 1 gateman gateman   752  426 22:02 Chart.yaml
drwxrwxr-x 2 gateman gateman  4096  625 01:26 ci
-rw-r--r-- 1 gateman gateman   177  426 22:02 OWNERS
-rw-r--r-- 1 gateman gateman 49134  426 22:02 README.md
-rw-r--r-- 1 gateman gateman 11358  426 22:02 README.md.gotmpl
drwxrwxr-x 3 gateman gateman  4096  625 01:26 templates
drwxrwxr-x 2 gateman gateman  4096  625 01:26 tests
-rw-r--r-- 1 gateman gateman 45136  625 02:02 values.yaml

其中values.yaml 就是最终要的配置文件

修改values.yaml

有些教程让我们修改 image repo 的 address 指向阿里云加速, 由于我的server在google cloud 就忽略这一步了。

  1. controller.kind -> 由 Deployment 改成 DaemonSet
    这样做的优点是
    a. 能够保证每个Node节点上都运行一个 ingress-nginx Pod实例,实现全集群访问入口。(实际上我们会用label 只让ingress-nginx 部署在1台node上)
    b. 节点故障转移时,新的Node上会自动启动Pod,保证入口始终可用。

  2. controller.hostnetwork -> 由false 改成 true
    这是DaemonSet的默认网络模式。每个Pod将直接共享Node的网络栈和资源,简化了网络配置。
    但同时也会带来上面提到的一些隔离性和安全性问题。

  3. controller.dnsPolic-> 由 ClusterFirst 改成 ClusterFirstWithHostNet
    ClusterFirst表示使用集群提供的DNS服务进行解析,这也是默认策略。
    但是DaemonSet使用hostNetwork模式后,Pod会直接使用宿主机的网络命名空间。
    此时设置dnsPolicy=ClusterFirstWithHostNet表示:
    首先使用集群的DNS服务来解析域名。
    如果集群DNS无法响应,则解析请求会转发到宿主机的DNS服务上寻求响应。
    这样可以实现两个目的:
    使用集群的DNS服务提高可配置性和维护性。
    同时如果集群DNSdown掉,Pod也可以fallback到宿主机本地DNS上,保证关键服务名能被解析到。
    这相比直接使用宿主机DNS或仅使用集群DNS更加灵活。
    因此对于使用hostNetwork的DaemonSet,dnsPolicy设置为ClusterFirstWithHostNet可以充分利用集群和宿主机的DNS功能,提高服务可用性。

  4. controller.service.type -> 由 Loadbalancer 改成 ClusterIP
    对于用Helm部署ingress-nginx,使用ClusterIP作为service类型通常是更好的选择。
    LoadBalancer类型会要求底层基础设施如云平台自动为ingress分配公网IP地址,但这可能会产生额外的网络开支。
    考虑到大多数K8S集群运行在内网环境,使用ClusterIP就可以满足需求。后续还可以配置支持内网访问的解决方案,如NodePort或External IPs。
    一般来说,你可以直接在values.yaml里修改service.type为ClusterIP:

在部署 ingress-nginx controller 之前(我们已经把它改成1个DaemonSet), 为它创建1个单独的namespace
kubectl create ns ingress-nginx

我们之后会单独地把 ingress-ingress 部署在这个 同名字的namespace 上面。

问题来了, 在命名空间A的 ingress controller 可以用与命名空间B的ingress 实例吗?

答案是yes:

关于Ingress controller namespace与Ingress资源namespace的关系:

1. Ingress controller一般会部署在单独的namespace下,比如ingress-namespace。
2. Ingress资源可以定义在任何namespace中。
3. Kubernetes会检测所有namespace下是否有Ingress Controller的服务运行。
	如果有,则Ingress资源对应的namespace会自动重定向到Ingress controller所在的namespace。
	Ingress controller通过监视Apiserver,可以查询到集群内所有namespace下定义的Ingress资源。
	
也就是说:

1. Ingress controller和Ingress资源可以部署在不同的namespace。
2. Kubernetes会自动帮助Ingress资源找到部署在哪个namespace的Ingress controller。
3. Ingress controller 通过Apiserver可以查到所有namespace下的Ingress定义。



为所在node添加label

ingress-controller 作为1个类网关程序, 理论上只在其中1个node 部署就够了

由于我们修改了value.yaml, 把这个controll的类型改成了DaemonSet 所以, 理论上每个node 都会部署1个pod, 是有资源浪费的。

而实际上, value.yaml 有定义了1个规则- node selector, 只有具有某个label ingress=true 的node 才会部署

node selector 的定义:
controller.nodeSelector:

  nodeSelector: # nodeSelector of DaemonSet we updated
    kubernetes.io/os: linux
    ingress: "true" # use String instead of bool

所以我们只需要为1台node 添加这个label 就好

但是, 如果我们只给master node添加label是不work的, 因为master node 配置了污点, 会bypass 大部分 deployment/DaemonSet 的部署

这次我们只给k8s-node0 这个node 添加label

gateman@MoreFine-S500:~/projects/coding/k8s-s/ingress/ingress-nginx/helm/ingress-nginx$ kubectl label no k8s-node0 ingress=true
node/k8s-node0 labeled

查看label

gateman@MoreFine-S500:~/tmp/ingress-nginx$ kubectl get nodes --show-labels=true
NAME         STATUS   ROLES                  AGE    VERSION   LABELS
k8s-master   Ready    control-plane,master   128d   v1.23.6   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
k8s-node0    Ready    <none>                 128d   v1.23.6   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node0,kubernetes.io/os=linux
k8s-node1    Ready    <none>                 128d   v1.23.6   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux
k8s-node3    Ready    <none>                 108d   v1.23.6   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node3,kubernetes.io/os=linux



部署ingress-inginx controller

进入之前解压的folder (value.yaml)的上一层

执行
helm install nginx

gateman@MoreFine-S500:~/projects/coding/k8s-s/ingress/ingress-nginx/helm/ingress-nginx$ helm install ingress-nginx -n ingress-nginx .
NAME: ingress-nginx
LAST DEPLOYED: Tue Jun 25 02:16:57 2024
NAMESPACE: ingress-nginx
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The ingress-nginx controller has been installed.

检查pods

gateman@MoreFine-S500:~/tmp/ingress-nginx$ kubectl get po -o wide -n ingress-nginx
NAME                             READY   STATUS    RESTARTS        AGE     IP            NODE        NOMINATED NODE   READINESS GATES
ingress-nginx-controller-72dmb   1/1     Running   3 (2d18h ago)   6d20h   192.168.0.6   k8s-node0   <none>           <none>

可见这个ingress-controller 已经运行在了 k8s-node0





创建1个ingress 资源

创建yaml

yaml file:

apiVersion: networking.k8s.io/v1
kind: Ingress # it is a resource name of k8s
metadata
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nvd11

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值