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所有的資源,默認列出所有資源。
1 [root@k8s-master ~]# kubectl get all 2 NAME DESIRED CURRENT READY AGE 3 rc/myweb 2 2 2 1d 4 5 NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE 6 svc/kubernetes 10.254.0.1 <none> 443/TCP 9d 7 8 NAME READY STATUS RESTARTS AGE 9 po/myweb-8pnn0 1/1 Running 0 1d 10 po/myweb-xkp12 1/1 Running 0 1d 11 [root@k8s-master ~]#
可以在命令后面根據-o wide參數,查看pod的ip地址。可以的話,多看看k8s權威指南這本書吧,里面介紹的更加詳細的。
1 [root@k8s-master ~]# kubectl get all -o wide 2 NAME DESIRED CURRENT READY AGE CONTAINER(S) IMAGE(S) SELECTOR 3 rc/myweb 2 2 2 1d myweb 192.168.110.133:5000/nginx:1.13 app=myweb 4 5 NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR 6 svc/kubernetes 10.254.0.1 <none> 443/TCP 9d <none> 7 8 NAME READY STATUS RESTARTS AGE IP NODE 9 po/myweb-8pnn0 1/1 Running 0 1d 172.16.5.2 k8s-node2 10 po/myweb-xkp12 1/1 Running 0 1d 172.16.38.2 k8s-node3 11 [root@k8s-master ~]#
4、在k8s中創建一個Service。
1 # 聲明api的版本。 2 apiVersion: v1 3 # kind代表資源的類型,資源是Service。 4 kind: Service 5 # 資源叫什么名字,是在其屬性metadata里面的。 6 metadata: 7 # 第一個屬性name的值是myweb,即Service的名字就叫做myweb。 8 name: myweb 9 # spec是詳細,詳細里面定義了一個容器。 10 spec: 11 # 類型使用的是端口映射的形式,使用端口映射進行訪問。 12 type: NodePort 13 ports: 14 # port端口是VIP端口即ClusterIP地址端口。 15 - port: 80 16 # 即宿主機的ip地址端口。映射宿主機的30000端口 17 nodePort: 30000 18 # 負載均衡目標端口80,即Pod的ip地址的端口。 19 targetPort: 80 20 # 選擇器。當有多個Pod的時候,需要使用選擇器選擇為那些Pod做負載均衡。和RC使用的一樣,是使用的標簽選擇器。 21 selector: 22 app: myweb
創建一個svc的目錄,Service資源簡稱是svc,然后創建一個nginx_svc.yaml配置文件。
1 [root@k8s-master ~]# cd k8s/ 2 [root@k8s-master k8s]# ls 3 pod rc 4 [root@k8s-master k8s]# mkdir svc 5 [root@k8s-master k8s]# cd svc/ 6 [root@k8s-master svc]# ls 7 [root@k8s-master svc]# vim nginx_svc.yaml 8 [root@k8s-master svc]# kubectl create -f nginx_svc.yaml 9 service "myweb" created 10 [root@k8s-master svc]# kubectl describe svc myweb 11 Name: myweb 12 Namespace: default 13 Labels: <none> 14 Selector: app=myweb 15 Type: NodePort 16 IP: 10.254.210.104 17 Port: <unset> 80/TCP 18 NodePort: <unset> 30000/TCP 19 Endpoints: 172.16.38.2:80,172.16.5.2:80 20 Session Affinity: None 21 No events. 22 [root@k8s-master svc]#
可以看到svc的根據選擇器myweb選擇的Pod已經有兩個Pod了,而且使用的的都是他們的80端口,使用宿主機Node的80端口號。
此時,可以使用瀏覽器進行查看,此時,只要是Node的ip地址加上端口映射就可以進行訪問。端口映射是k8s的kube-proxy服務進行端口映射的。
5、K8s中Service的服務自動發現。
可以通過命令修改RC(Replication Controller)副本控制器的副本數量,這樣可以自動新增Pod的數量。
1 [root@k8s-master svc]# kubectl get pod -o wide 2 NAME READY STATUS RESTARTS AGE IP NODE 3 myweb-8pnn0 1/1 Running 0 1d 172.16.5.2 k8s-node2 4 myweb-xkp12 1/1 Running 0 1d 172.16.38.2 k8s-node3 5 [root@k8s-master svc]# kubectl scale rc myweb --replicas=3 6 replicationcontroller "myweb" scaled 7 [root@k8s-master svc]# kubectl get pod -o wide 8 NAME READY STATUS RESTARTS AGE IP NODE 9 myweb-0x8tm 1/1 Running 0 2s 172.16.85.2 k8s-master 10 myweb-8pnn0 1/1 Running 0 1d 172.16.5.2 k8s-node2 11 myweb-xkp12 1/1 Running 0 1d 172.16.38.2 k8s-node3 12 [root@k8s-master svc]#
此時,查看Service的詳情,可以發現新增的Pod可以自動添加到負載均衡。
1 [root@k8s-master svc]# kubectl describe svc myweb 2 Name: myweb 3 Namespace: default 4 Labels: <none> 5 Selector: app=myweb 6 Type: NodePort 7 IP: 10.254.210.104 8 Port: <unset> 80/TCP 9 NodePort: <unset> 30000/TCP 10 Endpoints: 172.16.38.2:80,172.16.5.2:80,172.16.85.2:80 11 Session Affinity: None 12 No events. 13 [root@k8s-master svc]#
6、K8s中Service的負載均衡,在其內部就實現了一個簡單的負載均衡。
首先,生成一個首頁,然后將首頁拷貝到Pod中。
1 [root@k8s-master svc]# kubectl get pod -o wide 2 NAME READY STATUS RESTARTS AGE IP NODE 3 myweb-0x8tm 1/1 Running 0 7m 172.16.85.2 k8s-master 4 myweb-8pnn0 1/1 Running 0 1d 172.16.5.2 k8s-node2 5 myweb-xkp12 1/1 Running 0 1d 172.16.38.2 k8s-node3 6 [root@k8s-master svc]# echo 'node1' > index.html 7 [root@k8s-master svc]# cat index.html 8 node1 9 [root@k8s-master svc]# kubectl cp index.html myweb-0x8tm:/usr/share/nginx/html/index.html 10 [root@k8s-master svc]# echo 'node2' > index.html 11 [root@k8s-master svc]# kubectl cp index.html myweb-8pnn0:/usr/share/nginx/html/index.html 12 [root@k8s-master svc]# echo 'node3' > index.html 13 [root@k8s-master svc]# kubectl cp index.html myweb-xkp12:/usr/share/nginx/html/index.html 14 [root@k8s-master svc]#
查看運行效果,如下所示:
這個負載均衡會保持一段長連接,連續訪問可以進行負載均衡訪問,也可以使用curl進行訪問。
1 [root@k8s-master svc]# curl 192.168.110.133:30000 2 node1 3 [root@k8s-master svc]# curl 192.168.110.134:30000 4 node2 5 [root@k8s-master svc]# curl 192.168.110.135:30000 6 node1 7 [root@k8s-master svc]# curl 192.168.110.133:30000
為什么負載均衡的端口(即Node的端口號)默認的端口訪問是30000-32767。此默認值是可以進行修改的。修改nodeport默認范圍--service-node-port-range=30000-50000。
1 [root@k8s-master svc]# vim /etc/kubernetes/apiserver
也可以看看api-server的啟動文件的配置。
1 [root@k8s-master svc]# cat /usr/lib/systemd/system/kube-apiserver.service 2 [Unit] 3 Description=Kubernetes API Server 4 Documentation=https://github.com/GoogleCloudPlatform/kubernetes 5 After=network.target 6 After=etcd.service 7 8 [Service] 9 EnvironmentFile=-/etc/kubernetes/config 10 EnvironmentFile=-/etc/kubernetes/apiserver 11 User=kube 12 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 23 Restart=on-failure 24 Type=notify 25 LimitNOFILE=65536 26 27 [Install] 28 WantedBy=multi-user.target 29 [root@k8s-master svc]#
可以看到api-server啟動的時候,后面跟了很多參數。
修改完api-server的參數,需要重啟api-server的服務。
1 [root@k8s-master svc]# systemctl restart kube-apiserver.service 2 [root@k8s-master svc]#
此時,你可以修改修改nginx_svc.yaml配置文件里面的nodePort參數,我這里就不進行測試了。
也可以看到VIP地址段的范圍是10.254.0.0/16,也是在api-server的配置文件修改的,如下所示:
總結,一個服務要想在k8s中運行起來,至少需要一個rc來保證高可用,其次還需要一個service可以被外界所訪問。