kubeadm部署 Kubernetes(k8s) 高可用集群【V1.20 】

kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。
calico.yaml
kubernertes-dashboard.yaml

1. 安装要求

在开始之前,部署Kubernetes集群机器需要满足以下几个条件:

  • 7台机器,操作系统Openeuler22.03 LTS SP4
  • 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多,docker 数据卷单独挂载
  • 集群中所有机器之间网络互通
  • 可以访问外网,需要拉取镜像,【镜像代理自行解决】
  • 禁止swap分区

2. 准备环境


角色IP组件功能描述
Haproxy172.22.33.210Haproxyhaproxy 负载均衡
k8s-master01172.22.33.215docker,cri-dockerd,kube-apiserver,kube-scheduler,kube-controller-manager,etcd,kubelet,kube-proxy,coredns,calicok8s master01节点,etcd01节点
k8s-master02172.22.33.216docker,cri-dockerd,kube-apiserver,kube-scheduler,kube-controller-manager,etcd,kubelet,kube-proxy,calicok8s master02节点,etcd02节点
k8s-master03172.22.33.217docker,cri-dockerd,kube-apiserver,kube-scheduler,kube-controller-manager,etcd,kubelet,kube-proxy,calicok8s master03节点,etcd03节点
k8s-node01172.22.33.218docker,cri-dockerd,kubelet,kube-proxy,coredns,calicok8s-node01 工作节点
k8s-node02172.22.33.219docker,cri-dockerd,kubelet,kube-proxy,coredns,calicok8s-node02 工作节点
k8s-node03172.22.33.220docker,cri-dockerd,kubelet,kube-proxy,coredns,calicok8s-node03工作节点

2.1 环境初始化

K8S 集群服务器 都需要配置

关闭防火墙:
$ systemctl stop firewalld
$ systemctl disable firewalld关闭selinux:
$ sed -i 's/enforcing/disabled/' /etc/selinux/config  # 永久
$ setenforce 0  # 临时关闭swap:[临时和永久关闭]
#临时关闭
$ swapoff -a#永久关闭
$ sed -ri 's/.*swap.*/#&/' /etc/fstab设置主机名:
$ hostnamectl set-hostname k8s-master01
$ hostnamectl set-hostname k8s-master02
$ hostnamectl set-hostname k8s-master03
$ hostnamectl set-hostname k8s-node01
$ hostnamectl set-hostname k8s-node02
$ hostnamectl set-hostname k8s-node03#在K8S上所有节点添加hosts:
$ cat >> /etc/hosts << EOF
172.22.33.215 k8s-master01
172.22.33.216 k8s-master02
172.22.33.217 k8s-master03
172.22.33.218 k8s-node01
172.22.33.219 k8s-node02
172.22.33.220 k8s-node03
EOF#开启内核路由转发
sed -i 's/net.ipv4.ip_forward=0/net.ipv4.ip_forward=1/g' /etc/sysctl.conf#将桥接的IPv4,IPV6流量传递到iptables的链:
$ cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
vm.swappiness = 0
EOF# 生效
$ sysctl --system#每个节点都需要安装 IPVS 的相关工具和加载ipvs内核模块
$ yum install ipvsadm#在所有节点执行以下命令
$ cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF$ chmod 755 /etc/sysconfig/modules/ipvs.modules
$ bash /etc/sysconfig/modules/ipvs.modules#查看IPVS模块加载情况
$ lsmod | grep -e ip_vs -e nf_conntrack_ipv4
#能看到ip_vs ip_vs_rr ip_vs_wrr  ip_vs_sh nf_conntrack_ipv4  加载成功时间同步:
$ yum install ntpdate -y
$ ntpdate ntp.ntsc.ac.cn

3. 安装Docker/kubeadm/kubelet/kubectl

在所有K8S 集群的节点上,执行

3.1.1 docker二进制包下载

docker-ce 社区下载地址:

$ wget https://mirrors.nju.edu.cn/docker-ce/linux/static/stable/x86_64/docker-20.10.24.tgz

3.1.2 解压,拷贝至/usr/bin 下

