前言 早在 2022
年就有打算部署一套云原生组件,奈何手头繁忙,最终还是先按照单体应用,清单如下:
以 docker-compose
的方式运行单体应用
以 Jenkins
负责 CI/CD
以 GitLab
负责代码存储
以 Nginx
负责 LB
下方为早期单体应用构想图:
家里有一台旧笔记本,上面的组件都部署在了那台笔记本上,系统是 Ubuntu
,开了两台虚拟机(如果你没搭建过 Ubuntu Server
,你可以看下这篇文章:Ubuntu Server 20.04 安装教程 )。不难发现,单体应用的部署也可以用上自动化部署 CICD
,去年一整年,我私人的项目都是用这样的方式部署,它有如下优点:
简单,易操作,不用再用 nohop jar
的方式启动一个 java
程序
它支持在 Windows
操作系统上部署
它适合小型项目,流量小,短暂断流没有影响的网站
它适合小型公司部署项目,简化项目部署流程,简化测试环境
它也有如下缺点:
虽然能多副本,但没有滚动更新机制
没有自动伸缩,只能通过修改 docker-compose
配置文件,手动伸缩副本数
中间件也需要手动用 docker-compose
部署,如果遇到单点故障,需要手动去服务器上重启
无法侦测流量的传输,Prometheus
和 Grafana
等其他组件也需要手动部署
没有自愈能力,没有异地容灾,仅靠 docker-compose
的重启策略很难做到高可用
没有好的商店环境等等…
单体应用简单,但有时经不起考验。很多服务也没有使用 DDD
思想编写,也没有微服务的概念,大多都是一把梭,全部柔成一个服务,无法水平扩展服务 ,也无法水平扩展节点 。有时候问题源于需求,很多公司没有这种需求,也自然不会遇到集群部署的问题。因此,2023
年的目标就是部署一套微服务架构,将单体应用转型。
环境声明
hostname
系统
配置
节点
角色
部署
m1
Ubuntu-Server(20.04)
2c4g
192.168.0.67/32
control-plane,etcd,master
k3s(v1.24.6+k3n1) server nginx rancher(2.7.1) Helm(3.10.3)
n1
Ubuntu-Server(20.04)
1c2g
192.168.0.102/32
control-plane,etcd,master
k3s(v1.24.6+k3n1) server
m2
Ubuntu-Server(20.04)
2c4g
172.25.4.244/32
control-plane,etcd,master
k3s(v1.24.6+k3n1) server
harbor
Ubuntu-Server(20.04)
2c4g
192.168.0.88
Docker-Hub Jenkins CI/CD
Harbor(2.7.1) Jenkins(2.3) Docker-Compose
节点均用 WireGuard 打通内网,后续所有节点路由均用内网ip访问,具体详细的节点内容请访问上一篇文章
n1 节点因为内存小,当初设想的是以 Worker 节点部署,但由于 etcd 的特性,如果只有两台节点部署 etcd ,它的容错仍为 0
,所以这个节点虽然叫 n1,但它其实也是 Master 节点 ,为了不影响后续的主机名解析,暂时不会更换这个节点的 hostname。这里的 LB 我共用了 m1 节点,如果你的机器够多,你最好将它单独移出 ,它不需要多大的内存和 cpu ,仅作为内网流量的转发。
我没有开启那些 k3s 常用的端口,因为所有的端口都通过 51820
建立 TCP连接 ,以 WireGuard 加密的方式,通过 UDP协议传输。这不是一个去中心化的网络,因为 m1 和 n1 是内网互通的,因此少了一条 VPN 网络。由于 WireGuard 可以映射内网地址,因此即便 m2 的内网 ip 不在 192.168.0.0/24
网段上,也无可厚非,因为我们是通过 wg0
这个网卡传输,所以只需要开启 ipv4 转发即可。后续所有的地址也都会按照内网地址配置,就好像这几个节点都在“一个网段”一样。
准备工作 除非特殊声明,否则本文所有的命令均需要用到 root
用户
密钥登录 修改密钥登录是一个危险的步骤,请确保当前 ssh 连接不要断开 ,否者配置出错会导致你无法登录到服务器。本操作并非必须 ,只是由于云服务器暴露外网,经常遭受机器人暴力破解密码,如果你的 k3s 仅在内网访问,可不执行此步骤
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ssh-keygen -t rsa -f /root/.ssh/id_rsa -N '' cd /root/.ssh/cat id_rsa.pub >> authorized_keyssudo chmod 600 authorized_keyssudo chmod 700 ~/.sshnano /etc/ssh/sshd_config RSAAuthentication yes PubkeyAuthentication yes PermitRootLogin yes PasswordAuthentication no service sshd restart
最后在你所用的连接软件中,选择密钥登录即可,下面是 MobaXterm 的示例图:
时间同步
1 2 3 4 5 6 7 8 9 sudo apt-get install ntpdate -yntpdate cn.pool.ntp.org hwclock -w reboot
对于 etcd 而言,时间同步是一个很重要的步骤。节点延迟过长,网络阻塞,时间未同步,都会导致节点异常
修改主机名
1 hostnamectl set-hostname 各个节点的主机名
修改 hosts
1 2 3 4 5 6 7 nano /etc/hosts 192.168.0.67 m1 192.168.0.102 n1 192.168.0.88 harbor 172.25.4.244 m2
关闭防火墙
1 2 systemctl disable ufw systemctl stop ufw
安装 Docker
1 2 3 4 apt-get install docker -y
禁用交换空间
为什么要禁用交换空间?
Leopold:为什么要禁用交换空间?
ChatGPT:Kubernetes 在部署容器时,建议执行 swapoff -a
命令,这是因为在使用容器时启用交换空间会导致性能问题。
交换空间是在物理内存不足时使用的一种内存管理技术,它将部分内存数据移动到硬盘中的虚拟内存中,以便腾出更多的物理内存空间。但是,交换空间的使用会导致 I/O 操作频繁,这会影响应用程序的性能。
在容器环境下,每个容器都有自己的内存限制,而启用交换空间会导致容器使用的内存不受控制。当容器的内存使用量超过限制时,操作系统会将容器内存中的数据移动到硬盘上,这可能会导致应用程序性能下降。
因此,为了确保容器环境下的性能和稳定性,建议在 Kubernetes 中执行 swapoff -a
命令,以禁用交换空间并避免出现性能问题。这样,操作系统就会强制执行容器的内存限制,并且不会将容器内存中的数据移动到硬盘中,从而提高应用程序的性能和稳定性。
1 2 swapoff -a sed -i '/swap/s/^/#/' /etc/fstab
开启内核转发
为什么要开启内核转发?
Leopold:为什么要开启内核转发?
ChatGPT:Kubernetes需要执行net.ipv4.ip_forward=1
和net.bridge.bridge-nf-call-iptables=1
的原因是为了实现容器间和宿主机之间网络通信和网络隔离。
net.ipv4.ip_forward=1
开启了IP转发功能,使得在Kubernetes集群中的不同节点上运行的Pod可以互相通信,以及可以与集群外部的网络进行通信。当Pod要发送数据包到集群外部的网络时,需要它所在的节点将该数据包转发出去,开启IP转发功能可以使得节点可以转发数据包。
net.bridge.bridge-nf-call-iptables=1
开启了iptables的桥接模式,使得在容器之间的流量可以通过iptables规则进行管理,实现了对容器网络流量的控制和管理。当容器之间发生网络通信时,数据包会经过宿主机的iptables进行NAT转换和过滤,保障了网络安全和隔离。
因此,开启net.ipv4.ip_forward=1
和net.bridge.bridge-nf-call-iptables=1
可以实现Kubernetes集群的网络通信和网络隔离。
1 2 3 4 5 6 7 8 nano /etc/sysctl.conf net.ipv4.ip_forward=1 net.bridge.bridge-nf-call-iptables=1 sysctl -p /etc/sysctl.conf
离线安装 K3s
我的很多问题都是参照中文文档和 Git issue 解决的,很多配置一定要注意对应版本,网上千篇一律的解决方法可能还不如直接去官网查来的更准确,如果你 go 学的不错,你甚至能定位到一些问题的根本原因。
下载安装脚本与二进制文件
下载 k3s 二进制文件:Releases · k3s-io/k3s (github.com) k3s 和 k3s-airgap-images-amd64.tar,上传至 /root/zip/k3s/
1 2 3 4 5 6 7 8 9 10 11 12 mkdir -p /root/zip/k3smkdir -p /k3s/wget -O /root/zip/k3s/k3s-install.sh https://rancher-mirror.rancher.cn/k3s/k3s-install.sh chmod a+x /root/zip/k3s/k3schmod a+x /root/zip/k3s/k3s-install.shcp /root/zip/k3s/k3s-install.sh /k3s/cp /root/zip/k3s/k3s /usr/local/binmkdir -p /var/lib/rancher/k3s/agent/images/cp /root/zip/k3s/k3s-airgap-images-amd64.tar /var/lib/rancher/k3s/agent/images/
请严格确认 kubelet 使用版本和 rancher 是否支持,在 rancher release 上都有注明,亲测版本不对会装不上,或者导入不进去。版本指定是一个很重要的概念,对你排查问题和系统稳定有着决定性的作用,也为你后续升级省下不少事。由于网络问题,这些二进制包下载很慢,所以我们采用离线部署的方式,手动下载,并将二进制包放到对应位置即可。
配置安装参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 mkdir -p /etc/rancher/k3s/nano /etc/rancher/k3s/config.yaml tls-san: - 192.168.0.67 - 192.168.0.102 - 172.25.4.244 - 10.43.0.1 cluster-init: true
cluster-init
表示我们初始化 etcd,后续节点加入的时候会自动忽略这个参数。tls-san
用于 etcd 证书可信任域名/IP配置
Master 节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 INSTALL_K3S_SKIP_DOWNLOAD=true INSTALL_K3S_EXEC='server --docker' K3S_DATASTORE_ENDPOINT="etcd" /k3s/k3s-install.sh cat /var/lib/rancher/k3s/server/tokenINSTALL_K3S_SKIP_DOWNLOAD=true K3S_TOKEN=m1的token INSTALL_K3S_EXEC='server --docker --server https://m1:6443 --node-ip m2的本地ip --node-external-ip wg0网卡ip' K3S_DATASTORE_ENDPOINT="etcd" /k3s/k3s-install.sh INSTALL_K3S_SKIP_DOWNLOAD=true K3S_TOKEN=m1的token INSTALL_K3S_EXEC='server --docker --server https://m1:6443' K3S_DATASTORE_ENDPOINT="etcd" /k3s/k3s-install.sh
报错点我
此处是报错最容易出现、且是二进制安装最复杂的问题。如果出现问题,请先执行 journalctl -xfu k3s
报错可能原因有:
未禁用缓存 :swapoff -a
多次安装但环境清除不干净:starting kubernetes: preparing server: bootstrap data already found and encrypted with different token
,
使用 /usr/local/bin/k3s-uninstall.sh
先删除,再停止 docker
相关容器
etcd 错误:如果你想部署三台含有 etcd
的 Master
,其他节点加入 etcd
如果超时,请重启三台节点的 k3s
服务即可:systemctl restart k3s
,这是由于 etcd
的特性,需要同时启动才可以。如果你发现启动后,docker
里并没有关于 etcd
的容器,不用担心,这是由于 k3s
的特性,你可以在 /var/lib/rancher/k3s/server/db/etcd
找到 etcd
如果你使用了 WireGuard
加密,你需要给 k3s
指定 WireGuard
网卡的 ip,否则你无法异地加入 etcd
,请参考 --node-external-ip
大部分错误都是因为没有好好看文档中,每个参数的具体作用,问ChatGPT经常胡编乱造,反而降低效率,Git Issue 也帮助了我不少忙
安装成功后,执行 kubectl get pods -A
,STATUS 无 Error 表示安装成功:
1 2 3 4 5 6 7 8 9 root@m1:/k3s# kubectl get pods -A NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-7b5bbc6644-7llcm 1/1 Running 0 9m45s kube-system local-path-provisioner-687d6d7765-5rsrx 1/1 Running 0 9m45s kube-system helm-install-traefik-crd-k9rmd 0/1 Completed 0 9m46s kube-system metrics-server-667586758d-pkzm4 1/1 Running 0 9m45s kube-system helm-install-traefik-thkf8 0/1 Completed 2 9m46s kube-system svclb-traefik-ce1649e0-9dkmv 2/2 Running 0 8m51s kube-system traefik-64b96ccbcd-nwtrm 1/1 Running 0 8m51s
如果 kubectl get pods -A
报错 connection refused
,但你的 k3s 已经安装完成且无报错已启动,那可能需要你手动执行下配置
1 2 3 4 5 mkdir ~/.kubenano ~/.kube/config server: https://m1:6443 echo export KUBECONFIG=/etc/rancher/k3s/k3s.yaml>>/etc/profilesource /etc/profile
本章节的安装参数可参考安装选项介绍 | Rancher文档 ,比如是否使用docker,定制化组件,多网卡指定等功能
Worker 节点 所有需要装 k3s Worker
的节点均执行,本架构暂无 Worker 节点,仅记录操作步骤
1 2 3 4 5 cat /var/lib/rancher/k3s/server/node-tokenINSTALL_K3S_SKIP_DOWNLOAD=true K3S_TOKEN=填node-token INSTALL_K3S_EXEC='agent --docker --server https://m1:6443' K3S_DATASTORE_ENDPOINT='etcd' /k3s/k3s-install.sh
其他 删除k3s
Server: /usr/local/bin/k3s-uninstall.sh
Agent: /usr/local/bin/k3s-agent-uninstall.sh
Docker:停止相关镜像
升级 K3s 离线环境的升级可以通过以下步骤完成:
从K3s GitHub Release 页面下载要升级到的 K3s 版本。将 tar 文件放在每个节点的/var/lib/rancher/k3s/agent/images/
目录下。删除旧的 tar 文件。
复制并替换每个节点上/usr/local/bin
中的旧 K3s 二进制文件。复制https://get.k3s.io 的安装脚本(因为它可能在上次发布后发生了变化)。再次运行脚本。
重启 K3s 服务。
安装 Helm
官方文档:Helm | 快速入门指南
1 2 3 4 5 cd /root/zipwget https://mirrors.huaweicloud.com/helm/v3.10.3/helm-v3.10.3-linux-amd64.tar.gz tar -xvzf helm-v3.10.3-linux-amd64.tar.gz mv linux-amd64/helm /usr/local/bin/helm version
安装 Rancher
仅 m1 节点安装(这里仅为单节点 Rancher ,并非 HA,请自行斟酌参考)
自定义证书 在安装 rancher 之前,我们需要先生成自定义证书(10年有效期),如果你想使用 rancher 协助安装证书,请参考官方文档使用的证书示例
1 2 3 mkdir -p /k3s/certcd /k3s/certnano create_self-signed-cert.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 #!/bin/bash -e help (){ echo ' ================================================================ ' echo ' --ssl-domain: 生成ssl证书需要的主域名,如不指定则默认为www.rancher.local,如果是ip访问服务,则可忽略;' echo ' --ssl-trusted-ip: 一般ssl证书只信任域名的访问请求,有时候需要使用ip去访问server,那么需要给ssl证书添加扩展IP,多个IP用逗号隔开;' echo ' --ssl-trusted-domain: 如果想多个域名访问,则添加扩展域名(SSL_TRUSTED_DOMAIN),多个扩展域名用逗号隔开;' echo ' --ssl-size: ssl加密位数,默认2048;' echo ' --ssl-cn: 国家代码(2个字母的代号),默认CN;' echo ' 使用示例:' echo ' ./create_self-signed-cert.sh --ssl-domain=www.test.com --ssl-trusted-domain=www.test2.com \ ' echo ' --ssl-trusted-ip=1.1.1.1,2.2.2.2,3.3.3.3 --ssl-size=2048 --ssl-date=3650' echo ' ================================================================' } case "$1 " in -h|--help ) help ; exit ;; esac if [[ $1 == '' ]];then help ; exit ; fi CMDOPTS="$*" for OPTS in $CMDOPTS ;do key=$(echo ${OPTS} | awk -F"=" '{print $1}' ) value=$(echo ${OPTS} | awk -F"=" '{print $2}' ) case "$key " in --ssl-domain) SSL_DOMAIN=$value ;; --ssl-trusted-ip) SSL_TRUSTED_IP=$value ;; --ssl-trusted-domain) SSL_TRUSTED_DOMAIN=$value ;; --ssl-size) SSL_SIZE=$value ;; --ssl-date) SSL_DATE=$value ;; --ca-date) CA_DATE=$value ;; --ssl-cn) CN=$value ;; esac done CA_DATE=${CA_DATE:-3650} CA_KEY=${CA_KEY:-cakey.pem} CA_CERT=${CA_CERT:-cacerts.pem} CA_DOMAIN=cattle-ca SSL_CONFIG=${SSL_CONFIG:-$PWD /openssl.cnf} SSL_DOMAIN=${SSL_DOMAIN:-'www.rancher.local'} SSL_DATE=${SSL_DATE:-3650} SSL_SIZE=${SSL_SIZE:-2048} CN=${CN:-CN} SSL_KEY=$SSL_DOMAIN .key SSL_CSR=$SSL_DOMAIN .csr SSL_CERT=$SSL_DOMAIN .crt echo -e "\033[32m ---------------------------- \033[0m" echo -e "\033[32m | 生成 SSL Cert | \033[0m" echo -e "\033[32m ---------------------------- \033[0m" if [[ -e ./${CA_KEY} ]]; then echo -e "\033[32m ====> 1. 发现已存在CA私钥,备份" ${CA_KEY} "为" ${CA_KEY} "-bak,然后重新创建 \033[0m" mv ${CA_KEY} "${CA_KEY} " -bak openssl genrsa -out ${CA_KEY} ${SSL_SIZE} else echo -e "\033[32m ====> 1. 生成新的CA私钥 ${CA_KEY} \033[0m" openssl genrsa -out ${CA_KEY} ${SSL_SIZE} fi if [[ -e ./${CA_CERT} ]]; then echo -e "\033[32m ====> 2. 发现已存在CA证书,先备份" ${CA_CERT} "为" ${CA_CERT} "-bak,然后重新创建 \033[0m" mv ${CA_CERT} "${CA_CERT} " -bak openssl req -x509 -sha256 -new -nodes -key ${CA_KEY} -days ${CA_DATE} -out ${CA_CERT} -subj "/C=${CN} /CN=${CA_DOMAIN} " else echo -e "\033[32m ====> 2. 生成新的CA证书 ${CA_CERT} \033[0m" openssl req -x509 -sha256 -new -nodes -key ${CA_KEY} -days ${CA_DATE} -out ${CA_CERT} -subj "/C=${CN} /CN=${CA_DOMAIN} " fi echo -e "\033[32m ====> 3. 生成Openssl配置文件 ${SSL_CONFIG} \033[0m" cat > ${SSL_CONFIG} <<EOM [req] req_extensions = v3_req distinguished_name = req_distinguished_name [req_distinguished_name] [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, serverAuth EOM if [[ -n ${SSL_TRUSTED_IP} || -n ${SSL_TRUSTED_DOMAIN} || -n ${SSL_DOMAIN} ]]; then cat >> ${SSL_CONFIG} <<EOM subjectAltName = @alt_names [alt_names] EOM IFS="," dns=(${SSL_TRUSTED_DOMAIN} ) dns+=(${SSL_DOMAIN} ) for i in "${!dns[@]} " ; do echo DNS.$((i+1 )) = ${dns[$i]} >> ${SSL_CONFIG} done if [[ -n ${SSL_TRUSTED_IP} ]]; then ip=(${SSL_TRUSTED_IP} ) for i in "${!ip[@]} " ; do echo IP.$((i+1 )) = ${ip[$i]} >> ${SSL_CONFIG} done fi fi echo -e "\033[32m ====> 4. 生成服务SSL KEY ${SSL_KEY} \033[0m" openssl genrsa -out ${SSL_KEY} ${SSL_SIZE} echo -e "\033[32m ====> 5. 生成服务SSL CSR ${SSL_CSR} \033[0m" openssl req -sha256 -new -key ${SSL_KEY} -out ${SSL_CSR} -subj "/C=${CN} /CN=${SSL_DOMAIN} " -config ${SSL_CONFIG} echo -e "\033[32m ====> 6. 生成服务SSL CERT ${SSL_CERT} \033[0m" openssl x509 -sha256 -req -in ${SSL_CSR} -CA ${CA_CERT} \ -CAkey ${CA_KEY} -CAcreateserial -out ${SSL_CERT} \ -days ${SSL_DATE} -extensions v3_req \ -extfile ${SSL_CONFIG} echo -e "\033[32m ====> 7. 证书制作完成 \033[0m" echo echo -e "\033[32m ====> 8. 以YAML格式输出结果 \033[0m" echo "----------------------------------------------------------" echo "ca_key: |" cat $CA_KEY | sed 's/^/ /' echo echo "ca_cert: |" cat $CA_CERT | sed 's/^/ /' echo echo "ssl_key: |" cat $SSL_KEY | sed 's/^/ /' echo echo "ssl_csr: |" cat $SSL_CSR | sed 's/^/ /' echo echo "ssl_cert: |" cat $SSL_CERT | sed 's/^/ /' echo echo -e "\033[32m ====> 9. 附加CA证书到Cert文件 \033[0m" cat ${CA_CERT} >> ${SSL_CERT} echo "ssl_cert: |" cat $SSL_CERT | sed 's/^/ /' echo echo -e "\033[32m ====> 10. 重命名服务证书 \033[0m" echo "cp ${SSL_DOMAIN} .key tls.key" cp ${SSL_DOMAIN} .key tls.keyecho "cp ${SSL_DOMAIN} .crt tls.crt" cp ${SSL_DOMAIN} .crt tls.crt
生成证书:
1 2 3 chmod a+x create_self-signed-cert.sh./create_self-signed-cert.sh --ssl-domain=rancher的域名 --ssl-trusted-domain=rancher的域名 \ --ssl-trusted-ip=各个主机的ip(逗号分隔) --ssl-size=2048 --ssl-date=3650
配置证书:
1 2 3 4 5 6 7 8 kubectl create ns cattle-system kubectl -n cattle-system create secret tls tls-rancher-ingress --cert=/k3s/cert/tls.crt --key=/k3s/cert/tls.key kubectl -n cattle-system create secret generic tls-ca --from-file=/k3s/cert/cacerts.pem kubectl -n cattle-system delete secret tls-rancher-ingress kubectl -n cattle-system delete secret tls-ca
开始安装
参考文档:4. 安装 Rancher | Rancher Manager
1 2 3 4 5 6 7 8 9 10 helm repo add rancher-stable http://rancher-mirror.oss-cn-beijing.aliyuncs.com/server-charts/stable helm install rancher rancher-stable/rancher --version 2.7.1 \ --namespace cattle-system \ --set hostname=你的rancher域名 \ --set ingress.tls.source=secret \ --set systemDefaultRegistry=registry.cn-hangzhou.aliyuncs.com \ --set replicas=1 \ --set bootstrapPassword=testrancher \ --set privateCA=true
如果安装报 Error: Kubernetes cluster unreachable
,是因为kubeconfig
未注入环境变量
1 2 echo export KUBECONFIG=/etc/rancher/k3s/k3s.yaml>>/etc/profilesource /etc/profile
验证是否安装成功
1 kubectl -n cattle-system rollout status deploy/rancher
安装 Nginx
仅 m1 节点安装(此处我共用了 m1 节点,你可以自行选择一个节点负责 LB)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 apt-get -y install nginx nano /etc/nginx/conf.d/rancher.conf upstream rancher { server m1:80; } map $http_upgrade $connection_upgrade { default Upgrade; '' close; } server { listen 443 ssl http2; server_name 你的rancher域名; ssl_certificate /k3s/cert/tls.crt; ssl_certificate_key /k3s/cert/tls.key; location / { proxy_set_header Host $host ; proxy_set_header X-Forwarded-Proto $scheme ; proxy_set_header X-Forwarded-Port $server_port ; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ; proxy_pass http://rancher; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade ; proxy_set_header Connection $connection_upgrade ; proxy_read_timeout 900s; proxy_buffering off; } } server { listen 80; server_name 你的rancher域名; return 301 https://$server_name$request_uri ; } systemctl enable nginx nginx -t nginx -s reload
访问页面
1 2 3 4 5 6 7 8 nano /etc/hosts 192.168.0.67 你的rancher域名 C:\Windows\System32\drivers\etc\hosts 192.168.0.67 你的rancher域名
解决域名解析问题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 kubectl edit configmap coredns -n kube-system apiVersion: v1 data: Corefile: | .:53 { errors health ready kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa } hosts /etc/coredns/NodeHosts { ttl 60 reload 15s 192.168.0.67 你的rancher域名 fallthrough } prometheus :9153 forward . /etc/resolv.conf cache 30 loop reload loadbalance } import /etc/coredns/custom/*.server NodeHosts: | 192.168.0.67 m1 192.168.0.102 n1 172.25.4.244 m2 kind: ConfigMap ...... kubectl run -it --rm --restart=Never busybox --image=busybox:1.28 -- nslookup 192.168 .0 .67 你的rancher域名
如果你在 k3s 脚本中选择了默认安装 coredns,即便修改了它的 configmap,它也会因为重启复原导致失效。永久方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 nano /var/lib/rancher/k3s/server/mycoredns.yaml apiVersion: v1 kind: ConfigMap metadata: name: coredns-custom namespace: kube-system data: rancher.server: | 你的rancher域名 { hosts { 192.168.0.67 你的rancher域名 } } kubectl apply -f /var/lib/rancher/k3s/server/mycoredns.yaml
访问Rancher
主页
访问页面:https://你的rancher域名
,输入密码 testrancher
解决证书不安全 如果你是自定义证书安装,那么大概率会显示https所使用的证书不安全,因为这个是我们自定义的,证书不安全倒也不影响我们使用,内网环境还好,但外网环境下就比较危险了, 而且证书不安全无法自动保存密码,很麻烦,所以需要对这个证书添加至信任列表中
清除浏览器缓存,或者使用匿名模式访问你的rancher地址,就能看到证书正常,连接安全了
其他 删除 Rancher
官方脚本删除:清理节点 | Rancher文档 (太危险不建议使用)
一般方法:
1 2 helm uninstall rancher -n cattle-system kubectl delete -n cattle-system MutatingWebhookConfiguration rancher.cattle.io
如果执行卡住,我们在 m1 开启两个终端,其中一个 执行 kubectl proxy
,另一个 执行:
根据实际 namespace 输入,原理是强制删除文件
1 2 3 4 5 6 7 8 9 curl -H "Content-Type: application/json" -XPUT -d '{"apiVersion":"v1","kind":"Namespace","metadata":{"name":"cattle-monitoring-system"},"spec":{"finalizers":[]}}' http://localhost:8001/api/v1/namespaces/cattle-monitoring-system/finalize curl -H "Content-Type: application/json" -XPUT -d '{"apiVersion":"v1","kind":"Namespace","metadata":{"name":"cattle-ui-plugin-system"},"spec":{"finalizers":[]}}' http://localhost:8001/api/v1/namespaces/cattle-ui-plugin-system/finalize curl -H "Content-Type: application/json" -XPUT -d '{"apiVersion":"v1","kind":"Namespace","metadata":{"name":"cattle-system"},"spec":{"finalizers":[]}}' http://localhost:8001/api/v1/namespaces/cattle-system/finalize curl -H "Content-Type: application/json" -XPUT -d '{"apiVersion":"v1","kind":"Namespace","metadata":{"name":"cattle-fleet-clusters-system"},"spec":{"finalizers":[]}}' http://localhost:8001/api/v1/namespaces/cattle-fleet-clusters-system/finalize curl -H "Content-Type: application/json" -XPUT -d '{"apiVersion":"v1","kind":"Namespace","metadata":{"name":"cattle-fleet-local-system"},"spec":{"finalizers":[]}}' http://localhost:8001/api/v1/namespaces/cattle-fleet-local-system/finalize curl -H "Content-Type: application/json" -XPUT -d '{"apiVersion":"v1","kind":"Namespace","metadata":{"name":"cattle-fleet-system"},"spec":{"finalizers":[]}}' http://localhost:8001/api/v1/namespaces/cattle-fleet-system/finalize curl -H "Content-Type: application/json" -XPUT -d '{"apiVersion":"v1","kind":"Namespace","metadata":{"name":"cattle-global-data"},"spec":{"finalizers":[]}}' http://localhost:8001/api/v1/namespaces/cattle-global-data/finalize curl -H "Content-Type: application/json" -XPUT -d '{"apiVersion":"v1","kind":"Namespace","metadata":{"name":"cattle-global-nt"},"spec":{"finalizers":[]}}' http://localhost:8001/api/v1/namespaces/cattle-global-nt/finalize curl -H "Content-Type: application/json" -XPUT -d '{"apiVersion":"v1","kind":"Namespace","metadata":{"name":"cattle-impersonation-system"},"spec":{"finalizers":[]}}' http://localhost:8001/api/v1/namespaces/cattle-impersonation-system/finalize
重置密码 登录成功直接去 rancher 个人中心里改,这个是命令改的方法
1 kubectl -n cattle-system exec $(kubectl -n cattle-system get pods -l app=rancher | grep '1/1' | head -1 | awk '{ print $1 }' ) -- reset-password
安装 Harbor
自行下载 Harbor 压缩包,并解压到 /usr/local/harbor
目录下
修改配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 cd /usr/local/harbornano /usr/local/harbor/harbor.yml hostname: 192.168.0.88 http: port: 24270 data_volume: /data/harbor
然后执行安装 sh /usr/local/harbor/install.sh
即可,输入 docker ps -a
查看容器启动情况,如果有一直重启的容器,需要输入 docker logs -f -n 300 容器名称
查看报错原因。浏览器访问 192.168.0.88:24270
即可。
由于 Harbor 是用 Docker 启动的,如果 Docker 重启,Harbor 服务可能会不正常,所以我们在 Docker 重启后,重新启动下 Harbor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 nano /usr/local/harbor.service [Unit] Description=Harbor service with docker-compose Requires=docker.service After=docker.service [Service] Restart=always RemainAfterExit=yes StandardError=null StandardOutput=null WorkingDirectory=/usr/local/harbor/ ExecStartPre=/usr/bin/docker-compose -f /usr/local/harbor/docker-compose.yml down -v ExecStart=/usr/bin/docker-compose -f /usr/local/harbor/docker-compose.yml up -d ExecStop=/usr/bin/docker-compose -f /usr/local/harbor/docker-compose.yml down -v [Install] WantedBy=multi-user.target
注册服务,并测试
1 2 3 4 5 6 7 8 9 10 cp /usr/local/harbor.service /lib/systemd/system/systemctl daemon-reload systemctl enable harbor systemctl restart harbor systemctl status harbor.service systemctl restart docker
配置私有仓库地址:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 nano /etc/docker/daemon.json { "insecure-registries" : ["192.168.0.88:24270" , "harbor:24270" ] } systemctl daemon-reload systemctl restart docker docker pull hello-world docker tag `docker images | grep hello-world | awk 'NR==1{print $3}' ` 192.168.0.88:24270/registry/hello-world:latest docker login -u admin -p 管理员密码 192.168.0.88:24270 docker push 192.168.0.88:24270/registry/hello-world:latest docker pull hello-world docker tag `docker images | grep hello-world | awk 'NR==1{print $3}' ` harbor:24270/registry/hello-world:latest docker login -u admin -p 管理员密码 harbor:24270 docker push harbor:24270/registry/hello-world:latest
在Rancher中开启旧版功能:
最后在你的项目中,选中创建好的镜像拉取密钥即可:
快捷指令备份 1 2 3 4 5 6 7 8 9 10 11 kubectl delete pod `kubectl get pods --namespace 命名空间 | awk '$3 == "Error" {print $1}' ` --namespace 命名空间 docker rm $(docker ps -aq) journalctl -xfu k3s journalctl -xfu k3s-agent
疑难杂症篇 本小节会持续更新,也许后续会单独开一篇文章汇总遇到的问题
Helm
为什么总是出现 Error 的 Pod ?
大概率是报错了一直重试安装,一般是因为你的服务器 pull 某个镜像超时了,从而触发 helm 的重新安装,所以才会有一长串的 Error Pod
在下一篇文章中,我们将通过 k3s 和 rancher 部署单节点的 mysql 和 redis