有缘遇到你 發表於 2019-8-12 18:29:00

Kubernetes(三):集群部署

<p></p><div class="toc"><div class="toc-container-header">目录</div><ul><li>k8s部署环境</li><li>k8s运行模式</li><li>k8s部署方式</li><li>k8s部署要点</li><li>kubeadm部署k8s</li><li>安装dashboard</li><li>安装监控组件</li></ul></div><p></p>
<p> <br>
 </p>
<h1 id="k8s部署环境">k8s部署环境</h1>
<p> </p>
<ul>
<li><strong>公有云环境</strong>:AWS、腾讯云、阿里云等等</li>
<li><strong>私有云</strong>:OpenStack、vSphere等</li>
<li><strong>Baremetal环境</strong>:物理服务器或独立虚拟机(底层没有云环境)。</li>
</ul>
<p> </p>
<h1 id="k8s运行模式">k8s运行模式</h1>
<p> </p>
<p>  k8s运行模式有如下三种,使用kubeadm方式部署的k8s集群可运行为第二种或者第三种模式,默认为第二种模式,如果需要使用第三种模式,需要在kubeadm init时加上参数“--features-gates=selfHosting”。</p>
<ul>
<li>第一种模式:“独立组件模式”,系统各组件直接以守护进程的方式运行在节点之上,各组件之间相互协作构成集群。</li>
<li>第二种模式:“静态Pod模式”,除kubelet和docker之外的其它组件(etcd、kube-apiserver、kube-scheduler、kube-controller-manager)都以静态Pod对象运行与master主机上。</li>
<li>第三种模式:“自托管模式(self-hosted)”,它类似于第二种模式,但并非静态Pod。这些Pod对象托管运行在集群自身之上,受控于DaemonSet类型的控制器。</li>
</ul>
<p> </p>
<h1 id="k8s部署方式">k8s部署方式</h1>
<p> </p>
<ul>
<li>
<p><strong>Minikube</strong>:Kubernetes官网提供的微型分布式环境,适合初次学习体验。</p>
</li>
<li>
<p><strong>二进制部署</strong>:相对复杂,生产环境适用,将重要组件以守护进程的方式部署。</p>
</li>
<li>
<p><strong>Kubeadm</strong>:由于二进制部署方式过于复杂,所以后来出现了Kubeadm的部署方式,这种方式其实是将k8s的各组件容器化托管于k8s集群之上。</p>
</li>
<li>
<p>一些云厂商专有的部署方式,如AWS的kops。</p>
</li>
<li>
<p>还有一些二次封装的k8s发行版,如:</p>
<ul>
<li><strong>Rancher</strong>:Rancher Labs基于k8s的二次封装发行版。</li>
<li><strong>Tectonic</strong>:CoreOS公司基于k8s的二次封装发行版。</li>
<li><strong>Openshift</strong>:Redhat基于k8s的二次封装发行版,只留下k8s的成熟功能,部署更加便捷,需要有ansible基础。相比较知名的发行版就是Rancher和Openshift</li>
</ul>
</li>
</ul>
<p> </p>
<h1 id="k8s部署要点">k8s部署要点</h1>
<p> </p>
<ul>
<li>
<p>测试环境</p>
<ul>
<li>单Master节点,单etcd,Node节点随意。</li>
<li>持久化数据可以使用NFS存储。</li>
</ul>
</li>
<li>
<p>生产环境</p>
<ul>
<li>
<p>高可用Master,高可用etcd,至少三个节点。</p>
<ul>
<li>kube-apiserver是无状态的,可以配置多实例。利用nginx或者haproxy做反代,并借助keepalived实现冗余。</li>
<li>kube-scheduler和kube-controller-manager各自只能有一个活动实例(假设多个scheduler同时去调度一个Pod,那听谁的呢?),但是可以建多个实例备用。他们自带leader选举功能,且默认开启此功能。</li>
</ul>
</li>
<li>
<p>多Node主机,数量越多,冗余能力越强。</p>
</li>
<li>
<p>持久化数据使用ceph或glusterfs等分布式存储。</p>
</li>
</ul>
</li>
<li>
<p>环境准备</p>
<ul>
<li>如果有条件,最好搭建一个内网ntp服务,用来同步时间。</li>
<li>配置好各节点间的hosts解析。</li>
<li>禁用防火墙和Selinux,防止混淆。</li>
<li>各节点禁用swap,使用swap虽然暂时能节省一些物理内存,但也会造成性能下降。安装时会自动检查此项,不禁用会导致安装出错,不过也有参数可以忽略。</li>
</ul>
</li>
</ul>
<p> </p>
<h1 id="kubeadm部署k8s">kubeadm部署k8s</h1>
<p> </p>
<ul>
<li><strong>主机规划<font color="#DC143C">(其实2C4G足矣)</font></strong></li>
</ul>
<table>
<thead>
<tr>
<th>主机名</th>
<th>IP</th>
<th>角色</th>
<th>环境</th>
</tr>
</thead>
<tbody>
<tr>
<td>ck-master</td>
<td>192.168.2.24</td>
<td>控制节点</td>
<td>Centos 7.6 4C8G</td>
</tr>
<tr>
<td>ck-node1</td>
<td>192.168.2.25</td>
<td>数据节点</td>
<td>Centos 7.6 4C8G</td>
</tr>
<tr>
<td>ck-node2</td>
<td>192.168.2.26</td>
<td>数据节点</td>
<td>Centos 7.6 4C8G</td>
</tr>
<tr>
<td>ck-node3</td>
<td>192.168.2.27</td>
<td>数据节点</td>
<td>Centos 7.6 4C8G</td>
</tr>
</tbody>
</table>
<p> </p>
<ul>
<li><strong>准备工作<font color="#DC143C">(所有节点操作)</font></strong></li>
</ul>
<ol>
<li>未自行搭建ntp,使用定时任务替代。</li>
</ol>
<pre><code class="language-python"># crontab -l
# time sync
*/1 * * * * /usr/sbin/ntpdate ntp1.aliyun.com &amp;&gt;/dev/null
</code></pre>
<ol start="2">
<li>配置主机名解析</li>
</ol>
<pre><code class="language-python"># tail -4 /etc/hosts
192.168.2.24        ck-master
192.168.2.25        ck-node1
192.168.2.26        ck-node2
192.168.2.27        ck-node3
</code></pre>
<ol start="3">
<li>关闭防火墙和selinux</li>
</ol>
<pre><code class="language-python"># systemctl stop firewalld.service
# systemctl disable firewalld.service
# sed -i.bak 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
# setenforce 0
</code></pre>
<ol start="4">
<li>禁用swap,默认情况下系统的swap都是打开的。</li>
</ol>
<pre><code class="language-python"># swapoff -a
# echo 'swapoff -a' &gt;&gt;/etc/rc.local
</code></pre>
<ol start="5">
<li>配置免密。此步骤可选,我为了拷贝东西方便。</li>
</ol>
<pre><code class="language-python"># yum -y install sshpass
# mkdir -p /server/scripts/
# cd /server/scripts/
# vim batch.sh
#!/bin/bash

