Kubernetes(k8s)的Service资源
1、Service资源,为什么K8s要引入Service资源。
答:运行在docker中的业务,想要被外界访问,我们需要为它做端口映射才能被访问,那么运行在k8s中的容器,为什么不能直接为它做端口映射呢?
RC(Replication Controller)虽然保证了Pod的高可用,但是我们仅仅只能在k8s的内部访问它,但是在客户端是无法进行访问的,因为Pod的ip地址是私有ip地址,外界是无法进行访问的,而Docker中的容器是通过端口映射可以让容器中的业务被外界所访问,在k8s中,不能直接通过端口映射而被外界所访问。
2、K8s中为什么引入了Servvice。
答:Pod容器使用了RC(Replication Controller)来实现了高可用,此时就会出现一些问题,比如一些Pod死掉了,RC(Replication Controller)就会创建一些新的Pod,新的Pod的ip地址就变化了,此时做端口映射就发现一个很严重的问题,Ip地址发生了变化,修改规则很麻烦。在K8s中Node端口映射不可以直接映射到我们的Pod的Ip地址上面,此时K8s引入了Service(可以理解为是VIP的地址ClusterIp),VIP地址段的范围是10.254.0.0/16。
3、K8s中三种Ip地址类型。
答:Node ip地址、cluster ip地址、pod ip地址。
查看K8s所有的资源,默认列出所有资源。
[ ~]# kubectl get all NAME DESIRED CURRENT READY AGE rc/myweb 2 2 2 1d NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE svc/kubernetes 10.254.0.1 <none> 443/TCP 9d NAME READY STATUS RESTARTS AGE po/myweb-8pnn0 1/1 Running 0 1d po/myweb-xkp12 1/1 Running 0 1d [ ~]#
可以在命令后面根据-o wide参数,查看pod的ip地址。可以的话,多看看k8s权威指南这本书吧,里面介绍的更加详细的。
[ ~]# kubectl get all -o wide NAME DESIRED CURRENT READY AGE CONTAINER(S) IMAGE(S) SELECTOR rc/myweb 2 2 2 1d myweb 192.168.110.133:5000/nginx:1.13 app=myweb NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR svc/kubernetes 10.254.0.1 <none> 443/TCP 9d <none> NAME READY STATUS RESTARTS AGE IP NODE po/myweb-8pnn0 1/1 Running 0 1d 172.16.5.2 k8s-node2 po/myweb-xkp12 1/1 Running 0 1d 172.16.38.2 k8s-node3 [ ~]#
4、在k8s中创建一个Service。
# 声明api的版本。 apiVersion: v1 # kind代表资源的类型,资源是Service。 kind: Service # 资源叫什么名字,是在其属性metadata里面的。 metadata: # 第一个属性name的值是myweb,即Service的名字就叫做myweb。 name: myweb # spec是详细,详细里面定义了一个容器。 spec: # 类型使用的是端口映射的形式,使用端口映射进行访问。 type: NodePort ports: # port端口是VIP端口即ClusterIP地址端口。 - port: 80 # 即宿主机的ip地址端口。映射宿主机的30000端口 nodePort: 30000 # 负载均衡目标端口80,即Pod的ip地址的端口。 targetPort: 80 # 选择器。当有多个Pod的时候,需要使用选择器选择为那些Pod做负载均衡。和RC使用的一样,是使用的标签选择器。 selector: app: myweb
创建一个svc的目录,Service资源简称是svc,然后创建一个nginx_svc.yaml配置文件。
[ ~]# cd k8s/ [master k8s]# ls pod rc [master k8s]# mkdir svc [ k8s]# cd svc/ [master svc]# ls [master svc]# vim nginx_svc.yaml [ svc]# kubectl create -f nginx_svc.yaml service "myweb" created [master svc]# kubectl describe svc myweb Name: myweb Namespace: default Labels: <none> Selector: app=myweb Type: NodePort IP: 10.254.210.104 Port: <unset> 80/TCP NodePort: <unset> 30000/TCP Endpoints: 172.16.38.2:80,172.16.5.2:80 Session Affinity: None No events. [ svc]#
可以看到svc的根据选择器myweb选择的Pod已经有两个Pod了,而且使用的的都是他们的80端口,使用宿主机Node的80端口号。
此时,可以使用浏览器进行查看,此时,只要是Node的ip地址加上端口映射就可以进行访问。端口映射是k8s的kube-proxy服务进行端口映射的。
5、K8s中Service的服务自动发现。
可以通过命令修改RC(Replication Controller)副本控制器的副本数量,这样可以自动新增Pod的数量。
[ svc]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE myweb-8pnn0 1/1 Running 0 1d 172.16.5.2 k8s-node2 myweb-xkp12 1/1 Running 0 1d 172.16.38.2 k8s-node3 [ svc]# kubectl scale rc myweb --replicas=3 replicationcontroller "myweb" scaled [ svc]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE myweb-0x8tm 1/1 Running 0 2s 172.16.85.2 k8s-master myweb-8pnn0 1/1 Running 0 1d 172.16.5.2 k8s-node2 myweb-xkp12 1/1 Running 0 1d 172.16.38.2 k8s-node3 [ svc]#
此时,查看Service的详情,可以发现新增的Pod可以自动添加到负载均衡。
[master svc]# kubectl describe svc myweb Name: myweb Namespace: default Labels: <none> Selector: app=myweb Type: NodePort IP: 10.254.210.104 Port: <unset> 80/TCP NodePort: <unset> 30000/TCP Endpoints: 172.16.38.2:80,172.16.5.2:80,172.16.85.2:80 Session Affinity: None No events. [ svc]#
6、K8s中Service的负载均衡,在其内部就实现了一个简单的负载均衡。
首先,生成一个首页,然后将首页拷贝到Pod中。
[ svc]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE myweb-0x8tm 1/1 Running 0 7m 172.16.85.2 k8s-master myweb-8pnn0 1/1 Running 0 1d 172.16.5.2 k8s-node2 myweb-xkp12 1/1 Running 0 1d 172.16.38.2 k8s-node3 [ svc]# echo ‘node1‘ > index.html [master svc]# cat index.html node1 [ svc]# kubectl cp index.html myweb-0x8tm:/usr/share/nginx/html/index.html [ svc]# echo ‘node2‘ > index.html [ svc]# kubectl cp index.html myweb-8pnn0:/usr/share/nginx/html/index.html [ svc]# echo ‘node3‘ > index.html [ svc]# kubectl cp index.html myweb-xkp12:/usr/share/nginx/html/index.html [ svc]#
查看运行效果,如下所示:
这个负载均衡会保持一段长连接,连续访问可以进行负载均衡访问,也可以使用curl进行访问。
[ svc]# curl 192.168.110.133:30000 node1 [ svc]# curl 192.168.110.134:30000 node2 [ svc]# curl 192.168.110.135:30000 node1 [ svc]# curl 192.168.110.133:30000
为什么负载均衡的端口(即Node的端口号)默认的端口访问是30000-32767。此默认值是可以进行修改的。修改nodeport默认范围--service-node-port-range=30000-50000。
1 [ svc]# vim /etc/kubernetes/apiserver
也可以看看api-server的启动文件的配置。
[ svc]# cat /usr/lib/systemd/system/kube-apiserver.service [Unit] Description=Kubernetes API Server Documentation=https://github.com/GoogleCloudPlatform/kubernetes After=network.target After=etcd.service [Service] EnvironmentFile=-/etc/kubernetes/config EnvironmentFile=-/etc/kubernetes/apiserver User=kube ExecStart=/usr/bin/kube-apiserver 13 $KUBE_LOGTOSTDERR 14 $KUBE_LOG_LEVEL 15 $KUBE_ETCD_SERVERS 16 $KUBE_API_ADDRESS 17 $KUBE_API_PORT 18 $KUBELET_PORT 19 $KUBE_ALLOW_PRIV 20 $KUBE_SERVICE_ADDRESSES 21 $KUBE_ADMISSION_CONTROL 22 $KUBE_API_ARGS Restart=on-failure Type=notify LimitNOFILE=65536 [Install] WantedBy=multi-user.target [ svc]#
可以看到api-server启动的时候,后面跟了很多参数。
修改完api-server的参数,需要重启api-server的服务。
1 [ svc]# systemctl restart kube-apiserver.service 2 [ svc]#
此时,你可以修改修改nginx_svc.yaml配置文件里面的nodePort参数,我这里就不进行测试了。
也可以看到VIP地址段的范围是10.254.0.0/16,也是在api-server的配置文件修改的,如下所示:
总结,一个服务要想在k8s中运行起来,至少需要一个rc来保证高可用,其次还需要一个service可以被外界所访问。