k8s集群自动化部署01——通过Ansible进行k8s节点的基础环境配置
#k8s集群部署# #Ansible#
前期手动部署了k8s集群,过程比较复杂,为了提高集群部署的效率,所以决定做一下自动化部署,为此,最近学习了ansible,同时也进一步巩固一下k8s基础知识。
刚完成了基础环境配置部分,记录一下,如有建议请不吝赐教。我使用的操作系统是RockyLinux 9,最小化安装,集群为3master+2node。
1、服务管理
在部署期间,可以暂时关闭防火墙,以减少因端口问题产生的问题(生产环境中,完成部署后,要开启防火墙,按需开放端口);
- name: Stop and disable firewalld
ansible.builtin.systemd: name=firewalld state=stopped enabled=no
另外需要关闭SELinux,这是Linux内核的强制访问控制安全模块,主要用来限制进程对文件、端口、资源的访问,K8s + Docker/containerd + CNI 网络插件,很容易和 SELinux 策略冲突,导致容器无法挂载目录、端口无法绑定、socket无法访问、容器启动失败等问题,生产环境可以配置SELinux策略+容器securityContext。
- name: Disable SELinux immediately
ansible.builtin.command: setenforce 0
changed_when: true
ignore_errors: yes
- name: Disable SELinux permanently
ansible.builtin.selinux: state=disabled
- name: Disable SELinux in /etc/sysconfig/selinux
ansible.builtin.replace:
path: /etc/sysconfig/selinux
regexp: '^SELINUX=enforcing'
replace: 'SELINUX=disabled'
ignore_errors: yes
一般Linux中会有dnsmasq服务,属于轻量dns缓存+dhcp服务,其端口(53)会与k8s集群的CoreDNS端口冲突,也要关闭。
- name: Stop and disable dnsmasq
ansible.builtin.systemd:
name: dnsmasq
state: stopped
enabled: no
本集群中日志方面使用的是rsyslog服务,原因如下:①默认预装,不用额外安装,节点零侵入;②轻量、高性能、低资源占用;③稳定可靠、配置简单;④完美适配k8s容器日志架构,不依赖容器运行时日志驱动;⑤方便对接各种日志平台。
- name: Enable and start rsyslog
ansible.builtin.systemd:
name: rsyslog
state: started
enabled: yes
2、关闭SWAP
SWAP本质是从磁盘取一部分空间,作为“低速内存”,当内存不足时缓解内存压力,但磁盘速度比内存慢上万倍,而k8s集群的硬性需求是高并发、低延迟,一旦使用SWAP,Pod响应延迟将会暴增、接口超时,相关网络组件(kube-proxy、Calico、CoreDNS)对延迟和内存及其敏感……据说k8s官方设计之初就假设所有容器只使用物理内存,不依赖磁盘交换,在新版集群中,kubelet启动会硬性校验/proc/meminfo,如果SWAP不为0,则直接启动失败。
- name: Disable swap immediately
ansible.builtin.command: swapoff -a
changed_when: true
ignore_errors: yes
- name: Comment out swap entries in fstab
ansible.builtin.replace:
path: /etc/fstab
regexp: '^([^#].*swap)'
replace: '#\1'
backup: yes
- name: Set vm.swappiness to 0
ansible.builtin.sysctl:
name: vm.swappiness
value: '0'
state: present
reload: yes
3、基础软件和系统方面配置
3.1 host解析
- name: Configure /etc/hosts
ansible.builtin.blockinfile:
path: /etc/hosts
block: |
10.0.1.31 k8s-master01
10.0.1.32 k8s-master02
10.0.1.33 k8s-master03
10.0.1.41 k8s-node01
10.0.1.42 k8s-node02
marker: "# {mark} ANSIBLE MANAGED BLOCK"
backup: yes
3.2 配置yum源
#配置yum源:注释mirrorlist
- name: Comment out mirrorlist in repo files
ansible.builtin.replace:
path: "{{ item }}"
regexp: '^mirrorlist='
replace: '#mirrorlist='
backup: yes
loop: "{{ lookup('fileglob', '/etc/yum.repos.d/*.repo') }}"
#配置yum源:替换为阿里云baseurl
- name: Replace baseurl with Aliyun mirror
ansible.builtin.replace:
path: "{{ item }}"
regexp: '^#baseurl=http://dl\.rockylinux\.org/\$contentdir'
replace: 'baseurl=https://mirrors.aliyun.com/rockylinux'
backup: yes
loop: "{{ lookup('fileglob', '/etc/yum.repos.d/*.repo') }}"
#更新缓存
- name: Update yum cache
ansible.builtin.command: yum makecache
changed_when: true
3.3 安装基础软件
这里将epel跟其他软件分开安装了,因为这个epel-release 是一个特殊的 RPM,它会创建 /etc/yum.repos.d/epel*.repo 仓库文件。如果把它和依赖 EPEL 源的包(如 ntpsec)放在同一个 dnf 任务里,第一次执行时 dnf 可能还没刷新到新仓库,导致找不到包而报错。
- name: Install epel-release repository
ansible.builtin.dnf:
name: epel-release
state: present
- name: Install base packages
ansible.builtin.dnf:
name:
- git
- vim
- wget
- jq
- psmisc
- net-tools
- telnet
- device-mapper-persistent-data
- lvm2
- yum-utils
- ntpsec
- ipvsadm
- ipset
- sysstat
- conntrack
- libseccomp
state: present
enablerepo: epel
update_cache: yes
3.4 系统升级
基础软件安装完后,做一次系统升级
- name: Upgrade all packages
ansible.builtin.dnf:
name: '*'
state: latest
update_cache: yes
3.5 配置时区与时间同步
- name: Set timezone to Shanghai
ansible.builtin.file:
src: /usr/share/zoneinfo/Asia/Shanghai
dest: /etc/localtime
state: link
force: yes
- name: Set timezone file
ansible.builtin.copy:
content: "Asia/Shanghai\n"
dest: /etc/timezone
mode: '0644'
- name: Sync time with ntpdate
ansible.builtin.command: /usr/sbin/ntpdate time2.aliyun.com
changed_when: true
- name: Add ntpdate to crontab
ansible.builtin.cron:
name: "sync time with aliyun ntp"
minute: "*/5"
job: "/usr/sbin/ntpdate time2.aliyun.com"
3.6 系统资源配置
blockinfile模块功能:①在指定文件中插入/更新一整块多行文本;②通过marker标记区块,幂等执行(同一个操作执行多次,结果保持一致);③只修改标记范围内的内容,不影响其他原有配置。
/etc/security/limits.conf是Linux PAM资源限制配置文件,控制系统用户/进程的:最大打开文件数、最大进程数、内存锁定等限制。
*表示对所有用户生效(含root、普通用户、容器进程);soft表示软限制,系统默认上限,进程可临时调高至hard值;hard表示硬限制,为最高上限,进程无法突破。
nofile:最大可打开文件句柄数
nproc:最大用户进程数
memlock:锁定内存,设置为unlimited,不限制锁定内存大小,防止关键进程内存被换入SWAP。
- name: Configure system limits
ansible.builtin.blockinfile:
path: /etc/security/limits.conf
block: |
* soft nofile 65536
* hard nofile 131072
* soft nproc 65535
* hard nproc 655350
* soft memlock unlimited
* hard memlock unlimited
marker: "# {mark} ANSIBLE MANAGED BLOCK"
backup: yes
3.7 k8s网络相关内核模块配置
第一部分:
modprobe:等价系统命令modprobe 模块名
overlay:容器叠加网络模块,负责容器跨主机通信,Flannel、Calico等主流CNI都依赖
br_netfilter:网桥网络过滤模块,开启iptables对网桥流量的转发/过滤;
以上两个模块是容器网络的基础,不加载则CNI插件无法正常工作。
第二部分 :
kube-proxy有两种模式:iptables(默认)和IPVS(高性能负载均衡)
临时加载IPVS全套调度模块,保证kube-proxy切换到IPVS模式可以正常运行。
第三部分:
路径/etc/modules-load.d/*.conf是systemd标准目录,其中为内核模块列表,开机自动加载,前两部分是modprobe临时加载(立即生效,重启后丢失),这里是永久生效(重启后由systemd-modules-load读取配置后再加载)。
第四部分:
systemd-modules-load是systemd自带服务,专门负责开机读取/etc/modules-load.d/下的配置、自动加载内核模块。
#加载k8s网络相关内核模块
- name: Load overlay and br_netfilter modules
ansible.builtin.modprobe:
name: "{{ item }}"
state: present
loop:
- overlay
- br_netfilter
- name: Load ipvs kernel modules
ansible.builtin.modprobe:
name: "{{ item }}"
state: present
loop:
- ip_vs
- ip_vs_rr
- ip_vs_wrr
- ip_vs_sh
- nf_conntrack
#配置开机自动加载的模块(ipvs.conf)
- name: Create ipvs modules load config
ansible.builtin.copy:
dest: /etc/modules-load.d/ipvs.conf
content: |
ip_vs
ip_vs_lc
ip_vs_wlc
ip_vs_rr
ip_vs_wrr
ip_vs_lblc
ip_vs_lblcr
ip_vs_dh
ip_vs_sh
ip_vs_fo
ip_vs_nq
ip_vs_sed
ip_vs_ftp
ip_vs_sh
nf_conntrack
ip_tables
ip_set
xt_set
ipt_set
ipt_rpfilter
ipt_REJECT
ipip
mode: '0644'
- name: Enable systemd-modules-load service
ansible.builtin.systemd:
name: systemd-modules-load
state: started
enabled: yes
ignore_errors: yes
3.8 内核优化配置
第一部分:
/etc/sysctl.d/是systemd管理的内核参数目录,目录下所有.conf文件都会被统一加载,永久生效。
单独建立k8s.conf文件,和系统配置解耦,便于维护、排查、回滚。
第二部分:
生效所有sysctl配置
- name: Configure sysctl for Kubernetes
ansible.builtin.copy:
dest: /etc/sysctl.d/k8s.conf
content: |
#网络转发
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
fs.may_detach_mounts = 1
net.ipv4.conf.all.route_localnet = 1
#内存管理
vm.overcommit_memory = 1
vm.panic_on_oom = 0
#文件描述符、inotify
fs.inotify.max_user_watches = 89100 #值偏低,建议改为524288
fs.file-max = 52706963
fs.nr_open = 52706963
#连接追踪
net.netfilter.nf_conntrack_max = 2310720
#tcp保活与孤儿连接回收
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_max_orphans = 327680
net.ipv4.tcp_orphan_retries = 3
#高并发与syn flood防护
net.ipv4.tcp_max_tw_buckets = 36000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_timestamps = 0
net.core.somaxconn = 16384
mode: '0644'
- name: Apply sysctl configuration
ansible.builtin.command: sysctl --system
changed_when: true
3.8 master01节点克隆源码
可以在master01上提前准备Calico、krm、metrics-server的源码。
- name: Clone k8s-ha-install repository on master01
ansible.builtin.git:
repo: https://xxxx
dest: /root/
when: inventory_hostname == (groups['master'] | first)
4、其他说明
Ansible 执行每个任务后会报告三种状态之一:
ok(绿色):已处于期望状态,无需修改
changed(黄色):执行了修改操作
failed(红色):执行失败
在上述配置中很多地方都使用了changed_when: true,表示无论实际有没有发生变化,都显示为 changed(黄色)。原因是:比如command 模块只能执行命令,它无法判断其命令是否真的修改了 某服务的状态(可能本来已经修改了)。默认情况下,command 模块每次都会返回 changed,但 Ansible 有时会提示你确认这一点。显式写上 changed_when: true 就是告诉 Ansible:“我知道这个命令会改变系统状态,每次都报 changed 即可”。
更多推荐
所有评论(0)