rm -rf /root/.ssh/id_dsa*
ssh-keygen -t dsa -f /root/.ssh/id_dsa -P '' -q

for ip in $*
do
sshpass -p 123456 ssh-copy-id -i /root/.ssh/id_dsa.pub -o StrictHostKeyChecking=no 192.168.2.$ip &amp;&gt;/dev/null
echo -e "\n\033[32m-----主机192.168.2.$ip公钥分发完成-----\033[0m\n"
done
# sh batch.sh 25 26 27
# cd
</code></pre>
<p> </p>
<ul>
<li><strong>安装组件<font color="#DC143C">(所有节点操作)</font></strong></li>
</ul>
<ol>
<li>安装docker引擎</li>
</ol>
<pre><code class="language-python"># wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# yum -y install docker-ce
# 配置镜像加速器。如果是中途更换的镜像加速器,需要先systemctl daemon-reload,然后再systemctl restart docker。
# vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://p4y8tfz4.mirror.aliyuncs.com"]
}
# systemctl start docker
# systemctl enable docker
# docker info
# 此Warning如若放任不管,后面集群初始化和node节点加入集群都会报错,我也不知道这两条配置的具体作用,后面会研究一下。
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
# cat &gt; /etc/sysctl.d/kubernetes.conf &lt;&lt; EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
# sysctl -p /etc/sysctl.d/kubernetes.conf
</code></pre>
<ol start="2">
<li>配置k8s的yum仓库,安装kubeadm、kubelet、kubectl组件。</li>
</ol>
<pre><code class="language-python"># cat &gt; /etc/yum.repos.d/kubernetes.repo &lt;&lt; EOF

