<?xml version="1.0" encoding="utf-8"?>


<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-CN">
    <title type="text">公子玄襄BLOG</title>
    <subtitle type="html">MemE 是一个强大且可高度定制的 GoHugo 博客主题，专为个人博客设计。</subtitle>
    <updated>2022-12-30T06:41:02&#43;00:00</updated>
    <id>/blog/</id>
    <link rel="alternate" type="text/html" href="/blog/" />
    <link rel="self" type="application/atom&#43;xml" href="/blog/atom.xml" />
    <author>
            <name>wmmsxm</name>
            <uri>/</uri>
            
                <email>wmmsxm@163.com</email>
            </author>
    <rights>Copyright © 2022 WuMengMeng</rights>
    <generator uri="https://gohugo.io/" version="0.90.1">Hugo</generator>
        <entry>
            <title type="text">K8s离线部署-更新过期证书</title>
            <link rel="alternate" type="text/html" href="/blog/posts/k8s/offline-update-cert/" />
            <id>/blog/posts/k8s/offline-update-cert/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2022-12-30T14:21:52&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">K8s离线部署-更新过期证书 查看证书有效期 执行下面命令，可以看到apiserver.crt的有效期时间 # openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text |grep Not Not Before: Dec 8 02:26:37 2021 GMT Not After : Dec 8 02:26:37 2022 GMT K8S CA证书……</summary>
            
                <content type="html">&lt;h2 id=&#34;centerk8s离线部署-更新过期证书center&#34;&gt;&lt;center&gt;K8s离线部署-更新过期证书&lt;/center&gt;&lt;/h2&gt;
&lt;h4 id=&#34;查看证书有效期&#34;&gt;查看证书有效期&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;执行下面命令，可以看到apiserver.crt的有效期时间
# openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text  |grep Not
    Not Before: Dec  8 02:26:37 2021 GMT
    Not After : Dec  8 02:26:37 2022 GMT
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;K8S CA证书是10年，但是组件证书的日期只有1年，为了证书一直可用状态需要更新，需要执行下面步骤进行更新&lt;/p&gt;
&lt;h4 id=&#34;执行脚本&#34;&gt;执行脚本&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;如果使用 &lt;code&gt;containerd&lt;/code&gt; 作为 CRI 运行时，使用 &lt;code&gt;update-kubeadm-cert-crictl.sh&lt;/code&gt; 代替 &lt;code&gt;update-kubeadm-cert.sh&lt;/code&gt;&lt;/strong&gt;
&lt;strong&gt;如果有多个 master 节点，在每个 master 节点都执行一次&lt;/strong&gt;
&lt;strong&gt;该脚本仅需要在 master 节点执行，无需在 worker node 节点执行&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1、创建update-kubeadm-cert.sh文件，内容在下面，自行填充。
2、执行授权命令：    chmod 755 update-kubeadm-cert.sh
3、执行脚本    ./update-kubeadm-cert.sh all
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;输出类似信息：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;CERTIFICATE                                       EXPIRES
/etc/kubernetes/controller-manager.config         Sep 12 08:38:56 2022 GMT
/etc/kubernetes/scheduler.config                  Sep 12 08:38:56 2022 GMT
/etc/kubernetes/admin.config                      Sep 12 08:38:56 2022 GMT
/etc/kubernetes/pki/ca.crt                        Sep 11 08:38:53 2031 GMT
/etc/kubernetes/pki/apiserver.crt                 Sep 12 08:38:54 2022 GMT
/etc/kubernetes/pki/apiserver-kubelet-client.crt  Sep 12 08:38:54 2022 GMT
/etc/kubernetes/pki/front-proxy-ca.crt            Sep 11 08:38:54 2031 GMT
/etc/kubernetes/pki/front-proxy-client.crt        Sep 12 08:38:54 2022 GMT
/etc/kubernetes/pki/etcd/ca.crt                   Sep 11 08:38:55 2031 GMT
/etc/kubernetes/pki/etcd/server.crt               Sep 12 08:38:55 2022 GMT
/etc/kubernetes/pki/etcd/peer.crt                 Sep 12 08:38:55 2022 GMT
/etc/kubernetes/pki/etcd/healthcheck-client.crt   Sep 12 08:38:55 2022 GMT
/etc/kubernetes/pki/apiserver-etcd-client.crt     Sep 12 08:38:56 2022 GMT
[2021-09-12T16:41:25.93+0800][INFO] backup /etc/kubernetes to /etc/kubernetes.old-20210912
[2021-09-12T16:41:25.93+0800][INFO] updating...
[2021-09-12T16:41:25.99+0800][INFO] updated /etc/kubernetes/pki/etcd/server.conf
[2021-09-12T16:41:26.04+0800][INFO] updated /etc/kubernetes/pki/etcd/peer.conf
[2021-09-12T16:41:26.07+0800][INFO] updated /etc/kubernetes/pki/etcd/healthcheck-client.conf
[2021-09-12T16:41:26.11+0800][INFO] updated /etc/kubernetes/pki/apiserver-etcd-client.conf
[2021-09-12T16:41:26.54+0800][INFO] restarted etcd
[2021-09-12T16:41:26.60+0800][INFO] updated /etc/kubernetes/pki/apiserver.crt
[2021-09-12T16:41:26.64+0800][INFO] updated /etc/kubernetes/pki/apiserver-kubelet-client.crt
[2021-09-12T16:41:26.69+0800][INFO] updated /etc/kubernetes/controller-manager.conf
[2021-09-12T16:41:26.74+0800][INFO] updated /etc/kubernetes/scheduler.conf
[2021-09-12T16:41:26.79+0800][INFO] updated /etc/kubernetes/admin.conf
[2021-09-12T16:41:26.79+0800][INFO] backup /root/.kube/config to /root/.kube/config.old-20210912
[2021-09-12T16:41:26.80+0800][INFO] copy the admin.conf to /root/.kube/config
[2021-09-12T16:41:26.85+0800][INFO] updated /etc/kubernetes/kubelet.conf
[2021-09-12T16:41:26.88+0800][INFO] updated /etc/kubernetes/pki/front-proxy-client.crt
[2021-09-12T16:41:28.70+0800][INFO] restarted apiserver
[2021-09-12T16:41:29.17+0800][INFO] restarted controller-manager
[2021-09-12T16:41:30.07+0800][INFO] restarted scheduler
[2021-09-12T16:41:30.13+0800][INFO] restarted kubelet
[2021-09-12T16:41:30.14+0800][INFO] done!!!
CERTIFICATE                                       EXPIRES
/etc/kubernetes/controller-manager.config         Sep 11 08:41:26 2031 GMT
/etc/kubernetes/scheduler.config                  Sep 11 08:41:26 2031 GMT
/etc/kubernetes/admin.config                      Sep 11 08:41:26 2031 GMT
/etc/kubernetes/pki/ca.crt                        Sep 11 08:38:53 2031 GMT
/etc/kubernetes/pki/apiserver.crt                 Sep 11 08:41:26 2031 GMT
/etc/kubernetes/pki/apiserver-kubelet-client.crt  Sep 11 08:41:26 2031 GMT
/etc/kubernetes/pki/front-proxy-ca.crt            Sep 11 08:38:54 2031 GMT
/etc/kubernetes/pki/front-proxy-client.crt        Sep 11 08:41:26 2031 GMT
/etc/kubernetes/pki/etcd/ca.crt                   Sep 11 08:38:55 2031 GMT
/etc/kubernetes/pki/etcd/server.crt               Sep 11 08:41:25 2031 GMT
/etc/kubernetes/pki/etcd/peer.crt                 Sep 11 08:41:26 2031 GMT
/etc/kubernetes/pki/etcd/healthcheck-client.crt   Sep 11 08:41:26 2031 GMT
/etc/kubernetes/pki/apiserver-etcd-client.crt     Sep 11 08:41:26 2031 GMT
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;将更新以下证书和 kubeconfig 配置文件&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/etc/kubernetes
├── admin.conf
├── controller-manager.conf
├── scheduler.conf
├── kubelet.conf
└── pki
    ├── apiserver.crt
    ├── apiserver-etcd-client.crt
    ├── apiserver-kubelet-client.crt
    ├── front-proxy-client.crt
    └── etcd
        ├── healthcheck-client.crt
        ├── peer.crt
        └── server.crt
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;证书更新失败回滚&#34;&gt;证书更新失败回滚&lt;/h4&gt;
&lt;p&gt;脚本会自动备份 &lt;code&gt;/etc/kubernetes&lt;/code&gt; 目录到 &lt;code&gt;/etc/kubernetes.old-$(date +%Y%m%d)&lt;/code&gt; 目录（备份目录命名示例：&lt;code&gt;kubernetes.old-20221230&lt;/code&gt;）&lt;/p&gt;
&lt;p&gt;若更新证书失败需要回滚，手动将备份 &lt;code&gt;/etc/kubernetes.old-$(date +%Y%m%d)&lt;/code&gt;目录覆盖 &lt;code&gt;/etc/kubernetes&lt;/code&gt; 目录&lt;/p&gt;
&lt;h4 id=&#34;update-kubeadm-certsh-脚本&#34;&gt;update-kubeadm-cert.sh 脚本&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#!/usr/bin/env bash

set -o errexit
set -o pipefail
# set -o xtrace

# set output color
NC=&#39;\033[0m&#39;
RED=&#39;\033[31m&#39;
GREEN=&#39;\033[32m&#39;
YELLOW=&#39;\033[33m&#39;
BLUE=&#39;\033[34m&#39;

