<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
>
<channel>
<title><![CDATA[Hello World]]></title> 
<atom:link href="https://blog.zhappy.vip/rss.php" rel="self" type="application/rss+xml" />
<description><![CDATA[]]></description>
<link>https://blog.zhappy.vip/</link>
<language>zh-cn</language>

<item>
    <title>08-kubeadm部署K8s 1.25高可用集群</title>
    <link>https://blog.zhappy.vip/?post=24</link>
    <description><![CDATA[<h2>一、集群整体规划</h2>
<h3>1. 网段规划</h3>
<ul>
<li>
<p>Pod 网段（podSubnet）：<code>10.244.0.0/16</code></p>
</li>
<li>
<p>Service 网段（serviceSubnet）：<code>10.96.0.0/12</code></p>
</li>
<li>
<p>高可用虚拟 VIP：<code>192.168.40.199</code></p>
</li>
</ul>
<h3>2. 节点角色规划</h3>
<table>
<thead>
<tr>
<th>集群角色</th>
<th>IP 地址</th>
<th>主机名</th>
<th>核心组件</th>
</tr>
</thead>
<tbody>
<tr>
<td>控制节点 Master</td>
<td>(192.168.40.180)</td>
<td>zhappymaster1</td>
<td>apiserver、controller-manager、scheduler、kubelet、etcd、kube-proxy、容器运行时、calico、keepalived、nginx</td>
</tr>
<tr>
<td>工作节点 Node1</td>
<td>(192.168.40.181)</td>
<td>zhappynode1</td>
<td>kube-proxy、calico、coredns、容器运行时、kubelet</td>
</tr>
<tr>
<td>工作节点 Node2</td>
<td>(192.168.40.182)</td>
<td>zhappynode2</td>
<td>kube-proxy、calico、coredns、容器运行时、kubelet</td>
</tr>
</tbody>
</table>
<h3>3. 系统环境要求</h3>
<ul>
<li>
<p>操作系统：CentOS 7.9</p>
</li>
<li>
<p>硬件配置：4GiB 内存 / 4vCPU / 60G 硬盘</p>
</li>
<li>
<p>网络：NAT 模式</p>
</li>
</ul>
<hr />
<h2>二、集群环境初始化（所有节点执行）</h2>
<h3>1. 配置静态 IP</h3>
<p>修改网卡配置（网卡名以实际为准，示例为<code>ens33</code>）：</p>
<pre><code class="language-bash">vim /etc/sysconfig/network-scripts/ifcfg-ens33</code></pre>
<p>核心配置项：</p>
<pre><code class="language-ini">BOOTPROTO=static
IPADDR=192.168.40.180   # 替换为对应节点IP
NETMASK=255.255.255.0
GATEWAY=192.168.40.2
DNS1=192.168.40.2
ONBOOT=yes
NAME=ens33
DEVICE=ens33</code></pre>
<p>重启网络生效：</p>
<pre><code class="language-bash">service network restart</code></pre>
<blockquote>
<p>可选操作：执行 <code>yum update -y</code> 升级系统至最新版本。</p>
</blockquote>
<h3>2. 关闭 SELinux</h3>
<pre><code class="language-bash"># 永久关闭，重启后生效
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
# 重启机器
reboot
# 验证状态，输出 Disabled 即为成功
getenforce</code></pre>
<h3>3. 设置主机名</h3>
<p>分别在对应节点执行：</p>
<pre><code class="language-bash"># Master执行
hostnamectl set-hostname zhappymaster1 &amp;&amp; bash

# Node1执行
hostnamectl set-hostname zhappynode1 &amp;&amp; bash

# Node2执行
hostnamectl set-hostname zhappynode2 &amp;&amp; bash</code></pre>
<h3>4. 配置主机名解析</h3>
<p>所有节点的<code>/etc/hosts</code>添加节点映射：</p>
<pre><code class="language-bash">cat &gt;&gt; /etc/hosts &lt;&lt;EOF
192.168.40.180   zhappymaster1
192.168.40.181   zhappynode1
192.168.40.182   zhappynode2
EOF</code></pre>
<h3>5. 配置节点间 SSH 免密登录</h3>
<p>分别在三个节点生成密钥并分发至所有节点：</p>
<pre><code class="language-bash"># 生成密钥，一路回车即可
ssh-keygen

# 分发公钥
ssh-copy-id zhappymaster1
ssh-copy-id zhappynode1
ssh-copy-id zhappynode2</code></pre>
<h3>6. 关闭 Swap 交换分区</h3>
<p>K8s 默认禁用 Swap 以保证性能，未关闭会导致初始化失败。</p>
<pre><code class="language-bash"># 临时关闭
swapoff -a

# 永久关闭：注释fstab中swap挂载行
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab</code></pre>
<blockquote>
<p>说明：若必须保留 Swap，可在 kubeadm 命令后追加<code>--ignore-preflight-errors=Swap</code>跳过检测。</p>
</blockquote>
<h3>7. 配置内核网络参数</h3>
<p>加载桥接模块，开启 IP 转发与网桥 iptables 支持：</p>
<pre><code class="language-bash"># 加载br_netfilter内核模块
modprobe br_netfilter

# 写入内核配置
cat &gt; /etc/sysctl.d/k8s.conf &lt;&lt;EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

# 生效配置
sysctl -p /etc/sysctl.d/k8s.conf</code></pre>
<h3>8. 关闭 firewalld 防火墙</h3>
<pre><code class="language-bash">systemctl stop firewalld
systemctl disable firewalld</code></pre>
<h3>9. 配置 Docker/containerd 阿里云 YUM 源</h3>
<pre><code class="language-bash">yum install yum-utils -y
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo</code></pre>
<h3>10. 配置 K8s 阿里云 YUM 源</h3>
<pre><code class="language-bash">cat &gt; /etc/yum.repos.d/kubernetes.repo &lt;&lt;EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
EOF</code></pre>
<h3>11. 配置时间同步</h3>
<pre><code class="language-bash"># 安装同步工具
yum install ntpdate -y
# 立即同步时间
ntpdate cn.pool.ntp.org

# 添加定时任务，每小时同步一次
crontab -e
* */1 * * * /usr/sbin/ntpdate cn.pool.ntp.org

# 重启定时任务
service crond restart</code></pre>
<h3>12. 安装基础依赖包</h3>
<pre><code class="language-bash">yum install -y device-mapper-persistent-data lvm2 wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo ntp libaio-devel vim ncurses-devel autoconf automake zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack telnet ipvsadm</code></pre>
<hr />
<h2>三、安装容器运行时 containerd（所有节点执行）</h2>
<p>K8s 1.25 版本已移除 dockershim，默认使用 containerd 作为容器运行时。</p>
<h3>1. 安装 containerd</h3>
<pre><code class="language-bash">yum install containerd.io-1.6.6 -y</code></pre>
<h3>2. 生成并修改配置文件</h3>
<pre><code class="language-bash"># 创建配置目录
mkdir -p /etc/containerd
# 生成默认配置
containerd config default &gt; /etc/containerd/config.toml</code></pre>
<p>修改<code>/etc/containerd/config.toml</code>两个核心配置：</p>
<ol>
<li>
<p><strong>开启 SystemdCgroup</strong>：将<code>SystemdCgroup = false</code>改为<code>SystemdCgroup = true</code>，与 kubelet 驱动保持一致</p>
</li>
<li>
<p><strong>替换 pause 镜像源</strong>：将<code>sandbox_image = "k8s.gcr.io/pause:3.6"</code>改为<code>sandbox_image="registry.aliyuncs.com/google_containers/pause:3.7"</code></p>
</li>
</ol>
<p>启动并设置开机自启：</p>
<pre><code class="language-bash">systemctl enable containerd --now</code></pre>
<h3>3. 配置 crictl 客户端</h3>
<p>crictl 是 K8s CRI 接口的客户端工具，用于与容器运行时交互：</p>
<pre><code class="language-bash">cat &gt; /etc/crictl.yaml &lt;&lt;EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

systemctl restart containerd</code></pre>
<h3>4. （可选）安装 Docker 用于镜像构建</h3>
<p>containerd 不支持直接通过 Dockerfile 构建镜像，可同时安装 Docker，二者互不冲突：</p>
<pre><code class="language-bash">yum install docker-ce -y
systemctl enable docker --now</code></pre>
<h3>5. 配置镜像加速器</h3>
<h4>（1）containerd 镜像加速</h4>
<pre><code class="language-bash"># 修改配置文件，指定证书配置目录
sed -i 's#config_path = ""#config_path = "/etc/containerd/certs.d"#g' /etc/containerd/config.toml

# 创建docker.io镜像加速配置
mkdir /etc/containerd/certs.d/docker.io/ -p
cat &gt; /etc/containerd/certs.d/docker.io/hosts.toml &lt;&lt;EOF
[host."https://vh3bm52y.mirror.aliyuncs.com",host."https://registry.docker-cn.com"]
  capabilities = ["pull"]
EOF

# 重启生效
systemctl restart containerd</code></pre>
<h4>（2）Docker 镜像加速</h4>
<pre><code class="language-bash">cat &gt; /etc/docker/daemon.json &lt;&lt;EOF
{
 "registry-mirrors":["https://vh3bm52y.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hub-mirror.c.163.com"]
}
EOF

systemctl restart docker</code></pre>
<hr />
<h2>四、安装 K8s 核心组件（所有节点执行）</h2>
<h3>1. 安装指定版本组件</h3>
<pre><code class="language-bash">yum install -y kubelet-1.25.0 kubeadm-1.25.0 kubectl-1.25.0</code></pre>
<h3>2. 设置 kubelet 开机自启</h3>
<pre><code class="language-bash">systemctl enable kubelet</code></pre>
<blockquote>
<p>组件说明：</p>
<ul>
<li>
<p><strong>kubeadm</strong>：K8s 集群自动化初始化工具</p>
</li>
<li>
<p><strong>kubelet</strong>：运行在所有节点，负责 Pod 生命周期管理，与 APIServer 通信</p>
</li>
<li>
<p><strong>kubectl</strong>：K8s 命令行客户端，用于集群资源管理与操作</p>
</li>
</ul>
</blockquote>
<hr />
<h2>五、kubeadm 初始化 Master 控制节点</h2>
<h3>1. 指定 containerd 运行时端点（所有节点执行）</h3>
<pre><code class="language-bash">crictl config runtime-endpoint /run/containerd/containerd.sock</code></pre>
<h3>2. 编写初始化配置文件</h3>
<p>在 Master 节点生成并修改配置：</p>
<pre><code class="language-bash">kubeadm config print init-defaults &gt; kubeadm.yaml</code></pre>
<p>完整<code>kubeadm.yaml</code>配置：</p>
<pre><code class="language-yaml">apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.40.180  # Master节点IP
  bindPort: 6443
nodeRegistration:
  criSocket: unix:///run/containerd/containerd.sock  # 指定containerd运行时
  imagePullPolicy: IfNotPresent
  name: zhappymaster1  # Master主机名
  taints: null
---
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers  # 国内镜像源
kind: ClusterConfiguration
kubernetesVersion: 1.25.0  # K8s版本
networking:
  dnsDomain: cluster.local
  podSubnet: 10.244.0.0/16  # Pod网段
  serviceSubnet: 10.96.0.0/12  # Service网段
scheduler: {}
---
# kube-proxy启用IPVS模式
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
---
# kubelet cgroup驱动与containerd保持一致
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd</code></pre>
<h3>3. 导入离线镜像（所有节点）</h3>
<p>将<code>k8s_1.25.0.tar.gz</code>上传至所有节点，通过 ctr 导入 [k8s.io](k8s.io) 命名空间：</p>
<pre><code class="language-bash"># containerd有命名空间概念，k8s相关镜像默认在k8s.io命名空间
ctr -n=k8s.io images import k8s_1.25.0.tar.gz

# 验证镜像
crictl images</code></pre>
<h3>4. 执行集群初始化</h3>
<pre><code class="language-bash">kubeadm init --config=kubeadm.yaml --ignore-preflight-errors=SystemVerification</code></pre>
<p>初始化成功后会输出 Master 节点加入命令和 Worker 节点加入命令，请保存好 token 和 hash 值。</p>
<h3>5. 配置 kubectl 管理员权限</h3>
<pre><code class="language-bash">mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config</code></pre>
<h3>6. 查看初始节点状态</h3>
<pre><code class="language-bash">kubectl get nodes</code></pre>
<p>此时节点状态为<code>NotReady</code>属于正常现象，原因是尚未安装网络插件。</p>
<hr />
<h2>六、扩容 Worker 工作节点</h2>
<h3>1. 生成节点加入命令（Master 执行）</h3>
<pre><code class="language-bash">kubeadm token create --print-join-command</code></pre>
<h3>2. Node1 加入集群</h3>
<p>在 Node1 节点执行输出的 join 命令：</p>
<pre><code class="language-bash">kubeadm join 192.168.40.180:6443 --token 你的token值 \
    --discovery-token-ca-cert-hash sha256:你的hash值 \
    --ignore-preflight-errors=SystemVerification</code></pre>
<h3>3. Node2 加入集群</h3>
<p>同样执行 join 命令加入集群。</p>
<h3>4. 给 Worker 节点打角色标签</h3>
<pre><code class="language-bash">kubectl label nodes zhappynode1 node-role.kubernetes.io/work=work
kubectl label nodes zhappynode2 node-role.kubernetes.io/work=work</code></pre>
<hr />
<h2>七、安装 Calico 网络插件</h2>
<h3>1. 导入 Calico 离线镜像（所有节点）</h3>
<pre><code class="language-bash">ctr -n=k8s.io images import calico.tar.gz</code></pre>
<h3>2. 部署 Calico</h3>
<p>上传<code>calico.yaml</code>文件，在 Master 执行部署：</p>
<pre><code class="language-bash">kubectl apply -f calico.yaml</code></pre>
<blockquote>
<p>在线下载地址：<a href="https://docs.projectcalico.org/manifests/calico.yaml">https://docs.projectcalico.org/manifests/calico.yaml</a></p>
</blockquote>
<h3>3. 验证节点状态</h3>
<pre><code class="language-bash">kubectl get nodes</code></pre>
<p>等待所有节点 STATUS 变为<code>Ready</code>，说明网络插件安装成功。</p>
<h3>4. Calico 核心组件</h3>
<ol>
<li>
<p><strong>Felix</strong>：运行在每个节点的 Agent，负责路由、ARP、ACL 规则管理，保障容器网络互通</p>
</li>
<li>
<p><strong>Etcd</strong>：分布式存储，保存 Calico 网络元数据，保证状态一致性</p>
</li>
<li>
<p><strong>BGP Client（BIRD）</strong>：每个节点部署一个，将内核路由信息分发到整个 Calico 网络</p>
</li>
<li>
<p><strong>BGP Route Reflector</strong>：大规模集群使用，替代全网状互联，集中分发路由，降低节点连接数</p>
</li>
</ol>
<h3>5. IPIP 与 BGP 模式对比</h3>
<table>
<thead>
<tr>
<th>模式</th>
<th>原理</th>
<th>特点</th>
<th>适用场景</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>IPIP</strong></td>
<td>IP 包外层再封装一层 IP 头，通过 tunl0 隧道转发，属于 Overlay 网络</td>
<td>不要求节点二层互通，有额外封装开销</td>
<td>跨网段、三层不通的复杂网络环境</td>
</tr>
<tr>
<td><strong>BGP</strong></td>
<td>节点作为虚拟路由器，直接通过路由转发，无额外隧道</td>
<td>性能高，无封装开销，要求节点二层互通</td>
<td>同机房、同网段的物理机集群</td>
</tr>
</tbody>
</table>
<blockquote>
<p>Calico 默认开启 IPIP 模式，通过环境变量<code>CALICO_IPV4POOL_IPIP</code>控制，<code>Always</code>为开启，<code>Off</code>为关闭并使用 BGP 模式。<br />
多网卡节点可通过<code>IP_AUTODETECTION_METHOD</code>指定网卡，例如<code>interface=ens33</code>。</p>
</blockquote>
<hr />
<h2>八、集群功能验证</h2>
<h3>1. 导入测试镜像（所有 Node 节点）</h3>
<pre><code class="language-bash">ctr -n k8s.io images import busybox-1-28.tar.gz</code></pre>
<h3>2. Pod 外网连通性测试</h3>
<pre><code class="language-bash">kubectl run busybox --image docker.io/library/busybox:1.28 \
  --image-pull-policy=IfNotPresent --restart=Never --rm -it -- sh</code></pre>
<p>容器内执行 ping 测试：</p>
<pre><code class="language-bash">ping www.baidu.com</code></pre>
<p>能正常连通说明容器外网与 Calico 网络正常。</p>
<h3>3. CoreDNS 域名解析测试</h3>
<p>在 busybox 容器内执行：</p>
<pre><code class="language-bash">nslookup kubernetes.default.svc.cluster.local</code></pre>
<p>能正常解析出 Service IP 则集群 DNS 服务正常。</p>
<blockquote>
<p>注意：必须使用 busybox 1.28 版本，高版本存在 nslookup 解析异常问题。</p>
</blockquote>
<hr />
<h2>九、ctr 与 crictl 工具区别</h2>
<p>二者均为容器运行时的命令行工具，但定位与适用场景不同：</p>
<ol>
<li>
<p><strong>ctr</strong>：containerd 自带的原生 CLI 工具，功能全面，支持镜像、容器、命名空间等全量管理，不感知 K8s 概念。</p>
</li>
<li>
<p><strong>crictl</strong>：K8s CRI（容器运行时接口）的官方客户端，专门用于 K8s 场景下与容器运行时交互，功能偏向容器、Pod 生命周期管理，镜像管理能力较弱。</p>
</li>
</ol>
<p>简单理解：</p>
<ul>
<li>
<p>调试 containerd 本身、导入导出镜像、管理命名空间用 <code>ctr</code></p>
</li>
<li>
<p>调试 K8s 容器、查看 Pod 容器状态用 <code>crictl</code>，与 K8s 体系兼容性更好</p>
</li>
</ul>]]></description>
    <pubDate>Mon, 22 Jun 2026 15:45:10 +0800</pubDate>
    <dc:creator>ZHappy</dc:creator>
    <guid>https://blog.zhappy.vip/?post=24</guid>