$ tar -xf docker-20.10.24.tgz
$ cp docker/* /usr/bin
$ which docker

3.1.3 编写docker.service文件

$ cat > /etc/systemd/system/docker.service <<EOF[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=65535
LimitNPROC=65535
LimitCORE=65535
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s[Install]
WantedBy=multi-user.targetEOF

3.1.4 挂载docker默认存储路径[可选]

docker的默认工作路径在/var/lib/docker ,最好不修改默认存储路径,可以做软链接

#建立工作目录
$ mkdir /home/application/#格式化磁盘
$ mkfs.ext4 /dev/sdb#磁盘永久挂载
$ vim /etc/fstab
/dev/sdb  /home/application  ext4 defaults 0 0#使挂载生效
$ mount -a# 创建docker 工作目录
$ mkdir /home/application/docker#创建软链接
$ ln -s /home/application/docker /var/lib/

3.1.5 添加可执行权限

$ chmod +x /etc/systemd/system/docker.service

3.1.6 启动,加载,开机自启动

$ systemctl daemon-reload
$ systemctl start docker.service
$ systemctl enable docker.service

3.1.7 配置镜像加速器

$ mkdir -p /etc/docker
$ tee /etc/docker/daemon.json <<-'EOF'
{"registry-mirrors": ["https://docker.srebro.cn"],"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF$ systemctl daemon-reload
$ systemctl restart docker

⚠️tips:
如果仓库不是https 的,需要在 /etc/docker/daemon.json 中 添加忽略;比如下方的示例

"insecure-registries": ["https://harbor.srebro.cn","https://it-docker.pkg.devops.com"]

3.2.1 添加阿里云YUM软件源

$ cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
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

3.2.2 安装kubeadm,kubelet和kubectl

由于版本更新频繁,这里指定版本号部署:

# 查看所有的可用版本
$ yum list  kubeadm  kubelet kubectl --showduplicates | sort -r#在所有节点安装
$ yum install -y kubelet-1.20.15 kubeadm-1.20.15 kubectl-1.20.15$ systemctl enable kubelet

4. 部署Haproxy负载均衡

4.1 yum安装haproxy

在172.22.33.210 服务器上部署

yum  -y install haproxy

4.2 修改配置文件

$ cat > /etc/haproxy/haproxy.cfg << EOF
globallog /dev/log  local0 warningchroot      /var/lib/haproxypidfile     /var/run/haproxy.pidmaxconn     4000user        haproxygroup       haproxydaemonstats socket /var/lib/haproxy/stats
defaultslog globaloption  httplogoption  dontlognulltimeout connect 5000timeout client 50000timeout server 50000#frontend monitor-in#bind *:33305#mode http#option httplog#monitor-uri /monitorfrontend kube-apiserverbind *:36443mode tcpoption tcplogdefault_backend kube-apiserverbackend kube-apiservermode tcpoption tcplogoption tcp-checkbalance roundrobindefault-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100server kube-apiserver-1 172.22.33.215:6443 check # Replace the IP address with your own.server kube-apiserver-2 172.22.33.216:6443 check # Replace the IP address with your own.server kube-apiserver-3 172.22.33.217:6443 check # Replace the IP address with your own.
EOF

4.3 启动Haproxy

$ systemctl enable haproxy
$ systemctl start haproxy

6. 部署Kubernetes Master

官方kubeadm 初始化说明:

  • https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-init/#config-file

  • https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#initializing-your-control-plane-node

6.1 准备好kubeadm-init.yaml初始化文件

6.1.1 kubeadm 初始化

⚠️ kubeadm-init.yam K8S 版本 <= 1.20

#在每个master 节点创建K8S,init 的工作目录
$ mkdir -p /etc/kubernetes/init$ cat >> etc/kubernetes/init/kubeadm-init.yaml << EOF
---
apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:- system:bootstrappers:kubeadm:default-node-tokentoken: 35sesk.5tm3tqc66tzlse8cttl: 24h0m0susages:- signing- authentication
kind: InitConfiguration
localAPIEndpoint:advertiseAddress: 172.22.33.215     #指定master01 ip地址bindPort: 6443
nodeRegistration:criSocket: /var/run/dockershim.sockname: k8s-master01                  #指定master01主机名taints:- effect: NoSchedulekey: node-role.kubernetes.io/master
---
apiServer:certSANs:- "kubernetes"- "kubernetes.default"- "kubernetes.default.svc"- "kubernetes.default.svc.cluster.local"- "172.22.33.210"         #填写所有master节点IP,VIP, 以及公网IP,域名- "172.22.33.215"- "172.22.33.216"- "172.22.33.217"- "112.94.71.21"- "k8s.srebro.cn"timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
controlPlaneEndpoint: "172.22.33.210:36443"   #增加kubeapiserver集群ip地址和端口,就是VIP
dns:type: CoreDNS
etcd:local:dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.20.15
networking:dnsDomain: cluster.localserviceSubnet: 10.96.0.0/12podSubnet: 10.244.0.0/16
scheduler: {}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
EOF

6.2 在所有master 节点上,pull 镜像到本地

init 之前,先下载镜像到master 机器上

#k8s-master01 节点上
$ kubeadm config images pull --config kubeadm-init.yaml[config/images] Pulled registry.aliyuncs.com/google_containers/kube-apiserver:v1.20.15
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-controller-manager:v1.20.15
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-scheduler:v1.20.15
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-proxy:v1.20.15
[config/images] Pulled registry.aliyuncs.com/google_containers/pause:3.2
[config/images] Pulled registry.aliyuncs.com/google_containers/etcd:3.4.13-0
[config/images] Pulled registry.aliyuncs.com/google_containers/coredns:1.7.0#k8s-master02 节点上
$ kubeadm config images pull --config kubeadm-init.yaml[config/images] Pulled registry.aliyuncs.com/google_containers/kube-apiserver:v1.20.15
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-controller-manager:v1.20.15
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-scheduler:v1.20.15
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-proxy:v1.20.15
[config/images] Pulled registry.aliyuncs.com/google_containers/pause:3.2
[config/images] Pulled registry.aliyuncs.com/google_containers/etcd:3.4.13-0
[config/images] Pulled registry.aliyuncs.com/google_containers/coredns:1.7.0#k8s-master03 节点上
$ kubeadm config images pull --config kubeadm-init.yaml[config/images] Pulled registry.aliyuncs.com/google_containers/kube-apiserver:v1.20.15
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-controller-manager:v1.20.15
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-scheduler:v1.20.15
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-proxy:v1.20.15
[config/images] Pulled registry.aliyuncs.com/google_containers/pause:3.2
[config/images] Pulled registry.aliyuncs.com/google_containers/etcd:3.4.13-0
[config/images] Pulled registry.aliyuncs.com/google_containers/coredns:1.7.0

6.3 在master01 节点上,完成kubeadm 初始化

$ cd /etc/kubernetes/init
$ kubeadm init --config kubeadm-init.yaml[init] Using Kubernetes version: v1.20.15
[preflight] Running pre-flight checks[WARNING SystemVerification]: this Docker version is not on the list of validated versions: 20.10.18. Latest validated version: 19.03
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [k8s-master01 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 172.22.33.215 172.22.33.216 172.22.33.217 218.94.71.250]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [k8s-master01 localhost] and IPs [172.22.33.215 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [k8s-master01 localhost] and IPs [172.22.33.215 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 13.003320 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.20" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node k8s-master01 as control-plane by adding the labels "node-role.kubernetes.io/master=''" and "node-role.kubernetes.io/control-plane='' (deprecated)"
[mark-control-plane] Marking the node k8s-master01 as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: abcdef.0123456789abcdef
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
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/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:export KUBECONFIG=/etc/kubernetes/admin.conf
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 172.22.33.210:36443 --token abcdef.0123456789abcdef \--discovery-token-ca-cert-hash sha256:1105970dfcca841937c09964e46f3fa14a53672105462e50108d95279ed5dc7c \--control-plane Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 172.22.33.210:36443 --token abcdef.0123456789abcdef \--discovery-token-ca-cert-hash sha256:1105970dfcca841937c09964e46f3fa14a53672105462e50108d95279ed5dc7c 

拷贝kubectl使用的连接k8s认证文件到默认路径

$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

6.4 加入 Kubernetes Master 节点

因为我们的K8S集群已经初始化过了,再添加其他master 节点到集群中,首要添加是把已经初始化过的证书拷贝到其他master 节点上

6.4.1 在master02和master03节点复制相关证书
#创建K8S证书工作目录
$ mkdir -p /etc/kubernetes/pki/
$ scp -r 172.22.33.215:/etc/kubernetes/pki/ca.* /etc/kubernetes/pki/
$ scp -r 172.22.33.215:/etc/kubernetes/pki/sa.* /etc/kubernetes/pki/
$ scp -r 172.22.33.215:/etc/kubernetes/pki/front-proxy-ca.* /etc/kubernetes/pki/#创建ETCD证书工作目录
$ mkdir -p /etc/kubernetes/pki/etcd
$ scp -r 172.22.33.215:/etc/kubernetes/pki/etcd/ca.* /etc/kubernetes/pki/etcd/#拷贝kube-admin.conf 文件
$ scp -r 172.22.33.215:/etc/kubernetes/admin.conf /etc/kubernetes/
6.4.2 把 master02和master03节点 添加到Kubernetes 集群中

使用刚刚 master01 在kubeadm init输出的kubeadm join命令:

#加入控制平面
$  kubeadm join 172.22.33.210:36443 --token abcdef.0123456789abcdef \--discovery-token-ca-cert-hash sha256:1105970dfcca841937c09964e46f3fa14a53672105462e50108d95279ed5dc7c \--control-plane 
6.4.3 在master01节点上查看master节点个数
$ kubectl get node
NAME           STATUS     ROLES                  AGE     VERSION
k8s-master01   NotReady   control-plane,master   8m26s   v1.20.15
k8s-master02   NotReady   control-plane,master   2m54s   v1.20.15
k8s-master03   NotReady   control-plane,master   59s     v1.20.15

可以看到,所有的master 节点都已经加入到集群中了;NotReady是需要等待CNI网络插件安装好

7. 加入Kubernetes Node 节点

  • 官方文档: https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-join/

在K8S node 节点上操作

k8s-node01172.22.33.218
k8s-node02172.22.33.219
k8s-node03172.22.33.220

使用刚刚master01 在kubeadm init输出的kubeadm join命令:

$ kubeadm join 172.22.33.210:36443 --token abcdef.0123456789abcdef \--discovery-token-ca-cert-hash sha256:1105970dfcca841937c09964e46f3fa14a53672105462e50108d95279ed5dc7c

默认token有效期为24小时,当过期之后,该token就不可用了。这时就需要重新创建token,可以直接在master 节点上,使用命令快捷生成:

$ kubeadm token create --print-join-command

8. 部署容器网络(CNI)

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#pod-network
:::danger
注意:只需要部署下面其中一个,推荐Calico。
Calico是一个纯三层的数据中心网络方案,Calico支持广泛的平台,包括Kubernetes、OpenStack等。
Calico 在每一个计算节点利用 Linux Kernel 实现了一个高效的虚拟路由器( vRouter) 来负责数据转发,而每个 vRouter 通过 BGP 协议负责把自己上运行的 workload 的路由信息向整个 Calico 网络内传播。
此外,Calico 项目还实现了 Kubernetes 网络策略,提供ACL功能。
https://docs.projectcalico.org/getting-started/kubernetes/quickstart
K8S版本和calico 版本的对应关系
参考链接:https://blog.csdn.net/qq_32596527/article/details/127692734
:::

$ wget https://projectcalico.docs.tigera.io/archive/v3.21/manifests/calico.yaml

下载完后还需要修改里面定义Pod网络(CALICO_IPV4POOL_CIDR),与前面kubeadm init指定的
--pod-network-cidr=10.244.0.0/16 保持一致; 默认是 192.168.0.0/16

- name: CALICO_IPV4POOL_CIDRvalue: "10.244.0.0/16"


修改完后应用清单:

$ kubectl apply -f calico.yaml
$ kubectl get pods -n kube-system

查看所有节点,以及pod,svc情况

$ kubectl get nodes
NAME           STATUS   ROLES                  AGE   VERSION
k8s-master01   Ready    control-plane,master   70m   v1.20.15
k8s-master02   Ready    control-plane,master   64m   v1.20.15
k8s-master03   Ready    control-plane,master   62m   v1.20.15
k8s-node01     Ready    <none>                 46m   v1.20.15
k8s-node02     Ready    <none>                 46m   v1.20.15
k8s-node03     Ready    <none>                 46m   v1.20.15
[root@openeuler ~]# kubectl get all -A
NAMESPACE     NAME                                           READY   STATUS    RESTARTS   AGE
default       pod/my-web-6b6c9df775-2p67z                    1/1     Running   0          45m
default       pod/my-web-6b6c9df775-76f8w                    1/1     Running   0          45m
default       pod/my-web-6b6c9df775-t2zrm                    1/1     Running   0          45m
default       pod/my-web-6b6c9df775-zs6db                    1/1     Running   0          45m
kube-system   pod/calico-kube-controllers-5bb48c55fd-vvktf   1/1     Running   0          52m
kube-system   pod/calico-node-7ng4l                          1/1     Running   0          52m
kube-system   pod/calico-node-lrf24                          1/1     Running   0          47m
kube-system   pod/calico-node-qxnxg                          1/1     Running   0          52m
kube-system   pod/calico-node-vwjt4                          1/1     Running   0          52m
kube-system   pod/coredns-7f89b7bc75-cc6gn                   1/1     Running   0          70m
kube-system   pod/coredns-7f89b7bc75-wsg29                   1/1     Running   0          70m
kube-system   pod/etcd-k8s-master01                          1/1     Running   0          70m
kube-system   pod/etcd-k8s-master02                          1/1     Running   0          65m
kube-system   pod/etcd-k8s-master03                          1/1     Running   0          62m
kube-system   pod/kube-apiserver-k8s-master01                1/1     Running   0          70m
kube-system   pod/kube-apiserver-k8s-master02                1/1     Running   0          65m
kube-system   pod/kube-apiserver-k8s-master03                1/1     Running   0          62m
kube-system   pod/kube-controller-manager-k8s-master01       1/1     Running   1          70m
kube-system   pod/kube-controller-manager-k8s-master02       1/1     Running   0          65m
kube-system   pod/kube-controller-manager-k8s-master03       1/1     Running   0          62m
kube-system   pod/kube-proxy-ck9lr                           1/1     Running   0          63m
kube-system   pod/kube-proxy-vzrs8                           1/1     Running   0          65m
kube-system   pod/kube-proxy-wxb78                           1/1     Running   0          70m
kube-system   pod/kube-proxy-z5chd                           1/1     Running   0          47m
kube-system   pod/kube-scheduler-k8s-master01                1/1     Running   1          70m
kube-system   pod/kube-scheduler-k8s-master02                1/1     Running   0          65m
kube-system   pod/kube-scheduler-k8s-master03                1/1     Running   0          62mNAMESPACE     NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
default       service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP                  70m
kube-system   service/kube-dns     ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   70mNAMESPACE     NAME                         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
kube-system   daemonset.apps/calico-node   4         4         4       4            4           kubernetes.io/os=linux   52m
kube-system   daemonset.apps/kube-proxy    4         4         4       4            4           kubernetes.io/os=linux   70mNAMESPACE     NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
default       deployment.apps/my-web                    4/4     4            4           45m
kube-system   deployment.apps/calico-kube-controllers   1/1     1            1           52m
kube-system   deployment.apps/coredns                   2/2     2            2           70mNAMESPACE     NAME                                                 DESIRED   CURRENT   READY   AGE
default       replicaset.apps/my-web-6b6c9df775                    4         4         4       45m
kube-system   replicaset.apps/calico-kube-controllers-5bb48c55fd   1         1         1       52m
kube-system   replicaset.apps/coredns-7f89b7bc75                   2         2         2       70m

9. 测试kubernetes集群

  • 验证Pod工作
  • 验证Pod网络通信
  • 验证DNS解析

在Kubernetes集群中创建一个pod,验证是否正常运行:

$ kubectl create deployment nginx --image=nginx
$ kubectl expose deployment nginx --port=80 --type=NodePort
$ kubectl get pod,svc

访问地址:http://NodeIP:Port

10. 部署 Dashboard[可选]

$ wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.3/aio/deploy/recommended.yaml

默认Dashboard只能集群内部访问,修改Service为NodePort类型,暴露到外部:

$ vi recommended.yaml
...
kind: Service
apiVersion: v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kubernetes-dashboard
spec:ports:- port: 443targetPort: 8443nodePort: 30001selector:k8s-app: kubernetes-dashboardtype: NodePort
...$ kubectl apply -f recommended.yaml
$ kubectl get pods -n kubernetes-dashboard
NAME                                         READY   STATUS    RESTARTS   AGE
dashboard-metrics-scraper-6b4884c9d5-gl8nr   1/1     Running   0          13m
kubernetes-dashboard-7f99b75bf4-89cds        1/1     Running   0          13m

访问地址:https://NodeIP:30001
创建service account并绑定默认cluster-admin管理员集群角色:

# 创建用户
$ kubectl create serviceaccount dashboard-admin -n kube-system
# 用户授权
$ kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
# 获取用户Token
$ kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')

使用输出的token登录Dashboard。

11. 补充

11.1 将节点上的容器运行时从 Docker Engine 改为 containerd

官网参考:https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/migrating-from-dockershim/change-runtime-containerd/
1、配置先决条件【上面环境初始化的时候如果做过了,直接忽略】

$ cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF$ sudo modprobe overlay
$ sudo modprobe br_netfilter# 设置必需的 sysctl 参数,这些参数在重新启动后仍然存在。
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF# Apply sysctl params without reboot
$ sudo sysctl --system

2、下线节点

<node-to-drain> 替换为你所要下线的节点的名称

kubectl drain <node-to-drain> --ignore-daemonsets

3、停止 Docker 守护进程

systemctl stop kubelet
systemctl disable docker.service --now

4、二进制安装containerd

$ wget https://github.com/containerd/containerd/releases/download/v1.7.20/containerd-1.7.20-linux-amd64.tar.gz
$ tar -xf containerd-1.7.20-linux-amd64.tar.gz#复制bin下所有二进制文件到/usr/bin 目录下,并覆盖之前的文件
$ cp bin/* /usr/bin/
cp:是否覆盖'/usr/bin/containerd'? y
cp:是否覆盖'/usr/bin/containerd-shim'? y
cp:是否覆盖'/usr/bin/containerd-shim-runc-v2'? y
cp:是否覆盖'/usr/bin/ctr'? y#验证containerd的版本
$ containerd --version
containerd github.com/containerd/containerd v1.7.20 8fc6bcff51318944179630522a095cc9dbf9f353#创建containerd 配置文件
$ mkdir -p /etc/containerd#也可以使用生成的默认配置
$ containerd config default | sudo tee /etc/containerd/config.toml

修改containerd配置文件

$ cat > /etc/containerd/config.toml << EOF
disabled_plugins = []
imports = []
oom_score = 0
plugin_dir = ""
required_plugins = []
root = "/var/lib/containerd"
state = "/run/containerd"
temp = ""
version = 2[cgroup]path = ""[debug]address = ""format = ""gid = 0level = ""uid = 0[grpc]address = "/run/containerd/containerd.sock"gid = 0max_recv_message_size = 16777216max_send_message_size = 16777216tcp_address = ""tcp_tls_ca = ""tcp_tls_cert = ""tcp_tls_key = ""uid = 0[metrics]address = ""grpc_histogram = false[plugins][plugins."io.containerd.gc.v1.scheduler"]deletion_threshold = 0mutation_threshold = 100pause_threshold = 0.02schedule_delay = "0s"startup_delay = "100ms"[plugins."io.containerd.grpc.v1.cri"]device_ownership_from_security_context = falsedisable_apparmor = falsedisable_cgroup = falsedisable_hugetlb_controller = truedisable_proc_mount = falsedisable_tcp_service = trueenable_selinux = falseenable_tls_streaming = falseenable_unprivileged_icmp = falseenable_unprivileged_ports = falseignore_image_defined_volumes = falsemax_concurrent_downloads = 3max_container_log_line_size = 16384netns_mounts_under_state_dir = falserestrict_oom_score_adj = falsesandbox_image = "registry.aliyuncs.com/google_containers/pause:3.6"selinux_category_range = 1024stats_collect_period = 10stream_idle_timeout = "4h0m0s"stream_server_address = "127.0.0.1"stream_server_port = "0"systemd_cgroup = falsetolerate_missing_hugetlb_controller = trueunset_seccomp_profile = ""[plugins."io.containerd.grpc.v1.cri".cni]bin_dir = "/opt/cni/bin"conf_dir = "/etc/cni/net.d"conf_template = ""ip_pref = ""max_conf_num = 1[plugins."io.containerd.grpc.v1.cri".containerd]default_runtime_name = "runc"disable_snapshot_annotations = truediscard_unpacked_layers = falseignore_rdt_not_enabled_errors = falseno_pivot = falsesnapshotter = "overlayfs"[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]base_runtime_spec = ""cni_conf_dir = ""cni_max_conf_num = 0container_annotations = []pod_annotations = []privileged_without_host_devices = falseruntime_engine = ""runtime_path = ""runtime_root = ""runtime_type = ""[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime.options][plugins."io.containerd.grpc.v1.cri".containerd.runtimes][plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]base_runtime_spec = ""cni_conf_dir = ""cni_max_conf_num = 0container_annotations = []pod_annotations = []privileged_without_host_devices = falseruntime_engine = ""runtime_path = ""runtime_root = ""runtime_type = "io.containerd.runc.v2"[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]BinaryName = ""CriuImagePath = ""CriuPath = ""CriuWorkPath = ""IoGid = 0IoUid = 0NoNewKeyring = falseNoPivotRoot = falseRoot = ""ShimCgroup = ""SystemdCgroup = true[plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime]base_runtime_spec = ""cni_conf_dir = ""cni_max_conf_num = 0container_annotations = []pod_annotations = []privileged_without_host_devices = falseruntime_engine = ""runtime_path = ""runtime_root = ""runtime_type = ""[plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime.options][plugins."io.containerd.grpc.v1.cri".image_decryption]key_model = "node"[plugins."io.containerd.grpc.v1.cri".registry]config_path = ""[plugins."io.containerd.grpc.v1.cri".registry.auths][plugins."io.containerd.grpc.v1.cri".registry.configs][plugins."io.containerd.grpc.v1.cri".registry.headers][plugins."io.containerd.grpc.v1.cri".registry.mirrors][plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]endpoint = ["https://docker.srebro.site"][plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"]endpoint = ["https://gcr.srebro.site"][plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]endpoint = ["https://k8s-gcr.srebro.site"][plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"]endpoint = ["https://quay.srebro.site"][plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming]tls_cert_file = ""tls_key_file = ""[plugins."io.containerd.internal.v1.opt"]path = "/opt/containerd"[plugins."io.containerd.internal.v1.restart"]interval = "10s"[plugins."io.containerd.internal.v1.tracing"]sampling_ratio = 1.0service_name = "containerd"[plugins."io.containerd.metadata.v1.bolt"]content_sharing_policy = "shared"[plugins."io.containerd.monitor.v1.cgroups"]no_prometheus = false[plugins."io.containerd.runtime.v1.linux"]no_shim = falseruntime = "runc"runtime_root = ""shim = "containerd-shim"shim_debug = false[plugins."io.containerd.runtime.v2.task"]platforms = ["linux/amd64"]sched_core = false[plugins."io.containerd.service.v1.diff-service"]default = ["walking"][plugins."io.containerd.service.v1.tasks-service"]rdt_config_file = ""[plugins."io.containerd.snapshotter.v1.aufs"]root_path = ""[plugins."io.containerd.snapshotter.v1.btrfs"]root_path = ""[plugins."io.containerd.snapshotter.v1.devmapper"]async_remove = falsebase_image_size = ""discard_blocks = falsefs_options = ""fs_type = ""pool_name = ""root_path = ""[plugins."io.containerd.snapshotter.v1.native"]root_path = ""[plugins."io.containerd.snapshotter.v1.overlayfs"]root_path = ""upperdir_label = false[plugins."io.containerd.snapshotter.v1.zfs"]root_path = ""[plugins."io.containerd.tracing.processor.v1.otlp"]endpoint = ""insecure = falseprotocol = ""[proxy_plugins][stream_processors][stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]path = "ctd-decoder"returns = "application/vnd.oci.image.layer.v1.tar"[stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]path = "ctd-decoder"returns = "application/vnd.oci.image.layer.v1.tar+gzip"[timeouts]"io.containerd.timeout.bolt.open" = "0s""io.containerd.timeout.shim.cleanup" = "5s""io.containerd.timeout.shim.load" = "5s""io.containerd.timeout.shim.shutdown" = "3s""io.containerd.timeout.task.state" = "2s"[ttrpc]address = ""gid = 0uid = 0
EOF

使用systemd管理containerd ,并启动

$ cat > /etc/systemd/system/containerd.service << EOF[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target[Service]
ExecStart=/usr/bin/containerd
Restart=always
RestartSec=5
Delegate=yes
KillMode=process
OOMScoreAdjust=-999[Install]
WantedBy=multi-user.target
EOF$ systemctl daemon-reload
$ systemctl enable containerd
$ systemctl restart containerd

5、配置kubelet使用containerd并重启kubelet

$ vim /etc/sysconfig/kubelet 
KUBELET_EXTRA_ARGS=--container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --cgroup-driver=systemd$ systemctl restart kubelet

6、验证节点处于健康状态

# 会显示出containerd版本,健康状态
$ kubectl get nodes -o wide
NAME         STATUS   ROLES                  AGE     VERSION    INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                    KERNEL-VERSION                        CONTAINER-RUNTIME
k8s-master   Ready    control-plane,master   7d21h   v1.20.15   172.22.33.210   <none>        openEuler 22.03 (LTS-SP4)   5.10.0-221.0.0.124.oe2203sp3.x86_64   containerd://1.7.20
k8s-node1    Ready,SchedulingDisabled    <none>                 7d21h   v1.20.15   172.22.33.211   <none>        openEuler 22.03 (LTS-SP4)   5.10.0-221.0.0.124.oe2203sp3.x86_64   containerd://1.7.20
k8s-node2    Ready    <none>                 7d21h   v1.20.15   172.22.33.212   <none>        openEuler 22.03 (LTS-SP4)   5.10.0-221.0.0.124.oe2203sp3.x86_64   containerd://1.7.20
k8s-node3    Ready    <none>                 6d22h   v1.20.15   172.22.33.213   <none>        openEuler 22.03 (LTS-SP4)   5.10.0-221.0.0.124.oe2203sp3.x86_64   containerd://1.7.20

7、uncordon 节点

<node-to-uncordon> 替换为你之前下线的节点的名称。

$ kubectl uncordon <node-to-uncordon>

8、再次验证

[root@k8s-master bin]# kubectl get nodes -o wide
NAME         STATUS   ROLES                  AGE     VERSION    INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                    KERNEL-VERSION                        CONTAINER-RUNTIME
k8s-master   Ready    control-plane,master   7d21h   v1.20.15   172.22.33.210   <none>        openEuler 22.03 (LTS-SP4)   5.10.0-221.0.0.124.oe2203sp3.x86_64   containerd://1.7.20
k8s-node1    Ready    <none>                 7d21h   v1.20.15   172.22.33.211   <none>        openEuler 22.03 (LTS-SP4)   5.10.0-221.0.0.124.oe2203sp3.x86_64   containerd://1.7.20
k8s-node2    Ready    <none>                 7d21h   v1.20.15   172.22.33.212   <none>        openEuler 22.03 (LTS-SP4)   5.10.0-221.0.0.124.oe2203sp3.x86_64   containerd://1.7.20
k8s-node3    Ready    <none>                 6d22h   v1.20.15   172.22.33.213   <none>        openEuler 22.03 (LTS-SP4)   5.10.0-221.0.0.124.oe2203sp3.x86_64   docker://20.10.18

11.2 kubectl 命令补齐

$ yum install bash-completion -y
$ source /usr/share/bash-completion/bash_completion
$ source <(kubectl completion bash)
$ kubectl completion bash >/etc/bash_completion.d/kubectl

本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 运维小弟

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/415296.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通义千问AI PPT初体验:一句话、万字文档、长文本一键生成PPT!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;专注于分享AI全维度知识&#xff0c;包括但不限于AI科普&#xff0c;AI工…

笔记:《利用Python进行数据分析》之透视表和交叉表

透视表和交叉表 透视表&#xff08;pivot table&#xff09;是各种电子表格程序和其他数据分析软件中一种常见的数据汇总工具。它根据一个或多个键对数据进行聚合&#xff0c;并根据行和列上的分组键将数据分配到各个矩形区域中。在Python和pandas中&#xff0c;可以通过本章所…

黑悟空!一区预定!原创首发!SLWCHOA-Transformer-LSTM混合改进策略的黑猩猩优化算法多变量时间序列预测

黑悟空&#xff01;一区预定&#xff01;原创首发&#xff01;SLWCHOA-Transformer-LSTM混合改进策略的黑猩猩优化算法多变量时间序列预测 目录 黑悟空&#xff01;一区预定&#xff01;原创首发&#xff01;SLWCHOA-Transformer-LSTM混合改进策略的黑猩猩优化算法多变量时间序…

前缀和专题——一维模版+二维模版力扣实战应用

目录 1、模版 1.1【模版】一维前缀和 1.1.1 算法思想 1.1.2 算法代码 1.2【模版】二维前缀和 1.2.1 算法思想 1.2.2 算法代码 2、算法应用【leetcode】 2.1 题一&#xff1a;寻找数组的中心下标 2.1.1 算法思想 2.1.2 算法代码 2.2 题二&#xff1a;除自身以外数组…

聚观早报 | 理想汽车OTA 6.2发布;京东大幅上调校招薪资

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 9月3日消息 理想汽车OTA 6.2发布 京东大幅上调校招薪资 哪吒汽车8月销量持续破万 C919国产大飞机首航在即 现代…

怎么找TikTok代运营助力?灵感魔方怎么样?

在当今全球化的浪潮中&#xff0c;海外版抖音已然成为了品牌出海的重要阵地。然而&#xff0c;面对这个充满机遇与挑战的平台&#xff0c;如何找到专业的TikTok代运营团队来助力品牌成功出海呢&#xff1f;以下是一些关键的考量因素和方法。 首先&#xff0c;专业的TikTok代运…

【机器学习】图像处理与深度学习利器:OpenCV实战攻略全面解析

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 前言 OpenCV想必大家都听过跨平台计算机视觉库&#xff0c;可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而…

巴黎奥运会引发体育健身热潮:气膜体育馆成为新宠—轻空间

随着巴黎奥运会的成功举办&#xff0c;全球范围内掀起了一股体育健身的热潮。各地的健身场所迎来了前所未有的参与热情&#xff0c;其中&#xff0c;融合了体育、娱乐、休闲等多种业态的综合气膜体育馆因其独特的优势&#xff0c;迅速成为群众健身的新宠&#xff0c;成为了大众…

视频搬运的素材网站有哪些?打包好的视频素材在哪找?

探索短视频创作世界时&#xff0c;是不是经常碰到缺乏素材的难题&#xff1f;无需担心&#xff0c;今天我们来聊聊一些能够即刻丰富你视频内容的素材网站。无论是搬运视频还是寻找灵感&#xff0c;这些资源站都将为你的创作锦上添花。特别强调的是&#xff0c;除了国际上的珍贵…

小土堆pytorch

anaconda安装 pip list 可以看有哪些package包 nvidia-smi查看显卡的状态 安装pytorch 检验pytorch是否安装成功&#xff0c;以及是否pytorch是否可以使用gpu。 (1)查看conda版本 conda --version 或 conda -V (2)更新conda&#xff08;将conda自身更新到最新版本&#xff09; …

sqlite数据插入效率

一、程序效率测试 时间相关接口&#xff1a; int gettimeofday(struct timeval*tv, struct timezone *tz); 功能&#xff1a;得到从1970年1月1日0时0分0秒到现在的秒数。<可以利用该函数来计算一个程序的运行时间&#xff0c;只需在程序前后调用该函数&#xff0c;…

计算机网络概述(分组延时、丢失和吞吐量)

目录 分组丢失和延时是怎样发生的&#xff1f; 四种分组延时 节点延时 排队延迟 分组丢失 吞吐量 吞吐量&#xff1a;互联网场景 分组丢失和延时是怎样发生的&#xff1f; 在路由器缓冲区的分组队列 分组到达链路的速率超过了链路输出的能力分组等待排队到队头、被传输…

基于.NET6的WPF基础总结(上)

目录 一.常用属性介绍 二、 程序退出方式 三、布局样式 3.1 Panel的附加属性ZIndex 3.2 Grid(网格)布局 3.3 UniformGrid&#xff08;均分布局&#xff09; 3.4 StackPanel&#xff08;堆积面板&#xff09; 3.5 WrapPanel&#xff08;换行面板&#xff09; 3.6 Doc…

什么是I2C总线?

1.什么是I2C&#xff1f; 1.1 I2C的由来 在电视机内部电路中&#xff0c;众多功能需要用到许多集成电路IC来实现&#xff0c;包括主控器件微控制器和众多外围设备器件。这些器件相互之间要传递数据信息&#xff0c;那么就需要用导线相互连接&#xff0c;如此众多IC器件的互连&…

linux下cpu多核运行程序以及运行时间统计

一、多核心运行程序 在linux下我们可以指定线程或者进程运行在指定的cpu核心上&#xff0c;操作方法如下&#xff1a; 1&#xff09;运行进程指定cpu核心 taskset -c 2 ./app //-c指定运行的cpu核心号&#xff0c;从0计数&#xff0c;查看效果如下&#xff1a; 2&#xff09…

两句话讲清楚离线安装docker镜像

两句话讲清楚离线安装docker镜像 文章目录 两句话讲清楚离线安装docker镜像写在前面解决方案 写在前面 背景&#xff1a;银河麒麟、离线环境&#xff0c;装吧&#xff0c;一装一个不吱声。 准备&#xff1a; 首先&#xff0c;你要有个docker&#xff0c;安装好了才能搞镜像是不…

C++:构造函数与析构函数

一.类的默认成员函数 默认成员函数就是用户没有显式实现&#xff0c;编译器会自动生成的成员函数称为默认成员函数&#xff0c;如下图&#xff1a; 其中最重要的就是我们表格中的前四个函数&#xff0c;本篇文章我们主要介绍前三个。默认成员函数很重要&#xff0c;也比较复杂…

下载xhsell连接Linux系统

一、下载安装xshell 1、下载 免费版的网址&#xff1a;家庭/学校免费 - NetSarang Website 2、安装 选择自己想要下载的文件夹位置 创建一个新的文件夹即可 不想注册可以直接选择后来先进行试用 二、连接Linux虚拟机 1、点击加号新建会话 2、输入你要连接的虚拟机的IP地址…

4、Django Admin对自定义的计算字段进行排序

通常&#xff0c;Django会为模型属性字段&#xff0c;自动添加排序功能。当你添加计算字段时&#xff0c;Django不知道如何执行order_by&#xff0c;因此它不会在该字段上添加排序功能。 如果要在计算字段上添加排序&#xff0c;则必须告诉Django需要排序的内容。你可以通过在…

【综合架构】Part 5.2 Ansible

使用设备&#xff1a;管理设备-m01-10.0.0.61 1 概述 自动化运维工具&#xff1a;可实现批量管理、批量分发、批量执行、维护... Ansible 是由 Python语言 所编写 2 管理架构 Inventory 主机清单&#xff1a;被管理主机的ip列表、分类。ad-hoc模式&#xff1a;命令行批量管理…