log::err() {
  printf &amp;quot;[$(date +&#39;%Y-%m-%dT%H:%M:%S.%2N%z&#39;)][${RED}ERROR${NC}] %b\n&amp;quot; &amp;quot;$@&amp;quot;
}

log::info() {
  printf &amp;quot;[$(date +&#39;%Y-%m-%dT%H:%M:%S.%2N%z&#39;)][INFO] %b\n&amp;quot; &amp;quot;$@&amp;quot;
}

log::warning() {
  printf &amp;quot;[$(date +&#39;%Y-%m-%dT%H:%M:%S.%2N%z&#39;)][${YELLOW}WARNING${NC}] \033[0m%b\n&amp;quot; &amp;quot;$@&amp;quot;
}

check_file() {
  if [[ ! -r ${1} ]]; then
    log::err &amp;quot;can not find ${1}&amp;quot;
    exit 1
  fi
}

# get x509v3 subject alternative name from the old certificate
cert::get_subject_alt_name() {
  local cert=${1}.crt
  local alt_name

  check_file &amp;quot;${cert}&amp;quot;
  alt_name=$(openssl x509 -text -noout -in &amp;quot;${cert}&amp;quot; | grep -A1 &#39;Alternative&#39; | tail -n1 | sed &#39;s/[[:space:]]*Address//g&#39;)
  printf &amp;quot;%s\n&amp;quot; &amp;quot;${alt_name}&amp;quot;
}

# get subject from the old certificate
cert::get_subj() {
  local cert=${1}.crt
  local subj

  check_file &amp;quot;${cert}&amp;quot;
  subj=$(openssl x509 -text -noout -in &amp;quot;${cert}&amp;quot; | grep &amp;quot;Subject:&amp;quot; | sed &#39;s/Subject:/\//g;s/\,/\//;s/[[:space:]]//g&#39;)
  printf &amp;quot;%s\n&amp;quot; &amp;quot;${subj}&amp;quot;
}

cert::backup_file() {
  local file=${1}
  if [[ ! -e ${file}.old-$(date +%Y%m%d) ]]; then
    cp -rp &amp;quot;${file}&amp;quot; &amp;quot;${file}.old-$(date +%Y%m%d)&amp;quot;
    log::info &amp;quot;backup ${file} to ${file}.old-$(date +%Y%m%d)&amp;quot;
  else
    log::warning &amp;quot;does not backup, ${file}.old-$(date +%Y%m%d) already exists&amp;quot;
  fi
}

# check certificate expiration
cert::check_cert_expiration() {
  local cert=${1}.crt
  local cert_expires

  cert_expires=$(openssl x509 -text -noout -in &amp;quot;${cert}&amp;quot; | awk -F &amp;quot;: &amp;quot; &#39;/Not After/{print$2}&#39;)
  printf &amp;quot;%s\n&amp;quot; &amp;quot;${cert_expires}&amp;quot;
}

# check kubeconfig expiration
cert::check_kubeconfig_expiration() {
  local config=${1}.conf
  local cert
  local cert_expires

  cert=$(grep &amp;quot;client-certificate-data&amp;quot; &amp;quot;${config}&amp;quot; | awk &#39;{print$2}&#39; | base64 -d)
  cert_expires=$(openssl x509 -text -noout -in &amp;lt;(printf &amp;quot;%s&amp;quot; &amp;quot;${cert}&amp;quot;) | awk -F &amp;quot;: &amp;quot; &#39;/Not After/{print$2}&#39;)
  printf &amp;quot;%s\n&amp;quot; &amp;quot;${cert_expires}&amp;quot;
}

# check etcd certificates expiration
cert::check_etcd_certs_expiration() {
  local cert
  local certs

  certs=(
    &amp;quot;${ETCD_CERT_CA}&amp;quot;
    &amp;quot;${ETCD_CERT_SERVER}&amp;quot;
    &amp;quot;${ETCD_CERT_PEER}&amp;quot;
    &amp;quot;${ETCD_CERT_HEALTHCHECK_CLIENT}&amp;quot;
    &amp;quot;${ETCD_CERT_APISERVER_ETCD_CLIENT}&amp;quot;
  )

  for cert in &amp;quot;${certs[@]}&amp;quot;; do
    if [[ ! -r ${cert} ]]; then
      printf &amp;quot;%-50s%-30s\n&amp;quot; &amp;quot;${cert}.crt&amp;quot; &amp;quot;$(cert::check_cert_expiration &amp;quot;${cert}&amp;quot;)&amp;quot;
    fi
  done
}

# check master certificates expiration
cert::check_master_certs_expiration() {
  local certs
  local kubeconfs
  local cert
  local conf

  certs=(
    &amp;quot;${CERT_CA}&amp;quot;
    &amp;quot;${CERT_APISERVER}&amp;quot;
    &amp;quot;${CERT_APISERVER_KUBELET_CLIENT}&amp;quot;
    &amp;quot;${FRONT_PROXY_CA}&amp;quot;
    &amp;quot;${FRONT_PROXY_CLIENT}&amp;quot;
  )

  kubeconfs=(
    &amp;quot;${CONF_CONTROLLER_MANAGER}&amp;quot;
    &amp;quot;${CONF_SCHEDULER}&amp;quot;
    &amp;quot;${CONF_ADMIN}&amp;quot;
  )

  printf &amp;quot;%-50s%-30s\n&amp;quot; &amp;quot;CERTIFICATE&amp;quot; &amp;quot;EXPIRES&amp;quot;

  for conf in &amp;quot;${kubeconfs[@]}&amp;quot;; do
    if [[ ! -r ${conf} ]]; then
      printf &amp;quot;%-50s%-30s\n&amp;quot; &amp;quot;${conf}.config&amp;quot; &amp;quot;$(cert::check_kubeconfig_expiration &amp;quot;${conf}&amp;quot;)&amp;quot;
    fi
  done

  for cert in &amp;quot;${certs[@]}&amp;quot;; do
    if [[ ! -r ${cert} ]]; then
      printf &amp;quot;%-50s%-30s\n&amp;quot; &amp;quot;${cert}.crt&amp;quot; &amp;quot;$(cert::check_cert_expiration &amp;quot;${cert}&amp;quot;)&amp;quot;
    fi
  done
}

# check all certificates expiration
cert::check_all_expiration() {
  cert::check_master_certs_expiration
  cert::check_etcd_certs_expiration
}

# generate certificate whit client, server or peer
# Args:
#   $1 (the name of certificate)
#   $2 (the type of certificate, must be one of client, server, peer)
#   $3 (the subject of certificates)
#   $4 (the validity of certificates) (days)
#   $5 (the name of ca)
#   $6 (the x509v3 subject alternative name of certificate when the type of certificate is server or peer)
cert::gen_cert() {
  local cert_name=${1}
  local cert_type=${2}
  local subj=${3}
  local cert_days=${4}
  local ca_name=${5}
  local alt_name=${6}
  local ca_cert=${ca_name}.crt
  local ca_key=${ca_name}.key
  local cert=${cert_name}.crt
  local key=${cert_name}.key
  local csr=${cert_name}.csr
  local common_csr_conf=&#39;distinguished_name = dn\n[dn]\n[v3_ext]\nkeyUsage = critical, digitalSignature, keyEncipherment\n&#39;

  for file in &amp;quot;${ca_cert}&amp;quot; &amp;quot;${ca_key}&amp;quot; &amp;quot;${cert}&amp;quot; &amp;quot;${key}&amp;quot;; do
    check_file &amp;quot;${file}&amp;quot;
  done

  case &amp;quot;${cert_type}&amp;quot; in
  client)
    csr_conf=$(printf &amp;quot;%bextendedKeyUsage = clientAuth\n&amp;quot; &amp;quot;${common_csr_conf}&amp;quot;)
    ;;
  server)
    csr_conf=$(printf &amp;quot;%bextendedKeyUsage = serverAuth\nsubjectAltName = %b\n&amp;quot; &amp;quot;${common_csr_conf}&amp;quot; &amp;quot;${alt_name}&amp;quot;)
    ;;
  peer)
    csr_conf=$(printf &amp;quot;%bextendedKeyUsage = serverAuth, clientAuth\nsubjectAltName = %b\n&amp;quot; &amp;quot;${common_csr_conf}&amp;quot; &amp;quot;${alt_name}&amp;quot;)
    ;;
  *)
    log::err &amp;quot;unknow, unsupported certs type: ${YELLOW}${cert_type}${NC}, supported type: client, server, peer&amp;quot;
    exit 1
    ;;
  esac

  # gen csr
  openssl req -new -key &amp;quot;${key}&amp;quot; -subj &amp;quot;${subj}&amp;quot; -reqexts v3_ext \
    -config &amp;lt;(printf &amp;quot;%b&amp;quot; &amp;quot;${csr_conf}&amp;quot;) \
    -out &amp;quot;${csr}&amp;quot; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1
  # gen cert
  openssl x509 -in &amp;quot;${csr}&amp;quot; -req -CA &amp;quot;${ca_cert}&amp;quot; -CAkey &amp;quot;${ca_key}&amp;quot; -CAcreateserial -extensions v3_ext \
    -extfile &amp;lt;(printf &amp;quot;%b&amp;quot; &amp;quot;${csr_conf}&amp;quot;) \
    -days &amp;quot;${cert_days}&amp;quot; -out &amp;quot;${cert}&amp;quot; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1

  rm -f &amp;quot;${csr}&amp;quot;
}

cert::update_kubeconf() {
  local cert_name=${1}
  local kubeconf_file=${cert_name}.conf
  local cert=${cert_name}.crt
  local key=${cert_name}.key
  local subj
  local cert_base64

  check_file &amp;quot;${kubeconf_file}&amp;quot;
  # get the key from the old kubeconf
  grep &amp;quot;client-key-data&amp;quot; &amp;quot;${kubeconf_file}&amp;quot; | awk &#39;{print$2}&#39; | base64 -d &amp;gt;&amp;quot;${key}&amp;quot;
  # get the old certificate from the old kubeconf
  grep &amp;quot;client-certificate-data&amp;quot; &amp;quot;${kubeconf_file}&amp;quot; | awk &#39;{print$2}&#39; | base64 -d &amp;gt;&amp;quot;${cert}&amp;quot;
  # get subject from the old certificate
  subj=$(cert::get_subj &amp;quot;${cert_name}&amp;quot;)
  cert::gen_cert &amp;quot;${cert_name}&amp;quot; &amp;quot;client&amp;quot; &amp;quot;${subj}&amp;quot; &amp;quot;${CERT_DAYS}&amp;quot; &amp;quot;${CERT_CA}&amp;quot;
  # get certificate base64 code
  cert_base64=$(base64 -w 0 &amp;quot;${cert}&amp;quot;)

  # set certificate base64 code to kubeconf
  sed -i &#39;s/client-certificate-data:.*/client-certificate-data: &#39;&amp;quot;${cert_base64}&amp;quot;&#39;/g&#39; &amp;quot;${kubeconf_file}&amp;quot;

  rm -f &amp;quot;${cert}&amp;quot;
  rm -f &amp;quot;${key}&amp;quot;
}

cert::update_etcd_cert() {
  local subj
  local subject_alt_name
  local cert

  # generate etcd server,peer certificate
  # /etc/kubernetes/pki/etcd/server
  # /etc/kubernetes/pki/etcd/peer
  for cert in ${ETCD_CERT_SERVER} ${ETCD_CERT_PEER}; do
    subj=$(cert::get_subj &amp;quot;${cert}&amp;quot;)
    subject_alt_name=$(cert::get_subject_alt_name &amp;quot;${cert}&amp;quot;)
    cert::gen_cert &amp;quot;${cert}&amp;quot; &amp;quot;peer&amp;quot; &amp;quot;${subj}&amp;quot; &amp;quot;${CERT_DAYS}&amp;quot; &amp;quot;${ETCD_CERT_CA}&amp;quot; &amp;quot;${subject_alt_name}&amp;quot;
    log::info &amp;quot;${GREEN}updated ${BLUE}${cert}.conf${NC}&amp;quot;
  done

  # generate etcd healthcheck-client,apiserver-etcd-client certificate
  # /etc/kubernetes/pki/etcd/healthcheck-client
  # /etc/kubernetes/pki/apiserver-etcd-client
  for cert in ${ETCD_CERT_HEALTHCHECK_CLIENT} ${ETCD_CERT_APISERVER_ETCD_CLIENT}; do
    subj=$(cert::get_subj &amp;quot;${cert}&amp;quot;)
    cert::gen_cert &amp;quot;${cert}&amp;quot; &amp;quot;client&amp;quot; &amp;quot;${subj}&amp;quot; &amp;quot;${CERT_DAYS}&amp;quot; &amp;quot;${ETCD_CERT_CA}&amp;quot;
    log::info &amp;quot;${GREEN}updated ${BLUE}${cert}.conf${NC}&amp;quot;
  done

  # restart etcd
  docker ps | awk &#39;/k8s_etcd/{print$1}&#39; | xargs -r -I &#39;{}&#39; docker restart {} &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 || true
  log::info &amp;quot;restarted etcd&amp;quot;
}

cert::update_master_cert() {
  local subj
  local subject_alt_name
  local conf

  # generate apiserver server certificate
  # /etc/kubernetes/pki/apiserver
  subj=$(cert::get_subj &amp;quot;${CERT_APISERVER}&amp;quot;)
  subject_alt_name=$(cert::get_subject_alt_name &amp;quot;${CERT_APISERVER}&amp;quot;)
  cert::gen_cert &amp;quot;${CERT_APISERVER}&amp;quot; &amp;quot;server&amp;quot; &amp;quot;${subj}&amp;quot; &amp;quot;${CERT_DAYS}&amp;quot; &amp;quot;${CERT_CA}&amp;quot; &amp;quot;${subject_alt_name}&amp;quot;
  log::info &amp;quot;${GREEN}updated ${BLUE}${CERT_APISERVER}.crt${NC}&amp;quot;

  # generate apiserver-kubelet-client certificate
  # /etc/kubernetes/pki/apiserver-kubelet-client
  subj=$(cert::get_subj &amp;quot;${CERT_APISERVER_KUBELET_CLIENT}&amp;quot;)
  cert::gen_cert &amp;quot;${CERT_APISERVER_KUBELET_CLIENT}&amp;quot; &amp;quot;client&amp;quot; &amp;quot;${subj}&amp;quot; &amp;quot;${CERT_DAYS}&amp;quot; &amp;quot;${CERT_CA}&amp;quot;
  log::info &amp;quot;${GREEN}updated ${BLUE}${CERT_APISERVER_KUBELET_CLIENT}.crt${NC}&amp;quot;

  # generate kubeconf for controller-manager,scheduler and kubelet
  # /etc/kubernetes/controller-manager,scheduler,admin,kubelet.conf
  for conf in ${CONF_CONTROLLER_MANAGER} ${CONF_SCHEDULER} ${CONF_ADMIN} ${CONF_KUBELET}; do
    if [[ ${conf##*/} == &amp;quot;kubelet&amp;quot; ]]; then
      # https://github.com/kubernetes/kubeadm/issues/1753
      set +e
      grep kubelet-client-current.pem /etc/kubernetes/kubelet.conf &amp;gt;/dev/null 2&amp;gt;&amp;amp;1
      kubelet_cert_auto_update=$?
      set -e
      if [[ &amp;quot;$kubelet_cert_auto_update&amp;quot; == &amp;quot;0&amp;quot; ]]; then
        log::info &amp;quot;does not need to update kubelet.conf&amp;quot;
        continue
      fi
    fi

    # update kubeconf
    cert::update_kubeconf &amp;quot;${conf}&amp;quot;
    log::info &amp;quot;${GREEN}updated ${BLUE}${conf}.conf${NC}&amp;quot;

    # copy admin.conf to ${HOME}/.kube/config
    if [[ ${conf##*/} == &amp;quot;admin&amp;quot; ]]; then
      mkdir -p &amp;quot;${HOME}/.kube&amp;quot;
      local config=${HOME}/.kube/config
      local config_backup
      config_backup=${HOME}/.kube/config.old-$(date +%Y%m%d)
      if [[ -f ${config} ]] &amp;amp;&amp;amp; [[ ! -f ${config_backup} ]]; then
        cp -fp &amp;quot;${config}&amp;quot; &amp;quot;${config_backup}&amp;quot;
        log::info &amp;quot;backup ${config} to ${config_backup}&amp;quot;
      fi
      cp -fp &amp;quot;${conf}.conf&amp;quot; &amp;quot;${HOME}/.kube/config&amp;quot;
      log::info &amp;quot;copy the admin.conf to ${HOME}/.kube/config&amp;quot;
    fi
  done

  # generate front-proxy-client certificate
  # /etc/kubernetes/pki/front-proxy-client
  subj=$(cert::get_subj &amp;quot;${FRONT_PROXY_CLIENT}&amp;quot;)
  cert::gen_cert &amp;quot;${FRONT_PROXY_CLIENT}&amp;quot; &amp;quot;client&amp;quot; &amp;quot;${subj}&amp;quot; &amp;quot;${CERT_DAYS}&amp;quot; &amp;quot;${FRONT_PROXY_CA}&amp;quot;
  log::info &amp;quot;${GREEN}updated ${BLUE}${FRONT_PROXY_CLIENT}.crt${NC}&amp;quot;

  # restart apiserver, controller-manager, scheduler and kubelet
  for item in &amp;quot;apiserver&amp;quot; &amp;quot;controller-manager&amp;quot; &amp;quot;scheduler&amp;quot;; do
    docker ps | awk &#39;/k8s_kube-&#39;${item}&#39;/{print$1}&#39; | xargs -r -I &#39;{}&#39; docker restart {} &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 || true
    log::info &amp;quot;restarted ${item}&amp;quot;
  done
  systemctl restart kubelet || true
  log::info &amp;quot;restarted kubelet&amp;quot;
}

main() {
  local node_type=$1

  CERT_DAYS=3650

  KUBE_PATH=/etc/kubernetes
  PKI_PATH=${KUBE_PATH}/pki

  # master certificates path
  # apiserver
  CERT_CA=${PKI_PATH}/ca
  CERT_APISERVER=${PKI_PATH}/apiserver
  CERT_APISERVER_KUBELET_CLIENT=${PKI_PATH}/apiserver-kubelet-client
  CONF_CONTROLLER_MANAGER=${KUBE_PATH}/controller-manager
  CONF_SCHEDULER=${KUBE_PATH}/scheduler
  CONF_ADMIN=${KUBE_PATH}/admin
  CONF_KUBELET=${KUBE_PATH}/kubelet
  # front-proxy
  FRONT_PROXY_CA=${PKI_PATH}/front-proxy-ca
  FRONT_PROXY_CLIENT=${PKI_PATH}/front-proxy-client

  # etcd certificates path
  ETCD_CERT_CA=${PKI_PATH}/etcd/ca
  ETCD_CERT_SERVER=${PKI_PATH}/etcd/server
  ETCD_CERT_PEER=${PKI_PATH}/etcd/peer
  ETCD_CERT_HEALTHCHECK_CLIENT=${PKI_PATH}/etcd/healthcheck-client
  ETCD_CERT_APISERVER_ETCD_CLIENT=${PKI_PATH}/apiserver-etcd-client

  case ${node_type} in
  # etcd)
  # # update etcd certificates
  #   cert::update_etcd_cert
  # ;;
  master)
    # check certificates expiration
    cert::check_master_certs_expiration
    # backup $KUBE_PATH to $KUBE_PATH.old-$(date +%Y%m%d)
    cert::backup_file &amp;quot;${KUBE_PATH}&amp;quot;
    # update master certificates and kubeconf
    log::info &amp;quot;${GREEN}updating...${NC}&amp;quot;
    cert::update_master_cert
    log::info &amp;quot;${GREEN}done!!!${NC}&amp;quot;
    # check certificates expiration after certificates updated
    cert::check_master_certs_expiration
    ;;
  all)
    # check certificates expiration
    cert::check_all_expiration
    # backup $KUBE_PATH to $KUBE_PATH.old-$(date +%Y%m%d)
    cert::backup_file &amp;quot;${KUBE_PATH}&amp;quot;
    # update etcd certificates
    log::info &amp;quot;${GREEN}updating...${NC}&amp;quot;
    cert::update_etcd_cert
    # update master certificates and kubeconf
    cert::update_master_cert
    log::info &amp;quot;${GREEN}done!!!${NC}&amp;quot;
    # check certificates expiration after certificates updated
    cert::check_all_expiration
    ;;
  check)
    # check certificates expiration
    cert::check_all_expiration
    ;;
  *)
    log::err &amp;quot;unknown, unsupported cert type: ${node_type}, supported type: \&amp;quot;all\&amp;quot;, \&amp;quot;master\&amp;quot;&amp;quot;
    printf &amp;quot;Documentation: https://github.com/yuyicai/update-kube-cert
  example:
    &#39;\033[32m./update-kubeadm-cert.sh all\033[0m&#39; update all etcd certificates, master certificates and kubeconf
      /etc/kubernetes
      ├── admin.conf
      ├── controller-manager.conf
      ├── scheduler.conf
      ├── kubelet.conf
      └── pki
          ├── apiserver.crt
          ├── apiserver-etcd-client.crt
          ├── apiserver-kubelet-client.crt
          ├── front-proxy-client.crt
          └── etcd
              ├── healthcheck-client.crt
              ├── peer.crt
              └── server.crt

    &#39;\033[32m./update-kubeadm-cert.sh master\033[0m&#39; update only master certificates and kubeconf
      /etc/kubernetes
      ├── admin.conf
      ├── controller-manager.conf
      ├── scheduler.conf
      ├── kubelet.conf
      └── pki
          ├── apiserver.crt
          ├── apiserver-kubelet-client.crt
          └── front-proxy-client.crt
&amp;quot;
    exit 1
    ;;
  esac
}

main &amp;quot;$@&amp;quot;


&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;update-kubeadm-cert-crictlsh脚本&#34;&gt;update-kubeadm-cert-crictl.sh脚本&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#!/usr/bin/env bash

set -o errexit
set -o pipefail
# set -o xtrace

# set output color
NC=&#39;\033[0m&#39;
RED=&#39;\033[31m&#39;
GREEN=&#39;\033[32m&#39;
YELLOW=&#39;\033[33m&#39;
BLUE=&#39;\033[34m&#39;

log::err() {
  printf &amp;quot;[$(date +&#39;%Y-%m-%dT%H:%M:%S.%2N%z&#39;)][${RED}ERROR${NC}] %b\n&amp;quot; &amp;quot;$@&amp;quot;
}

log::info() {
  printf &amp;quot;[$(date +&#39;%Y-%m-%dT%H:%M:%S.%2N%z&#39;)][INFO] %b\n&amp;quot; &amp;quot;$@&amp;quot;
}

log::warning() {
  printf &amp;quot;[$(date +&#39;%Y-%m-%dT%H:%M:%S.%2N%z&#39;)][${YELLOW}WARNING${NC}] \033[0m%b\n&amp;quot; &amp;quot;$@&amp;quot;
}

check_file() {
  if [[ ! -r ${1} ]]; then
    log::err &amp;quot;can not find ${1}&amp;quot;
    exit 1
  fi
}

# get x509v3 subject alternative name from the old certificate
cert::get_subject_alt_name() {
  local cert=${1}.crt
  local alt_name

  check_file &amp;quot;${cert}&amp;quot;
  alt_name=$(openssl x509 -text -noout -in &amp;quot;${cert}&amp;quot; | grep -A1 &#39;Alternative&#39; | tail -n1 | sed &#39;s/[[:space:]]*Address//g&#39;)
  printf &amp;quot;%s\n&amp;quot; &amp;quot;${alt_name}&amp;quot;
}

# get subject from the old certificate
cert::get_subj() {
  local cert=${1}.crt
  local subj

  check_file &amp;quot;${cert}&amp;quot;
  subj=$(openssl x509 -text -noout -in &amp;quot;${cert}&amp;quot; | grep &amp;quot;Subject:&amp;quot; | sed &#39;s/Subject:/\//g;s/\,/\//;s/[[:space:]]//g&#39;)
  printf &amp;quot;%s\n&amp;quot; &amp;quot;${subj}&amp;quot;
}

cert::backup_file() {
  local file=${1}
  if [[ ! -e ${file}.old-$(date +%Y%m%d) ]]; then
    cp -rp &amp;quot;${file}&amp;quot; &amp;quot;${file}.old-$(date +%Y%m%d)&amp;quot;
    log::info &amp;quot;backup ${file} to ${file}.old-$(date +%Y%m%d)&amp;quot;
  else
    log::warning &amp;quot;does not backup, ${file}.old-$(date +%Y%m%d) already exists&amp;quot;
  fi
}

# check certificate expiration
cert::check_cert_expiration() {
  local cert=${1}.crt
  local cert_expires

  cert_expires=$(openssl x509 -text -noout -in &amp;quot;${cert}&amp;quot; | awk -F &amp;quot;: &amp;quot; &#39;/Not After/{print$2}&#39;)
  printf &amp;quot;%s\n&amp;quot; &amp;quot;${cert_expires}&amp;quot;
}

# check kubeconfig expiration
cert::check_kubeconfig_expiration() {
  local config=${1}.conf
  local cert
  local cert_expires

  cert=$(grep &amp;quot;client-certificate-data&amp;quot; &amp;quot;${config}&amp;quot; | awk &#39;{print$2}&#39; | base64 -d)
  cert_expires=$(openssl x509 -text -noout -in &amp;lt;(printf &amp;quot;%s&amp;quot; &amp;quot;${cert}&amp;quot;) | awk -F &amp;quot;: &amp;quot; &#39;/Not After/{print$2}&#39;)
  printf &amp;quot;%s\n&amp;quot; &amp;quot;${cert_expires}&amp;quot;
}

# check etcd certificates expiration
cert::check_etcd_certs_expiration() {
  local cert
  local certs

  certs=(
    &amp;quot;${ETCD_CERT_CA}&amp;quot;
    &amp;quot;${ETCD_CERT_SERVER}&amp;quot;
    &amp;quot;${ETCD_CERT_PEER}&amp;quot;
    &amp;quot;${ETCD_CERT_HEALTHCHECK_CLIENT}&amp;quot;
    &amp;quot;${ETCD_CERT_APISERVER_ETCD_CLIENT}&amp;quot;
  )

  for cert in &amp;quot;${certs[@]}&amp;quot;; do
    if [[ ! -r ${cert} ]]; then
      printf &amp;quot;%-50s%-30s\n&amp;quot; &amp;quot;${cert}.crt&amp;quot; &amp;quot;$(cert::check_cert_expiration &amp;quot;${cert}&amp;quot;)&amp;quot;
    fi
  done
}

# check master certificates expiration
cert::check_master_certs_expiration() {
  local certs
  local kubeconfs
  local cert
  local conf

  certs=(
    &amp;quot;${CERT_CA}&amp;quot;
    &amp;quot;${CERT_APISERVER}&amp;quot;
    &amp;quot;${CERT_APISERVER_KUBELET_CLIENT}&amp;quot;
    &amp;quot;${FRONT_PROXY_CA}&amp;quot;
    &amp;quot;${FRONT_PROXY_CLIENT}&amp;quot;
  )

  kubeconfs=(
    &amp;quot;${CONF_CONTROLLER_MANAGER}&amp;quot;
    &amp;quot;${CONF_SCHEDULER}&amp;quot;
    &amp;quot;${CONF_ADMIN}&amp;quot;
  )

  printf &amp;quot;%-50s%-30s\n&amp;quot; &amp;quot;CERTIFICATE&amp;quot; &amp;quot;EXPIRES&amp;quot;

  for conf in &amp;quot;${kubeconfs[@]}&amp;quot;; do
    if [[ ! -r ${conf} ]]; then
      printf &amp;quot;%-50s%-30s\n&amp;quot; &amp;quot;${conf}.config&amp;quot; &amp;quot;$(cert::check_kubeconfig_expiration &amp;quot;${conf}&amp;quot;)&amp;quot;
    fi
  done

  for cert in &amp;quot;${certs[@]}&amp;quot;; do
    if [[ ! -r ${cert} ]]; then
      printf &amp;quot;%-50s%-30s\n&amp;quot; &amp;quot;${cert}.crt&amp;quot; &amp;quot;$(cert::check_cert_expiration &amp;quot;${cert}&amp;quot;)&amp;quot;
    fi
  done
}

# check all certificates expiration
cert::check_all_expiration() {
  cert::check_master_certs_expiration
  cert::check_etcd_certs_expiration
}

# generate certificate whit client, server or peer
# Args:
#   $1 (the name of certificate)
#   $2 (the type of certificate, must be one of client, server, peer)
#   $3 (the subject of certificates)
#   $4 (the validity of certificates) (days)
#   $5 (the name of ca)
#   $6 (the x509v3 subject alternative name of certificate when the type of certificate is server or peer)
cert::gen_cert() {
  local cert_name=${1}
  local cert_type=${2}
  local subj=${3}
  local cert_days=${4}
  local ca_name=${5}
  local alt_name=${6}
  local ca_cert=${ca_name}.crt
  local ca_key=${ca_name}.key
  local cert=${cert_name}.crt
  local key=${cert_name}.key
  local csr=${cert_name}.csr
  local common_csr_conf=&#39;distinguished_name = dn\n[dn]\n[v3_ext]\nkeyUsage = critical, digitalSignature, keyEncipherment\n&#39;

  for file in &amp;quot;${ca_cert}&amp;quot; &amp;quot;${ca_key}&amp;quot; &amp;quot;${cert}&amp;quot; &amp;quot;${key}&amp;quot;; do
    check_file &amp;quot;${file}&amp;quot;
  done

  case &amp;quot;${cert_type}&amp;quot; in
  client)
    csr_conf=$(printf &amp;quot;%bextendedKeyUsage = clientAuth\n&amp;quot; &amp;quot;${common_csr_conf}&amp;quot;)
    ;;
  server)
    csr_conf=$(printf &amp;quot;%bextendedKeyUsage = serverAuth\nsubjectAltName = %b\n&amp;quot; &amp;quot;${common_csr_conf}&amp;quot; &amp;quot;${alt_name}&amp;quot;)
    ;;
  peer)
    csr_conf=$(printf &amp;quot;%bextendedKeyUsage = serverAuth, clientAuth\nsubjectAltName = %b\n&amp;quot; &amp;quot;${common_csr_conf}&amp;quot; &amp;quot;${alt_name}&amp;quot;)
    ;;
  *)
    log::err &amp;quot;unknow, unsupported certs type: ${YELLOW}${cert_type}${NC}, supported type: client, server, peer&amp;quot;
    exit 1
    ;;
  esac

  # gen csr
  openssl req -new -key &amp;quot;${key}&amp;quot; -subj &amp;quot;${subj}&amp;quot; -reqexts v3_ext \
    -config &amp;lt;(printf &amp;quot;%b&amp;quot; &amp;quot;${csr_conf}&amp;quot;) \
    -out &amp;quot;${csr}&amp;quot; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1
  # gen cert
  openssl x509 -in &amp;quot;${csr}&amp;quot; -req -CA &amp;quot;${ca_cert}&amp;quot; -CAkey &amp;quot;${ca_key}&amp;quot; -CAcreateserial -extensions v3_ext \
    -extfile &amp;lt;(printf &amp;quot;%b&amp;quot; &amp;quot;${csr_conf}&amp;quot;) \
    -days &amp;quot;${cert_days}&amp;quot; -out &amp;quot;${cert}&amp;quot; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1

  rm -f &amp;quot;${csr}&amp;quot;
}

cert::update_kubeconf() {
  local cert_name=${1}
  local kubeconf_file=${cert_name}.conf
  local cert=${cert_name}.crt
  local key=${cert_name}.key
  local subj
  local cert_base64

  check_file &amp;quot;${kubeconf_file}&amp;quot;
  # get the key from the old kubeconf
  grep &amp;quot;client-key-data&amp;quot; &amp;quot;${kubeconf_file}&amp;quot; | awk &#39;{print$2}&#39; | base64 -d &amp;gt;&amp;quot;${key}&amp;quot;
  # get the old certificate from the old kubeconf
  grep &amp;quot;client-certificate-data&amp;quot; &amp;quot;${kubeconf_file}&amp;quot; | awk &#39;{print$2}&#39; | base64 -d &amp;gt;&amp;quot;${cert}&amp;quot;
  # get subject from the old certificate
  subj=$(cert::get_subj &amp;quot;${cert_name}&amp;quot;)
  cert::gen_cert &amp;quot;${cert_name}&amp;quot; &amp;quot;client&amp;quot; &amp;quot;${subj}&amp;quot; &amp;quot;${CERT_DAYS}&amp;quot; &amp;quot;${CERT_CA}&amp;quot;
  # get certificate base64 code
  cert_base64=$(base64 -w 0 &amp;quot;${cert}&amp;quot;)

  # set certificate base64 code to kubeconf
  sed -i &#39;s/client-certificate-data:.*/client-certificate-data: &#39;&amp;quot;${cert_base64}&amp;quot;&#39;/g&#39; &amp;quot;${kubeconf_file}&amp;quot;

  rm -f &amp;quot;${cert}&amp;quot;
  rm -f &amp;quot;${key}&amp;quot;
}

cert::update_etcd_cert() {
  local subj
  local subject_alt_name
  local cert

  # generate etcd server,peer certificate
  # /etc/kubernetes/pki/etcd/server
  # /etc/kubernetes/pki/etcd/peer
  for cert in ${ETCD_CERT_SERVER} ${ETCD_CERT_PEER}; do
    subj=$(cert::get_subj &amp;quot;${cert}&amp;quot;)
    subject_alt_name=$(cert::get_subject_alt_name &amp;quot;${cert}&amp;quot;)
    cert::gen_cert &amp;quot;${cert}&amp;quot; &amp;quot;peer&amp;quot; &amp;quot;${subj}&amp;quot; &amp;quot;${CERT_DAYS}&amp;quot; &amp;quot;${ETCD_CERT_CA}&amp;quot; &amp;quot;${subject_alt_name}&amp;quot;
    log::info &amp;quot;${GREEN}updated ${BLUE}${cert}.conf${NC}&amp;quot;
  done

  # generate etcd healthcheck-client,apiserver-etcd-client certificate
  # /etc/kubernetes/pki/etcd/healthcheck-client
  # /etc/kubernetes/pki/apiserver-etcd-client
  for cert in ${ETCD_CERT_HEALTHCHECK_CLIENT} ${ETCD_CERT_APISERVER_ETCD_CLIENT}; do
    subj=$(cert::get_subj &amp;quot;${cert}&amp;quot;)
    cert::gen_cert &amp;quot;${cert}&amp;quot; &amp;quot;client&amp;quot; &amp;quot;${subj}&amp;quot; &amp;quot;${CERT_DAYS}&amp;quot; &amp;quot;${ETCD_CERT_CA}&amp;quot;
    log::info &amp;quot;${GREEN}updated ${BLUE}${cert}.conf${NC}&amp;quot;
  done

  # restart etcd
  #docker ps | awk &#39;/k8s_etcd/{print$1}&#39; | xargs -r -I &#39;{}&#39; docker restart {} &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 || true
  crictl ps | awk &#39;/etcd-/{print$(NF-1)}&#39; |xargs -r -I &#39;{}&#39; crictl stopp {} &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 || true
  log::info &amp;quot;restarted etcd&amp;quot;
}

cert::update_master_cert() {
  local subj
  local subject_alt_name
  local conf

  # generate apiserver server certificate
  # /etc/kubernetes/pki/apiserver
  subj=$(cert::get_subj &amp;quot;${CERT_APISERVER}&amp;quot;)
  subject_alt_name=$(cert::get_subject_alt_name &amp;quot;${CERT_APISERVER}&amp;quot;)
  cert::gen_cert &amp;quot;${CERT_APISERVER}&amp;quot; &amp;quot;server&amp;quot; &amp;quot;${subj}&amp;quot; &amp;quot;${CERT_DAYS}&amp;quot; &amp;quot;${CERT_CA}&amp;quot; &amp;quot;${subject_alt_name}&amp;quot;
  log::info &amp;quot;${GREEN}updated ${BLUE}${CERT_APISERVER}.crt${NC}&amp;quot;

  # generate apiserver-kubelet-client certificate
  # /etc/kubernetes/pki/apiserver-kubelet-client
  subj=$(cert::get_subj &amp;quot;${CERT_APISERVER_KUBELET_CLIENT}&amp;quot;)
  cert::gen_cert &amp;quot;${CERT_APISERVER_KUBELET_CLIENT}&amp;quot; &amp;quot;client&amp;quot; &amp;quot;${subj}&amp;quot; &amp;quot;${CERT_DAYS}&amp;quot; &amp;quot;${CERT_CA}&amp;quot;
  log::info &amp;quot;${GREEN}updated ${BLUE}${CERT_APISERVER_KUBELET_CLIENT}.crt${NC}&amp;quot;

  # generate kubeconf for controller-manager,scheduler and kubelet
  # /etc/kubernetes/controller-manager,scheduler,admin,kubelet.conf
  for conf in ${CONF_CONTROLLER_MANAGER} ${CONF_SCHEDULER} ${CONF_ADMIN} ${CONF_KUBELET}; do
    if [[ ${conf##*/} == &amp;quot;kubelet&amp;quot; ]]; then
      # https://github.com/kubernetes/kubeadm/issues/1753
      set +e
      grep kubelet-client-current.pem /etc/kubernetes/kubelet.conf &amp;gt;/dev/null 2&amp;gt;&amp;amp;1
      kubelet_cert_auto_update=$?
      set -e
      if [[ &amp;quot;$kubelet_cert_auto_update&amp;quot; == &amp;quot;0&amp;quot; ]]; then
        log::info &amp;quot;does not need to update kubelet.conf&amp;quot;
        continue
      fi
    fi

    # update kubeconf
    cert::update_kubeconf &amp;quot;${conf}&amp;quot;
    log::info &amp;quot;${GREEN}updated ${BLUE}${conf}.conf${NC}&amp;quot;

    # copy admin.conf to ${HOME}/.kube/config
    if [[ ${conf##*/} == &amp;quot;admin&amp;quot; ]]; then
      mkdir -p &amp;quot;${HOME}/.kube&amp;quot;
      local config=${HOME}/.kube/config
      local config_backup
      config_backup=${HOME}/.kube/config.old-$(date +%Y%m%d)
      if [[ -f ${config} ]] &amp;amp;&amp;amp; [[ ! -f ${config_backup} ]]; then
        cp -fp &amp;quot;${config}&amp;quot; &amp;quot;${config_backup}&amp;quot;
        log::info &amp;quot;backup ${config} to ${config_backup}&amp;quot;
      fi
      cp -fp &amp;quot;${conf}.conf&amp;quot; &amp;quot;${HOME}/.kube/config&amp;quot;
      log::info &amp;quot;copy the admin.conf to ${HOME}/.kube/config&amp;quot;
    fi
  done

  # generate front-proxy-client certificate
  # /etc/kubernetes/pki/front-proxy-client
  subj=$(cert::get_subj &amp;quot;${FRONT_PROXY_CLIENT}&amp;quot;)
  cert::gen_cert &amp;quot;${FRONT_PROXY_CLIENT}&amp;quot; &amp;quot;client&amp;quot; &amp;quot;${subj}&amp;quot; &amp;quot;${CERT_DAYS}&amp;quot; &amp;quot;${FRONT_PROXY_CA}&amp;quot;
  log::info &amp;quot;${GREEN}updated ${BLUE}${FRONT_PROXY_CLIENT}.crt${NC}&amp;quot;

  # restart apiserver, controller-manager, scheduler and kubelet
  for item in &amp;quot;apiserver&amp;quot; &amp;quot;controller-manager&amp;quot; &amp;quot;scheduler&amp;quot;; do
    #docker ps | awk &#39;/k8s_kube-&#39;${item}&#39;/{print$1}&#39; | xargs -r -I &#39;{}&#39; docker restart {} &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 || true
    crictl ps | awk &#39;/kube-&#39;${item}&#39;-/{print $(NF-1)}&#39; | xargs -r -I &#39;{}&#39; crictl stopp {} &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 || true 
    log::info &amp;quot;restarted ${item}&amp;quot;
  done
  systemctl restart kubelet || true
  log::info &amp;quot;restarted kubelet&amp;quot;
}

main() {
  local node_type=$1

  CERT_DAYS=3650

  KUBE_PATH=/etc/kubernetes
  PKI_PATH=${KUBE_PATH}/pki

  # master certificates path
  # apiserver
  CERT_CA=${PKI_PATH}/ca
  CERT_APISERVER=${PKI_PATH}/apiserver
  CERT_APISERVER_KUBELET_CLIENT=${PKI_PATH}/apiserver-kubelet-client
  CONF_CONTROLLER_MANAGER=${KUBE_PATH}/controller-manager
  CONF_SCHEDULER=${KUBE_PATH}/scheduler
  CONF_ADMIN=${KUBE_PATH}/admin
  CONF_KUBELET=${KUBE_PATH}/kubelet
  # front-proxy
  FRONT_PROXY_CA=${PKI_PATH}/front-proxy-ca
  FRONT_PROXY_CLIENT=${PKI_PATH}/front-proxy-client

  # etcd certificates path
  ETCD_CERT_CA=${PKI_PATH}/etcd/ca
  ETCD_CERT_SERVER=${PKI_PATH}/etcd/server
  ETCD_CERT_PEER=${PKI_PATH}/etcd/peer
  ETCD_CERT_HEALTHCHECK_CLIENT=${PKI_PATH}/etcd/healthcheck-client
  ETCD_CERT_APISERVER_ETCD_CLIENT=${PKI_PATH}/apiserver-etcd-client

  case ${node_type} in
  # etcd)
  # # update etcd certificates
  #   cert::update_etcd_cert
  # ;;
  master)
    # check certificates expiration
    cert::check_master_certs_expiration
    # backup $KUBE_PATH to $KUBE_PATH.old-$(date +%Y%m%d)
    cert::backup_file &amp;quot;${KUBE_PATH}&amp;quot;
    # update master certificates and kubeconf
    log::info &amp;quot;${GREEN}updating...${NC}&amp;quot;
    cert::update_master_cert
    log::info &amp;quot;${GREEN}done!!!${NC}&amp;quot;
    # check certificates expiration after certificates updated
    cert::check_master_certs_expiration
    ;;
  all)
    # check certificates expiration
    cert::check_all_expiration
    # backup $KUBE_PATH to $KUBE_PATH.old-$(date +%Y%m%d)
    cert::backup_file &amp;quot;${KUBE_PATH}&amp;quot;
    # update etcd certificates
    log::info &amp;quot;${GREEN}updating...${NC}&amp;quot;
    cert::update_etcd_cert
    # update master certificates and kubeconf
    cert::update_master_cert
    log::info &amp;quot;${GREEN}done!!!${NC}&amp;quot;
    # check certificates expiration after certificates updated
    cert::check_all_expiration
    ;;
  check)
    # check certificates expiration
    cert::check_all_expiration
    ;;
  *)
    log::err &amp;quot;unknown, unsupported cert type: ${node_type}, supported type: \&amp;quot;all\&amp;quot;, \&amp;quot;master\&amp;quot;&amp;quot;
    printf &amp;quot;Documentation: https://github.com/yuyicai/update-kube-cert
  example:
    &#39;\033[32m./update-kubeadm-cert.sh all\033[0m&#39; update all etcd certificates, master certificates and kubeconf
      /etc/kubernetes
      ├── admin.conf
      ├── controller-manager.conf
      ├── scheduler.conf
      ├── kubelet.conf
      └── pki
          ├── apiserver.crt
          ├── apiserver-etcd-client.crt
          ├── apiserver-kubelet-client.crt
          ├── front-proxy-client.crt
          └── etcd
              ├── healthcheck-client.crt
              ├── peer.crt
              └── server.crt

    &#39;\033[32m./update-kubeadm-cert.sh master\033[0m&#39; update only master certificates and kubeconf
      /etc/kubernetes
      ├── admin.conf
      ├── controller-manager.conf
      ├── scheduler.conf
      ├── kubelet.conf
      └── pki
          ├── apiserver.crt
          ├── apiserver-kubelet-client.crt
          └── front-proxy-client.crt
&amp;quot;
    exit 1
    ;;
  esac
}

main &amp;quot;$@&amp;quot;


&lt;/code&gt;&lt;/pre&gt;</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/k8s/" term="k8s" label="k8s" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/k8s/" term="k8s" label="k8s" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">K8s离线部署-内网使用https</title>
            <link rel="alternate" type="text/html" href="/blog/posts/k8s/offline-https/" />
            <id>/blog/posts/k8s/offline-https/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2022-10-24T17:01:14&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">K8s离线部署-内网使用https 证书生成 生成证书请求文件 单独在一个文件夹iphttps新建openssl.cnf，内容如下： [req] distinguished_name = req_distinguished_name req_extensions = v3_req [req_distinguished_name] countryName = Country Name (2 letter code) countryName_default =……</summary>
            
                <content type="html">&lt;h2 id=&#34;centerk8s离线部署-内网使用httpscenter&#34;&gt;&lt;center&gt;K8s离线部署-内网使用https&lt;/center&gt;&lt;/h2&gt;
&lt;h4 id=&#34;证书生成&#34;&gt;证书生成&lt;/h4&gt;
&lt;h5 id=&#34;生成证书请求文件&#34;&gt;生成证书请求文件&lt;/h5&gt;
&lt;p&gt;单独在一个文件夹iphttps新建openssl.cnf，内容如下：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req

[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = CH
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = GD
localityName = Locality Name (eg, city)
localityName_default = ShenZhen
organizationalUnitName  = Organizational Unit Name (eg, section)
organizationalUnitName_default  = organizationalUnitName
commonName = Internet Widgits Ltd
commonName_max  = 64

[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

[alt_names]

# 改成自己的域名
#DNS.1 = kb.example.com
#DNS.2 = helpdesk.example.org
#DNS.3 = systems.example.net

# 改成自己的ip
IP.1 = 172.16.1.71
IP.2 = 172.16.1.72
IP.3 = 172.16.1.73
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id=&#34;生成私钥&#34;&gt;生成私钥&lt;/h5&gt;
&lt;p&gt;san_domain_com 为最终生成得文件名，一般以服务器命名，可自行更改。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;openssl genrsa -out san_domain_com.key 2048
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id=&#34;创建csr文件&#34;&gt;创建CSR文件&lt;/h5&gt;
&lt;p&gt;创建csr文件命令：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;openssl req -new -out san_domain_com.csr -key san_domain_com.key -config openssl.cnf
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id=&#34;自签名并创建证书&#34;&gt;自签名并创建证书、&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;openssl x509 -req -days 3650 -in san_domain_com.csr -signkey san_domain_com.key -out san_domain_com.crt -extensions v3_req -extfile openssl.cnf
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;至此，使用openssl生成得证书已完成，可看到目录下又三个文件&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;san_domain_com.crt

san_domain_com.csr

san_domain_com.key
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;创建secret资源&#34;&gt;创建secret资源&lt;/h4&gt;
&lt;p&gt;直接使用kubectl命令创建&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd /root/iphttps
kubectl create secret tls iphttps-secret --key san_domain_com.key --cert san_domain_com.crt -n fhzh

&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;创建ingress资源&#34;&gt;创建ingress资源&lt;/h4&gt;
&lt;p&gt;创建ing资源，增加一个tls字段：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;kind: Ingress
apiVersion: extensions/v1beta1
metadata:
  name: iphttps
  namespace: fhzh
spec:
  tls:
    - hosts:
        # 域名
        - www.iphttpsfhzh.com
      secretName: iphttps-secret
  rules:
      # 域名
    - host: www.iphttpsfhzh.com
      http:
        paths:
          - backend:
              # service的名称
              serviceName: fhzh-web-svc
              # service的内部端口
              servicePort: 80
    # 默认访问，解决内网ip无法访问的问题(弊端：不支持多个服务，后面考虑使用路径解析)
    - http:
        paths:
          - backend:
              serviceName: fhzh-web-svc
              servicePort: 80
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;https访问&#34;&gt;https访问&lt;/h4&gt;
&lt;p&gt;内网使用域名访问的话，需要在客户端修改hosts，这里并不推荐。&lt;br&gt;
先查询ingress的暴露的端口&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 查看
kubectl get svc -n ingress-nginx
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&#34;/blog/blog/images/k8s/ingress.png&#34; alt=&#34;配置&#34;&gt;&lt;br&gt;
可以看出 80映射为 30865；443映射 31287&lt;br&gt;
至此访问路径 https://172.16.1.71:31287即可看到系统&lt;/p&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/k8s/" term="k8s" label="k8s" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/k8s/" term="k8s" label="k8s" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Centos Python3</title>
            <link rel="alternate" type="text/html" href="/blog/posts/centos/centos-python3/" />
            <id>/blog/posts/centos/centos-python3/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2022-10-22T16:40:33&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Centos环境 python升级python3 查看系统远python版本 [root@localhost ~]# python // 默认是2.7.5 下载Python3.8.0 Python3.8.0下载地址 依赖环境……</summary>
            
                <content type="html">&lt;h2 id=&#34;centercentos环境-python升级python3center&#34;&gt;&lt;center&gt;Centos环境 python升级python3&lt;/center&gt;&lt;/h2&gt;
&lt;h4 id=&#34;查看系统远python版本&#34;&gt;查看系统远python版本&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[root@localhost ~]# python
// 默认是2.7.5

&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;下载python380&#34;&gt;下载Python3.8.0&lt;/h4&gt;
&lt;p&gt;Python3.8.0&lt;a href=&#34;https://www.python.org/ftp/python/3.8.0/&#34;&gt;下载地址&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&#34;依赖环境gcczlib&#34;&gt;依赖环境gcc、zlib&lt;/h4&gt;
&lt;p&gt;查看gcc是否安装&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;whereis gcc  或者
gcc --version

# 没有安装的话需要制作离线安装包
yum install --downloadonly --downloaddir=/root/k8sOfflineSetup/packages \
    gcc-c++
# 将下载的包打包并上传到服务器，并执行下面命令：
rpm -ivh * --nodeps --force

# 如果再make install报错 zlib not available时，安装下面zlib包
yum install --downloadonly --downloaddir=/root/k8sOfflineSetup/packages \
    zlib \
    zlib-devel
yum install -y 
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;安装python3&#34;&gt;安装python3&lt;/h4&gt;
&lt;p&gt;安装步骤：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1、解压安装宝
tar -zxvf Python-3.8.0.tgz
2、进入解压后的文件夹
./configure --prefix=/usr/local/python3
# 编译
make
# 安装
make install

&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;替换默认python2&#34;&gt;替换默认python2&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ll /usr/bin/ | grep python
# 可以看到python指向python2

#修改名称再添加python3的软连接
mv /usr/bin/python /usr/bin/old_python
ln -s /usr/local/python3/bin/python3.8 /usr/bin/python

# pip更换
mv /usr/bin/pip /usr/bin/old_pip
ln -s /usr/local/python3/bin/pip3 /usr/bin/pip

# 查看版本
pip --version
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;python运行依赖包&#34;&gt;python运行依赖包&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 将已安装的依赖包导出
pip freeze &amp;gt; requirements.txt
# 离线文件导出
pip download -r requestments.txt -d ./pip_packages

# 将 whl 包下载后放至某文件夹，如 /root/pip-packages
pip install --no-index --find-links=/root/pip-packages &amp;lt;软件名&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;升级pip&#34;&gt;升级pip&lt;/h4&gt;
&lt;p&gt;在离线环境下，pip安装离线包时有时候会报错，首先看下下载依赖包的pip版本和当前服务器版本是否一致&lt;br&gt;
不一致的情况下，需要更新pip版本。 &lt;a href=&#34;https://pypi.org/project/pip/#files&#34;&gt;版本下载地址&lt;/a&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;python -m pip install --upgrade xxx(注意：pip轮子的文件名.whl，一定要有后缀)
&lt;/code&gt;&lt;/pre&gt;</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/centos/" term="centos" label="centos" />
                            
                        
                            
                            
                            
                                <category scheme="/blog/categories/python/" term="python" label="python" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/centos/" term="centos" label="centos" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Tidb探究 扩容缩容</title>
            <link rel="alternate" type="text/html" href="/blog/posts/tidb/tidb-scale/" />
            <id>/blog/posts/tidb/tidb-scale/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2022-09-23T10:03:35&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Tidb探究 扩容缩容 查看当前tidb配置 # 查看tidb信息 tiup cluster list # 查看cluster的配置 tiup cluster edit-config &amp;lt;cluster-name&amp;gt; # 查看集群状态 tiup cluster display &amp;lt;cluster-name&amp;gt; 扩容TiDB/PD/TiKV节点 添加节点……</summary>
            
                <content type="html">&lt;h1 id=&#34;centertidb探究-扩容缩容center&#34;&gt;&lt;center&gt;Tidb探究 扩容缩容&lt;/center&gt;&lt;/h1&gt;
&lt;h3 id=&#34;查看当前tidb配置&#34;&gt;查看当前tidb配置&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 查看tidb信息
tiup cluster list

# 查看cluster的配置
tiup cluster edit-config &amp;lt;cluster-name&amp;gt;

# 查看集群状态
tiup cluster display &amp;lt;cluster-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;扩容tidbpdtikv节点&#34;&gt;扩容TiDB/PD/TiKV节点&lt;/h4&gt;
&lt;p&gt;添加节点ip地址为192.168.174.128，可按照如下步骤进行操作。&lt;/p&gt;
&lt;h5 id=&#34;1编写扩容拓扑配置&#34;&gt;1.编写扩容拓扑配置&lt;/h5&gt;
&lt;blockquote&gt;
&lt;p&gt;⚠️&lt;strong&gt;注意&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;默认情况下，可以不填写端口以及目录信息。但在单机多实例场景下，则需要分配不同的端口以及目录，如果有端口或目录冲突，会在部署或扩容时提醒。&lt;/li&gt;
&lt;li&gt;从 TiUP v1.0.0 开始，扩容配置会继承原集群配置的 global 部分。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;创建scale-out.yaml文件添加扩容拓扑配置&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;vi scale-out.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;TiDB配置文件参考：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tidb_servers:
  - host: 192.168.174.128
    ssh_port: 22
    port: 4000
    status_port: 10080
    # 文件存储地址，可参考edit-config
    deploy_dir: /tidb-deploy/tidb-4000
    log_dir: /tidb-deploy/tidb-4000/log
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;TiKV配置文件参考：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tikv_servers:
  - host: 192.168.174.128
    ssh_port: 22
    port: 20160
    status_port: 20180
    # 文件存储地址，可参考edit-config
    deploy_dir: /tidb-deploy/tikv-20160
    data_dir: /tidb-data/tikv-20160
    log_dir: /tidb-deploy/tikv-20160/log
    config:
      server.labels:
        host: 192.168.174.128
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;PD配置文件参考：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;pd_servers:
  - host: 192.168.174.128
    ssh_port: 22
    name: pd-192.168.174.128-2379
    client_port: 2379
    peer_port: 2380
    # 文件存储地址，可参考edit-config
    deploy_dir: /tidb-deploy/pd-2379
    data_dir: /tidb-data/pd-2379
    log_dir: /tidb-deploy/pd-2379/log
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id=&#34;2执行扩容命令&#34;&gt;2.执行扩容命令&lt;/h5&gt;
&lt;p&gt;执行&lt;code&gt;scale-out&lt;/code&gt;命令前，先使用&lt;code&gt;check&lt;/code&gt;及&lt;code&gt;check --apply&lt;/code&gt;命令，检查和自动修复集群存在的潜在风险：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1.检查集群存在的潜在风险
tiup cluster check &amp;lt;cluster-name&amp;gt; scale-out.yaml --cluster --user tidb [-p] [-i /home/root/.ssh/gcp_rsa]

2.自动修复集群存在的潜在风险
tiup cluster check &amp;lt;cluster-name&amp;gt; scale-out.yaml --cluster --apply --user tidb [-p] [-i /home/root/.ssh/gcp_rsa]

3.执行`scale-out`命令扩容TiDB集群
tiup cluster scale-out &amp;lt;cluster-name&amp;gt; scale-out.yaml [-p] [-i /home/root/.ssh/gcp_rsa]

&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;扩容配置文件为 scale-out.yaml。&lt;/li&gt;
&lt;li&gt;--user tidb 表示通过 tidb 用户登录到目标主机完成集群部署，该用户需要有 ssh 到目标机器的权限，并且在目标机器有 sudo 权限。也可以用其他有 ssh 和 sudo 权限的用户完成部署。&lt;/li&gt;
&lt;li&gt;[-i] 及 [-p] 为可选项，如果已经配置免密登录目标机，则不需填写。否则选择其一即可，[-i] 为可登录到目标机的 root 用户（或 --user 指定的其他用户）的私钥，也可使用 [-p] 交互式输入该用户的密码。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;预期日志结尾输出 Scaled cluster &lt;code&gt;&amp;lt;cluster-name&amp;gt;&lt;/code&gt; out successfully 信息，表示扩容操作成功。&lt;/p&gt;
&lt;h4 id=&#34;缩容tidbpdtikv节点&#34;&gt;缩容TiDB/PD/TiKV节点&lt;/h4&gt;
&lt;p&gt;添加节点ip地址为192.168.174.128，可按照如下步骤进行操作。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;注意&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;移除 TiDB、PD 节点和移除 TiKV 节点的步骤类似。&lt;/li&gt;
&lt;li&gt;由于 TiKV、TiFlash 和 TiDB Binlog 组件是异步下线的，且下线过程耗时较长，所以 TiUP 对 TiKV、TiFlash 和 TiDB Binlog 组件做了特殊处理，详情参考&lt;a href=&#34;https://docs.pingcap.com/zh/tidb/stable/tiup-component-cluster-scale-in#%E4%B8%8B%E7%BA%BF%E7%89%B9%E6%AE%8A%E5%A4%84%E7%90%86&#34;&gt;下线特殊处理&lt;/a&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;注意&lt;/strong&gt;&lt;br&gt;
TiKV 中的 PD Client 会缓存 PD 节点的列表。当前版本的 TiKV 有定期自动更新 PD 节点的机制，可以降低 TiKV 缓存的 PD 节点列表过旧这一问题出现的概率。但你应尽量避免在扩容新 PD 后直接一次性缩容所有扩容前就已经存在的 PD 节点。如果需要，请确保在下线所有之前存在的 PD 节点前将 PD 的 leader 切换至新扩容的 PD 节点。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h5 id=&#34;1查看节点id信息&#34;&gt;1.查看节点ID信息&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tiup cluster display &amp;lt;cluster-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Starting /root/.tiup/components/cluster/v1.10.0/cluster display &amp;lt;cluster-name&amp;gt;

TiDB Cluster: &amp;lt;cluster-name&amp;gt;

TiDB Version: v6.1.0

ID       Role         Host    Ports                            Status  Data Dir        Deploy Dir

--       ----         ----      -----                            ------  --------        ----------

10.0.1.3:8300  cdc          10.0.1.3    8300                            Up      data/cdc-8300      deploy/cdc-8300

10.0.1.4:8300  cdc          10.0.1.4    8300                            Up      data/cdc-8300      deploy/cdc-8300

10.0.1.4:2379  pd           10.0.1.4    2379/2380                        Healthy data/pd-2379      deploy/pd-2379

10.0.1.1:20160 tikv         10.0.1.1    20160/20180                      Up      data/tikv-20160     deploy/tikv-20160

10.0.1.2:20160 tikv         10.0.1.2    20160/20180                      Up      data/tikv-20160     deploy/tikv-20160

10.0.1.5:20160 tikv        10.0.1.5    20160/20180                     Up      data/tikv-20160     deploy/tikv-20160

10.0.1.3:4000  tidb        10.0.1.3    4000/10080                      Up      -                 deploy/tidb-4000

10.0.1.4:4000  tidb        10.0.1.4    4000/10080                      Up      -                 deploy/tidb-4000

10.0.1.5:4000  tidb         10.0.1.5    4000/10080                       Up      -            deploy/tidb-4000

10.0.1.3:9000   tiflash      10.0.1.3    9000/8123/3930/20170/20292/8234  Up      data/tiflash-9000       deploy/tiflash-9000

10.0.1.4:9000   tiflash      10.0.1.4    9000/8123/3930/20170/20292/8234  Up      data/tiflash-9000       deploy/tiflash-9000

10.0.1.5:9090  prometheus   10.0.1.5    9090                             Up      data/prometheus-9090  deploy/prometheus-9090

10.0.1.5:3000  grafana      10.0.1.5    3000                             Up      -            deploy/grafana-3000

10.0.1.5:9093  alertmanager 10.0.1.5    9093/9094                        Up      data/alertmanager-9093 deploy/alertmanager-9093
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id=&#34;2执行缩容操作&#34;&gt;2.执行缩容操作&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tiup cluster scale-in &amp;lt;cluster-name&amp;gt; --node 10.0.1.5:20160


# tidb 端口是 4000
# tikv 端口是 20160
# pc 端口是 2379
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;其中 --node 参数为需要下线节点的 ID。&lt;br&gt;
预期输出 Scaled cluster &lt;code&gt;&amp;lt;cluster-name&amp;gt;&lt;/code&gt; in successfully 信息，表示缩容操作成功。&lt;br&gt;
下线需要一定时间，下线节点的状态变为 Tombstone 就说明下线成功。&lt;/p&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/tidb/" term="TiDB" label="TiDB" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/tidb/" term="TiDB" label="TiDB" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Tidb探究 Haproxy负载</title>
            <link rel="alternate" type="text/html" href="/blog/posts/tidb/tidb-haproxy/" />
            <id>/blog/posts/tidb/tidb-haproxy/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2022-09-22T14:35:35&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Tidb探究 Haproxy负载 HAProxy 简介 HAProxy 是由 C 语言编写的自由开放源码的软件，为基于 TCP 和 HTTP 协议的应用程序提供高可用性、负载均衡和代理服务。因为 HAProxy 能够快速、高效使用 CPU……</summary>
            
                <content type="html">&lt;h1 id=&#34;centertidb探究-haproxy负载center&#34;&gt;&lt;center&gt;Tidb探究 Haproxy负载&lt;/center&gt;&lt;/h1&gt;
&lt;h4 id=&#34;haproxy-简介&#34;&gt;HAProxy 简介&lt;/h4&gt;
&lt;p&gt;HAProxy 是由 C 语言编写的自由开放源码的软件，为基于 TCP 和 HTTP 协议的应用程序提供高可用性、负载均衡和代理服务。因为 HAProxy 能够快速、高效使用 CPU 和内存，所以目前使用非常广泛，许多知名网站诸如 GitHub、Bitbucket、Stack Overflow、Reddit、Tumblr、Twitter 和 Tuenti 以及亚马逊网络服务系统都在使用 HAProxy。&lt;br&gt;
HAProxy 由 Linux 内核的核心贡献者 Willy Tarreau 于 2000 年编写，他现在仍然负责该项目的维护，并在开源社区免费提供版本迭代。本文示例使用 HAProxy 2.5.0。&lt;/p&gt;
&lt;h4 id=&#34;haproxy-部分核心功能介绍&#34;&gt;HAProxy 部分核心功能介绍&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;高可用性：HAProxy 提供优雅关闭服务和无缝切换的高可用功能；&lt;/li&gt;
&lt;li&gt;负载均衡：L4 (TCP) 和 L7 (HTTP) 两种负载均衡模式，至少 9 类均衡算法，比如 roundrobin，leastconn，random 等；&lt;/li&gt;
&lt;li&gt;健康检查：对 HAProxy 配置的 HTTP 或者 TCP 模式状态进行检查；&lt;/li&gt;
&lt;li&gt;会话保持：在应用程序没有提供会话保持功能的情况下，HAProxy 可以提供该项功能；&lt;/li&gt;
&lt;li&gt;SSL：支持 HTTPS 通信和解析；&lt;/li&gt;
&lt;li&gt;监控与统计：通过 web 页面可以实时监控服务状态以及具体的流量信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;安装包&#34;&gt;安装包&lt;/h4&gt;
&lt;p&gt;1、离线安装下载&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;yum install --downloadonly --downloaddir=/root/k8sOfflineSetup/packages \
    haproxy
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2、然后复制到root文件夹&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;rpm -ivh /root/haproxy-**.rpm --nodeps --force
# 查看haproxy是否已安装
which haproxy

# 查看命令
haproxy -help

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;参数说明如下：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;参数&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-v&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;显示简略的版本信息。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-vv&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;显示详细的版本信息。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-d&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;开启 debug 模式。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-db&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;禁用后台模式和多进程模式。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-dM [&lt;code&gt;&amp;lt;byte&amp;gt;&lt;/code&gt;]&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;执行分配内存。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-V&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;启动过程显示配置和轮询信息。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-D&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;开启守护进程模式。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-C &lt;code&gt;&amp;lt;dir&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;在加载配置文件之前更改目录位置至&lt;code&gt;&amp;lt;dir&amp;gt;&lt;/code&gt;。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-W&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;主从模式。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-q&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;静默模式，不输出信息。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-c&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;只检查配置文件并在尝试绑定之前退出。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-n &amp;lt;&lt;code&gt;limit&lt;/code&gt;&amp;gt;&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;设置每个进程的最大总连接数为 &amp;lt;&lt;code&gt;limit&lt;/code&gt;&amp;gt;。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-m &amp;lt;&lt;code&gt;limit&lt;/code&gt;&amp;gt;&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;设置所有进程的最大可用内存为 &amp;lt;&lt;code&gt;limit&lt;/code&gt;&amp;gt;（单位：MB）。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-N &amp;lt;&lt;code&gt;limit&lt;/code&gt;&amp;gt;&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;设置单点最大连接数为 &amp;lt;&lt;code&gt;limit&lt;/code&gt;&amp;gt;，默认为 2000。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-L &amp;lt;&lt;code&gt;name&lt;/code&gt;&amp;gt;&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;将本地实例对等名称改为 &amp;lt;&lt;code&gt;name&lt;/code&gt;&amp;gt;，默认为本地主机名。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-p &amp;lt;&lt;code&gt;file&lt;/code&gt;&amp;gt;&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;将 HAProxy 所有子进程的 PID 信息写入 &amp;lt;&lt;code&gt;file&lt;/code&gt;&amp;gt;。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-de&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;禁止使用 epoll(7)，epoll(7) 仅在 Linux 2.6 和某些定制的 Linux 2.4 系统上可用。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-dp&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;禁止使用 epoll(2)，可改用 select(2)。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-dS&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;禁止使用 splice(2)，splice(2) 在一些旧版 Linux 内核上不可用。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-dR&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;禁止使用 SO_REUSEPORT。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-dr&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;忽略服务器地址解析失败。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-dV&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;禁止在服务器端使用 SSL。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-sf &amp;lt;&lt;code&gt;pidlist&lt;/code&gt;&amp;gt;&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;启动后，向 pidlist 中的 PID 发送 finish 信号，收到此信号的进程在退出之前将等待所有会话完成，即优雅停止服务。此选项必须最后指定，后跟任意数量的 PID。从技术上讲，SIGTTOU 和 SIGUSR1 都被发送。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-st &amp;lt;&lt;code&gt;pidlist&lt;/code&gt;&amp;gt;&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;启动后，向 pidlist 中的 PID 发送 terminate 信号，收到此信号的进程将立即终止，关闭所有活动会话。此选项必须最后指定，后跟任意数量的 PID。从技术上讲，SIGTTOU 和 SIGTERM 都被发送。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-x &amp;lt;&lt;code&gt;unix_socket&lt;/code&gt;&amp;gt;&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;连接指定的 socket 并从旧进程中获取所有 listening socket，然后，使用这些 socket 而不是绑定新的。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-S &amp;lt;&lt;code&gt;bind&lt;/code&gt;&amp;gt;[,&amp;lt;bind_options&amp;gt;...]&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;主从模式下，创建绑定到主进程的 socket，此 socket 可访问每个子进程的 socket。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&#34;haproxy配置文件&#34;&gt;HAProxy配置文件&lt;/h4&gt;
&lt;p&gt;使用&lt;code&gt;vi /etc/haproxy/haproxy.cfg&lt;/code&gt;命令编辑内容如下：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;global                                     # 全局配置。
   log         127.0.0.1 local2            # 定义全局的 syslog 服务器，最多可以定义两个。
   chroot      /var/lib/haproxy            # 更改当前目录并为启动进程设置超级用户权限，从而提高安全性。
   pidfile     /var/run/haproxy.pid        # 将 HAProxy 进程的 PID 写入 pidfile。
   maxconn     4096                        # 单个 HAProxy 进程可接受的最大并发连接数，等价于命令行参数 &amp;quot;-n&amp;quot;。
   nbthread    48                          # 最大线程数。线程数的上限与 CPU 数量相同。
   user        haproxy                     # 同 UID 参数。
   group       haproxy                     # 同 GID 参数，建议使用专用用户组。
   daemon                                  # 让 HAProxy 以守护进程的方式工作于后台，等同于命令行参数“-D”的功能。当然，也可以在命令行中用“-db”参数将其禁用。
   stats socket /var/lib/haproxy/stats     # 统计信息保存位置。

defaults                                   # 默认配置。
   log global                              # 日志继承全局配置段的设置。
   retries 2                               # 向上游服务器尝试连接的最大次数，超过此值便认为后端服务器不可用。
   timeout connect  2s                     # HAProxy 与后端服务器连接超时时间。如果在同一个局域网内，可设置成较短的时间。
   timeout client 30000s                   # 客户端与 HAProxy 连接后，数据传输完毕，即非活动连接的超时时间。
   timeout server 30000s                   # 服务器端非活动连接的超时时间。

listen admin_stats                         # frontend 和 backend 的组合体，此监控组的名称可按需进行自定义。
   bind 0.0.0.0:8080                       # 监听端口。
   mode http                               # 监控运行的模式，此处为 `http` 模式。
   option httplog                          # 开始启用记录 HTTP 请求的日志功能。
   maxconn 10                              # 最大并发连接数。
   stats refresh 30s                       # 每隔 30 秒自动刷新监控页面。
   stats uri /haproxy                      # 监控页面的 URL。
   stats realm HAProxy                     # 监控页面的提示信息。
   stats auth admin:pingcap123             # 监控页面的用户和密码，可设置多个用户名。
   stats hide-version                      # 隐藏监控页面上的 HAProxy 版本信息。
   stats  admin if TRUE                    # 手工启用或禁用后端服务器（HAProxy 1.4.9 及之后版本开始支持）。

listen tidb-cluster                        # 配置 database 负载均衡。
   bind 0.0.0.0:3390                       # 浮动 IP 和 监听端口。
   mode tcp                                # HAProxy 要使用第 4 层的传输层。
   balance leastconn                       # 连接数最少的服务器优先接收连接。`leastconn` 建议用于长会话服务，例如 LDAP、SQL、TSE 等，而不是短会话协议，如 HTTP。该算法是动态的，对于启动慢的服务器，服务器权重会在运行中作调整。
   server tidb-1 10.9.18.229:4000 check inter 2000 rise 2 fall 3       # 检测 4000 端口，检测频率为每 2000 毫秒一次。如果 2 次检测为成功，则认为服务器可用；如果 3 次检测为失败，则认为服务器不可用。
   server tidb-2 10.9.39.208:4000 check inter 2000 rise 2 fall 3
   server tidb-3 10.9.64.166:4000 check inter 2000 rise 2 fall 3
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;启动haproxy&#34;&gt;启动HAProxy&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;haproxy -f /etc/haproxy/haproxy.cfg
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;停止haproxy&#34;&gt;停止HAProxy&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ps -ef | grep haproxy
kill -9 ${haproxy.pid}

&lt;/code&gt;&lt;/pre&gt;</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/tidb/" term="TiDB" label="TiDB" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/tidb/" term="TiDB" label="TiDB" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">K8s离线部署-NFS-Docker-Harbor</title>
            <link rel="alternate" type="text/html" href="/blog/posts/k8s/offline-docker-nfs-harbor/" />
            <id>/blog/posts/k8s/offline-docker-nfs-harbor/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2022-09-22T13:50:26&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">K8s离线部署-NFS-Docker-Harbor 站点服务器安装nfs服务 # 执行命令准备nfs离线资源 yum -y install nfs-utils --downloadonly --downloaddir /root/nfs 打包nfs.tar并执行下面操作： 1、先将文……</summary>
            
                <content type="html">&lt;h2 id=&#34;centerk8s离线部署-nfs-docker-harborcenter&#34;&gt;&lt;center&gt;K8s离线部署-NFS-Docker-Harbor&lt;/center&gt;&lt;/h2&gt;
&lt;h4 id=&#34;站点服务器安装nfs服务&#34;&gt;站点服务器安装nfs服务&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 执行命令准备nfs离线资源
yum -y install nfs-utils --downloadonly --downloaddir /root/nfs
打包nfs.tar并执行下面操作：
1、先将文件copy到服务器root目录下
2、tar -xvf nfs.tar
3、切换到packages包下  先将依赖包全部安装  rpm -ivh * --nodeps --force
4、执行下面步骤：
    #创建nfs目录
    mkdir -p /nfs/data/

    #修改权限
    chmod -R 777 /nfs/data

    #编辑export文件
    vi /etc/exports
    /nfs/data 192.168.0.0/24(rw,no_root_squash,sync)  （“*“代表所有人都能连接，建议换成具体ip或ip段，如192.168.20.0/24）

    #配置生效
    exportfs -r
    #查看生效
    exportfs

    #启动rpcbind、nfs服务
    systemctl restart rpcbind &amp;amp;&amp;amp; systemctl enable rpcbind
    systemctl restart nfs &amp;amp;&amp;amp; systemctl enable nfs

    #查看 RPC 服务的注册状况
    rpcinfo -p localhost

    #showmount测试
    showmount -e 192.168.92.56
    # 关闭 防火墙  否则其他服务不能访问
    systemctl stop firewalld
    systemctl disable firewalld

    #所有node节点安装客户端 执行1、2、3

5、为申请PV划分磁盘
    #创建pv卷对应的目录
    mkdir -p /nfs/data/pv001
    mkdir -p /nfs/data/pv002

    #配置exportrs
    vi /etc/exports
    /nfs/data 192.168.0.0/24(rw,no_root_squash,sync)
    /nfs/data/pv001 192.168.0.0/24(rw,no_root_squash,sync)
    /nfs/data/pv002 192.168.0.0/24(rw,no_root_squash,sync)

    #配置生效
    exportfs -r
    #重启rpcbind、nfs服务
    systemctl restart rpcbind &amp;amp;&amp;amp; systemctl restart nfs
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;harbor离线安装&#34;&gt;harbor离线安装&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;需要提前安装docker。&lt;br&gt;
docker-19.03.9.tgz离线包下载地址&lt;a href=&#34;https://download.docker.com/linux/static/stable/x86_64/docker-19.03.9.tgz&#34;&gt;https://download.docker.com/linux/static/stable/x86_64/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;harbor离线包下载地址&lt;a href=&#34;https://github.com/goharbor/harbor/releases&#34;&gt;https://github.com/goharbor/harbor/releases&lt;/a&gt;，这里选择的harbor-offline-installer-v1.10.10.tgz为例。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;安装步骤如下：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1、先安装docker  tar -zxvf docker-19.03.9.tgz
2、将解压docker文件夹全部移动到/usr/bin  cp -p docker/* /usr/bin
3、将docker注册为系统服务
    （1）在/usr/lib/systemd/system/目录下，创建docker.service文件
    （2）编辑docker.service文件    vi /usr/lib/systemd/system/docker.service
[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=infinity
LimitNPROC=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
 
[Install]
WantedBy=multi-user.target			

4、重启生效
    systemctl daemon-reload
    systemctl start docker
5、查看docker状态  systemctl status docker
6、设置开机启动   systemctl enable docker   查看版本 docker version
6.1、# vi /etc/docker/daemon.json
    {
    &amp;quot;insecure-registries&amp;quot;: [&amp;quot;192.168.229.148:8080&amp;quot;]
    }
	systemctl restart docker
7、安装docker-compose
    (1) mv /root/docker-compose-Linux-x86_64 /usr/bin/docker-compose
    (2) chmod +x /usr/bin/docker-compose
    (3) docker-compose - v
8、安装Harbor
    (1) tar -zxvf harbor-offline-installer-v1.10.10\(最新版2022-02-21\).tgz
    (2) cd /harbor   cp harbor.yml harbor.yml.tmpl
    (3) 编辑harbor.yml   vi ./harbor.yml
    (4) # 修改成你的ip
        hostname: 192.168.211.99
        # 修改端口号
        http:
            port: 8080
        # 如果不需要https，请注释掉https相关
        #https:
        #  port: 443
        #  certificate: /your/certificate/path
        #  private_key: /your/private/key/path
        # 配置密码，将 Harbor12345换成你自己的密码
        harbor_admin_password: Fhzh@zkah!@#123
    （5）执行setenforce 0 
    (6) ./install.sh  即可安装成功  http://192.168.211.99:8080 即可访问
    (7) 常用命令
        # 回到harbor文件夹下 启动harbor  
        setenforce 0
        docker-compose up -d
        # 关闭harbor
        docker-compose down
9、 k8s配置镜像私库密钥
    kubectl create secret docker-registry harbor-secret  --namespace=fhzh --docker-server=20.184.3.15:8080 --docker-username=admin --docker-password=Fhzh@zkah!@#123
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;harbor自启动&#34;&gt;Harbor自启动&lt;/h4&gt;
&lt;p&gt;自启动前提，需要知道docker-compose的路径和harbor安装的路径&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;whereis docker-compose
# 可以看到docker-compose的路径， 本服务路径是在/usr/bin/docker-compose


# 查看harbor文件夹位置
find / -name &#39;harbor&#39; -type d
# 返回文件夹
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;将harbor配置成systemd的service，添加配置文件&lt;code&gt;/usr/lib/systemd/system/harbor.service&lt;/code&gt;,内容如下：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[Unit]
Description=Harbor
After=docker.service systemd-networkd.service systemd-resolved.service
Requires=docker.service
Documentation=http://github.com/vmware/harbor

[Service]
Type=simple
Restart=on-failure
RestartSec=5
ExecStart=/usr/bin/docker-compose -f /root/harbor/docker-compose.yml up
ExecStop=/usr//bin/docker-compose -f /root/harbor/docker-compose.yml down

[Install]
WantedBy=multi-user.target

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;然后执行下面设置服务的命令：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;sudo systemctl enable harbor
sudo systemctl start harbor

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;查看harbor启动情况&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;docker ps -a
&lt;/code&gt;&lt;/pre&gt;</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/k8s/" term="k8s" label="k8s" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/k8s/" term="k8s" label="k8s" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">K8s离线部署-离线部署</title>
            <link rel="alternate" type="text/html" href="/blog/posts/k8s/offline-setup/" />
            <id>/blog/posts/k8s/offline-setup/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2022-09-22T11:15:35&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">K8s离线部署-离线部署 环境 服务器 IP Master 192.168.174.128 Node1 192.168.174.129 Node2 192.168.174.130 将制作的离线安装包上传到各节点,解压到/root/k8sOfflineSetup目录,解压路径不能修改 Maste……</summary>
            
                <content type="html">&lt;h2 id=&#34;centerk8s离线部署-离线部署center&#34;&gt;&lt;center&gt;K8s离线部署-离线部署&lt;/center&gt;&lt;/h2&gt;
&lt;h4 id=&#34;环境&#34;&gt;环境&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;服务器&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;IP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Master&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;192.168.174.128&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Node1&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;192.168.174.129&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Node2&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;192.168.174.130&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;将制作的离线安装包上传到各节点,解压到&lt;code&gt;/root/k8sOfflineSetup&lt;/code&gt;目录,&lt;font color=&#39;red&#39;&gt;&lt;em&gt;解压路径不能修改&lt;/em&gt;&lt;/font&gt;&lt;/p&gt;
&lt;h4 id=&#34;master节点安装&#34;&gt;Master节点安装&lt;/h4&gt;
&lt;p&gt;在&lt;code&gt;master&lt;/code&gt;节点执行下面操作:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1、先将文件copy到服务器root目录下
2、tar -xvf k8sOfflineSetup.tar
3、切换到packages包下  先将依赖包全部安装  rpm -ivh * --nodeps --force
4、创建环境变量
    # master节点的主机名
	export HOSTNAME=k8s-master
    # kubernetes apiserver的主机地址
	export APISERVER_NAME=apiserver.k8s.com
    # 集群中master节点的ip地址
	export MASTER_IP=192.168.174.128
    # Pod 使用的网段
	export POD_SUBNET=10.11.10.0/16
5、回到k8sOfflineSetup文件夹
   执行./setup_master.sh
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;执行完毕后，执行下面操作获取加入master的参数&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 在 master 节点执行
kubeadm token create --print-join-command

# 得到token和cert，这两个参数在2个小时内可以重复使用，超过以后就得再次生成
kubeadm join apiserver.k8s.com --token mpfjma.4vjjg8flqihor4vt     --discovery-token-ca-cert-hash sha256:6f7a8e40a810323672de5eee6f4d19aa2dbdb38411845a1bf5dd63485c43d303
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;node节点安装&#34;&gt;Node节点安装&lt;/h4&gt;
&lt;p&gt;在每个node节点执行下面操作：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1、先将文件copy到服务器root目录下
2、tar -xvf k8sOfflineSetup.tar
3、切换到packages包下  先将依赖包全部安装  rpm -ivh * --nodeps --force
4、创建环境变量
    # node节点的主机名
    export HOSTNAME=node1
    # kubernetes apiserver的主机地址
    export APISERVER_NAME=apiserver.k8s.com
    # 集群中master节点的ip地址
    export MASTER_IP=192.168.174.128
    # 加入master的token
    export TOKEN=mpfjma.4vjjg8flqihor4vt
    # 加入master的证书
    export CERT=sha256:6f7a8e40a810323672de5eee6f4d19aa2dbdb38411845a1bf5dd63485c43d303
5、回到k8sOfflineSetup文件夹，执行./setup_worker.sh
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;每个node节点之后完之后，就已经部署完成了。可执行&lt;code&gt;kubectl get nodes&lt;/code&gt;看所有节点的情况。&lt;/p&gt;
&lt;h4 id=&#34;访问kuboard&#34;&gt;访问Kuboard&lt;/h4&gt;
&lt;p&gt;Kuboard是一个非常方便的web管理界面，安装完以后可以通过&lt;a href=&#34;http://xn--ip-dh3cr99d42rrmy:32567/&#34;&gt;http://任意节点IP:32567/&lt;/a&gt;访问。&lt;/p&gt;
&lt;h5 id=&#34;获取登录token&#34;&gt;获取登录token&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 在 Master 节点上执行此命令
kubectl -n kube-system get secret $(kubectl -n kube-system get secret | grep kuboard-user | awk &#39;{print $1}&#39;) -o go-template=&#39;{{.data.token}}&#39; | base64 -d
&lt;/code&gt;&lt;/pre&gt;</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/k8s/" term="k8s" label="k8s" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/k8s/" term="k8s" label="k8s" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">K8s离线部署-资源准备</title>
            <link rel="alternate" type="text/html" href="/blog/posts/k8s/offline-pre-source/" />
            <id>/blog/posts/k8s/offline-pre-source/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2022-09-22T09:58:40&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">K8s离线部署-资源准备 背景 因当前客户提供服务器均为局域网，不能访问外网，固需要进行离线部署k8s。 版本管理 软件 版本 Docker 19.03.5 Kubernetes 1.17.1 获取yum的环境依赖 在一个可以联网的……</summary>
            
                <content type="html">&lt;h2 id=&#34;centerk8s离线部署-资源准备center&#34;&gt;&lt;center&gt;K8s离线部署-资源准备&lt;/center&gt;&lt;/h2&gt;
&lt;h4 id=&#34;背景&#34;&gt;背景&lt;/h4&gt;
&lt;p&gt;因当前客户提供服务器均为局域网，不能访问外网，固需要进行离线部署k8s。&lt;/p&gt;
&lt;h4 id=&#34;版本管理&#34;&gt;版本管理&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;软件&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;版本&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Docker&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;19.03.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Kubernetes&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;1.17.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&#34;获取yum的环境依赖&#34;&gt;获取yum的环境依赖&lt;/h4&gt;
&lt;p&gt;在一个可以联网的系统下载依赖包，注意这个系统要跟服务器的一致，并且是全新安装的，防止出现yum已安装过一些软件，导致依赖包可能不完整的问题。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这里提供阿里源的[CentOS-7-x86_64-DVD-2009]下载地址(&lt;a href=&#34;http://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/CentOS-7-x86_64-DVD-2009.iso?spm=a2c6h.25603864.0.0.5e776aearg27RG&#34;&gt;http://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/CentOS-7-x86_64-DVD-2009.iso?spm=a2c6h.25603864.0.0.5e776aearg27RG&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;依赖包下载到&lt;code&gt;/root/k8sOfflineSetup/packages&lt;/code&gt;目录。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 使用阿里云镜像源
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

# 创建本地仓库包
yum install --downloadonly --downloaddir=/root/k8sOfflineSetup/packages \
    createrepo

# 实用工具
yum install --downloadonly --downloaddir=/root/k8sOfflineSetup/packages \
    yum-utils \
    nfs-utils \
    wget

# docker 依赖包
yum install --downloadonly --downloaddir=/root/k8sOfflineSetup/packages \
    device-mapper-persistent-data \
    lvm2

# 添加阿里云Docker源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# docker
yum install --downloadonly --downloaddir=/root/k8sOfflineSetup/packages \
    docker-ce-19.03.5 \
    docker-ce-cli-19.03.5 \
    containerd.io

# 时间同步
yum install --downloadonly --downloaddir=/root/k8sOfflineSetup/packages \
    chrony

# HAProxy 和 KeepAlived
yum install --downloadonly --downloaddir=/root/k8sOfflineSetup/packages \
    haproxy \
    keepalived

# 配置K8S的yum源
cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
       http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

# kubelet
yum install --downloadonly --downloaddir=/root/k8sOfflineSetup/packages \
    kubelet-1.17.1 \
    kubeadm-1.17.1 \
    kubectl-1.17.1

&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;获取kubeadm依赖镜像&#34;&gt;获取kubeadm依赖镜像&lt;/h4&gt;
&lt;p&gt;获取kubeadm用到的镜像列表，这步操作要在一台安装好Docker环境的计算机上进行，拉取完成后打包复制到资源包&lt;code&gt;/root/k8sOfflineSetup/images&lt;/code&gt;目录中。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;kubeadm config images list
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;得到的结果是以下这些镜像，因为镜像的服务器都在国外，下载速度慢或者根本无法下载。所以，我们先在阿里云上获取镜像后再改名放到资源包中。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;k8s.gcr.io/kube-apiserver:v1.17.1&lt;/li&gt;
&lt;li&gt;k8s.gcr.io/kube-controller-manager:v1.17.1&lt;/li&gt;
&lt;li&gt;k8s.gcr.io/kube-scheduler:v1.17.1&lt;/li&gt;
&lt;li&gt;k8s.gcr.io/kube-proxy:v1.17.1&lt;/li&gt;
&lt;li&gt;k8s.gcr.io/pause:3.1&lt;/li&gt;
&lt;li&gt;k8s.gcr.io/etcd:3.4.3-0&lt;/li&gt;
&lt;li&gt;k8s.gcr.io/coredns:1.6.5&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 从阿里云拉取镜像
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.17.1
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:v1.17.1
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.17.1
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.17.1
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.1
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.4.3-0
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:1.6.5

# 重新tag镜像
docker images \
    | grep registry.cn-hangzhou.aliyuncs.com/google_containers \
    | sed &#39;s/registry.cn-hangzhou.aliyuncs.com\/google_containers/k8s.gcr.io/&#39; \
    | awk &#39;{print &amp;quot;docker tag &amp;quot; $3 &amp;quot; &amp;quot; $1 &amp;quot;:&amp;quot; $2}&#39; \
    | sh

# 删除旧镜像
docker images \
    | grep registry.cn-hangzhou.aliyuncs.com/google_containers \
    | awk &#39;{print &amp;quot;docker rmi &amp;quot; $1 &amp;quot;:&amp;quot; $2}&#39; \
    | sh

# 在当前目录导出镜像为压缩包
docker save -o kube-controller-manager-v1.17.1.tar k8s.gcr.io/kube-controller-manager:v1.17.1
docker save -o kube-apiserver-v1.17.1.tar k8s.gcr.io/kube-apiserver:v1.17.1
docker save -o kube-scheduler-v1.17.1.tar k8s.gcr.io/kube-scheduler:v1.17.1
docker save -o kube-proxy-v1.17.1.tar k8s.gcr.io/kube-proxy:v1.17.1
docker save -o coredns-1.6.5.tar k8s.gcr.io/coredns:1.6.5
docker save -o etcd-3.4.3-0.tar k8s.gcr.io/etcd:3.4.3-0
docker save -o pause-3.1.tar k8s.gcr.io/pause:3.1
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;calico网络插件依赖镜像&#34;&gt;calico网络插件依赖镜像&lt;/h4&gt;
&lt;p&gt;从&lt;a href=&#34;https://docs.projectcalico.org/v3.10/getting-started/kubernetes/&#34;&gt;Quickstart for Calico on Kubernetes&lt;/a&gt;找到calico.yaml文件，命名为&lt;code&gt;calico-v3.10.3.yaml&lt;/code&gt;保存到资源包&lt;code&gt;/root/k8sOfflineSetup/plugins&lt;/code&gt;目录中。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cat calico-v3.10.3.yaml | grep image: | awk &#39;{print $2}&#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;从文件中搜索&lt;code&gt;image&lt;/code&gt;关键字找到如下依赖镜像。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;calico/cni:v3.10.3&lt;/li&gt;
&lt;li&gt;calico/pod2daemon-flexvol:v3.10.3&lt;/li&gt;
&lt;li&gt;calico/node:v3.10.3&lt;/li&gt;
&lt;li&gt;calico/kube-controllers:v3.10.3&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 拉取全部镜像
cat calico-v3.10.3.yaml \
    | grep image: \
    | awk &#39;{print &amp;quot;docker pull &amp;quot; $2}&#39; \
    | sh

# 在当前目录导出镜像为压缩包
docker save -o calico-cni-v3.10.3.tar calico/cni:v3.10.3
docker save -o calico-pod2daemon-flexvol-v3.10.3.tar calico/pod2daemon-flexvol:v3.10.3
docker save -o calico-node-v3.10.3.tar calico/node:v3.10.3
docker save -o calico-kube-controllers-v3.10.3.tar calico/kube-controllers:v3.10.3
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;同样拉取完成后打包复制到资源包&lt;code&gt;/root/k8sOfflineSetup/images&lt;/code&gt;目录中。&lt;/p&gt;
&lt;h4 id=&#34;kubernetes-dashboard&#34;&gt;kubernetes dashboard&lt;/h4&gt;
&lt;p&gt;从GitHub上找到Dashboard最新版本部署文件。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dashboard版本发布地址：&lt;a href=&#34;https://github.com/kubernetes/dashboard/releases&#34;&gt;https://github.com/kubernetes/dashboard/releases&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下载&lt;a href=&#34;https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc5/aio/deploy/recommended.yaml&#34;&gt;v2.0.0-rc5&lt;/a&gt;，命名为&lt;code&gt;dashboard-v2.0.0-rc5.yaml&lt;/code&gt;保存到资源包&lt;code&gt;/root/k8sOfflineSetup/plugins&lt;/code&gt;目录中。&lt;/p&gt;
&lt;p&gt;修改&lt;code&gt;dashboard-v2.0.0-rc5.yaml&lt;/code&gt;的imagePullPolicy,默认是&lt;code&gt;Always&lt;/code&gt;，注释掉。否则即使本地已有镜像dashboard启动时还是要从网上拉取。为了内网能正常运行，所以禁止每次运行都重新pull image。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;找出镜像列表&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cat dashboard-v2.0.0-rc5.yaml | grep image: | awk &#39;{print $2}&#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;得到着两个镜像名称&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;kubernetesui/dashboard:v2.0.0-rc5&lt;/li&gt;
&lt;li&gt;kubernetesui/metrics-scraper:v1.0.3&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;拉取镜像&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cat dashboard-v2.0.0-rc5.yaml \
    | grep image: \
    | awk &#39;{print &amp;quot;docker pull &amp;quot; $2}&#39; \
    | sh

# 在当前目录导出镜像为压缩包
docker save -o kubernetesui-dashboard-v2.0.0-rc5.tar kubernetesui/dashboard:v2.0.0-rc5
docker save -o kubernetesui-metrics-scraper-v1.0.3.tar kubernetesui/metrics-scraper:v1.0.3
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;同样拉取完成后打包复制到资源包&lt;code&gt;/root/k8sOfflineSetup/images&lt;/code&gt;目录中。&lt;/p&gt;
&lt;h4 id=&#34;kuboard&#34;&gt;Kuboard&lt;/h4&gt;
&lt;p&gt;查看Kuboard官网安装文档，从中获取到需要&lt;code&gt;kuboard.yaml&lt;/code&gt;和&lt;code&gt;metrics-server.yaml&lt;/code&gt;两个部署文件，中需要使用以下两个镜像，还是按前面到方法拉下来保存起来。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;eipwork/kuboard:latest&lt;/li&gt;
&lt;li&gt;registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;
# 拉取镜像
docker pull eipwork/kuboard:latest
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6

# 在当前目录导出镜像为压缩包
docker save -o kuboard-latest.tar eipwork/kuboard:latest
docker save -o kuboard-metrics-server-amd64-v0.3.6.tar registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;同样拉取完成后打包复制到资源包&lt;code&gt;/root/k8sOfflineSetup/images&lt;/code&gt;目录中。&lt;/p&gt;
&lt;h4 id=&#34;nginx-ingress-controller&#34;&gt;NGINX Ingress Controller&lt;/h4&gt;
&lt;p&gt;同样在官方网站找到部署yaml文件，并获取镜像列。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://kubernetes.github.io/ingress-nginx/deploy/&#34;&gt;https://kubernetes.github.io/ingress-nginx/deploy/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这里下载&lt;a href=&#34;https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.29.0/deploy/static/mandatory.yaml&#34;&gt;ingress-nginx-v0.29.0&lt;/a&gt;，命名为&lt;code&gt;ingress-nginx-v0.29.0.yaml&lt;/code&gt;保存到资源包&lt;code&gt;/root/k8sOfflineSetup/plugins&lt;/code&gt;目录中。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;找出镜像列表&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cat ingress-nginx-v0.29.0.yaml | grep image: | awk &#39;{print $2}&#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;得到如下镜像&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.29.0&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;拉取镜像&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cat ingress-nginx-v0.29.0.yaml \
    | grep image: \
    | awk &#39;{print &amp;quot;docker pull &amp;quot; $2}&#39; \
    | sh

# 如果网络原因拉取速度太慢可从这儿拉取再重新tag
# docker pull quay.azk8s.cn/kubernetes-ingress-controller/nginx-ingress-controller:0.29.0
# docker tag quay.azk8s.cn/kubernetes-ingress-controller/nginx-ingress-controller:0.29.0 quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.29.0
# docker rim quay.azk8s.cn/kubernetes-ingress-controller/nginx-ingress-controller:0.29.0

# 在当前目录导出镜像为压缩包
docker save -o nginx-ingress-controller-0.29.0.tar quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.29.0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;同样拉取完成后打包复制到资源包&lt;code&gt;/root/k8sOfflineSetup/images&lt;/code&gt;目录中。&lt;/p&gt;
&lt;h4 id=&#34;资源包打包&#34;&gt;资源包打包&lt;/h4&gt;
&lt;p&gt;将下载到&lt;code&gt;packages&lt;/code&gt;、&lt;code&gt;images&lt;/code&gt;与&lt;a href=&#34;https://github.com/scfido/k8s-offline-setup&#34;&gt;https://github.com/scfido/k8s-offline-setup&lt;/a&gt;仓库的文件合并，最后的目录应该是这样的。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;📁k8sOfflineSetup
├── 📁gpg
├── 📁plugins
├── 📁repos
├── 📁scripts
├── 📁packages
├── 📁images
├── 📃setup_master.sh
└── 📃setup_worker.sh
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;压缩资源包&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd /root/k8sOfflineSetup
tar -czf k8sOfflineSetup.tar.gz *
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;现在就完成了可以离线安装到Kubernetes单节点Master集群到资源包。&lt;/p&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/k8s/" term="k8s" label="k8s" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/k8s/" term="k8s" label="k8s" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Tidb探究 Tidb性能调优</title>
            <link rel="alternate" type="text/html" href="/blog/posts/tidb/tidb-majorization/" />
            <id>/blog/posts/tidb/tidb-majorization/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2022-09-15T15:00:14&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Tidb探究 Tidb性能调优 设置 scan 操作的并发度,默认是15 通过navicat连接数据库，使用命令列界面执行下面命令： # 查询session的当前值 select @@tidb_distsql_scan_concurrency; # 查询glo……</summary>
            
                <content type="html">&lt;h1 id=&#34;centertidb探究-tidb性能调优center&#34;&gt;&lt;center&gt;Tidb探究 Tidb性能调优&lt;/center&gt;&lt;/h1&gt;
&lt;h4 id=&#34;设置-scan-操作的并发度默认是15&#34;&gt;设置 scan 操作的并发度,默认是15&lt;/h4&gt;
&lt;p&gt;通过navicat连接数据库，使用命令列界面执行下面命令：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 查询session的当前值
select @@tidb_distsql_scan_concurrency;
# 查询global的当前值
select @@global.tidb_distsql_scan_concurrency;
 
# 全局
set global tidb_distsql_scan_concurrency=30;
# session
set session tidb_distsql_scan_concurrency=30;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;索引添加&#34;&gt;索引添加&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 查询索引
show index from tableName

# 添加索引
CREATE INDEX indeKey ON tableName (字段1, 字段2);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;单条sql只能使用一个索引，开始索引合并测试不生效。需要后续测试&lt;/p&gt;
&lt;p&gt;使用索引时，需要注意一下情况无法使用索引：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;避免总是 SELECT * 查询所有列的语句&lt;/li&gt;
&lt;li&gt;查询条件使用 !=，NOT IN 时，无法使用索引。&lt;/li&gt;
&lt;li&gt;使用 LIKE 时如果条件是以通配符 % 开头，也无法使用索引。&lt;/li&gt;
&lt;li&gt;查询条件使用 IN 表达式时，后面匹配的条件数量建议不要超过 300 个，否则执行效率会较差。&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;使用tiflash&#34;&gt;使用TiFlash&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# count 表示副本数，0 表示删除。
ALTER TABLE table_name SET TIFLASH REPLICA count;


# 查看表同步进度
# AVAILABLE 字段表示该表的 TiFlash 副本是否可用。1 代表可用，0 代表不可用。副本
# PROGRESS 字段代表同步进度，在 0.0~1.0 之间，1 代表至少 1 个副本已经完成同步
SELECT * FROM information_schema.tiflash_replica WHERE TABLE_SCHEMA = &#39;&amp;lt;db_name&amp;gt;&#39; and TABLE_NAME = &#39;&amp;lt;table_name&amp;gt;&#39;;
&lt;/code&gt;&lt;/pre&gt;</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/tidb/" term="TiDB" label="TiDB" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/tidb/" term="TiDB" label="TiDB" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Tidb探究 mysql迁移问题</title>
            <link rel="alternate" type="text/html" href="/blog/posts/tidb/tidb-lightning-question/" />
            <id>/blog/posts/tidb/tidb-lightning-question/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2022-08-11T15:11:07&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Tidb探究 mysql迁移问题 1、The isolation level &#39;SERIALIZABLE&#39; is not supported. Set tidb_skip_isolation_level_check=1 to skip this error 通过navicat连接数据库，使用命令列界面执行下面命令： set global tidb_skip_isolation_level_check=1; TiDB 不支持 SERIALIZABLE 隔离级别，设置 tidb_skip_isolation_level_check 只是将……</summary>
            
                <content type="html">&lt;h1 id=&#34;centertidb探究-mysql迁移问题center&#34;&gt;&lt;center&gt;Tidb探究 mysql迁移问题&lt;/center&gt;&lt;/h1&gt;
&lt;h4 id=&#34;1the-isolation-level-serializable-is-not-supported-set-tidb_skip_isolation_level_check1-to-skip-this-error&#34;&gt;1、The isolation level &#39;SERIALIZABLE&#39; is not supported. Set tidb_skip_isolation_level_check=1 to skip this error&lt;/h4&gt;
&lt;p&gt;通过navicat连接数据库，使用命令列界面执行下面命令：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-纯文本&#34; data-lang=&#34;纯文本&#34;&gt;set global tidb_skip_isolation_level_check=1;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;TiDB 不支持 SERIALIZABLE 隔离级别，设置 tidb_skip_isolation_level_check 只是将报错信息变成了 warning ，实际上设置 SERIALIZABLE 还是不生效的。  &lt;/p&gt;
&lt;p&gt;设置了 tidb_skip_isolation_level_check=1 还是会报错是因为你是会话级别设置了这个参数，只对当前会话生效。要全局生效的话，可以 set global tidb_skip_isolation_level_check=1;&lt;/p&gt;
&lt;h4 id=&#34;2group-by不支持问题&#34;&gt;2、group by不支持问题&lt;/h4&gt;
&lt;p&gt;TiDB 支持 SQL 模式 &lt;code&gt;ONLY_FULL_GROUP_BY&lt;/code&gt;，当启用该模式时，TiDB 拒绝不明确的非聚合列的查询。目前，TiDB 默认开启 SQL 模式 &lt;code&gt;ONLY_FULL_GROUP_BY&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;通过navicat连接数据库，使用命令列界面执行下面命令：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-纯文本&#34; data-lang=&#34;纯文本&#34;&gt;# 更新全局  对全局作用域变量的更改将作用于集群中的其它服务器，并且重启后更改依然有效。
set @@global.sql_mode=&#39;STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION&#39;;
# 更新当前会话
set @@sql_mode=&#39;STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION&#39;; 

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;例如：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-纯文本&#34; data-lang=&#34;纯文本&#34;&gt;select a, b, sum(c) from t group by a;

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;会报下面的错误：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-纯文本&#34; data-lang=&#34;纯文本&#34;&gt;ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column &#39;b&#39; which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;3tidb-sql兼容适配max_allowed_packet&#34;&gt;3、tidb sql兼容适配max_allowed_packet&lt;/h4&gt;
&lt;p&gt;批量插入数量过多时，会出现下面得错误：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;com.mysql.cj.jdbc.exceptions.PacketTooBigException: Packet for query is too large (70,199,179 &amp;gt; 67,108,864). You can change this value on the server by setting the ‘max_allowed_packet’ variable.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;执行下面命令解决：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;默认 67108864 (64 MB)
set @@global.max_allowed_packet=134217728;   （ 134217728 = 128M ）
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;&lt;font color=red size=3 &gt;注意：这个虽然是持久化的，但是不会对已连接的会话产生影响，只对新连接的会话产生影响。所以需要重启相应得服务。&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&#34;4-tidb-transaction-is-too-large&#34;&gt;4、 tidb Transaction is too large&lt;/h4&gt;
&lt;p&gt;TiDB限制了单条KV entry不超过6MB，可以修改配置文件中的txn-entry-size-limit配置项进行调整，最大可以修改到120MB。&lt;br&gt;
分布式事务要做两阶段提交，而且底层还需要做 Raft 复制。如果一个事务非常大，提交过程会非常慢，事务写冲突概率会增加，而且事务失败后回滚会导致不必要的性能开销。所以我们设置了 key-value entry 的总大小默认不超过100MB。如果业务需要使用大事务，可以修改配置文件中的txn-total-size-limit 配置项进行调整，最大可以修改到 10G。实际的大小限制还受机器的物理内存影响。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tiup cluster edit-config tidb-fhzh

修改相应配置
server_configs:
  tidb:
    performance.txn-total-size-limit: 1073741824    1073741824(1G)，改成10G 目前已完成


tiup cluster reload tidb-fhzh -R tidb
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;5单条sql处理出现out-of-memory-quota问题&#34;&gt;5、单条sql处理出现Out of Memory Quota问题&lt;/h4&gt;
&lt;p&gt;使用系统变量tidb_mem_quota_query 来配置一条 SQL 执行过程中的内存使用阈值，单位为字节。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 查看配置
select @@tidb_mem_quota_query;

# 配置8G 下面两条命令有待验证
set global tidb_mem_quota_query=8589934592;
SET @@global.tidb_mem_quota_query = 8589934592;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;distinct聚合函数优化有待验证&#34;&gt;distinct聚合函数优化(有待验证)&lt;/h4&gt;
&lt;p&gt;session会话中可以先执行下面得命令进行优化测试：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;set session tidb_opt_distinct_agg_push_down = 1;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;全局优化，需要重新配置tidb得配置&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tiup cluster edit-config tidb-fhzh

修改相应配置
server_configs:
  tidb:
    distinct-agg-push-down: true    


tiup cluster reload tidb-fhzh -R tidb
&lt;/code&gt;&lt;/pre&gt;</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/tidb/" term="TiDB" label="TiDB" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/tidb/" term="TiDB" label="TiDB" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Modbus RTU与Modbus TCP的区别</title>
            <link rel="alternate" type="text/html" href="/blog/posts/modbus/tcp-rtu/" />
            <id>/blog/posts/modbus/tcp-rtu/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2022-08-05T08:54:30&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Modbus RTU与Modbus TCP的区别 Modbus简介 Modbus通信协议具有多个变种，支持串口（主要是RS-485总线），以太网多个版本，其中最著名的是Modbu……</summary>
            
                <content type="html">&lt;h1 id=&#34;centermodbus-rtu与modbus-tcp的区别center&#34;&gt;&lt;center&gt;Modbus RTU与Modbus TCP的区别&lt;/center&gt;&lt;/h1&gt;
&lt;h2 id=&#34;modbus简介&#34;&gt;Modbus简介&lt;/h2&gt;
&lt;p&gt;  Modbus通信协议具有多个变种，支持串口（主要是RS-485总线），以太网多个版本，其中最著名的是Modbus RTU,Modbus ASCII和Modbus TCP三种。
在工业现场一般都是采用Modbus RTU协议，一般而言，大家说的基于串口通信的Modbus通信协议都是指Modbus RTU通信协议。与Modbus RTU协议相比较，Modbus TCP协议则是在RTU协议上加一个MBAP报文头，并且由于TCP是基于可靠连接的服务，RTU协议中的CRC校验码就不再需要，所以在Modbus TCP协议中是没有CRC校验码的，所以就常用一句比较通俗的话来说：Modbus TCP协议就是Modbus RTU协议在前面加上五个0以及一个6，然后去掉两个CRC校验码字节就OK。&lt;/p&gt;
&lt;h2 id=&#34;modbus功能码&#34;&gt;Modbus功能码&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;功能码&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;含义&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0x01&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;读线圈&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0x02&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;读离散量输入&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0x03&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;读保持寄存器&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0x04&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;读输入寄存器&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0x05&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;写单个线圈&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0x06&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;写单个保持寄存器&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0x10&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;写多个保持寄存器&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0x0F&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;写多个线圈&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;modbus-rtu&#34;&gt;Modbus RTU&lt;/h2&gt;
&lt;p&gt;  RTU协议中的指令由地址码(一个字节），功能码（一个字节），起始地址（两个字节），数据（N个字节），校验码（两个字节）五个部分组成。数据由数据长度（两个字节，表示的是寄存器个数，假定为M）和数据正文（M乘以2个字节）组成。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 读（0x03），从寄存器地址01 8E 开始读，读4个寄存器00 04
发：01 03 01 8E 00 04 25 DE  
# 08表示数据长度  ，00 01 00 01 00 01 00 01读到的数据
回：01 03 08 00 01 00 01 00 01 00 01 28 D7 

 
# 写（0x10），从寄存器地址 00 20开始写，写一个寄存器 00 01，写入值 00 00
发：00 10 00 20 00 01 02 00 00 AC A0
回：00 10 00 20 00 01 01 D2

&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;modbus-tcp&#34;&gt;Modbus TCP&lt;/h2&gt;
&lt;p&gt;  Modbus TCP协议是在RTU协议前面添加MBAP报文头，由于TCP是基于可靠连接的服务，RTU协议中的CRC校验码就不再需要，所以在Modbus TCP协议中是没有CRC校验码。&lt;br&gt;
MBAP报文头： &lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;事务处理标识&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;协议标识&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;长度&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;单元标识符&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;2字节&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;2字节&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;2字节&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;1字节&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;备注标识： &lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;报文头&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;事务处理标识&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;可以理解为报文的序列号，一般每次通信之后就要加1以区别不同的通信数据报文&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;协议标识符&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;00 00表示ModbusTCP协议&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;长度&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;表示接下来的数据长度，单位为字节&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;单元标识符&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;可以理解为设备地址&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 读取
发：00 00 00 00 00 06 00 03 00 20 00 01 
回：00 00 00 00 00 05 00 03 02 00 00 

发：00 00 00 00 00 06 00 04 00 30 00 01
回：00 00 00 00 00 05 00 04 02 00 08 

 
# 写入
发：00 00 00 00 00 09 00 10 00 20 00 01 02 00 00
回：00 00 00 00 00 06 00 10 00 20 00 01
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;rtu和tcp对比16进制发送&#34;&gt;RTU和TCP对比(16进制发送)&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;读指令对比(例：0x04)&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;MBAP报文头&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;地址码&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;功能码&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;寄存器地址&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;寄存器数量&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;CRC校验&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Modbus RTU&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;无&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;01&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;04&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;00 00&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;00 16&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;71 C4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Modbus TCP&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;00 00 00 00 00 06 01&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;04&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;00 00&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;00 16&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;无&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;写指令对比(例：0x10)&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;MBAP报文头&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;地址码&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;功能码&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;寄存器地址&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;寄存器数量&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;数据长度&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;正文&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;CRC校验&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Modbus RTU&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;无&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;00&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;10&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;00 20&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;00 01&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;02&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;00 00&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;AC A0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Modbus TCP&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;00 00 00 00 00 09 00&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;10&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;00 20&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;00 01&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;02&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;00 00&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;无&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/modbus/" term="Modbus" label="Modbus" />
                            
                        
                            
                            
                            
                                <category scheme="/blog/categories/rtu/" term="RTU" label="RTU" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/modbus/" term="Modbus" label="Modbus" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Tidb探究 Mysql迁入TiDB</title>
            <link rel="alternate" type="text/html" href="/blog/posts/tidb/tidb-mysql-to-tidb/" />
            <id>/blog/posts/tidb/tidb-mysql-to-tidb/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2022-08-01T17:32:01&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Tidb探究 Mysql迁入TiDB TiDB是一个分布式关系型数据库，可以无缝对接 MySQL。考虑到产品数据量大的情况下，单机MySQL可能无法支撑，而无缝切换到……</summary>
            
                <content type="html">&lt;h1 id=&#34;centertidb探究-mysql迁入tidbcenter&#34;&gt;&lt;center&gt;Tidb探究 Mysql迁入TiDB&lt;/center&gt;&lt;/h1&gt;
&lt;p&gt;TiDB是一个分布式关系型数据库，可以无缝对接 MySQL。考虑到产品数据量大的情况下，单机MySQL可能无法支撑，而无缝切换到TiDB集群也比较方便。&lt;br&gt;
使用Dumpling工具导出MySQL数据库数据，并使用TiDB Lightning将数据迁移到TiDB集群的流程。&lt;/p&gt;
&lt;h3 id=&#34;1迁移工具下载&#34;&gt;1、迁移工具下载&lt;/h3&gt;
&lt;p&gt;TiDB-community-toolkit软件包可以在&lt;a href=&#34;https://pingcap.com/zh/product-community&#34;&gt;官网&lt;/a&gt;下载。将下载的tidb-community-toolkit-v6.1.0-linux-amd64.tar.gz放在中控机master的tidb账号下的/home/tidb文件目录。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 解压文件
tar -xzf tidb-toolkit-v4.0.0-linux-amd64.tar.gz
cd ./tidb-toolkit-v4.0.0-linux-amd64
tar -xzf ./dumpling-v6.1.0-linux-amd64.tar.gz 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;进入该文件夹，可以看到对应工具&lt;img src=&#34;/blog/blog/images/tidb/toolkit1.png&#34; alt=&#34;工具&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;2mysql数据备份&#34;&gt;2、MySQL数据备份&lt;/h3&gt;
&lt;p&gt;Dumpling和tidb-lightning就是一对导出、导入工具，其中Dumpling跟MySQL的mysqldump功能是一样的。&lt;br&gt;
建议使用Dumpling，原因是用它导出的数据时，会自动创建 xxx-schema-create.sql建库文件，而且建表和插入SQL文件分开，不用额外操作，配套用tidb-lightning执行导入，不容易出错。&lt;br&gt;
在工具文件夹下，用Dumpling工具连接目标数据库导出，命令如下：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;./dumpling -h 172.16.1.71 -P 30306 -u root -p 123456 -t 16 -F256MiB -B ry-cloud --filetype sql  -o /tidb-data/mydumpersql/ -r 200000 
# 执行时间过程，请耐心等待
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;参数说明：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;主要选项&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;用途&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-V 或 --version&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;输出 Dumpling 版本并直接退出&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-B 或 --database&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;导出指定的数据库&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-T 或 --tables-list&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;导出指定数据表&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-f 或 --filter&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;导出能匹配模式的表&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;--case-sensitive&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;table-filter 是否大小写敏感&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-t 或 --threads&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;备份执行的线程数，默认4个线程&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-r 或 --rows&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;将 table 划分成 row 行数据，一般针对大表操作并发生成多个文件&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-L 或 --logfile&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;日志输出地址，为空时会输出到控制台&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-F 或 --filesize&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;将 table 数据划分出来的文件大小，需指明单位（如 128B, 64KiB, 32MiB, 1.5GiB）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-o 或 --output&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;导出本地文件路径或外部存储 URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;--filetype&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;导出文件类型（csv/sql）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-p 或 --password&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;连接的数据库主机的密码&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-P 或 --port&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;连接的数据库主机的端口&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;注意：最后一个 outputdir 的值，后面导入的时候需要使用。&lt;/p&gt;
&lt;h3 id=&#34;3tidb-lightning导入数据&#34;&gt;3、tidb-lightning导入数据&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;进入tidb-toolkit-v4.0.0-linux-amd64文件夹，解压TiDB Lightning安装包&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tar -xzf ./tidb-lightning-v6.1.0-linux-amd64.tar.gz
&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;配置 tidb-lightning.toml
在/home/tidb/tidb-toolkit-v4.0.0-linux-amd64文件夹下添加文件tidb-lightning.toml&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[lightning]
# 日志
level = &amp;quot;info&amp;quot;
file = &amp;quot;tidb-lightning.log&amp;quot;

[tikv-importer]
# 选择使用的导入模式
backend = &amp;quot;local&amp;quot;
# 设置排序的键值对的临时存放地址，目标路径需要是一个空目录，不存在就新建文件夹  
sorted-kv-dir = &amp;quot;/mnt/ssd/sorted-kv-dir&amp;quot;

[mydumper]
# 源数据目录。
data-source-dir = &amp;quot;/tidb-data/mydumpersql&amp;quot;

# 配置通配符规则，默认规则会过滤 mysql、sys、INFORMATION_SCHEMA、PERFORMANCE_SCHEMA、METRICS_SCHEMA、INSPECTION_SCHEMA 系统数据库下的所有表
# 若不配置该项，导入系统表时会出现“找不到 schema”的异常
filter = [&#39;*.*&#39;, &#39;!mysql.*&#39;, &#39;!sys.*&#39;, &#39;!INFORMATION_SCHEMA.*&#39;, &#39;!PERFORMANCE_SCHEMA.*&#39;, &#39;!METRICS_SCHEMA.*&#39;, &#39;!INSPECTION_SCHEMA.*&#39;]
[tidb]
# 目标集群的信息
host = &amp;quot;172.16.1.73&amp;quot;
port = 4000
user = &amp;quot;root&amp;quot;
password = &amp;quot;123456&amp;quot;
# 表架构信息在从 TiDB 的“状态端口”获取。
status-port = 10080
# 集群 pd 的地址
pd-addr = &amp;quot;172.16.1.73:2379&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;开始还原&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 在/home/tidb/tidb-toolkit-v4.0.0-linux-amd64目录下执行下面命令：
./tidb-lightning -config tidb-lightning.toml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;等待一段时间后，输出如下信息即还原完成。如有问题，可在当前目录下查看tidb-lightning.log
&lt;img src=&#34;/blog/blog/images/tidb/toolkit2.png&#34; alt=&#34;输出&#34;&gt;&lt;/p&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/tidb/" term="TiDB" label="TiDB" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/tidb/" term="TiDB" label="TiDB" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">TiDB建库建用户及授权</title>
            <link rel="alternate" type="text/html" href="/blog/posts/tidb/tidb-user-password/" />
            <id>/blog/posts/tidb/tidb-user-password/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2022-08-01T16:01:08&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">TiDB建库建用户及授权 TiDB初始化账号 TiDB部署完之后，会生成一个密码，可以用来登录数据库并进行修改。 密码验证长度修改 set global validate_password_length=3; root授权远程访问 ALTER USER &#39;root&#39;@&#39;%&#39; IDENTIFIED BY……</summary>
            
                <content type="html">&lt;h1 id=&#34;centertidb建库建用户及授权center&#34;&gt;&lt;center&gt;TiDB建库建用户及授权&lt;/center&gt;&lt;/h1&gt;
&lt;h2 id=&#34;tidb初始化账号&#34;&gt;TiDB初始化账号&lt;/h2&gt;
&lt;p&gt;TiDB部署完之后，会生成一个密码，可以用来登录数据库并进行修改&lt;img src=&#34;/blog/blog/images/tidb/user_password1.png&#34; alt=&#34;图片&#34;&gt;。&lt;/p&gt;
&lt;h3 id=&#34;密码验证长度修改&#34;&gt;密码验证长度修改&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;set global validate_password_length=3;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;root授权远程访问&#34;&gt;root授权远程访问&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ALTER USER &#39;root&#39;@&#39;%&#39; IDENTIFIED BY &#39;123456&#39;; 
grant all privileges on *.* to &#39;root&#39;@&#39;%&#39; identified by &#39;123456&#39;;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;创建用户&#34;&gt;创建用户&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# localhost   密码123456
CREATE USER &#39;tidb&#39;@&#39;localhost&#39; IDENTIFIED BY &#39;123456&#39;; 

# %   密码123456   可以指定ip
CREATE USER &#39;tidb&#39;@&#39;%&#39; IDENTIFIED BY &#39;123456&#39;; 
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;授权&#34;&gt;授权&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# tidb.* 指 数据库tidb; 全部授权使用 *.*
grant all privileges on tidb.* to &#39;tidb&#39;@&#39;localhost&#39; identified by &#39;123456&#39;;


grant all privileges on tidb.* to &#39;tidb&#39;@&#39;%&#39; identified by &#39;123456&#39;;

&lt;/code&gt;&lt;/pre&gt;</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/tidb/" term="TiDB" label="TiDB" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/tidb/" term="TiDB" label="TiDB" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Tidb探究 离线安装</title>
            <link rel="alternate" type="text/html" href="/blog/posts/tidb/tidb-offline-setup/" />
            <id>/blog/posts/tidb/tidb-offline-setup/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2022-07-13T08:41:51&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Tidb探究 离线安装 TiDB介绍 什么是TiDB TiDB 是 PingCAP 公司自主设计、研发的开源分布式关系型数据库，是一款同时支持在线事务处理与在线分析处理 (Hybrid Transactional and Analytical Processing, HTAP）的融……</summary>
            
                <content type="html">&lt;h1 id=&#34;centertidb探究-离线安装center&#34;&gt;&lt;center&gt;Tidb探究 离线安装&lt;/center&gt;&lt;/h1&gt;
&lt;h2 id=&#34;tidb介绍&#34;&gt;TiDB介绍&lt;/h2&gt;
&lt;h3 id=&#34;什么是tidb&#34;&gt;什么是TiDB&lt;/h3&gt;
&lt;p&gt;TiDB 是 PingCAP 公司自主设计、研发的开源分布式关系型数据库，是一款同时支持在线事务处理与在线分析处理 (Hybrid Transactional and Analytical Processing, HTAP）的融合型分布式数据库产品，具备水平扩容或者缩容、金融级高可用、实时 HTAP、云原生的分布式数据库、兼容 MySQL 5.7 协议和 MySQL 生态等重要特性。目标是为用户提供一站式 OLTP (Online Transactional Processing)、OLAP (Online Analytical Processing)、HTAP 解决方案。TiDB 适合高可用、强一致要求较高、数据规模较大等各种应用场景。&lt;/p&gt;
&lt;h3 id=&#34;tidb五大核心特性&#34;&gt;TiDB五大核心特性&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;一键水平扩容或者缩容&lt;br&gt;
得益于 TiDB 存储计算分离的架构的设计，可按需对计算、存储分别进行在线扩容或者缩容，扩容或者缩容过程中对应用运维人员透明。&lt;/li&gt;
&lt;li&gt;金融级高可用&lt;br&gt;
数据采用多副本存储，数据副本通过 Multi-Raft 协议同步事务日志，多数派写入成功事务才能提交，确保数据强一致性且少数副本发生故障时不影响数据的可用性。可按需配置副本地理位置、副本数量等策略满足不同容灾级别的要求。&lt;/li&gt;
&lt;li&gt;实时 HTAP&lt;br&gt;
提供行存储引擎 TiKV、列存储引擎 TiFlash 两款存储引擎，TiFlash 通过 Multi-Raft Learner 协议实时从 TiKV 复制数据，确保行存储引擎 TiKV 和列存储引擎 TiFlash 之间的数据强一致。TiKV、TiFlash 可按需部署在不同的机器，解决 HTAP 资源隔离的问题。&lt;/li&gt;
&lt;li&gt;云原生的分布式数据库&lt;br&gt;
专为云而设计的分布式数据库，通过 TiDB Operator 可在公有云、私有云、混合云中实现部署工具化、自动化。&lt;/li&gt;
&lt;li&gt;兼容 MySQL 5.7 协议和 MySQL 生态&lt;br&gt;
兼容 MySQL 5.7 协议、MySQL 常用的功能、MySQL 生态，应用无需或者修改少量代码即可从 MySQL 迁移到 TiDB。提供丰富的数据迁移工具帮助应用便捷完成数据迁移。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;tidb离线安装部署&#34;&gt;TiDB离线安装部署&lt;/h2&gt;
&lt;h3 id=&#34;一前期准备&#34;&gt;一、前期准备&lt;/h3&gt;
&lt;h4 id=&#34;wmware虚拟环境&#34;&gt;wmware虚拟环境&lt;/h4&gt;
&lt;p&gt;使用vmware部署3个节点服务器，分别是master,node1,node2;使用&lt;a href=&#34;https://mirrors.aliyun.com/centos/7/isos/x86_64/CentOS-7-x86_64-DVD-2009.iso?spm=a2c6h.25603864.0.0.74092d1cWv24j8&#34;&gt;CentOS7镜像&lt;/a&gt;,&lt;/p&gt;
&lt;h4 id=&#34;创建普通用户--每个节点&#34;&gt;创建普通用户--每个节点&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;groupadd tidb 
useradd tidb -g tidb 
passwd tidb 
输入密码
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;sudo免密&#34;&gt;sudo免密&lt;/h4&gt;
&lt;p&gt;在每个节点执行如下命令来配置 sudo 免密&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;vi /etc/sudoers

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;最后一行输入：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tidb ALL=(ALL) NOPASSWD: ALL  

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;font color=&#39;red&#39; size=2&gt;&lt;em&gt;注意最后需要空一行&lt;/em&gt;&lt;/font&gt;&lt;/p&gt;
&lt;h4 id=&#34;验证sudo免密&#34;&gt;验证sudo免密&lt;/h4&gt;
&lt;p&gt;登录中控机master，切换到tidb用户&lt;br&gt;
ssh 到其他目标节点&lt;br&gt;
以192.168.174.129节点为例，其他节点也需要验证&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;su - tidb 
ssh 192.168.174.129  
输入密码
sudo -su root
不需要密码切换到`root`用户，表示`sudo`免密成功
eixt   //退出ssh
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;关闭防火墙&#34;&gt;关闭防火墙&lt;/h4&gt;
&lt;p&gt;每个节点都需要关闭系统的防火墙&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# root账号下执行以下命令
# 防火墙状态
systemctl status firewalld
# 临时关闭防火墙
systemctl stop firewalld
# 永久关闭防火墙
systemctl disable firewalld

&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;ip&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;备注&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;功能&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;192.168.174.128&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;中控机master&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;无&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;192.168.174.129&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;node1&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;PD,DB,KV,TIFLASH,MONITOR,GRAFANA,ALERTMANAGER&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;192.168.174.130&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;node2&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;PD,DB,KV,TIFLASH&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;192.168.174.131&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;node3&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;PD,DB,KV,TIFLASH&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&#34;tidb离线包下载&#34;&gt;tidb离线包下载&lt;/h4&gt;
&lt;p&gt;使用社区版离线进行部署，软件包可以在&lt;a href=&#34;https://pingcap.com/zh/product-community&#34;&gt;官网&lt;/a&gt;下载。将下载的tidb-community-server-v6.1.0-linux-amd64.tar.gz放在中控机master的tidb账号下的/home/tidb文件目录&lt;/p&gt;
&lt;h3 id=&#34;二安装部署&#34;&gt;二、安装部署&lt;/h3&gt;
&lt;h4 id=&#34;解压执行&#34;&gt;解压执行&lt;/h4&gt;
&lt;p&gt;下面命令在中控机master执行&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;su - tidb
tar xzvf tidb-community-server-v6.1.0-linux-amd64.tar.gz
sh tidb-community-server-v6.1.0-linux-amd64/local_install.sh
source /home/tidb/.bash_profile
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&#34;/blog/blog/images/tidb/offline_setup1.png&#34; alt=&#34;解压&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;配置初始化参数文件topologyyaml&#34;&gt;配置初始化参数文件topology.yaml&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#执行命令
vi topology.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;topology.yaml的内容如下：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;global:
  user: &amp;quot;tidb&amp;quot;
  ssh_port: 22
  deploy_dir: &amp;quot;/tidb-deploy&amp;quot;
  data_dir: &amp;quot;/tidb-data&amp;quot;

monitored:
 node_exporter_port: 9100
 blackbox_exporter_port: 9115

server_configs:
 tidb:
   log.slow-threshold: 300
 tikv:
   readpool.storage.use-unified-pool: false
   readpool.coprocessor.use-unified-pool: true
 pd:
   replication.enable-placement-rules: true
   replication.location-labels: [&amp;quot;host&amp;quot;]
 tiflash:
   logger.level: &amp;quot;info&amp;quot;

pd_servers:
  - host: 192.168.174.129
  - host: 192.168.174.130
  - host: 192.168.174.131
tidb_servers:
  - host: 192.168.174.129
  - host: 192.168.174.130
  - host: 192.168.174.131
tikv_servers:
  - host: 192.168.174.129
    config:
      server.labels: { host: &amp;quot;192.168.174.129&amp;quot; }
  - host: 192.168.174.130
    config:
      server.labels: { host: &amp;quot;192.168.174.130&amp;quot; }
  - host: 192.168.174.131
    config:
      server.labels: { host: &amp;quot;192.168.174.131&amp;quot; }
tiflash_servers:
  - host: 192.168.174.129
    data_dir: /data1/tiflash/data
  - host: 192.168.174.130
    data_dir: /data1/tiflash/data
  - host: 192.168.174.131
    data_dir: /data1/tiflash/data
monitoring_servers:
  - host: 192.168.174.129
grafana_servers:
  - host: 192.168.174.129
alertmanager_servers:
  - host: 192.168.174.129

&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;安装部署启动&#34;&gt;安装部署、启动&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#  部署
tiup cluster deploy tidb-vmware v6.1.0 topology.yaml --user tidb -p
输入 y 然后 `tidb` 用户密码密码  
# 这个过程有点漫长，需要耐心等待

# 初始启动命令 
tiup cluster start tidb-vmware  --init

# 查询tidb状态
tiup cluster display tidb-vmware

# 启动命令 
tiup cluster start tidb-vmware

# 重启pd
tiup cluster reload tidb-vmware -R pd

# 删除集群
tiup cluster destroy tidb-vmware --force

# 修改配置
tiup cluster edit-config tidb-vmware 

# 重启tidb
tiup cluster reload tidb-vmware 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;部署输出如下：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[tidb@localhost ~]$ tiup cluster deploy tidb-vmware v6.1.0 topology.yaml --user tidb -p
tiup is checking updates for component cluster ...
A new version of cluster is available:
   The latest version:         v1.10.2
   Local installed version:    
   Update current component:   tiup update cluster
   Update all components:      tiup update --all

The component `cluster` version  is not installed; downloading from repository.
Starting component `cluster`: /home/tidb/.tiup/components/cluster/v1.10.2/tiup-cluster deploy tidb-vmware v6.1.0 topology.yaml --user tidb -p
Input SSH password: 



+ Detect CPU Arch Name
  - Detecting node 192.168.174.129 Arch info ... Done
  - Detecting node 192.168.174.130 Arch info ... Done
  - Detecting node 192.168.174.131 Arch info ... Done



+ Detect CPU OS Name
  - Detecting node 192.168.174.129 OS info ... Done
  - Detecting node 192.168.174.130 OS info ... Done
  - Detecting node 192.168.174.131 OS info ... Done
Please confirm your topology:
Cluster type:    tidb
Cluster name:    tidb-vmware
Cluster version: v6.1.0
Role          Host             Ports                            OS/Arch       Directories
----          ----             -----                            -------       -----------
pd            192.168.174.129  2379/2380                        linux/x86_64  /tidb-deploy/pd-2379,/tidb-data/pd-2379
tikv          192.168.174.130  20160/20180                      linux/x86_64  /tidb-deploy/tikv-20160,/tidb-data/tikv-20160
tikv          192.168.174.131  20160/20180                      linux/x86_64  /tidb-deploy/tikv-20160,/tidb-data/tikv-20160
tidb          192.168.174.130  4000/10080                       linux/x86_64  /tidb-deploy/tidb-4000
tidb          192.168.174.131  4000/10080                       linux/x86_64  /tidb-deploy/tidb-4000
tiflash       192.168.174.129  9000/8123/3930/20170/20292/8234  linux/x86_64  /tidb-deploy/tiflash-9000,/data1/tiflash/data
tiflash       192.168.174.130  9000/8123/3930/20170/20292/8234  linux/x86_64  /tidb-deploy/tiflash-9000,/data1/tiflash/data
tiflash       192.168.174.131  9000/8123/3930/20170/20292/8234  linux/x86_64  /tidb-deploy/tiflash-9000,/data1/tiflash/data
prometheus    192.168.174.129  9090/12020                       linux/x86_64  /tidb-deploy/prometheus-9090,/tidb-data/prometheus-9090
grafana       192.168.174.129  3000                             linux/x86_64  /tidb-deploy/grafana-3000
alertmanager  192.168.174.129  9093/9094                        linux/x86_64  /tidb-deploy/alertmanager-9093,/tidb-data/alertmanager-9093
Attention:
    1. If the topology is not what you expected, check your yaml file.
    2. Please confirm there is no port/directory conflicts in same host.
Do you want to continue? [y/N]: (default=N) y
+ Generate SSH keys ... Done
+ Download TiDB components
  - Download pd:v6.1.0 (linux/amd64) ... Done
  - Download tikv:v6.1.0 (linux/amd64) ... Done
  - Download tidb:v6.1.0 (linux/amd64) ... Done
  - Download tiflash:v6.1.0 (linux/amd64) ... Done
  - Download prometheus:v6.1.0 (linux/amd64) ... Done
  - Download grafana:v6.1.0 (linux/amd64) ... Done
  - Download alertmanager: (linux/amd64) ... Done
  - Download node_exporter: (linux/amd64) ... Done
  - Download blackbox_exporter: (linux/amd64) ... Done
+ Initialize target host environments
  - Prepare 192.168.174.129:22 ... Done
  - Prepare 192.168.174.130:22 ... Done
  - Prepare 192.168.174.131:22 ... Done
+ Deploy TiDB instance
  - Copy pd -&amp;gt; 192.168.174.129 ... Done
  - Copy tikv -&amp;gt; 192.168.174.130 ... Done
  - Copy tikv -&amp;gt; 192.168.174.131 ... Done
  - Copy tidb -&amp;gt; 192.168.174.130 ... Done
  - Copy tidb -&amp;gt; 192.168.174.131 ... Done
  - Copy tiflash -&amp;gt; 192.168.174.129 ... Done
  - Copy tiflash -&amp;gt; 192.168.174.130 ... Done
  - Copy tiflash -&amp;gt; 192.168.174.131 ... Done
  - Copy prometheus -&amp;gt; 192.168.174.129 ... Done
  - Copy grafana -&amp;gt; 192.168.174.129 ... Done
  - Copy alertmanager -&amp;gt; 192.168.174.129 ... Done
  - Deploy node_exporter -&amp;gt; 192.168.174.129 ... Done
  - Deploy node_exporter -&amp;gt; 192.168.174.130 ... Done
  - Deploy node_exporter -&amp;gt; 192.168.174.131 ... Done
  - Deploy blackbox_exporter -&amp;gt; 192.168.174.129 ... Done
  - Deploy blackbox_exporter -&amp;gt; 192.168.174.130 ... Done
  - Deploy blackbox_exporter -&amp;gt; 192.168.174.131 ... Done
+ Copy certificate to remote host
+ Init instance configs
  - Generate config pd -&amp;gt; 192.168.174.129:2379 ... Done
  - Generate config tikv -&amp;gt; 192.168.174.130:20160 ... Done
  - Generate config tikv -&amp;gt; 192.168.174.131:20160 ... Done
  - Generate config tidb -&amp;gt; 192.168.174.130:4000 ... Done
  - Generate config tidb -&amp;gt; 192.168.174.131:4000 ... Done
  - Generate config tiflash -&amp;gt; 192.168.174.129:9000 ... Done
  - Generate config tiflash -&amp;gt; 192.168.174.130:9000 ... Done
  - Generate config tiflash -&amp;gt; 192.168.174.131:9000 ... Done
  - Generate config prometheus -&amp;gt; 192.168.174.129:9090 ... Done
  - Generate config grafana -&amp;gt; 192.168.174.129:3000 ... Done
  - Generate config alertmanager -&amp;gt; 192.168.174.129:9093 ... Done
+ Init monitor configs
  - Generate config node_exporter -&amp;gt; 192.168.174.129 ... Done
  - Generate config node_exporter -&amp;gt; 192.168.174.130 ... Done
  - Generate config node_exporter -&amp;gt; 192.168.174.131 ... Done
  - Generate config blackbox_exporter -&amp;gt; 192.168.174.131 ... Done
  - Generate config blackbox_exporter -&amp;gt; 192.168.174.129 ... Done
  - Generate config blackbox_exporter -&amp;gt; 192.168.174.130 ... Done
Enabling component pd
	Enabling instance 192.168.174.129:2379
	Enable instance 192.168.174.129:2379 success
Enabling component tikv
	Enabling instance 192.168.174.131:20160
	Enabling instance 192.168.174.130:20160
	Enable instance 192.168.174.130:20160 success
	Enable instance 192.168.174.131:20160 success
Enabling component tidb
	Enabling instance 192.168.174.131:4000
	Enabling instance 192.168.174.130:4000
	Enable instance 192.168.174.131:4000 success
	Enable instance 192.168.174.130:4000 success
Enabling component tiflash
	Enabling instance 192.168.174.131:9000
	Enabling instance 192.168.174.129:9000
	Enabling instance 192.168.174.130:9000
	Enable instance 192.168.174.129:9000 success
	Enable instance 192.168.174.131:9000 success
	Enable instance 192.168.174.130:9000 success
Enabling component prometheus
	Enabling instance 192.168.174.129:9090
	Enable instance 192.168.174.129:9090 success
Enabling component grafana
	Enabling instance 192.168.174.129:3000
	Enable instance 192.168.174.129:3000 success
Enabling component alertmanager
	Enabling instance 192.168.174.129:9093
	Enable instance 192.168.174.129:9093 success
Enabling component node_exporter
	Enabling instance 192.168.174.131
	Enabling instance 192.168.174.129
	Enabling instance 192.168.174.130
	Enable 192.168.174.130 success
	Enable 192.168.174.131 success
	Enable 192.168.174.129 success
Enabling component blackbox_exporter
	Enabling instance 192.168.174.131
	Enabling instance 192.168.174.129
	Enabling instance 192.168.174.130
	Enable 192.168.174.129 success
	Enable 192.168.174.131 success
	Enable 192.168.174.130 success
Cluster `tidb-vmware` deployed successfully, you can start it with command: `tiup cluster start tidb-vmware --init`

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;部署成功后，可以访问如下地址： &lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;服务器&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;地址&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;pd-dashboard&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;http://192.168.174.129:2379/dashboard&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;账号密码为tidb账户密码。默认账号root，密码在控制台输出；可依据下一篇文章修改密码。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;grafana&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;http://192.168.174.129:3000/&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;账号密码初始均为admin，登录后更改自己的密码。 监控自动关联Prometheus&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/tidb/" term="TiDB" label="TiDB" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/tidb/" term="TiDB" label="TiDB" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Docker_Desktop学习(三) Kubernetes-Dashboard安装</title>
            <link rel="alternate" type="text/html" href="/blog/posts/docker-desktop-three/" />
            <id>/blog/posts/docker-desktop-three/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2021-12-04T13:35:05&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Docker_Desktop学习(三) Kubernetes-Dashboard安装 创建kubernetes-dashboard服务和对应的pod kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.4.0/aio/deploy/recommended.yaml 如果发现……</summary>
            
                <content type="html">&lt;h2 id=&#34;centerdocker_desktop学习三-kubernetes-dashboard安装center&#34;&gt;&lt;center&gt;Docker_Desktop学习(三) Kubernetes-Dashboard安装&lt;/center&gt;&lt;/h2&gt;
&lt;h3 id=&#34;创建kubernetes-dashboard服务和对应的pod&#34;&gt;创建kubernetes-dashboard服务和对应的pod&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.4.0/aio/deploy/recommended.yaml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果发现链接失效，可以访问&lt;a href=&#34;https://github.com/kubernetes/dashboard&#34;&gt;https://github.com/kubernetes/dashboard&lt;/a&gt;,查找最新的链接。&lt;br&gt;
或者将yaml内容存到本地，使用下面命令：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;kubectl create -f kubernetes-dashboard.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&#34;/blog/blog/images/docker_desktop/dd3_1.png&#34; alt=&#34;dd3-1&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;检查kubernetes-dashboard应用状态&#34;&gt;检查kubernetes-dashboard应用状态&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;kubectl get pod -n kubernetes-dashboard  
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/blog/blog/images/docker_desktop/dd3_3.png&#34; alt=&#34;dd3-3&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;使用代理访问dashboard&#34;&gt;使用代理访问dashboard&lt;/h3&gt;
&lt;p&gt;使用代理命令&lt;code&gt;kubectl proxy&lt;/code&gt;， 默认端口是8001，可以使用 &lt;code&gt;-p xxx&lt;/code&gt;指定端口，比如&lt;code&gt;kubectl proxy -p 8112&lt;/code&gt;,&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/docker_desktop/dd3_2.png&#34; alt=&#34;dd3-2&#34;&gt;&lt;br&gt;
然后在通过&lt;a href=&#34;http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#/login&#34;&gt;http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#/login&lt;/a&gt;访问dashboard&lt;/p&gt;
&lt;h3 id=&#34;token访问&#34;&gt;token访问&lt;/h3&gt;
&lt;p&gt;首次访问时会阻拦，继续访问需要选择验证方式，会有kubeconfig和令牌两种方式，我们选择令牌token。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;kubectl -n kube-system describe secret default | awk &#39;$1==&amp;quot;token:&amp;quot;{print $2}&#39;  
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;执行此命令获取token填入即可正常访问。&lt;/p&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/docker/" term="docker" label="docker" />
                            
                        
                            
                            
                            
                                <category scheme="/blog/categories/docker-desktop/" term="docker-desktop" label="docker-desktop" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/docker-desktop/" term="docker-desktop" label="docker-desktop" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Docker_Desktop学习(二) Kubernetes</title>
            <link rel="alternate" type="text/html" href="/blog/posts/docker-desktop-two/" />
            <id>/blog/posts/docker-desktop-two/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2021-12-03T14:24:09&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Docker_Desktop学习(二) Kubernetes docker_desktop安装Kubernetes 使用docker desktop安装kubernetes，打开sett……</summary>
            
                <content type="html">&lt;h2 id=&#34;centerdocker_desktop学习二-kubernetescenter&#34;&gt;&lt;center&gt;Docker_Desktop学习(二) Kubernetes&lt;/center&gt;&lt;/h2&gt;
&lt;h3 id=&#34;docker_desktop安装kubernetes&#34;&gt;docker_desktop安装Kubernetes&lt;/h3&gt;
&lt;p&gt;使用docker desktop安装kubernetes，打开settings，选择Kubernetes, Enable Kubernetes前打钩，然后点击右下角 Apply &amp;amp; Restart,耐心等待即可。&lt;img src=&#34;/blog/blog/images/docker_desktop/dd2_1.png&#34; alt=&#34;dd2-1&#34;&gt;&lt;br&gt;
等待一段时间后，如果成功即可；未成功则使用下面的方法安装&lt;/p&gt;
&lt;h3 id=&#34;使用k8s-for-docker-desktop方式安装&#34;&gt;使用k8s-for-docker-desktop方式安装&lt;/h3&gt;
&lt;p&gt;1、git下载k8s-for-docker-desktop&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git clone https://github.com/AliyunContainerService/k8s-for-docker-desktop.git
cd k8s-for-docker-desktop
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/blog/blog/images/docker_desktop/dd2_2.png&#34; alt=&#34;dd2-2&#34;&gt;&lt;br&gt;
2、 然后cmd命令窗口，执行命令&lt;code&gt;.\load_images.ps1&lt;/code&gt;， 等待下载镜像&lt;br&gt;
3、 回到docker desktop的settings中kubernetes，点击&amp;quot;Reset Kubernetes Cluster&amp;quot;,清空docker desktop的kubernetes的缓存。  &lt;img src=&#34;/blog/blog/images/docker_desktop/dd2_3.png&#34; alt=&#34;dd2-3&#34;&gt;&lt;br&gt;
4、 重新点击Enable Kubernetes前打钩，然后点击右下角 Apply &amp;amp; Restart。等待重启之后即可安装成功。&lt;/p&gt;
&lt;h3 id=&#34;kubectl基础命令&#34;&gt;kubectl基础命令&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;/blog/blog/images/docker_desktop/dd2_4.png&#34; alt=&#34;dd2-4&#34;&gt;&lt;br&gt;
基础命令包括 create、delete、get、run、expose、set、explain、edit&lt;/p&gt;
&lt;h4 id=&#34;create-命令根据文件或者输入来创建资源&#34;&gt;create 命令：根据文件或者输入来创建资源&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;# 创建Deployment和Service资源
$ kubectl create -f demo-deployment.yaml
$ kubectl create -f demo-service.yaml   
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;delete-命令删除资源&#34;&gt;delete 命令：删除资源&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;# 根据yaml文件删除对应的资源，但是yaml文件并不会被删除，这样更加高效
$ kubectl delete -f demo-deployment.yaml 
$ kubectl delete -f demo-service.yaml

# 也可以通过具体的资源名称来进行删除，使用这个删除资源，同时删除deployment和service资源

$ kubectl delete 具体的资源名称
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;get-命令-获得资源信息&#34;&gt;get 命令 ：获得资源信息&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;# 查看所有的资源信息
$ kubectl get all
$ kubectl get --all-namespaces

# 查看pod列表
$ kubectl get pod

# 显示pod节点的标签信息
$ kubectl get pod --show-labels

# 根据指定标签匹配到具体的pod
$ kubectl get pods -l app=example

# 查看node节点列表
$ kubectl get node 

# 显示node节点的标签信息
$ kubectl get node --show-labels

# 查看pod详细信息，也就是可以查看pod具体运行在哪个节点上（ip地址信息）
$ kubectl get pod -o wide

# 查看服务的详细信息，显示了服务名称，类型，集群ip，端口，时间等信息
$ kubectl get svc
$ kubectl get svc -n kube-system

# 查看命名空间
$ kubectl get ns
$ kubectl get namespaces

# 查看所有pod所属的命名空间
$ kubectl get pod --all-namespaces

# 查看所有pod所属的命名空间并且查看都在哪些节点上运行
$ kubectl get pod --all-namespaces  -o wide

# 查看目前所有的replica set，显示了所有的pod的副本数，以及他们的可用数量以及状态等信息
$ kubectl get rs

# 查看已经部署了的所有应用，可以看到容器，以及容器所用的镜像，标签等信息
$ kubectl get deploy -o wide
$ kubectl get deployments -o wide
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;run-命令在集群中创建并运行一个或多个容器镜像&#34;&gt;run 命令：在集群中创建并运行一个或多个容器镜像。&lt;/h4&gt;
&lt;p&gt;run语法：&lt;code&gt;run NAME --image=image [--env=&amp;quot;key=value&amp;quot;] [--port=port] [--replicas=replicas] [--dry-run=bool] [--overrides=inline-json] [--command] -- [COMMAND] [args...]&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 示例，运行一个名称为nginx，副本数为3，标签为app=example，镜像为nginx:1.10，端口为80的容器实例

$ kubectl run nginx --replicas=3 --labels=&amp;quot;app=example&amp;quot; --image=nginx:1.10 --port=80

# 示例，运行一个名称为nginx，副本数为3，标签为app=example，镜像为nginx:1.10，端口为80的容器实例，并绑定到k8s-node1上
$ kubectl run nginx --image=nginx:1.10 --replicas=3 --labels=&amp;quot;app=example&amp;quot; --port=80 --overrides=&#39;{&amp;quot;apiVersion&amp;quot;:&amp;quot;apps/v1&amp;quot;,&amp;quot;spec&amp;quot;:{&amp;quot;template&amp;quot;:{&amp;quot;spec&amp;quot;:{&amp;quot;nodeSelector&amp;quot;:{&amp;quot;kubernetes.io/hostname&amp;quot;:&amp;quot;k8s-node1&amp;quot;}}}}}&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;expose-命令创建一个service服务并且暴露端口让外部可以访问&#34;&gt;expose 命令：创建一个service服务，并且暴露端口让外部可以访问&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;# 创建一个nginx服务并且暴露端口让外界可以访问

$ kubectl expose deployment nginx --port=88 --type=NodePort --target-port=80 --name=nginx-service
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;set-命令配置应用的一些特定资源也可以修改应用已有的资源&#34;&gt;set 命令：配置应用的一些特定资源，也可以修改应用已有的资源&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;使用 kubectl set --help查看，它的子命令，env，image，resources，selector，serviceaccount，subject。

语法: resources (-f FILENAME | TYPE NAME) ([--limits=LIMITS &amp;amp; --requests=REQUESTS]
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&#34;kubectl-set-resources-命令&#34;&gt;kubectl set resources 命令&lt;/h5&gt;
&lt;p&gt;这个命令用于设置资源的一些范围限制。&lt;br&gt;
资源对象中的Pod可以指定计算资源需求（CPU-单位m、内存-单位Mi），即使用的最小资源请求（Requests），限制（Limits）的最大资源需求，Pod将保证使用在设置的资源数量范围。&lt;br&gt;
对于每个Pod资源，如果指定了Limits（限制）值，并省略了Requests（请求），则Requests默认为Limits的值。&lt;br&gt;
# 将deployment的nginx容器cpu限制为“200m”，将内存设置为“512Mi”
$ kubectl set resources deployment nginx -c=nginx --limits=cpu=200m,memory=512Mi&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 设置所有nginx容器中 Requests和Limits
$ kubectl set resources deployment nginx --limits=cpu=200m,memory=512Mi --requests=cpu=100m,memory=256Mi

# 删除nginx中容器的计算资源值
$ kubectl set resources deployment nginx --limits=cpu=0,memory=0 --requests=cpu=0,memory=0
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;kubectl-set-selector-命令&#34;&gt;kubectl set selector 命令&lt;/h4&gt;
&lt;p&gt;设置资源的 selector（选择器）。如果在调用&amp;quot;set selector&amp;quot;命令之前已经存在选择器，则新创建的选择器将覆盖原来的选择器。&lt;br&gt;
selector必须以字母或数字开头，最多包含63个字符，可使用：字母、数字、连字符&amp;quot; - &amp;quot; 、点&amp;quot;.&amp;quot;和下划线&amp;quot; _ &amp;quot;。如果指定了--resource-version，则更新将使用此资源版本，否则将使用现有的资源版本。&lt;br&gt;
注意：目前selector命令只能用于Service对象。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;语法：selector (-f FILENAME | TYPE NAME) EXPRESSIONS [--resource-version=version]
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;kubectl-set-image-命令&#34;&gt;kubectl set image 命令&lt;/h4&gt;
&lt;p&gt;​用于更新现有资源的容器镜像。&lt;br&gt;
可用资源对象包括：pod (po)、replicationcontroller (rc)、deployment (deploy)、daemonset (ds)、job、replicaset (rs)。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;语法：image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N 

# 将deployment中的nginx容器镜像设置为“nginx：1.9.1”
$ kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.1

# 所有deployment和rc的nginx容器镜像更新为“nginx：1.9.1”
$ kubectl set image deployments,rc nginx=nginx:1.9.1 --all

# 将daemonset abc的所有容器镜像更新为“nginx：1.9.1”
$ kubectl set image daemonset abc *=nginx:1.9.1

# 从本地文件中更新nginx容器镜像
$ kubectl set image -f path/to/file.yaml nginx=nginx:1.9.1 --local -o yaml
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;explain-命令用于显示资源文档信息&#34;&gt;explain 命令：用于显示资源文档信息&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;kubectl explain rs
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;edit-命令-用于编辑资源信息&#34;&gt;edit 命令: 用于编辑资源信息&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;# 编辑Deployment nginx的一些信息
$ kubectl edit deployment nginx

# 编辑service类型的nginx的一些信息
$ kubectl edit service/nginx
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;logs-命令输出pod中一个容器的日志&#34;&gt;logs 命令：输出pod中一个容器的日志&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;#查看指定pod日志
kubectl logs &amp;lt;pod_name&amp;gt;

#类似tail -f的方式查看
kubectl logs -f &amp;lt;pod_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;describe-命令输出指定资源的详细信息&#34;&gt;describe 命令：输出指定资源的详细信息&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;# 显示node的详细信息
kubectl describe nodes
kubectl describe node &amp;lt;node-name&amp;gt;

# 显示pod的详细信息
kubectl describe pods
kubectl describe pod &amp;lt;pod-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;进入容器内部&#34;&gt;进入容器内部&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;kubectl -n &amp;lt;命名空间&amp;gt; exec -it &amp;lt;pod-name&amp;gt; sh
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;创建删除的命名空间&#34;&gt;创建/删除的命名空间&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;# 创建
kubectl create namespace &amp;lt;namespace&amp;gt;
# 删除
kubectl delete namespace &amp;lt;namespace&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;deployment重启&#34;&gt;deployment重启&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;# 方式1
kubectl scale deployment {your_deployment_name} --replicas=0 -n {namespace}
kubectl scale deployment {your_deployment_name} --replicas=1 -n {namespace}

# 方式2
kubectl rollout restart {your_deployment_name}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;pod重启&#34;&gt;pod重启&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;kubectl get pod &amp;lt;pod_name&amp;gt; -n &amp;lt;命名空间&amp;gt; -o yaml | kubectl replace --force -f -
&lt;/code&gt;&lt;/pre&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/docker/" term="docker" label="docker" />
                            
                        
                            
                            
                            
                                <category scheme="/blog/categories/docker-desktop/" term="docker-desktop" label="docker-desktop" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/docker-desktop/" term="docker-desktop" label="docker-desktop" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Docker_Desktop学习(一) 环境安装</title>
            <link rel="alternate" type="text/html" href="/blog/posts/docker-desktop-one/" />
            <id>/blog/posts/docker-desktop-one/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2021-12-03T10:11:26&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Docker_Desktop学习(一) 环境安装 windows安装docker_desktop 1、我们先去官网下载安装包2、打开安装包加载一会后一般会弹出两个选项……</summary>
            
                <content type="html">&lt;h2 id=&#34;centerdocker_desktop学习一-环境安装center&#34;&gt;&lt;center&gt;Docker_Desktop学习(一) 环境安装&lt;/center&gt;&lt;/h2&gt;
&lt;h3 id=&#34;windows安装docker_desktop&#34;&gt;windows安装docker_desktop&lt;/h3&gt;
&lt;p&gt;1、我们先去&lt;a href=&#34;https://www.docker.com/products/docker-desktop&#34;&gt;官网下载安装包&lt;/a&gt;&lt;img src=&#34;/blog/blog/images/docker_desktop/dd1_1.png&#34; alt=&#34;dd1&#34;&gt;&lt;br&gt;
2、打开安装包加载一会后一般会弹出两个选项,在较旧的Windows10或之前的系统会出现如下所示的相关提示。我们把第一个选上,第二个根据需求选择即可。&lt;img src=&#34;/blog/blog/images/docker_desktop/dd1_2.png&#34; alt=&#34;dd2&#34;&gt;&lt;br&gt;
3、如下图,这里推荐使用WSL2。使用WSL2(基于Windows的Linux子系统),如果我们不适用,就会使用Hyper-v虚拟机运行,不过相比于虚拟机,子系统在性能方面更加出色。&lt;img src=&#34;/blog/blog/images/docker_desktop/dd1_3.png&#34; alt=&#34;dd3&#34;&gt;在我们选择使用WSL2之后,并且我们也确定打开了如下图所示的Windows功能(如果没有打开,请先百度如何打开wsl。)&lt;img src=&#34;/blog/blog/images/docker_desktop/dd1_5.png&#34; alt=&#34;dd5&#34;&gt;&lt;br&gt;
3.1、如果之后安装完成后发生报错可能是WSL2版本比较老,需要更新导致的。&lt;img src=&#34;/blog/blog/images/docker_desktop/dd1_4.png&#34; alt=&#34;dd4&#34;&gt;  需要我们自己手动更新一下,我们根据提示去微软官网下载最新版的wsl2安装后即可正常打开。&lt;a href=&#34;https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi&#34;&gt;更新包下载链接&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;docekr_desktop换源&#34;&gt;docekr_desktop换源&lt;/h3&gt;
&lt;p&gt;在docker_desktop中选择setting,然后选择Docker Engine在其中输入以下源&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;{
  &amp;quot;registry-mirrors&amp;quot;: [
    &amp;quot;https://registry.docker-cn.com&amp;quot;,
    &amp;quot;https://docker.mirrors.ustc.edu.cn&amp;quot;,
    &amp;quot;http://hub-mirror.c.163.com&amp;quot;,
    &amp;quot;https://cr.console.aliyun.com/&amp;quot;
  ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;docker_desktop使用&#34;&gt;docker_desktop使用&lt;/h3&gt;
&lt;p&gt;docker_desktop安装好之后，就可以使用命令窗口操作docker&lt;/p&gt;
&lt;h4 id=&#34;镜像操作&#34;&gt;镜像操作&lt;/h4&gt;
&lt;h5 id=&#34;镜像列表&#34;&gt;镜像列表&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#所有镜像
docker images
&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;标签&lt;/th&gt;
&lt;th&gt;含义&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;REPOSITORY&lt;/td&gt;
&lt;td&gt;镜像所在的仓库名称&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TAG&lt;/td&gt;
&lt;td&gt;镜像标签&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IMAGEID&lt;/td&gt;
&lt;td&gt;镜像ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CREATED&lt;/td&gt;
&lt;td&gt;镜像创建日期(不是获取该镜像的日期)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SIZE&lt;/td&gt;
&lt;td&gt;镜像大小&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src=&#34;/blog/blog/images/docker_desktop/dd1_6.png&#34; alt=&#34;dd6&#34;&gt;&lt;/p&gt;
&lt;h5 id=&#34;镜像拉取&#34;&gt;镜像拉取&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#镜像拉取
docker pull 镜像名称
比如
docker pull ubuntu
docker pull ubuntu:16.04
#个人镜像
docker pull 仓库名称/镜像名称
docker pull xuanxiang/mysql
#第三方私库
docker pull 第三方仓库地址/仓库名称/镜像名称
docker pull registry.cn-hangzhou.aliyuncs.com/fhzh/system:1.0.0

&lt;/code&gt;&lt;/pre&gt;&lt;h5 id=&#34;镜像删除&#34;&gt;镜像删除&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;docker image rm 镜像名或者镜像id
docker rmi 镜像名或者镜像id
比如
docker image rm mysql
docker rmi e34a19f7b66d
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id=&#34;加载镜像&#34;&gt;加载镜像&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;docker run [可选参数] 镜像名 [向启动容器中传入的命令]
&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;常用可选参数&lt;/th&gt;
&lt;th&gt;作用&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;-i&lt;/td&gt;
&lt;td&gt;表示以《交互模式》运行容器&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-d&lt;/td&gt;
&lt;td&gt;会创建一个守护式容器在后台运行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-t&lt;/td&gt;
&lt;td&gt;表示容器启动后会进入其命令行。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--name&lt;/td&gt;
&lt;td&gt;为创建的容器命名。(默认会随机给名称，不支持中文字符)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-v&lt;/td&gt;
&lt;td&gt;表示目录映射关系，即宿主机目录:容器中目录&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-p&lt;/td&gt;
&lt;td&gt;表示端口映射，即宿主机端口:容器端口&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--network=host&lt;/td&gt;
&lt;td&gt;表示将主机的网络环境映射到容器中，使容器的网络与主机相同。(windows和mac不生效)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&#34;容器操作&#34;&gt;容器操作&lt;/h4&gt;
&lt;h5 id=&#34;查看容器&#34;&gt;查看容器&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 查看当前所有正在运行的容器
docker ps
# 查看当前所有容器
docker ps -a
# 使用过滤器
docker ps -f name=指定的名称
# 显示2个上次创建的容器(2可以改变)
docker ps -n 2
# 显示最新创建的容器(包括所有容器)
docker ps -l
# 仅显示ip
docker ps -q
# 显示容器大小
docker ps -s
&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;标签&lt;/th&gt;
&lt;th&gt;含义&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CONTAINER ID&lt;/td&gt;
&lt;td&gt;容器id&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IMAGE&lt;/td&gt;
&lt;td&gt;镜像ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;COMMAND&lt;/td&gt;
&lt;td&gt;默认启动命令(启动时会自动执行)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CREATED&lt;/td&gt;
&lt;td&gt;创建容器的日期&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;STATUS&lt;/td&gt;
&lt;td&gt;当前的状态(启动了多久,多久之前退出等)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PORTS&lt;/td&gt;
&lt;td&gt;映射的端口&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NAMES&lt;/td&gt;
&lt;td&gt;容器的名称&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src=&#34;/blog/blog/images/docker_desktop/dd1_7.png&#34; alt=&#34;dd7&#34;&gt;&lt;/p&gt;
&lt;h5 id=&#34;启动和关闭容器&#34;&gt;启动和关闭容器&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 停止容器
docker container stop 容器名或者容器id
# 或可简写成
docker stop 容器名或容器id

# 强制关闭容器
docker container kill 容器名或容器id
# 或可简写成
docker kill 容器名或容器id

# 启动容器
docker container start 容器名或容器id
# 或可简写成
docker start 容器名或容器id

# 重启容器
docker restart 容器名或容器id
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id=&#34;操作后台容器&#34;&gt;操作后台容器&lt;/h5&gt;
&lt;p&gt;我们开启容器后,如果需要在容器内执行命令,可以将后台切换到前台,也可能使用docker命令将我们需要执行的命令传入。&lt;br&gt;
操作方法有很多种,这里我们介绍一些比较常用的方法&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 执行单条命令
docker exec -it 容器名或容器id 执行的命令
#比如
docker exec -it mysql whoami
# 进入容器内部
docker exec -it 容器名或容器id /bin/bash
# 比如
docker exec -it mysql /bin/bash
# 除了exec外还有attach可以使用，attach有弊端，多终端启动attach后，都会同步显示。但如果一个窗口阻塞，其他窗口也无法再进行操作。
docker attach 容器名或容器id
docker attach mysql
&lt;/code&gt;&lt;/pre&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;exec可选参数&lt;/th&gt;
&lt;th&gt;作用&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;-d&lt;/td&gt;
&lt;td&gt;会创建一个守护式容器在后台运行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-e&lt;/td&gt;
&lt;td&gt;设置环境变量&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-i&lt;/td&gt;
&lt;td&gt;表示以《交互模式》运行容器&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-t&lt;/td&gt;
&lt;td&gt;表示容器启动后会进入其命令行。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-u&lt;/td&gt;
&lt;td&gt;设置用户名和UID。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-w&lt;/td&gt;
&lt;td&gt;设置容器内的工作目录。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h5 id=&#34;删除容器&#34;&gt;删除容器&lt;/h5&gt;
&lt;p&gt;需要删除一个容器,首先需要确保这个容器已经停止了,因为正在运行的容器是无法直接删除。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;docker rm 容器名或者容器id
docker rm mysql
&lt;/code&gt;&lt;/pre&gt;</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/docker/" term="docker" label="docker" />
                            
                        
                            
                            
                            
                                <category scheme="/blog/categories/docker-desktop/" term="docker-desktop" label="docker-desktop" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/docker-desktop/" term="docker-desktop" label="docker-desktop" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">elasticsearch 安装教程</title>
            <link rel="alternate" type="text/html" href="/blog/posts/elasticsearch-setup/" />
            <id>/blog/posts/elasticsearch-setup/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2021-01-21T10:56:59&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">elasticsearch 安装教程 elasticsearch安装使用版本是7.8.1, 鉴于封装rest_client的版本最高支持8，向下兼容的； 8之后api接口路径调整,可以选择6,……</summary>
            
                <content type="html">&lt;h3 id=&#34;elasticsearch-安装教程&#34;&gt;elasticsearch 安装教程&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;elasticsearch安装使用版本是7.8.1, 鉴于封装rest_client的版本最高支持8，向下兼容的； 8之后api接口路径调整,可以选择6,7，考虑到项目稳定和技术支持这里选择版本7.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;为了方便下载，可以点击&lt;a href=&#34;https://pan.baidu.com/s/1auq9JPJmT3x_yQD0TANgsw&#34;&gt;这里&lt;/a&gt;进行下载； 提取码：c5gy&lt;br&gt;
废话不多说开始进入安装步骤：&lt;/p&gt;
&lt;p&gt;前言：&lt;br&gt;
elasticsearch安装需要配置java环境，篇幅有限，就不介绍怎么安装java了，只需要配置JAVA_HOME环境变量即可。&lt;font color=&#34;#dd0000&#34;&gt;注意必须是java8以上的版本&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;1、将下载的文件解压，将里面的elasticsearch-7.8.1文件夹放到相应目录， 注意目录不能有空格例如&lt;font color=&#34;#dd0000&#34;&gt;d:/Program Files/&lt;/font&gt;  &lt;img src=&#34;/blog/blog/images/elasticsearch/esset-1.png&#34; alt=&#34;文件&#34;&gt;&lt;/p&gt;
&lt;p&gt;2、进入elasticsearch/bin目录，双击执行elasticsearch.bat&lt;img src=&#34;/blog/blog/images/elasticsearch/esset-2.png&#34; alt=&#34;命令&#34;&gt;
执行完毕之后，打开浏览器，输入 http://localhost:9200 ，显式以下画面，说明ES安装成功。
&lt;img src=&#34;/blog/blog/images/elasticsearch/esset-3.png&#34; alt=&#34;命令&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;安装elasticsearch服务&#34;&gt;安装elasticsearch服务&lt;/h3&gt;
&lt;p&gt;因为上述方法在关闭命令窗口后，elasticsearch会退出关闭，所以安装服务进行启动更合理&lt;br&gt;
1、修改elasticsearch-env.bat文件，将内容&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;if &amp;quot;%JAVA_HOME%&amp;quot; == &amp;quot;&amp;quot; (
  set JAVA=&amp;quot;%ES_HOME%\jdk\bin\java.exe&amp;quot;
  set JAVA_HOME=&amp;quot;%ES_HOME%\jdk&amp;quot;
  set JAVA_TYPE=bundled jdk
) else (
  set JAVA=&amp;quot;%JAVA_HOME%\bin\java.exe&amp;quot;
  set JAVA_TYPE=JAVA_HOME
)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;替换成&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;set JAVA=&amp;quot;%ES_HOME%\jdk\bin\java.exe&amp;quot;
set JAVA_HOME=&amp;quot;%ES_HOME%\jdk&amp;quot;
set JAVA_TYPE=bundled jdk
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;1、打开DOS命令行界面，切换到elasticSearch的bin目录，执行以下命令：&lt;br&gt;
&lt;code&gt;.\elasticsearch-service.bat install &lt;/code&gt;  &lt;img src=&#34;/blog/blog/images/elasticsearch/esset-4.png&#34; alt=&#34;命令&#34;&gt;&lt;/p&gt;
&lt;p&gt;2、打开任务管理器，选择服务,输入e筛选elasticsearch服务&lt;img src=&#34;/blog/blog/images/elasticsearch/esset-5.png&#34; alt=&#34;服务&#34;&gt;, 右键启动即可&lt;/p&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/elasticsearch/" term="elasticsearch" label="elasticsearch" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/elasticsearch/" term="elasticsearch" label="elasticsearch" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Docker学习(六) 自定义tomcat镜像</title>
            <link rel="alternate" type="text/html" href="/blog/posts/docker-six-custom-image/" />
            <id>/blog/posts/docker-six-custom-image/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2020-12-10T14:09:32&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Docker学习(六) 自定义tomcat镜像 前期准备 1、tomcat: tomcat版本选择的是apache-tomcat-8.5.61， 文件名：apache-t……</summary>
            
                <content type="html">&lt;h2 id=&#34;centerdocker学习六-自定义tomcat镜像center&#34;&gt;&lt;center&gt;Docker学习(六) 自定义tomcat镜像&lt;/center&gt;&lt;/h2&gt;
&lt;h3 id=&#34;前期准备&#34;&gt;前期准备&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;1、tomcat: tomcat版本选择的是apache-tomcat-8.5.61，
    文件名：apache-tomcat-8.5.61.tar.gz
2、java: java版本选择的是JDK1.8.0_211，
    文件名：jdk-8u211-linux-x64.tar.gz
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以上文件均可在&lt;a href=&#34;https://pan.baidu.com/s/14-8cf3OLXi841bc_OkpoGA&#34;&gt;这里&lt;/a&gt;下载， 提取码：【tf2u】&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/docker/docker6-1.png&#34; alt=&#34;文件&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;dockerfile文件&#34;&gt;Dockerfile文件&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# centos在这里作为tomcat的基础镜像
FROM centos     
MAINTAINER wmm
#（这个环境变量用来表示该镜像模板的最后更新时间）
ENV REFRESHED_AT 2020-12-10  

# 切换镜像目录，进入/usr目录
WORKDIR /usr
# 在/usr/下创建jdk目录,用来存放jdk文件
RUN mkdir jdk
# 在/usr/下创建tomcat目录，用来存放tomcat
RUN mkdir tomcat

# 将宿主机的jdk目录下的文件拷至镜像的/usr/jdk目录下
ADD jdk-8u211-linux-x64.tar.gz /usr/jdk/
# 将宿主机的tomcat目录下的文件拷至镜像的/usr/tomcat目录下
ADD apache-tomcat-8.5.61.tar.gz /usr/tomcat/

# 给权限
RUN chmod -R 777 /usr/tomcat/
RUN chmod -R 777 /usr/jdk/

# 设置环境变量
ENV JAVA_HOME=/usr/jdk/jdk1.8.0_211
ENV JRE_HOME=$JAVA_HOME/jre
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH=/sbin:$JAVA_HOME/bin:$PATH

# 设置时间区域
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &amp;amp;&amp;amp; echo &#39;Asia/Shanghai&#39; &amp;gt;/etc/timezone

# 公开端口
EXPOSE 8080
# 设置启动命令
ENTRYPOINT [&amp;quot;/usr/tomcat/apache-tomcat-8.5.61/bin/catalina.sh&amp;quot;,&amp;quot;run&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;打包&#34;&gt;打包&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;1、将apache-tomcat-8.5.61.tar.gz、jdk-8u211-linux-x64.tar.gz、Dockerfile放在同一级目录
2、命令进入该目录，执行 docker build -t yuzhi/tomcat .
3、执行完后，使用命令docker images 查看镜像列表。
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;运行&#34;&gt;运行&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;docker run -d -p 8080:8080 --name wmm_tomcat yuzhi/tomcat:latest
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;具体执行步骤&#34;&gt;具体执行步骤&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;1、进入需要组装镜像的路径
2、执行命令  docker build -t 镜像名:版本号  .	        # 也可以直接是镜像名  这样版本默认是latest
3、docker images   							            # 查看镜像   即可以看到创建的镜像
4、docker run -d -p 映射端口:容器的端口 --name 自定义容器名称 镜像名:版本号   
例如： docker run -d -p 8080:8080 --name wmm_tomcat yuzhi/tomcat:latest
5、docker logs -f --tail=200 容器名称                   # 查看日志
6、docker exec -it 容器名称 /bin/bash			        # 进入容器&lt;/code&gt;&lt;/pre&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/docker/" term="docker" label="docker" />
                            
                        
                            
                            
                            
                                <category scheme="/blog/categories/learn/" term="learn" label="learn" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/docker/" term="docker" label="docker" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Docker学习(五) 安装Jenkins实现自动化部署</title>
            <link rel="alternate" type="text/html" href="/blog/posts/docker-five-jenkins/" />
            <id>/blog/posts/docker-five-jenkins/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2019-12-11T09:41:13&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Docker学习(五) 安装Jenkins实现自动化部署项目 安装Jenkins 玄襄这里为了方便省事，直接使用docker安装Jenkins。 # 下载镜像 docker pull jenkins/jenkins:latest # 准备……</summary>
            
                <content type="html">&lt;h2 id=&#34;centerdocker学习五-安装jenkins实现自动化部署项目center&#34;&gt;&lt;center&gt;Docker学习(五) 安装Jenkins实现自动化部署项目&lt;/center&gt;&lt;/h2&gt;
&lt;h3 id=&#34;安装jenkins&#34;&gt;安装Jenkins&lt;/h3&gt;
&lt;p&gt;玄襄这里为了方便省事，直接使用docker安装Jenkins。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 下载镜像
docker pull jenkins/jenkins:latest
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/blog/blog/images/jenkins/jenkins1-1.png&#34; alt=&#34;下载镜像&#34;&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 准备宿主挂载的文件夹
mkdir /docker
mkdir /docker/jenkins

# 此处注意 容器需要宿主挂载文件夹的权限  不设置的话  挂载启动会失败
chown -R 1000 /docker/jenkins
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/blog/blog/images/jenkins/jenkins1-2.png&#34; alt=&#34;准备&#34;&gt;&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins1-2-1.png&#34; alt=&#34;权限&#34;&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 启动容器
docker run -d --name=jenkins --privileged=true -p 8081:8080 -p 50000:50000 -v /docker/jenkins:/var/jenkins_home jenkins/jenkins

命令解析：
  -p 8081:8080  指定宿主端口8081映射容器8080
  -p 50000:50000 主站进行通信
  -d 后台运行容器
  -v /docker/jenkins:/var/jenkins_home 宿主文件映射容器文件
  --privileged=true  开启特权模式
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/blog/blog/images/jenkins/jenkins1-3.png&#34; alt=&#34;启动&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;初始化jenkins&#34;&gt;初始化Jenkins&lt;/h3&gt;
&lt;p&gt;jenkins容器已经成功启动了，下面就是初始化jenkins。访问地址 是宿主ip + 8081端口即可访问。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;打开网站 需要登录&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins1-4.png&#34; alt=&#34;登录&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;密码可以根据网页提示找到文件夹，要注意这里应该是查看宿主文件夹&lt;br&gt;
输入命令  vi /docker/jenkins/secrets/initialAdminPassword   复制密码即可&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins1-5.png&#34; alt=&#34;密码&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;登录成功之后，选择安装插件，玄襄这个直接选择推荐的。耐心等待安装完成&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins1-6.png&#34; alt=&#34;插件&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;创建第一个admin用户，也可以直接跳过，继续使用admin进行登录，玄襄这里直接跳过了&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins1-7.png&#34; alt=&#34;admin&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;访问地址修改，玄襄这里是直接在后面添加 jenkins  此处强烈建议(未来的我)  不要设置jenkins，最好不改url
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins1-8.png&#34; alt=&#34;url&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;初始化基本完成，登录系统之后修改admin账号&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins1-9.png&#34; alt=&#34;初始化完成&#34;&gt;&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins1-10.png&#34; alt=&#34;修改admin密码&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;添加item项目并运行&#34;&gt;添加item项目并运行&lt;/h3&gt;
&lt;h4 id=&#34;安装插件&#34;&gt;安装插件&lt;/h4&gt;
&lt;p&gt;在运行项目之前，jenkins需要安装相应的插件。在jenkins页面 → 系统管理  →  管理插件 →  可选插件 中搜索&lt;br&gt;
插件如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  Maven Integration       用来支持构建maven项目
  Publish Over SSH        用来把构建好的部署包传送到指定服务器的指定位置
  Git安装
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/blog/blog/images/jenkins/jenkins2-2.png&#34; alt=&#34;插件&#34;&gt;&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins2-3.png&#34; alt=&#34;插件&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;配置jenkins&#34;&gt;配置Jenkins&lt;/h3&gt;
&lt;p&gt;jenkins需要配置jdk环境，根据个人项目需求 还涉及到 maven git等配置。这里需要解释下，因为jenkins是运行
在docker上，所以配置要安装宿主挂碍的文件夹/docker/jenkins下。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;创建全局文件夹  执行命令 mkdir /docker/jenkins/globalEnv&lt;/li&gt;
&lt;li&gt;因为玄襄的centos7没有wget， 所以需要下载   yum y install wget&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;maven安装&#34;&gt;maven安装&lt;/h4&gt;
&lt;p&gt;maven选择安装3.6.3的，下载安装完之后  需要设置settings的镜像为阿里镜像，添加路径。具体请跟着玄襄一步步执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 下载maven
wget  http://mirror.bit.edu.cn/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz

# 解压文件
tar -zvxf apache-maven-3.6.3-bin.tar.gz

# 移动文件夹到全局
mv /apache-maven-3.6.3 /docker/jenkins/globalEnv

# 添加阿里镜像
vi /docker/jenkins/globalEnv/apache-maven-3.6.3/conf/settings.xml
  添加下面命令
...
  &amp;lt;mirror&amp;gt;  
      &amp;lt;id&amp;gt;nexus-aliyun&amp;lt;/id&amp;gt;  
      &amp;lt;mirrorOf&amp;gt;central&amp;lt;/mirrorOf&amp;gt;    
      &amp;lt;name&amp;gt;Nexus aliyun&amp;lt;/name&amp;gt;  
      &amp;lt;url&amp;gt;http://maven.aliyun.com/nexus/content/groups/public&amp;lt;/url&amp;gt;  
  &amp;lt;/mirror&amp;gt;
....

# 添加到路径
vi /etc/profile 
  添加下面命令
  M2_HOME=/docker/jenkins/globalEnv/apache-maven-3.6.0   
  export PATH=$M2_HOME/bin:$PATH

# 更新配置文件 
source /etc/profile
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;jdk安装&#34;&gt;jdk安装&lt;/h4&gt;
&lt;p&gt;jdk安装选择是1.8，因为jdk在官网下载需要登录，所以玄襄直接通过浏览器下载好之后，再上传到虚拟机中的。
&lt;a href=&#34;https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&#34;&gt;jdk下载页面&lt;/a&gt; 选择相应版本下载即可
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins2-4.png&#34; alt=&#34;jdk&#34;&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 解压文件
tar -zvxf jdk-8u231-linux-x64.tar.gz
#移动文件
mv /jdk-1.8.0_231 /docker/jenkins/globalEnv

# 添加到路径
vim /etc/profile 
export JAVA_HOME=/docker/jenkins/globalEnv/jdk1.8.0_231
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$CLASSPATH

# 更新配置文件 
source /etc/profile
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/blog/blog/images/jenkins/jenkins2-5.png&#34; alt=&#34;安装完毕&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;安装git&#34;&gt;安装git&lt;/h4&gt;
&lt;p&gt;git安装比较简单，执行下面的命令即可&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel asciidoc
yum install gcc perl-ExtUtils-MakeMaker
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;jenkins全局环境配置&#34;&gt;jenkins全局环境配置&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;首先进行jenkins的系统配置，系统管理  → 系统配置  → 添加Publish over SSH 可参照下图：
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins2-8.png&#34; alt=&#34;系统配置&#34;&gt;&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins2-9.png&#34; alt=&#34;ssh&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;配置全局工具， 系统管理→ 全局工具配置 → maven配置   → jdk安装  → git配置  → maven安装，具体步骤请看下图：&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins2-6.png&#34; alt=&#34;全局工具配置&#34;&gt;&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins2-7.png&#34; alt=&#34;配置添加&#34;&gt;&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins2-7-1.png&#34; alt=&#34;继续配置添加&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;远程部署项目&#34;&gt;远程部署项目&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;在首页点击“ 新建任务 ” 创建新项目，在弹出框中 输入项目名称，选择构建项目类型，玄襄构建的是maven项目，
然后点击 “ 确定 ”。如下图：&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins3-1.png&#34; alt=&#34;创建任务&#34;&gt; &lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins3-2.png&#34; alt=&#34;项目&#34;&gt;&lt;/li&gt;
&lt;li&gt;进入项目配置页面，添加源码管理git仓库，输入git地址  选择git仓库的账户密码， 没有的话，添加即可。
然后记得选择分支，玄襄这里执行的是&lt;font color=&#34;red&#34;&gt;develop&lt;/font&gt;分支&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins3-3.png&#34; alt=&#34;git&#34;&gt;&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins3-3-1.png&#34; alt=&#34;git1&#34;&gt;&lt;/li&gt;
&lt;li&gt;在Build这里的 Goals and options  添加命令   package compile -U&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins3-4.png&#34; alt=&#34;build&#34;&gt;&lt;/li&gt;
&lt;li&gt;注意这里！！！ 这里是最后一步，也是最重要的一步。在build完成之后，要连接远程服务，将编译好的jar包发送过去，
然后执行远程服务的启动项目命令。&lt;br&gt;
首先选择远程服务 →  设置传输的员文件  →  移除前缀  →  远程服务的文件夹  → 执行命令&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/jenkins/jenkins3-5.png&#34; alt=&#34;远程&#34;&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# 切到目录
cd /home/finance
# 显示工作目录    --- 方便查看
pwd
# 检查该项目是否运行， 是则杀掉
ps -ef | grep yobtc-finance-service| grep -v grep | awk &#39;{print $2}&#39; | xargs --no-run-if-empty kill -9
# 休眠10s
sleep 10
# 使环境变量立即生效
source /etc/profile
# 执行项目setsid  实现后台运行
setsid nohup java -jar  -Xmx512m -Xms512m yobtc-finance-service.jar  &amp;gt; yobtc-finance-service.log &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&#34;5&#34;&gt;
&lt;li&gt;保存配置之后，直接点击构建即可。&lt;/li&gt;
&lt;/ol&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/docker/" term="docker" label="docker" />
                            
                        
                            
                            
                            
                                <category scheme="/blog/categories/learn/" term="learn" label="learn" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/docker/" term="docker" label="docker" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Docker学习(四) 远程部署springboot项目</title>
            <link rel="alternate" type="text/html" href="/blog/posts/docker-four-springboot/" />
            <id>/blog/posts/docker-four-springboot/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2019-12-05T09:10:20&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Docker学习(四) 远程部署springboot项目 远程部署简述 Docker远程部署项目使用的是DockerFile方式，使用IDEA集成Docker进行发布……</summary>
            
                <content type="html">&lt;h2 id=&#34;centerdocker学习四-远程部署springboot项目center&#34;&gt;&lt;center&gt;Docker学习(四) 远程部署springboot项目&lt;/center&gt;&lt;/h2&gt;
&lt;h3 id=&#34;远程部署简述&#34;&gt;远程部署简述&lt;/h3&gt;
&lt;p&gt;Docker远程部署项目使用的是DockerFile方式，使用IDEA集成Docker进行发布，使用起来比较方便。&lt;br&gt;
基本过程是：开放远程docker端口，本地连接docker，项目根目录创建DockerFile文件，项目打包，运行dockerFile文件。&lt;/p&gt;
&lt;h3 id=&#34;docker端口开放&#34;&gt;docker端口开放&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# 修改配置文件
1. cd /usr/lib/systemd/system
2. vi docker.service
3. 在ExecStart=/usr/bin/dockerd-current 后面添加 -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock -H tcp://0.0.0.0:7654 
解析： 2375为主管理端口，unix://var/run/docker.sock用于本地管理，7654是备用端口
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/blog/blog/images/docker/docker4-1.png&#34; alt=&#34;开发端口&#34;&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 将管理地址写入/etc/profile
4. echo &#39;export DOCKER_HOST=tcp://0.0.0.0:2375&#39; &amp;gt;&amp;gt; /etc/profile
5. source /etc/profile

# 重新读取配置文件
6. systemctl daemon-reload

# 重启docker服务
7. systemctl restart docker
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;连接远程docker&#34;&gt;连接远程docker&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;idea安装dokcer插件&lt;br&gt;
打开idea的settings，选择Plugins，搜索插件Docker，安装图片中的插件&lt;img src=&#34;/blog/blog/images/docker/docker4-2.png&#34; alt=&#34;插件&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;连接远程docker地址&lt;br&gt;
安装完插件之后，添加远程docker的远程地址&lt;img src=&#34;/blog/blog/images/docker/docker4-3.png&#34; alt=&#34;远程&#34;&gt;&lt;br&gt;
在idea的services工具进行连接docker&lt;img src=&#34;/blog/blog/images/docker/docker4-4.png&#34; alt=&#34;连接&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;创建DockerFile文件
在项目根目录添加dockerFile文件，内容如下：&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  #指定jdk8，注意，改镜像包比较精简，精简掉了如字体等插件  
  #如果需要操作系统字体库，那么就得使用slim版本或者默认版本。需要操作系统字体库的程序例如：图片验证码、PDF导出。  
  #https://segmentfault.com/a/1190000016449865  
  #不涉及到以上问题的，默认请使用openjdk:8-alpine  
  FROM openjdk:8-alpine

  MAINTAINER wmm  
  #tomcat需要  
  VOLUME /tmp   
  #讲jar包加到根目录  
  ADD /target/*.jar app.jar  
  #设置时区  
  RUN echo &amp;quot;Asia/Shanghai&amp;quot; &amp;gt; /etc/timezone  
  RUN ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime  
  RUN sh -c &#39;touch /app.jar&#39;  
  RUN echo $(date) &amp;gt; /image_built_at  
  #执行命令  
  ENTRYPOINT [&amp;quot;java&amp;quot;, &amp;quot;-Djava.security.egd=file:/dev/./urandom&amp;quot;, &amp;quot;-jar&amp;quot;,&amp;quot;app.jar&amp;quot;]  
&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;镜像启动&lt;br&gt;
使用maven打包项目，然后打开dockerfile文件，点击下面图标&lt;img src=&#34;/blog/blog/images/docker/docker4-5.png&#34; alt=&#34;图标&#34;&gt;&lt;br&gt;
选择编辑运行环境 如下图&lt;img src=&#34;/blog/blog/images/docker/docker4-6.png&#34; alt=&#34;运行环境&#34;&gt;&lt;br&gt;
重新点击上一部的小图标，点击运行即可。&lt;br&gt;
此时远程docker可以通过命令 docker ps -s 看到正在运行的项目
&lt;img src=&#34;/blog/blog/images/docker/docker4-7.png&#34; alt=&#34;启动&#34;&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/docker/" term="docker" label="docker" />
                            
                        
                            
                            
                            
                                <category scheme="/blog/categories/learn/" term="learn" label="learn" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/docker/" term="docker" label="docker" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Docker学习(三) Docker安装mysql</title>
            <link rel="alternate" type="text/html" href="/blog/posts/docker-three-mysql/" />
            <id>/blog/posts/docker-three-mysql/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2019-12-04T11:17:31&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Docker学习(三) Docker安装mysql 安装mysql简述 Docker安装mysql比较方便，主要是以下步骤： 确认安装mysql的版本 访问Mysql的版……</summary>
            
                <content type="html">&lt;h2 id=&#34;centerdocker学习三-docker安装mysqlcenter&#34;&gt;&lt;center&gt;Docker学习(三) Docker安装mysql&lt;/center&gt;&lt;/h2&gt;
&lt;h3 id=&#34;安装mysql简述&#34;&gt;安装mysql简述&lt;/h3&gt;
&lt;p&gt;Docker安装mysql比较方便，主要是以下步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;确认安装mysql的版本 访问Mysql的版本库，点击&lt;a href=&#34;https://hub.docker.com/_/mysql?tab=tags&#34;&gt;这里&lt;/a&gt; 查看版本
&lt;img src=&#34;/blog/blog/images/docker/docker3-1.png&#34; alt=&#34;版本&#34;&gt;&lt;/li&gt;
&lt;li&gt;选择版本后，复制后面的命令  拉取mysql镜像  docker pull mysql:latest
&lt;img src=&#34;/blog/blog/images/docker/docker3-2.png&#34; alt=&#34;mysql&#34;&gt;&lt;/li&gt;
&lt;li&gt;根据mysql镜像启动mysql容器&lt;br&gt;
docker run --name mysql --privileged=true -v /docker/mysql/data:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql&lt;br&gt;
参数说明：&lt;br&gt;
run           运行一个容器&lt;br&gt;
--name        容器的名称&lt;br&gt;
--privileged=true  开启特权模式
-v /docker/mysql/data:/var/lib/mysql    将容器中的/var/lib/mysql文件挂载到宿主/docker/mysql/data上，这样删除容器后，数据也不会丢失
-p 3306:3306  表示这个容器使用3306端口(第二个) 映射到本机的端口号也为3306(第一个)&lt;br&gt;
-d            服务后台运行&lt;/li&gt;
&lt;li&gt;外部客户端链接数据库 使用虚拟机的ip + 3306端口  密码是123456即可访问&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;mysql服务停止和重启&#34;&gt;mysql服务停止和重启&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;docker查看正在运行的容器   $ docker ps -s                &lt;img src=&#34;/blog/blog/images/docker/docker3-3.png&#34; alt=&#34;正在运行的容器&#34;&gt;&lt;/li&gt;
&lt;li&gt;docker停止运行的容器       $ docker stop 5fa83e71137d        5fa83e71137d 是容器id&lt;/li&gt;
&lt;li&gt;docker启动容器            $ docker start 5fa83e71137d&lt;/li&gt;
&lt;/ol&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/docker/" term="docker" label="docker" />
                            
                        
                            
                            
                            
                                <category scheme="/blog/categories/learn/" term="learn" label="learn" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/docker/" term="docker" label="docker" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Docker学习(二) Docker安装</title>
            <link rel="alternate" type="text/html" href="/blog/posts/docker-two-docker/" />
            <id>/blog/posts/docker-two-docker/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2019-12-03T15:31:56&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Docker学习(二) Docker安装 Docker安装前提准备 为了操作方便，玄襄这里直接使用root用户执行。docker支持Centos系统的内核版本要高于3……</summary>
            
                <content type="html">&lt;h2 id=&#34;centerdocker学习二-docker安装center&#34;&gt;&lt;center&gt;Docker学习(二) Docker安装&lt;/center&gt;&lt;/h2&gt;
&lt;h3 id=&#34;docker安装前提准备&#34;&gt;Docker安装前提准备&lt;/h3&gt;
&lt;p&gt;为了操作方便，玄襄这里直接使用root用户执行。docker支持Centos系统的内核版本要高于3.10，首先检查内核，使用uname -r 命令
&lt;img src=&#34;/blog/blog/images/docker/docker2-1.png&#34; alt=&#34;内核版本&#34;&gt;&lt;br&gt;
Centos7满足Docker环境需求，可以继续安装Docker(可能无法正常运行18.06.x及以上版本)。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  # 更新最新yum内核
  yum update -y

  # 卸载旧版的docker(如果安装过的话)
  yum remove docker-*

  # 安装需要的软件包
  yum install -y yum-utils device-mapper-persistent-data lvm2
  
  # 设置yum源  yum-config-manager 是yum-utils下的  一般出现问题可能yum-utils是没有安装好 
  yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;docker安装&#34;&gt;Docker安装&lt;/h3&gt;
&lt;p&gt;安装有问题的情况：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1、 yum install docker-ce     安装完之后，启动不起来  failed to start docker application container engine
    各种搜索 说是版本问题，然后卸载安装的docker
2、 yum install -y docker-ce-18.03.1.ce   依旧启动不起来，同样的错误  
    参照网上的解决方式   使用命令 curl -fsSL https://get.docker.com/ | sh  等待运行完成  问题依旧没有解决
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;成功历程:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1、卸载安装的docker  yum remove docker-*
2、重新更新内核      yum update 
3、然后重启一下系统  reboot
4、安装docker       yum install docker
5、启动docker       systemctl start docker        ---- 很顺利
6、docker版本       docker version
7、docker开启启动   systemctl enable docker
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/blog/blog/images/docker/docker2-2.png&#34; alt=&#34;docker版本&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;删除本地文件&#34;&gt;删除本地文件&lt;/h3&gt;
&lt;p&gt;注意，docker 的本地文件，包括镜像(images), 容器(containers), 存储卷(volumes)等，都需要手工删除。默认目录存储在 &lt;font color=#DC143C&gt;/var/lib/docker。&lt;/font&gt;&lt;/p&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/docker/" term="docker" label="docker" />
                            
                        
                            
                            
                            
                                <category scheme="/blog/categories/learn/" term="learn" label="learn" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/docker/" term="docker" label="docker" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">Docker学习(一) Centos7环境</title>
            <link rel="alternate" type="text/html" href="/blog/posts/docker-one-centos/" />
            <id>/blog/posts/docker-one-centos/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2019-12-03T10:11:50&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">Docker学习(一) Centos7环境 虚拟机VMware安装 玄襄的电脑是windows系统，所以为了模拟线上环境，使用VMware虚拟机创建Centos系统。……</summary>
            
                <content type="html">&lt;h2 id=&#34;centerdocker学习一-centos7环境center&#34;&gt;&lt;center&gt;Docker学习(一) Centos7环境&lt;/center&gt;&lt;/h2&gt;
&lt;h3 id=&#34;虚拟机vmware安装&#34;&gt;虚拟机VMware安装&lt;/h3&gt;
&lt;p&gt;玄襄的电脑是windows系统，所以为了模拟线上环境，使用VMware虚拟机创建Centos系统。 玄襄使用的是VMware15 pro版本&lt;br&gt;
为了方便下载，在&lt;a href=&#34;https://pan.baidu.com/s/1VZ4Vg8b5F3TB8wozQ54j8w&#34;&gt;这里&lt;/a&gt;提供了下载链接，网盘密码是【7k58】，有需要的可以下载。
文件如下：
&lt;img src=&#34;/blog/blog/images/docker/docker1.png&#34; alt=&#34;vmware&#34;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;安装vmware，选择安装位置，中间有可能需要重启，一路下一步直到安装完成。&lt;/li&gt;
&lt;li&gt;安装完之后，打开注册机KeyGen.exe生成key，然后打开vmware应用，把key复制到需要填写的许可证秘钥即可，点击确定破解完成。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;创建centos7虚拟机&#34;&gt;创建Centos7虚拟机&lt;/h3&gt;
&lt;p&gt;玄襄使用的是Centos7，废话不多说，下载地址在&lt;a href=&#34;https://pan.baidu.com/s/1GoyC5kRicueZ2x_7VggvHg&#34;&gt;这里&lt;/a&gt;，密码【ogv0】。
下载完之后，就可以直接创建虚拟机了。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;点击vmware的文件选项，选择【创建虚拟机】&lt;img src=&#34;/blog/blog/images/docker/docker1-1.png&#34; alt=&#34;创建虚拟机&#34;&gt;，弹出如下向导：&lt;img src=&#34;/blog/blog/images/docker/docker1-2.png&#34; alt=&#34;安装向导&#34;&gt;直接选择【典型(推荐)】即可，点击下一步；&lt;/li&gt;
&lt;li&gt;&lt;img src=&#34;/blog/blog/images/docker/docker1-3.png&#34; alt=&#34;稍后安装系统&#34;&gt; 此处现在稍后安装系统，点击下一步；&lt;/li&gt;
&lt;li&gt;选择【Linux】操作系统，版本选择【Centos7 64位】，点击下一步；&lt;/li&gt;
&lt;li&gt;【虚拟机名称】和【位置】  根据自己的情况设置即可，点击下一步；&lt;/li&gt;
&lt;li&gt;&lt;img src=&#34;/blog/blog/images/docker/docker1-4.png&#34; alt=&#34;磁盘大小&#34;&gt; 磁盘大小一般设置20GB, 选择【将虚拟磁盘拆分成多个文件】，点击下一步；&lt;/li&gt;
&lt;li&gt;&lt;img src=&#34;/blog/blog/images/docker/docker1-5.png&#34; alt=&#34;自定义硬盘&#34;&gt; 选择【自定义硬件】，在【硬件】窗口中选择 【新CD/DVD】,修改右侧的【连接】，使用ISO映像文件，选择本地下载好的镜像文件即可。
&lt;img src=&#34;/blog/blog/images/docker/docker1-6.png&#34; alt=&#34;硬件&#34;&gt;点击关闭， 最后点击完成。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;centos7系统安装&#34;&gt;Centos7系统安装&lt;/h3&gt;
&lt;p&gt;在上一步创建完虚拟机之后，vmware左侧【我的计算机】菜单会出现创建好的虚拟机。&lt;img src=&#34;/blog/blog/images/centos/centos1-1.png&#34; alt=&#34;开始&#34;&gt;
点击【开启此虚拟机】进行系统安装初始化。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;开启之后  首先我们选择第二个选项 检查并安装Centos7，一堆命令行之后，会出现初始化界面&lt;img src=&#34;/blog/blog/images/centos/centos1-2.png&#34; alt=&#34;初始化&#34;&gt;，推荐默认english，直接continue即可；&lt;/li&gt;
&lt;li&gt;&lt;img src=&#34;/blog/blog/images/centos/centos1-3.png&#34; alt=&#34;安装信息摘要&#34;&gt; 出现叹号的地方，需要我们点击进行进行确认，然后点击完成即可。&lt;img src=&#34;/blog/blog/images/centos/centos1-4.png&#34; alt=&#34;目标位置&#34;&gt;，点击开始安装；&lt;/li&gt;
&lt;li&gt;配置界面需要设置下root密码（简单的密码，需要点击2次完成才能设置成功），安装进度条安装完毕后，点击重启即可。&lt;img src=&#34;/blog/blog/images/centos/centos1-5.png&#34; alt=&#34;设置密码&#34;&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;centos7网络设置&#34;&gt;Centos7网络设置&lt;/h3&gt;
&lt;p&gt;在新装的Centos系统中，网络基本都是不通的，使用root和密码登录系统之后，使用 ping &lt;a href=&#34;http://www.baidu.com&#34;&gt;www.baidu.com&lt;/a&gt;会出现如图情况 &lt;img src=&#34;/blog/blog/images/centos/centos1-6.png&#34; alt=&#34;ping&#34;&gt;
需要我们重新设置网络&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;使用 ip addr 会发现 eno16777736(文件名可能不一样)，下一步要找到这个文件&lt;img src=&#34;/blog/blog/images/centos/centos1-7.png&#34; alt=&#34;eno&#34;&gt;&lt;/li&gt;
&lt;li&gt;使用 cd /etc/sysconfig/network-scripts/  进入文件中， 使用 dir 命令可以看到 ifcfg-eno16777736 文件&lt;/li&gt;
&lt;li&gt;使用 vi ifcfg-eno16777736  查看内容 按 【i】 进入编辑模式， 将ONBOOT=no改成ONBOOT=yes， 按【esc】退出编辑模式， 使用【:wq】保存并退出vi。 &lt;img src=&#34;/blog/blog/images/centos/centos1-8.png&#34; alt=&#34;内容&#34;&gt;&lt;/li&gt;
&lt;li&gt;使用 service network restart 重启网络服务即可。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;配置阿里源&#34;&gt;配置阿里源&lt;/h3&gt;
&lt;p&gt;阿里源地址：&lt;a href=&#34;http://mirrors.aliyun.com/repo/&#34;&gt;http://mirrors.aliyun.com/repo/&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;下载阿里源配置&lt;br&gt;
yum -y install wget&lt;br&gt;
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak&lt;br&gt;
wget -O /etc/yum.repos.d/CentOS-Base.repo &lt;a href=&#34;http://mirrors.aliyun.com/repo/Centos-7.repo&#34;&gt;http://mirrors.aliyun.com/repo/Centos-7.repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;清除缓存并生成新的缓存&lt;br&gt;
yum clean all&lt;br&gt;
yum makecache&lt;/li&gt;
&lt;li&gt;验证是否成功，安装net-tools&lt;br&gt;
yum -y -install net-tools&lt;br&gt;
ifconfig&lt;br&gt;
成功后会出现以下结果：&lt;img src=&#34;/blog/blog/images/centos/centos1-9.png&#34; alt=&#34;ifconfig&#34;&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/docker/" term="docker" label="docker" />
                            
                        
                            
                            
                            
                                <category scheme="/blog/categories/learn/" term="learn" label="learn" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/docker/" term="docker" label="docker" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">elasticsearh-rest-client</title>
            <link rel="alternate" type="text/html" href="/blog/posts/elasticsearh-rest-client/" />
            <id>/blog/posts/elasticsearh-rest-client/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2019-11-22T10:51:38&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">elasticsearch rest client(一) low level rest client使用和问题 low client使用 low level rest client使用http与elasticsearch进行通信，不会对请求进行编码和响应……</summary>
            
                <content type="html">&lt;h2 id=&#34;centerelasticsearch-rest-client一center&#34;&gt;&lt;center&gt;elasticsearch rest client(一)&lt;/center&gt;&lt;/h2&gt;
&lt;h3 id=&#34;low-level-rest-client使用和问题&#34;&gt;low level rest client使用和问题&lt;/h3&gt;
&lt;h4 id=&#34;low-client使用&#34;&gt;low client使用&lt;/h4&gt;
&lt;p&gt;low level rest client使用http与elasticsearch进行通信，不会对请求进行编码和响应编码。它与所有elasticsearch版本兼容。&lt;br&gt;
如果在命令或者语法上有问题，建议查看官方的文档，需要查看java doc的同学可以点击&lt;a href=&#34;https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.5/java-rest-low.html&#34; title=&#34;文档&#34;&gt;这里&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;maven配置&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.elasticsearch.client&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;elasticsearch-rest-client&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;7.3.2&amp;lt;/version&amp;gt;
    &amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;elasticsearch配置
restClient可以设置请求头和请求回调。此处不多加叙述，网上介绍有很多，不懂的可以去看看。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;@Component
@Configuration
public class EsConfig {

	private static final String HTTP_SCHEME = &amp;quot;http&amp;quot;;

	@Value(&amp;quot;${elasticsearch.config.address}&amp;quot;)
	private String ip;

	@Value(&amp;quot;${elasticsearch.config.port}&amp;quot;)
	private Integer port;

	@Bean
	public RestClient client() {
		HttpHost[] hosts = new HttpHost[]{new HttpHost(ip, port, HTTP_SCHEME)};
		RestClientBuilder builder = RestClient.builder(hosts);
		// 添加header
		Header[] defaultHeader = new Header[]{
				// 内容格式
				new BasicHeader(&amp;quot;content-type&amp;quot;, &amp;quot;application/json&amp;quot;),
				// 长连接
				new BasicHeader(&amp;quot;Connection&amp;quot;, &amp;quot;keepalive&amp;quot;),
		};
		builder.setDefaultHeaders(defaultHeader);
		// 默认连接池    线程1
		builder.setHttpClientConfigCallback(httpAsyncClientBuilder -&amp;gt;
				httpAsyncClientBuilder.setDefaultIOReactorConfig(IOReactorConfig.custom().setIoThreadCount(1).build())
		);

		builder.setRequestConfigCallback(builder1 -&amp;gt; builder1
				// 连接超时
				.setConnectTimeout(30000)
				// 数据请求超时
				.setSocketTimeout(40000)
				// 连接池超时设置
				.setConnectionRequestTimeout(0)

		);
		builder.setFailureListener(new RestClient.FailureListener(){
			@Override
			public void onFailure(Node node) {
				super.onFailure(node);
			}
		});

		return  builder.build();
	}

}
&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;
&lt;p&gt;封装基层语法
低级客户端的命令都需要进行拼接，所以本人就封装了一下底层，并添加了一个简单的方法封装工具。源代码在&lt;a href=&#34;https://gitee.com/wmmsxm/yuzhi_tools.git&#34; title=&#34;源代码&#34;&gt;gitee&lt;/a&gt;上。
&lt;a href=&#34;/blog/blog/images/elasticsearch/es-2.png&#34;&gt;!工具结构&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;案例
可以参考这个&lt;a href=&#34;https://gitee.com/wmmsxm/btw_learn/tree/master/elasticsearch-seven&#34; title=&#34;案例&#34;&gt;案例&lt;/a&gt;来使用的封装的方法。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;low-client问题&#34;&gt;low client问题&lt;/h4&gt;
&lt;p&gt;封装的low rest client方法中，可能会出现以下问题&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Low-level REST client status error:ava.lang.IllegalStateException: Request cannot be executed; I/O reactor status: STOPPED&lt;/p&gt;
&lt;p&gt;这个异常的原因主要是httpClient中的IOReactor被关闭了，原因有很多。出现异常后，再次访问时，就可以正常访问。&lt;br&gt;
查了百度和谷歌，基本上没有能完全解决这个问题的，有的说是内存原因，有的则是减少client链接，或者使用新线程创建client。&lt;br&gt;
本人的解决方式  在restClient.performRequest(request)处捕捉IO异常，再次请求；超过2次(可配)，返回null，异常打印。方式如下图：&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/elasticsearch/es-1.png&#34; alt=&#34;异常处理&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/elasticsearch/" term="elasticsearch" label="elasticsearch" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/elasticsearch/" term="elasticsearch" label="elasticsearch" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">zookeeper知识点(三)</title>
            <link rel="alternate" type="text/html" href="/blog/posts/zookeeper-three/" />
            <id>/blog/posts/zookeeper-three/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2019-11-20T09:25:10&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">zookeeper做一级缓存测试 因公司项目需求，准备做一级缓存，然后就想到了zookeeper，都说它性能不错，特地做个测试看下是否可以用于生产。 封装完成使用g……</summary>
            
                <content type="html">&lt;h3 id=&#34;zookeeper做一级缓存测试&#34;&gt;zookeeper做一级缓存测试&lt;/h3&gt;
&lt;p&gt;因公司项目需求，准备做一级缓存，然后就想到了zookeeper，都说它性能不错，特地做个测试看下是否可以用于生产。
封装完成使用gitee上的sync_cache项目进行测试。&lt;/p&gt;
&lt;h4 id=&#34;测试前提&#34;&gt;测试前提&lt;/h4&gt;
&lt;p&gt;在服务器上搭建zookeeper集群，最少三个节点。使用sync-cache打包4个项目  分别对应全部节点、每个对应一个不同节点。每个项目都有节点监听和
api入口。&lt;/p&gt;
&lt;h4 id=&#34;测试场景&#34;&gt;测试场景&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;使用主项目存储比较小的节点数据，测试其他项目的同步时间
测试结果： 主节点 使用1ms ;其他两个节点使用2ms&lt;/li&gt;
&lt;li&gt;使用主项目存储不断循环变大的节点数据，测试其他项目的同步时间
测试结果：  15KB的数据  每个节点相差2ms    就是 主节点2ms    follower1 是4ms   follower2 是6ms。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;结论&#34;&gt;结论&lt;/h4&gt;
&lt;p&gt;上述测试不一定完全符合zookeeper的性能，但是也能看出zookeeper不适合做大数据存储。大项目的时候，在消息同步这块就要垮掉，无法做到一致性（因为有半数机制存在，没有同步完，主节点就已经默认结束了）。
如果非要做一级缓存的话，zookeeper比较适合做热门数据的缓存，数量小的情景.&lt;/p&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/zookeeper/" term="Zookeeper" label="Zookeeper" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/zookeeper/" term="Zookeeper" label="Zookeeper" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">zookeeper知识点(二)</title>
            <link rel="alternate" type="text/html" href="/blog/posts/zookeeper-two/" />
            <id>/blog/posts/zookeeper-two/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2019-11-20T09:25:10&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">zookeeper知识点(二) zookeeper集群 zookeeper是由多个server组成的集群，一个leader，一个follower。 leader为客户……</summary>
            
                <content type="html">&lt;h3 id=&#34;zookeeper知识点二&#34;&gt;zookeeper知识点(二)&lt;/h3&gt;
&lt;h4 id=&#34;zookeeper集群&#34;&gt;zookeeper集群&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;zookeeper是由多个server组成的集群，一个leader，一个follower。
leader为客户端服务器提供读写服务，除了leader外其他的机器只能提供读服务。
每个server保存一份数据副本，全数据一致；分布式读follower，写由leader实施更新请求转发。
由leader实施更新请求顺序进行，来自同一个client的更新请求按其发送的顺序依次执行，保持原子性，要么成功，要么失败。
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;zookeeper角色&#34;&gt;zookeeper角色&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;leader&lt;/strong&gt;：是整个zookeeper集群工作机制的核心。负责响应所有对Zookeeper状态变更的请求。主要工作如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;事务请求的唯一调度和处理，保持集群处理事务的顺序性&lt;/li&gt;
&lt;li&gt;集群内各服务器的调度者&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;leader的选举是zookeeper最重要的技术之一，假如有三个服务器server启动，
每个机器都视图找到一个leader，就进入了leader选举流程：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;每个 server 发出一个投票,投票的最基本元素是（SID-服务器id,ZXID-事物id）&lt;/li&gt;
&lt;li&gt;接受来自各个服务器的投票 处理投票&lt;/li&gt;
&lt;li&gt;优先检查 ZXID(数据越新ZXID越大),ZXID比较大的作为leader，ZXID一样的情况下比较SID&lt;/li&gt;
&lt;li&gt;统计投票 这里有个过半的概念，大于集群机器数量的一半，即大于或等于（n/2+1）,我们这里的由三台，大于等于2即为达到“过半”的要求。
这里也有引申到为什么 Zookeeper 集群推荐是单数。&lt;br&gt;
“过半”设计策略也适用在广播通知中，leader在收到过半的follower的ack后，即认为消息抵达了&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Follower&lt;/strong&gt;：是zookeeper集群状态的跟随者，，除了响应服务器上的读请求外，还要处理leader的提议。需要注意的是，
leader和follower是构造zookeeper集群的法定人数，只有他们能参与新的leader的选举和响应leader的提议。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Observer&lt;/strong&gt;：服务器的观察者。如果 ZooKeeper 集群的读取负载很高，或者客户端多到跨机房，可以设置一些 observer 服务器，以提高读取的吞吐量。
Observer 和 Follower 比较相似，只有一些小区别：首先 observer 不属于法定人数，即不参加选举也不响应提议，也不参与写操作的“过半写成功”策略；
其次是 observer 不需要将事务持久化到磁盘，一旦 observer 被重启，需要从 leader 重新同步整个名字空间。&lt;/p&gt;
&lt;h4 id=&#34;会话session&#34;&gt;会话(Session)&lt;/h4&gt;
&lt;p&gt;Session指的是zookeeper服务器与客户端的会话。在zookeeper中，一个客户端链接是只客户端和服务器之间的一个TCP长连接。
客户端启动的时候，首先会与服务器建立一个 TCP 连接，从第一次连接建立开始，客户端会话的生命周期也开始了。
通过这个连接，客户端能够通过心跳检测与服务器保持有效的会话，也能够向Zookeeper 服务器发送请求并接受响应，同时还能够通过该连接接收来自服务器的Watch事件通知。
Session 的 sessionTimeout 值用来设置一个客户端会话的超时时间。当由于服务器压力太大、网络故障或是客户端主动断开连接等各种原因导致客户端连接断开时，
只要在sessionTimeout规定的时间内能够重新连接上集群中任意一台服务器，那么之前创建的会话仍然有效。在为客户端创建会话之前，服务端首先会为每个客户端都分配一个sessionID。
由于 sessionID 是 Zookeeper 会话的一个重要标识，许多与会话相关的运行机制都是基于这个 sessionID 的，因此，无论是哪台服务器为客户端分配的 sessionID，都务必保证全局唯一。&lt;/p&gt;
&lt;h4 id=&#34;会话创建&#34;&gt;会话创建&lt;/h4&gt;
&lt;p&gt;session是zookeeper的会话实体，代表了一个客户端会话，其包含了如下四个属性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;sessionID  会话ID，唯一标识的一个会话，每个客户端创建新的会话时，zookeeper都会为其分配一个全局唯一的sessionID&lt;/li&gt;
&lt;li&gt;TimeOut 会话超时时间，客户端构造zookeeper实例时，会配置sessionTimeout参数用于指定会话的超时时间，服务器会根据自己的超时时间限制最后确定会话的超时时间。&lt;/li&gt;
&lt;li&gt;TikTime 下次会话超时时间点，为了便于zookeeper对会话实行“分桶策略”管理，同时为了高效低耗地实现会话的超时检查和清理，zookeeper会为每个会话都标记一个下次会话超时时间点，
其值大致等于当前时间 + timeout&lt;/li&gt;
&lt;li&gt;isClosing。标记一个会话是否已经被关闭，当服务器检测会话已经超时失效时，会将该会话的isClosing标记为&amp;quot;已关闭&amp;quot;，这样就能确保不再处理来自该会话的新请求了。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;数据节点-znode&#34;&gt;数据节点 Znode&lt;/h4&gt;
&lt;p&gt;&amp;quot;节点&amp;quot;分两类，第一类指构成集群的机器，称之机器节点；第二类是数据模型中的数据单元，我们称之数据节点--ZNode。
zookeeper将所有数据存储在内存中，树形存储，每个节点会保存自己的数据内容，还会存储一系列属性信息。&lt;/p&gt;
&lt;h5 id=&#34;节点类型&#34;&gt;节点类型&lt;/h5&gt;
&lt;p&gt;node可以分持久节点和临时节点和顺序节点三大类。可通过组合生成如下四种类型节点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;PERSISTENT 持久节点 创建后会一直存在于zookeeper服务器中，直到删除&lt;/li&gt;
&lt;li&gt;PERSISTENT_SEQUENTIAL 持久顺序节点， 相比持久节点，其新增了顺序特性，每个父节点都会为他的第一级子节点维护一份顺序，用于记录每个子节点创建的先后顺序。
在创建节点时，会自动添加一个数字后缀，作为新的节点名，改数字后缀的上限是整形的最大值&lt;/li&gt;
&lt;li&gt;EPEMERAL 临时节点，其生命周期和客户端会话绑定在一起，客户端失效，节点自动删除。&lt;/li&gt;
&lt;li&gt;EPEMERAL_SEQUENTIAL 临时顺序节点  在临时节点上添加了顺序特性。&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;版本--保证分布式数据的原子性操作&#34;&gt;版本--保证分布式数据的原子性操作&lt;/h4&gt;
&lt;p&gt;每个数据节点都具有三种类型的版本信息，对数据节点的任何更新操作都会引起版本号的变化。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;version– 当前数据节点数据内容的版本号&lt;/li&gt;
&lt;li&gt;cversion– 当前数据子节点的版本号&lt;/li&gt;
&lt;li&gt;aversion– 当前数据节点ACL变更版本号&lt;/li&gt;
&lt;/ul&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/zookeeper/" term="Zookeeper" label="Zookeeper" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/zookeeper/" term="Zookeeper" label="Zookeeper" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">elasticsearch-bulk</title>
            <link rel="alternate" type="text/html" href="/blog/posts/elasticsearch-bulk/" />
            <id>/blog/posts/elasticsearch-bulk/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2019-11-18T10:56:59&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">elasticsearch 使用rest-client进行批量操作性能测试 之前做交易所项目， 大量实时数据存储在mongodb中，导致在查询账单、K线会出现查询慢的情况。在优化mongod……</summary>
            
                <content type="html">&lt;h3 id=&#34;elasticsearch-使用rest-client进行批量操作性能测试&#34;&gt;elasticsearch 使用rest-client进行批量操作性能测试&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;之前做交易所项目， 大量实时数据存储在mongodb中，导致在查询账单、K线会出现查询慢的情况。在优化mongodb的同时，寻找其他
nosql数据库做备用，所以才有了本文的性能测试。
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&#34;elasticsearch-rest-client选择&#34;&gt;elasticsearch rest client选择&lt;/h5&gt;
&lt;pre&gt;&lt;code&gt;low level rest client
    1、对elasticsearch版本要求低，封装组件之后，很多项目后续都可以使用；凭借原生json语句。

high level rest client
    1、对elasticsearch版本要求相当高，必须一致，引入的elasticsearch版本也要一致，否则容易报错；
    笔者因为这个吃了不少亏。组件是封装好的，直接拿来使用即可。

在测试环节，elasticsearch使用的版本是7.1.0， 笔者优先使用了low level rest client，对其进行了原生json语句封装。在测试基本创建和其他基本操作时，
效果都不错，但是在批量操作时发现执行比较慢，只能进行优化。
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;elasticsearch批量操作优化&#34;&gt;elasticsearch批量操作优化&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;1. 调整刷新频率 refresh_interval = -1，手动刷新
2. 仅备份数据时，可以把副本先关掉，完成后再打开 &amp;quot;number_of_replicas&amp;quot;:0
3. 每次数据不能超过5-15MB,数量最好不要超过1000条。
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;测试结果&#34;&gt;测试结果&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;1、 low client:   每个文档大约0.016MB
    1. 500个        200ms     
    2. 1000个       500ms
    3. 2000个       1100ms
    4. 4000个       2300ms
可以看出来 随着文档树越多，时间也越长。 如果es要引入交易所，批量必须要达到10000-20000/s,  所以这个不能满足.

2、high client： 每个文档大约0.016MB
同步请求
    1. 500个        250ms
    2. 1000个       480ms
    3. 2000个       970ms
    4. 4000个       1900ms

异步请求  适合做数据备份或者拷贝
    1. 500个        17ms    后台处理回调数据
    2. 1000个       46ms 
    3. 2000个       77ms
    4. 4000ge       180ms
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;结果&#34;&gt;结果&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;笔者最终没有使用elasticsearch，场景所需的条件达不到，只能先放弃，此处仅是记录批量操作性能，方便后期使用。&lt;/code&gt;&lt;/pre&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/elasticsearch/" term="elasticsearch" label="elasticsearch" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/elasticsearch/" term="elasticsearch" label="elasticsearch" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">umi搭建dva</title>
            <link rel="alternate" type="text/html" href="/blog/posts/umi-dva/" />
            <id>/blog/posts/umi-dva/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2019-10-22T18:00:35&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">umi搭建dva 使用umiJs搭建后台管理页面，集成dav、ant，一些react需要的插件不需要手动添加，按需加载即可。 此处记录安装流程和走过的坑！！ 安装步骤……</summary>
            
                <content type="html">&lt;h3 id=&#34;umi搭建dva&#34;&gt;umi搭建dva&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;使用umiJs搭建后台管理页面，集成dav、ant，一些react需要的插件不需要手动添加，按需加载即可。  
此处记录安装流程和走过的坑！！
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;安装步骤&#34;&gt;安装步骤&lt;/h4&gt;
&lt;p&gt;一、yarn安装&lt;br&gt;
国内推荐使用yarn，可以直接在&lt;a href=&#34;https://yarn.bootcss.com/docs/install/#windows-stable&#34; title=&#34;yarn官网&#34;&gt;yarn官网&lt;/a&gt;下载安装。 不过本人没有成功 (&lt;em&gt;^▽^&lt;/em&gt;)
或者使用npm install -g yarn 命令进行安装。&lt;/p&gt;
&lt;p&gt;二、下载create-umi&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;两种方式  
    1、yarn create umi  
    2、yarn global add create-umi --prefix &amp;quot;D:\Program Files\nodejs\node_global_modules&amp;quot;  

    下载完的create-umi执行失败，系统无法识别，如下所示
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/blog/blog/images/react/20191023141701.png&#34; alt=&#34;错误&#34;&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;这是因为create-umi.cmd里面的盘符前有符号转义，内容如下：
@&amp;quot;%~dp0\C:\Users\wmm\AppData\Local\Yarn\Data\global\node_modules\.bin\create-umi.cmd&amp;quot;   %*

修改为：
@&amp;quot;C:\Users\wmm\AppData\Local\Yarn\Data\global\node_modules\.bin\create-umi.cmd&amp;quot;   %*

保存后，重新运行一下 &amp;quot;create-umi&amp;quot;命令，就可以正常运行了。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;三、安装&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1、选择project
	? Select the boilerplate type (Use arrow keys)
	  ant-design-pro  - Create project with an layout-only ant-design-pro boilerplate, use together with umi block.
	&amp;gt; app             - Create project with a simple boilerplate, support typescript.
	  block           - Create a umi block.
	  library         - Create a library with umi.
	  plugin          - Create a umi plugin.
	本人选择了app
	
2、是否使用TypeScript
	? Do you want to use typescript? (y/N)
	y

3、选择需要的插件功能
	? What functionality do you want to enable? (Press &amp;lt;space&amp;gt; to select, &amp;lt;a&amp;gt; to toggle all, &amp;lt;i&amp;gt; to invert selection)
	&amp;gt;◯ antd
	 ◯ dva
	 ◯ code splitting
	 ◯ dll
	此处本人全选

4、最后确定，并使用yarn 安装依赖
	顺利的话  在浏览器打开 [地址](http://localhost:8000 &amp;quot;地址&amp;quot;) 可看到umi界面&lt;/code&gt;&lt;/pre&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/react/" term="react" label="react" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/react/" term="react" label="react" />
                            
                        
                            
                            
                            
                                <category scheme="/blog/tags/umi/" term="umi" label="umi" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">redis集群</title>
            <link rel="alternate" type="text/html" href="/blog/posts/redis%E9%9B%86%E7%BE%A4/" />
            <id>/blog/posts/redis%E9%9B%86%E7%BE%A4/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2019-10-17T09:02:40&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">windows搭建redis集群 操作系统：win10 64位 redis版本：3.2.100 x64 ruby版本：2.5.1 x64 rubygems版本：2.7.6 开场白 昨天同……</summary>
            
                <content type="html">&lt;meta name=&#34;referrer&#34; content=&#34;no-referrer&#34; /&gt;
&lt;h3 id=&#34;windows搭建redis集群&#34;&gt;windows搭建redis集群&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;操作系统：win10 64位  
redis版本：3.2.100 x64  
ruby版本：2.5.1 x64  
rubygems版本：2.7.6  
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;开场白&#34;&gt;开场白&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;昨天同事需要本地的redis集群环境，在网上找了点资料，历经各种坑，终于搭建完成。今天特地整理一下搭建的流程，加深下印象。
安装工具在百度网盘下载：   
链接：https://pan.baidu.com/s/1LxWEfF8bQGIxd2sxN3N3Pw
提取码：sqmw 
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;开始搭建&#34;&gt;开始搭建&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;搭建顺序就是 redis --&amp;gt; 复制多份redis配置 --&amp;gt; 安装ruby --&amp;gt; 安装rubygems --&amp;gt; 进行集群构建脚本
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;redis安装&lt;/p&gt;
&lt;p&gt;下载的redis文件进行解压，最好是放在新的文件夹中，方便集群使用和管理。&lt;br&gt;
&lt;img src=&#34;/blog/blog/images/redis/20191017094637.png&#34; alt=&#34;文件&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;配置三主三从集群&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;因为集群最少是6个节点，所以这里配置三主三从，将上面的redis文件夹复制5份，我这边端口修改是6479,6480,6481,6482,6483,6484。如下所示：
&lt;img src=&#34;/blog/blog/images/redis/20191017095130.png&#34; alt=&#34;三主三从&#34;&gt;
其中每一个文件夹都相当于一个redis。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;配置redis
以6479为例，打开文件夹中的redis.windows.conf文件，分别修改如下数据：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; port 6479     ---&amp;gt; 端口号，与文件夹保持一致  
 cluster-enabled yes  ---&amp;gt; 开始实例的集群模式  
 cluster-config-file nodes-6479.conf  ---&amp;gt; 设定保存节点配置文件的路径，端口与文件保持一致  
 cluster-node-timeout 15000 ---&amp;gt; 创建集群时超时时间 
 appendonly yes ---&amp;gt; 开启后，每次写操作请求都追加到appendonly.aof 文件中  
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;注意，修改时前面不能有空格！！！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在每个文件夹中添加一个bat来启动redis，内容如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; title redis-6479         //和当前端口保持一致
 redis-server.exe redis.windows.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;创建完成之后，分别点击这个bat，启动redis。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;安装ruby&lt;br&gt;
redis的集群需要ruby环境，所以需要使用下载的rebyinstaller，基本上都勾选，然后一路下一步，最后让你选择，没搞懂啥意思，本人选了3。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;安装rubygems&lt;br&gt;
解压完成之后，进入文件夹使用powershell，运行如下命令:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; 1. ruby setup.rb           // 直接安装即可
 2. gem install redis       // 安装redis插件
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;redis-trib.rb
将下载的redis-trib.rb放在redis同级。使用powershell运行如下命令：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; redis-trib.rb create --replicas 1 127.0.0.1:6479 127.0.0.1:6480 127.0.0.1:6481 127.0.0.1:6482 127.0.0.1:6483 127.0.0.1:6484

 其中会出现Can I set the above configuration? (type &#39;yes&#39; to accept)，输入yes
 最后出现两个OK的时候差不多就是构建成功了。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意，如果需要绑定IP地址的话，需要修改redis中的属性 bind 127.0.0.1， 改为bind (你的ip)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/redis/" term="redis" label="redis" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/redis/" term="redis" label="redis" />
                            
                        
                    
                
            
        </entry>
    
        <entry>
            <title type="text">zookeeper知识点(一)</title>
            <link rel="alternate" type="text/html" href="/blog/posts/zookeeper-one/" />
            <id>/blog/posts/zookeeper-one/</id>
            <updated>2022-12-30T06:40:57&#43;00:00</updated>
            <published>2019-08-09T19:43:03&#43;08:00</published>
            <author>
                    <name>wmmsxm</name>
                    <uri>https://io-oi.me/</uri>
                    <email>wmmsxm@163.com</email>
                    </author>
            <rights>Copyright © 2022 WuMengMeng</rights><summary type="html">zookeeper知识点(一) zookeeper简介 zookeeper是一个分布式的，开放源码的分布式应用程序协调服务，它可以在分布式系统中协作多个任务。整个Z……</summary>
            
                <content type="html">&lt;h3 id=&#34;zookeeper知识点一&#34;&gt;zookeeper知识点(一)&lt;/h3&gt;
&lt;h4 id=&#34;zookeeper简介&#34;&gt;zookeeper简介&lt;/h4&gt;
&lt;p&gt;zookeeper是一个分布式的，开放源码的分布式应用程序协调服务，它可以在分布式系统中协作多个任务。整个Zookeeper的服务器集群管理着应用协作的关键数据。&lt;br&gt;
但是zookeeper不是万能的，它不适合用作海量数据存储。&lt;br&gt;
它主要是提供功能:
1. 保障强一致性、有序性和持久性
2. 实现通用的同步原语的能力
3. 在实际开发中，提供一个简单的并发处理机制，处理并发。&lt;/p&gt;
&lt;h4 id=&#34;zookeeper特性&#34;&gt;zookeeper特性&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;顺序一致性，从同一个客户端发起的事务请求，最终会严格的按照其发起的顺序被应用到zookeeper中。&lt;/li&gt;
&lt;li&gt;原子性， 所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致的，即整个集群要么成功应用了，要么都没有应用。&lt;/li&gt;
&lt;li&gt;单一视图， 无聊客户端链接的哪个zookeeper服务器，其看到的服务器数据模型都是一致的。&lt;/li&gt;
&lt;li&gt;可靠性， 一旦服务器成功的应用了一个事务，并完成响应，该事务所引起的服务器状态变更会一直保留，除非有另一个事务对其进行变更。&lt;/li&gt;
&lt;li&gt;实时性， zookeeper保证在一定的时间段内，客户端最终一定能够从服务端读取到最新的数据状态。&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;zookeeper结构&#34;&gt;zookeeper结构&lt;/h4&gt;
&lt;p&gt;zookeeper会维护一个具有层次关系的数据结构，类似于文件系统的层级树状结构。
&lt;img src=&#34;/blog/blog/images/zookeeper/965360-20180418191100883-2107625307.png&#34; alt=&#34;数据模型&#34;&gt;&lt;/p&gt;
</content>
            
            
            
            
            
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/categories/zookeeper/" term="Zookeeper" label="Zookeeper" />
                            
                        
                    
                
                    
                        
                            
                            
                            
                                <category scheme="/blog/tags/zookeeper/" term="Zookeeper" label="Zookeeper" />
                            
                        
                    
                
            
        </entry>
    
</feed>
