1. インストールと最適化
1.1 基本的な環境構成
1. 環境の紹介
(1). 高可用性クラスタの計画
CPU名 | IPアドレス | 説明する |
---|---|---|
k8s-master01 | 192.168.2.96 | マスターノード |
k8s-master02 | 192.168.2.97 | マスターノード |
k8s-master03 | 192.168.2.98 | マスターノード |
k8s-node01 | 192.168.2.99 | ノードノード |
k8s-node02 | 192.168.2.100 | ノードノード |
k8s-マスター-vip | 192.168.2.236 | キープアライブ仮想 IP |
(2). ネットワークセグメント計画
ネットワークセグメント名 | ネットワークのセグメンテーション |
---|---|
ホストネットワークセグメント | 192.168.2.1/24 |
ポッドネットワークセグメント | 172.16.0.0/12 |
サービスネットワークセグメント | 10.0.0.0/16 |
2. 構成情報
構成情報 | 述べる |
---|---|
システムバージョン | セントス7.9 |
Docker のバージョン | 20.10倍 |
kubeadm バージョン | v1.23.17 |
cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
docker --version
Docker version 20.10.21, build baeda1f
kubeadm version
kubeadm version: &version.Info{
Major:"1", Minor:"23", GitVersion:"v1.23.17", GitCommit:"953be8927218ec8067e1af2641e540238ffd7576", GitTreeState:"clean", BuildDate:"2023-02-22T13:33:14Z", GoVersion:"go1.19.6", Compiler:"gc", Platform:"linux/amd64"}
注: ホスト ネットワーク セグメント、K8s サービス ネットワーク セグメント、およびポッド ネットワーク セグメントを繰り返すことはできません!!!
3. ホスト名を変更します
( 1) 計画情報に従って各マシンのホスト名を変更します
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
4. hosts ファイルを変更します
(1) vim エディタをインストールします。すでにインストールされている場合は無視してください
yum insytall vim -y
(2) 各マシンの hosts ファイルを変更します
vim /etc/hosts
192.168.2.96 k8s-master01
192.168.2.97 k8s-master02
192.168.2.98 k8s-master03
192.168.2.236 k8s-master-vip
192.168.2.99 k8s-node01
192.168.2.100 k8s-node02
注: 高可用性クラスターではない場合、上記の VIP は Master01 の IP です。 ! !
5.yumソースをインストールする
(1) 各マシンで次のコマンドを実行して、デフォルトの yum ソースを構成し、依存関係をインストールします。
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
yum install -y yum-utils device-mapper-persistent-data lvm2
(2) 各マシンで以下のコマンドを実行し、Docker の yum ソースを設定します。
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
(3) 各マシンで以下のコマンドを実行し、kubernetes の yum ソースを設定します。
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
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
sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo
6. 必要なツールのインストール
(1) 各マシンで以下のコマンドを実行し、必要なツールをインストールします。
yum install wget jq psmisc vim net-tools telnet yum-utils device-mapper-persistent-data lvm2 git -y
7. ファイアウォールをオフにし、パーティションをスワップし、dnsmasq、selinux をオフにします。
(1) 各マシンで以下のコマンドを実行し、ファイアウォールをオフにします。
systemctl disable --now firewalld
(2) 各マシンで以下のコマンドを実行し、selinux をシャットダウンします。
setenforce 0
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/sysconfig/selinux
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
(3) 各マシンで以下のコマンドを実行し、dnsmasq をシャットダウンします。
systemctl disable --now dnsmasq
操作の実行に失敗しました: そのようなファイルまたはディレクトリはありません
注: これを VMware 仮想マシンを通じて実行すると、そのようなサービスがないためエラーが報告されます。
(4) 各マシンで以下のコマンドを実行し、NetworkManager をシャットダウンします。
systemctl disable --now NetworkManager
注: パブリック クラウドでは NetworkManager を閉じないでください。
(5) 各マシンで以下のコマンドを実行し、スワップパーティションを閉じます。
臨時休業
swapoff -a && sysctl -w vm.swappiness=0
永久閉鎖
sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab
8. クロック同期
(1) 各マシンで以下のコマンドを実行し、ntpdateをインストールします。
rpm -ivh http://mirrors.wlnmp.com/centos/wlnmp-release-centos.noarch.rpm
yum install ntpdate -y
(2) 各マシンで以下のコマンドを実行し、時刻を同期します。
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo 'Asia/Shanghai' >/etc/timezone
ntpdate time2.aliyun.com
#スケジュールされたタスクを追加
crontab -e
*/5 * * * * /usr/sbin/ntpdate time2.aliyun.com
9.制限の設定
(1) 各マシンで以下のコマンドを実行し、制限を設定します。
ulimit -SHn 65535
vim /etc/security/limits.conf
末尾添加以下内容
* soft nofile 65536
* hard nofile 131072
* soft nproc 65535
* hard nproc 655350
* soft memlock unlimited
* hard memlock unlimited
10.Master01ノード設定キーフリーログイン
(1) Master01 ノードで次のコマンドを設定し、キーなしで他のノードにログインできるようにします。
ssh-keygen -t rsa #按3次回车即可
for i in k8s-master01 k8s-master02 k8s-master03 k8s-node01 k8s-node02;do ssh-copy-id -i .ssh/id_rsa.pub $i;done
注: この操作が完了すると、他のノードのパスワードを 4 回入力するよう求められます!!!
(2) k8s-node02 ノードにリモートでログインします。 Master01 ノードでテストし、 テストが成功したことを確認します。
ssh k8s-node02
11. ソースコードファイルをダウンロードする
(1) Master01ノードにソースコードファイルをダウンロードする
git clone https://gitee.com/jeckjohn/k8s-ha-install.git
(2) Master01 ノードで以下のコマンドを実行し、ブランチを表示します。
cd k8s-ha-install
git branch -a
[root@192 k8s-ha-install]# git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/manual-installation
remotes/origin/manual-installation-v1.16.x
remotes/origin/manual-installation-v1.17.x
remotes/origin/manual-installation-v1.18.x
remotes/origin/manual-installation-v1.19.x
remotes/origin/manual-installation-v1.20.x
remotes/origin/manual-installation-v1.20.x-csi-hostpath
remotes/origin/manual-installation-v1.21.x
remotes/origin/manual-installation-v1.22.x
remotes/origin/manual-installation-v1.23.x
remotes/origin/manual-installation-v1.24.x
remotes/origin/manual-installation-v1.25.x
remotes/origin/manual-installation-v1.26.x
remotes/origin/manual-installation-v1.27.x
remotes/origin/manual-installation-v1.28.x
remotes/origin/master
1.2 カーネルのアップグレード
1.3ランタイムとしてのContainerd
インストールされているバージョンが 1.24 より低い場合は、Docker または Containerd を選択できます。1.24 より高い場合は、ランタイムとして Containerd を選択します。
1. 各マシンで次のコマンドを実行して、docker-ce-20.10 をインストールします。ここで docker をインストールすると、Containerd もインストールされることに注意してください。
yum install docker-ce-20.10.* docker-ce-cli-20.10.* -y
2. 各マシンで次のコマンドを実行して、Containerd に必要なモジュールを構成します。
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
3. 各マシンで次のコマンドを実行してモジュールをロードします。
modprobe -- overlay
modprobe -- br_netfilter
4. 各マシンで次のコマンドを実行して、Containerd に必要なカーネルを構成します。
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
5. 各マシンで次のコマンドを実行してカーネルをロードします。
sysctl --system
6. 各マシンで次のコマンドを実行して、Containerd 構成ファイルを構成します。
mkdir -p /etc/containerd
containerd config default | tee /etc/containerd/config.toml
7. 各マシンで次のコマンドを実行して、Containerd の Cgroup を Systemd に変更し、containerd.runtimes.runc.options を見つけて、SystemdCgroup = true を追加します (既に存在する場合は直接変更します。そうでない場合は、エラーが報告されます)。
vim /etc/containerd/config.toml
...
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
BinaryName = ""
CriuImagePath = ""
CriuPath = ""
CriuWorkPath = ""
IoGid = 0
IoUid = 0
NoNewKeyring = false
NoPivotRoot = false
Root = ""
ShimCgroup = ""
SystemdCgroup = true
8. 各マシンで次のコマンドを実行して、sandbox_image の一時停止イメージを自分のバージョン http://registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6 と一致するアドレスに変更します。
vim /etc/containerd/config.toml
#原本内容
sandbox_image = "registry.k8s.io/pause:3.6"
#修改后的内容
sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6"
9. 各マシンで次のコマンドを実行して Containerd を起動し、起動時の自動起動を構成します。
systemctl daemon-reload
systemctl enable --now containerd
ls /run/containerd/containerd.sock /run/containerd/containerd.sock
10. 各マシンで次のコマンドを実行して、crictl クライアント接続のランタイムの場所を構成します。
cat > /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF
11. 各マシンで次のコマンドを実行して確認します。
ctr image ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
1.4 Kubernetes コンポーネント Kubeadm と Kubelet をインストールする
1. Master01 ノードで最新の Kubernetes バージョンを確認します。
yum list kubeadm.x86_64 --showduplicates | sort -r
2. 各マシンで次のコマンドを実行して、kubeadm、kubelet、および kubectl の最新バージョン 1.23 をインストールします。
yum install kubeadm-1.23* kubelet-1.23* kubectl-1.23* -y
查看版本
kubeadm version
3. 各マシンで次のコマンドを実行して、Kubelet 構成を変更し、Containerd をランタイムとして使用します。ランタイムとして docker を選択した場合は、変更は必要ありません。
cat >/etc/sysconfig/kubelet<<EOF
KUBELET_KUBEADM_ARGS="--container-runtime=remote --runtime-request-timeout=15m --container-runtime-endpoint=unix:///run/containerd/containerd.sock"
EOF
4. 各マシンで次のコマンドを実行して、起動時に Kubelet が自動的に起動するように設定します (まだ初期化されておらず、kubelet 構成ファイルがないため、現時点では kubelet を起動できず、管理は必要ありません)。
systemctl daemon-reload
systemctl enable --now kubelet
systemctl status kubelet
注: まだ初期化されておらず、kubelet の設定ファイルがないため、現時点では kubelet を起動できず、管理は必要ありません。
1.5 高可用性コンポーネントのインストール
パブリック クラウドは、ほとんどのパブリック クラウドがキープアライブをサポートしていないため、Alibaba Cloud の SLB や Tencent Cloud の ELB などのパブリック クラウドに付属する負荷分散を使用して、haproxy と keepalived を置き換える必要があります。 Alibaba Cloud の SLB にはループバック問題 (SLB プロキシ サーバーが SLB に逆アクセスできない) があるため、Tencent Cloud を使用することをお勧めしますが、Tencent Cloud ではこの問題が修正されています。
注: 高可用性クラスタではない場合、haproxy と keepalived をインストールする必要はありません!!!
1. HAProxy をインストールします
(1) すべてのマスター ノードに yum を介して HAProxy と KeepAlived をインストールします。
yum install keepalived haproxy -y
(2) すべてのマスター ノードは HAProxy で構成されており、すべてのマスター ノードの HAProxy 構成は同じです
mkdir /etc/haproxy
vim /etc/haproxy/haproxy.cfg
global
maxconn 2000
ulimit-n 16384
log 127.0.0.1 local0 err
stats timeout 30s
defaults
log global
mode http
option httplog
timeout connect 5000
timeout client 50000
timeout server 50000
timeout http-request 15s
timeout http-keep-alive 15s
frontend monitor-in
bind *:33305
mode http
option httplog
monitor-uri /monitor
frontend k8s-master
bind 0.0.0.0:16443
bind 127.0.0.1:16443
mode tcp
option tcplog
tcp-request inspect-delay 5s
default_backend k8s-master
backend k8s-master
mode tcp
option tcplog
option tcp-check
balance roundrobin
default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
server k8s-master01 192.168.2.96:6443 check
server k8s-master02 192.168.2.97:6443 check
server k8s-master03 192.168.2.98:6443 check
(3) すべてのマスター ノードが HAProxy を再起動し、ポート 16443 を確認します。
systemctl restart haproxy
netstat -lntp | grep 16443
tcp 0 0 127.0.0.1:16443 0.0.0.0:* LISTEN 1075/haproxy
tcp 0 0 0.0.0.0:16443 0.0.0.0:*
2.KeepAlivedをインストールする
すべてのマスター ノードは KeepAlived で構成されていますが、構成が異なるため、各ノードの IP およびネットワーク カード (インターフェイス パラメーター) の区別に注意してください。
(1) Master01ノードの構成は以下のとおりです。
! Configuration File for keepalived
global_defs {
router_id LVS_DEVEL
script_user root
enable_script_security
}
vrrp_script chk_apiserver {
script "/etc/keepalived/check_apiserver.sh"
interval 5
weight -5
fall 2
rise 1
}
vrrp_instance VI_1 {
state MASTER
interface ens33
mcast_src_ip 192.168.2.96
virtual_router_id 51
priority 101
advert_int 2
authentication {
auth_type PASS
auth_pass K8SHA_KA_AUTH
}
virtual_ipaddress {
192.168.2.236
}
track_script {
chk_apiserver
}
}
(2) Master02ノードの構成は以下のとおりです。
! Configuration File for keepalived
global_defs {
router_id LVS_DEVEL
script_user root
enable_script_security
}
vrrp_script chk_apiserver {
script "/etc/keepalived/check_apiserver.sh"
interval 5
weight -5
fall 2
rise 1
}
vrrp_instance VI_1 {
state MASTER
interface ens33
mcast_src_ip 192.168.2.97
virtual_router_id 51
priority 101
advert_int 2
authentication {
auth_type PASS
auth_pass K8SHA_KA_AUTH
}
virtual_ipaddress {
192.168.2.236
}
track_script {
chk_apiserver
}
}
(3) Master03ノードの構成は以下のとおりです。
! Configuration File for keepalived
global_defs {
router_id LVS_DEVEL
script_user root
enable_script_security
}
vrrp_script chk_apiserver {
script "/etc/keepalived/check_apiserver.sh"
interval 5
weight -5
fall 2
rise 1
}
vrrp_instance VI_1 {
state MASTER
interface ens33
mcast_src_ip 192.168.2.98
virtual_router_id 51
priority 101
advert_int 2
authentication {
auth_type PASS
auth_pass K8SHA_KA_AUTH
}
virtual_ipaddress {
192.168.2.236
}
track_script {
chk_apiserver
}
}
(4) すべてのマスターノードが KeepAlived ヘルスチェックファイルを設定します
vim /etc/keepalived/check_apiserver.sh
#!/bin/bash
#初始化错误计数器
err=0
#循环三次检查HAProxy进程是否在运行
for k in $(seq 1 3)
do
check_code=$(pgrep haproxy)
if [[ $check_code == "" ]]; then
#如果未找到进程,增加错误计数器并等待一秒钟
err=$(expr $err + 1)
sleep 1
continue
else
#如果找到进程,重置错误计数器并退出循环
err=0
break
fi
done
#根据错误计数器的值,决定是否停止keepalived服务并退出脚本
if [[ $err != "0" ]]; then
echo "systemctl stop keepalived"
/usr/bin/systemctl stop keepalived
exit 1
else
exit 0
fi
#赋权
chmod +x /etc/keepalived/check_apiserver.sh
3. すべてのマスターノードが haproxy と keepalived を開始します。
systemctl daemon-reload
systemctl enable --now haproxy
systemctl enable --now keepalived
4. VIP をテストし、キープアライブが正常であるかどうかを確認します。
ping 192.168.2.236 -c 4
2. クラスター構築
2.1マスターノードの初期化
1. Master01 ノードは、次のように kubeadm-config.yaml 構成ファイルを作成します。
vim kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: 7t2weq.bjbawausm0jaxury
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.2.96 #Master01节点的IP地址
bindPort: 6443
nodeRegistration:
criSocket: /run/containerd/containerd.sock
name: k8s-master01
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiServer:
certSANs:
- 192.168.2.236 #VIP地址/公有云的负载均衡地址
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controlPlaneEndpoint: 192.168.2.236:16443
controllerManager: {
}
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.23.17 #此处版本号和kubeadm版本一致
networking:
dnsDomain: cluster.local
podSubnet: 172.16.0.0/12
serviceSubnet: 10.0.0.0/16
scheduler: {
}
2. Master01 ノードの kubeadm ファイルを更新します。
kubeadm config migrate --old-config kubeadm-config.yaml --new-config new.yaml
3. Master01 ノード上の new.yaml ファイルを他のマスター ノードにコピーします。
for i in k8s-master02 k8s-master03; do scp new.yaml $i:/root/; done
4. すべてのマスター ノードは事前にイメージをダウンロードするため、初期化時間を節約できます (他のノードは IP アドレスを含む構成を変更する必要がありません)。
kubeadm config images pull --config /root/new.yaml
5. すべてのノードは、電源がオンになったときに kubelet を自動的に起動するように設定されています。
systemctl enable --now kubelet
6. Master01 ノードが初期化されます。初期化後、対応する証明書と構成ファイルが /etc/kubernetes ディレクトリに生成され、他のマスター ノードが Master01 に参加できるようになります。
kubeadm init --config /root/new.yaml --upload-certs
正常に実行されると、以下のようなログが出力されます。
[root@k8s-master01 ~]# kubeadm init --config /root/new.yaml --upload-certs
[init] Using Kubernetes version: v1.23.17
[preflight] Running pre-flight checks
[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.0.0.1 192.168.2.96 192.168.2.236]
[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 [192.168.2.96 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 [192.168.2.96 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"
[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[kubeconfig] Writing "admin.conf" kubeconfig file
[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[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 22.532424 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.23" in namespace kube-system with the configuration for the kubelets in the cluster
NOTE: The "kubelet-config-1.23" naming of the kubelet ConfigMap is deprecated. Once the UnversionedKubeletConfigMap feature gate graduates to Beta the default name will become just "kubelet-config". Kubeadm upgrade will handle this transition transparently.
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
3b03fabd6969ee744908335536f94e0ac11d15be87edd918d8ad08324ddfdbb2
[mark-control-plane] Marking the node k8s-master01 as control-plane by adding the labels: [node-role.kubernetes.io/master(deprecated) node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[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: 7t2weq.bjbawausm0jaxury
[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
[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address
[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/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo 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 the control-plane node running the following command on each as root:
kubeadm join 192.168.2.236:16443 --token 7t2weq.bjbawausm0jaxury \
--discovery-token-ca-cert-hash sha256:c5891bc7b53ee8e7548de96db1f4ed5ef353b77e572910f8aa3965040356701d \
--control-plane --certificate-key 3b03fabd6969ee744908335536f94e0ac11d15be87edd918d8ad08324ddfdbb2
Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.2.236:16443 --token 7t2weq.bjbawausm0jaxury \
--discovery-token-ca-cert-hash sha256:c5891bc7b53ee8e7548de96db1f4ed5ef353b77e572910f8aa3965040356701d
補充:
初期化に失敗した場合はリセットして再度初期化を行います。コマンドは以下の通りです(失敗した場合は実行しないでください)
kubeadm reset -f ; ipvsadm --clear ; rm -rf ~/.kube
7. Master01 ノードは、Kubernetes クラスターにアクセスするための環境変数を構成します
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
#查看节点状态
kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master01 NotReady control-plane,master 4m5s v1.23.17
2.2 k8s クラスターへのマスターとノードの追加
1. Master02 ノードと Master03 ノードを k8s クラスターに追加します
kubeadm join 192.168.2.236:16443 --token 7t2weq.bjbawausm0jaxury \
--discovery-token-ca-cert-hash sha256:c5891bc7b53ee8e7548de96db1f4ed5ef353b77e572910f8aa3965040356701d \
--control-plane --certificate-key 3b03fabd6969ee744908335536f94e0ac11d15be87edd918d8ad08324ddfdbb2
2. Node01 ノードと Node02 ノードを k8s クラスターに追加します
kubeadm join 192.168.2.236:16443 --token 7t2weq.bjbawausm0jaxury \
--discovery-token-ca-cert-hash sha256:c5891bc7b53ee8e7548de96db1f4ed5ef353b77e572910f8aa3965040356701d
3. Master01 ノードでノードのステータスを確認します。
kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master01 NotReady control-plane,master 7m11s v1.23.17
k8s-master02 NotReady control-plane,master 2m28s v1.23.17
k8s-master03 NotReady control-plane,master 102s v1.23.17
k8s-node01 NotReady <none> 106s v1.23.17
k8s-node02 NotReady <none> 84s v1.23.17
2.3 Calico コンポーネントのインストール
1. Master01 ノード上の対応するブランチ ディレクトリを入力します。
cd /root/k8s-ha-install && git checkout manual-installation-v1.23.x && cd calico/
2. Pod ネットワークセグメントを抽出し、変数に割り当てます。
POD_SUBNET=`cat /etc/kubernetes/manifests/kube-controller-manager.yaml | grep cluster-cidr= | awk -F= '{print $NF}'`
3. calico.yaml ファイルを変更する
sed -i "s#POD_CIDR#${POD_SUBNET}#g" calico.yaml
4.Calicoをインストールする
kubectl apply -f calico.yaml
5. ノードのステータスを確認する
kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master01 Ready control-plane,master 9h v1.23.17
k8s-master02 Ready control-plane,master 9h v1.23.17
k8s-master03 Ready control-plane,master 9h v1.23.17
k8s-node01 Ready <none> 9h v1.23.17
k8s-node02 Ready <none> 9h v1.23.17
6. ポッドのステータスを確認し、すべてのポッドが実行されていることを確認します。
kubectl get po -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-6f6595874c-tntnr 1/1 Running 0 8m52s
calico-node-5mj9g 1/1 Running 1 (41s ago) 8m52s
calico-node-hhjrv 1/1 Running 2 (61s ago) 8m52s
calico-node-szjm7 1/1 Running 0 8m52s
calico-node-xcgwq 1/1 Running 0 8m52s
calico-node-ztbkj 1/1 Running 1 (11s ago) 8m52s
calico-typha-6b6cf8cbdf-8qj8z 1/1 Running 0 8m52s
coredns-65c54cc984-nrhlg 1/1 Running 0 9h
coredns-65c54cc984-xkx7w 1/1 Running 0 9h
etcd-k8s-master01 1/1 Running 1 (29m ago) 9h
etcd-k8s-master02 1/1 Running 1 (29m ago) 9h
etcd-k8s-master03 1/1 Running 1 (29m ago) 9h
kube-apiserver-k8s-master01 1/1 Running 1 (29m ago) 9h
kube-apiserver-k8s-master02 1/1 Running 1 (29m ago) 9h
kube-apiserver-k8s-master03 1/1 Running 2 (29m ago) 9h
kube-controller-manager-k8s-master01 1/1 Running 2 (29m ago) 9h
kube-controller-manager-k8s-master02 1/1 Running 1 (29m ago) 9h
kube-controller-manager-k8s-master03 1/1 Running 1 (29m ago) 9h
kube-proxy-7rmrs 1/1 Running 1 (29m ago) 9h
kube-proxy-bmqhr 1/1 Running 1 (29m ago) 9h
kube-proxy-l9rqg 1/1 Running 1 (29m ago) 9h
kube-proxy-nn465 1/1 Running 1 (29m ago) 9h
kube-proxy-sghfb 1/1 Running 1 (29m ago) 9h
kube-scheduler-k8s-master01 1/1 Running 2 (29m ago) 9h
kube-scheduler-k8s-master02 1/1 Running 1 (29m ago) 9h
kube-scheduler-k8s-master03 1/1 Running 1 (29m ago) 9h
2.4メトリクスの展開
新しいバージョンの Kubernetes では、システム リソースの収集に Metrics-server が使用され、ノードとポッドのメモリ、ディスク、CPU、ネットワークの使用状況を収集することができます。
1. Master01ノードのfront-proxy-ca.crtをNode-01ノードとNode-02ノードにコピーします。
scp /etc/kubernetes/pki/front-proxy-ca.crt k8s-node01:/etc/kubernetes/pki/front-proxy-ca.crt
scp /etc/kubernetes/pki/front-proxy-ca.crt k8s-node02:/etc/kubernetes/pki/front-proxy-ca.crt
2. Master01 ノードにメトリクス サーバーをインストールします
cd /root/k8s-ha-install/kubeadm-metrics-server
kubectl create -f comp.yaml
3. Master01 ノードでのメトリクス サーバーの展開ステータスを確認します。
kubectl get po -n kube-system -l k8s-app=metrics-server
NAME READY STATUS RESTARTS AGE
metrics-server-5cf8885b66-jdjtb 1/1 Running 0 115s
4. Master01 ノードのノード使用状況を確認します。
kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
k8s-master01 130m 0% 1019Mi 12%
k8s-master02 102m 0% 1064Mi 13%
k8s-master03 93m 0% 971Mi 12%
k8s-node01 45m 0% 541Mi 6%
k8s-node02 57m 0% 544Mi 6%
2.5ダッシュボードの展開
ダッシュボードは、Web ベースの Kubernetes ユーザー インターフェイスです。ダッシュボードを使用すると、コンテナ アプリケーションを Kubernetes クラスタにデプロイし、コンテナ アプリケーションのトラブルシューティングを行い、クラスタ リソースを管理できます。ダッシュボードを使用すると、クラスター内で実行されているアプリケーションに関する概要情報を取得できます。また、Kubernetes リソース (デプロイメント、ジョブ、DaemonSet など) を作成または変更することもできます。たとえば、デプロイメントの自動スケーリング、ローリング アップグレードの開始、ポッドの再起動、ウィザードを使用した新しいアプリケーションの作成などを行うことができます。ダッシュボードには、Kubernetes クラスター内のリソースのステータス情報とすべてのエラー メッセージも表示されます。
1. Master01 ノードにダッシュボードをインストールします
cd /root/k8s-ha-install/dashboard/
kubectl create -f .
2. Master01 ノードのダッシュボード サービスを表示します。
kubectl get svc -n kubernetes-dashboard
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dashboard-metrics-scraper ClusterIP 10.0.159.210 <none> 8000/TCP 2m6s
kubernetes-dashboard NodePort 10.0.241.159 <none> 443:31822/TCP 2m6s
3. ダッシュボードにアクセスできない問題を解決するには、Google Chrome 起動ファイルに起動パラメータを追加します。
(1) Google Chrome(クローム)を右クリックし、[プロパティ]を選択します
(2) [ターゲット] の場所に次のパラメータを追加します –test-type --ignore-certificate-errors の前にパラメータがあることを再度強調します
–test-type --ignore-certificate-errors
4. Master01 ノードのトークン値を表示します
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')
5. Google Chrome (Chrome) を開き、「https://任意のノード IP:サービス ポート」と入力します。ここでは例として Master01 ノードを取り上げます。
https://192.168.2.97:32636/
6. 名前付き名前空間を kube-system に切り替えます。デフォルトのデフォルト名前空間にはリソースがありません。
2.6 Kube プロキシ モードを ipvs に設定する
1. Master01 ノードで Kube-proxy を ipvs モードに変更します (デフォルトは iptables)。
kubectl edit cm kube-proxy -n kube-system
2. Master01 ノード上の Kube-Proxy ポッドを更新します
kubectl patch daemonset kube-proxy -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"date\":\"`date +'%s'`\"}}}}}" -n kube-system
3. Master01 ノード上の kube-proxy のローリング アップデート ステータスを確認します。
kubectl get po -n kube-system | grep kube-proxy
kube-proxy-2kz9g 1/1 Running 0 58s
kube-proxy-b54gh 1/1 Running 0 63s
kube-proxy-kclcc 1/1 Running 0 61s
kube-proxy-pv8gc 1/1 Running 0 59s
kube-proxy-xt52m 1/1 Running 0 56s
4. Master01 ノードで Kube-Proxy モードを確認する
curl 127.0.0.1:10249/proxyMode
ipvs
2.7Kubectlの自動補完
1. Master01 ノードで kubectl オートコンプリートを有効にする
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc
2. Master01 ノードで kubectl の短縮エイリアスを使用します。
alias k=kubectl
complete -o default -F __start_kubectl k
3. クラスターの可用性の検証
1. Master01 ノードでノードが正常であるかどうかを確認し、すべてが Ready であることを確認します。
kubectl get node
[root@k8s-master01 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master01 Ready control-plane,master 2d2h v1.23.17
k8s-master02 Ready control-plane,master 2d v1.23.17
k8s-master03 Ready control-plane,master 2d v1.23.17
k8s-node01 Ready <none> 2d v1.23.17
k8s-node02 Ready <none> 2d v1.23.17
[root@k8s-master01 ~]#
2. Master01 ノード上のすべてのポッドが正常であるかどうかを確認し、READY が N/N の形式であり、STATUS が実行中であることを確認します。
3. クラスタ ネットワーク セグメントを確認します。 Master01 ノードで競合
(1) Master01ノードのSVCネットワークセグメントを確認する
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 2d2h
nginx NodePort 10.0.25.21 <none> 80:30273/TCP 47h
springboot-demo NodePort 10.0.115.157 <none> 30000:30001/TCP 45h
(2) Master01 ノードの POD ネットワーク セグメントを確認します。これは主に 2 つのセグメントに分かれています。1 つのセグメントは HostNetwork を使用するためホスト ネットワーク セグメントを使用し、もう 1 つのセグメントは POD ネットワーク セグメントを使用します
4. Master01 ノードでリソースが正常に作成されているか確認します
(1) Master01ノード上にcluster-testという名前のデプロイメントを作成します。
kubectl create deploy cluster-test --image=registry.cn-hangzhou.aliyuncs.com/zq-demo/debug-tools -- sleep 3600
(2) Master01ノードでのデプロイメントの作成状況を確認します。
kubectl get po
NAME READY STATUS RESTARTS AGE
cluster-test-79b978867f-mcqgr 1/1 Running 2 (10m ago) 2d
nginx-85b98978db-vb9gc 1/1 Running 1 (10m ago) 47h
springboot-demo-6d87f66f6b-fxpgj 1/1 Running 1 (10m ago) 45h
springboot-demo-6d87f66f6b-p4tmd 1/1 Running 1 (10m ago) 45h
springboot-demo-6d87f66f6b-tmtkn 1/1 Running 1 (10m ago) 45h
5. ポッドが Master01 ノード上のサービスを解決できるかどうかを確認します。
(1) Master01 ノードで kubernetes を解析し、上記の SVC アドレスと一致していることを確認します。
[root@k8s-master01 ~]# kubectl exec -it cluster-test-79b978867f-mcqgr -- bash
(06:53 cluster-test-79b978867f-mcqgr:/) nslookup kubernetes
Server: 10.0.0.10
Address: 10.0.0.10#53
Name: kubernetes.default.svc.cluster.local
Address: 10.0.0.1
(2) Master01 ノードで kube-dns.kube-system を解析し、上記の SVC アドレスと一致していることを確認します。
(06:53 cluster-test-79b978867f-mcqgr:/) nslookup kube-dns.kube-system
Server: 10.0.0.10
Address: 10.0.0.10#53
Name: kube-dns.kube-system.svc.cluster.local
Address: 10.0.0.10
6.各ノードがKubernetesのkubernetes svc 443とkube-dnsのservice 53にアクセスできるかどうか
(1) 各マシン上の Kubernetes にアクセスする kubernetes svc 443 をテストします。
[root@k8s-master02 ~]# curl https://10.0.0.1:443
curl: (60) Peer's Certificate issuer is not recognized.
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.
(2) 各マシン上の Kubernetes の kube-dns にアクセスするテスト サービス 53
curl 10.0.0.10:53
curl: (52) Empty reply from server
7. Podとマシンが正常に通信できるかどうか
(1) Master01ノードのポッドノードIPを確認します。
[root@k8s-master01 ~]# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
cluster-test-79b978867f-mcqgr 1/1 Running 2 (16m ago) 2d 172.27.14.201 k8s-node02 <none> <none>
nginx-85b98978db-vb9gc 1/1 Running 1 (16m ago) 47h 172.17.125.7 k8s-node01 <none> <none>
springboot-demo-6d87f66f6b-fxpgj 1/1 Running 1 (16m ago) 45h 172.27.14.203 k8s-node02 <none> <none>
springboot-demo-6d87f66f6b-p4tmd 1/1 Running 1 (16m ago) 45h 172.27.14.204 k8s-node02 <none> <none>
springboot-demo-6d87f66f6b-tmtkn 1/1 Running 1 (16m ago) 45h 172.17.125.9 k8s-node01 <none> <none>
(2) Master01ノードでのPingテスト
[root@k8s-master01 ~]# ping 172.27.14.201
PING 172.27.14.201 (172.27.14.201) 56(84) bytes of data.
64 bytes from 172.27.14.201: icmp_seq=1 ttl=63 time=0.418 ms
64 bytes from 172.27.14.201: icmp_seq=2 ttl=63 time=0.222 ms
64 bytes from 172.27.14.201: icmp_seq=3 ttl=63 time=0.269 ms
64 bytes from 172.27.14.201: icmp_seq=4 ttl=63 time=0.364 ms
64 bytes from 172.27.14.201: icmp_seq=5 ttl=63 time=0.197 ms
^C
--- 172.27.14.201 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4106ms
rtt min/avg/max/mdev = 0.197/0.294/0.418/0.084 ms
[root@k8s-master01 ~]#
8. Pod と Pod 間の通信が正常に行われているかどうかを確認します
(1) Master01 ノードのデフォルトの名前空間内のポッドを表示する
[root@k8s-master01 ~]# kubectl get po -owide
名前 準備完了ステータス 再開年齢 IP ノード指定ノード準備ゲート
cluster-test-79b978867f-mcqgr 1/1 実行中 2 (19 分前) 2d 172.27.14.201 k8s-node02 < a i =4> nginx-85b98978db-vb9gc 1/1 実行中 1 (19 分前) 47 時間 172.17.125.7 k8s-node01 springboot-demo-6d87f66f6b-fxpgj 1/1 実行中 1 (19 分前) 45 時間172.27.14.203 k8s-node02 springboot-demo-6d87f66f6b-p4tmd 1/1 実行中 1 (19 分前) 45 時間 172.27.14.204 k8s-node02 springboot-demo -6d87f66f6b-tmtkn 1/1 実行中 1 (19 分前) 45h 172.17.125.9 k8s-node01 /var/spool/mail/root に新しいメールがあります [root@k8s-master01 ~]# (2) Master01 ノードの kube-system 名前空間下のポッド [root@k8s-master01 ~] # kubectl get po -n kube-system -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
calico-kube-controllers-6f6595874c-rvpbg 1/1 Running 4 (20m ago) 2d1h 172.18.195.8 k8s-master03 <none> <none>
calico-node-6vwpm 1/1 Running 2 (20m ago) 2d1h 192.168.2.99 k8s-node01 <none> <none>
calico-node-b8kfr 1/1 Running 3 (25m ago) 2d1h 192.168.2.96 k8s-master01 <none> <none>
calico-node-blqnz 1/1 Running 2 (20m ago) 2d1h 192.168.2.100 k8s-node02 <none> <none>
calico-node-hpw8m 1/1 Running 3 (20m ago) 2d1h 192.168.2.98 k8s-master03 <none> <none>
calico-node-pbb9c 1/1 Running 2 2d1h 192.168.2.97 k8s-master02 <none> <none>
calico-typha-6b6cf8cbdf-4jt8j 1/1 Running 2 (20m ago) 2d1h 192.168.2.99 k8s-node01 <none> <none>
coredns-65c54cc984-cdksw 1/1 Running 2 (20m ago) 2d3h 172.18.195.9 k8s-master03 <none> <none>
coredns-65c54cc984-qb5nz 1/1 Running 2 (20m ago) 2d3h 172.18.195.7 k8s-master03 <none> <none>
etcd-k8s-master01 1/1 Running 3 (21m ago) 2d3h 192.168.2.96 k8s-master01 <none> <none>
etcd-k8s-master02 1/1 Running 2 (21m ago) 2d1h 192.168.2.97 k8s-master02 <none> <none>
etcd-k8s-master03 1/1 Running 2 (20m ago) 2d1h 192.168.2.98 k8s-master03 <none> <none>
kube-apiserver-k8s-master01 1/1 Running 7 (20m ago) 2d3h 192.168.2.96 k8s-master01 <none> <none>
kube-apiserver-k8s-master02 1/1 Running 3 (18m ago) 2d1h 192.168.2.97 k8s-master02 <none> <none>
kube-apiserver-k8s-master03 1/1 Running 3 (20m ago) 2d1h 192.168.2.98 k8s-master03 <none> <none>
kube-controller-manager-k8s-master01 1/1 Running 5 (25m ago) 2d3h 192.168.2.96 k8s-master01 <none> <none>
kube-controller-manager-k8s-master02 1/1 Running 2 (21m ago) 2d1h 192.168.2.97 k8s-master02 <none> <none>
kube-controller-manager-k8s-master03 1/1 Running 3 (19m ago) 2d1h 192.168.2.98 k8s-master03 <none> <none>
kube-proxy-258rd 1/1 Running 1 (20m ago) 2d 192.168.2.99 k8s-node01 <none> <none>
kube-proxy-7vgnc 1/1 Running 1 (20m ago) 2d 192.168.2.98 k8s-master03 <none> <none>
kube-proxy-9gsq5 1/1 Running 1 (21m ago) 2d 192.168.2.97 k8s-master02 <none> <none>
kube-proxy-fltdx 1/1 Running 1 (20m ago) 2d 192.168.2.100 k8s-node02 <none> <none>
kube-proxy-hc7z9 1/1 Running 1 (25m ago) 2d 192.168.2.96 k8s-master01 <none> <none>
kube-scheduler-k8s-master01 1/1 Running 5 (25m ago) 2d3h 192.168.2.96 k8s-master01 <none> <none>
kube-scheduler-k8s-master02 1/1 Running 2 (21m ago) 2d1h 192.168.2.97 k8s-master02 <none> <none>
kube-scheduler-k8s-master03 1/1 Running 3 (19m ago) 2d1h 192.168.2.98 k8s-master03 <none> <none>
metrics-server-5cf8885b66-w9dkt 1/1 Running 1 (20m ago) 2d 172.27.14.205 k8s-node02 <none> <none>
(3) Master01 ノードで「cluster-test-79b978867f-429xg」と入力し、ping テストを実行します。
[root@k8s-master01 ~]# kubectl exec -it cluster-test-79b978867f-mcqgr -- bash
(07:02 cluster-test-79b978867f-mcqgr:/) ping 192.168.2.99
PING 192.168.2.99 (192.168.2.99) 56(84) bytes of data.
64 bytes from 192.168.2.99: icmp_seq=1 ttl=63 time=0.260 ms
64 bytes from 192.168.2.99: icmp_seq=2 ttl=63 time=0.431 ms
64 bytes from 192.168.2.99: icmp_seq=3 ttl=63 time=0.436 ms
64 bytes from 192.168.2.99: icmp_seq=4 ttl=63 time=0.419 ms
64 bytes from 192.168.2.99: icmp_seq=5 ttl=63 time=0.253 ms
64 bytes from 192.168.2.99: icmp_seq=6 ttl=63 time=0.673 ms
64 bytes from 192.168.2.99: icmp_seq=7 ttl=63 time=0.211 ms
64 bytes from 192.168.2.99: icmp_seq=8 ttl=63 time=0.374 ms
64 bytes from 192.168.2.99: icmp_seq=9 ttl=63 time=0.301 ms
64 bytes from 192.168.2.99: icmp_seq=10 ttl=63 time=0.194 ms
^C
--- 192.168.2.99 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 9217ms
rtt min/avg/max/mdev = 0.194/0.355/0.673/0.137 ms