</item>
<item>
    <title>07-K8s 可视化UI界面 Dashboard 部署指南</title>
    <link>https://blog.zhappy.vip/?post=23</link>
    <description><![CDATA[<h2>一、安装 Dashboard</h2>
<h3>1. 导入离线镜像</h3>
<p>将 Dashboard 依赖的镜像包上传到所有工作节点，手动导入：</p>
<pre><code class="language-bash"># 两个Node节点都执行
docker load -i dashboard_2_0_0.tar.gz
docker load -i metrics-scrapter-1-0-1.tar.gz</code></pre>
<h3>2. 部署 Dashboard 组件</h3>
<p>在 Master 节点执行部署命令：</p>
<pre><code class="language-bash">kubectl apply -f kubernetes-dashboard.yaml</code></pre>
<p>验证 Pod 运行状态：</p>
<pre><code class="language-bash">kubectl get pods -n kubernetes-dashboard</code></pre>
<p>正常输出示例：</p>
<pre><code class="language-Plain">NAME                                         READY   STATUS    RESTARTS   AGE
dashboard-metrics-scraper-7445d59dfd-n5krt   1/1     Running   0          66s
kubernetes-dashboard-54f5b6dc4b-mhd2c        1/1     Running   0          66s</code></pre>
<p>查看默认 Service 信息：</p>
<pre><code class="language-bash">kubectl get svc -n kubernetes-dashboard</code></pre>
<p>默认 Service 类型为 <code>ClusterIP</code>，仅集群内部可访问。</p>
<h3>3. 修改 Service 暴露 NodePort 端口</h3>
<p>将 Service 类型改为 <code>NodePort</code>，通过节点 IP + 端口对外访问：</p>
<pre><code class="language-bash">kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard</code></pre>
<p>将配置中的 <code>type: ClusterIP</code> 修改为 <code>type: NodePort</code>，保存退出。</p>
<p>再次查看 Service，获取随机映射的端口：</p>
<pre><code class="language-bash">kubectl get svc -n kubernetes-dashboard</code></pre>
<p>输出示例：</p>
<pre><code class="language-Plain">NAME                        TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)         AGE
dashboard-metrics-scraper   ClusterIP   10.98.221.57   &lt;none&gt;        8000/TCP        
kubernetes-dashboard        NodePort    10.97.37.171   &lt;none&gt;        443:32728/TCP   2m50s</code></pre>
<p>本例中对外暴露的端口为 <code>32728</code>。</p>
<h3>4. 浏览器访问与证书问题处理</h3>
<p>访问地址：<code>https://任意节点IP:NodePort端口</code>，例如 <code>https://192.168.40.180:32728/</code></p>
<p>由于 Dashboard 默认使用自签名证书，浏览器会提示安全风险，处理方式：</p>
<ul>
<li>
<p><strong>火狐浏览器</strong>：点击「高级」→「接受风险并继续」</p>
</li>
<li>
<p><strong>Chrome 浏览器</strong>：在报错页面任意位置，直接键盘输入 <code>thisisunsafe</code>（共 11 个字符，无需输入框），即可自动跳过证书校验进入登录页</p>
</li>
</ul>
<hr />
<h2>二、方式一：Token 令牌登录 Dashboard</h2>
<h3>1. 授权 Dashboard 管理员权限</h3>
<p>给 Dashboard 服务账号绑定集群管理员角色，拥有全集群管理权限：</p>
<pre><code class="language-bash">kubectl create clusterrolebinding dashboard-cluster-admin \
  --clusterrole=cluster-admin \
  --serviceaccount=kubernetes-dashboard:kubernetes-dashboard</code></pre>
<h3>2. 获取登录 Token</h3>
<ol>
<li>查看命名空间下的 Secret 列表：</li>
</ol>
<pre><code class="language-bash">kubectl get secret -n kubernetes-dashboard</code></pre>
<p>找到名称格式为 <code>kubernetes-dashboard-token-xxxx</code> 的 Secret。</p>
<ol start="2">
<li>查看 Secret 详情，获取 Token 值：</li>
</ol>
<pre><code class="language-bash">kubectl describe secret kubernetes-dashboard-token-ppc8c -n kubernetes-dashboard</code></pre>
<p>输出中 <code>token:</code> 后面对应的长字符串即为登录凭证。</p>
<h3>3. Token 登录验证</h3>
<p>在 Dashboard 登录页选择「Token」方式，粘贴获取到的 Token 字符串，点击登录即可进入管理界面。</p>
<hr />
<h2>三、方式二：kubeconfig 文件登录 Dashboard</h2>
<p>通过生成独立的 kubeconfig 配置文件，导入界面完成登录，无需每次输入 Token。</p>
<blockquote>
<p>操作目录：<code>/etc/kubernetes/pki</code></p>
</blockquote>
<pre><code class="language-bash">cd /etc/kubernetes/pki</code></pre>
<h3>1. 创建集群（cluster）配置</h3>
<p>写入集群地址与 CA 证书到配置文件：</p>
<pre><code class="language-bash">kubectl config set-cluster kubernetes \
  --certificate-authority=./ca.crt \
  --server="https://192.168.40.180:6443" \
  --embed-certs=true \
  --kubeconfig=/root/dashboard-admin.conf</code></pre>
<h3>2. 创建用户凭证（credentials）</h3>
<p>将 Dashboard 的 Token 写入配置文件作为用户认证信息：</p>
<pre><code class="language-bash"># 先把Token存入变量
DEF_NS_ADMIN_TOKEN=$(kubectl get secret kubernetes-dashboard-token-ppc8c -n kubernetes-dashboard -o jsonpath={.data.token}|base64 -d)

# 写入用户凭证
kubectl config set-credentials dashboard-admin \
  --token=$DEF_NS_ADMIN_TOKEN \
  --kubeconfig=/root/dashboard-admin.conf</code></pre>
<h3>3. 创建上下文（context）</h3>
<p>将集群与用户绑定，生成访问上下文：</p>
<pre><code class="language-bash">kubectl config set-context dashboard-admin@kubernetes \
  --cluster=kubernetes \
  --user=dashboard-admin \
  --kubeconfig=/root/dashboard-admin.conf</code></pre>
<h3>4. 切换默认上下文</h3>
<pre><code class="language-bash">kubectl config use-context dashboard-admin@kubernetes --kubeconfig=/root/dashboard-admin.conf</code></pre>
<h3>5. kubeconfig 文件登录</h3>
<p>将生成的 <code>/root/dashboard-admin.conf</code> 文件下载到本地，在 Dashboard 登录页选择「Kubeconfig」方式，上传该文件即可完成登录。</p>
<hr />
<h2>四、通过 Dashboard 可视化创建应用</h2>
<h3>1. 提前导入镜像</h3>
<p>将应用镜像（以 nginx 为例）上传到所有工作节点并导入：</p>
<pre><code class="language-bash">docker load -i nginx.tar.gz</code></pre>
<h3>2. 界面创建 Deployment 与 Service</h3>
<ol>
<li>
<p>点击 Dashboard 右上角的「+」号创建资源</p>
</li>
<li>
<p>选择「Create from form」表单创建模式</p>
</li>
<li>
<p>填写核心参数：</p>
<ul>
<li>
<p><strong>App name</strong>：应用名称，例如 <code>nginx</code></p>
</li>
<li>
<p><strong>Container image</strong>：容器镜像名，例如 <code>nginx</code></p>
</li>
<li>
<p><strong>Number of pods</strong>：Pod 副本数，例如 <code>2</code></p>
</li>
<li>
<p><strong>Service</strong>：选择 <code>External</code>（对外暴露服务）</p>
</li>
<li>
<p><strong>Port</strong>：Service 端口，填 <code>80</code></p>
</li>
<li>
<p><strong>Target port</strong>：容器内端口，填 <code>80</code></p>
</li>
<li>
<p><strong>Protocol</strong>：选择 <code>TCP</code></p>
</li>
</ul>
</li>
<li>
<p>点击「Deploy」完成部署</p>
</li>
</ol>
<h3>3. 验证应用访问</h3>
<ol>
<li>
<p>左侧菜单进入「Services」页面，找到刚创建的 nginx 服务</p>
</li>
<li>
<p>查看对外映射的 NodePort 端口（例如 31135）</p>
</li>
<li>
<p>浏览器访问 <code>http://节点IP:端口</code>，例如 <code>http://192.168.40.180:31135</code>，能看到 Nginx 欢迎页即为部署成功。</p>
</li>
</ol>
<blockquote>
<p>说明：通过表单创建对外服务时，会自动生成 30000 以上的随机 NodePort 端口。</p>
</blockquote>
<hr />
<h2>五、端口概念说明（port /targetPort/nodePort）</h2>
<ul>
<li>
<p><strong>nodePort</strong>：集群外部流量访问的入口端口，暴露在节点物理机上，供外部用户访问服务（如浏览器访问 Nginx）。</p>
</li>
<li>
<p><strong>port</strong>：Service 在集群内部的端口，用于集群内其他 Pod 互相访问当前服务（例如集群内其他服务调用 MySQL）。</p>
</li>
<li>
<p><strong>targetPort</strong>：目标端口，即 Pod 内部容器实际监听的端口，Service 会将流量最终转发到该端口。</p>
</li>
</ul>]]></description>
    <pubDate>Mon, 22 Jun 2026 14:45:20 +0800</pubDate>
    <dc:creator>ZHappy</dc:creator>
    <guid>https://blog.zhappy.vip/?post=23</guid>
</item>
<item>
    <title>06-kubeadm部署单Master K8s测试集群</title>
    <link>https://blog.zhappy.vip/?post=22</link>
    <description><![CDATA[<h2>一、集群整体规划</h2>
<h3>1. 网段规划</h3>
<ul>
<li>
<p>Pod 网段（podSubnet）：<code>10.244.0.0/16</code></p>
</li>
<li>
<p>Service 网段（serviceSubnet）：<code>10.96.0.0/12</code></p>
</li>
<li>
<p>物理机网段：<code>192.168.40.0/24</code></p>
</li>
</ul>
<h3>2. 节点角色规划</h3>
<table>
<thead>
<tr>
<th>角色</th>
<th>主机名</th>
<th>IP 地址</th>
<th>核心组件</th>
</tr>
</thead>
<tbody>
<tr>
<td>控制节点 Master</td>
<td>zhappymaster1</td>
<td>(192.168.40.180)</td>
<td>apiserver、controller-manager、scheduler、etcd、kube-proxy、docker、calico</td>
</tr>
<tr>
<td>工作节点 Node1</td>
<td>zhappynode1</td>
<td>(192.168.40.181)</td>
<td>kubelet、kube-proxy、docker、calico、coredns</td>
</tr>
<tr>
<td>工作节点 Node2</td>
<td>zhappynode2</td>
<td>(192.168.40.182)</td>
<td>kubelet、kube-proxy、docker、calico、coredns</td>
</tr>
</tbody>
</table>
<h3>3. 系统环境要求</h3>
<ul>
<li>
<p>操作系统：CentOS 7.9</p>
</li>
<li>
<p>硬件配置：4GiB 内存 / 4vCPU / 60G 硬盘</p>
</li>
<li>
<p>网络：NAT 模式，虚拟机开启 CPU 虚拟化支持</p>
</li>
</ul>
<hr />
<h2>二、集群环境初始化（所有节点执行）</h2>
<h3>1. 配置静态 IP</h3>
<p>修改网卡配置（网卡名以实际为准，示例为<code>ens33</code>）：</p>
<pre><code class="language-bash">vim /etc/sysconfig/network-scripts/ifcfg-ens33</code></pre>
<p>核心配置项：</p>
<pre><code class="language-ini">BOOTPROTO=static
IPADDR=192.168.40.180   # 替换为对应节点IP
NETMASK=255.255.255.0
GATEWAY=192.168.40.2
DNS1=192.168.40.2
ONBOOT=yes
NAME=ens33
DEVICE=ens33</code></pre>
<p>重启网络生效：</p>
<pre><code class="language-bash">service network restart</code></pre>
<h3>2. 关闭 SELinux</h3>
<pre><code class="language-bash"># 临时关闭
setenforce 0
# 永久关闭，重启后生效
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
# 重启机器
reboot -f
# 验证状态
getenforce</code></pre>
<h3>3. 设置主机名</h3>
<p>分别在对应节点执行：</p>
<pre><code class="language-bash"># Master执行
hostnamectl set-hostname zhappymaster1 &amp;&amp; bash

# Node1执行
hostnamectl set-hostname zhappynode1 &amp;&amp; bash

# Node2执行
hostnamectl set-hostname zhappynode2 &amp;&amp; bash</code></pre>
<blockquote>
<p>可选操作：执行 <code>yum update -y</code> 升级系统至最新 CentOS7 版本。</p>
</blockquote>
<h3>4. 配置主机名解析</h3>
<p>所有节点的<code>/etc/hosts</code>添加节点映射：</p>
<pre><code class="language-bash">cat &gt;&gt; /etc/hosts &lt;&lt;EOF
192.168.40.180   zhappymaster1
192.168.40.181   zhappynode1
192.168.40.182   zhappynode2
EOF</code></pre>
<h3>5. 配置节点间 SSH 免密登录</h3>
<p>分别在三个节点生成密钥并分发至所有节点：</p>
<pre><code class="language-bash"># 生成密钥，一路回车即可
ssh-keygen

# 分发公钥
ssh-copy-id zhappymaster1
ssh-copy-id zhappynode1
ssh-copy-id zhappynode2</code></pre>
<h3>6. 关闭 Swap 交换分区</h3>
<p>K8s 默认禁用 Swap 以保证性能，未关闭会导致初始化失败。</p>
<pre><code class="language-bash"># 临时关闭
swapoff -a

# 永久关闭：注释fstab中swap挂载行
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab</code></pre>
<blockquote>
<p>说明：若必须保留 Swap，可在 kubeadm 命令后追加<code>--ignore-preflight-errors=Swap</code>跳过检测。</p>
</blockquote>
<h3>7. 配置内核网络参数</h3>
<p>加载桥接模块，开启 IP 转发与网桥 iptables 支持：</p>
<pre><code class="language-bash"># 加载br_netfilter内核模块
modprobe br_netfilter
echo "modprobe br_netfilter" &gt;&gt; /etc/profile

# 写入内核配置
cat &gt; /etc/sysctl.d/k8s.conf &lt;&lt;EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

# 生效配置
sysctl -p /etc/sysctl.d/k8s.conf</code></pre>
<h3>8. 关闭 firewalld 防火墙</h3>
<pre><code class="language-bash">systemctl stop firewalld
systemctl disable firewalld</code></pre>
<h3>9. 配置软件源与基础依赖</h3>
<ol>
<li>添加 Docker 阿里云 YUM 源：</li>
</ol>
<pre><code class="language-bash">yum install yum-utils -y
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo</code></pre>
<ol start="2">
<li>安装基础依赖包：</li>
</ol>
<pre><code class="language-bash">yum install -y yum-utils device-mapper-persistent-data lvm2 wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo ntp libaio-devel vim ncurses-devel autoconf automake zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack ntpdate telnet ipvsadm</code></pre>
<h3>10. 配置 K8s 阿里云 YUM 源</h3>
<p>在 Master 创建源文件，再分发到其他节点：</p>
<pre><code class="language-bash">cat &gt; /etc/yum.repos.d/kubernetes.repo &lt;&lt;EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
EOF

# 分发至工作节点
scp /etc/yum.repos.d/kubernetes.repo zhappynode1:/etc/yum.repos.d/
scp /etc/yum.repos.d/kubernetes.repo zhappynode2:/etc/yum.repos.d/</code></pre>
<h3>11. 配置时间同步</h3>
<pre><code class="language-bash"># 安装同步工具
yum install ntpdate -y
# 立即同步时间
ntpdate cn.pool.ntp.org

# 添加定时任务，每小时同步一次
crontab -e
* */1 * * * /usr/sbin/ntpdate cn.pool.ntp.org

# 重启定时任务
service crond restart</code></pre>
<hr />
<h2>三、安装 Docker 服务（所有节点执行）</h2>
<h3>1. 安装指定版本 Docker</h3>
<pre><code class="language-bash">yum install docker-ce-20.10.6 -y</code></pre>
<h3>2. 配置镜像加速器与 Cgroup 驱动</h3>
<pre><code class="language-bash">cat &gt; /etc/docker/daemon.json &lt;&lt;EOF
{
 "registry-mirrors":["https://rsbud4vc.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hub-mirror.c.163.com"],
  "exec-opts": ["native.cgroupdriver=systemd"]
}
EOF</code></pre>
<blockquote>
<p><strong>重要</strong>：Kubelet 默认使用<code>systemd</code>作为 cgroup 驱动，Docker 默认为<code>cgroupfs</code>，两者必须一致，否则集群启动失败。</p>
</blockquote>
<h3>3. 启动并设置开机自启</h3>
<pre><code class="language-bash">systemctl daemon-reload
systemctl start docker
systemctl enable docker.service
systemctl status docker</code></pre>
<hr />
<h2>四、安装 K8s 核心组件（所有节点执行）</h2>
<h3>1. 安装指定版本组件</h3>
<pre><code class="language-bash">yum install -y kubelet-1.20.6 kubeadm-1.20.6 kubectl-1.20.6</code></pre>
<h3>2. 设置 kubelet 开机自启</h3>
<pre><code class="language-bash">systemctl enable kubelet</code></pre>
<blockquote>
<p>组件说明：</p>
<ul>
<li>
<p><strong>kubeadm</strong>：K8s 集群自动化初始化工具</p>
</li>
<li>
<p><strong>kubelet</strong>：运行在所有节点，负责 Pod 生命周期管理、与 APIServer 通信</p>
</li>
<li>
<p><strong>kubectl</strong>：K8s 命令行客户端，用于集群资源管理与操作</p>
</li>
</ul>
</blockquote>
<hr />
<h2>五、kubeadm 初始化 Master 节点（Master 执行）</h2>
<h3>1. 导入离线镜像（所有节点）</h3>
<p>提前将<code>k8simage-1-20-6.tar.gz</code>上传至所有节点，导入镜像：</p>
<pre><code class="language-bash">docker load -i k8simage-1-20-6.tar.gz</code></pre>
<h3>2. 生成并修改初始化配置文件</h3>
<pre><code class="language-bash"># 生成默认配置模板
kubeadm config print init-defaults &gt; kubeadm.yaml</code></pre>
<p>修改<code>kubeadm.yaml</code>，完整配置如下：</p>
<pre><code class="language-yaml">apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.40.180  # Master节点IP
  bindPort: 6443
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  name: zhappymaster1  # Master主机名
  taints:
  - effect: NoSchedule
    key: node-role.kubernetes.io/master
---
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns:
  type: CoreDNS
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers  # 国内镜像源
kind: ClusterConfiguration
kubernetesVersion: v1.20.6
networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.96.0.0/12
  podSubnet: 10.244.0.0/16  # Pod网段
scheduler: {}
---
# kube-proxy启用IPVS模式
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
---
# kubelet cgroup驱动与docker保持一致
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd</code></pre>
<h3>3. 执行集群初始化</h3>
<pre><code class="language-bash">kubeadm init --config=kubeadm.yaml --ignore-preflight-errors=SystemVerification</code></pre>
<p>初始化成功后会输出 Worker 节点加入命令，请保存好 token 和 hash 值。</p>
<h3>4. 配置 kubectl 管理员权限</h3>
<pre><code class="language-bash">mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config</code></pre>
<h3>5. 查看初始节点状态</h3>
<pre><code class="language-bash">kubectl get nodes</code></pre>
<p>此时节点状态为<code>NotReady</code>属于正常现象，原因是尚未安装网络插件。</p>
<hr />
<h3>扩展：kubeadm init 执行流程详解</h3>
<ol>
<li>
<p><strong>配置初始化</strong>：加载默认配置与用户自定义配置，转换为内部参数格式</p>
</li>
<li>
<p><strong>安装预检</strong>：检查 root 权限、版本兼容性、防火墙、端口占用、容器运行时、内核参数、Swap 状态等</p>
</li>
<li>
<p><strong>镜像拉取</strong>：拉取 apiserver、controller-manager、scheduler、etcd、coredns 等组件镜像</p>
</li>
<li>
<p><strong>配置 kubelet</strong>：写入 kubelet 配置文件并重启服务</p>
</li>
<li>
<p><strong>生成证书</strong>：生成 CA 根证书及各组件证书、kubeconfig 配置文件</p>
</li>
<li>
<p><strong>生成静态 Pod 清单</strong>：在<code>/etc/kubernetes/manifests</code>下生成控制平面组件的 Pod 配置，由 kubelet 启动</p>
</li>
<li>
<p><strong>等待控制平面启动</strong>：等待 APIServer 等组件就绪</p>
</li>
<li>
<p><strong>集群后置配置</strong>：创建 ConfigMap、RBAC 权限、标记 Master 节点、部署 CoreDNS 与 kube-proxy</p>
</li>
<li>
<p><strong>输出加入命令</strong>：打印 Worker 节点加入集群的命令</p>
</li>
</ol>
<hr />
<h3>扩展：Kubeadm 证书体系说明</h3>
<p>K8s 证书分为两大目录：<code>/etc/kubernetes/pki</code>、<code>/etc/kubernetes/pki/etcd</code></p>
<ol>
<li>
<p><strong>K8s 集群根证书 CA</strong></p>
<ul>
<li><code>ca.crt / ca.key</code>：签发 APIServer、kubelet 客户端等组件证书</li>
</ul>
</li>
<li>
<p><strong>APIServer 相关证书</strong></p>
<ul>
<li>
<p><code>apiserver.crt / apiserver.key</code>：APIServer 服务端证书</p>
</li>
<li>
<p><code>apiserver-kubelet-client.crt / apiserver-kubelet-client.key</code>：APIServer 访问 kubelet 的客户端证书</p>
</li>
</ul>
</li>
<li>
<p><strong>前端代理根证书</strong></p>
<ul>
<li>
<p><code>front-proxy-ca.crt / front-proxy-ca.key</code>：用于聚合层 API 代理认证</p>
</li>
<li>
<p><code>front-proxy-client.crt / front-proxy-client.key</code>：代理客户端证书</p>
</li>
</ul>
</li>
<li>
<p><strong>Etcd 证书体系</strong></p>
<ul>
<li>
<p><code>etcd/ca.crt / etcd/ca.key</code>：Etcd 集群根证书</p>
</li>
<li>
<p><code>etcd/server.crt / etcd/server.key</code>：Etcd 服务端证书</p>
</li>
<li>
<p><code>etcd/peer.crt / etcd/peer.key</code>：Etcd 节点间通信证书</p>
</li>
<li>
<p><code>etcd/healthcheck-client.crt / etcd/healthcheck-client.key</code>：Etcd 健康检查客户端证书</p>
</li>
<li>
<p><code>apiserver-etcd-client.crt / apiserver-etcd-client.key</code>：APIServer 访问 Etcd 的客户端证书</p>
</li>
</ul>
</li>
</ol>
<hr />
<h2>六、扩容 Worker 工作节点</h2>
<h3>1. 生成节点加入命令（Master 执行）</h3>
<pre><code class="language-bash">kubeadm token create --print-join-command</code></pre>
<h3>2. Node1 加入集群</h3>
<p>在 Node1 节点执行输出的 join 命令：</p>
<pre><code class="language-bash">kubeadm join 192.168.40.180:6443 --token 你的token值 \
    --discovery-token-ca-cert-hash sha256:你的hash值 \
    --ignore-preflight-errors=SystemVerification</code></pre>
<h3>3. Node2 加入集群</h3>
<p>同样执行 join 命令加入集群。</p>
<h3>4. 给 Worker 节点打角色标签</h3>
<pre><code class="language-bash">kubectl label node zhappynode1 node-role.kubernetes.io/worker=worker
kubectl label node zhappynode2 node-role.kubernetes.io/worker=worker</code></pre>
<h3>5. 查看节点状态</h3>
<pre><code class="language-bash">kubectl get nodes</code></pre>
<p>所有节点均为<code>NotReady</code>，等待安装网络插件后恢复正常。</p>
<hr />
<h2>七、安装 Calico 网络插件（Master 执行）</h2>
<h3>1. 部署 Calico</h3>
<p>上传<code>calico.yaml</code>文件，或在线下载：</p>
<pre><code class="language-bash"># 在线下载（可选）
# wget https://docs.projectcalico.org/manifests/calico.yaml

kubectl apply -f calico.yaml</code></pre>
<h3>2. 验证 Pod 与节点状态</h3>
<pre><code class="language-bash"># 查看系统Pod状态
kubectl get pods -n kube-system

# 查看节点状态
kubectl get nodes</code></pre>
<p>等待 calico 相关 Pod 全部 Running，节点状态变为<code>Ready</code>，CoreDNS 也会从 Pending 转为正常运行。</p>
<h3>3. Calico 核心组件</h3>
<ol>
<li>
<p><strong>Felix</strong>：运行在每个节点的 Agent，负责路由、ARP、ACL 规则管理，保障容器网络互通</p>
</li>
<li>
<p><strong>Etcd</strong>：分布式存储，保存 Calico 网络元数据，保证状态一致性</p>
</li>
<li>
<p><strong>BGP Client（BIRD）</strong>：每个节点部署一个，将内核路由信息分发到整个 Calico 网络</p>
</li>
<li>
<p><strong>BGP Route Reflector</strong>：大规模集群使用，替代全网状互联，集中分发路由，降低节点连接数</p>
</li>
</ol>
<h3>4. IPIP 与 BGP 模式对比</h3>
<table>
<thead>
<tr>
<th>模式</th>
<th>原理</th>
<th>特点</th>
<th>适用场景</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>IPIP</strong></td>
<td>IP 包外层再封装一层 IP 头，通过 tunl0 隧道转发，属于 Overlay 网络</td>
<td>不要求节点二层互通，有额外封装开销</td>
<td>跨网段、三层不通的复杂网络环境</td>
</tr>
<tr>
<td><strong>BGP</strong></td>
<td>节点作为虚拟路由器，直接通过路由转发，无额外隧道</td>
<td>性能高，无封装开销，要求节点二层互通</td>
<td>同机房、同网段的物理机集群</td>
</tr>
</tbody>
</table>
<blockquote>
<p>Calico 默认开启 IPIP 模式，通过环境变量<code>CALICO_IPV4POOL_IPIP</code>控制，<code>Always</code>为开启，<code>Off</code>为关闭并使用 BGP 模式。<br />
多网卡节点可通过<code>IP_AUTODETECTION_METHOD</code>指定网卡，例如<code>interface=ens33</code>。</p>
</blockquote>
<hr />
<h2>八、集群功能验证</h2>
<h3>1. Pod 外网连通性测试</h3>
<ol>
<li>所有 Node 节点导入 busybox 镜像：</li>
</ol>
<pre><code class="language-bash">docker load -i busybox-1-28.tar.gz</code></pre>
<ol start="2">
<li>启动临时测试 Pod：</li>
</ol>
<pre><code class="language-bash">kubectl run busybox --image busybox:1.28 --image-pull-policy=IfNotPresent --restart=Never --rm -it -- sh</code></pre>
<ol start="3">
<li>容器内 ping 公网测试：</li>
</ol>
<pre><code class="language-bash">ping www.baidu.com</code></pre>
<p>能正常连通说明容器外网与 Calico 网络正常。</p>
<h3>2. CoreDNS 域名解析测试</h3>
<p>在 busybox 容器内执行：</p>
<pre><code class="language-bash">nslookup kubernetes.default.svc.cluster.local</code></pre>
<p>能正常解析出 Service IP（[10.96.0.1](10.96.0.1)）则集群 DNS 服务正常。</p>
<blockquote>
<p>注意：必须使用 busybox 1.28 版本，高版本存在 nslookup 解析异常问题。</p>
</blockquote>
<hr />
<h2>九、K8s 证书有效期续期</h2>
<p>kubeadm 默认签发的组件证书有效期为 1 年，CA 根证书为 10 年，可通过脚本将组件证书延长至 10 年。</p>
<h3>1. 查看证书有效期</h3>
<pre><code class="language-bash"># 查看CA根证书有效期
openssl x509 -in /etc/kubernetes/pki/ca.crt -noout -text | grep Not

# 查看APIServer证书有效期
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text | grep Not</code></pre>
<h3>2. 执行续期脚本（Master 执行）</h3>
<p>上传<code>update-kubeadm-cert.sh</code>脚本：</p>
<pre><code class="language-bash"># 授权可执行
chmod +x update-kubeadm-cert.sh

# 全量续期所有证书
./update-kubeadm-cert.sh all</code></pre>
<h3>3. 验证续期结果</h3>
<pre><code class="language-bash"># 验证组件证书已延长至10年
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text | grep Not

# 验证系统Pod运行正常
kubectl get pods -n kube-system</code></pre>]]></description>
    <pubDate>Mon, 22 Jun 2026 10:31:46 +0800</pubDate>
    <dc:creator>ZHappy</dc:creator>
    <guid>https://blog.zhappy.vip/?post=22</guid>
