arm部署k8s
0 环境说明
泰山2000 arm64架构服务器。
操作系统openEuler 20.03。
内核:Linux 4.19.90-2112.8.0.0131.oe1.aarch64
1 关闭防火墙
默认openEuler会安装并启动firewalld防火墙,需要提前关闭,否则在后续操作中可能会出现无法连接主机的问题。
1systemctl stop firewalld
2systemctl disable firewalld
2 部署rancher
使用rancher安装。
首先安装docker:
1wget -O /etc/yum.repos.d/openEulerOS.repo https://repo.huaweicloud.com/repository/conf/openeuler_aarch64.repo
2
3yum clean all
4
5yum makecache
6
7yum install docker
然后运行rancher的docker镜像进行集群管理。
1docker run --privileged -d --restart=unless-stopped -p 3080:80 -p 3443:443 rancher/rancher:v2.5.15
注意这里一定不能使用2.6.x版本,否则集群部署遇到问题的时候不方便得到kubeconfig.json文件。
安装镜像之后,需要等待一会儿,最终会变成ready状态。
创建自定义集群,然后选择k8s版本为1.18。注意:下面选择Network(网络插件)要改成Flannel!!!,如果使用默认的canel,会拉取不到arm64对应版本的镜像导致部署失败,即使按照下面安装问题中解决了部署的问题,插件也无法正常使用,会出现不同节点不能ping通其他节点上部署的pod的情况。
参考文章https://cloud.tencent.com/developer/article/1768489
安装问题
Runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
原因:
先从cluster的overview界面右上角那里拿到kubeconfig file的内容,存入~/.kube/config
中,之后kubectl就可以访问这个未完成的集群了。使用kubectl get pod -n kube-system
命令查看集群中kube-system的pod运行情况,发现是一个pod卡住了。通过kubectl describe pod
命令查看这个pod的信息,发现其镜像是rancher/mirrored-calico-node:v3.13.4,然而去docker hub上查找发现,Calico该版本没有arm64的image,因此pod卡在ImagePullBackOff上。
解决方案:
kubectl apply -f https://docs.projectcalico.org/v3.11/manifests/calico.yaml
手动安装一个calico之后,就正常了。
如果后续不需要该节点作为集群的节点,可以用以下脚本清理:
1#!/bin/sh
2docker rm -f $(docker ps -qa)
3docker volume rm $(docker volume ls -q)
4cleanupdirs="/var/lib/etcd /etc/kubernetes /etc/cni /opt/cni /var/lib/cni /var/run/calico /opt/rke"
5for dir in $cleanupdirs; do
6 echo "Removing $dir"
7 rm -rf $dir
8done
遇到其他问题时,首先冷静想想,是否是因为Docker镜像没有对应的arm64版本。
获取kubeconfig.json
在rancher的界面上,cluster的overview处右上角有kubeconfig文件
按钮。点击按钮,复制所有文件内容,并覆盖写入~/.kube/config文件,之后就可以使用kubectl访问和操作集群。
获取api token
首先绑定角色。kubectl create -f admin-role.yml
1kind: ClusterRoleBinding
2apiVersion: rbac.authorization.k8s.io/v1beta1
3metadata:
4 name: admin
5 annotations:
6 rbac.authorization.kubernetes.io/autoupdate: "true"
7roleRef:
8 kind: ClusterRole
9 name: cluster-admin
10 apiGroup: rbac.authorization.k8s.io
11subjects:
12- kind: ServiceAccount
13 name: admin
14 namespace: kube-system
15---
16apiVersion: v1
17kind: ServiceAccount
18metadata:
19 name: admin
20 namespace: kube-system
21 labels:
22 kubernetes.io/cluster-service: "true"
23 addonmanager.kubernetes.io/mode: Reconcile
然后运行kubectl -n kube-system get secret|grep admin-token
会出现一个admin-token-xxx
最后运行kubectl -n kube-system describe secret admin-token-xxx
,将显示出的非常长的一串token复制出来。
参考文章https://jimmysong.io/kubernetes-handbook/guide/auth-with-kubeconfig-or-token.html
通过rancher安装的k8s集群中已经有metrics,因此可以直接使用java fabric8 api进行访问和使用。
工具安装
- kubens 快速切换namespace。
添加rancher节点
在新的节点主机上首先要关闭防火墙。
然后在Rancher上找到Registration Cmd。复制后一定要加上 -e CATTLE_NODE_NAME=xxx来指定主机名,将新的节点加入到集群中。
还有一点需要注意的是,如果只添加work角色,会导致一直卡在等待注册(原因还不明)。
3 GlusterFS配置持久化卷
提前安装glusterfs和heketi,并配置好。
安装启动glusterfs:
1yum install glusterfs
2systemctl start glusterd
3systemctl enable glusterd
安装heketi:https://github.com/heketi/heketi。只需要解压将可执行文件放入/usr/local/bin即可。
配置heketi:参考 https://claws.top/2022/07/18/glusterfs/#%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AEheketi。配置好节点和device即可,无需自己创建volume,k8s会根据需要请求heketi创建volume。
创建k8s的StorageClass:
1apiVersion: storage.k8s.io/v1
2kind: StorageClass
3metadata:
4 name: seecoder-paas
5provisioner: kubernetes.io/glusterfs
6reclaimPolicy: Retain
7allowVolumeExpansion: true
8parameters:
9 resturl: "http://172.29.7.102:5080" #glusterfs service url
10 restauthenabled: "true"
11 restuser: "admin"
12 restuserkey: "WJNJqeGZGBJC6k1kaRxd"
13 volumetype: "none"
注意,如果是单节点部署的glusterfs,必须要使用volumetype: "none"
选项,否则创建持久卷会失败。
4 部署PaaS
数据库
先运行一个mysql数据库,供后端使用。
这里采用docker部署:
mkdir -p /mnt/mysql-data && docker run --restart=always -p 3306:3306 -p 33060:33060 --name my-mysql -v /mnt/mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql
然后新建seecoder_paas
数据库备用。
后端
安装java。
docker仓库地址:
在application.yml里面使用的docker仓库地址应该为 nexus.seecoder.cn:8092
需要将这个http网址加入到docker的配置文件的insecure中,否则在拉取镜像时会报错。另外还需要配置一个镜像站点,否则部署时拉取镜像会很慢。修改所有部署节点的/etc/docker/daemon.json
如下所示:
1{
2 "registry-mirrors":["https://8eemjwlo.mirror.aliyuncs.com"],
3 "insecure-registries":["nexus.seecoder.cn:8092"]
4}
可以使用app.sh进行部署,需要对脚本文件中的一些变量进行修改。脚本使用同目录下的config.yml作为后端SpringBoot的配置文件。
运行目录中,要新建docker-config.json文件并填入以下内容,paas构建镜像后,会读取其中的账号密码并将镜像推送到私有的镜像仓库中:
1{
2 "auths": {
3 "172.19.51.6:8092": {
4 "username": "admin",
5 "password": "NJU67nexus"
6 }
7 }
8}
必须要新建seec的namespace,应用才可以正常部署。
kubectl create -f ns.yml
1apiVersion: v1
2kind: Namespace
3metadata:
4 name: seec
前端
使用nginx静态部署。如果部署前端的机器上面运行有集群,则需要避开80和443端口。
Nginx
由于含有websocket连接,需要进行特殊分流配置。
参考的nginx配置文件如下:
1map $http_upgrade $connection_upgrade {
2 default upgrade;
3 '' close;
4}
5upstream websocket {
6 server 127.0.0.1:8080;
7}
8server {
9 listen 443 ssl http2;
10 listen [::]:443 ssl http2 ;
11 root /srv/paas-ui/dist;
12 server_name paas-test-seec.claws.top;
13 ssl_certificate_key /root/cert/paas-test-seec.claws.top/cert.key;
14 ssl_certificate /root/cert/paas-test-seec.claws.top/fullchain.cer;
15
16 location ~ /ws {
17 proxy_pass http://websocket;
18 proxy_read_timeout 3h;
19 proxy_send_timeout 3h;
20
21 proxy_set_header Host $host;
22 proxy_set_header X-Real-IP $remote_addr;
23 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
24
25 proxy_http_version 1.1;
26 proxy_set_header Upgrade $http_upgrade;
27 proxy_set_header Connection $connection_upgrade;
28 }
29 location ~ / {
30 if ($request_uri ~* (api)) {
31 proxy_pass http://127.0.0.1:8080;
32 }
33 try_files $uri $uri/ /index.html;
34 }
35}
终端问题
无法连接:服务器nginx必须使用ssl加密,因为前端里面写死的wss。
连接之后出现unable to start container process: open /dev/pts/0: operation not permitted: unknown错误:在服务器上运行kubectl exec仍然有问题,重启pod解决。
5 配置ingress相关
rancher建立集群的时候,如果全部采用默认选项,就会自动开启一个nginx ingress controller,但是会占用宿主机原有的80和443端口。
paas的配置文件中deployment-host就是域名后缀的内容,先将这里设置好,然后解析泛域名到自己的服务器,就可以正常通过域名前缀和后缀的组合得到完整域名访问服务了。此时证书还是不正确的。
配置证书首先需要去OHTTPS上面申请一个泛域名证书,然后来到rancher的控制台,在seec的命名空间下添加一个新的secret,插入tls.crt(证书内容)和tls.key(证书私钥)两个值之后保存。如果rancher里面不能直接给seec插入,则需要先把seec命名空间加入到default的project的下面。最后在后端的config.yaml中修改secret-name,改成该证书secret的名字即可。
ingress 部署后访问时可能会出现 504Gateway Time-out的错误,是因为两个节点互相不能访问到对方节点上部署的pod。
6 后续维护Q&A
- Q:运行环境时出现镜像架构不正确的问题。A:检查镜像(尤其是build使用的基本镜像)是否是官方镜像,有出现类似
java:8-jre-alpine
的镜像不是官方镜像(可能是阿里的一个什么镜像),manifest书写不规范导致arm64的机器也可以pullamd64版本的镜像,但是后续运行就出现问题了。一定要使用官方镜像,防止出现架构不符的问题导致环境部署失败!