K8s集群部署的本质理解

K8s集群部署的本质是:在一组机器上配置和启动一组协同工作的进程,使它们能够共同提供容器编排服务。

这些进程包括:

  • 控制平面进程:负责集群的决策和管理

  • 工作节点进程:负责实际运行容器工作负载

  • 辅助进程:负责网络、存储、DNS等基础设施服务

k8s 环境部署说明

主机名ip角色
harbor.timinglee.org172.25.254.250harbor仓库
master-node172.25.254.100master,k8s集群控制节点
node1172.25.254.10worker,k8s集群工作节点
node2172.25.254.20worker,k8s集群工作节点
  • 所有节点禁用selinux和防火墙
  • 所有节点同步时间和解析
  • 所有节点安装docker-ce
  • 所有节点禁用swap,注意注释掉/etc/fstab文件中的定义

利用Ansible部署kubernetes运行环境

Ansible的本质:声明式状态管理

Ansible部署K8s的核心原理是将"目标状态"通过SSH推送到各节点,由各节点上的模块将实际状态收敛到目标状态。另外K8s本身就是声明式系统,而Ansible同样是声明式配置管理工具,两者理念天然契合。

但两者作用在不同层面:

  • Ansible:负责集群基础设施层的部署(二进制、配置、服务)

  • K8s:负责应用层的编排(Pod、Deployment、Service)

具体操作

一.安装ansible(在harbor仓库执行)
1.先配置软件仓库,再安装ansible
[root@hardor ~]# cat /etc/yum.repos.d/epel.repo
[epel]
name = epel
baseurl = https://mirrors.aliyun.com/epel/9/Everything/x86_64/
gpgcheck = 0
[root@hardor ~]# 
[root@harbor ~]# dnf install ansible-core.x86_64 ansible.noarch -y
二.配置所需用户

在生产环境中,最佳实践是使用专用用户进行部署操作,而不是直接使用root用户。

1.创建devops用户并设置密码
[root@hardor ~]# useradd  devops
useradd:用户“devops”已存在
[root@hardor ~]# echo lee | passwd --stdin devops
2.切换到devops用户并创建ansible工作目录
[root@harbor ~]# su - devops
[devops@harbor ~]$ mkdir  ansible
[devops@harbor ~]$ cd ansible/
[devops@harbor ansible]$
三.生成ansible的临时配置文件并建立运行环境
1.创建一个Ansible Inventory(主机清单)文件,这是Ansible最核心的配置文件之一。

Inventory的核心作用就三件事:

1. 告诉Ansible:管理哪些机器(IP地址/主机名)
2. 给机器分组:方便批量操作([servers]就是分组)
3. 给机器贴标签:定义变量(如用户名、密码等)

[servers]           # ← 定义了一个名为"servers"的组
172.25.254.100     # ← 组内第一个主机(Master节点)
172.25.254.20      # ← 组内第二个主机(node1-Worker节点)
172.25.254.10      # ← 组内第三个主机(node2-Worker节点)

原理解释:

  • [servers]:方括号定义一个主机组,可以对这个组内的所有主机批量执行任务

  • 下面的IP地址:组内的成员主机,Ansible通过SSH连接这些IP

  • 这是一个INI格式的Inventory文件,是最简单直观的格式

2. 创建Ansible配置文件
[devops@harbor ansible]$ vim ansible.cfg
[defaults]
inventory = /home/devops/ansible/inventory       #指定Ansible的主机清单文件位置
remote_user = root                              #指定Ansible通过SSH连接远程主机时使用的用户名
ask_pass = false       #控制Ansible是否交互式询问SSH密码,false 表示不询问密码,依赖SSH密钥认证
host_key_checking = false    #控制是否检查目标主机的SSH主机密钥,false 表示自动信任,不询问
3.Ansible Ping模块执行结果
[devops@hardor ansible]$ ansible all -m ping
172.25.254.100 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 172.25.254.100 port 22: No route to host",
    "unreachable": true
}
172.25.254.20 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 172.25.254.20 port 22: No route to host",
    "unreachable": true
}
172.25.254.10 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 172.25.254.10 port 22: No route to host",
    "unreachable": true
}
[devops@hardor ansible]$ 

