前言

翻看了很多的kubernetes的安装教程,也反复做了一些实验,深感教程之复杂,所以决定写一个极简版本的安装教程,目标在于用尽可能少的参数启动服务,并且剖析各组件关系,然后再在此基础上逐步添加参数,实现功能完备;

干什么

  • 在server节点上启动三个主要服务:apiserver、controller-manager、scheduler;
  • 在node节点上启动两个主要服务:kubelet、kube-proxy;
  • 试验启动容器,且测试容器内服务的功能;

不干什么

  • 不通过软件源安装;
  • 不添加systemd服务;
  • 尽量不做安全配置;不做bootstrap流程,不用kubeadm创建集群;
  • 不做高可用配置;
  • 不用ipvs做负载均衡;
  • 不装任何插件(dns, dashboard, etc);

说明:

  1. 如果通过软件源安装,看似会简化部署流程,但事实上会引入一些别的问题,因为一方面解决版本配套要添加合适的源比较麻烦,另一方面发布包在操作系统上做的一些配置也很复杂,为迎合它也需要做一些复杂的工作;(其实就是源里的东西版本低了不想用这种大实话我是绝对不会说的)
  2. 个人感觉安全配置是提高了kubernetes入门门槛的关键原因,本身安全认证授权就是非常复杂的机制,与业务独立,一般人较少接触,任何一个新入门kubernetes的人在瞎子摸象之前要先搞明白这些东西就要花很多功夫;
    但是,非安全的服务端口正在被deperecate,看一下今年4月社区contributer的表态,自己感受一下吧,https://github.com/kubernetes/kubernetes/pull/59018#issuecomment-381583629
    未来这一部分可能是造成本文失效的最主要原因; 

准备

架构概述

先大概知道一下架构,借用一张图,来源:https://www.kubernetes.org.cn/4047.html

版本及依赖

etcd 3.3.8
docker 18.03.1-ce
flannel 0.10.0
kubernetes 1.10.5

etcd是一个基础组件,没有太复杂的依赖关系,没什么好说的;

docker见之前的docker安装流程

flannel见之前的flannel安装流程

下载程序包

到官方changelog里找downloads:https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.10.md

只下载server和node包就够了,client包只有一个kubectl工具,在前两个里都有带;

Server部署

server有三个组件,apiserver是接口服务,对接etcd,做存储逻辑的封装,后面跟着controller-manager和scheduler,做一些后台控制逻辑;

整个server做的事情全都围绕etcd转,所以根本不需要系统的root权限,普通用户足够;

安装server

解压server包,程序都解压到了kubernetes/server/bin路径:

$ tar vfxz kubernetes-server-linux-amd64.tar.gz # 解压
$ ls kubernetes/server/bin #看一下
$ cd kubernetes/server # 就在这个路径下做server服务的管理

启动apiserver

bin/kube-apiserver \
--cert-dir=etc/kubernetes/cert \
--insecure-bind-address=0.0.0.0 \
--insecure-port= \
--service-cluster-ip-range=10.0.0.0/ \
--etcd-servers=http://<etcd>:2379 \
--logtostderr=true

参数说明:

  1. --cert-dir:虽然我不想做安全配置,但奈何kubernetes的https server是必选项,一定要有TLS证书和密钥才行,如果没有提供自定义的证书密钥,就会自动创建一个;如果不设这个参数,证书和密钥会创建到/var/run/kubernetes下;
  2. --insecure-bind-address,--insecure-port:非安全服务地址和端口,以后会废弃;
  3. --service-cluster-ip-range:service cluster ip是提供给service的虚拟ip,因而这里应当使用一个虚拟段,以免与物理ip段混用造成路由混乱;
  4. --etcd-servers:kubernetes强依赖etcd服务;

生成的文件及数据

apiserver启动后,在cert-dir下出现了自动创建的证书和密钥:

$ file etc/kubernetes/cert/*
etc/kubernetes/cert/apiserver.crt: PEM certificate
etc/kubernetes/cert/apiserver.key: PEM RSA private key

在etcd上出现了一些数据:

# ETCDCTL_API= etcdctl get / --prefix --keys-only
/registry/apiregistration.k8s.io/apiservices/v1. /registry/apiregistration.k8s.io/apiservices/v1.apps /registry/apiregistration.k8s.io/apiservices/v1.authentication.k8s.io /registry/apiregistration.k8s.io/apiservices/v1.authorization.k8s.io /registry/apiregistration.k8s.io/apiservices/v1.autoscaling /registry/apiregistration.k8s.io/apiservices/v1.batch /registry/apiregistration.k8s.io/apiservices/v1.networking.k8s.io /registry/apiregistration.k8s.io/apiservices/v1.rbac.authorization.k8s.io /registry/apiregistration.k8s.io/apiservices/v1.storage.k8s.io /registry/apiregistration.k8s.io/apiservices/v1beta1.admissionregistration.k8s.io /registry/apiregistration.k8s.io/apiservices/v1beta1.apiextensions.k8s.io /registry/apiregistration.k8s.io/apiservices/v1beta1.apps /registry/apiregistration.k8s.io/apiservices/v1beta1.authentication.k8s.io /registry/apiregistration.k8s.io/apiservices/v1beta1.authorization.k8s.io /registry/apiregistration.k8s.io/apiservices/v1beta1.batch /registry/apiregistration.k8s.io/apiservices/v1beta1.certificates.k8s.io /registry/apiregistration.k8s.io/apiservices/v1beta1.events.k8s.io /registry/apiregistration.k8s.io/apiservices/v1beta1.extensions /registry/apiregistration.k8s.io/apiservices/v1beta1.policy /registry/apiregistration.k8s.io/apiservices/v1beta1.rbac.authorization.k8s.io /registry/apiregistration.k8s.io/apiservices/v1beta1.storage.k8s.io /registry/apiregistration.k8s.io/apiservices/v1beta2.apps /registry/apiregistration.k8s.io/apiservices/v2beta1.autoscaling /registry/namespaces/default /registry/namespaces/kube-public /registry/namespaces/kube-system /registry/ranges/serviceips /registry/ranges/servicenodeports /registry/services/endpoints/default/kubernetes /registry/services/specs/default/kubernetes

忽略掉前面的/register/apixxx,来看一下后面这些东西:

  • 三个namespace:default、kube-public、kube-system;
  • /register/ranges/serviceips:内容包含10.0.0.0/16,与--service-cluster-ip-range一致;
  • /registry/ranges/servicenodeports:内容包含30000-32767,查了一下代码,这个值是--service-node-port-range参数的默认值,见https://github.com/kubernetes/kubernetes/blob/release-1.10/pkg/kubeapiserver/options/options.go
  • /registry/services/<endpoints,specs>/default/kubernetes:描述了同一个service(kubernetes)的endpoints信息及specs信息,endpoints内容可见server的外网ip,specs内容可见10.0.0.1,这是service-cluster-ip-range的第一个ip地址;

使用kubectl查看信息

apiserver提供了restapi以获取和管理在etcd上的集群状态信息;kubectl就是这个restapi的客户端;

因为我们的服务端口不在默认的8080上,所以使用时要加一个-s参数:

查看namespace:

$ bin/kubectl -s 127.0.0.1: get ns # 查看三个namespace,与etcd的/registry/namespaces对应
NAME STATUS AGE
default Active 1h
kube-public Active 1h
kube-system Active 1h

查看service:

$ bin/kubectl -s 127.0.0.1: get svc # 查看service,与/registry/services/specs/default/kubernetes对应
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> /TCP 1h

查看endpionts:

$ bin/kubectl -s 127.0.0.1: get ep #查看endpoints,与/registry/services/endpoints/default/kubernetes对应
NAME ENDPOINTS AGE
kubernetes xxxxx: 1h

启动controller-manager

注:这个命令虽然可以启动controller-manager,但后续会出现一些问题,需要再添加参数,见“测试”部分对controller-manaer的调整

bin/kube-controller-manager \
--master=127.0.0.1: \
--logtostderr=true

生成的数据

查看etcd,多出现一些节点:

/registry/events/kube-system/kube-controller-manager.153c40f68e70e209

/registry/serviceaccounts/default/default

/registry/serviceaccounts/kube-public/default

/registry/serviceaccounts/kube-system/default

/registry/services/endpoints/kube-system/kube-controller-manager

多出一个event,三个serviceaccounts(三个namespace下的default),以及一个endpoints;

使用kubectl查看信息

event就不看了,来看一下service account:

$ bin/kubectl -s 127.0.0.1: get sa
NAME SECRETS AGE
default 3m

这里的SECRETS为0,表明没有为这个service account生成secret,这个也是与安全相关的东西,先忽略,后面会遇到问题,然后我们再回来处理它;

再看一下endpoint:

$ bin/kubectl -s 127.0.0.1: get ep --namespace kube-system
NAME ENDPOINTS AGE
kube-controller-manager <none> 7m

因为kube-controller-manager在kube-system下,所以需要多加一个namespace参数;

启动scheduler

bin/kube-scheduler \
--master=127.0.0.1:

生成的数据

查看etcd,多出现一些节点:

/registry/events/kube-system/kube-scheduler.153c41b5b3052d28

/registry/services/endpoints/kube-system/kube-scheduler

使用kubectl查看信息

再看一下endpoints

$ bin/kubectl -s 127.0.0.1: get ep --namespkube-system
NAME ENDPOINTS AGE
kube-controller-manager <none> 15m
kube-scheduler <none> 1m

查看集群状态

$ bin/kubectl -s 127.0.0.1: get cs
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd- Healthy {"health":"true"}

至此,server就算部署好了

node部署

本想node的两个服务组件也用非root用户的,但试下来发现不行,kubelet需要与docker交互,而kube-proxy则要改iptables,都需要提供root权限;

安装node

解压node包,程序都解压到了kubernetes/node/bin路径:

# tar vfxz kubernetes-node-linux-amd64.tar.gz #解压
# ls kubernetes/node/bin/ # 看一下
# cd kubernetes/node # 就在这个路径下进行node服务的管理

启动kubelet

kubelet的参数太多了,可能为了简化kubelet的启动脚本吧,引入了两个配置文件,两个,两个......而且除这两个文件外还要设置其它参数,设置其它参数,其它参数......faint

先生成访问apiserver需要用的kubeconfig文件:

# KUBE_APISERVER="http://<apiserver>:18080"
#
# bin/kubectl config set-cluster kubernetes \
--server=$KUBE_APISERVER \
--kubeconfig=etc/kubernetes/kubelet.kubeconfig
#
# bin/kubectl config set-context default \
--cluster=kubernetes \
--user=default-noauth \
--kubeconfig=etc/kubernetes/kubelet.kubeconfig
#
# bin/kubectl config use-context default --kubeconfig=etc/kubernetes/kubelet.kubeconfig
#
# bin/kubectl config view --kubeconfig=etc/kubernetes/kubelet.kubeconfig apiVersion: v1
clusters:
- cluster:
server: http://<apiserver>:18080
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: ""
name: default
current-context: default
kind: Config
preferences: {}
users: []

这个配置文件就声明了一个以http://<apiserver>:18080为入口的名为“kubernetes”的集群,以及一个匿名访问“kubernetes”集群的名为“default”的上下文,并声明使用这个"default"上下文;

写kubelet自身需要的配置文件(这个文件可以是yaml或json格式,因为很多教程用了json格式,所以这里我用一下yaml格式):

# cat etc/kubernetes/kubelet.config.yaml
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: cgroupfs

kind和apiVersion都是定死的,可见https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/,以及代码的这里:https://github.com/kubernetes/kubernetes/blob/release-1.10/pkg/kubelet/apis/kubeletconfig/v1beta1/register.go

cgroupDriver需要与docker的真实情况相符,通过以下命令查看:

# docker info|grep 'Cgroup Driver'
Cgroup Driver: cgroupfs

启动kubelet:

bin/kubelet \
--cert-dir=etc/kubernetes/cert \
--kubeconfig=etc/kubernetes/kubelet.kubeconfig \
--config=etc/kubernetes/kubelet.config.yaml \
--pod-infra-container-image=<registry>/rhel7/pod-infrastructure:latest \
--runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice \
--logtostderr=true

参数说明:

  1. --cert-dir:与apiserver的参数道理相同;kubernete强制生成;
  2. --kubeconfig:访问apiserver需要的config;
  3. --config:kubelet自己需要的config;
  4. --pod-infra-container-image:一个基础容器镜像,做为pod的第一个容器启动,为每个pod提供network namespace;没啥业务逻辑,理论上说就是启动之后保持不退出即可,以后我可以自己写一个试试。默认镜像地址可能被墙,所以想办法下载一个下来(docker官方registry上有),然后推到私有的registry比较好;
  5. --runtime-cgroups,--kubelet-cgroups:可能是因为我手动启动kubelet,而不是做为systemd的service启动的缘故吧,启动之后会时而出现这个错误:Failed to get system container stats for "/user.slice/user-0.slice/,加上这两个参数就好了;

生成的文件及数据

在cert-dir下出现了自动创建的证书和密钥:

# file etc/kubernetes/cert/*
etc/kubernetes/cert/kubelet.crt: PEM certificate
etc/kubernetes/cert/kubelet.key: PEM RSA private key

多说一句,这个证书是node自己签发的,肯定得不到apiserver的认可;当然因为我在这里不做安全集群,这就无所谓;但在安全集群里,kubelet的证书会由controller-manager签发;

在etcd上出现了一些新的数据,除去events外,就一个最重要的minions数据:

/registry/minions/<node>

使用kubectl查看信息

$ bin/kubectl -s 127.0.0.1: get node
NAME STATUS ROLES AGE VERSION
<node> Ready <none> 38m v1.10.5

启动kube-proxy

bin/kube-proxy \
--master=<apiserver>: \
--proxy-mode=iptables \
--logtostderr=true

参数说明:

  1. proxy-mode:当前默认使用的就是iptables模式,ipvs还是experiment功能;如果iptables不适用,则回退到userspace模式下;

至此,node部署完成;

测试

启动应用

到apiserver上,执行以下命令,运行一个标准的nginx容器,为了省时间,我也把它拉下来,push到私有registry上了:

$ bin/kubectl -s 127.0.0.1: run nginx --image=<registry>/nginx/nginx --port=

pod启动失败,报错:No API token found for service account "default"

之前遗留了一个问题,见service_account_without_secrets

于是调整一下controller-manager的参数,加上--service-account-private-key-file和--root-ca-file参数,重启controller-manager:

$ bin/kube-controller-manager \
--master=127.0.0.1: \
--service-account-private-key-file=etc/kubernetes/cert/apiserver.key \
--root-ca-file=etc/kubernetes/cert/apiserver.crt \
--logtostderr=true

再看一下service account的情况,secrets已经不是0了:

$ bin/kubectl -s 127.0.0.1: get sa
NAME SECRETS AGE
default 2h

再重新试一下启动nginx,并查看状态;

$ bin/kubectl -s 127.0.0.1: run nginx --image=<registry>/nginx/nginx --port=  # 启动
$
$ bin/kubectl -s 127.0.0.1: get deploy # 查看deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx 1m
$
$ bin/kubectl -s 127.0.0.1: describe deploy nginx|grep NewReplicaSet # 查看deploy详情
Progressing True NewReplicaSetAvailable
NewReplicaSet: nginx-55cc995fdb (/ replicas created)
$
$ bin/kubectl -s 127.0.0.1: describe replicasets nginx-55cc995fdb |tail -1 # 查看replicaset详情
Normal SuccessfulCreate 10m replicaset-controller Created pod: nginx-55cc995fdb-27t7z
$
$ bin/kubectl -s 127.0.0.1: get pod nginx-55cc995fdb-27t7z -o wide # 查看pod
NAME READY STATUS RESTARTS AGE IP NODE
nginx-55cc995fdb-27t7z / Running 11m 172.10.63.2 <node>

再到node上看一下容器状态:

# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3e5e69a69950 <registry>/nginx/nginx "nginx -g 'daemon of…" seconds ago Up seconds k8s_nginx_nginx-55cc995fdb-27t7z_default_1ca63ddd-7ab5-11e8-be61-3440b59f0098_0
ec311fee295d <registry>/rhel7/pod-infrastructure:latest "/pod" seconds ago Up seconds k8s_POD_nginx-55cc995fdb-27t7z_default_1ca63ddd-7ab5-11e8-be61-3440b59f0098_0

看以看到,同时启动了两个容器,一个是pod-infrastructure,另一个是nginx;如果进入这两个容器内看一下的话,会发现它们的ip地址是同一个;

总结一下启动应用时这些资源的关系:

  • 一个应用会对应一个deploy资源;
  • 一个deploy会对应一个replicaset资源;
  • 一个replicaset会对应多个(默认为一个)pod资源;
  • 一个pod会在某个node上启动至少两个container,其中一个是pod-infrastructure运行容器,另一个是应用所在的运行容器;它们共享ip地址;

暴露服务

如果启动的应用本身是个服务的话,还需要将服务地址暴露出来,在server(master)上运行:

$ bin/kubectl -s 127.0.0.1:  expose deployment nginx --type=NodePort --name=example-service
service "example-service" exposed
$
$ bin/kubectl -s 127.0.0.1: describe services example-service
Name: example-service
Namespace: default
Labels: run=nginx
Annotations: <none>
Selector: run=nginx
Type: NodePort
IP: 10.0.158.97
Port: <unset> /TCP
TargetPort: /TCP
NodePort: <unset> /TCP
Endpoints: 172.10.63.2:
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>

从后面的服务描述中得到以下信息:

  • service的cluster_ip是10.0.158.97,这个地址在apiserver启动时的--service-cluster-ip-range参数范围内,也即etcd上/register/ranges/serviceips节点内配置的信息;
  • service的nodeport是30152,这个端口在apiserver启动时的--service-node-port-range参数范围内,也即etcd上/registry/ranges/servicenodeports节点内配置的信息;
  • service的endpoints是172.10.63.2:80,这是ip地址是容器内的地址;

测试服务

在server(master)上访问node的30152端口,nginx服务正常:

$ curl <node>:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p> <p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p>
</body>
</html>

在node上访问10.0.158.97:80,nginx也服务正常;查看一下node的iptables,会发现有一条规则将target为10.0.158.97:80的流量转发到了本机的30152端口;这是kueb-proxy做的事情;

在另一个节点(可以不是kubernetes node,只要求启用了与node相同的flanneld)或容器(可以不是kubernetes pod,只要求容器所在节点启用了与node相同的flanneld)内访问172.10.63.2:80,nginx也服务正常;这就是flanneld做的事情了;

重点参考以下三篇:

  • https://www.jianshu.com/p/8358117a23bb
  • https://github.com/opsnull/follow-me-install-kubernetes-cluster
  • https://jimmysong.io/kubernetes-handbook/practice/install-kubernetes-on-centos.html

CentOS7上手动部署入门级kubernetes的更多相关文章

  1. 使用 Azure CLI 在 Azure China Cloud 云平台上手动部署一套 Cloud Foundry

    这篇文章将介绍如何使用 Azure CLI 在 Azure China Cloud 云平台上手动部署一套 Cloud Foundry.本文的目的在于: 了解作为 PaaS 的 Cloud Foundr ...

  2. Docker(2)--Centos7 上安装部署

    Centos7 上安装docker Docker从1.13版本之后采用时间线的方式作为版本号,分为社区版CE和企业版EE. 社区版是免费提供给个人开发者和小型团体使用的,企业版会提供额外的收费服务,比 ...

  3. docker 在 centos7.* 上的部署及问题解决

    最近尝试搭建docker 环境,其实个人是比较喜欢“菜鸟学习系列”的知识的,怎奈它的讲解是以Ubuntu为主的,最后找到一个搭建学习系列,感觉写的很好,主要是页面风格清晰明了,遂决定按照此教程学习搭建 ...

  4. kvm+webvirtmgr在centos7上的部署

    #!/bin/bash #+++++++++++++++++++++++++++++++++++++++++++++++++++++++安装配置kvm并创建虚拟机+++++++++++++++++++ ...

  5. 在centos7上安装部署hadoop2.7.3和spark2.0.0

    一.安装装备 下载安装包: vmware workstations pro 12 三台centos7.1 mini 虚拟机 网络配置NAT网络如下: 二.创建hadoop用户和hadoop用户组 1. ...

  6. Spring Boot框架开发的Java项目在CentOS7上的部署

    需求:上级拿来一份Spring Boot框架开发的Java项目代码让我在服务器上运行起来,只说了一句该框架是自带了Tomcat(不用重新安装Tomcat),一份代码下有两个项目(一个管理端项目,一个用 ...

  7. 密码管理平台ratticdb的部署,在centos7上的部署

    一,前言 一直想用ratticdb这个有web界面的密码管理工具,百度了一下居然没有找到中文的部署文档,访问官网也是notfound.找到了官方的部署指南:https://github.com/til ...

  8. 在CentOS7上部署OpenStack 步骤详解

    OpenStack作为一个由NASA(美国国家航空航天局)和Rackspace合作研发并发起的,开放源代码项目的云计算管理平台项目.具体知识我会在后面文章中做出介绍,本章主要按步骤给大家演示在Cent ...

  9. Docker实践(6)—CentOS7上部署Kubernetes

    Kubernetes架构 Kubernetes的整体架构如下: Master为主控节点,上面运行apiserver,scheduler,controller-manager等组件.Minion相当于工 ...

随机推荐

  1. 9. http协议_响应状态码_页面渲染流程_路由_中间件

    1. http协议 超文本传输协议 协议详细规定了 浏览器 和 万维网服务器 之间互相通信的规则 客户端与服务端通信时传输的内容我们称之为报文(请求报文.响应报文) 常见的发送 get 请求方式 在浏 ...

  2. ubuntu重复登录问题

    第一次遇到: 昨天好不容易装好了驱动,紧接着装了CUDA,cuDNN,Anaconda,VSCode等等.然后安装pytorch的时候遇到了下载的问题,后来也算搞定了.但是在更换了显示器后重启(好像是 ...

  3. javascript的数组之slice()

    slice()方法创建一个新数组,将原数组的部分元素拷贝到新数组,并将新数组返回,且原数组不会被修改. var animals = ['ant', 'bison', 'camel', 'duck', ...

  4. Lecture4_1&4_2.多维随机变量及其概率分布

    1.二维随机变量(X,Y)的联合分布函数: F(x,y)=P(X≤x,Y≤y) 2.二维随机变量(X,Y)关于X的边缘分布函数: FX(x)=P(X≤x) =P(X≤x,Y<+∞) =F(x,+ ...

  5. mysql - Truncated incorrect DOUBLE value: 'undefined'

    mysql - Truncated incorrect DOUBLE value: 'undefined' 我是怎么遇到这个问题的? 我要从多个表里,查询统计数据,保存到统计表里,需要执行下面这种结构 ...

  6. C#获取项目程序及运行路径的方

    1.asp.net webform用“Request.PhysicalApplicationPath获取站点所在虚拟目录的物理路径,最后包含“\”:   2.c# winform用 A:“Applic ...

  7. Jackson Annotation Examples

    1. Overview In this article, we’ll do a deep dive into Jackson Annotations. We’ll see how to use the ...

  8. 3. Scala运算符

    3.1 运算符介绍 运算符是一种特殊的符号,用以表示数据的运算.赋值和比较等 1) 算术运算符 2) 赋值运算符 3) 比较运算符(关系运算符) 4) 逻辑运算符 5) 位运算符 3.2 算术运算符 ...

  9. kubernetes in action - Replication Controller

    理解这个问题,就是pods在Kubernetes中怎么进行failover 在Kubernetes的work node上有kubelet,会负责监控该work node上的pods,如果有contai ...

  10. 使用pushstate,指定回退地址

    history.pushState(null,"testname", window.location.href); window.addEventListener('popstat ...