</item>
<item>
    <title>05-kubeadm部署生产级多Master高可用K8s集群</title>
    <link>https://blog.zhappy.vip/?post=21</link>
    <description><![CDATA[<h2>一、集群整体规划</h2>
<h3>1. 网络网段规划</h3>
<ul>
<li>
<p>Pod网段（podSubnet）：<code>10.244.0.0/16</code></p>
</li>
<li>
<p>Service网段（serviceSubnet）：<code>10.96.0.0/16</code></p>
</li>
<li>
<p>高可用虚拟VIP：<code>192.168.40.199</code></p>
</li>
</ul>
<h3>2. 节点角色规划</h3>
<table>
<thead>
<tr>
<th>角色</th>
<th>主机名</th>
<th>IP地址</th>
<th>核心组件</th>
</tr>
</thead>
<tbody>
<tr>
<td>控制节点Master1</td>
<td>zhappymaster1</td>
<td>192.168.40.180</td>
<td>apiserver、controller-manager、scheduler、kubelet、etcd、docker、kube-proxy、keepalived、nginx、calico</td>
</tr>
<tr>
<td>控制节点Master2</td>
<td>zhappymaster2</td>
<td>192.168.40.181</td>
<td>apiserver、controller-manager、scheduler、kubelet、etcd、docker、kube-proxy、keepalived、nginx、calico</td>
</tr>
<tr>
<td>工作节点Node1</td>
<td>zhappynode1</td>
<td>192.168.40.182</td>
<td>kubelet、kube-proxy、docker、calico、coredns</td>
</tr>
</tbody>
</table>
<h3>3. 系统环境要求</h3>
<ul>
<li>
<p>操作系统：CentOS 7.6 / 7.9</p>
</li>
<li>
<p>硬件配置：4GiB内存 / 4vCPU / 60G硬盘</p>
</li>
<li>
<p>网络：NAT模式，虚拟机开启CPU虚拟化支持</p>
</li>
</ul>
<h3>4. kubeadm vs 二进制安装对比</h3>
<table>
<thead>
<tr>
<th>部署方式</th>
<th>核心特点</th>
<th>适用场景</th>
</tr>
</thead>
<tbody>
<tr>
<td>kubeadm</td>
<td>官方自动化工具，组件以Pod运行具备故障自愈能力；部署快捷，屏蔽底层细节，排障门槛稍高</td>
<td>高频部署、自动化要求高的生产环境</td>
</tr>
<tr>
<td>二进制</td>
<td>手动逐组件部署，对K8s架构理解更深入，排障清晰；部署流程繁琐</td>
<td>定制化需求高、希望深度掌握原理的场景</td>
</tr>
</tbody>
</table>
<blockquote>
<p>两种方式生产环境运行均稳定可靠，可根据团队技术栈与运维能力选择。</p>
</blockquote>
<hr />
<h2>二、集群环境初始化（所有节点执行）</h2>
<h3>1. 配置静态IP</h3>
<p>修改网卡配置（网卡名以实际为准，示例为<code>ens33</code>）：</p>
<pre><code class="language-Bash">vim /etc/sysconfig/network-scripts/ifcfg-ens33</code></pre>
<p>核心配置：</p>
<pre><code class="language-Plaintext">BOOTPROTO=static
IPADDR=192.168.40.180   # 替换为对应节点IP
NETMASK=255.255.255.0
GATEWAY=192.168.40.2
DNS1=192.168.40.2
ONBOOT=yes
NAME=ens33
DEVICE=ens33</code></pre>
<p>重启网络生效：</p>
<pre><code class="language-Bash">service network restart</code></pre>
<h3>2. 关闭SELinux</h3>
<pre><code class="language-Bash"># 临时关闭
setenforce 0
# 永久关闭，重启后生效
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
# 验证状态，输出 Disabled 即为成功
getenforce</code></pre>
<h3>3. 设置主机名</h3>
<p>分别在对应节点执行：</p>
<pre><code class="language-Bash"># Master1执行
hostnamectl set-hostname zhappymaster1 &amp;&amp; bash

# Master2执行
hostnamectl set-hostname zhappymaster2 &amp;&amp; bash

# Node1执行
hostnamectl set-hostname zhappynode1 &amp;&amp; bash</code></pre>
<blockquote>
<p>可选操作：执行 <code>yum update -y</code> 将系统从CentOS7.6升级至7.9。</p>
</blockquote>
<h3>4. 配置主机名解析</h3>
<p>所有节点的<code>/etc/hosts</code>添加节点映射：</p>
<pre><code class="language-Bash">cat &gt;&gt; /etc/hosts &lt;&lt;EOF
192.168.40.180   zhappymaster1
192.168.40.181   zhappymaster2
192.168.40.182   zhappynode1
EOF</code></pre>
<h3>5. 配置节点间SSH免密登录</h3>
<p>分别在三个节点生成密钥并分发至所有节点：</p>
<pre><code class="language-Bash"># 生成密钥，一路回车即可
ssh-keygen

# 分发公钥，按提示输入yes与密码
ssh-copy-id zhappymaster1
ssh-copy-id zhappymaster2
ssh-copy-id zhappynode1</code></pre>
<h3>6. 关闭Swap交换分区</h3>
<p>K8s默认禁用Swap以保证性能，未关闭会导致初始化失败。</p>
<pre><code class="language-Bash"># 临时关闭
swapoff -a

# 永久关闭：注释fstab中swap挂载行
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab</code></pre>
<blockquote>
<p>说明：若必须保留Swap，可在kubeadm命令后追加<code>--ignore-preflight-errors=Swap</code>跳过检测。</p>
</blockquote>
<h3>7. 配置内核网络参数</h3>
<p>加载桥接模块，开启IP转发与网桥iptables支持：</p>
<pre><code class="language-Bash"># 加载br_netfilter内核模块
modprobe br_netfilter
echo "modprobe br_netfilter" &gt;&gt; /etc/profile

# 写入内核配置
cat &gt; /etc/sysctl.d/k8s.conf &lt;&lt;EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

# 生效配置
sysctl -p /etc/sysctl.d/k8s.conf</code></pre>
<blockquote>
<p>参数作用：</p>
</blockquote>
<ul>
<li>
<p><code>bridge-nf-call-iptables</code>：让网桥流量经过iptables链，是容器网络插件的基础依赖</p>
</li>
<li>
<p><code>ip_forward</code>：开启IP数据包转发，实现跨节点容器网络互通</p>
</li>
</ul>
<h3>8. 关闭firewalld防火墙</h3>
<pre><code class="language-Bash">systemctl stop firewalld
systemctl disable firewalld</code></pre>
<h3>9. 配置软件源</h3>
<ol>
<li>
<p>备份原有YUM源，替换为阿里云CentOS基础源+epel源</p>
</li>
<li>
<p>添加Docker阿里云YUM源：</p>
</li>
</ol>
<pre><code class="language-Bash">yum install yum-utils -y
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo</code></pre>
<h3>10. 配置K8s阿里云YUM源</h3>
<p>在Master1创建源文件，再分发到其他节点：</p>
<pre><code class="language-Bash">cat &gt; /etc/yum.repos.d/kubernetes.repo &lt;&lt;EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
EOF

# 分发至另外两个节点
scp /etc/yum.repos.d/kubernetes.repo zhappymaster2:/etc/yum.repos.d/
scp /etc/yum.repos.d/kubernetes.repo zhappynode1:/etc/yum.repos.d/</code></pre>
<h3>11. 配置时间同步</h3>
<pre><code class="language-Bash"># 安装同步工具
yum install ntpdate -y
# 立即同步时间
ntpdate cn.pool.ntp.org

# 添加定时任务，每小时同步一次
crontab -e
# 写入以下内容
* */1 * * * /usr/sbin/ntpdate cn.pool.ntp.org

# 重启定时任务
service crond restart</code></pre>
<h3>12. 安装基础依赖包</h3>
<pre><code class="language-Bash">yum install -y yum-utils device-mapper-persistent-data lvm2 wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo ntp libaio-devel vim ncurses-devel autoconf automake zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack ntpdate telnet</code></pre>
<hr />
<h2>三、安装Docker服务（所有节点执行）</h2>
<h3>1. 安装指定版本Docker</h3>
<pre><code class="language-Bash">yum install docker-ce-20.10.6 docker-ce-cli-20.10.6 containerd.io -y</code></pre>
<h3>2. 启动并设置开机自启</h3>
<pre><code class="language-Bash">systemctl start docker
systemctl enable docker
systemctl status docker</code></pre>
<h3>3. 配置镜像加速器与Cgroup驱动</h3>
<pre><code class="language-Bash">cat &gt; /etc/docker/daemon.json &lt;&lt;EOF
{
 "registry-mirrors":["https://rsbud4vc.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hub-mirror.c.163.com"],
  "exec-opts": ["native.cgroupdriver=systemd"]
}
EOF</code></pre>
<blockquote>
<p><strong>重要</strong>：Kubelet默认使用<code>systemd</code>作为cgroup驱动，Docker默认为<code>cgroupfs</code>，两者必须一致，否则集群启动失败。</p>
</blockquote>
<p>重启Docker生效：</p>
<pre><code class="language-Bash">systemctl daemon-reload
systemctl restart docker</code></pre>
<hr />
<h2>四、安装K8s核心组件（所有节点执行）</h2>
<h3>1. 安装指定版本组件</h3>
<pre><code class="language-Bash">yum install -y kubelet-1.20.6 kubeadm-1.20.6 kubectl-1.20.6</code></pre>
<h3>2. 设置kubelet开机自启</h3>
<pre><code class="language-Bash">systemctl enable kubelet</code></pre>
<blockquote>
<p>组件说明：</p>
</blockquote>
<ul>
<li>
<p><strong>kubeadm</strong>：K8s集群自动化初始化工具</p>
</li>
<li>
<p><strong>kubelet</strong>：运行在所有节点，负责Pod生命周期管理、与APIServer通信</p>
</li>
<li>
<p><strong>kubectl</strong>：K8s命令行客户端，用于集群资源管理与操作</p>
</li>
</ul>
<hr />
<h2>五、Keepalived+Nginx实现APIServer高可用（两个Master节点执行）</h2>
<h3>方案原理</h3>
<ul>
<li>
<p>Nginx做<strong>四层负载均衡</strong>，将请求转发至两台Master的6443端口</p>
</li>
<li>
<p>Keepalived提供虚拟VIP，实现Nginx主备故障自动切换</p>
</li>
<li>
<p>Nginx监听16443端口，避免与宿主机APIServer的6443端口冲突</p>
</li>
</ul>
<h3>1. 安装依赖软件</h3>
<pre><code class="language-Bash">yum install nginx keepalived nginx-mod-stream -y</code></pre>
<h3>2. 配置Nginx四层负载（两个Master配置一致）</h3>
<pre><code class="language-Bash">vim /etc/nginx/nginx.conf</code></pre>
<p>完整配置：</p>
<pre><code class="language-Nginx">user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

# 四层负载：转发APIServer请求
stream {
    log_format  main  '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';
    access_log  /var/log/nginx/k8s-access.log  main;

    upstream k8s-apiserver {
        server 192.168.40.180:6443 weight=5 max_fails=3 fail_timeout=30s;
        server 192.168.40.181:6443 weight=5 max_fails=3 fail_timeout=30s;
    }

    server {
       listen 16443;
       proxy_pass k8s-apiserver;
    }
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    server {
        listen       80 default_server;
        server_name  _;
    }
}</code></pre>
<h3>3. 配置Keepalived</h3>
<h4>（1）Master1（主节点）配置</h4>
<pre><code class="language-Bash">vim /etc/keepalived/keepalived.conf</code></pre>
<pre><code class="language-Plaintext">global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id NGINX_MASTER
}

# Nginx健康检查脚本
vrrp_script check_nginx {
    script "/etc/keepalived/check_nginx.sh"
}

vrrp_instance VI_1 {
    state MASTER
    interface ens33        # 修改为实际网卡名
    virtual_router_id 51   # 主备节点必须一致
    priority 100           # 优先级，主节点高于备节点
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    # 虚拟VIP地址
    virtual_ipaddress {
        192.168.40.199/24
    }
    track_script {
        check_nginx
    }
}</code></pre>
<h4>（2）Master2（备节点）配置</h4>
<pre><code class="language-Bash">vim /etc/keepalived/keepalived.conf</code></pre>
<pre><code class="language-Plaintext">global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id NGINX_BACKUP
}

