云原生入门之k8s: Service、Ingress

122 阅读5分钟

Service

An abstract way to expose an application running on a set of Pods as a network service. A key aim of Services in Kubernetes is that you don’t need to modify your existing application to use an unfamiliar service discovery mechanism. You can run code in Pods, whether this is a code designed for a cloud-native world, or an older app you’ve containerized. You use a Service to make that set of Pods available on the network so that clients can interact with it. If you use a Deployment to run your app, that Deployment can create and destroy Pods dynamically. From one moment to the next, you don’t know how many of those Pods are working and healthy; you might not even know what those healthy Pods are named. Kubernetes Pods are created and destroyed to match the desired state of your cluster. Pods are emphemeral resources (you should not expect that an individual Pod is reliable and durable). Each Pod gets its own IP address (Kubernetes expects network plugins to ensure this). For a given Deployment in your cluster, the set of Pods running in one moment in time could be different from the set of Pods running that application a moment later. This leads to a problem: if some set of Pods (call them “backends”) provides functionality to other Pods (call them “frontends”) inside your cluster, how do the frontends find out and keep track of which IP address to connect to, so that the frontend can use the backend part of the workload?

Service其实就是将运行在一套pod上的应用公开作为网络服务。对于Deployment部署的应用无法保障节点的状态,即节点是不可靠和不耐用的。此时如果后端服务提供函数,前端如何追踪到该接口并连接到对应的ip?这就是service的作用—服务发现。
kubectl expose deploy my-dep --port=8000 --target-port=80 --type=ClusterIP,–port参数是service对外的目标端口,–target-port是要访问的集群内的容器端口。此时使用kubectl get service,就能获取到名为my-dep的service以及对应的ip,加上设置的对外port就可以集群内负载均衡访问对应的容器。也可以使用.yaml配置文件实现。

apiVersion: v1
kind: Service
metadata:
	labels:
		app: my-dep
	name: my-dep
spec:
	selector:
		app: my-dep
	ports:
	- port: 8000
	  protocal: TCP
	  targetPort: 80

也可以直接通过访问服务名在集群内直接访问容器:curl my-dep.default.svc:8000
service可以感知到pod的状态变化,当pod下线,就无法访问该pod对应的服务,而pod重新上线,又会加入到pod的服务中。
以上演示的暴露只能在集群内暴露,如果想对外暴露,在公网中访问,需要采用NodePort模式kubectl expose deploy my-dep --port=8000 --target-port=80 --type=NodePort。此时运行kubectl get svc,拥有ClusterIP信息,和type=ClusterIP相比,还多了Port数据,此时访问集群内任一机器ip+该port都可以访问服务,实现服务对外暴露。

Ingress

An API object that manages external access to the services in a cluster, typically HTTP. Ingress may provide load balancing, SSL termination and name-based virtual hosting.

Ingress是Service的统一网关入口,对于Service是访问Pod的入口。即流量->Ingress->Service->Pod。

kubernetes.github.io/ingress-ngi… 底层还是nginx

安装
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml

#修改镜像
vi deploy.yaml
#将image的值改为如下值:
registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/ingress-nginx-controller:v0.46.0

# 检查安装的结果
kubectl get pod,svc -n ingress-nginx
# 此时会因NodePort模式暴露访问端口,需要在安全组把svc暴露的端口放行
环境测试
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-server # deployment的名称
spec:
  replicas: 2 # 副本
  selector:
    matchLabels:
      app: hello-server
  template:
    metadata:
      labels:
        app: hello-server
    spec:
      containers:
      - name: hello-server
        image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/hello-server
        ports:
        - containerPort: 9000 # 容器的工作端口
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-demo # deployment的名称
  name: nginx-demo
spec:
  replicas: 2 # 副本
  selector:
    matchLabels:
      app: nginx-demo
  template:
    metadata:
      labels:
        app: nginx-demo
    spec:
      containers:
      - image: nginx
        name: nginx
---
apiVersion: v1
kind: Service 
metadata:
  labels:
    app: nginx-demo
  name: nginx-demo # Service的名称
spec:
  selector:
    app: nginx-demo
  ports:
  - port: 8000 # 访问端口
    protocol: TCP
    targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: hello-server
  name: hello-server # Service的名称
spec:
  selector:
    app: hello-server
  ports:
  - port: 8000 # 访问端口
    protocol: TCP
    targetPort: 9000

应用上述配置文件。配置文件中部署了两个Service,第一个Service是hello-server,负责两个有hello-server镜像的pod;第二个Service是nginx-demo,控制两个有nginx镜像的pod。

域名访问

目前想实现如下功能:访问hello.atguigui.com:31405可以将请求转给hello-server处理,访问demo.atguigu.com:31405将请求转给nginx-demo处理。

  1. 配置域名和service映射访问规则。
apiVersion: networking.k8s.io/v1
kind: Ingress  
metadata:
  name: ingress-host-bar
spec:
  ingressClassName: nginx
  rules:
  - host: "hello.atguigu.com"  
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-server
            port:
              number: 8000
  - host: "demo.atguigu.com"
    http:
      paths:
      - pathType: Prefix
        path: "/nginx"  # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
        backend:
          service:
            name: nginx-demo  ## java,比如使用路径重写,去掉前缀nginx
            port:
              number: 8000
  1. 配置域名和节点ip的映射。(/etc/hosts)。此时就实现了域名访问的功能。
路径重写

以下配置是使用正则表达式实现路径截串。

apiVersion: networking.k8s.io/v1
kind: Ingress  
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  name: ingress-host-bar
spec:
  ingressClassName: nginx
  rules:
  - host: "hello.atguigu.com"
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-server
            port:
              number: 8000
  - host: "demo.atguigu.com"
    http:
      paths:
      - pathType: Prefix
        path: "/nginx(/|$)(.*)"  # 把请求会转给下面的服务,如/nginx解析为/,/nginx/router解析为/router
        backend:
          service:
            name: nginx-demo  ## java,比如使用路径重写,去掉前缀nginx
            port:
              number: 8000

📄复制

流量限制
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-limit-rate
  annotations:
    nginx.ingress.kubernetes.io/limit-rps: "1" # 每s限流1个
spec:
  ingressClassName: nginx
  rules:
  - host: "haha.atguigu.com"
    http:
      paths:
      - pathType: Exact # 精确匹配
        path: "/"
        backend:
          service:
            name: nginx-demo
            port:
              number: 8000

如果超过流量限制,会返回503(service temporarily unavailable)。而这些状态码也可以在配置文件自定义配置。

当请求流量来时,先通过LB负载均衡,根据负载均衡策略将流量打到任一机器的Ingress上,根据配置的域名或路由规则达到对应的Service。

文章首发: zerlina-ysl.github.io/posts/blog/… 开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 25 天,点击查看活动详情