name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
# 组件的版本要与下面kubernetes初始化时指定的版本保持一致。
# yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0
# systemctl enable kubelet.service
# PS:此处无需启动kubelet,后续将节点join到集群时,会自动拉起。
</code></pre>
<p> </p>
<ul>
<li><strong>k8s集群初始化<font color="#DC143C">(master节点操作)</font></strong></li>
</ul>
<ol>
<li>kubeadm命令说明</li>
</ol>
<pre><code class="language-python"># kubeadm --help
Usage:
kubeadm
Available Commands:
alpha             # 处于测试中不太完善的命令
config            # 显示当前配置
init            # 初始化集群
join            # 各Node节点加入集群中时使用
reset             # 每个节点都可以用,把配置还原到最初始的状态。
upgrade         # 升级集群的版本。
# print参数也是有子命令的,使用下面命令可以查看集群初始化时的预设配置,其中一些与我们真实环境不匹配,可以在初始化时手动指定修改。
# kubeadm config print init-defaults                # 下面只截取部分配置
imageRepository: k8s.gcr.io                        # 默认加载镜像的仓库,需要梯子才能访问,如果知道国内别的仓库有需要的镜像,初始化时可以手动指定仓库地址。
kind: ClusterConfiguration
kubernetesVersion: v1.18.0                        # k8s版本,这是初始化会加载的配置,如果与你预期的版本不符,自行修改。
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12                # Service网络默认网段。
scheduler: {}
# 至于Pod网络间通讯,k8s只提供CNI,真正实现网络通信需要借助第三方插件,如flannel、calico,两者各有优劣。flannel的默认地址是10.244.0.0/16,calico的默认地址是192.168.0.0/16。不使用默认地址也可以,只要保证部署网路插件时yaml中指定的网段与k8s部署时指定的Pod网络网段一致就可。
</code></pre>
<ol start="2">
<li>k8s集群初始化</li>
</ol>
<pre><code class="language-python"># kubeadm init \
--apiserver-advertise-address=192.168.2.24 \                        # kube-apiserver的监听地址。
--image-repository=registry.aliyuncs.com/google_containers \                # 指定init过程中拉取镜像的仓库。
--kubernetes-version=v1.18.0 \                        # 指定kubernetes的版本。
--service-cidr=10.96.0.0/12 \                                # 指定service资源的网段。
--pod-network-cidr=10.244.0.0/16 \                # 指定Pod资源的网段。
--ignore-preflight-errors=all                                # 忽略前置检查中出现的错误,被忽略的错误会显示为警告信息。
# PS:如果初始化过程出错,可以使用kubeadm reset命令删除初始化过程产生的文件,重置到初始状态。上面执行结果会返回一些重要的信息:
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 .yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:                # 运行如下命令将一个节点加入到集群中。

kubeadm join 192.168.2.24:6443 --token s04557.easpgb5aztlba7pd \
    --discovery-token-ca-cert-hash sha256:e91a885d5c6412ca08236697b2b817ceaa4ec61f838439cab9b10ca2081dc117
--------------------------------------------------------------------------------------------------------------
# 上面是命令行的方式初始化,也可以使用配置文件来引导。
# vim kubeadm.conf
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.18.0
imageRepository: registry.aliyuncs.com/google_containers
networking:
podSubnet: 10.244.0.0/16
serviceSubnet: 10.96.0.0/12
# kubeadm init --config kubeadm.conf --ignore-preflight-errors=all
--------------------------------------------------------------------------------------------------------------
# 上面集群初始化返回的结果中有提示建议使用普通用户执行如下命令,此处为了方便就暂时不听从他的建议了^_^。
# mkdir -p $HOME/.kube
# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# chown $(id -u):$(id -g) $HOME/.kube/config                # 管理员下此步骤可省略
</code></pre>
<ol start="3">
<li>查看集群信息。</li>
</ol>
<pre><code class="language-python"># 查看集群健康状态。
# kubectl get cs
NAME               STATUS    MESSAGE             ERROR
scheduler            Healthy   ok                  
controller-manager   Healthy   ok                  
etcd-0               Healthy   {"health":"true"}
# 查看集群版本。
# kubectl version --short
Client Version: v1.18.0
Server Version: v1.18.0
# 查看集群信息。
# kubectl cluster-info
# # kubectl cluster-info dump表示查看集群详细信息。
Kubernetes master is running at https://192.168.2.24:6443
KubeDNS is running at https://192.168.2.24:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.、
# 查看node信息
# kubectl get node
NAME      STATUS   ROLES    AGE   VERSION
ck-master   NotReady   master   47m   v1.18.0
# 上条命令表示master节点是NotReady的,通过看日志发现是缺少网络插件,下面会安装。
# tail -f /var/log/messages
Jul 27 17:29:24 k8s4 kubelet: W0727 17:29:24.559226   10459 cni.go:237] Unable to update cni config: no networks found in /etc/cni/net.d
Jul 27 17:29:27 k8s4 kubelet: E0727 17:29:27.641272   10459 kubelet.go:2187] Container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
# PS:我们能够在master上查看集群信息,主要就是因为家目录下的.kube/config文件(admin.conf),也就是将这个文件拷贝到别的主机后,别的主机也可以使用查看集群的相关信息,并不建议这么做,存在一定的风险性。
</code></pre>
<p> </p>
<ul>
<li><strong>部署calico网络插件<font color="#DC143C">(master节点操作)</font></strong></li>
</ul>
<ol>
<li>上面在集群初始化时指定了Pod网络网段为10.244.0.0/16,calico的默认网段为192.168.0.0/16,所以我们需要先修改下配置文件</li>
</ol>
<pre><code class="language-python"># mkdir /server/k8s
# cd /server/k8s
# wget https://docs.projectcalico.org/manifests/calico.yaml
# vim calico.yaml                # 找到如下两行,取消注释并修改。
            - name: CALICO_IPV4POOL_CIDR
            value: "10.244.0.0/16"