vrrp_script check_nginx {
    script "/etc/keepalived/check_nginx.sh"
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.40.199/24
    }
    track_script {
        check_nginx
    }
}</code></pre>
<h3>4. 创建Nginx健康检查脚本（两个Master都配置）</h3>
<pre><code class="language-Bash">vim /etc/keepalived/check_nginx.sh</code></pre>
<pre><code class="language-Bash">#!/bin/bash
# 检测Nginx进程是否存活
counter=$(ps -ef |grep nginx | grep sbin | egrep -cv "grep|$$" )
if [ $counter -eq 0 ]; then
    # 尝试启动Nginx
    service nginx start
    sleep 2
    counter=$(ps -ef |grep nginx | grep sbin | egrep -cv "grep|$$" )
    # 启动失败则停止Keepalived，触发VIP漂移
    if [ $counter -eq 0 ]; then
        service keepalived stop
    fi
fi</code></pre>
<p>授权可执行：</p>
<pre><code class="language-Bash">chmod +x /etc/keepalived/check_nginx.sh</code></pre>
<h3>5. 启动服务</h3>
<pre><code class="language-Bash">systemctl daemon-reload
systemctl start nginx
systemctl start keepalived
systemctl enable nginx keepalived</code></pre>
<h3>6. 验证VIP与故障切换</h3>
<ol>
<li>查看VIP是否绑定在Master1：</li>
</ol>
<pre><code class="language-Bash">ip addr
# ens33网卡下出现 192.168.40.199 即为成功</code></pre>
<ol start="2">
<li>故障切换测试：停止Master1的keepalived，观察VIP漂移至Master2</li>
</ol>
<pre><code class="language-Bash"># Master1执行
service keepalived stop

# Master2查看
ip addr</code></pre>
<ol start="3">
<li>恢复Master1服务，VIP自动漂移回主节点</li>
</ol>
<pre><code class="language-Bash">systemctl start keepalived</code></pre>
<hr />
<h2>六、kubeadm初始化K8s集群（Master1执行）</h2>
<h3>1. 导入离线镜像（所有节点）</h3>
<p>提前将<code>k8simage-1-20-6.tar.gz</code>上传至所有节点，导入镜像：</p>
<pre><code class="language-Bash">docker load -i k8simage-1-20-6.tar.gz</code></pre>
<h3>2. 编写初始化配置文件</h3>
<pre><code class="language-Bash">cd /root/
vim kubeadm-config.yaml</code></pre>
<p>配置内容：</p>
<pre><code class="language-YAML">apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.20.6
controlPlaneEndpoint: 192.168.40.199:16443  # 高可用VIP入口
imageRepository: registry.aliyuncs.com/google_containers
apiServer:
  certSANs:
  - 192.168.40.180
  - 192.168.40.181
  - 192.168.40.182
  - 192.168.40.199
networking:
  podSubnet: 10.244.0.0/16
  serviceSubnet: 10.96.0.0/16
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind:  KubeProxyConfiguration
mode: ipvs</code></pre>
<blockquote>
<p>说明：</p>
</blockquote>
<ul>
<li>
<p><code>controlPlaneEndpoint</code>：所有节点统一通过VIP访问APIServer</p>
</li>
<li>
<p><code>certSANs</code>：APIServer证书信任的IP列表</p>
</li>
<li>
<p><code>mode: ipvs</code>：kube-proxy采用IPVS模式，性能远高于默认iptables，生产环境推荐</p>
</li>
</ul>
<h3>3. 执行集群初始化</h3>
<pre><code class="language-Bash">kubeadm init --config kubeadm-config.yaml --ignore-preflight-errors=SystemVerification</code></pre>
<p>初始化成功后会输出<strong>Master节点加入命令</strong>和<strong>Worker节点加入命令</strong>，请务必保存好token和hash值。</p>
<h3>4. 配置kubectl管理员权限</h3>
<pre><code class="language-Bash">mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config</code></pre>
<h3>5. 查看节点初始状态</h3>
<pre><code class="language-Bash">kubectl get nodes</code></pre>
<p>此时节点状态为<code>NotReady</code>属于正常现象，原因是尚未安装网络插件。</p>
<hr />
<h2>七、扩容集群节点</h2>
<h3>1. 添加第二个Master控制节点</h3>
<h4>（1）拷贝集群证书到Master2</h4>
<p>Master1执行，将证书分发至Master2：</p>
<pre><code class="language-Bash"># 先在Master2创建目录
ssh zhappymaster2 "mkdir -p /etc/kubernetes/pki/etcd &amp;&amp; mkdir -p ~/.kube/"

# 批量拷贝证书
scp /etc/kubernetes/pki/ca.crt zhappymaster2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/ca.key zhappymaster2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.key zhappymaster2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/sa.pub zhappymaster2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.crt zhappymaster2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/front-proxy-ca.key zhappymaster2:/etc/kubernetes/pki/
scp /etc/kubernetes/pki/etcd/ca.crt zhappymaster2:/etc/kubernetes/pki/etcd/
scp /etc/kubernetes/pki/etcd/ca.key zhappymaster2:/etc/kubernetes/pki/etcd/</code></pre>
<h4>（2）生成节点加入命令（Master1执行）</h4>
<pre><code class="language-Bash">kubeadm token create --print-join-command</code></pre>
<h4>（3）Master2执行加入命令</h4>
<p>在join命令后追加<code>--control-plane</code>表示加入控制平面：</p>
<pre><code class="language-Bash">kubeadm join 192.168.40.199:16443 --token 你的token值 \
    --discovery-token-ca-cert-hash sha256:你的hash值 \
    --control-plane --ignore-preflight-errors=SystemVerification</code></pre>
<h3>2. 添加Worker工作节点</h3>
<h4>（1）生成加入命令（Master1执行）</h4>
<pre><code class="language-Bash">kubeadm token create --print-join-command</code></pre>
<h4>（2）Node1执行加入</h4>
<pre><code class="language-Bash">kubeadm join 192.168.40.199:16443 --token 你的token值 \
    --discovery-token-ca-cert-hash sha256:你的hash值 \
    --ignore-preflight-errors=SystemVerification</code></pre>
<h4>（3）给Worker节点打角色标签</h4>
<pre><code class="language-Bash">kubectl label node zhappynode1 node-role.kubernetes.io/worker=worker</code></pre>
<hr />
<h2>八、安装Calico网络插件（Master1执行）</h2>
<h3>1. 部署Calico</h3>
<p>上传<code>calico.yaml</code>文件，或在线下载：</p>
<pre><code class="language-Bash"># 在线下载（可选）
# wget https://docs.projectcalico.org/manifests/calico.yaml

kubectl apply -f calico.yaml</code></pre>
<h3>2. 验证Pod状态</h3>
<pre><code class="language-Bash">kubectl get pods -n kube-system</code></pre>
<p>等待所有calico相关Pod变为<code>Running</code>，CoreDNS也会从<code>Pending</code>转为正常运行。</p>
<h3>3. 验证节点状态</h3>
<pre><code class="language-Bash">kubectl get nodes</code></pre>
<p>所有节点STATUS变为<code>Ready</code>，说明集群网络正常。</p>
<hr />
<h2>九、集群功能验证</h2>
<h3>1. 验证Pod外网访问能力</h3>
<p>导入busybox测试镜像（node节点）：</p>
<pre><code class="language-Bash">docker load -i busybox-1-28.tar.gz</code></pre>
<p>启动临时测试Pod（master节点）：</p>
<pre><code class="language-Bash">kubectl run busybox --image busybox:1.28 --restart=Never --rm -it -- sh</code></pre>
<p>容器内执行ping测试：</p>
<pre><code class="language-Bash">ping www.baidu.com</code></pre>
<p>能正常通说明容器外网网络正常。</p>
<h3>2. 验证CoreDNS域名解析</h3>
<p>在busybox容器内执行：</p>
<pre><code class="language-Bash">nslookup kubernetes.default.svc.cluster.local</code></pre>
<p>能正常解析出Service IP则集群DNS服务正常。</p>
<blockquote>
<p>注意：必须使用busybox 1.28版本，高版本存在nslookup解析异常问题。</p>
</blockquote>
<hr />
<h2>十、延长K8s证书有效期</h2>
<p>kubeadm默认签发的APIServer组件证书有效期为1年，CA根证书为10年，可通过脚本将组件证书延长至10年。</p>
<h3>1. 查看证书有效期</h3>
<pre><code class="language-Bash"># 查看CA根证书有效期
openssl x509 -in /etc/kubernetes/pki/ca.crt -noout -text | grep Not

# 查看APIServer证书有效期
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text | grep Not</code></pre>
<h3>2. 执行续期脚本（两个Master节点都执行）</h3>
<p>上传<code>update-kubeadm-cert.sh</code>脚本至两个Master节点：</p>
<pre><code class="language-Bash"># 授权可执行
chmod +x update-kubeadm-cert.sh

# 执行全量证书续期，延长至10年
./update-kubeadm-cert.sh all</code></pre>
<h3>3. 验证续期结果</h3>
<pre><code class="language-Bash">openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text | grep Not</code></pre>
<p>有效期变为10年即为操作成功。</p>]]></description>
    <pubDate>Thu, 18 Jun 2026 16:37:29 +0800</pubDate>
    <dc:creator>ZHappy</dc:creator>
    <guid>https://blog.zhappy.vip/?post=21</guid>
</item>
<item>
    <title>04-Docker资源配额及私有镜像仓库</title>
    <link>https://blog.zhappy.vip/?post=20</link>
    <description><![CDATA[<h2>一、Docker 资源配额（Cgroup 资源限制）</h2>
<p>Docker 基于 Linux <strong>Cgroup</strong> 机制实现容器资源管控，可限制 CPU、内存、磁盘 IO 三类核心资源，避免单容器占用过多宿主机资源。</p>
<h3>1. CPU 资源控制</h3>
<h4>1.1 CPU 份额权重（--cpu-shares /-c）</h4>
<ul>
<li>
<p><strong>作用</strong>：设置 CPU 相对加权值，默认所有容器份额为 <code>1024</code>，仅在<strong>多个容器争抢同一 CPU 核心</strong>时生效。</p>
</li>
<li>
<p><strong>特点</strong>：不是固定分配多少 GHz CPU，而是相对优先级。CPU 空闲时，低权重容器也能占用全部 CPU 资源。</p>
</li>
</ul>
<p>示例：创建 512 权重的容器</p>
<pre><code class="language-bash"># 查看参数帮助
docker run --help | grep cpu-shares

# 创建指定CPU份额的容器
docker run -it --cpu-shares 512 centos /bin/bash

# 容器内查看生效的配置
cat /sys/fs/cgroup/cpu/cpu.shares
# 输出：512</code></pre>
<p><strong>权重规则说明</strong>：</p>
<ul>
<li>
<p>容器 A（1024）、容器 B（512）争抢同核心 CPU 时，A 获得的 CPU 时间片约为 B 的 2 倍。</p>
</li>
<li>
<p>若只有一个容器运行，即使权重很低，也会独占全部 CPU 资源。</p>
</li>
</ul>
<h4>1.2 CPU 核心绑定（--cpuset-cpus）</h4>
<ul>
<li>
<p><strong>作用</strong>：强制容器只能运行在指定的 CPU 核心上，适合 NUMA 架构服务器做性能优化。</p>
</li>
<li>
<p>配套参数 <code>--cpuset-mems</code> 可绑定内存节点，仅多内存节点服务器有明显效果。</p>
</li>
</ul>
<p>示例：容器只能使用 0 号和 1 号 CPU 核心</p>
<pre><code class="language-bash">docker run -itd --name test-cpu --cpuset-cpus 0,1 centos /bin/bash</code></pre>
<blockquote>
<p>扩展：服务器三大架构</p>
<ol>
<li>
<p><strong>SMP（对称多处理器）</strong>：普通双路 x86 服务器，多 CPU 共享内存</p>
</li>
<li>
<p><strong>NUMA（非一致存储访问）</strong>：IBM 小型机等，每个 CPU 有独立内存节点</p>
</li>
<li>
<p><strong>MPP（海量并行处理）</strong>：大型机，多节点分布式并行计算</p>
</li>
</ol>
</blockquote>
<h4>1.3 CPU 配额混合验证（stress 压测）</h4>
<p>通过压力测试工具 <code>stress</code> 跑满 CPU，验证权重和核心绑定是否生效。</p>
<h5>（1）安装 stress 工具</h5>
<pre><code class="language-bash">yum install -y epel-release
yum install stress -y</code></pre>
<p>stress 核心参数：</p>
<ul>
<li>
<p><code>-c n</code>：生成 n 个进程，持续计算随机数平方根，占满 CPU</p>
</li>
<li>
<p><code>-i n</code>：生成 n 个进程，调用 sync 刷盘，测试磁盘 IO</p>
</li>
<li>
<p><code>-m n</code>：生成 n 个进程，持续申请 / 释放内存，测试内存</p>
</li>
<li>
<p><code>-t 时间</code>：运行指定时长后自动停止</p>
</li>
</ul>
<h5>（2）实验：验证 CPU 份额 + 核心绑定效果</h5>
<p>实验目标：两个容器都绑定 CPU0、CPU1，权重分别为 512 和 1024，验证 CPU 占用比例。</p>
<ol>
<li>启动两个测试容器</li>
</ol>
<pre><code class="language-bash"># 容器docker10：绑定0、1核心，权重512
docker run -itd --name docker10 --cpuset-cpus 0,1 --cpu-shares 512 centos /bin/bash

# 容器docker20：绑定0、1核心，权重1024
docker run -itd --name docker20 --cpuset-cpus 0,1 --cpu-shares 1024 centos /bin/bash</code></pre>
<ol start="2">
<li>两个容器内分别安装 stress 并跑满 CPU</li>
</ol>
<pre><code class="language-bash"># 进入docker10
docker exec -it docker10 /bin/bash
yum install -y epel-release &amp;&amp; yum install stress -y
# 启动2个进程，跑10分钟
stress -c 2 -v -t 10m

# 进入docker20，执行相同操作
docker exec -it docker20 /bin/bash
yum install -y epel-release &amp;&amp; yum install stress -y
stress -c 2 -v -t 10m</code></pre>
<ol start="3">
<li>宿主机执行 <code>top</code> 按 <code>1</code> 查看各核心占用</li>
</ol>
<ul>
<li>
<p>预期 1：仅 CPU0、CPU1 被占满，其他核心空闲 → 核心绑定生效</p>
</li>
<li>
<p>预期 2：docker20 的 CPU 占用约为 docker10 的 2 倍 → 权重限制生效</p>
</li>
</ul>
<h3>2. 内存资源控制（-m /--memory）</h3>
<ul>
<li><strong>作用</strong>：限制容器最大可使用内存，超出可能触发 OOM（内存溢出）被系统杀掉。</li>
</ul>
<p>示例 1：限制容器最大内存 128M</p>
<pre><code class="language-bash">docker run -it -m 128m centos /bin/bash

# 容器内验证限制
cat /sys/fs/cgroup/memory/memory.limit_in_bytes
# 输出：134217728（对应128MB）</code></pre>
<p>示例 2：同时限制 CPU 核心 + 内存</p>
<pre><code class="language-bash">docker run -it --cpuset-cpus 0,1 -m 128m centos</code></pre>
<h3>3. 磁盘 IO 资源控制</h3>
<ul>
<li>
<p><strong>作用</strong>：限制容器对磁盘的读写速度，防止单容器吃光磁盘 IO 影响其他服务。</p>
</li>
<li>
<p>核心参数：</p>
<ul>
<li>
<p><code>--device-read-bps</code>：限制磁盘读速度，单位 kb/mb/gb</p>
</li>
<li>
<p><code>--device-write-bps</code>：限制磁盘写速度，单位 kb/mb/gb</p>
</li>
</ul>
</li>
</ul>
<p>示例：限制容器对 /dev/sda 磁盘写入速度最高 2MB/s</p>
<pre><code class="language-bash"># 启动容器，挂载磁盘设备并限制写速度
docker run -it -v /var/www/html/:/var/www/html \
  --device /dev/sda:/dev/sda \
  --device-write-bps /dev/sda:2mb centos /bin/bash

# 容器内用dd命令测试写速度
time dd if=/dev/sda of=/var/www/html/test.out bs=2M count=50 oflag=direct,nonblock</code></pre>
<blockquote>
<p>dd 参数说明：<code>direct</code> 跳过缓存直接写盘，<code>nonblock</code> 非阻塞 IO，确保测速准确<br />
预期结果：写入速度稳定在 2MB/s 左右，限制生效</p>
</blockquote>
<h3>4. 容器运行结束自动释放（--rm）</h3>
<ul>
<li><strong>作用</strong>：容器执行完命令后自动删除，释放资源，适合一次性临时任务。</li>
</ul>
<p>示例：容器执行 sleep 6 秒后自动删除</p>
<pre><code class="language-bash">docker run -it --rm --name zhappy centos sleep 6

# 6秒后查看，容器已自动消失
docker ps -a | grep zhappy</code></pre>
<h2>二、Harbor 私有镜像仓库</h2>
<h3>1. Harbor 介绍</h3>
<p>Harbor 是 VMware 开源的企业级 Docker 镜像仓库，相比官方公共仓库，更适合企业内网使用，核心能力：</p>
<ul>
<li>
<p>RBAC 角色权限管理、LDAP 集成</p>
</li>
<li>
<p>镜像复制、漏洞扫描、日志审计</p>
</li>
<li>
<p>中文 Web 管理界面、镜像签名等</p>
</li>
</ul>
<p>官网地址：<a href="https://github.com/goharbor/harbor">https://github.com/goharbor/harbor</a></p>
<p><strong>实验环境</strong>：</p>
<ul>
<li>
<p>主机名：<code>harbor</code></p>
</li>
<li>
<p>IP：<code>192.168.40.181</code></p>
</li>
<li>
<p>配置建议：4vCPU / 4G 内存 / 100G 硬盘</p>
</li>
</ul>
<h3>2. 自签发 HTTPS 证书</h3>
<p>Harbor 默认推荐 HTTPS 访问，先生成自签证书。</p>
<pre><code class="language-bash"># 设置主机名
hostnamectl set-hostname harbor &amp;&amp; bash

# 创建证书目录
mkdir -p /data/ssl &amp;&amp; cd /data/ssl</code></pre>
<h4>步骤 1：生成 CA 根证书</h4>
<pre><code class="language-bash"># 生成CA私钥
openssl genrsa -out ca.key 3072

# 生成CA根证书，有效期10年
openssl req -new -x509 -days 3650 -key ca.key -out ca.pem
# 按提示填写国家、省份、城市等信息即可</code></pre>
<h4>步骤 2：生成 Harbor 域名证书</h4>
<pre><code class="language-bash"># 生成harbor域名私钥
openssl genrsa -out harbor.key 3072

# 生成证书签发请求
openssl req -new -key harbor.key -out harbor.csr
# Common Name 必须填 harbor（和主机名、配置一致）</code></pre>
<h4>步骤 3：用 CA 签发 harbor 证书</h4>
<pre><code class="language-bash">openssl x509 -req -in harbor.csr -CA ca.pem -CAkey ca.key \
  -CAcreateserial -out harbor.pem -days 3650</code></pre>
<h3>3. 宿主机 Docker 环境安装</h3>
<p>和常规 Docker 安装步骤一致，简要流程：</p>
<ol>
<li>
<p>关闭 firewalld、iptables、SELinux</p>
</li>
<li>
<p>配置时间同步、安装基础依赖包</p>
</li>
<li>
<p>安装 docker-ce、启动并设置开机自启</p>
</li>
<li>
<p>开启内核桥接转发参数</p>
</li>
<li>
<p>配置镜像加速器并重启 Docker</p>
</li>
</ol>
<blockquote>
<p>详细安装命令可参考 Docker 入门文档，此处不再重复。</p>
</blockquote>
<h3>4. 安装 Harbor</h3>
<h4>步骤 1：准备安装包</h4>
<ol>
<li>
<p>上传 <code>harbor-offline-installer-v2.3.0-rc3.tgz</code> 离线安装包</p>
</li>
<li>
<p>上传 <code>docker-compose</code> 二进制文件</p>
</li>
</ol>
<pre><code class="language-bash"># 创建安装目录
mkdir -p /data/install &amp;&amp; cd /data/install

# 解压安装包
tar zxvf harbor-offline-installer-v2.3.0-rc3.tgz
cd harbor</code></pre>
<h4>步骤 2：安装 docker-compose</h4>
<pre><code class="language-bash"># 将二进制文件移动到系统路径并授权
mv docker-compose-Linux-x86_64 /usr/bin/docker-compose
chmod +x /usr/bin/docker-compose</code></pre>
<blockquote>
<p>docker-compose 是 Docker 官方容器编排工具，可批量管理多个关联容器，Harbor 依赖它启动多组件。</p>
</blockquote>
<h4>步骤 3：修改 Harbor 配置文件</h4>
<pre><code class="language-bash"># 复制配置模板
cp harbor.yml.tmpl harbor.yml
vim harbor.yml</code></pre>
<p>核心修改项：</p>
<pre><code class="language-yaml"># 主机名，和证书域名一致
hostname: harbor

# HTTPS证书路径
certificate: /data/ssl/harbor.pem
private_key: /data/ssl/harbor.key</code></pre>
<blockquote>
<p>默认管理员账号：<code>admin</code>，默认密码：<code>Harbor12345</code></p>
</blockquote>
<h4>步骤 4：加载镜像并执行安装</h4>
<pre><code class="language-bash"># 加载harbor离线镜像包
docker load -i docker-harbor-2-3-0.tar.gz

# 执行安装脚本
./install.sh</code></pre>
<p>出现 <code>Harbor has been installed and started successfully.</code> 即安装成功。</p>
<h4>Harbor 启停命令</h4>
<pre><code class="language-bash">cd /data/install/harbor
# 停止
docker-compose stop
# 启动
docker-compose start</code></pre>
<h3>5. Web 界面使用说明</h3>
<ol>
<li>
<p>本地电脑配置 hosts 解析：<code>192.168.40.181 harbor</code></p>
</li>
<li>
<p>浏览器访问 <code>https://harbor</code>，接受自签证书风险</p>
</li>
<li>
<p>使用 <code>admin / Harbor12345</code> 登录</p>
</li>
</ol>
<p><strong>基础操作</strong>：</p>
<ul>
<li>
<p>默认公共项目 <code>library</code>，存放基础镜像</p>
</li>
<li>
<p>「新建项目」→ 输入项目名 → 勾选「公开」→ 确定，即可创建可公开拉取的镜像仓库</p>
</li>
</ul>
<h3>6. 客户端上传镜像到 Harbor</h3>
<h4>步骤 1：客户端 Docker 配置信任 Harbor</h4>
<pre><code class="language-bash">vim /etc/docker/daemon.json</code></pre>
<p>添加 <code>insecure-registries</code> 配置：</p>
<pre><code class="language-json">{
  "registry-mirrors": ["https://rsbud4vc.mirror.aliyuncs.com"],
  "insecure-registries": ["192.168.40.181","harbor"]
}</code></pre>
<p>重启 Docker 生效：</p>
<pre><code class="language-bash">systemctl daemon-reload &amp;&amp; systemctl restart docker</code></pre>
<h4>步骤 2：登录 Harbor</h4>
<pre><code class="language-bash">docker login 192.168.40.181
# 输入账号 admin 密码 Harbor12345
# 出现 Login Succeeded 即登录成功</code></pre>
<h4>步骤 3：镜像打标签并上传</h4>
<pre><code class="language-bash"># 1. 准备本地镜像（例：tomcat）
docker load -i tomcat.tar.gz

# 2. 给镜像打标签，格式：仓库地址/项目名/镜像名:版本
docker tag tomcat:latest 192.168.40.181/test/tomcat:v1

# 3. 推送到Harbor
docker push 192.168.40.181/test/tomcat:v1</code></pre>
<p>推送完成后，可在 Web 界面 test 项目中看到镜像。</p>
<h3>7. 从 Harbor 下载镜像</h3>
<pre><code class="language-bash"># 删除本地镜像
docker rmi -f 192.168.40.181/test/tomcat:v1

# 从Harbor拉取
docker pull 192.168.40.181/test/tomcat:v1</code></pre>]]></description>
    <pubDate>Thu, 18 Jun 2026 11:03:07 +0800</pubDate>
    <dc:creator>ZHappy</dc:creator>
    <guid>https://blog.zhappy.vip/?post=20</guid>
