Posted on:
Last modified:
Service 是 Kubernetes 中的一种资源。如果一个 Deployment 对外(Pod 外)提供服务的话,可以 定义 Service 以暴露给外部。常用的服务有三种类型:
其中,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 本身是一个 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 中指定就好了。
服务治理有两种方式:
两种模式的区别如图:
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
© 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 教程站