k8s service与ingress

1.前言

service只能作用与网络模型中的四层,ingress可以作用于网络模型中的七层,Service是一种抽象,定义了一个逻辑上的一组Pod以及访问它们的策略。Service为Pod提供了一个稳定的IP地址和DNS名称,并通过标签选择器来定义需要暴露的Pod。Service可以通过Cluster IP、Node Port、Load Balancer和External Name等方式来提供服务,这取决于具体的部署需求

Ingress是在Kubernetes集群中暴露HTTP和HTTPS服务的API对象。它为集群中的服务提供外部访问,并提供负载均衡、SSL终止和基于名称的虚拟主机等功能。Ingress通过将流量路由到不同的后端Service来实现这些功能。Ingress需要一个Ingress Controller来实现其规则,这个控制器可以是Kubernetes自带的或者是第三方提供的

简单来说,Service用于在Kubernetes集群内部暴露服务,而Ingress则用于将服务暴露到集群外部,使得外部用户可以通过HTTP或HTTPS协议访问应用程序,相当于nginx的反向代理

endpoint

service并不是单独工作就可以对pod进行负载均衡服务,实际上还需要endpoint的协助

Service 代表一个逻辑的服务,它负责将一组 Pod 组合成一个可访问的服务,Endpoint 是 Service 的底层实现,它包含了 Service 关联的一组 Pod 的实际 IP 地址和端口信息,当 Service 与一组 Pod 关联时,Kubernetes 会自动创建并更新对应的 Endpoint,以确保 Service 能够正确地发现和负载均衡到这些 Pod

 

2.更改kube-proxy代理

在开始之前,先把kube-proxy代理的模式改为ipvs模式

kubectl edit cm kube-proxy -n kube-system

 再把所有kube-proxy的pod重启一下

kubectl delete pod -l k8s-app=kube-proxy -n kube-system

kubectl get pod -l k8s-app=kube-proxy -n kube-system

3.service

接下来简单的使用一下service的几种方式,这里展示ClusterIP、NodePort、headless的使用

3.1ClusterIP

编辑yaml文件

vi deployment-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata: 
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  replicas: 5
  progressDeadlineSeconds: 600
  minReadySeconds: 10
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec: 
      containers:
      - name: nginx
        image: nginx:1.21
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
spec:
  selector:         #配置标签选择,选择符合该标签的pod
    app: nginx       
  type: ClusterIP    #配置service模式为ClusterIP
  clusterIP:         #可以指定ClusterIP地址,留空就会自动生成ClusterIP地址
  ports:
    - port: 80      #service服务的端口
      targetPort: 80    #pod监听的端口
      protocol: TCP    #配置网络协议

执行yaml文件

kubectl create -f deployment-nginx.yaml

kubectl get service

kubectl describe service nginx

kubectl get pod -o wide -l app=nginx

可以看到service已经创建出来了,并且已经绑定了pod,通过service访问一下pod的端口服务看看效果

curl 10.98.144.122:80 

可以看到能成功访问到pod的端口服务,使用ClusterIP方式只能在集群内部访问,集群外访问不了

以下再补充一下ClusterIP方式的一些知识

ipvsadm -Ln

通过ipvsadm命令可以看到我们使用的ClusterIP访问pod的方式为轮询,rr代表轮询模式,即每次请求都会按顺序顺延访问每个pod的服务 ,有些场景下我们可能会希望每个访问的ip,都能固定访问一个pod服务,而不是轮询每个pod,我们就可以在配置文件中引入一个sessionAffinity参数,接下来配置一下看看

vi deployment-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata: 
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  replicas: 5
  progressDeadlineSeconds: 600
  minReadySeconds: 10
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec: 
      containers:
      - name: nginx
        image: nginx:1.21
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
spec:
  selector:
    app: nginx
  type: ClusterIP 
  clusterIP:
  sessionAffinity: ClientIP  #增加ClientIP参数值,使得访问的ip固定访问一个pod服务
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP

执行一下yaml

kubectl create -f deployment-nginx.yaml

kubectl get service 

kubectl get pod -o wide -l app=nginx

ipvsadm -Ln

从上图可以看到不在单单是显示rr轮询模式,可以更改nginx的页面内容去试一下,相同的ip访问的内容是固定的,因为我这边做过了试验,在这里就不展示了

 3.2NodePort

编辑yaml文件

