Service介绍

概述

● 在kubernetes中,Pod是应用程序的载体,我们可以通过Pod的IP来访问应用程序,但是Pod的IP地址不是固定的,这就意味着不方便直接采用Pod的IP对服务进行访问。

● 为了解决这个问题,kubernetes提供了Service资源,Service会对提供同一个服务的多个Pod进行聚合,并且提供一个统一的入口地址,通过访问Service的入口地址就能访问到后面的Pod服务。
在这里插入图片描述
Service在很多情况下只是一个概念,真正起作用的其实是kube-proxy服务进程,每个Node节点上都运行了一个kube-proxy的服务
进程。当创建Service的时候会通过API Serveretcd写入创建的Service的信息,而kube-proxy会基于监听的机制发现这种Service的变化,然后它会将最新的Service信息转换为对应的访问规则。
在这里插入图片描述

防止Pod失联【服务发现】

在这里插入图片描述

定义Pod访问策略【负载均衡】

页面前端的Pod访问到后端的Pod,中间会通过Service一层,而Service在这里还能做负载均衡,负载均衡的策略有很多种实现策略,例如:

  • 随机
  • 轮询
  • 响应比

Pod和Service的关系

这里Pod 和 Service 之间还是根据 label 和 selector 建立关联的 【和Controller一样】

在这里插入图片描述

Service常用类型

  • ClusterIp:集群内部访问
  • NodePort:对外访问应用使用
  • LoadBalancer:对外访问应用使用,公有云

Service类型

Service的资源清单:

apiVersion: v1 # 版本
kind: Service # 类型
metadata: # 元数据
  name: # 资源名称
  namespace: # 命名空间
spec:
  selector: # 标签选择器,用于确定当前Service代理那些Pod
    app: nginx
  type: NodePort # Service的类型,指定Service的访问方式
  clusterIP: # 虚拟服务的IP地址
  sessionAffinity: # session亲和性,支持ClientIP、None两个选项,默认值为None
  ports: # 端口信息
    - port: 8080 # Service端口
      protocol: TCP # 协议
      targetPort : # Pod端口
      nodePort:  # 主机端口

spec.type的说明:

  • ClusterIP:默认值,它是kubernetes系统自动分配的虚拟IP,只能在集群内部访问
  • NodePort:将Service通过指定的Node上的端口暴露给外部,通过此方法,就可以在集群外部访问服务。
  • LoadBalancer:使用外接负载均衡器完成到服务的负载分发,注意此模式需要外部云环境的支持。
  • ExternalName:把集群外部的服务引入集群内部,直接使用。

Service使用

● 在使用Service之前,首先利用Deployment创建出3个Pod,注意要为Pod设置app=nginx-pod的标签。

● 创建deployment.yaml文件,内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pc-deployment
  namespace: dev
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
        - name: nginx
          image: nginx:1.17.1
          ports:
            - containerPort: 80

创建Deployment:

kubectl apply -f deployment.yaml

查看Pod信息:

kubectl get pod -n dev -o wide --show-labels

在这里插入图片描述
为了方便后面的测试,修改三台Nginx的index.html

kubectl exec -it  pc-deployment-7d7dd5499b-59qkm -c nginx -n dev /bin/sh 
# 	进入pod,选择nginx这个容器,在dev这个namespace下, /bin/bash 命令
echo "10.244.1.30" > /usr/share/nginx/html/index.html # > 重定向到index.html页面,覆盖其中内容

测试访问:

curl 10.244.0.31:80
curl 10.244.0.32:80
curl 10.244.0.33:80

在这里插入图片描述

ClusterIP类型的Service

创建Service

创建service-clusterip.yaml文件,内容如下:

apiVersion: v1
kind: Service
metadata:
  name: service-clusterip
  namespace: dev
spec:
  selector:
    app: nginx-pod
  clusterIP: 10.244.11.11 # service的IP地址,如果不写,默认会生成一个
  type: ClusterIP
  ports:
    - port: 80 # Service的端口
      targetPort: 80 # Pod的端口

创建Service:

kubectl apply -f service-clusterip.yaml

查看Service

kubectl get svc -n dev -o wide