</code></pre>
<ol start="2">
<li>安装calico网络插件。</li>
</ol>
<pre><code class="language-python"># kubectl apply -f calico.yaml
# 然后查看插件安装状态。
# kubectl get pod -n kube-system -w
## -n:指定名称空间
## -w:实时查看pod状态。
## READY状态取决于网速。
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-578894d4cd-bdm4s   1/1   Running   0          3m20s
calico-node-fzwlj                        1/1   Running   0          3m20s
coredns-7ff77c879f-6m9qb                   1/1   Running   0          54m
coredns-7ff77c879f-qc7jx                   1/1   Running   0          54m
etcd-ck-master                           1/1   Running   0          55m
kube-apiserver-ck-master                   1/1   Running   0          55m
kube-controller-manager-ck-master          1/1   Running   0          55m
kube-proxy-8cl6x                           1/1   Running   0          54m
kube-scheduler-ck-master                   1/1   Running   0          55m
# pod全部就绪后,再去看node,已经Ready了。
# kubectl get node
NAME      STATUS   ROLES    AGE   VERSION
ck-master   Ready    master   57m   v1.18.0
</code></pre>
<p> </p>
<ul>
<li><strong>配置Node节点加入到k8s集群<font color="#DC143C">(所有Node节点执行)</font></strong></li>
</ul>
<ol>
<li>根据k8s集群初始化的结果提示,使用如下命令将节点加入到集群中。</li>
</ol>
<pre><code class="language-python"># kubeadm join 192.168.2.24:6443 --token s04557.easpgb5aztlba7pd \
    --discovery-token-ca-cert-hash sha256:e91a885d5c6412ca08236697b2b817ceaa4ec61f838439cab9b10ca2081dc117
</code></pre>
<p> </p>
<ul>
<li><strong>最终验证<font color="#DC143C">(master节点执行)</font></strong></li>
</ul>
<ol>
<li>查看node,全部Ready。</li>
</ol>
<pre><code class="language-python"># kubectl get node
NAME      STATUS   ROLES    AGE   VERSION
ck-master   Ready    master   64m   v1.18.0
ck-node1    Ready    &lt;none&gt;   2m31s   v1.18.0
ck-node2    Ready    &lt;none&gt;   113s    v1.18.0
ck-node3    Ready    &lt;none&gt;   112s    v1.18.0
</code></pre>
<ol start="2">
<li>节点join集群所用的token默认是24小时。</li>
</ol>
<pre><code class="language-python"># kubeadm token list
TOKEN                     TTL         EXPIRES                     USAGES                   DESCRIPTION                                                EXTRA GROUPS
s04557.easpgb5aztlba7pd   22h         2020-07-28T16:41:18+08:00   authentication,signing   The default bootstrap token generated by 'kubeadm init'.   system:bootstrappers:kubeadm:default-node-token
# 如果token过期,可以使用如下命令重新生成token。
# kubeadm token create
W0727 17:52:37.585489    9637 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups
64pxzt.sd7oeubsaz6geu3d
# kubeadm token list
TOKEN                     TTL         EXPIRES                     USAGES                   DESCRIPTION                                                EXTRA GROUPS
64pxzt.sd7oeubsaz6geu3d   23h         2020-07-28T17:52:37+08:00   authentication,signing   &lt;none&gt;                                                   system:bootstrappers:kubeadm:default-node-token
# 如下命令得到CA公钥的hash值
# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2&gt;/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
e91a885d5c6412ca08236697b2b817ceaa4ec61f838439cab9b10ca2081dc117
# 组合得到命令:
kubeadm join 192.168.2.24:6443 --token 64pxzt.sd7oeubsaz6geu3d \
    --discovery-token-ca-cert-hash sha256:e91a885d5c6412ca08236697b2b817ceaa4ec61f838439cab9b10ca2081dc117