vi deployment-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata: 
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  replicas: 5
  progressDeadlineSeconds: 600
  minReadySeconds: 10
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec: 
      containers:
      - name: nginx
        image: nginx:1.21
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
spec:
  selector:
    app: nginx
  type: NodePort    #选择NodePort类型
  clusterIP:
  sessionAffinity: ClientIP
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30001   #配置nodePort外部端口,不设置则随机分配
      protocol: TCP

执行yaml

kubectl create -f deployment-nginx.yam

kubectl get service

kubectl get pod -o wide -l app=nginx

可以看到已经按要求创建出了service,现在来访问一下看看效果,我们直接用集群外的网络来访问看看

 可以看到使用NodePort方式,可以在集群外部访问到pod端口服务

补充一个知识点

nodeport默认的端口范围是30000-32767,所以默认只有2767个端口,但是我们可以修改nodeport的端口范围

vi /etc/kubernetes/manifests/kube-apiserver.yaml

 - --service-cluster-ip-range=10.96.0.0/12    #在此项配置下面加上以下配置

- --service-node-port-range=30000-34000  #也可以根据自己的需求调大端口范围

 删除apiserver的pod,让它自动重新构建

kubectl get pod -n kube-system

kubectl delete pod kube-apiserver-k8s-master01 -n kube-system

kubectl delete pod kube-apiserver-k8s-master02 -n kube-system

kubectl delete pod kube-apiserver-k8s-master03 -n kube-system

查看一下apiserver pod的详细信息看是否生效

kubectl describe pod kube-apiserver-k8s-master01 -n kube-system

3.3headless

无头服务,通常与setafulset控制器一起使用,用于部署有状态服务,解决容器奔溃重启后ip地址变更的问题,用无头服务后就可以通过固定域名的方式去访问pod,而不是通过ip地址,这样就可以解决ip地址变更的问题

编辑yaml文件

vi headless.yaml

apiVersion: v1
kind: Service
metadata:
  name: nacos
  labels:
    app: nacos
spec:
  publishNotReadyAddresses: true
  clusterIP: None             #使用headless模式,配置cluster ip为none
  ports:
    - port: 8848
      name: server
      targetPort: 8848
    - port: 9848
      name: client-rpc
      targetPort: 9848
      ## 兼容1.4.x版本的选举端口
    - port: 7848
      name: old-raft-rpc
      targetPort: 7848
  selector:
    app: nacos

执行yaml

kubectl create -f deployment-nginx.yam

查看svc

kubectl get service

以nacos为例,部署后都是使用域名进行通信

4.ingress

这里使用nginx作为Ingress Controller来实现ingress定义的规则,也可以使用haproxy等工具来实现,实际上工作流程就是,向ingress写入规则,ingress Controller将规则转化为nginx的规则,写入nginx配置中,以实现反向代理

4.1搭建ingress环境

这里我直接使用helm安装nginx ingress控制器

helm配置可以参考:k8s helm安装使用_Apex Predator的博客-CSDN博客

查找镜像源

helm search repo ingress

安装插件

helm install ingress bitnami/nginx-ingress-controller

helm list

 状态为deployed就表示正常部署

查看一下pod,svc,deployment中的ingress服务

kubectl get pod,svc,deployment

 可以看到都已经正常启动了,但是svc中的ingress-nginx-ingress-controller默认用的是LoadBalancer模式,需要修改为NodePort模式,上图中我已经修改过后的状态

修改一下svc的配置

kubectl edit svc service/ingress-nginx-ingress-controller

type: NodePort      #将type项的LoadBalancer改为NodePort即可保存退出

再次查看svc

 至此ingress环境已经部署好了

4.2使用ingress

编辑yaml文件

vi deployment-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata: 
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  replicas: 5
  progressDeadlineSeconds: 600
  minReadySeconds: 10
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec: 
      containers:
      - name: nginx
        image: nginx:1.21
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
spec:
  selector:
    app: nginx
  type: ClusterIP 
  clusterIP:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress
  namespace: default
