目录

Kubernetes的安装和使用(一)
Kubernetes的安装和使用(二)
Kubernetes的安装和使用(三)

k8s使用Service

在前面的例子中我们使用port-forward进行端口转发,这样会存在两个问题:

  1. pod重启后ip地址发生了变化怎么办
  2. 如何进行负载均衡

k8s的Service就是用来解决这个问题的,它包含ClusterIP、NodePort和Headless等模块。

ClusterIP

ClusterIP就是将多个pod用一个ip进行访问的服务,这个ip只能在集群内访问,我们创建如下的程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import (
"fmt"
"io"
"net/http"
"os"
)

func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
host, _ := os.Hostname()
io.WriteString(w, fmt.Sprintf("[v3] Hello, Kubernetes!, From host: %s\n", host))
})
http.ListenAndServe(":3000", nil)
}

我们将如上程序打包成镜像

docker build . -t derobukal/hellok8s:v3_hostname
docker push derobukal/hellok8s:v3_hostname

然后启动k8s的deployment,可以得到3个运行的pod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: apps/v1
kind: Deployment
metadata:
# deployment 唯一名称
name: hellok8s-go-http
spec:
replicas: 3 # 副本数量
selector:
matchLabels:
app: hellok8s # 管理template下所有 app=hellok8s的pod,(要求和template.metadata.labels完全一致!!!否则无法部署deployment)
template: # template 定义一组容器
metadata:
labels:
app: hellok8s
spec:
containers:
- image: derobukal/hellok8s:v3_hostname
name: hellok8s

之后我们创建service-clusterip.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: Service
metadata:
name: service-hellok8s-clusterip
spec:
type: ClusterIP # 这行是默认的,可省略
# sessionAffinity: ClientIP # or None, 设置会话亲和性(ClientIP表示同一客户端ip的请求会路由到同个Pod)
# sessionAffinityConfig:
# clientIP:
# timeoutSeconds: 3600 # 范围 0~86400,默认10800(3h)
selector:
app: hellok8s # 通过selector关联pod组
ports:
- port: 3000 # service端口
targetPort: 3000 # 后端pod端口

随后启动service,并查看service所生成的clusterIp的值,以及clusterIp后面的endpoints的详细信息

~ kc apply -f service-clusterip.yaml 
service/service-hellok8s-clusterip created
~ kc get svc                        
NAME                         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes                   ClusterIP   10.96.0.1        <none>        443/TCP    7d1h
service-hellok8s-clusterip   ClusterIP   10.111.240.227   <none>        3000/TCP   10s
~ kc get endpoints
NAME                         ENDPOINTS                                            AGE
kubernetes                   192.168.49.2:8443                                    7d1h
service-hellok8s-clusterip   10.244.0.67:3000,10.244.0.68:3000,10.244.0.69:3000   16s

有了service之后,我们就可以很方便的通过clusterIp的地址访问服务了。因为我们使用的是minikube,为了能正常访问clusterIp,我们先创建一个nginx的pod

1
2
3
4
5
6
7
8
9
10
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx

之后我们进入nginx的pod测试clusterIp

~ kc apply -f pod_nginx.yaml        
pod/nginx created
~ kc get pods
NAME                                READY   STATUS    RESTARTS   AGE
hellok8s-go-http-6f5d68bc64-6xrdx   1/1     Running   0          23m
hellok8s-go-http-6f5d68bc64-b7wq2   1/1     Running   0          23m
hellok8s-go-http-6f5d68bc64-rk59k   1/1     Running   0          23m
nginx                               1/1     Running   0          98s
~ kc exec nginx -it -- bash                            
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-b7wq2
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-rk59k
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-rk59k
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-b7wq2
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-6xrdx
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-b7wq2
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-rk59k
root@nginx:/# 

上面通过curl测试service,可以看到每次访问的后端pod都是不一样的。接下来我们增加pod的数量,可以看到endpoint的数量也发生了变化,同时测试请求也打到了新的pod上面

~ kc scale deployment/hellok8s-go-http --replicas=10
deployment.apps/hellok8s-go-http scaled
~ kc get endpoints                                                             
NAME                         ENDPOINTS                                                        AGE
kubernetes                   192.168.49.2:8443                                                7d1h
service-hellok8s-clusterip   10.244.0.67:3000,10.244.0.68:3000,10.244.0.69:3000 + 7 more...   22m
~ kc get pods     
NAME                                READY   STATUS    RESTARTS   AGE
hellok8s-go-http-6f5d68bc64-5lxvs   1/1     Running   0          27s
hellok8s-go-http-6f5d68bc64-6xrdx   1/1     Running   0          29m
hellok8s-go-http-6f5d68bc64-b7wq2   1/1     Running   0          29m
hellok8s-go-http-6f5d68bc64-cl56f   1/1     Running   0          27s
hellok8s-go-http-6f5d68bc64-gbn9v   1/1     Running   0          27s
hellok8s-go-http-6f5d68bc64-k7db4   1/1     Running   0          27s
hellok8s-go-http-6f5d68bc64-m4h5s   1/1     Running   0          27s
hellok8s-go-http-6f5d68bc64-rk59k   1/1     Running   0          29m
hellok8s-go-http-6f5d68bc64-whpht   1/1     Running   0          27s
hellok8s-go-http-6f5d68bc64-xnvk2   1/1     Running   0          27s
nginx                               1/1     Running   0          8m13s
~ kc exec nginx -it -- bash
root@nginx:/# curl 10.111.240.227:3000                                 
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-6xrdx
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-b7wq2
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-m4h5s
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-whpht
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-whpht
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-cl56f
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-xnvk2
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-cl56f
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-cl56f
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-m4h5s
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-rk59k
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-whpht
root@nginx:/# curl 10.111.240.227:3000
[v3] Hello, Kubernetes!, From host: hellok8s-go-http-6f5d68bc64-k7db4
root@nginx:/# 

NodePort

clusterIp只能在集群内部进行访问,NodePort在clusterIp的基础上,还支持了通过k8s集群的节点进行访问。有如下的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: v1
kind: Service
metadata:
name: service-hellok8s-nodeport
spec:
type: NodePort
selector:
app: hellok8s
ports:
- port: 3000 # pod端口
nodePort: 30000 # 节点固定端口。在NodePort类型中,k8s要求在 30000-32767 范围内,否则apply报错
# 若需要暴露多个端口,则按下面形式
# - name: http
# protocol: TCP
# port: 80
# targetPort: 9376
# - name: https
# protocol: TCP
# port: 443
# targetPort: 9377

之后启动nodeport的服务,就可以在集群的节点上访问服务了

~ kc apply -f service-nodeport.yaml 
service/service-hellok8s-nodeport created
~ kc get svc                       
NAME                         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes                   ClusterIP   10.96.0.1        <none>        443/TCP          7d1h
service-hellok8s-clusterip   ClusterIP   10.111.240.227   <none>        3000/TCP         28m
service-hellok8s-nodeport    NodePort    10.106.138.169   <none>        3000:30000/TCP   17s

因为使用minikube创建服务,而非创建了k8s的集群,因此暂时不太方便测试该功能。