K8S组件介绍及安装
K8S组件组件作用master组件1. API Server程序:kube-apiserver,定义存储特定存储格式,声明式,只支持特定格式的存储(类似文档格式{key1:value1,key2:value2})2. Controller Manager(控制管理)程序:kube-controller-manager,(管理容器扩缩容,滚动更新等)控制器:包含route controller(路由
K8S组件介绍以及安装
一、K8S组件
1. 组件作用
1.1 master组件
1. API Server
端口:6443
集群内部所有及外部通信都是https协议(内部包括kube-controller,kube-scheduler等组件之间的通信都需要经过api-server。)
程序:kube-apiserver,定义存储特定存储格式,声明式,只支持特定格式的存储(类似文档格式{key1:value1,key2:value2})
官方理解作用:集群的统一入口,各组件协调者,以HTTP API提供接口服务,所有对象资源的增删改查和监听操作都交给APIServer处理后再提交给Etcd存储。
作用:kube-apiserver用于暴露Kubernetes API。任何的资源请求/调用操作都是通过kube-apiserver提供的接口进行。
3. Controller Manager(控制管理)
程序:kube-controller-manager,(管理容器扩缩容,滚动更新等)(控制器管理器)
控制器:包含route controller(路由),volume controller(数据卷),service controller(服务),node controller,deployment controller(编排),replicaset controller等
还包含很多控制器共同构成kube-controller-manager
运维人员可以自己开发控制器链接API Server
官方理解作用:处理集群中常规后台任务,一个资源对应一个控制器,而ControllerManager就是负责管理这些控制器的。
作用:kube-controller-manager运行管理控制器,它们是集群中处理常规任务的后台线程。逻辑上,每个控制器是一个单独的进程,但为了降低复杂性,它们都被编译成单个二进制文件,并在单个进程中运行。
4. Scheduler(调度)
程序:kube-scheduler,调度容器到某node节点
官方理解作用:根据调度算法为新创建的Pod选择一个Node节点。
作用:监视新创建没有分配到Node的Pod,为Pod选择一个Node。
5. Etcd(状态存储)
程序:etcd,存储容器以及node节点状态信息等,(etcd使用raft协议的(k/v)键值存储系统)
官方理解作用:第三方服务;分布式键值存储系统,负责集群的持久化。用于保持集群状态,比如Pod、Service等对象信息
作用:API server与etcd集群以https通信,集群所有信息都存储在etcd,etcd是Kubernetes提供默认的存储系统,保存所有集群数据,使用时需要为etcd数据提供备份计划。
1.2 node组件
1. kubelet
安装时必须安装到服务器不能运行容器
包含三个接口
(1).CNI(Container Network Interface容器网络接口):链接网络插件为pod提供网络功能
(2).Volume(CSI)(Container Storage Interface容器存储接口):内嵌存储插件链接存储设备从而为pod提供存储卷
(3).CRI(Container Runtime Interface容器运行池接口):通过这个接口K8S可支持很多容器引擎
node节点上执行指令,注册监听kube-apiserver数据变动,与kube-apiserver利用https协议通信,需要证书
官方理解作用:kubelet是Master在Node节点上的Agent,管理本机运行容器的生命周期,比如创建容器、Pod挂载数据卷、下载secret、获取容器和节点状态等工作。kubelet将每个Pod转换成一组容器。
作用: kubelet是主要的节点代理,它会监视已分配给节点的pod
2. kube-proxy
为应用转发
官方理解作用:在Node节点上实现Pod网络代理,维护网络规则和四层负载均衡工作,代理iptables做防火墙策略。
作用:kube-proxy通过在主机上维护网络规则并执行连接转发来实现Kubernetes服务抽象。
3. container engine(容器引擎)
docker等
4. pod
pod不是组件。pod内的所有容器必须运行在同一个节点。
每个pod都有label,用于被service识别
1.3 插件组件
1.3.1 kubeDNS
- DNS作用映射service与IP地址的关系等等。
例:CoreDNS
1.3.2 Dashboard(Web界面)
1.3.3 监控系统
- promethus
1.3.4 日志系统
- 例:ElasticSearh (java开发,搜索引擎,用于存储日志)
Filebeat/Fluentd/fluent-bit/logstash (收集日志) logstash(基于java开发比Filebeat站内存)
Kibana(web展示日志) - 例:Loki (收集存储日志)(新生产品云原生)
Grafana(web展示日志)
1.3.5 Ingress Controller(入站流量控制器)
- 作用:管理进出集群的流量
1.3.6 网络插件
主要流行两种:flannel、Calico
flannel:支持网络通信但不支持配置网络策略(简单易用)
Calico:支持网络通信又支持配置网络策略
1.4 k8s和docker对应版本
https://github.com/kubernetes/kubernetes/releases
2. k8s基本结构
3. k8s证书
二、运行一个应用的过程
1.kube-controller-manager声明需要创建的配置,并写入kube-apiserver数据中。
2.kube-scheduler会检测到kube-apiserver的数据,并进行调度(就是将pod创建在那个节点上)
3.node节点的kubelet组件监听到调度给自己,然后创建pod,kubelet和kube-apiserver通信时会加载kubeconfig进行证书与双向认证。
4.通过service控制pod,假设一共3个节点,每个节点一个nginx-pod,k8s就会创建service来管理这些pod(包括增删映射等),service也是一个数据表特定格式,service是通过label来记录每个pod。
三、k8s安装方式
3.1 二进制方式安装
https://mp.weixin.qq.com/s?__biz=MzIwNDA3ODg3OQ==&mid=2648000112&idx=2&sn=307080df073fddb30835254943a8b15d&chksm=8ee44c00b993c5162b21c8605ab32ebd0402c9d6d67a5e4c4ea240b0813d43dca4d16a894615&cur_album_id=1835825486392770561&scene=189#wechat_redirect
3.2 静态Pod方式安装
- 例:kubeadm方式
静态Pod方式
1.matser和node节点组件pod不受controller管理,
会受kubelet直接管理,kubelet会监控某个目录下的manifest(清单)文件(每个组件pod对应一个文件),一旦某一个文件没有之后就会重新创建对应组件的pod。
2.其他运行在k8s集群上的Pod受控于controller。
>
蓝色部分是由kubeadm部署起来的组件
3.3 动态Pod方式安装
- 动态pod的方式:master组件和node组件是受controller控制的
四、kubeadm方式安装K8S
4.1 主机配置信息
CentOS Linux release 7.7.1908 (Core) 全部2核2G
192.168.8.10 master01 master01.timerovers.com kubeapi.timerovers.com kubeapi
192.168.8.20 node01 node01.timerovers.com
192.168.8.30 node02 node02.timerovers.com
4. 2 安装组件
4.2.1 master安装组件
kube-apiserver,kube-controller-manager,kube-scheduler.etcd
4.2.2 node安装组件
kubelet,kube-proxy,docker
注意:每个节点都需要安装kubeadm,kubelet,docker,kube-proxy (目的是将(除kubelet外)所有组件运行成pod)
kubeadm:以pod方式运行所有组件(除kubelet外)
kubectl:运行在控制节点上(但是安装时会作为依赖安装)
4.2.3 环境准备
注意:(以下操作不做特殊说明表示在所有节点操作)
- 关闭swap
sed -i '/swap/s/^/#/g' /etc/fstab
swapoff -a
- 保证时间一直
ntpdate ntp.aliyun.com
- 关闭防火墙
iptables -F
setenforce 0
systemctl stop firewalld
systemctl disable firewalld
- docker改为国内镜像源
vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://njrds9qc.mirror.aliyuncs.com"]
}
systemctl restart docker
- 配置k8s国内yum源
yum源
[root@localhost yum.repos.d]# ls
Centos-7.repo epel-7.repo kubernetes.repo docker-ce.repo
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
EOF
- 修改主机名并hosts解析
hostnamectl set-hostname master01
hostnamectl set-hostname node01
hostnamectl set-hostname node02
#域名后期使用,现在可以不加,一般公司里都会用DNS解析
cat <<EOF >> /etc/hosts
192.168.8.10 master01 master01.timerovers.com kubeapi.timerovers.com kubeapi
192.168.8.20 node01 node01.timerovers.com
192.168.8.30 node02 node02.timerovers.com
EOF
- 配置内核参数并加载内核模块
cat <<EOF >> /etc/sysctl.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_nonlocal_bind = 1
net.ipv4.ip_forward = 1
vm.swappiness=0
EOF
sysctl --system
cat <<EOF > /etc/sysconfig/modules/ipvs.modules
#!/bin/bash
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
modprobe nf_conntrack_ipv4
EOF
chmod +x /etc/sysconfig/modules/ipvs.modules
/etc/sysconfig/modules/ipvs.modules
4.2.4 开始安装
注意:(以下操作不做特殊说明表示在所有节点操作)
- 安装
(所有节点)安装之前,将exec-opts加入daemon.json,并重启docker
[root@master01 ~]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://njrds9qc.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
yum -y install kubeadm kubectl kubelet
#指定版本号
yum -y install kubeadm-1.19.4 kubectl-1.19.4 kubelet-1.19.4
- 初始化master节点
(master节点操作)
kubeadm init --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers --kubernetes-version=v1.19.4 --control-plane-endpoint=kubeapi.timerovers.com --apiserver-advertise-address=192.168.8.10 --pod-network-cidr=10.244.0.0/16 --token-ttl=0
选项解释:
--token-ttl:指定token的日期,--token-ttl=0表示永不过期
--image-repository:指定仓库地址
--kubernetes-version:指定k8s版本,和kubeadm版本保持一致
--control-plane-endpoint:指定控制平面的地址(控制平面指:master上的关键组件组成的结构)(可以不加)
--apiserver-advertise-address:指定apiserverIP地址(不指定自动探测)(这里本人指定的是masterIP)
--apiserver-bind-port:API服务器要绑定到的端口。6443(默认)
--pod-network-cidr:指定pod网络的IP地址范围。如果设置,控制平面将自动为每个节点分配cidr
注意:由于要用flannel,flannel默认网段是10.244.0.0/16
记住以下产生的(类似)部分
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join kubeapi.timerovers.com:6443 --token 7i7dlx.kfo4hxytoj32t58b \
--discovery-token-ca-cert-hash sha256:97c588edeb459d4790fe2bd3fe3668355466e8af2d1911ca6d32a342e394e1f6 \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join kubeapi.timerovers.com:6443 --token 7i7dlx.kfo4hxytoj32t58b \
--discovery-token-ca-cert-hash sha256:97c588edeb459d4790fe2bd3fe3668355466e8af2d1911ca6d32a342e394e1f6
3.token过期处理
1.重新生成token
kubeadm token generate
4ivc2t.m4o2ki1ybufwf75m
2.根据token输出添加命令
kubeadm token create 4ivc2t.m4o2ki1ybufwf75m --print-join-command --ttl=0
3.生成物
kubeadm join kubeapi.timerovers.com:6443 --token 4ivc2t.m4o2ki1ybufwf75m --discovery-token-ca-cert-hash sha256:295bdbf93a24d8ffd79608762ff8567d2edb14b854f09a37fdebbcc64a917613
kubeadm init主要执行了以下操作:
[init]:指定版本进行初始化操作
[preflight] :初始化前的检查和下载所需要的Docker镜像文件
[kubelet-start] :生成kubelet的配置文件”/var/lib/kubelet/config.yaml”,没有这个文件kubelet无法启动,所以初始化之前的kubelet实际上启动失败。
[certificates]:生成Kubernetes使用的证书,存放在/etc/kubernetes/pki目录中。
[kubeconfig] :生成 KubeConfig 文件,存放在/etc/kubernetes目录中,组件之间通信需要使用对应文件。
[control-plane]:使用/etc/kubernetes/manifest目录下的YAML文件,安装 Master 组件。
[etcd]:使用/etc/kubernetes/manifest/etcd.yaml安装Etcd服务。
[wait-control-plane]:等待control-plan部署的Master组件启动。
[apiclient]:检查Master组件服务状态。
[uploadconfig]:更新配置
[kubelet]:使用configMap配置kubelet。
[patchnode]:更新CNI信息到Node上,通过注释的方式记录。
[mark-control-plane]:为当前节点打标签,打了角色Master,和不可调度标签,这样默认就不会使用Master节点来运行Pod。
[bootstrap-token]:生成token记录下来,后边使用kubeadm join往集群中添加节点时会用到
[addons]:安装附加组件CoreDNS和kube-proxy
- 为kubectl准备Kubeconfig文件
(master操作)
kubectl默认会在执行的用户家目录下面的.kube目录下寻找config文件。这里是将在初始化时[kubeconfig]步骤生成的admin.conf拷贝到.kube/config
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
在该配置文件中,记录了API Server的访问地址,所以后面直接执行kubectl命令就可以正常连接到API Server中
- 还原到安装之前
(master操作)
(node节点也可以)
kubeadm reset
rm -fr $HOME/.kube/config
rm -fr /etc/kubernetes/
4.2.5 node节点加入集群
(所有node节点操作)
1.启动
systemctl enable kubelet.service
2.加入
kubeadm join kubeapi.timerovers.com:6443 --token 7i7dlx.kfo4hxytoj32t58b --discovery-token-ca-cert-hash sha256:97c588edeb459d4790fe2bd3fe3668355466e8af2d1911ca6d32a342e394e1f6
(运行这条命令会下载镜像)
3.结果
[root@node01 ~]# kubeadm join kubeapi.timerovers.com:6443 --token 7i7dlx.kfo4hxytoj32t58b --discovery-token-ca-cert-hash sha256:97c588edeb459d4790fe2bd3fe3668355466e8af2d1911ca6d32a342e394e1f6
[preflight] Running pre-flight checks
[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
4.查看node节点
[root@master01 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master01 Ready master 4d23h v1.19.4
node01 NotReady <none> 50s v1.19.4
node02 NotReady <none> 47s v1.19.4
5.查看pod状态
[root@master01 ~]# kubectl get pod --all-namespaces
4.2.6 安装flannel网络插件
flannel github网址:https://github.com/flannel-io/flannel
常见K8S网络插件:
·Flannel是可与Kubernetes一起使用的覆盖网络提供商。
·Calico是安全的L3网络和网络策略提供商。
·Canal联合Flannel和Calico,提供网络和网络策略。
·Romana是用于Pod网络的第3层网络解决方案。
(master操作)
- 安装
方式一:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
#以上方式下载不下来就用以下方式
方式二:(和上边是一个)
wget https://github.com/flannel-io/flannel/blob/701c2e8749714022758d5360fbe627005901349c/Documentation/kube-flannel.yml
或wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl apply -f kube-flannel.yml
2.结果
[root@master01 ~]# kubectl apply -f kube-flannel.yml
podsecuritypolicy.policy/psp.flannel.unprivileged created
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRole is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRole
clusterrole.rbac.authorization.k8s.io/flannel created
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRoleBinding is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRoleBinding
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds-amd64 created
daemonset.apps/kube-flannel-ds-arm64 created
daemonset.apps/kube-flannel-ds-arm created
daemonset.apps/kube-flannel-ds-ppc64le created
daemonset.apps/kube-flannel-ds-s390x created
3.查看节点状态
[root@master01 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master01 Ready master 35m v1.19.4
node01 Ready <none> 32m v1.19.4
node02 Ready <none> 31m v1.19.4
4.查看pod状态
以下状态表示完成
[root@master01 ~]# kubectl get pod --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-6c76c8bb89-pskcq 1/1 Running 0 19m
kube-system coredns-6c76c8bb89-tk2m6 1/1 Running 0 19m
kube-system etcd-master01 1/1 Running 0 20m
kube-system kube-apiserver-master01 1/1 Running 0 20m
kube-system kube-controller-manager-master01 1/1 Running 0 20m
kube-system kube-flannel-ds-f8g89 1/1 Running 0 5m44s
kube-system kube-flannel-ds-fv62j 1/1 Running 0 5m44s
kube-system kube-flannel-ds-kjqnb 1/1 Running 0 5m44s
kube-system kube-proxy-cb4t9 1/1 Running 0 19m
kube-system kube-proxy-kv8mj 1/1 Running 0 19m
kube-system kube-proxy-n622g 1/1 Running 0 19m
kube-system kube-scheduler-master01 1/1 Running 0 20m
4.2.7 修改为ipvs模式
如果k8s集群中service很多默认的iptables会生成好多规则,影响服务访问,所以这里先修改成ipvs模式详情见文章:k8s service+kube-proxy+endpoint+标签+通信过程解释
因为ipvs规则是由kube-proxy生成的,所以需要修改kube-proxy的配置
- 查看kube-proxy配置文件
[root@master01 ~]# kubectl get configmap -n kube-system
NAME DATA AGE
coredns 1 103d
extension-apiserver-authentication 6 103d
kube-flannel-cfg 2 103d
kube-proxy 2 103d
kubeadm-config 2 103d
kubelet-config-1.19 1 103d
- 可在线修改kube-proxy配置文件
1. 修改
kubectl edit cm kube-proxy -n kube-system
解释:
ipvs:
excludeCIDRs: null
minSyncPeriod: 0s
scheduler: "" #调度算法,默认是轮询(rr)
strictARP: false
syncPeriod: 0s
tcpFinTimeout: 0s
tcpTimeout: 0s
udpTimeout: 0s
修改data字段中的mode字段,默认是空(默认就是iptables模式),改为ipvs
mode: "ipvs"
修改完之后保存退出即可,之后会自动应用的
2. 手动删除kube-proxy
如果不自动应用,可以手动删除以下kube-proxy,因为删除之后,会重新创建,但是需要注意一个一个删除,等第一个起来在删除第二个,否则集群就不能访问了。
[root@master01 ~]# kubectl get pod -n kube-system -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
coredns-6c76c8bb89-pskcq 1/1 Running 71 103d 10.244.0.39 master01 <none> <none>
coredns-6c76c8bb89-tk2m6 1/1 Running 71 103d 10.244.0.38 master01 <none> <none>
etcd-master01 1/1 Running 18 103d 192.168.8.10 master01 <none> <none>
kube-apiserver-master01 1/1 Running 22 103d 192.168.8.10 master01 <none> <none>
kube-controller-manager-master01 1/1 Running 32 103d 192.168.8.10 master01 <none> <none>
kube-flannel-ds-f8g89 1/1 Running 19 103d 192.168.8.30 node02 <none> <none>
kube-flannel-ds-fv62j 1/1 Running 16 103d 192.168.8.20 node01 <none> <none>
kube-flannel-ds-kjqnb 1/1 Running 24 103d 192.168.8.10 master01 <none> <none>
kube-proxy-cb4t9 1/1 Running 15 103d 192.168.8.20 node01 <none> <none>
kube-proxy-kv8mj 1/1 Running 18 103d 192.168.8.30 node02 <none> <none>
kube-proxy-n622g 1/1 Running 18 103d 192.168.8.10 master01 <none> <none>
kube-scheduler-master01 1/1 Running 31 103d 192.168.8.10 master01 <none> <none>
3. 删除操作
kubectl delete pods kube-proxy-cb4t9 -n kube-system
4. 查看网卡是否出现kube-ipvs0
ip a
5. 最好重启一下kubelet,不重启应该也没关系,如果生产环境在运行这,最好不要重启
4.3 k8s 集群增加node节点
4.3.1 加入之前准备
新node需要安装kubelet,kube-proxy,docker,还有环境准备,就是上边的4.2.2和4.2.3,之后执行下边的操作即可
4.3.2 重新生成token
如果之前的token过期了可以重新生成一下,如果之前的token设置的是永久的,可以使用之前的token
[root@master01 ~]# kubeadm token create --print-join-command
W0619 21:36:48.113295 25418 configset.go:348] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
kubeadm join kubeapi.timerovers.com:6443 --token dz4oaa.38over7mpgo7aqgp --discovery-token-ca-cert-hash sha256:cd2471827475870374a03ebf5cff374745af54ebeb983995761c2da2e4698a3a
4.3.3 新node加入节点
- 加入
[root@node03 ~]# kubeadm join kubeapi.timerovers.com:6443 --token dz4oaa.38over7mpgo7aqgp --discovery-token-ca-cert-hash sha256:cd2471827475870374a03ebf5cff374745af54ebeb983995761c2da2e4698a3a
[preflight] Running pre-flight checks
[WARNING Service-Kubelet]: kubelet service is not enabled, please run 'systemctl enable kubelet.service'
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
- 查看是否有了
这里等一会就会Ready
[root@master01 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master01 Ready master 104d v1.19.4
node01 Ready <none> 104d v1.19.4
node02 Ready <none> 104d v1.19.4
node03 Ready <none> 83s v1.19.4
更多推荐
所有评论(0)