</item>
<item>
    <title>03-Docker数据持久化及网络模式介绍</title>
    <link>https://blog.zhappy.vip/?post=19</link>
    <description><![CDATA[<h2>一、Docker 容器数据管理（数据卷 Volume）</h2>
<h3>1. 什么是数据卷</h3>
<p>数据卷是宿主机上特殊目录，绕过镜像联合文件系统（UFS），用于容器<strong>永久持久化存储</strong>。</p>
<ul>
<li>
<p>生命周期独立于容器：删除容器不会自动删除数据卷</p>
</li>
<li>
<p>支持多个容器同时挂载、共享同一份数据</p>
</li>
</ul>
<h3>2. 数据卷五大核心特点</h3>
<ol>
<li>
<p>容器初始化挂载时，镜像挂载点原有数据会自动复制到数据卷</p>
</li>
<li>
<p>多容器可共享、复用同一个数据卷</p>
</li>
<li>
<p>宿主机 / 容器内可直接修改卷内文件</p>
</li>
<li>
<p>数据卷修改不会更新镜像本身</p>
</li>
<li>
<p>容器删除，数据卷依然保留，不会丢失数据</p>
</li>
</ol>
<h3>3. 数据卷基础使用方式</h3>
<h4>方式 1：run 命令直接挂载宿主机目录（-v）</h4>
<p>语法：<code>docker run -v 宿主机目录:容器内目录 镜像名</code></p>
<pre><code class="language-bash"># 后台启动容器，挂载宿主机 ~/datavolume 到容器 /data
docker run --name volume -v ~/datavolume:/data -itd centos /bin/bash</code></pre>
<p>效果：宿主机目录与容器目录文件双向实时同步。</p>
<h4>只读挂载（:ro）</h4>
<p>容器内仅可读，仅宿主机可修改文件</p>
<pre><code class="language-bash">docker run --name volume1 -v ~/datavolume1:/data:ro -itd centos /bin/bash</code></pre>
<h4>方式 2：Dockerfile 声明匿名数据卷 VOLUME</h4>
<p>Dockerfile 指令 <code>VOLUME ["目录1","目录2"]</code>，构建镜像时定义挂载点，启动容器自动生成匿名卷。</p>
<ol>
<li>编写 Dockerfile</li>
</ol>
<pre><code class="language-dockerfile">FROM centos
# 声明两个数据卷目录
VOLUME ["/datavolume3","/datavolume6"]
CMD /bin/bash</code></pre>
<ol start="2">
<li>构建镜像</li>
</ol>
<pre><code class="language-bash">docker build -t="volume" .</code></pre>
<ol start="3">
<li>启动容器</li>
</ol>
<pre><code class="language-bash">docker run --name volume-dubble -it volume</code></pre>
<p>容器内自动生成 <code>/datavolume3</code>、<code>/datavolume6</code> 两个持久化目录。</p>
<h2>二、数据卷容器（多容器共享数据）</h2>
<h3>1. 概念</h3>
<p>专门挂载数据卷的容器称为<strong>数据卷容器</strong>，其他容器通过 <code>--volumes-from</code> 挂载该容器，实现多容器数据共享。</p>
<h3>2. 实操示例</h3>
<ol>
<li>启动数据卷容器（基于上面带 VOLUME 的 volume 镜像）</li>
</ol>
<pre><code class="language-bash">docker run --name data-volume -itd volume
# 进入容器创建测试文件
docker exec -it data-volume /bin/bash
touch /datavolume6/lucky.txt
exit</code></pre>
<ol start="2">
<li>新容器挂载数据卷容器，共享数据</li>
</ol>
<pre><code class="language-bash"># --volumes-from 指定要共享的容器名称
docker run --name data-volume2 --volumes-from data-volume -itd centos /bin/bash</code></pre>
<ol start="3">
<li>验证共享</li>
</ol>
<pre><code class="language-bash">docker exec -it data-volume2 /bin/bash
cd /datavolume6
# 可查看到上一个容器创建的 lucky.txt
ls</code></pre>
<h2>三、数据卷备份与还原</h2>
<h3>1. 数据卷备份</h3>
<p>原理：临时容器同时挂载数据卷容器 + 宿主机备份目录，使用 tar 打包卷内文件到宿主机。<br />
语法：</p>
<pre><code class="language-bash">docker run --volumes-from 数据卷容器名 -v 宿主机备份目录:/backup 镜像 tar czvf /backup/压缩包名 容器卷目录</code></pre>
<p>示例：</p>
<pre><code class="language-bash">docker run --volumes-from data-volume2 -v /root/backup:/backup --name datavolume-copy centos tar zcvf /backup/data-volume2.tar.gz /datavolume6</code></pre>
<p>执行后宿主机 <code>/root/backup</code> 生成备份压缩包。</p>
<h3>2. 数据卷还原</h3>
<ol>
<li>先删除容器内测试文件模拟数据丢失</li>
</ol>
<pre><code class="language-bash">docker exec -it data-volume2 /bin/bash
rm -rf /datavolume6/lucky.txt
exit</code></pre>
<ol start="2">
<li>解压备份文件还原数据</li>
</ol>
<pre><code class="language-bash">docker run --volumes-from data-volume2 -v /root/backup/:/backup centos tar zxvf /backup/data-volume2.tar.gz -C /datavolume6</code></pre>
<ol start="3">
<li>重新进入容器查看，文件恢复</li>
</ol>
<pre><code class="language-bash">docker exec -it data-volume2 /bin/bash
cd /datavolume6
ls</code></pre>
<h2>四、Docker 容器网络基础与互联</h2>
<h3>1. Docker 四大网络模式</h3>
<p>使用 <code>--net</code> 参数指定，四种模式：</p>
<ol>
<li>
<p><code>bridge</code>：网桥模式，<strong>默认网络</strong></p>
</li>
<li>
<p><code>host</code>：宿主机网络模式，共享宿主机网卡</p>
</li>
<li>
<p><code>none</code>：无网络，仅本地回环 lo</p>
</li>
<li>
<p><code>container</code>：共享其他容器网络命名空间</p>
</li>
</ol>
<h3>2. Docker 网络底层基础</h3>
<ol>
<li>
<p><strong>docker0 虚拟网桥</strong><br />
Docker 安装后自动创建，IP 默认 <code>172.17.0.1/16</code>，所有 bridge 模式容器默认接入该网桥。</p>
</li>
<li>
<p><strong>veth 设备对</strong><br />
每启动一个容器生成一对虚拟网卡：一端在容器内 eth0，一端挂载到宿主机 docker0 网桥，实现容器与宿主机互通。</p>
</li>
<li>
<p>网桥管理工具</p>
</li>
</ol>
<pre><code class="language-bash"># 安装网桥工具
yum install bridge-utils -y
# 查看网桥及挂载容器
brctl show</code></pre>
<h3>3. 容器直接互通（通过 IP 访问）</h3>
<h4>前置：构建测试镜像</h4>
<pre><code class="language-bash">cd dockerfile/inter-image
vim dockerfile</code></pre>
<pre><code class="language-dockerfile">FROM centos
RUN rm -rf /etc/yum.repos.d/*
COPY Centos-vault-8.5.2111.repo /etc/yum.repos.d/
RUN yum install wget -y
RUN yum install nginx -y
# RUN sed -i "7s/^/#/g" /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD /bin/bash</code></pre>
<p>构建镜像：</p>
<pre><code class="language-bash">docker build -t="inter-image" .</code></pre>
<h4>实操：IP 互通</h4>
<pre><code class="language-bash"># 启动容器test1
docker run --name test1 -itd inter-image
# 进入容器启动nginx
docker exec -it test1 /bin/bash
/usr/sbin/nginx
exit

# 启动容器test2
docker run --name test2 -itd inter-image

# 进入test2 ping test1容器IP
docker exec -it test2 /bin/bash
ping 172.17.0.20
curl http://172.17.0.20</code></pre>
<p>缺点：容器重启 IP 会变化，无法固定访问地址。</p>
<h3>4. --link 容器别名访问（解决 IP 变动问题）</h3>
<p>语法：<code>--link=容器名:自定义别名</code></p>
<pre><code class="language-bash"># 1. 启动基础容器test3
docker run --name test3 -itd inter-image /bin/bash

# 2. 创建test5，关联test3并设置别名webtest
docker run --name test5 -itd --link=test3:webtest inter-image /bin/bash

# 3. 重启test3，IP会变更
docker restart test3

# 4. 在test5内通过别名访问，不受IP变化影响
docker exec -it test5 /bin/bash
ping webtest</code></pre>
<h2>五、四大网络模式详细讲解</h2>
<h3>1. none 无网络模式</h3>
<p>容器仅拥有本地回环网卡 <code>lo</code>，无外网、无容器互通能力，适合完全隔离场景。</p>
<pre><code class="language-bash"># 创建none模式容器
docker run -itd --name none --net=none --privileged=true centos
# 查看网卡，只有lo
docker exec -it none /bin/bash
ip addr</code></pre>
<h3>2. container 共享容器网络模式</h3>
<p>新容器<strong>复用已有容器的 Network Namespace</strong>，共用 IP、端口，无独立网卡。</p>
<pre><code class="language-bash"># 新容器共享上面none容器的网络
docker run --name container2 --net=container:none -it --privileged=true centos
# 查看网卡，和none容器完全一致，仅lo网卡
docker exec -it container2 /bin/bash
ip addr</code></pre>
<h3>3. bridge 网桥模式（默认）</h3>
<p>Docker 默认网络，容器独立 IP，接入 docker0 网桥，容器间、容器与宿主机可互通，端口映射依赖该模式。</p>
<pre><code class="language-bash"># 默认bridge模式，无需指定--net
docker run --name bridge -it --privileged=true centos bash
# 查看网卡，拥有独立eth0，172.17.x.x网段
ip addr</code></pre>
<h3>4. host 宿主机网络模式</h3>
<p>容器不创建独立虚拟网卡，<strong>直接使用宿主机物理网卡、IP、端口</strong>，性能最高，端口不能重复占用。</p>
<pre><code class="language-bash"># 指定host网络
docker run --name host -it --net=host --privileged=true centos bash
# ip addr查看，网卡和宿主机完全一致
ip addr</code></pre>]]></description>
    <pubDate>Wed, 17 Jun 2026 16:49:46 +0800</pubDate>
    <dc:creator>ZHappy</dc:creator>
    <guid>https://blog.zhappy.vip/?post=19</guid>
</item>
<item>
    <title>02-基于Dockerfile构建企业级生产环境镜像</title>
    <link>https://blog.zhappy.vip/?post=18</link>
    <description><![CDATA[<h2>相关官网地址</h2>
<ul>
<li>
<p>Docker 官网：<a href="https://docs.docker.com/">https://docs.docker.com/</a></p>
</li>
<li>
<p>Docker GitHub：<a href="https://github.com/moby/moby">https://github.com/moby/moby</a></p>
</li>
<li>
<p>Docker Hub 镜像仓库：<a href="https://registry.hub.docker.com">https://registry.hub.docker.com</a></p>
</li>
<li>
<p>DaoCloud 镜像加速器（拉取镜像慢时使用）：<a href="https://dashboard.daocloud.io/mirror">https://dashboard.daocloud.io/mirror</a></p>
</li>
</ul>
<hr />
<h2>一、Dockerfile 语法详解</h2>
<h3>1. 什么是 Dockerfile</h3>
<p>Dockerfile 是<strong>构建镜像的文本指令文件</strong>，通过 <code>docker build</code> 命令读取文件内指令，自动完成镜像构建；可使用 <code>-f</code> 参数指定非默认名称的 Dockerfile 文件。</p>
<h3>2. Dockerfile 构建流程</h3>
<ol>
<li>
<p>基于指定基础镜像启动临时容器</p>
</li>
<li>
<p>逐行执行文件中的指令，修改容器内容</p>
</li>
<li>
<p>提交修改，生成新镜像层</p>
</li>
<li>
<p>基于新镜像再次启动临时容器，执行下一条指令</p>
</li>
<li>
<p>循环执行，直至所有指令运行完毕</p>
</li>
</ol>
<h3>3. 常用指令全解</h3>
<h4>（1）FROM</h4>
<p><strong>作用</strong>：指定<strong>基础镜像</strong>，Dockerfile 第一条指令必须是 <code>FROM</code>，后续所有操作都基于该镜像。</p>
<pre><code class="language-dockerfile">FROM centos</code></pre>
<h4>（2）MAINTAINER</h4>
<p><strong>作用</strong>：标注镜像作者、联系方式等信息。</p>
<pre><code class="language-dockerfile">MAINTAINER ZHappy</code></pre>
<h4>（3）RUN</h4>
<p><strong>作用</strong>：构建镜像过程中执行命令（镜像构建阶段运行），分两种写法：</p>
<ol>
<li>Shell 模式（常用）</li>
</ol>
<pre><code class="language-dockerfile">RUN echo hello</code></pre>
<ol start="2">
<li>Exec 模式</li>
</ol>
<pre><code class="language-dockerfile">RUN ["/bin/bash","-c","echo hello"]</code></pre>
<h4>（4）EXPOSE</h4>
<p><strong>作用</strong>：声明容器对外暴露的端口，<strong>仅为标记，不会自动开启端口映射</strong>。</p>
<ul>
<li>使用 <code>docker run -P</code>（大写 P）时，宿主机将随机映射该端口。</li>
</ul>
<pre><code class="language-dockerfile"># 声明单个端口
EXPOSE 80
# 声明多个端口
EXPOSE 80 8080</code></pre>
<h4>（5）CMD</h4>
<p><strong>作用</strong>：容器启动时默认执行命令（容器运行阶段运行），<code>docker run</code> 后跟指令会<strong>覆盖</strong> <code>CMD</code> 配置。<br />
三种用法：</p>
<pre><code class="language-dockerfile"># Exec 模式（推荐）
CMD ["/usr/sbin/nginx","-g","daemon off;"]
# Shell 模式
CMD echo "start container"
# 作为 ENTRYPOINT 的默认参数
CMD ["param1","param2"]</code></pre>
<p><strong>示例</strong></p>
<pre><code class="language-dockerfile">FROM centos
MAINTAINER ZHappy
RUN yum clean all
RUN yum install nginx -y
EXPOSE 80
CMD ["/usr/sbin/nginx","-g","daemon off;"]</code></pre>
<p>构建 \&amp; 运行：</p>
<pre><code class="language-bash"># 构建镜像
docker build -t="dockerfile/test-cmd:v1" .
# 启动容器，无需重复写启动命令
docker run -p 80 --name cmd_test2 -d dockerfile/test-cmd:v1</code></pre>
<h4>（6）ENTRYPOINT</h4>
<p><strong>作用</strong>：指定容器启动入口命令，和 <code>CMD</code> 类似，但默认<strong>不会被 **</strong><code>docker run</code><strong>** 指令覆盖</strong>；仅使用 <code>--entrypoint</code> 参数时可强制覆盖。</p>
<ul>
<li>可与 <code>CMD</code> 搭配：<code>ENTRYPOINT</code> 写固定命令，<code>CMD</code> 充当动态参数。</li>
</ul>
<p><strong>基础用法</strong></p>
<pre><code class="language-dockerfile"># Exec 模式
ENTRYPOINT ["nginx", "-c"]
# Shell 模式
ENTRYPOINT nginx -g daemon off;</code></pre>
<p><strong>组合用法示例</strong></p>
<pre><code class="language-dockerfile">FROM nginx
ENTRYPOINT ["nginx", "-c"]   # 固定指令
CMD ["/etc/nginx/nginx.conf"] # 默认参数</code></pre>
<p>运行测试：</p>
<pre><code class="language-bash"># 不传参，使用默认参数：nginx -c /etc/nginx/nginx.conf
docker run nginx:test

# 传参，替换默认参数：nginx -c /etc/nginx/new.conf
docker run nginx:test -c /etc/nginx/new.conf</code></pre>
<h4>（7）COPY</h4>
<p><strong>作用</strong>：从<strong>构建上下文目录</strong>复制文件 / 目录到容器内路径，仅做单纯复制，官方推荐日常文件复制使用。</p>
<ul>
<li>目标路径不存在会自动创建；支持通配符；可指定文件属主。</li>
</ul>
<pre><code class="language-dockerfile"># 基础写法
COPY index.html /usr/share/nginx/html/
# 带权限配置
COPY --chown=root:root test.txt /data/
# 通配符
COPY hom* /mydir/</code></pre>
<h4>（8）ADD</h4>
<p><strong>作用</strong>：功能包含 <code>COPY</code>，额外支持<strong>自动解压</strong> <code>gzip/bzip2/xz</code> 格式压缩包。</p>
<ul>
<li>
<p>缺点：不解压场景下无法单纯传输压缩包，容易破坏构建缓存。</p>
</li>
<li>
<p>选型建议：<strong>单纯复制用 COPY，需要解压用 ADD</strong>。</p>
</li>
</ul>
<pre><code class="language-dockerfile"># 自动解压 tar 包到 /usr/local/
ADD apache-tomcat-8.0.26.tar.gz /usr/local/</code></pre>
<h4>（9）VOLUME</h4>
<p><strong>作用</strong>：定义匿名数据卷，用于持久化数据。</p>
<ul>
<li>
<p>防止容器删除 / 重启导致数据丢失；避免容器磁盘持续膨胀。</p>
</li>
<li>
<p>容器运行时可通过 <code>docker run -v</code> 手动挂载覆盖。</p>
</li>
</ul>
<pre><code class="language-dockerfile">VOLUME ["/data", "/logs"]</code></pre>
<h4>（10）WORKDIR</h4>
<p><strong>作用</strong>：指定容器内<strong>工作目录</strong>，后续 <code>RUN/COPY/CMD</code> 等指令都会在该目录下执行。</p>
<ul>
<li>目录会持久存在，建议使用绝对路径。</li>
</ul>
<pre><code class="language-dockerfile">WORKDIR /usr/local/tomcat8</code></pre>
<h4>（11）ENV</h4>
<p><strong>作用</strong>：设置环境变量，构建和运行阶段均可引用。</p>
<pre><code class="language-dockerfile"># 定义变量
ENV NODE_VERSION 6.6.6
# 引用变量
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz"</code></pre>
<h4>（12）USER</h4>
<p><strong>作用</strong>：切换后续指令执行的用户 / 用户组，前提是用户已存在。</p>
<pre><code class="language-dockerfile">USER nginx
USER nginx:nginx</code></pre>
<h4>（13）ONBUILD</h4>
<p><strong>作用</strong>：延迟执行指令（镜像触发器）。</p>
<ul>
<li>当前镜像构建时不生效；<strong>当该镜像被其他镜像用作基础镜像时</strong>，自动触发执行。</li>
</ul>
<p><strong>演示示例</strong></p>
<ol>
<li>编写基础镜像 Dockerfile</li>
</ol>
<pre><code class="language-dockerfile">FROM centos
MAINTAINER ZHappy
RUN yum install nginx -y
# 延迟指令
ONBUILD COPY index.html /usr/share/nginx/html/
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]</code></pre>
<ol start="2">
<li>构建基础镜像</li>
</ol>
<pre><code class="language-bash">docker build -t="onbuild-nginx:v1" .</code></pre>
<ol start="3">
<li>编写新 Dockerfile，基于上述镜像构建</li>
</ol>
<pre><code class="language-dockerfile">FROM onbuild-nginx:v1
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]</code></pre>
<ol start="4">
<li>构建新镜像，此时会自动执行 <code>ONBUILD</code> 内的 COPY 指令</li>
</ol>
<pre><code class="language-bash">docker build -t="onbuild-nginx1" .</code></pre>
<h4>（14）LABEL</h4>
<p><strong>作用</strong>：为镜像添加元数据（标签），键值对格式，用于备注作者、版本、描述等。</p>
<pre><code class="language-dockerfile">LABEL org.opencontainers.image.authors="ZHappy"
LABEL version="v1" description="nginx image"</code></pre>
<h4>（15）HEALTHCHECK</h4>
<p><strong>作用</strong>：容器健康检查，定时检测容器内服务运行状态。</p>
<pre><code class="language-dockerfile"># 自定义命令检查健康状态
HEALTHCHECK CMD curl -f http://localhost/ || exit 1
# 屏蔽基础镜像自带的健康检查
HEALTHCHECK NONE</code></pre>
<h4>（16）ARG</h4>
<p><strong>作用</strong>：构建参数，仅在 <code>docker build</code> 构建过程中生效，镜像运行后失效。</p>
<ul>
<li>可通过 <code>--build-arg</code> 动态传参覆盖默认值。</li>
</ul>
<pre><code class="language-dockerfile"># 定义参数，带默认值
ARG VERSION=v1</code></pre>
<pre><code class="language-bash"># 构建时动态修改参数
docker build --build-arg VERSION=v2 -t test:v1 .</code></pre>
<hr />
<h2>二、实战 1：Dockerfile 构建 Nginx 镜像</h2>
<h3>1. 准备文件</h3>
<p>新建目录并上传本地 YUM 源文件 <code>Centos-vault-8.5.2111.repo</code></p>
<pre><code class="language-bash">mkdir dockerfile &amp;&amp; cd dockerfile/</code></pre>
<h3>2. 编写 Dockerfile</h3>
<pre><code class="language-dockerfile">FROM centos
MAINTAINER ZHappy
# 替换YUM源
RUN rm -rf /etc/yum.repos.d/*
COPY Centos-vault-8.5.2111.repo /etc/yum.repos.d/
# 安装依赖与Nginx
RUN yum install wget -y
RUN yum install nginx -y
# 拷贝自定义页面
COPY index.html /usr/share/nginx/html/
# 声明端口
EXPOSE 80
# 容器启动自动运行Nginx
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]</code></pre>
<h3>3. 编写自定义页面 index.html</h3>
<pre><code class="language-html">&lt;html&gt;
&lt;head&gt;
        &lt;title&gt;page added to dockerfile&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
        &lt;h1&gt;Hello ,My Name is ZHappy,My wechat is luckylucky421302 &lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<h3>4. 构建镜像</h3>
<pre><code class="language-bash">docker build -t="ZHappy/nginx:v1" .
# 查看镜像
docker images | grep nginx</code></pre>
<h3>5. 启动容器并测试访问</h3>
<pre><code class="language-bash"># 后台启动容器，随机映射80端口
docker run -d  -p 80 --name html2 ZHappy/nginx:v1
# 查看容器端口
docker ps | grep html2
# 访问测试（替换为你的服务器IP+映射端口）
curl http://192.168.40.180:49154</code></pre>
<hr />
<h2>三、实战 2：Dockerfile 构建 Tomcat 镜像</h2>
<h3>环境准备</h3>
<p>新建目录，上传以下文件：</p>
<ul>
<li>
<p><code>apache-tomcat-8.0.26.tar.gz</code>（Tomcat 压缩包）</p>
</li>
<li>
<p><code>jdk-8u45-linux-x64.rpm</code>（JDK 安装包）</p>
</li>
<li>
<p><code>Centos-vault-8.5.2111.repo</code>（YUM 源文件）</p>
</li>
</ul>
<pre><code class="language-bash">mkdir tomcat8 &amp;&amp; cd tomcat8</code></pre>
<h3>方式 1：基础版（需手动启动 Tomcat）</h3>
<h4>1. 编写 Dockerfile</h4>
<pre><code class="language-dockerfile">FROM centos
MAINTAINER ZHappy
# 替换YUM源
RUN rm -rf /etc/yum.repos.d/*
COPY Centos-vault-8.5.2111.repo /etc/yum.repos.d/
RUN yum install wget -y
# 解压JDK、Tomcat
ADD jdk-8u45-linux-x64.rpm /usr/local/
ADD apache-tomcat-8.0.26.tar.gz /usr/local/
# 安装JDK、重命名Tomcat目录
RUN cd /usr/local &amp;&amp; rpm -ivh jdk-8u45-linux-x64.rpm
RUN mv /usr/local/apache-tomcat-8.0.26 /usr/local/tomcat8
# 声明端口
EXPOSE 8080</code></pre>
<h4>2. 构建 \&amp; 运行</h4>
<pre><code class="language-bash"># 构建镜像
docker build -t="tomcat8:v1" .
# 启动容器
docker run --name tomcat8  -itd -p 8080 tomcat8:v1
# 进入容器，手动启动Tomcat
docker exec -it tomcat8  /bin/bash
/usr/local/tomcat8/bin/startup.sh</code></pre>
<h3>方式 2：进阶版（容器启动自动运行 Tomcat）</h3>
<h4>1. 编写 Dockerfile1</h4>
<pre><code class="language-dockerfile">FROM centos
MAINTAINER ZHappy
RUN rm -rf /etc/yum.repos.d/*
COPY Centos-vault-8.5.2111.repo /etc/yum.repos.d/
RUN yum install wget -y
ADD jdk-8u45-linux-x64.rpm /usr/local/
ADD apache-tomcat-8.0.26.tar.gz /usr/local/
RUN cd /usr/local &amp;&amp; rpm -ivh jdk-8u45-linux-x64.rpm
RUN mv /usr/local/apache-tomcat-8.0.26 /usr/local/tomcat8
# 容器启动自动运行Tomcat并打印日志
ENTRYPOINT /usr/local/tomcat8/bin/startup.sh &amp;&amp; tail -F /usr/local/tomcat8/logs/catalina.out
EXPOSE 8080</code></pre>
<blockquote>
<p>推荐写法：<code>ENTRYPOINT ["/usr/local/tomcat8/bin/catalina.sh", "run"]</code></p>
</blockquote>
<h4>2. 构建 \&amp; 运行</h4>
<pre><code class="language-bash"># -f 指定Dockerfile文件名
docker build -f dockerfile1 -t="tomcat8:v2" .
# 启动容器
docker run --name tomcat68  -itd -p 8080 tomcat8:v2 /bin/bash
# 查看端口并访问
docker ps |grep tomcat68</code></pre>
<hr />
<h2>四、扩展实战：Go 项目构建镜像</h2>
<h3>1. 环境准备（CentOS7.9）</h3>
<pre><code class="language-bash"># 安装Go环境
yum install go -y
# 创建项目目录
mkdir test &amp;&amp; cd test</code></pre>
<h3>2. 编写 Go 代码 <code>main.go</code></h3>
<pre><code class="language-go">package main

import (
"net/http"
"github.com/gin-gonic/gin"
)

func statusOKHandler(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "success~welcome to study"})
}

func versionHandler(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"version": "v1.1版本"})
}

func main() {
router := gin.New()
router.Use(gin.Recovery())
router.GET("/", statusOKHandler)
router.GET("/version", versionHandler)
router.Run(":8080")
}</code></pre>
<h3>3. 编译二进制程序</h3>
<pre><code class="language-bash"># 初始化项目
go mod init test
# 配置国内代理
go env -w GOPROXY=https://goproxy.cn,direct
# 拉取依赖
go mod tidy
# 交叉编译 Linux 可执行文件
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o k8s-demo main.go</code></pre>
<h3>4. 编写 Dockerfile</h3>
<pre><code class="language-dockerfile"># 轻量Alpine基础镜像
FROM alpine
# 工作目录
WORKDIR /data/app
# 拷贝可执行文件
ADD k8s-demo /data/app/
# 启动程序
CMD ["/bin/sh","-c","./k8s-demo"]</code></pre>
<h3>5. 构建镜像 \&amp; 运行容器</h3>
<pre><code class="language-bash">docker build -t ZHappy/k8sdemo:v1 .
# 端口映射：宿主机30180 -&gt; 容器8080
docker run -d --name go -p 30180:8080 ZHappy/k8sdemo:v1</code></pre>
<p>访问：<code>服务器IP:30180</code></p>
<hr />
<h2>五、扩展实战：Python 项目构建镜像</h2>
<h3>1. 准备代码</h3>
<p>解压项目压缩包，进入项目目录（包含 <code>main.py</code>、<code>requirements.txt</code>）</p>
<pre><code class="language-bash">tar zxvf hello-python.tar.gz
cd /root/hello-python/app</code></pre>
<h3>2. 编写 Dockerfile</h3>
<pre><code class="language-dockerfile"># 基于Python3.7官方镜像
FROM python:3.7
# 创建目录并设置工作目录
RUN mkdir /app
WORKDIR /app
# 拷贝所有项目文件
ADD . /app/
# 升级pip、安装项目依赖
RUN /usr/local/bin/python -m pip install --upgrade pip
RUN pip install -r requirements.txt
# 声明端口
EXPOSE 5000
# 启动Python程序
CMD ["python","/app/main.py"]</code></pre>
<h3>3. 构建镜像 \&amp; 运行容器</h3>
<pre><code class="language-bash"># 构建镜像
docker build  -t hello-python:v1 .
# 启动容器，端口映射 30050:5000
docker run -d --name python -p 30050:5000  hello-python:v1</code></pre>
<p>访问：<code>服务器IP:30050</code></p>]]></description>
    <pubDate>Wed, 17 Jun 2026 12:02:27 +0800</pubDate>
    <dc:creator>ZHappy</dc:creator>
    <guid>https://blog.zhappy.vip/?post=18</guid>
</item>
<item>
    <title>01-Docker零基础入门到企业实战</title>
    <link>https://blog.zhappy.vip/?post=17</link>
    <description><![CDATA[<h2>一、容器与虚拟机的区别</h2>
<p>虚拟机运行应用时，调用请求需要经过虚拟化软件，再访问宿主机操作系统；<br />
Docker 容器可<strong>直接使用宿主机操作系统</strong>，省去虚拟化层开销。</p>
<h3>容器核心优势</h3>
<ol>
<li>
<p><strong>敏捷、高性能</strong>：无需虚拟化中转，资源调用效率更高</p>
</li>
<li>
<p><strong>环境隔离</strong>：不同应用、依赖互不干扰</p>
</li>
</ol>
<h3>Docker 设计思想：类比集装箱</h3>
<p>服务器 = 货运大船<br />
容器 = 标准集装箱</p>
<ul>
<li>
<p>各类应用及依赖统一封装，相互隔离</p>
</li>
<li>
<p>一台服务器可运行多个不同环境应用，无需单独划分主机 / 虚拟机</p>
</li>
<li>
<p>解决应用环境冲突、端口冲突等问题</p>
</li>
</ul>
<h3>Docker 解决的实际业务问题</h3>
<ol>
<li>
<p><strong>环境冲突</strong>：.NET、PHP 等不同技术栈应用，依赖、端口易冲突，容器可轻量隔离，比虚拟机开销更小、成本更低。</p>
</li>
<li>
<p><strong>环境迁移难题</strong>：开发、测试、生产系统版本不一致（Ubuntu / CentOS），镜像可完整打包运行环境，<strong>一次封装，到处运行</strong>。</p>
</li>
<li>
<p><strong>资源利用率高</strong>：虚拟机常驻占用空闲内存，Docker 可合理利用服务器内存资源。</p>
</li>
<li>
<p><strong>经典痛点</strong>：开发环境正常，测试 / 生产环境报错（JDK、Tomcat、脚本版本不匹配），引发沟通问题、影响上线效率。</p>
</li>
</ol>
<h3>镜像 \&amp; 容器概念</h3>
<ul>
<li>
<p><strong>镜像</strong>：把代码、运行依赖（JDK、Tomcat、系统文件等）整体打包的文件包。</p>
</li>
<li>
<p><strong>容器</strong>：镜像运行后的实例，对外提供服务。</p>
</li>
<li>
<p>特性：镜像支持迁移、备份、存储、快速交付，保证<strong>环境强一致性</strong>。</p>
</li>
</ul>
<h2>二、为什么学习 Docker</h2>
<p>传统部署痛点：环境不一致导致跨环境运行异常，排障繁琐。<br />
Docker 核心价值：</p>
<ol>
<li>
<p>完整打包应用 + 所有依赖，环境完全统一</p>
</li>
<li>
<p>一次打包，任意 Docker 环境都可运行</p>
</li>
<li>
<p>启动、部署速度快，适合持续交付</p>
</li>
</ol>
<h2>三、Docker 基础介绍</h2>
<h3>1. 什么是 Docker</h3>
<p>Docker 是 2013 年诞生的<strong>开源容器引擎</strong>，基于 Go 语言开发，隶属于 Linux 基金会，遵循 Apache 2.0 协议。<br />
作用：将应用及依赖打包为可移植镜像，以沙箱模式运行容器，容器之间相互隔离、无直接调用。</p>
<h3>2. Docker 优点</h3>
<ol>
<li>
<p><strong>速度快</strong>：启动、停止、重启均为秒级 / 毫秒级</p>
</li>
<li>
<p><strong>部署敏捷</strong>：裸机部署简单，运维成本低</p>
</li>
<li>
<p><strong>轻量化</strong>：不额外加装完整操作系统</p>
</li>
<li>
<p><strong>高密度</strong>：单台服务器可运行数百甚至上千个容器</p>
</li>
<li>
<p><strong>低成本</strong>：开源免费</p>
</li>
</ol>
<h3>3. Docker 版本区分</h3>
<ul>
<li>
<p><code>docker-ce</code>：社区版（免费，个人 / 中小企业使用）</p>
</li>
<li>
<p><code>docker-ee</code>：商业版（付费，企业级商用）</p>
</li>
</ul>
<h3>4. Docker 缺点</h3>
<p>所有容器<strong>共用 Linux 内核</strong>，在资源隔离、安全层面存在一定局限性。</p>
<h2>四、CentOS7 环境安装 Docker</h2>
<h3>环境信息</h3>
<p>主机 IP：<code>192.168.40.180</code><br />
系统：CentOS7.6 \~ CentOS7.9<br />
配置：4Gib 内存 / 4vCPU</p>
<h3>1. 基础环境初始化</h3>
<h4>1.1 设置主机名</h4>
<pre><code class="language-bash">hostnamectl set-hostname master1 &amp;&amp; bash</code></pre>
<h4>1.2 关闭防火墙 \&amp; Iptables</h4>
<pre><code class="language-bash"># 关闭并禁用 firewalld
systemctl stop firewalld &amp;&amp; systemctl disable firewalld

# 安装、关闭并禁用 iptables
yum install iptables-services -y
service iptables stop &amp;&amp; systemctl disable iptables

# 清空防火墙规则
iptables -F</code></pre>
<h4>1.3 关闭 SELinux</h4>
<pre><code class="language-bash"># 临时关闭
setenforce 0
# 永久关闭（重启生效）
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

# 查看状态（显示 Disabled 即为成功）
getenforce</code></pre>
<h4>1.4 时间同步</h4>
<pre><code class="language-bash"># 安装时间同步工具
yum install -y ntp ntpdate
# 立即同步时间
ntpdate cn.pool.ntp.org

# 配置定时任务：每小时同步一次时间
crontab -e
# 写入内容
* */1 * * * /usr/sbin/ntpdate   cn.pool.ntp.org

# 重启定时任务服务
systemctl restart crond</code></pre>
<h4>1.5 安装基础依赖包</h4>
<pre><code class="language-bash">yum install -y wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo ntp libaio-devel wget vim ncurses-devel autoconf automake zlib-devel  python-devel epel-release openssh-server socat  ipvsadm conntrack</code></pre>
<h3>2. 安装 Docker CE</h3>
<h4>2.1 配置阿里云 Docker YUM 源</h4>
<pre><code class="language-bash">yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo</code></pre>
<h4>2.2 安装依赖</h4>
<pre><code class="language-bash">yum install -y yum-utils device-mapper-persistent-data lvm2</code></pre>
<h4>2.3 安装 Docker CE</h4>
<pre><code class="language-bash">yum install docker-ce -y</code></pre>
<h3>3. 启动 Docker 服务</h3>
<pre><code class="language-bash"># 启动并设置开机自启
systemctl start docker &amp;&amp; systemctl enable docker

# 查看运行状态（显示 active(running) 即正常）
systemctl status docker

# 查看 Docker 版本
docker version</code></pre>
<h3>4. 开启内核转发与网络模块</h3>
<p>Docker 网络依赖桥接转发，需配置内核参数。</p>
<h4>4.1 加载内核模块 \&amp; 配置参数</h4>
<pre><code class="language-bash"># 加载 br_netfilter 模块
modprobe br_netfilter

# 写入内核配置
cat &gt; /etc/sysctl.d/docker.conf &lt;&lt;EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

# 生效配置
sysctl -p /etc/sysctl.d/docker.conf</code></pre>
<h4>4.2 设置开机自动加载模块</h4>
<pre><code class="language-bash"># 创建开机加载脚本
cat &gt; /etc/rc.sysinit &lt;&lt;EOF
#!/bin/bash
for file in /etc/sysconfig/modules/*.modules ; do
[ -x \$file ] &amp;&amp; \$file
done
EOF

# 创建模块自启文件
cat &gt; /etc/sysconfig/modules/br_netfilter.modules &lt;&lt;EOF
modprobe br_netfilter
EOF

# 授权
chmod 755 /etc/sysconfig/modules/br_netfilter.modules

# 查看模块是否加载
lsmod |grep br_netfilter</code></pre>
<h4>4.3 重启 Docker</h4>
<pre><code class="language-bash">systemctl restart docker</code></pre>
<blockquote>
<p>说明：<code>net.ipv4.ip_forward = 1</code> 开启 IP 数据包转发，否则容器内应用无法被外网访问。</p>
</blockquote>
<h3>5. 配置 Docker 镜像加速器</h3>
<p>官方仓库拉取镜像速度慢，配置国内加速器提升下载速度。</p>
<h4>5.1 编辑加速器配置文件</h4>
<pre><code class="language-bash">mkdir -p /etc/docker
tee /etc/docker/daemon.json &lt;&lt;-'EOF'
{
 "registry-mirrors":["https://y8y6vosv.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hub-mirror.c.163.com"]
}
EOF</code></pre>
<h4>5.2 生效配置</h4>
<pre><code class="language-bash">systemctl daemon-reload
systemctl restart docker</code></pre>
<p><strong>常用国内加速器地址</strong></p>
<ul>
<li>
<p>阿里云：专属镜像地址（需登录阿里云容器镜像服务获取）</p>
</li>
<li>
<p>Docker 中国官方：<code>https://registry.docker-cn.com</code></p>
</li>
<li>
<p>科大镜像：<code>https://docker.mirrors.ustc.edu.cn</code></p>
</li>
<li>
<p>网易云：<code>http://hub-mirror.c.163.com</code></p>
</li>
<li>
<p>DaoCloud：<code>http://f1361db2.m.daocloud.io</code></p>
</li>
</ul>
<h2>五、Docker 基础命令</h2>
<h3>1. 镜像操作</h3>
<h4>1.1 搜索镜像</h4>
<pre><code class="language-bash">docker search centos</code></pre>
<p>字段说明：</p>
<ul>
<li>
<p><code>NAME</code>：镜像名称</p>
</li>
<li>
<p><code>DESCRIPTION</code>：镜像描述</p>
</li>
<li>
<p><code>STARS</code>：点赞数</p>
</li>
<li>
<p><code>OFFICIAL</code>：是否为官方镜像</p>
</li>
<li>
<p><code>AUTOMATED</code>：是否自动构建</p>
</li>
</ul>
<h4>1.2 拉取（下载）镜像</h4>
<pre><code class="language-bash">docker pull centos</code></pre>
<h4>1.3 查看本地镜像</h4>
<pre><code class="language-bash">docker images</code></pre>
<h4>1.4 镜像导出为离线包</h4>
<pre><code class="language-bash">docker save -o centos.tar.gz centos</code></pre>
<h4>1.5 导入离线镜像包</h4>
<pre><code class="language-bash">docker load -i centos.tar.gz</code></pre>
<h4>1.6 删除镜像</h4>
<pre><code class="language-bash">docker rmi -f centos:latest</code></pre>
<h3>2. 容器操作</h3>
<h4>2.1 交互式启动容器（前台运行，退出即停止）</h4>
<pre><code class="language-bash">docker run --name=hello -it centos /bin/bash</code></pre>
<p>参数说明：</p>
<ul>
<li>
<p><code>--name</code>：指定容器名称</p>
</li>
<li>
<p><code>-i</code>：交互式运行</p>
</li>
<li>
<p><code>-t</code>：分配虚拟终端</p>
</li>
<li>
<p><code>/bin/bash</code>：进入 bash 终端</p>
</li>
</ul>
<p>输入 <code>exit</code> 退出容器。</p>
<h4>2.2 守护进程方式启动（后台运行）</h4>
<pre><code class="language-bash">docker run --name=hello1 -td centos</code></pre>
<ul>
<li><code>-d</code>：后台守护进程运行</li>
</ul>
<h4>2.3 进入后台运行的容器</h4>
<pre><code class="language-bash">docker exec -it hello1 /bin/bash</code></pre>
<h4>2.4 查看容器</h4>
<pre><code class="language-bash"># 查看正在运行的容器
docker ps

# 查看所有容器（包含已停止）
docker ps -a</code></pre>
<h4>2.5 启停容器</h4>
<pre><code class="language-bash"># 停止容器
docker stop hello1

# 启动已停止的容器
docker start hello1</code></pre>
<h4>2.6 删除容器</h4>
<pre><code class="language-bash"># 强制删除容器
docker rm -f hello1</code></pre>
<h4>2.7 查看帮助</h4>
<pre><code class="language-bash">docker --help</code></pre>
<h2>六、实战：Docker 部署 Nginx 服务</h2>
<h3>1. 启动容器并做端口映射</h3>
<pre><code class="language-bash"># -p 端口映射：容器80端口随机映射到宿主机端口
docker run --name nginx -p 80 -itd centos</code></pre>
<h3>2. 进入容器</h3>
<pre><code class="language-bash">docker exec -it nginx /bin/bash</code></pre>
<h3>3. 查看容器 IP</h3>
<pre><code class="language-bash">ip addr
# 示例容器IP：172.17.0.3</code></pre>
<h3>4. 容器内配置 YUM 源并安装 Nginx</h3>
<pre><code class="language-bash">rm -rf /etc/yum.repos.d/*
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/CentOS-vault-8.5.2111.repo
yum install wget -y
yum install nginx -y
yum install vim-enhanced -y</code></pre>
<h3>5. 编写静态页面</h3>
<pre><code class="language-bash">mkdir /var/www/html -p
cd /var/www/html/

cat &gt; index.html &lt;&lt;EOF
&lt;html&gt;
        &lt;head&gt;
                 &lt;title&gt;nginx in docker&lt;/title&gt;
        &lt;/head&gt;
        &lt;body&gt;
                &lt;h1&gt;hello,My Name is ZHappy&lt;/h1&gt;
        &lt;/body&gt;
&lt;/html&gt;
EOF</code></pre>
<h3>6. 修改 Nginx 配置，指定页面路径</h3>
<pre><code class="language-bash">vim /etc/nginx/nginx.conf
# 修改配置项
root         /var/www/html/;</code></pre>
<h3>7. 启动 Nginx</h3>
<pre><code class="language-bash">/usr/sbin/nginx</code></pre>
<h3>8. 访问服务</h3>
<h4>8.1 查看宿主机映射端口（宿主机终端执行）</h4>
<pre><code class="language-bash">docker ps | grep nginx
# 例：宿主机端口 49153 -&gt; 容器80端口</code></pre>
<h4>8.2 访问测试</h4>
<pre><code class="language-bash"># 方式1：宿主机IP+映射端口
curl http://192.168.40.180:49153

# 方式2：直接访问容器IP+端口
curl 172.17.0.3:80</code></pre>
<h3>访问流量走向</h3>
<p>客户端访问 <strong>宿主机 IP: 映射端口</strong> → 转发至 <strong>容器 IP: 服务端口</strong> → 访问容器内应用</p>]]></description>
    <pubDate>Wed, 17 Jun 2026 09:57:40 +0800</pubDate>
    <dc:creator>ZHappy</dc:creator>
    <guid>https://blog.zhappy.vip/?post=17</guid>
</item>
<item>
    <title>Kickstart 完整详解模板</title>
    <link>https://blog.zhappy.vip/?post=15</link>
    <description><![CDATA[<p>适用系统：RHEL8/RHEL9、CentOS Stream 8/9、Rocky Linux、AlmaLinux<br />
文件后缀：<code>ks.cfg</code>，配合 PXE / 本地 U 盘自动安装</p>
<h2>完整 ks.cfg 文件（每行附带超长详细说明）</h2>
<pre><code class="language-cfg"># ====================== 1. 安装类型与语言时区全局配置 ======================
# install：代表全新安装；若写upgrade为系统升级，自动安装必须用install
install
# 系统安装源配置，两种方式任选其一，注释掉不用的
# 方式1：本地光盘/ISO源（U盘本地安装用）
# cdrom
# 方式2：HTTP网络yum源（PXE批量装机推荐，替换为你的镜像源地址）
url --url=http://192.168.1.100/centos9-stream/BaseOS/
# 系统语言，en_US.utf8英文，zh_CN.utf8中文，服务器推荐英文避免编码bug
lang en_US.UTF-8
# 系统时区，Asia/Shanghai东八区；--utc 硬件时钟使用UTC时间，服务器必加
timezone Asia/Shanghai --utc
# 键盘布局，us美式键盘，中文环境可加cn，多布局用逗号分隔
keyboard us
# 系统授权许可，RHEL必须写，CentOS/Rocky可保留
licence --accept
# 关闭图形化安装界面，全程文本自动安装，无人工交互
text
# 设置安装过程日志输出，--file保存到本地文件，--remote发送日志到远端服务器
logging --level=info

# ====================== 2. 网络配置（服务器必配，PXE装机核心） ======================
# network 配置第一块网卡eth0/ens33
# --bootproto：dhcp自动获取IP | static静态IP
# --device：网卡设备名，ens33为VMware默认网卡，ens160是ESXi默认
# --onboot=on 开机自动启用网卡；--ipv6=disable 关闭IPv6减少故障
# static模式额外参数：ip、netmask、gateway、nameserver
network --device=ens33 --bootproto=dhcp --onboot=on --ipv6=disable
# 静态IP完整示例（替换上面network行，二选一）
# network --device=ens33 --bootproto=static --ip=192.168.1.10 --netmask=255.255.255.0 --gateway=192.168.1.1 --nameserver=223.5.5.5 --onboot=on --ipv6=disable
# 设置主机名，安装完成后写入/etc/hostname
hostname kicktest-server01

# ====================== 3. 存储磁盘分区（重点详细，单磁盘全盘清空方案） ======================
# clearpart：清空磁盘分区，自动装机必备
# --all：清空本机所有磁盘所有分区；--drives=sda 指定只清空sda盘
# --initlabel：清空后初始化磁盘标签，MBR(BIOS) / GPT(UEFI)自动识别
# --linux：仅删除Linux分区，保留Windows，多系统共存用
clearpart --all --initlabel
# 初始化磁盘标签，UEFI环境强制生成GPT分区表，BIOS可选mbr
zerombr
# 磁盘分区方案，分 /boot/efi(UEFI)、/boot、swap、根分区/
# UEFI分区：必须vfat格式，大小最小600M，推荐1G，挂载/boot/efi
part /boot/efi --fstype=vfat --size=1024
# /boot 系统启动分区 xfs格式，存放内核，1G足够
part /boot --fstype=xfs --size=1024
# swap交换分区，内存小于16G建议和内存同等大小，大于16G给4G即可
part swap --size=4096
# 根分区 / 所有剩余空间全部给根目录，--grow 参数代表占用磁盘剩余全部容量
part / --fstype=xfs --size=10240 --grow

# 若需要LVM逻辑卷分区方案（企业生产常用，替换上面part分区段）
# # 创建物理卷
# volgroup vg01 /dev/sda3
# # 创建逻辑卷根分区
# logvol / --vgname=vg01 --size=20480 --name=lvroot --fstype=xfs
# # 创建swap逻辑卷
# logvol swap --vgname=vg01 --size=4096 --name=lvswap

# ====================== 4. 系统密码、用户、root权限配置 ======================
# root管理员密码，两种写法
# 明文：rootpw 123456 仅测试用，禁止生产环境
# --iscrypted 加密密码，使用openssl passwd -6 生成SHA512加密字符串（生产推荐）
rootpw --iscrypted $6$xxxxxx$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 新建普通用户，参数详解：
# --name 用户名；--groups 附属组wheel代表拥有sudo权限；--password加密密码
# --shell 指定登录shell /bin/bash；--homedir 家目录
user --name=admin --groups=wheel --shell=/bin/bash --homedir=/home/admin --password=$6$xxxxxx$xxxxxxx
# 允许root账号ssh远程登录（安全规范建议关闭，关闭去掉此参数）
sshkey --username=root
# 防火墙配置：--enabled开启防火墙；--disabled关闭；--service开放端口
firewall --enabled --service=ssh,http,https

# ====================== 5. 安全与SELinux ======================
# SELinux模式：enforcing强制开启（生产推荐）、permissive告警不拦截、disabled彻底关闭
selinux --enforcing

# ====================== 6. 引导程序、开机配置 ======================
# bootloader 系统引导程序grub2
# --location=mbr BIOS模式写入主引导；UEFI自动写入ESP分区无需修改
# --append 内核启动参数，net.ifnames=0关闭网卡命名，网卡变回eth0格式
bootloader --location=mbr --append="net.ifnames=0 biosdevname=0"
# 关闭开机图形界面，默认进入字符终端3级别
runlevel 3
# 关闭kdump崩溃转储服务，服务器资源紧张可关闭，生产排查故障建议开启
# kdump --enable --reserve-mb=256
kdump --disable

# ====================== 7. 软件包安装选择（核心：%packages段） ======================
# %packages 定义需要安装的软件组/单独软件，@代表软件组，-代表排除不装
%packages
# 最小化服务器安装组，仅基础组件，无图形（生产首选）
@Minimal
# 开启网络工具组，包含ifconfig、netstat、traceroute等
@NetworkTools
# 开发工具组，编译安装软件必备（不需要可删除）
@Development Tools
# 系统基础工具
vim-enhanced
wget
unzip
zip
telnet
# 排除不需要的软件，减少安装体积
-*-gnome
-*-kde
-xfirefox
# 排除弱密码检测、图形相关包
-plymouth
%end

# ====================== 8. 安装后自动执行脚本 %post（装机自动化核心） ======================
# %post --nochroot：安装环境执行；不加nochroot代表进入新系统后执行
# --log=/var/log/ks-post.log 将脚本执行日志写入文件，方便排错
%post --log=/var/log/ks-post-install.log
# 1. 关闭SELinux永久关闭（可选，上面selinux参数已控制，此处二次修改）
sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
# 2. 关闭防火墙（可选，根据业务需求）
# systemctl disable --now firewalld
# 3. 设置时间同步chrony
cat &gt; /etc/chrony.conf &lt;&lt;EOF
server ntp.aliyun.com iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
allow 192.168.1.0/24
EOF
systemctl enable --now chronyd
# 4. 优化ssh配置，禁止密码登录（测试环境注释）
# sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
# systemctl restart sshd
# 5. 写入开机提示
echo "Kickstart自动装机完成，服务器IP查看：ip a" &gt;&gt; /etc/motd
# 6. 清除安装缓存，减小系统占用
dnf clean all
%end

# ====================== 9. 安装完成动作 ======================
# reboot：安装完成自动重启
# halt：安装完成停机
# poweroff：安装完成断电
reboot</code></pre>
<h1>分模块超详细参数说明（逐个字段拆解）</h1>
<h2>一、安装基础段（install 开头）</h2>
<ol>
<li>
<p><code>install</code><br />
作用：声明本次执行全新操作系统安装，<code>upgrade</code>代表升级现有系统，自动化装机必须使用<code>install</code>，升级模式无法分区清空。</p>
</li>
<li>
<p><code>url --url=源地址</code></p>
<ul>
<li>
<p>HTTP/HTTPS/FTP 网络安装源，企业 PXE 批量装机主流方式</p>
</li>
<li>
<p>本地 ISO 使用 <code>cdrom</code> 替代，读取本地光盘镜像，适合离线单机安装</p>
</li>
</ul>
</li>
<li>
<p><code>lang en_US.UTF-8</code><br />
系统全局语言，服务器强烈推荐英文中文：</p>
<ul>
<li><code>zh_CN.UTF-8</code>：中文，控制台中文会出现方块乱码，排查日志不友好</li>
</ul>
</li>
<li>
<p><code>timezone Asia/Shanghai --utc</code></p>
<ul>
<li>
<p><code>Asia/Shanghai</code>：东八区北京时间，不能写 CST 会冲突</p>
</li>
<li>
<p><code>--utc</code>：主板硬件时钟使用 UTC 标准时间，多服务器集群时间同步必加</p>
</li>
</ul>
</li>
<li>
<p><code>text</code><br />
强制文本模式安装；去掉该参数默认图形 GUI 安装，无人值守必须文本。</p>
</li>
</ol>
<h2>二、网络 network 参数全解析</h2>
<pre><code class="language-Plain">network --device=ens33 --bootproto=dhcp --onboot=on --ipv6=disable</code></pre>
<ul>
<li>
<p><code>--device</code>：指定网卡设备名称，虚拟机 ens33/ens160，物理机 eth0</p>
</li>
<li>
<p><code>--bootproto=dhcp</code>：自动获取 IP；<code>static</code>静态固定 IP，必须搭配 ip/netmask/gateway</p>
</li>
<li>
<p><code>--ip=192.168.1.10</code>：静态 IP 地址</p>
</li>
<li>
<p><code>--netmask=255.255.255.0</code>：子网掩码</p>
</li>
<li>
<p><code>--gateway=192.168.1.1</code>：网关</p>
</li>
<li>
<p><code>--nameserver=223.5.5.5</code>：DNS 服务器，多 DNS 逗号分隔</p>
</li>
<li>
<p><code>--onboot=on</code>：开机自启网卡，off 则开机禁用网卡</p>
</li>
<li>
<p><code>--ipv6=disable</code>：关闭 IPv6 协议，内网服务器一般不需要 IPv6</p>
</li>
</ul>
<h2>三、磁盘分区核心参数（最容易出错模块）</h2>
<ol>
<li>
<p><code>clearpart --all --initlabel</code></p>
<ul>
<li>
<p><code>--all</code>：清空本机所有硬盘全部分区，全新装机必选</p>
</li>
<li>
<p><code>--drives=sda</code>：仅清空指定硬盘，多磁盘服务器用，例<code>clearpart --drives=sda,sdb</code></p>
</li>
<li>
<p><code>--initlabel</code>：磁盘清空后重建分区表，UEFI 生成 GPT，BIOS 生成 MBR</p>
</li>
<li>
<p><code>--linux</code>：只删除 Linux 分区，保留 Windows，双系统专用</p>
</li>
</ul>
</li>
<li>
<p><code>zerombr</code><br />
清空磁盘 MBR 引导残留，防止旧系统引导干扰新系统安装。</p>
</li>
<li>
<p><code>part 分区命令通用参数</code></p>
<ul>
<li>
<p><code>--fstype=xfs/vfat/ext4</code>：文件系统类型，RHEL8 + 默认 xfs；EFI 分区必须 vfat</p>
</li>
<li>
<p><code>--size=数字</code>：分区固定大小，单位 MB</p>
</li>
<li>
<p><code>--grow</code>：占用磁盘剩余所有空闲空间，仅根分区使用</p>
</li>
<li>
<p><code>--ondisk=sda</code>：指定分区创建在哪块硬盘</p>
</li>
</ul>
</li>
<li>
<p>LVM 逻辑卷参数（企业生产）</p>
<ul>
<li>
<p><code>volgroup vg名 /dev/sda3</code>：创建卷组，绑定物理分区</p>
</li>
<li>
<p><code>logvol 挂载点 --vgname=卷组名 --size=大小 --name=逻辑卷名</code>：创建逻辑卷</p>
</li>
</ul>
</li>
</ol>
<h2>四、用户与密码配置</h2>
<ol>
<li>
<p><code>rootpw --iscrypted 加密字符串</code></p>
<ul>
<li>
<p><code>--iscrypted</code>：密码为 SHA512 加密密文，生产环境强制使用</p>
</li>
<li>
<p>生成加密密码命令：<code>openssl passwd -6</code>，输入密码直接复制密文</p>
</li>
<li>
<p>无 --iscrypted 为明文密码，仅本地测试，严禁线上使用</p>
</li>
</ul>
</li>
<li>
<p><code>user --name=xxx</code> 创建普通用户</p>
<ul>
<li>
<p><code>--groups=wheel</code>：加入 wheel 组，拥有 sudo 管理员权限</p>
</li>
<li>
<p><code>--shell=/bin/bash</code>：可交互登录 shell，默认 /sbin/nologin 无法登录</p>
</li>
<li>
<p><code>--homedir=/home/admin</code> 用户家目录路径</p>
</li>
</ul>
</li>
<li>
<p><code>firewall --enabled --service=ssh</code></p>
<ul>
<li>
<p><code>--enabled</code> 开启 firewalld 防火墙；<code>--disabled</code>关闭</p>
</li>
<li>
<p><code>--service=ssh,http</code> 放行对应服务端口，逗号分隔多服务</p>
</li>
</ul>
</li>
</ol>
<h2>五、引导 bootloader 参数</h2>
<pre><code class="language-Plain">bootloader --location=mbr --append="net.ifnames=0 biosdevname=0"</code></pre>
<ul>
<li>
<p><code>--location=mbr</code> BIOS 机器，引导写入磁盘主引导记录</p>
</li>
<li>
<p>UEFI 环境无需修改，自动写入 /boot/efi 分区</p>
</li>
<li>
<p><code>--append</code> 内核启动参数：<code>net.ifnames=0</code> 关闭 systemd 网卡命名，网卡变回 eth0</p>
</li>
</ul>
<h2>六、% packages 软件安装段规则</h2>
<ol>
<li>
<p><code>@软件组名</code>：批量安装一组软件，系统内置分组</p>
<ul>
<li>
<p><code>@Minimal</code> 最小化服务器（推荐）</p>
</li>
<li>
<p><code>@Server with GUI</code> 带图形桌面服务器</p>
</li>
<li>
<p><code>@Development Tools</code> 编译开发工具</p>
</li>
</ul>
</li>
<li>
<p>直接写包名：单独安装单个软件，如 vim-enhanced wget</p>
</li>
<li>
<p><code>-包名</code>：减号代表排除该软件，不进行安装，精简系统体积</p>
</li>
</ol>
<h2>七、% post 装机后脚本段（自动化核心）</h2>
<p>执行时机：系统文件全部复制完成，重启之前执行</p>
<ul>
<li>
<p><code>--log=/xxx.log</code>：将脚本所有输出写入日志，排错必备</p>
</li>
<li>
<p><code>--nochroot</code>：在安装临时环境执行，不加参数则进入新系统根环境执行<br />
常用自动化场景：配置 yum 源、时间同步、ssh 加固、初始化业务环境、自动推送脚本、修改系统配置文件</p>
</li>
</ul>
<h2>八、收尾动作指令</h2>
<ul>
<li>
<p><code>reboot</code>：安装完成自动重启，PXE 批量装机最常用</p>
</li>
<li>
<p><code>poweroff</code>：安装完成自动断电，机房批量上架使用</p>
</li>
<li>
<p><code>halt</code>：安装完成停机，需手动开机</p>
</li>
</ul>
<h1>配套实用操作命令</h1>
<ol>
<li>校验 ks.cfg 语法是否错误（系统自带工具）</li>
</ol>
<pre><code class="language-bash">ksvalidator ks.cfg</code></pre>
<ol start="2">
<li>生成 root 加密密码</li>
</ol>
<pre><code class="language-bash">openssl passwd -6</code></pre>
<ol start="3">
<li>测试 Kickstart 本地安装（虚拟机挂载 ISO 测试）<br />
在系统启动菜单添加内核参数：<code>inst.ks=http://192.168.1.100/ks.cfg</code><br />
本地文件：<code>inst.ks=hd:sda1:/ks.cfg</code></li>
</ol>
<h1>使用注意事项</h1>
<ol>
<li>
<p>UEFI 启动必须存在<code>/boot/efi</code> vfat 分区，缺少会安装失败</p>
</li>
<li>
<p>静态网络配置时，网关、DNS、IP 网段必须匹配，否则安装源无法访问</p>
</li>
<li>
<p>生产环境禁止明文 root 密码，必须使用<code>--iscrypted</code>加密</p>
</li>
<li>
<p>% post 脚本中所有命令使用绝对路径，安装环境 PATH 不完整</p>
</li>
<li>
<p>最小化安装不带 ifconfig、netstat，需要手动安装 @NetworkTools 软件组</p>
</li>
</ol>]]></description>
    <pubDate>Wed, 17 Jun 2026 09:17:42 +0800</pubDate>
    <dc:creator>ZHappy</dc:creator>
    <guid>https://blog.zhappy.vip/?post=15</guid>
</item>
<item>
    <title>IPMITool 工具使用详细教程</title>
    <link>https://blog.zhappy.vip/?post=14</link>
    <description><![CDATA[<h2>一、IPMI 与 IPMITool 简介</h2>
<h3>1. IPMI 概述</h3>
<p>智能平台管理接口（Intelligent Platform Management Interface，简称 IPMI）是一种开放标准的硬件管理接口规格，定义了嵌入式管理子系统进行通信的特定方法。它独立于系统的 CPU、BIOS 和操作系统，能够在系统未开机的状态下，对系统进行监控、管理和维护。通过 IPMI，管理员可以远程监控服务器的硬件状态（如温度、电压、风扇转速等）、控制服务器的电源状态、进行系统日志记录等操作。</p>
<h3>2. IPMITool 概述</h3>
<p>IPMITool 是一个开源的命令行工具，用于与支持 IPMI 标准的系统进行交互。它提供了丰富的功能，允许用户通过 IPMI 接口执行各种管理任务。IPMITool 可以运行在多种操作系统上，如 Linux、Windows 等，为管理员提供了一种方便、灵活的方式来管理和监控服务器硬件。</p>
<h2>二、IPMITool 安装</h2>
<h3>1. Linux 系统安装</h3>
<h4>Debian/Ubuntu 系统</h4>
<p>在终端中执行以下命令进行安装：</p>
<pre><code class="language-bash">sudo apt-get update
sudo apt-get install ipmitool</code></pre>
<h4>Red Hat/CentOS 系统</h4>
<p>使用以下命令进行安装：</p>
<pre><code class="language-bash">sudo yum install ipmitool</code></pre>
<h3>2. Windows 系统安装</h3>
<ul>
<li>访问 IPMITool 的官方下载页面或相关软件源，下载适用于 Windows 的 IPMITool 安装包。</li>
<li>运行安装包，按照安装向导的提示完成安装。安装完成后，需要将 IPMITool 的安装目录添加到系统的环境变量中，以便在命令提示符中可以直接使用。</li>
</ul>
<h2>三、IPMITool 基本使用</h2>
<h3>1. 连接到目标服务器</h3>
<p>在使用 IPMITool 之前，需要先与支持 IPMI 的目标服务器建立连接。连接服务器需要知道服务器的 IPMI 接口的 IP 地址、用户名和密码。使用以下命令进行连接：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; &lt;命令&gt;</code></pre>
<ul>
<li><code>-I lanplus</code>：指定使用 LAN 协议进行连接，这是最常用的连接方式。</li>
<li><code>-H &lt;IP 地址&gt;</code>：指定目标服务器 IPMI 接口的 IP 地址。</li>
<li><code>-U &lt;用户名&gt;</code>：指定登录 IPMI 接口的用户名。</li>
<li><code>-P &lt;密码&gt;</code>：指定登录 IPMI 接口的密码。</li>
</ul>
<p>例如，连接到 IP 地址为 <code>192.168.1.100</code>，用户名为 <code>admin</code>，密码为 <code>password</code> 的服务器，并查看服务器的系统信息：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H 192.168.1.100 -U admin -P password chassis status</code></pre>
<h3>2. 查看服务器硬件状态信息</h3>
<h4>查看传感器信息</h4>
<p>传感器信息可以反映服务器的硬件状态，如温度、电压、风扇转速等。使用以下命令查看传感器信息：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; sensor</code></pre>
<p>该命令将输出服务器上所有传感器的详细信息，包括传感器名称、当前值、状态等。例如：</p>
<pre><code class="language-plaintext">CPU Temp         | 32.000     | degrees C  | ok    | na        | 5.000     | 10.000    | 80.000    | 85.000    | 90.000    
MB Temp          | 28.000     | degrees C  | ok    | na        | 5.000     | 10.000    | 70.000    | 75.000    | 80.000    
Fan1             | 3000       | RPM        | ok    | na        | 1000      | 1500      | 8000      | 8500      | 9000    </code></pre>
<h4>查看系统事件日志（SEL）</h4>
<p>系统事件日志记录了服务器硬件的各种事件信息，如硬件故障、传感器告警等。使用以下命令查看系统事件日志：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; sel list</code></pre>
<p>该命令将输出系统事件日志的详细信息，包括事件发生的时间、事件类型、事件描述等。例如：</p>
<pre><code class="language-plaintext">1 | 01/01/2025 | 12:00:00 | Temperature Sensor | CPU Temp | Going High
2 | 01/01/2025 | 12:05:00 | Temperature Sensor | CPU Temp | Going Normal</code></pre>
<h3>3. 控制服务器电源状态</h3>
<h4>查看电源状态</h4>
<p>使用以下命令查看服务器的电源状态：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; chassis power status</code></pre>
<p>该命令将输出服务器的电源状态，如 <code>Power is on</code> 或 <code>Power is off</code>。</p>
<h4>开机</h4>
<p>使用以下命令开启服务器电源：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; chassis power on</code></pre>
<h4>关机</h4>
<p>使用以下命令关闭服务器电源：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; chassis power off</code></pre>
<h4>重启</h4>
<p>使用以下命令重启服务器：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; chassis power reset</code></pre>
<h3>4. 远程控制台（SOL）功能</h3>
<p>远程控制台（Serial over LAN，简称 SOL）允许用户通过网络远程访问服务器的串口控制台。使用以下命令启用 SOL 功能：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; sol activate</code></pre>
<p>启用 SOL 功能后，用户可以在终端中像操作本地串口控制台一样操作服务器。要退出 SOL 会话，可以按下 <code>Ctrl + ]</code> 组合键。</p>
<h2>四、高级使用</h2>
<h3>1. 设置 IPMI 接口参数</h3>
<p>可以使用 IPMITool 来设置服务器 IPMI 接口的参数，如 IP 地址、子网掩码、网关等。以下是设置 IPMI 接口 IP 地址的示例：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; lan set 1 ipsrc static
ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; lan set 1 ipaddr &lt;新 IP 地址&gt;
ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; lan set 1 netmask &lt;子网掩码&gt;
ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; lan set 1 defgw ipaddr &lt;网关地址&gt;</code></pre>
<h3>2. 批量操作</h3>
<p>如果需要对多台服务器进行相同的操作，可以编写脚本实现批量操作。以下是一个使用 Bash 脚本批量查看多台服务器传感器信息的示例：</p>
<pre><code class="language-bash">#!/bin/bash

# 定义服务器列表
servers=(
"192.168.1.100"
"192.168.1.101"
"192.168.1.102"
)

# 定义用户名和密码
username="admin"
password="password"

# 遍历服务器列表
for server in "${servers[@]}"
do
    echo "查看服务器 $server 的传感器信息："
    ipmitool -I lanplus -H $server -U $username -P $password sensor
    echo "------------------------------"
done</code></pre>
<p>将上述脚本保存为 <code>batch_sensor.sh</code>，并赋予执行权限：</p>
<pre><code class="language-bash">chmod +x batch_sensor.sh</code></pre>
<p>然后运行脚本：</p>
<pre><code class="language-bash">./batch_sensor.sh</code></pre>
<h3>3. 用户管理</h3>
<h4>创建用户</h4>
<p>可以使用 IPMITool 创建新的 IPMI 用户，以便不同的管理员使用不同的账号进行管理操作。创建用户的命令如下：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; user set name &lt;用户 ID&gt; &lt;新用户名&gt;
ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; user set password &lt;用户 ID&gt; &lt;新密码&gt;
ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; user enable &lt;用户 ID&gt;</code></pre>
<ul>
<li><code>&lt;用户 ID&gt;</code>：是一个唯一的数字，用于标识用户，范围通常是 1 - 16。</li>
<li><code>&lt;新用户名&gt;</code>：指定要创建的新用户的名称。</li>
<li><code>&lt;新密码&gt;</code>：指定新用户的登录密码。</li>
</ul>
<p>例如，创建一个用户 ID 为 3，用户名为 <code>newuser</code>，密码为 <code>newpassword</code> 的新用户：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H 192.168.1.100 -U admin -P password user set name 3 newuser
ipmitool -I lanplus -H 192.168.1.100 -U admin -P password user set password 3 newpassword
ipmitool -I lanplus -H 192.168.1.100 -U admin -P password user enable 3</code></pre>
<h4>修改用户权限</h4>
<p>创建用户后，可以根据需要为用户分配不同的权限。权限分为不同的级别，如 <code>CALLBACK</code>、<code>USER</code>、<code>OPERATOR</code>、<code>ADMINISTRATOR</code> 等。使用以下命令修改用户权限：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; channel setaccess &lt;通道 ID&gt; &lt;用户 ID&gt; privilege=&lt;权限级别&gt;</code></pre>
<ul>
<li><code>&lt;通道 ID&gt;</code>：通常为 1，表示 LAN 通道。</li>
<li><code>&lt;权限级别&gt;</code>：可以是 <code>CALLBACK</code>、<code>USER</code>、<code>OPERATOR</code>、<code>ADMINISTRATOR</code> 等。</li>
</ul>
<p>例如，将用户 ID 为 3 的用户权限设置为 <code>ADMINISTRATOR</code>：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H 192.168.1.100 -U admin -P password channel setaccess 1 3 privilege=ADMINISTRATOR</code></pre>
<h4>删除用户</h4>
<p>如果某个用户不再需要，可以使用以下命令删除用户：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; user disable &lt;用户 ID&gt;
ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; user delete &lt;用户 ID&gt;</code></pre>
<p>例如，删除用户 ID 为 3 的用户：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H 192.168.1.100 -U admin -P password user disable 3
ipmitool -I lanplus -H 192.168.1.100 -U admin -P password user delete 3</code></pre>
<h3>4. 修改 IPMI 接口密码</h3>
<p>可以使用 IPMITool 修改 IPMI 接口的管理员密码。使用以下命令修改密码：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;旧密码&gt; user set password &lt;用户 ID&gt; &lt;新密码&gt;</code></pre>
<p>例如，将用户 ID 为 1（通常为管理员用户）的密码从 <code>oldpassword</code> 修改为 <code>newpassword</code>：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H 192.168.1.100 -U admin -P oldpassword user set password 1 newpassword</code></pre>
<h3>5. 传感器阈值设置</h3>
<p>可以使用 IPMITool 设置传感器的阈值，当传感器的值超过或低于阈值时，系统会触发相应的告警。以下是设置 CPU 温度传感器高阈值的示例：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; sensor thresh &lt;传感器名称&gt; upper &lt;高阈值&gt;</code></pre>
<p>例如，将 CPU 温度传感器的高阈值设置为 85 摄氏度：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H 192.168.1.100 -U admin -P password sensor thresh "CPU Temp" upper 85</code></pre>
<h3>6. 远程固件升级</h3>
<p>部分支持 IPMI 的服务器可以通过 IPMITool 进行远程固件升级。固件升级通常需要先下载最新的固件文件，然后使用 IPMITool 上传并执行升级操作。不同服务器的固件升级命令可能有所不同，一般需要参考服务器的用户手册。以下是一个简单的示例：</p>
<pre><code class="language-bash">ipmitool -I lanplus -H &lt;IP 地址&gt; -U &lt;用户名&gt; -P &lt;密码&gt; raw &lt;升级命令&gt; &lt;固件文件路径&gt;</code></pre>
<h2>五、常见问题及解决方法</h2>
<h3>1. 连接失败</h3>
<ul>
<li><strong>原因</strong>：可能是 IP 地址、用户名或密码错误，或者目标服务器的 IPMI 接口未开启。</li>
<li><strong>解决方法</strong>：检查 IP 地址、用户名和密码是否正确，确保目标服务器的 IPMI 接口已开启。可以通过服务器的 BIOS 或 BMC 管理界面进行检查和设置。</li>
</ul>
<h3>2. 命令执行无响应</h3>
<ul>
<li><strong>原因</strong>：可能是网络问题或服务器负载过高。</li>
<li><strong>解决方法</strong>：检查网络连接是否正常，尝试使用 <code>ping</code> 命令测试与目标服务器的网络连通性。如果服务器负载过高，可以等待一段时间后再尝试执行命令。</li>
</ul>
<h3>3. 权限不足</h3>
<ul>
<li><strong>原因</strong>：可能是使用的用户名没有足够的权限执行相应的命令。</li>
<li><strong>解决方法</strong>：使用具有更高权限的用户名登录 IPMI 接口，或者在服务器的 BMC 管理界面中为当前用户分配相应的权限。</li>
</ul>
<h3>4. 用户创建或权限修改失败</h3>
<ul>
<li><strong>原因</strong>：可能是用户 ID 已被使用，或者权限级别指定错误。</li>
<li><strong>解决方法</strong>：检查用户 ID 是否可用，确保权限级别指定正确。可以使用 <code>ipmitool user list</code> 命令查看已有的用户信息。</li>
</ul>
<h2>六、总结</h2>
<p>IPMITool 是一个功能强大的工具，通过它可以方便地对支持 IPMI 标准的服务器进行管理和监控。本文详细介绍了 IPMITool 的安装、基本使用、高级使用以及常见问题的解决方法。希望通过本文的介绍，你能够熟练掌握 IPMITool 的使用，提高服务器管理的效率。</p>]]></description>
    <pubDate>Wed, 17 Jun 2026 09:16:06 +0800</pubDate>
    <dc:creator>ZHappy</dc:creator>
    <guid>https://blog.zhappy.vip/?post=14</guid>
</item>
</channel>
</rss>