</code></pre>
<p> </p>
<h1 id="安装dashboard">安装dashboard</h1>
<ol>
<li>默认dashboard只能集群内部访问,想要外部访问需要修改service为NodePort类型。</li>
</ol>
<pre><code class="language-python"># wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.3/aio/deploy/recommended.yaml
# vim recommended.yaml
spec:
ports:
    - port: 443
      targetPort: 8443
      nodePort: 30001                        # 添加此行,此处端口可用范围为30000-32767。
selector:
    k8s-app: kubernetes-dashboard
type: NodePort                # 添加此行
</code></pre>
<ol start="2">
<li>安装dashboard。</li>
</ol>
<pre><code class="language-shell"># kubectl apply -f recommended.yaml
# kubectl get pod -n kubernetes-dashboard
NAME                                       READY   STATUS    RESTARTS   AGE
dashboard-metrics-scraper-6b4884c9d5-p7tzj   1/1   Running   0          48s
kubernetes-dashboard-7f99b75bf4-62tnf      1/1   Running   0          48s
</code></pre>
<ol start="3">
<li>访问任意节点的IP+30001端口(https)即可访问dashboard。</li>
</ol>
<div align="center">
    <img style="max-width: 80%" src="https://img2020.cnblogs.com/blog/1419513/202007/1419513-20200727181851324-708524849.png">
</div>
<ol start="4">
<li>生成登录token。</li>
</ol>
<pre><code class="language-python">root@ck-master k8s]# kubectl create serviceaccount dashboard-admin -n kube-system
serviceaccount/dashboard-admin created
# kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
clusterrolebinding.rbac.authorization.k8s.io/dashboard-admin created
# kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
</code></pre>
<ol start="5">
<li>登录。</li>
</ol>
<div align="center">
    <img style="max-width: 80%" src="https://img2020.cnblogs.com/blog/1419513/202007/1419513-20200727182336971-515906112.png">
</div>
<ol start="6">
<li>也可以设置为使用账户密码登录dashboard,请自行百度。</li>
</ol>
<p> </p>
<h1 id="安装监控组件">安装监控组件</h1>
<p> </p>
<ol>
<li>默认集群不带监控组件。</li>
</ol>
<pre><code class="language-python"># kubectl top pod
Error from server (NotFound): the server could not find the requested resource (get services http:heapster)
</code></pre>
<ol start="2">
<li>heapster从1.11版本开始逐渐废弃,替代品为新的组件metrics-server。</li>
</ol>
<pre><code class="language-python"># wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.3.7/components.yaml
# vim components.yaml
      containers:
      - name: metrics-server
      image: hamerle/metrics-server:v0.3.7                # 默认的k8s.gcr.io我们是访问不到的,所以我修改为自己的dockerhub。
      imagePullPolicy: IfNotPresent
      args:
          - --cert-dir=/tmp
          - --secure-port=4443
          - --kubelet-insecure-tls                # 设定不验证tls
          - --kubelet-preferred-address-types=InternalIP        # 设定优先使用InternalIP的方式来访问kubelet,这样可以避免节点名称没有DNS解析记录时,通过节点名称调用节点kubelet API失败的情况。
</code></pre>
<ol start="3">
<li>安装组件。</li>
</ol>
<pre><code class="language-python"># kubectl apply -f components.yaml
# kubectl get pods -n kube-system | grep metrics
metrics-server-6c9b6974db-ftmzc            1/1   Running   0          59s
</code></pre>
<ol start="4">
<li>查看各对象的资源使用信息。</li>
</ol>
<pre><code class="language-python"># kubectl top nodes
NAME      CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
ck-master   278m         6%   1905Mi          24%      
ck-node1    160m         4%   906Mi         11%      
ck-node2    142m         3%   904Mi         11%      
ck-node3    149m         3%   902Mi         11%
# kubectl top pods etcd-ck-master -n kube-system
NAME             CPU(cores)   MEMORY(bytes)   
etcd-ck-master   17m          223Mi
</code></pre>
<ol start="5">
<li>安装完监控插件后,dashboard就会展示一些新功能。</li>
</ol>
<div align="center">
    <img style="max-width: 80%" src="https://img2020.cnblogs.com/blog/1419513/202007/1419513-20200728155926745-1759746300.png">
</div>
<p> <br>
 </p>
<p><em><strong>写作不易,转载请注明出处,谢谢~~</strong></em></p><br><br>
来源:https://www.cnblogs.com/ccbloom/p/11320407.html
頁: [1]
查看完整版本: Kubernetes(三):集群部署