Posted on:
Last modified:
Service. 如果一个 Deployment 对外(pod 外)提供服务的话,可以定义 Service 以通过 kube-proxy 和 DNS 等提供负载均衡暴露给外部。服务一共有三种类型:
另外还可以使用 Ingress Controller. Service 只是对集群内部暴露了服务,Ingress Controller 用于把 Service 再对外暴露,就相当于一个反向代理。
这时将创建一个 ClusterIP,需要特别注意的是,这个 ClusterIP 也是虚拟的,并没有和任何 pod 绑定,而是绑定到了服务上,可以理解为绑定到了这个服务对应的内部负载均衡上,并且是不变的。 即使你的 Deployment 中指定了多个副本,那么也只有这一个 clusterIP,pod 的创建和销毁也都不会影响到 clusterIP。
ClusterIP 是集群内部提供服务的默认方式。可以采用 kubelet proxy + ClusterIP 的方式临时提供对外服务。
NodePort 方式在每个 host 上都开一个端口来对外提供服务,适合一些临时性的服务。
使用云厂商提供的 LoadBalancer 来提供服务,唯一的缺点是每一个服务会消耗一个 IP,比较贵。
除此之外,还可以使用 MetalLB 等等第三方的 LB。
Ingress 身是一个 Service,然后路由到不同的服务。实际上 Ingress 就是反向代理。一般情况下 Ingress 只能用来暴露 80 或者 443 端口的服务。如果需要暴露其他端口的服务,最好使用 Load Balancer 或者是 NodePort 型服务。
但是要暴露出去 Ingress 服务本身,可能还是要使用 NodePort 或者 LoadBalancer。
Internet -> Loadbalancer -> Ingress Controller -> Ingress Rules -> K8s-Services -> Replicas
Internet -> NodePort -> Ingress Controller -> Ingress Rules -> K8s-Services -> Replicas
在 K3S 中自带了一个 service lb,所以只要确保 ingress controller 第一个暴露出 loadbalancer 类型的 80 端口,就能自动通过 80 端口访问了。
Traefik 在 2.0 中不止支持了 K8S 默认的 ingress,还自己定义了一种 IngressRoute 类型的 CRD。 千万不要用这个 IngressRoute,他还不支持证书,简直就是废物。尽量不要使用 Traefik,bug 太多了。
Nginx 毕竟是官方支持的 ingress,比较稳定,而且性能也比较好。
Cert-Manager 用于管理 k8s 集群内部的证书。
Cert-Manager 中最重要的三个概念是:
安装 cert-manager
kubectl create namespace cert-manager
kubectl apply -f https://github.com/jetstack/cert-manager/releases/latest/download/cert-manager.yaml
kubectl get pods -n cert-manager # 可以看到几个在运行的 pod
安装一个 clusterissuer
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
email: <your>@<email>.<com> # 替换掉这个
privateKeySecretRef:
name: prod-issuer-account-key
server: https://acme-v02.api.letsencrypt.org/directory
solvers:
- http01:
ingress:
class: traefik
selector: {}
然后,kubectl apply -f letsencrypt.yaml
安装一个服务
# 创建一个简单的 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: traefik # 使用 traefik 做 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 协议访问。
服务治理有两种方式:
两种模式的区别如图:
Kubernetes 使用探针来确定服务当前的状态,以及是否需要重启和分配流量。
Kubernetes 中共有三类探针:
看起来我们似乎只需要一个 Liveliness Probe 或者 Readiness Probe 就够了,毕竟只有当容器存活的时候我们给他分配流量就够了,为什么要分三个呢?
为什么需要 Startup Probe?
假设你的容器启动很慢,比如说启动的时候需要编译字节码之类的,那么你需要定义一个 Startup Probe,否则在启动过程中就可能因为没有响应而被干掉重启了,从而陷入死循环。
为什么需要 Readiness Probe?
假设你的容器已经启动了,可以响应简单的 Liveliness Probe 了,但是程序的主要功能需要加载一个很大的文件,这时候还不能提供席上服务,那么你需要定义一个 Readiness Probe,在数据加载完成后再通过检测,这时候 Kubernetes 才会分配流量。
当一个 Pod 启动的时候,大概的流程是这样的:
大概分为三种:
© 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.