在这里插入图片描述

查看Service的详细信息

kubectl describe svc service-clusterip  -n dev

在这里插入图片描述

访问

在这里插入图片描述

默认的负载策略为rr(轮询),ClusterIP意思是给Service分配的是只有当前k8s集群内部才能访问的ip,外部无法访问

NodePort类型的Service

创建的Service的IP地址只能在集群内部才可以访问,如果希望Service暴露给集群外部使用,那么就需要使用到另外一种类型的Service,称为NodePort类型的Service。NodePort的工作原理就是将Service的端口映射到Node的一个端口上,然后就可以通过NodeIP:NodePort来访问Service了
在这里插入图片描述

创建Service

创建service-nodeport.yaml文件,内容如下:

apiVersion: v1
kind: Service
metadata:
  name: service-nodeport
  namespace: dev
spec:
  selector:
    app: nginx-pod
  type: NodePort # Service类型为NodePort
  ports:
    - port: 80 # Service的端口
      targetPort: 80 # Pod的端口
      nodePort: 30002 # 指定绑定的node的端口(默认取值范围是30000~32767),如果不指定,会默认分配

创建Service:

kubectl apply -f service-nodeport.yaml

查看Service

kubectl get svc service-nodeport -n dev -o wide # -o wide 查看详细信息

在这里插入图片描述

访问

在这里插入图片描述

LoadBalancer类型的Service

LoadBalancerNodePort很相似,目的都是向外部暴露一个端口,区别在于LoadBalancer会在集群的外部再来做一个负载均衡设备,而这个设备需要外部环境的支持,外部服务发送到这个设备上的请求,会被设备负载之后转发到集群中。
在这里插入图片描述

Ingress

Ingress和Pod关系

pod 和 ingress 是通过service进行关联的,而ingress作为统一入口,由service关联一组pod中
在这里插入图片描述

Ingress工作流程

在实际的访问中,我们都是需要维护很多域名, a.com 和 b.com

然后不同的域名对应的不同的Service,然后service管理不同的pod
在这里插入图片描述

使用Ingress

配置ingress-controller

ingress-controller.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: ingress
  labels:
    app.kubernetes.io/name: ingress
    app.kubernetes.io/part-of: ingress

---

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-configuration
  namespace: ingress
  labels:
    app.kubernetes.io/name: ingress
    app.kubernetes.io/part-of: ingress

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: tcp-services
  namespace: ingress
  labels:
    app.kubernetes.io/name: ingress
    app.kubernetes.io/part-of: ingress

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: udp-services
  namespace: ingress
  labels:
    app.kubernetes.io/name: ingress
    app.kubernetes.io/part-of: ingress

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nginx-ingress-serviceaccount
  namespace: ingress
  labels:
    app.kubernetes.io/name: ingress
    app.kubernetes.io/part-of: ingress

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: nginx-ingress-clusterrole
  labels:
    app.kubernetes.io/name: ingress
    app.kubernetes.io/part-of: ingress
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - endpoints
      - nodes
      - pods
      - secrets
    verbs:
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - services
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - events
    verbs:
      - create
      - patch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses/status
    verbs:
      - update

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: nginx-ingress-role
  namespace: ingress
  labels:
    app.kubernetes.io/name: ingress
    app.kubernetes.io/part-of: ingress
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/v1beta1
kind: RoleBinding
metadata:
  name: nginx-ingress-role-nisa-binding
  namespace: ingress
  labels:
    app.kubernetes.io/name: ingress
    app.kubernetes.io/part-of: ingress
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: nginx-ingress-role
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: nginx-ingress-clusterrole-nisa-binding
  labels:
    app.kubernetes.io/name: ingress
    app.kubernetes.io/part-of: ingress
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: nginx-ingress-clusterrole
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ingress-controller
  namespace: ingress
  labels:
    app.kubernetes.io/name: ingress
    app.kubernetes.io/part-of: ingress
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress
      app.kubernetes.io/part-of: ingress
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress
        app.kubernetes.io/part-of: ingress
      annotations:
        prometheus.io/port: "10254"
        prometheus.io/scrape: "true"
    spec:
      hostNetwork: true
      # wait up to five minutes for the drain of connections
      terminationGracePeriodSeconds: 300
      serviceAccountName: nginx-ingress-serviceaccount
      nodeSelector:
        kubernetes.io/os: linux
      containers:
        - name: nginx-ingress-controller
          image: lizhenliang/nginx-ingress-controller:0.30.0
          args:
            - /nginx-ingress-controller
            - --configmap=$(POD_NAMESPACE)/nginx-configuration
            - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
            - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
            - --publish-service=$(POD_NAMESPACE)/ingress
            - --annotations-prefix=nginx.ingress.kubernetes.io
          securityContext:
            allowPrivilegeEscalation: true
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            # www-data -> 101
            runAsUser: 101
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
            - name: https
              containerPort: 443
              protocol: TCP
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          lifecycle:
            preStop:
              exec:
                command:
                  - /wait-shutdown

