K8s笔记之一:在N1集群上部署Kubernetes
硬件说明
2019年的时候听说了斐讯N1这个好东西,因为P2P翻车给市场提供了大量的便宜货,相比当年市场上那些垃圾货,这个的性价比非常好,所以一下买了四个。时过境迁,现在N1的价格已经涨了,市场高性能的便宜盒子也出了几代,比如一些同样用晶晨SoC的运营商盒子,只要N1一半的价格,N1的优势已经不大了。
我的四个N1做了很多用途:一个刷成电视盒子接在旧电视上看电视,一个刷了OMV做NAS,两个刷了Armbian Buster跑ELK。
现在过了一年多,我自己也因为主服务器换了一台AMD A12-9800E(现在又升级成Ryzen3 5300U了),性能比原来的Intel J1900好了很多,所以ELK什么的都迁到新服务器上了。又因为托某个壕朋友的福,送了我一台白裙,所以OMV的NAS也不需要了。于是一下空出三台N1来。
于是想点办法来用起来,就搞了这么个集群来跑Kubernetes玩玩——虽然在主服务器跑三个虚拟机也不是不行,但是虚拟集群毕竟不如物理集群爽。
基本安装配置
当然是先把系统全部重刷一遍,都用Armbian Buster。然后跑一个Ansible剧本做一下基本配置并安装Docker。然后用一个新的角色来安装Kubernetes。
- roles
- k8s
- files
- docker.systemd
- handler
- main.yml
- tasks
- main.yml
- files
- k8s
docker配置
其中docker.systemd是docker的配置文件,用于增加一个代理,因为k8s的docker源在国内无法直接访问。当然另外一个方法是修改k8s的配置,让它使用国内镜像,这个可以参考别的文章。
[Service]
Environment="HTTP_PROXY=http://proxy_ip:proxy_port"
Environment="HTTPS_PROXY=http://proxy_ip:proxy_port"
systemd配置
handler的main.yml用于修改docker配置后重启docker。
---
- name: Restart docker
systemd:
name: docker
state: restarted
daemon_reload: yes
注意,这里用的不是service模块,而是systemd模块,并且其中需要加上daemon_reload,让systemd重新加载配置,不然重启docker也没用。
角色任务
tasks的main.yml用于安装k8s。
安装前有几个配置工作:
- docker服务配置代理,用于下载k8s镜像
- 安装和配置arptables和ebtables
- 禁用swap
之后为k8s安装工作。
---
- name: Create directory for docker config
file:
path: /etc/systemd/system/docker.service.d
state: directory
recurse: yes
owner: root
group: root
mode: 0775
- name: Copy docker config file
copy:
src: docker.systemd
dest: "/etc/systemd/system/docker.service.d/override.conf"
mode: '0644'
notify:
- Restart docker
- name: Install packages
apt:
pkg:
- arptables
- ebtables
update_cache: no
install_recommends: no
autoremove: yes
autoclean: yes
environment: "{{ proxy_env }}"
- name: Update alternatives
alternatives:
name: "{{ item.name }}"
path: "{{ item.path }}"
with_items:
- { name: 'iptables', path: '/usr/sbin/iptables-legacy' }
- { name: 'ip6tables', path: '/usr/sbin/ip6tables-legacy' }
- { name: 'arptables', path: '/usr/sbin/arptables-legacy' }
- { name: 'ebtables', path: '/usr/sbin/ebtables-legacy' }
- name: Turn off swap
command: swapoff -a
- name: Turn off swap forever
lineinfile:
path: /etc/fstab
regexp: "^([^#].*none\\s+swap\\s+sw.*)$"
line: "#\\g<1>"
backrefs: yes
- name: Add apt signing key of kubernetes
apt_key:
url: "https://packages.cloud.google.com/apt/doc/apt-key.gpg"
state: present
environment: "{{ proxy_env }}"
- name: Add repository of kubernetes
apt_repository:
repo: "deb https://apt.kubernetes.io/ kubernetes-xenial main"
state: present
environment: "{{ proxy_env }}"
- name: Actually install kubernetes
apt:
pkg:
- kubelet
- kubeadm
- kubectl
state: latest
update_cache: yes
install_recommends: no
environment: "{{ proxy_env }}"
- name: Hold kubernetes version
dpkg_selections:
name: "{{ item.name }}"
selection: hold
with_items:
- { name: 'kubelet' }
- { name: 'kubeadm' }
- { name: 'kubectl' }
- name: Get kubernetes images
shell: kubeadm config images pull
安装后配置
三台N1都用上面的剧本完成基本安装后,开始分别安装K8s环境。
首先在其中一台N1(比如叫KUBESVR1)配置Control Plane(就是Master Node,因为狗日的政治正确而改成这样莫名其妙的名字,暂时先不考虑高可用集群配置):
安装网络
K8s支持多种不同的Pod网络插件,这里以最基础的Flannel为例:
# 常规操作是这样:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 但由于国内的网络问题,建议还是先下载这个yml文件,然后在本地安装:
kubectl apply -f kube-flannel.yml
安装完后打开这个yaml文件,可以看到这么一段:
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan"
}
}
这个网段就是Flannel所用的网段。
初始化Control Plane
准备工作:
确认Control Plane节点的CPU至少是双核(N1是4核所以没问题)
# 如果PATH里没有sbin要加上
export PATH=/sbin:$PATH
开始安装Control Plane
kubeadm init --pod-network-cidr 10.244.0.0/16
其中的网段就是Flannel的,如果使用不同的网络插件,要就指定不同的网段。
初始化完成后返回这么一段内容:
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a Pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
/docs/concepts/cluster-administration/addons/
You can now join any number of machines by running the following on each node
as root:
kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
其中包含几个重要信息:
第一:如果要用非root用户操作kubectl,则需要在用户目录下创建.kube/config
第二:如果要在集群里部署应用,则使用kubectl apply命令
第三:如果有其它节点要加入这个集群,则使用kubeadm join命令,参数中的token和hash要注意安全保存,如果忘记记录token,可以用kubeadm token list
查看
第四:token的有效期只有24小时,过期后需要重新创建kubeadm token create
添加节点
在其它节点(即Slave Node)上简单使用上面提示的命令运行即可:
kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
在另两台N1(KUBESVR2,KUBESVR3)上执行这个命令,完成集群的组建。
现在回到Control Plane(KUBESVR1),运行:
kubectl get nodes
即可查看此Control Plane管理的集群中的节点。
至此K8s集群搭建完成,之后就可以通过Control Plane在集群里部署应用了。
顺便说一下,如果一个节点要退出集群,可以用:
kubeadm reset
需要再次加入时则再执行join命令。
故障排除
如果kubectl get nodes
返回节点状态是NotReady
则需要检查一下节点详情:
kubectl describe node <node_name>
在返回结果里搜索相关的关键字查找错误原因,比如未安装网络会导致network plugin is not ready: cni config uninitialized
错误。
如果确定网络已经安装,新增节点仍然报这个错误,可以看一下是否没有下载成功flannel镜像,有时会因为网络问题导致下载失败,手工下载一下即可。
推送到[go4pro.org]