这是一个Ansible Ad-Hoc命令(临时命令),用于快速测试与所有主机的连接。输出显示了3台主机的测试结果,每台主机的输出格式相同。这是Ansible部署K8s的第一步,也是最基础的验证。只有ping通了,后续的部署操作才能进行。

4.Ansible用户创建与权限配置
[devops@harbor ansible]$ ansible all -m user -a "name=devops state=present"
[devops@harbor ansible]$ ansible all -m shell -a 'echo "lee" | passwd --stdin devops'
[devops@harbor ansible]$ ansible all -m lineinfile -a 'path=/etc/sudoers line="devops    ALL=(ALL)    NOPASSWD: ALL" insertafter=EOF'

这三条命令的目的是在所有K8s节点上创建统一的部署用户,为后续的Ansible自动化部署做准备。

三条命令的具体作用

  1. 创建用户:在所有节点创建统一的devops用户

  2. 设置密码:为devops用户设置统一密码lee

  3. 配置sudo:赋予devops免密sudo权限

这是K8s部署的用户准备阶段,确保后续Ansible可以用devops用户自动化管理所有节点,同时保持安全和标准化

四.生成ansible的主配置文件并测试
1.配置文件
[devops@hardor ansible]$ cat ansible.cfg 
[defaults]
inventory = /home/devops/ansible/inventory
remote_user = root
ask_pass = false
host_key_checking = false


