$ ls ~yifei/notes/

Kubernetes 初探——服务

Posted on:

Last modified:

Service 是 Kubernetes 中的一种资源。如果一个 Deployment 对外(Pod 外)提供服务的话,可以 定义 Service 以暴露给外部。常用的服务有三种类型:

  • ClusterIP. 服务暴露在集群内部的一个虚拟 IP,IP 生命周期和服务相同。
  • NodePort. 暴露在所有 Node 上的端口,不建议在生产环境使用,适合临时性服务。
  • LoadBalancer. 通过外部平台提供的 LB 暴露对应的服务。

其中,ClusterIP 是默认方式,也是最基础的方式。NodePort 和 LoadBalancer 也会在集群内部隐式 创建对应的 ClusterIP。

集群创建的 IP 没有和任何 Pod 绑定,而是绑定到 Service。然后负载均衡到一个或多个 Pods 上。 Pod 的创建和销毁并不会影响到虚拟 IP 的声明周期。

使用云厂商提供的 LoadBalancer 来提供服务比较方便,也可以用于生产环境,唯一的缺点是比较贵。 除此之外,还可以使用 MetalLB 等插件来打造自己的 LB。

除了 NodePort 和 LoadBalancer,另一种更加灵活的方式是使用 Ingress + ClusterIP 对外暴露服务。

apiVersion: v1
kind: Service
metadata:
  name: my-service
  labels:
    app: my-service
spec:
  type: "NodePort"  # NodePort/ClusterIP/LoadBalancer,默认是 ClusterIP
  selector:
    app: backend  # 选择一个后端的 deploy 或者 sts
  ports:
  - name: http
    port: 8080  # 对外暴露的端口
    protocol: TCP
    targetPort: 8080  # 目标端口

在集群中访问服务

在集群中的任何一个 Pod,可以直接使用如下的方式访问对应的服务。一般情况下,可以省去后缀, 在同一个 namespace 中,还可以省去 namespace.

service_name + "." + service_namespace + ".svc.cluster.local"

Ingress

Ingress 本身是一个 Service,然后路由到不同的服务。实际上 Ingress 就是反向代理。一般情况下 Ingress 只能用来暴露 80 或者 443 端口的服务。如果需要暴露其他端口的服务,最好使用 Load Balancer 或者是 NodePort 型服务。

Ingress 也是一个普通服务,本身也需要使用 NodePort 或者 LoadBalancer 暴露到外网中。

在 K3S 中自带了一个 service lb,所以只要确保 ingress controller 第一个暴露出 LoadBalancer 类型的 80 端口,就能自动通过 80 端口访问了。

Nginx 是官方支持的 ingress,比较稳定,而且性能也比较好。尽量不要使用 Traefik,bug 太多了。

安装一个服务的完整例子:

# 创建一个简单的 deployment,这里我们用了 rancher logos 这个服务
apiVersion: apps/v1
kind: Deployment
metadata:
  name: rancher-logo-app
  namespace: default
spec:
  selector:
    matchLabels:
      name: rancher-logo-backend
  template:
    metadata:
      labels:
        name: rancher-logo-backend
    spec:
      containers:
        - name: backend
          image: rancher/logos:rancher
          ports:
            - containerPort: 80
---
# 创建一个 service,暴露了 80 端口,注意这里不需要暴露 443 端口
apiVersion: v1
kind: Service
metadata:
  name: rancher-logo-service
  namespace: default
spec:
  selector:
    name: rancher-logo-backend
  ports:
    # 这里的 port 可以做一个转换
    - name: http
      port: 80
      protocol: TCP
      targetPort: 80
---
# 创建一个 ingress,并在 annotation 中指定了使用 cluster-issuer
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: rancher-logo-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx  # 使用 nginx 做 ingress
    cert-manager.io/cluster-issuer: letsencrypt-prod  # 使用 cluster-issuer
spec:
  tls:
  - secretName: logos-ezly-tv-tls  # 指定证书对应的 secret
    hosts:
    - logos.ezly.tv
  rules:
  - host: logos.ezly.tv  # ingress 的配置
    http:
      paths:
        - path: /
          backend:
            service: rancher-logo-service  # 指向的 service
            port:
              number: 80

需要注意的是,https 证书的发放需要时间,可能得等 1 分钟左右才能从 https 协议访问。

如果不实用 CertManager 自动生成证书,可以上传自己的证书到 k8s cluster 中:

k create secret tls NAME --key KEY_FILE --cert CERT_FILE

同样在 spec.tls.secretName 中指定就好了。

服务治理

服务治理有两种方式:

  • 一种是直接在服务中集成熔断降级等操作
  • 一种是使用 sidecar 模式,有公共组件来处理

两种模式的区别如图:

最简单的 load balancer

https://github.com/k3s-io/klipper-lb/blob/master/entry

#!/bin/sh
set -e -x

trap exit TERM INT

for dest_ip in ${DEST_IPS}
do
    if echo ${dest_ip} | grep -Eq ":" 
    then
        if [ `cat /proc/sys/net/ipv6/conf/all/forwarding` != 1 ]; then
            exit 1
        fi
        ip6tables -t nat -I PREROUTING ! -s ${dest_ip}/128 -p ${DEST_PROTO} --dport ${SRC_PORT} -j DNAT --to [${dest_ip}]:${DEST_PORT}
        ip6tables -t nat -I POSTROUTING -d ${dest_ip}/128 -p ${DEST_PROTO} -j MASQUERADE
    else
        if [ `cat /proc/sys/net/ipv4/ip_forward` != 1 ]; then
            exit 1
        fi
        iptables -t nat -I PREROUTING ! -s ${dest_ip}/32 -p ${DEST_PROTO} --dport ${SRC_PORT} -j DNAT --to ${dest_ip}:${DEST_PORT}
        iptables -t nat -I POSTROUTING -d ${dest_ip}/32 -p ${DEST_PROTO} -j MASQUERADE
    fi
done

if [ ! -e /pause ]; then
    mkfifo /pause
fi
</pause

参考

  1. https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0
  2. https://stackoverflow.com/questions/45079988/ingress-vs-load-balancer
  3. https://sysadmins.co.za/https-using-letsencrypt-and-traefik-with-k3s/
  4. https://medium.com/@jmrobles/free-ssl-certificate-for-your-kubernetes-cluster-with-rancher-2cf6559adeba
  5. Service Mesh 的本质、价值和应用探索
  6. Istio, K8S 的微服务支持
  7. https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
  8. https://matthewpalmer.net/kubernetes-app-developer/articles/kubernetes-ingress-guide-nginx-example.html
  9. 微服务之熔断、降级、限流
  10. 微服务拆分与服务发现
  11. https://kubernetes.io/docs/concepts/services-networking/ingress/
  12. https://medium.com/flant-com/comparing-ingress-controllers-for-kubernetes-9b397483b46b
  13. https://www.servicemesher.com/blog/kubernetes-ingress-controller-deployment-and-ha/
  14. https://thenewstack.io/kubernetes-ingress-for-beginners/
  15. https://mp.weixin.qq.com/s?__biz=MzUzNzYxNjAzMg==&mid=2247487777&idx=1&sn=24334d7c48a92adb89a26724da2d51fe
WeChat Qr Code

© 2016-2022 Yifei Kong. Powered by ynotes

All contents are under the CC-BY-NC-SA license, if not otherwise specified.

Opinions expressed here are solely my own and do not express the views or opinions of my employer.

友情链接: MySQL 教程站