成功把整个网站放到自己的树莓派集群上了,现在有数据在自己手上(物理的)的感觉了。
自己动手搞了个架子,然后弄了几个开关(下方四个小开关)方便断路,并给每个开关加了个自恢复保险防止手滑短路,并且可以增加仪式感。启动集群的时候一个开关一个开关地打开感觉自己在启动核反应堆😁,不过这个24小时常开的,基本上用不太到开关功能。自恢复保险确实起了一次作用,在面包版插元件不小心短路了,直接断开。
搭建基本参照K8s官网,用的Kubeadm启动集群,Calico作为CNI。然后左上方路由器跑的HAproxy通过autossh穿透到外网,然后反代到Nginx Ingress,CEPH作为存储(另有一个现成的CEPH集群),(恩,在那个CEPH集群上再跑K8s更合理一些毕竟性能好,但我就是觉得树莓派在日常工作的桌子旁边跑更好玩…)。
内核需要自己编译,然后配置引导,参考树莓派官网,uboot形式暂时走不通。Gentoo上有很好的关于如何boot一个64bit kernel的说明。其他也遇到不少坑,其中就包括Fedora里的K8s太过陈旧,正在帮maintainer更新包发个新Release,PR已提,快了™。
在那之前我自己弄了个COPR:https://copr.fedorainfracloud.org/coprs/kasong/kubernetes/
其他大部分坑都包含在这个playbook里,可以参考,请不要直接用,IP地址域名都不通用:
- - hosts: all tasks: - name: Enable crio 1.17 dnf module command: "dnf module enable cri-o:1.17/default -y" - name: Basic K8s package yum: name: "{{ packages }}" state: installed vars: packages: - kubernetes-node - kubernetes-client - kubernetes-kubeadm - kubernetes-master - cri-tools - crio - name: Ensure overlayfs, br_netfilter is loaded lineinfile: path: "/etc/modules-load.d/kubernetes-crio.conf" line: "{{ item }}" create: yes with_items: - br_netfilter - overlay - name: Enable Kluster firewall zone firewalld: zone: pi-cluster state: present permanent: yes - name: Enable 192.168.2.0/24 to Kluster zone firewalld: source: 192.168.2.0/24 zone: pi-cluster state: enabled permanent: yes - name: Enable Kluster firewall zone firewalld: zone: intra-intra-net state: present permanent: yes - name: Enable 192.168.2.0/24 to Intra zone firewalld: source: 192.168.12.0/24 zone: intra-intra-net state: enabled permanent: yes - name: Enable 192.168.2.0/24 to Intra zone firewalld: source: 192.168.0.0/24 zone: intra-intra-net state: enabled permanent: yes - name: Enable K8s API port to Intra firewalld: port: 6443/tcp permanent: yes zone: intra-intra-net state: enabled - name: Enable K8s API port to Intra firewalld: service: ssh permanent: yes zone: intra-intra-net state: enabled - name: Enable NodePort Services to Intra firewalld: port: 30000-32767/tcp permanent: yes zone: intra-intra-net state: enabled - name: Enable crio service: name: crio enabled: yes state: started - name: Enable kubelet service: name: kubelet enabled: yes # - name: Disable ZRAM # service: # name: zram-swap # enabled: no # state: stopped - name: Enable K8s API port firewalld: port: 6443/tcp permanent: yes zone: pi-cluster state: enabled - name: Enable etcd ports firewalld: port: 2379-2380/tcp permanent: yes zone: pi-cluster state: enabled - name: Enable mdns port firewalld: service: mdns permanent: yes zone: pi-cluster state: enabled - name: Enable kubelet port firewalld: port: 10250/tcp permanent: yes zone: pi-cluster state: enabled - name: Enable kube-scheduler port firewalld: port: 10251/tcp permanent: yes zone: pi-cluster state: enabled - name: Enable kube-controller-manager port firewalld: port: 10252/tcp permanent: yes zone: pi-cluster state: enabled - name: Enable NodePort Services port firewalld: port: 30000-32767/tcp permanent: yes zone: pi-cluster state: enabled - name: Enable BGP ports firewalld: port: 179/tcp permanent: yes zone: pi-cluster state: enabled - name: QUIRK Firewalld disable nft lineinfile: dest: "/etc/firewalld/firewalld.conf" regexp: '^FirewallBackend=.*' line: 'FirewallBackend=iptables' - name: Start/Restart Firewalld service: name: firewalld state: restarted - name: QUIRK Remove invalid Kubelet config option replace: path: /etc/systemd/system/kubelet.service.d/kubeadm.conf regexp: '^(.+)--allow-privileged=([^ "]*)(.*)' replace: '\1\3' - name: QUIRK Kubelet don't depend on docker lineinfile: dest: "/usr/lib/systemd/system/kubelet.service" regexp: '^(Requires=docker.service)$' line: '# \1' backrefs: yes - name: Tell NetworkManager not to control calico interface blockinfile: create: yes path: /etc/NetworkManager/conf.d/calico.conf block: | [keyfile] unmanaged-devices=interface-name:cali*;interface-name:tunl* - name: Start/Restart NetworkManager service: name: NetworkManager state: restarted - name: K8s kernel modules blockinfile: create: yes path: /etc/modules-load.d/kubernetes-crio.conf block: | br_netfilter overlay - name: K8s kernel sysctl blockinfile: create: yes path: /etc/sysctl.d/99-calico.conf block: | net.ipv4.conf.all.rp_filter = 1 - name: K8s kernel sysctl blockinfile: create: yes path: /etc/sysctl.d/99-kubernetes-cri.conf block: | net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-ip6tables = 1 - name: Update Kubelet config lineinfile: dest: "/etc/systemd/system/kubelet.service.d/kubeadm.conf" line: 'Environment="KUBELET_CRIO_ARGS=--container-runtime=remote --container-runtime-endpoint=/var/run/crio/crio.sock"' insertbefore: "ExecStart=.*" - name: Update Kubelet config lineinfile: dest: "/etc/systemd/system/kubelet.service.d/kubeadm.conf" regexp: '^ExecStart=(((?!\$KUBELET_CRIO_ARGS).)+)$' line: 'ExecStart=\1 $KUBELET_CRIO_ARGS' backrefs: yes - name: Update CRIO config for insecure repo ini_file: dest: "/etc/crio/crio.conf" section: "crio.image" option: 'insecure_registries' value: '[ "registry.intra.intra-net.com" ]' - name: Update common container config for insecure repo ini_file: dest: "/etc/containers/registries.conf" section: "registries.insecure" option: 'registries' value: '[ "registry.intra.intra-net.com" ]' - name: Ensure /opt/cni exists for symlink creation in next step file: path: "/opt/cni" state: directory - name: Create symbolic link for CNI Plugin file: src: "/usr/libexec/cni" dest: "/opt/cni/bin" state: link - name: "Now run 'sudo kubeadm init --cri-socket /var/run/crio/crio.sock --pod-network-cidr=10.24.0.0/16'" debug: # Misc TODO: Apply a Docker mirror # # Misc TODO: Apply following config for calico yaml # - name: IP # value: "autodetect" # - name: IP_AUTODETECTION_METHOD # value: "interface=eth.*" # - name: IP6_AUTODETECTION_METHOD # value: "interface=eth.*" # # Misc TODO: Black list vc4 if kernel is failing # echo blacklist vc4 > /etc/modprobe.d/blacklist-vc4.conf # # Misc TODO: Still need old fashion cgroup # cgroup_enable=memory systemd.unified_cgroup_hierarchy=0 # # Misc TODO: Ensure following kernel configs are enabled # CONFIG_NETFILTER_XT_MATCH_CGROUP # CONFIG_F2FS_FS_SECURITY # CONFIG_CFS_BANDWIDTH # CONFIG_BLK_DEV_RBD # CONFIG_BRIDGE_NETFILTER # # Misc TODO: Tune etcd # - name: ETCD_MAX_WALS # value: "5" # - name: ETCD_HEARTBEAT_INTERVAL # value: "500" # - name: ETCD_ELECTION_TIMEOUT # value: "10000" # - name: ETCD_SNAPSHOT_COUNT # value: "5000" # - name: ETCD_LOG_LEVEL # value: "error"
正如所见,还有一堆TODO没写成playbook形式,回头需要再搭一遍的时候再说了XD。很多坑我会尝试在打包环节修一下,playbook中的一部分就不再需要了。