一、Service概念

通过创建service可以为一组具有相同功能的容器应用提供一个统一的入口地址,并将请求负载分发到后端的各个容器应用上。

二、Service基本用法

1.定义一个web服务的RC,由两个tomcat容器副本组成

# cat webapp-rc.yaml 
apiVersion: v1
kind: ReplicationController
metadata:
  name: webapp
spec:
  replicas: 2
  template:
    metadata:
      name: webapp
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: tomcat
        ports:
        - containerPort: 8080

2.创建该RC

# kubectl get pod
NAME           READY   STATUS    RESTARTS   AGE
webapp-t5q4g   1/1     Running   0          17m
webapp-wq88m   1/1     Running   0          17m
# kubectl get pods -l app=webapp -o yaml | grep  podIP
    podIP: 10.44.0.2
    podIP: 10.36.0.1

3.使用kubectl expose创建一个SVC

# kubectl expose rc webapp
service/webapp exposed
# kubectl get svc
webapp       ClusterIP   10.111.192.152   <none>        8080/TCP   8s

4.通过svc地址和端口访问

# curl 10.111.192.152:8080

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Apache Tomcat/8.5.42</title>
......

对svc地址10.111.192.152:8080的访问被自动负载分发到了后端的两个Pod之一10.44.0.2:8080或10.36.0.1:8080。
kubernets提供了两种负载分发策略:RoundRobin和SessionAffinity,默认情况下采用的是RoundRobin模式进行负载。

  • RoundRobin:轮询模式
  • SessionAffinity:粘性会话,将来自同一个客户端的请求始终转发至同一个后端的Pod对象,可以通过设置service.spec.sessionAffinity: ClientIP来启用

5.使用配置文件方式创建svc

apiVersion: v1
kind: Service
metadata:
  name: webapp
spec:
  type: ClusterIP
  ports:
  - port: 8081
    targetPort: 8080
  selector:
    app: webapp

ports:与后端容器端口关联
selector:关联到哪些pod资源上

# kubectl delete svc webapp
service "webapp" deleted
# kubectl create -f webapp-svc.yaml 
service/webapp created
# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
webapp       ClusterIP   10.96.231.61     <none>        8081/TCP   14s

6.多端口Service创建

apiVersion: v1
kind: Service
metadata:
  name: webapp
spec:
  ports:
  - port: 8080
    targetPort: 8080
    name: web
  - port: 8005
    targetPort: 8005
    name: management
  selector:
    app: webapp

7.使用UDP端口模式

apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "KubeDNS"
spec:
  selector:
    k8s-app: kube-dns
  clusterIP: 169.169.0.100
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP

8.外部服务Service

在一些环境中,应用系统需要将一个外部数据库作为后端服务进行连接,这时可以通过创建一个没有Selector的svc来实现

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

由于这个 Service 没有 selector,就不会创建相关的 Endpoints 对象。可以手动将 Service 映射到指定的 Endpoints:

kind: Endpoints
apiVersion: v1
metadata:
  name: my-service
subsets:
- addresses:
  - IP: 1.2.3.4
  ports:
  - port: 80

三、Headless Service

有时不需要或不想要负载均衡,以及单独的 Service IP。 遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP)的值为 "None" 来创建Headless Service,仅通过Selector将后端的Pod列表返回给调用的客户端

创建一个Headless Service实例

apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  ports:
  - port: 80
  clusterIP: None
  selector:
    app: nginx
# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
nginx        ClusterIP   None         <none>        80/TCP    26s

四、从集群外部访问Pod或Service

1.将容器应用的端口映射到物理机

# cat pod-hostport.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: webapp
  labels:
    app: webapp
spec:
  containers:
  - name: webapp
    image: tomcat
    ports:
    - containerPort: 8080
      hostPort: 8081

此处映射的IP地址为该Pod所在node的IP

# curl 20.0.20.103:8081

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Apache Tomcat/8.5.42</title>
        <link href="favicon.ico" rel="icon" type="image/x-icon" />
        <link href="favicon.ico" rel="shortcut icon" type="image/x-icon" />

通过设置spce.hostNetwork=true,默认hostPort等于containerPort

apiVersion: v1
kind: Pod
metadata:
  name: webapp
  labels:
    app: webapp
spec:
  hostNetwork: true
  containers:
  - name: webapp
    image: tomcat
    ports:
    - containerPort: 8080

2.将Service的端口映射到物理机

# cat webapp-rc.yaml 
apiVersion: v1
kind: ReplicationController
metadata:
  name: webapp
spec:
  replicas: 2
  template:
    metadata:
      name: webapp
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: tomcat
        ports:
        - containerPort: 8080
# cat webapp-svcnodeport.yaml 
apiVersion: v1
kind: Service
metadata:
  name: webapp
spec:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 8080
    nodePort: 30011
  selector:
    app: webapp
# curl 20.0.20.101:30011

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Apache Tomcat/8.5.42</title>
        <link href="favicon.ico" rel="icon" type="image/x-icon" />
        <link href="favicon.ico" rel="shortcut icon" type="image/x-icon" />