---

apiVersion: v1
kind: LimitRange
metadata:
  name: ingress
  namespace: ingress
  labels:
    app.kubernetes.io/name: ingress
    app.kubernetes.io/part-of: ingress
spec:
  limits:
  - min:
      memory: 90Mi
      cpu: 100m
    type: Container

创建ingress-controller

# 需要执行两次 kubectl apply -f ingress-controller.yaml !
kubectl apply -f ingress-controller.yaml 
kubectl apply -f ingress-controller.yaml

查看ingress-controller

kubectl get pods -n ingress

创建tomcat和Nginx

创建控制器,tomcat-nginx.yaml

apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: tomcat-deployment 
spec: # 详细描述
  replicas: 1 
  selector: 
    matchLabels: 
      app: tomcat-pod
  template: # 模块 当副本数据不足的时候,会根据下面的模板创建Pod副本
    metadata:
      labels:
        app: tomcat-pod
    spec:
      containers:
        - name: tomcat 
          image: tomcat:8.0
          ports:
            - containerPort: 8080 

---
apiVersion: v1
kind: Service
metadata:
  name: tomcat
spec:
  selector:
    app: tomcat-pod
  type: NodePort
  ports:
    - port: 8080
      targetPort: 8080 
---
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: nginx-deployment 
spec: # 详细描述
  replicas: 1 
  selector: 
    matchLabels: 
      app: nginx-pod
  template: # 模块 当副本数据不足的时候,会根据下面的模板创建Pod副本
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
        - name: nginx
          image: nginx:1.18.0
          ports:
            - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx-pod
  type: NodePort
  ports:
    - port: 80
      targetPort: 80

运行命令,创建deploy和svc

kubectl apply -f tomcat-nginx.yaml

查看pod,svc,deploy

kubectl get pod
kubectl get deploy
kubectl get svc

在这里插入图片描述

创建ingress规则文件

ingress-rule.yaml

---
# http
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: tomcat-nginx-ingress
spec:
  rules:
  - host: example.nginx.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx
          servicePort: 80
  - host: example.tomcat.com
    http:
      paths:
       - path: /
         backend:
           serviceName: tomcat
           servicePort: 8080

---
# https
# apiVersion: networking.k8s.io/v1beta1
# kind: Ingress
# metadata:
#   name: tls-example-ingress
# spec:
#   tls:
#   - hosts:
#     - sslexample.ctnrs.com
#     secretName: secret-tls
#   rules:
#     - host: sslexample.ctnrs.com
#       http:
#         paths:
#         - path: /
#           backend:
#             serviceName: web
#             servicePort: 80

kubectl apply -f ingress-rule.yaml
kubectl get ingress

在这里插入图片描述

配置hosts文件

C:\Windows\System32\drivers\etc

在这里插入图片描述

加入以下两个配置

192.168.111.101 example.nginx.com
192.168.111.101 example.tomcat.com

访问

流程据我理解是这样:

浏览器输入http://example.tomcat.com/,代理到192.168.111.101这个地址,然后ingress-rule规则判断来源是example.tomcat.com,然后把它转到service名为tomcat的服务,并且端口是8080,然后转到Pod的8080端口,完成请求!
在这里插入图片描述

在这里插入图片描述

完成配置!

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