spec:
  rules:   #配置代理规则
  - host: nginx.apex.com     #配置反向代理的域名
    http:
      paths:
        - path: /          #匹配路径,相当于nginx location,以下的pathType用于配置匹配规则
          pathType: ImplementationSpecific    #pathType 字段用于指定 Ingress 路由规则中的路径类型,pathType 字段有三个可选值,Exact表示 Ingress 规则中的路径必须与请求的路径完全匹配,Prefix表示 Ingress 规则中的路径必须是请求路径的前缀,ImplementationSpecific表示 Ingress 控制器可以自行决定路径类型
          backend:      #配置需要代理服务的参数
            service: 
              name: nginx    #配置需要代理的sevice服务的名称
              port:
                number: 80   #配置需要代理的service监听端口
  ingressClassName: nginx   #指定实现规则的应用类型,controller会将以上的规则转变为适合该应用的配置写入应用的配置文件中

我这边把deployment、service、ingress的yaml配置都写在了一个yaml文件上,现在来执行yaml看看效果

kubectl create -f deployment-nginx.yaml

kubectl get pod -l app=nginx

kubectl get ingress

 可以看到pod、svc、ingress都已经正常运行,可以看到ingress监听的端口为80,因为代理的是http服务

编辑一下本机的hosts文件,使得域名能正常解析到服务主机上

vi /etc/hosts

10.1.60.119 nginx.apex.com   #在末尾新增此条内容

 查看ingress service服务端口,测试访问一下域名看是否能正常访问到pod中的服务

kubectl get svc

可以看到http服务使用31079端口,https服务使用31920端口 

curl nginx.apex.com:31079

 域名可以正常访问pod服务

接下来配置一下https服务

创建证书

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=BJ/L=BJ/O=nginx/CN=apex.com"

创建密钥

kubectl create secret tls tls-secret --key tls.key --cert tls.crt

编辑yaml文件

vi deployment-tomcat.yaml 

apiVersion: apps/v1
kind: Deployment
metadata: 
  labels:
    app: tomcat
  name: tomcat
  namespace: default
spec:
  replicas: 2
  progressDeadlineSeconds: 600
  minReadySeconds: 10
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec: 
      containers:
      - name: tomcat
        image: tomcat
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: tomcat
  namespace: default
spec:
  selector:
    app: tomcat
  type: ClusterIP 
  clusterIP:
  ports:
    - port: 8080
      targetPort: 8080
      protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-tomcat
  namespace: default
spec:
  tls:     #https服务配置项
    - hosts:
      - tomcat.apex.com     #配置需要使用https服务的域名
      secretName: tls-secret   #配置创建的证书名称
  rules:
  - host: tomcat.apex.com
    http:
      paths:
        - path: /
          pathType: ImplementationSpecific
          backend:
            service: 
              name: tomcat
              port:
                number: 8080
  ingressClassName: nginx

执行一下yaml

kubectl create -f deployment-tomcat.yaml

kubectl get pod -l app=tomcat

kubectl get ingress

 可以看到pod正常启动,ingress也正常创建好了,端口也显示监听80和443端口,即代理了http和https服务

也可以查看一下ingress的详细信息

 kubectl describe ingress ingress-tomcat

看一下svc服务

 可以看到创建的tomcat svc服务监听端口为配置的8080端口

现在来访问一下域名看看是否代理成功

curl --insecure https://tomcat.apex.com:31920

 可以看到使用域名能正常访问到pod的服务

至此https配置完成

额外补充一下ingress基于性能的轮询

基于性能的轮询(Performance-Based Round Robin)是一种负载均衡算法,它根据后端服务的性能指标来动态分配请求的转发量。在这种配置下,负载均衡器会根据后端服务的性能情况,调整请求的分发比例,使性能较好的服务接收更多的请求

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: example-service
                port:
                  number: 80
  annotations:
    nginx.ingress.kubernetes.io/upstream-vhost: example.com
    nginx.ingress.kubernetes.io/upstream-hash-by: $request_uri
    nginx.ingress.kubernetes.io/upstream-hash-by-substring: $server_name

nginx.ingress.kubernetes.io/upstream-vhost:设置上游后端服务的虚拟主机名称。这里设置为 example.com

nginx.ingress.kubernetes.io/upstream-hash-by:设置用于计算请求哈希的变量。这里我们使用 $request_uri,根据请求URI进行哈希计算

nginx.ingress.kubernetes.io/upstream-hash-by-substring:设置用于计算请求哈希的子字符串变量。这里我们使用 $server_name,根据请求的服务名称进行哈希计算

通过以上配置,NGINX Ingress Controller会根据请求URI和服务名称计算请求的哈希值,并将请求转发到后端服务。这样,请求将按照哈希值进行分发,实现基于性能的轮询。性能较好的后端服务将接收到更多的请求

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值