1 Service
Kubernetes Pods 是有生命周期的。他们会被创建,被销毁,但是他们不会无条件"复活"。比如 ReplicaSets 这种 Pod 控制器会动态生成或者销毁 Pods(如在扩容或者缩容时)。当然每个Pod 都会自动被 k8s 分配IP地址,且这些 IP 也是动态分配的,也就是说如果你重新启动 Pod, 这个 Pod 将会得到一个新的 IP 地址。这导致了如下问题:如果这些 Pod (比如后台程序)对其他 Pods (比如前端程序) 提供某些功能,那么这些前端服务怎么才能锁定后端程序呢?(如果IP一直被动态分配)
K8s Service 其实就是为了解决这些问题而设计的。
Service 是定义一组 Pod 访问权限的抽象服务(服务也被称之为 microservice)。这些Pod 组通常是被一个叫 Label Selector 的组件锁定住的。比如:你有一组处理图片的后台程序,这个程序有3 个replica 副本。这3个副本运行相同的内容,前端无论访问哪个副本都可以达到同样的效果。这是如果你给这组后台程序设置了 Service,那么你的前端程序只需要与 Service通信,而不需要关心后台程序 IP 地址有没有变化等问题。在这里 Service 扮演了一个解耦的角色。
一个 Kubernetes-Native 应用,k8s一般会提供一个简单的 Endpoints
API 它会追踪 Service 配置的变化。对于 non-native 的应用,k8s 提供了 桥接 Service 的 virtual-IP,它会重定向给后台 Pod。
PS: Service 一共有3 种工作方式
- userspace: kubernetes 1.1 之前
- iptables: k8s 1.1 and 1.10 之间
- ipvs: 1.11+ (最新)
Service 类型:
ExternalName, ClusterIP, NodePort 和LoadBalancer
2. 为 Redis 创建 Service
使用如下模板创建:
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: redis
role: logstore
template:
metadata:
labels:
app: redis
role: logstore
spec:
containers:
- name: redis
image: redis:4.0-alpine
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis-svc
namespace: default
spec:
selector:
app: redis
role: logstore
clusterIP: 10.97.97.97
type: ClusterIP
ports:
- port: 6379
targetPort: 6379
说明:
* port -> service ip address port
* targetPort -> Container 的 Port 且带有 Label "app=redis and role=logstore"
* nodePort -> node port 用于对外提供访问
* clusterIP: 会自动生成,通常由 Service 自动分配(在上面的例子中我们自己定义了), 这个IP address 主要由 service proxy 提供
详见: https://kubernetes.io/docs/concepts/services-networking/service
运行如下命令:
[root@k8smaster service]# kubectl apply -f redis-svc.yaml
service/redis created
[root@k8smaster service]# kubectl get pods -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE LABELS
redis-797f4cc7c4-xmvcm 1/1 Running 0 18d 10.244.1.47 k8snode1 app=redis,pod-template-hash=3539077370,role=logstore
[root@k8smaster service]# kubectl get svc -o wide --show-labels
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR LABELS
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24d <none> component=apiserver,provider=kubernetes
redis-svc ClusterIP 10.97.97.97 <none> 6379/TCP 18d app=redis,role=logstore <none>
[root@k8smaster service]# kubectl describe svc redis-svc
Name: redis-svc
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"redis-svc","namespace":"default"},"spec":{"clusterIP":"10.97.97.9...
Selector: app=redis,role=logstore
Type: ClusterIP
IP: 10.97.97.97
Port: <unset> 6379/TCP
TargetPort: 6379/TCP
Endpoints: 10.244.1.47:6379
Session Affinity: None
Events: <none>
从命令行输出可以看到 Endpoint 指向 10.244.1.47:6379, ip 符合了随机生成 ip 的范围。
Endpoint 也是一个 k8s 对象,用户也可以自己手动配置, 它起着在 Pod 和 Service 间桥梁的作用。