[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
[devops@hardor ansible]$ 

这个配置文件与之前的临时配置相比,增加了 [privilege_escalation] 段,实现了权限提升功能

配置项值含义作用
becometrue启用权限提升允许从devops提升到root
become_methodsudo提升方式使用sudo命令
become_userroot目标用户提升到root用户
become_ask_passfalse

不询问sudo

密码

依赖NOPASSWD配置

这个配置为后续K8s部署提供了安全、灵活、自动化的基础环境

2.测试
[devops@harbor ansible]$ ansible all -m shell -a 'whoami'

返回结果

172.25.254.10  | CHANGED | rc=0 >> root
172.25.254.100 | CHANGED | rc=0 >> root
172.25.254.20  | CHANGED | rc=0 >> root

虽然配置文件中的 remote_user = devops,但执行的 whoami 返回的是 root,这说明权限提升(become)生效了

五.利用ansible剧本部署docker

目的

  1. 安装Docker:容器运行时

  2. 配置网络:iptables、IP转发

  3. 配置镜像源:加速镜像拉取

  4. 配置证书:信任私有仓库

  5. 启动服务:确保Docker运行

        

Playbook的YAML结构
- name: devops k8s from ansible    # Play级别(顶层列表元素)
  hosts: all                        # 目标主机
  tasks:                            # 任务列表
    - name: setup docker repo       # Task 1
      yum_repository:               # 模块名
        name: docker                # 模块参数
        ...
    
    - name: install docker          # Task 2
      dnf:                          # 模块名
        name: docker-ce
        state: present
1.配置Docker仓库
[devops@hardor ansible]$ vim kubernetes-devops.yml 
- name: setup docker repo
  yum_repository:
    name: docker
    description: Docker CE Repository
    baseurl: http://172.25.254.250:4444/docker
    file: docker
    gpgcheck: no

结果显示

2.安装Docker
- name: install docker
  package:
    name: docker-ce
    state: present
3.配置Docker服务
- name: setup docker.service
    replace:
      path: /lib/systemd/system/docker.service
      regexp: "ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock"
      replace: "ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock  --iptables=true"
4. 配置镜像加速器
- name: setup docker registry
  copy:
    content: |
      {
        "registry-mirrors":["https://reg.timinglee.org"]
      }
    dest: /etc/docker/daemon.json
5.配置私有仓库证书
# 创建证书目录
- name: setup docker certs directory
  file:
    path: /etc/docker/certs.d/reg.timinglee.org
    state: directory

# 复制Docker证书
  - name: cp certs file
    copy:
      src: "{{item.src}}"
      dest: "{{item.dest}}"
    loop:
      - src: /etc/docker/certs.d/reg.timinglee.org/ca.crt
        dest: /etc/docker/certs.d/reg.timinglee.org/ca.crt

      - src: /etc/docker/certs.d/reg.timinglee.org/ca.crt
        dest: /etc/pki/ca-trust/source/anchors/ca.crt

  • Docker访问HTTPS私有仓库需要证书

  • 证书放在特定目录让Docker自动识别

  • 同时加入系统信任库

6.内核模块和参数配置
  - name: load module
    copy:
      dest: "{{item.dest}}"
      content: "{{item.value}}"
    loop:
      - dest: /etc/modules-load.d/docker_mod.conf
        value: br_netfilter
      - dest: /etc/sysctl.d/docker.conf
        value: |
          net.bridge.bridge-nf-call-iptables = 1
          net.bridge.bridge-nf-call-ip6tables = 1
          net.ipv4.ip_forward = 1

原理

  • br_netfilter模块:让桥接流量经过iptables

  • 内核参数:启用网络转发和桥接过滤

  • 开机自动加载br_netfilter内核模块

7.更新系统配置
- name: update ca cert and sysctl
  shell: "update-ca-trust extract && sysctl --system"

原理

  • update-ca-trust extract:更新系统证书信任库

  • sysctl --system:重新加载内核参数

8.启动服务
  - name: start services
    service:
      name: "{{item}}"
      state: restarted
      enabled: yes
    loop:
      - docker
      - systemd-modules-load.service

循环的两个服务:

  1. 重启Docker服务

  2. 重启模块加载服务

9.结果显示

六.利用ansible安装cri-dockerd
为什么要安装cir-dockerd

cri-dockerd是一个"翻译器",将CRI接口调用转换为Docker API调用,让K8s继续使用Docker作为容器运行时

1.解压cri-dockerd安装包
[devops@harbor ansible]$ tar zxf cri-dockerd-0.4.4.amd64.tgz
2.进入cri-dockerd目录并编辑服务配置文件
[devops@harbor ansible]$ cd cri-dockerd
[devops@harbor cri-dockerd]$ vim cri-docker.service
[Service]
Type=notify
ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --pod-infra-container-image=reg.timinglee.org/k8s/pause:3.10.1 
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always

作用:

  1. 通过Type=notify让服务主动通知systemd就绪状态,

  2. 通过ExecStart指定cri-dockerd的启动命令及关键参数(使用fd://与Docker通信、启用CNI网络插件、指定私有仓库的pause基础镜像)

  3. 通过ExecReload实现配置的热重载

  4. 通过TimeoutSec=0取消超时限制

  5. 通过Restart=always和RestartSec=2确保服务崩溃后2秒自动重启,从而保证cri-dockerd作为K8s与Docker之间的CRI适配器能够稳定、可靠地持续运行

3.在playbook添加新内容
- name: setup cri-dockerd
  copy:
    src: "{{item.src}}"
    dest: "{{item.dest}}"
    mode: '0755'
  loop:
    - src: ./cri-dockerd/cri-dockerd
      dest: /usr/bin/cri-dockerd

    - src: "./cri-dockerd/cri-docker.service"
      dest: "/lib/systemd/system/cri-docker.service"

    - src: "./cri-dockerd/cri-docker.socket"
      dest: "/lib/systemd/system/cri-docker.socket"

作用: 将控制节点上的cri-dockerd文件复制到所有目标主机

- name: update ca cert
  shell: "update-ca-trust extract;sysctl --system;systemctl daemon-reload"

作用: 一次性执行三个系统更新命令

- name: start services
  service:
    name: "{{item}}"
    state: restarted
    enabled: yes
  loop:
    - docker
    - systemd-modules-load.service
    - cri-docker

作用: 重启三个关键服务,确保cri-dockerd在所有节点上正常运行,为K8s使用Docker作为容器运行时做好准备

七.利用ansible部署k8s软件
1.配置k8s仓库
  - name: setup k8s repo
    yum_repository:
      name: kubernetes
      description: kubernetes
      baseurl: https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.35/rpm
      file: kubernetes
      gpgcheck: no
2.安装Master节点软件
  - name: install software in master
    dnf:
      name: "{{item}}"
      state: present
    loop:
      - kubeadm-1.35.7-150500.1.1
      - kubelet-1.35.7-150500.1.1
      - kubectl-1.35.7-150500.1.1
    when: inventory_hostname == "172.25.254.100"
3.安装Worker节点软件
  - name: install software in work node
    dnf:
      name: "{{item}}"
      state: present
    loop:
      - kubeadm-1.35.7-150500.1.1
      - kubelet-1.35.7-150500.1.1
    when: inventory_hostname == "172.25.254.10" or inventory_hostname == "172.25.254.20"
4.配置命令补全
  - name: setup kubectl kubeadm complication
    lineinfile:
      path: /root/.bashrc
      line: |
        source <(kubectl completion bash)
        source <(kubeadm completion bash)
    when: inventory_hostname == "172.25.254.100"
5.启动kubelet
  - name: start kubelet
    service:
      name: kubelet
      state: started
      enabled: yes

作用:这个Playbook完成了K8s软件的差异化部署,根据节点角色安装不同组件,为后续的集群初始化(kubeadm init)和节点加入(kubeadm join)做好准备。

6.让补齐功能生效
 source  ~/.bashrc
八.下载kubernetes集群所需镜像
[root@master ~]# kubeadm config images list

1.将以上镜像下载下来,上传到本地harbor

先登录私有仓库

[root@master ~]# docker  login  reg.timinglee.org -u admin
2.重新打标签
docker images --format "{{.Repository}}:{{.Tag}}" | awk -F "/" '/google/{system("docker tag "$0" reg.timinglee.org/k8s/"$3)}'
3.推送镜像
docker images --format "{{.Repository}}:{{.Tag}}" | awk -F "/" '/timinglee/{system("docker push "$0)}'

结果显示(下载的镜像都在k8s项目中)

九.在master中初始化kubernetes集群
1. 在Master节点上初始化Kubernetes集群控制平面
[root@master ~]# kubeadm init --pod-network-cidr=10.244.0.0/16 \
--image-repository reg.timinglee.org/k8s \
--kubernetes-version v1.35.7 \
--cri-socket=unix:///var/run/cri-dockerd.sock
2.在两个work节点加入到Kubernetes集群
kubeadm join 172.25.254.100:6443 \
  --token tdwjoc.8d1yw3wl4r4tm6c4 \
  --discovery-token-ca-cert-hash sha256:4d948d67f380a0f55a42a3092fd2737a4a02c066c791a79ba3ac93ce3d67a8dc \
  --cri-socket=unix:///var/run/cri-dockerd.sock

sha256:4d948d67f380a0f55a42a3092fd2737a4a02c066c791a79ba3ac93ce3d67a8dc是我的哈希值,每个人的都不同

十.添加kubernets环境变量到本机和添加node节点到本集群

在msater上

[root@master ~]# echo "export KUBECONFIG=/etc/kubernetes/admin.conf" > ~/.bash_profile
[root@master ~]# source  ~/.bash_profile

在worker节点

kubeadm join 172.25.254.100:6443 --token jl4ztx.cax3iysvu7onsh5s --discovery-token-ca-cert-hash sha256:6b5950ef2cdba85d6dfdb564ee90d4187fa3d341767dc9852cbdd5c9dee4f927 --cri-socket=unix:///var/run/cri-dockerd.sock
十一.安装网络插件
1. 解压Flannel安装包
tar zxf kube-flannel-v0.28.9.tar.gz
2.加载Flannel镜像
docker load -i kube-flannel-v0.28.9.tar
3.给镜像打标签
docker tag ghcr.io/flannel-io/flannel-cni-plugin:v1.9.1-flannel1 reg.timinglee.org/flannel-io/flannel-cni-plugin:v1.9.1-flannel1
docker tag ghcr.io/flannel-io/flannel:v0.28.9 reg.timinglee.org/flannel-io/flannel:v0.28.1
docker push reg.timinglee.org/flannel-io/flannel-cni-plugin:v1.9.1-flannel1
docker push reg.timinglee.org/flannel-io/flannel:v0.28.9

结果

4.修改配置文件
vim kube-flannel.yml
148行 image: flannel-io/flannel:v0.28.9
175行 image: flannel-io/flannel-cni-plugin:v1.9.1-flannel3
186行 image: flannel-io/flannel:v0.28.9

5.将Flannel网络插件的配置应用到Kubernetes集群
kubectl apply -f kube-flannel.yml

测试

总结

至此k8s集群部署完成,核心经验总结

  1. Ansible自动化:减少手动操作,提高效率

  2. 私有仓库:加速部署,支持离线

  3. cri-dockerd:解决K8s与Docker兼容性

  4. 版本统一:所有组件版本一致

  5. 安全实践:最小权限、认证机制

  6. 网络规划:Pod网络与Service网络分离

更多推荐