kubernetes部署springcloud(kubeadm篇)
说在前面在开始之前有这样一个问题:用了kubernetes还要不要用springcloud?关于这个问题可以看下kubernetes社区翻译的一篇文章:Kubernetes和Spring Cloud哪个部署微服务更好?对于我(码农)来说对springcloud会比较熟悉,所以我选择了全套都用springcloud,只用kubernetes部署。部署方式参阅kubernetes官...
说在前面
在开始之前有这样一个问题:用了kubernetes还要不要用springcloud?关于这个问题可以看下kubernetes社区翻译的一篇文章:Kubernetes和Spring Cloud哪个部署微服务更好?对于我(码农)来说对springcloud会比较熟悉,所以我选择了全套都用springcloud,只用kubernetes部署。
2022-05-14:
部署方式
参阅kubernetes官方文档:Installing Kubernetes with kops | Kubernetes,安装方式有很多,测试环境我选择了kubeadm,简单快速并且根据官方文档的描述可以用于生产环境,缺点是当运行是出现一些BUG可能排错会有些困难。生产环境我选择的是二进制安装(还是有点麻烦),本文将记录kubeadm安装的方式,下一篇再记二进制。
2022-03-18更新:
官方已经正式说明kubeadm可以用于生产环境,没必要再搞二进制了。
环境配置
CentOS7(三台,master+node01+node02),docker 18.06.0,kubelet-1.18.8,kubeadm-1.18.8,kubectl-1.18.8。
务必装1.18以上的版本,如果非要装1.18以下的那一定要重新编译源码改证书过期时间,否则就会移步这篇:kubernetes-1.16版本证书延期_岩烧乳酪吐司面包的博客-CSDN博客
开始安装
关闭selinux和swap
关闭selinux
/usr/sbin/sestatus -v
关闭swap
echo "vm.swappiness = 0">> /etc/sysctl.conf
swapoff -a
sysctl -p
安装docker(三台都需要)
根据官方文档:Redirecting…。
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce-18.06.0.ce-3.el7
docker-ce-cli-18.06.0.ce-3.el7
containerd.io
//现在已经找不到docker-ce-cli-18.06.0.ce-3.el7这个版本了,不过这个是远程控制用的,不按也无所谓
修改docker镜像源:
mkdir /etc/docker
vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://y0qd3iq.mirror.aliyuncs.com"],
"insecure-registries":["120.78.151.255:5000"],//此为私有仓库的仓库地址,后面会写
"log-driver":"json-file",
"log-opts": {"max-size":"500m", "max-file":"3"} //限制日志大小
}
systemctl start docker.service
要使用k8s部署需要一个私有的镜像仓库,推荐harbor,我这时间比较赶就用了简易版,这个仓库可以安装在单独一台服务器上,我是直接装在master上了。
docker pull registry:2
docker run -d -v /usr/local/docker-registry:/var/lib/registry -e REGISTRY_STORAGE_DELETE_ENABLED=true -p 5000:5000 --name myregistry registry:2
上面的“insecure-registries”地址配置为安装了私有仓库的地址,注意REGISTRY_STORAGE_DELETE_ENABLED是开启删除镜像功能,某日掉坑里了,这个仓库大小涨的很快,轻轻松松几十个G。
至此docker安装完毕。
安装kubernetes(三台都需要)
注意kubernetes和docker有版本对应关系,具体可以在这里查看:https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.16.md#downloads-for-v1167。
首先配置kubernetes的镜像源
vim /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
清空缓存
yum clean all
yum makecache
安装三件套
yum install -y kubelet-1.18.8 kubeadm-1.18.8 kubectl-1.18.8 --disableexcludes=Kubernete
2021-01更新:建议换1.19版本,最低也要1.18,这个1.16版本是以前部署的了。
注意如果你的环境无法访问外网,那么你需要找一台能访问外网的机器下载离线的rpm包,如下:
yum install --downloadonly --downloaddir=/usr/local/kubernetes-rpm kubelet-1.16.4 kubeadm-1.16.4 kubectl-1.16.4 --disableexcludes=Kubernete
这条命令可以把相关的所需包全部下载到本地但是不安装,下载完以后拖到需要安装的机器上用rpm安装。安装完以后还需要导入所需的镜像,使用
kubeadm config images list
查看安装所需要的镜像
然后根据需要的列表去找到并导入(就是找台外网机器用docker下载镜像,打包出来在导入这台离线机器)。例子如下:
#可访问外网的机器
docker save -o /usr/local/kubernetes-data/kubernetes-offline-image/kube-controller-manager fb4cca6b4e4c
打包出这个镜像后,扔到离线机器上导入:
#离线机器
docker load -i kube-controller-manager.tar
#注意此时导入的镜像name等信息都是空的,需要手动加上
docker tag fb4cca6b4e4cb2f606da76df5c3227ca1769493d1a1f89fcc7e6351908fced20 k8s.gcr.io/kube-controller-manager:v1.16.4
#fb4cca6b4e4cb2f606da76df5c3227ca1769493d1a1f89fcc7e6351908fced20 是镜像id,我把他重命名为k8s.gcr.io/kube-controller-manager,版本是v1.16.4
如此往复把所需要的镜像都导入就可以了。如果你懒的搞就下这个:
链接:百度网盘-链接不存在 提取码:c0an,这是我导出的反正也没用了干脆放上来。导入完成后上传到最开始搭建的私有仓库里,写了个凑合用的脚本:
#!/bin/bash
images=(
k8s.gcr.io/kube-apiserver:v1.16.4
k8s.gcr.io/kube-controller-manager:v1.16.4
k8s.gcr.io/kube-scheduler:v1.16.4
k8s.gcr.io/kube-proxy:v1.16.4
k8s.gcr.io/etcd:3.3.15-0
k8s.gcr.io/coredns:1.6.2
k8s.gcr.io/pause:3.1
)
for imageName in ${images[@]} ;
do
name=`echo $imageName | grep -o '/.*'`;
docker tag k8s.gcr.io$name 120.78.151.255:5000$name;
docker push 120.78.151.255:5000$name;
done
echo "push success"
其中120.78.151.255是上面搭建的私有库的地址,这样其他的机器直接去这里下载即可,不用再次导入,至此离线的处理也完了。
使用kubeadm安装
kubeadm init --image-repository=registry.aliyuncs.com/google_containers --pod-network-cidr=10.244.0.0/16
其中cidr是指定 Pod 网络的范围。Kubernetes 支持多种网络方案,而且不同网络方案对 --pod-network-cidr
有自己的要求,这里设置为 10.244.0.0/16
是因为我用 flannel 网络方案,必须设置成这个。repository地址就是拉取镜像的地址,如果是离线机器的话改成自己的私有仓库地址即可。
成功后会出现:
一定要保存master机器上以kubeadm join开头的这两行,这是node加入用的token。此命令生成的token24小时候会过期,所以应该创建一条永久的token来代替它:
kubeadm token create --ttl 0
将生成的token替换掉刚才保存的kubeadm join中的token就可以了。
接下来安装flannel(三台):
如果是root用户执行:
export KUBECONFIG=/etc/kubernetes/admin.conf
非root用户:
其实就是把root下的admin.conf(/etc/kubernetes/admin.conf)复制到当前用户的用户目录(/home/xxxx),然后用root在用户的bash_profile文件夹下增加权限,记得也要把复制过来的admin.conf授权给当前用户,具体如下,需要使用root用户:
cp /etc/kubernetes/admin.conf /home/testuser/
chown -R testuser/home/testuser/admin.conf
vim /home/testuser/.bash_profile
#在bash_profile文件内添加如下:
export KUBECONFIG=/home/testuser/admin.conf
:wq
#保存退出
#生效
source /home/cifiadmin/.bash_profile
注意需要退出shell重进才有反应,export命令是一次性的,最上面那个root仅执行了一次,重启后会无效,想每次重启生效的话还是要写入root下的bash_profile文件,这样每次重启都会执行。
以上二选一,然后执行
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
如果这个连接不好用了就需要去github上下载flannel的yml文件,然后在本地执行。
如果报以下错误
unable to recognize "kube-flannel.yml": Get http://localhost:8080/api?timeout=32s: dial tcp 127.0.0.1:8080: connect: connection refused
unable to recognize "kube-flannel.yml": Get http://localhost:8080/api?timeout=32s: dial tcp 127.0.0.1:8080: connect: connection refused
unable to recognize "kube-flannel.yml": Get http://localhost:8080/api?timeout=32s: dial tcp 127.0.0.1:8080: connect: connection refused
unable to recognize "kube-flannel.yml": Get http://localhost:8080/api?timeout=32s: dial tcp 127.0.0.1:8080: connect: connection refused
unable to recognize "kube-flannel.yml": Get http://localhost:8080/api?timeout=32s: dial tcp 127.0.0.1:8080: connect: connection refused
unable to recognize "kube-flannel.yml": Get http://localhost:8080/api?timeout=32s: dial tcp 127.0.0.1:8080: connect: connection refused
unable to recognize "kube-flannel.yml": Get http://localhost:8080/api?timeout=32s: dial tcp 127.0.0.1:8080: connect: connection refused
unable to recognize "kube-flannel.yml": Get http://localhost:8080/api?timeout=32s: dial tcp 127.0.0.1:8080: connect: connection refused
unable to recognize "kube-flannel.yml": Get http://localhost:8080/api?timeout=32s: dial tcp 127.0.0.1:8080: connect: connection refused
unable to recognize "kube-flannel.yml": Get http://localhost:8080/api?timeout=32s: dial tcp 127.0.0.1:8080: connect: connection refused
你需要检查下/etc/kubernetes/文件夹下到底有没有admin.conf文件,没有就去master复制一份过来。
最后在两个node节点上都执行刚才保存的kubeadm join语句,如果报以下错误
可以通过重置网络来解决,在Node上重置:
kubeadm reset
systemctl stop kubelet
systemctl stop docker
rm -rf /var/lib/cni/
rm -rf /var/lib/kubelet/*
rm -rf /etc/cni/
rm -rf /root/.kube/
ifconfig cni0 down
ifconfig flannel.1 down
ifconfig docker0 down
ip link delete cni0
ip link delete flannel.1
systemctl start docker
mkdir -p /root/.kube
cp -i /etc/kubernetes/admin.conf /root/.kube/config
chown $(id -u):$(id -g) /root/.kube/config
注意此命令有时会导致/etc/kubernetes/admin.conf丢失,如果是node节点丢失直接把master的拷贝过来即可,master的话需要重新init生成。最后加入master即可,至此kubernetes安装完毕。
部署springcloud(都在master上操作)
首先创建命名空间 test-cloud
kubectl create namespace test-cloud
安装ingress
关于ingress网上有很多资料,我就不再废话了,选用的nginx。首先需要下载mandatory.yaml文件:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
如果这个下载不了就去github上下载需要的版本:https://github.com/kubernetes/ingress-nginx/blob/nginx-0.20.0/docs/deploy/index.md
打开mandatory.yaml文件,找到image处:
替换镜像地址,图中是我已经替换过的,然后执行
kubectl apply -f mandatory.yaml
创建完以后我采用nodeport的方式暴露ingress,所以需要创建一个service
vim service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
nodePort: 32700 #http
- name: https
port: 443
targetPort: 443
protocol: TCP
nodePort: 31443 #https
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
此处32700和31443端口是指外部访问的端口,当外部访问32700时就会进入此ingress,同样的创建它
kubectl apply -f service-nodeport.yaml
最后创建本项目用的ingress
vim ingress-test-cloud.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-test-cloud
namespace: test-cloud
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/enable-cors: "true"
#nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /test-eureka(/|$)(.*)
backend:
serviceName: eureka
servicePort: 32316
- path: /eureka-static(/|$)(.*)
backend:
serviceName: eureka
servicePort: 32316
- path: /testcenter(/|$)(.*)
backend:
serviceName: zuul
servicePort: 12335
由于eureka的css文件路径有差异(有的带/eureka,有的不带),我在nginx中做了路由,当请求由nginx处理后转发到k8s的ingress时就是上面的路径,nginx下面会贴。将其创建,ingress就完成了:
kubectl apply -f ingress-test-cloud.yaml
根据上面的配置,当访问master节点的32700端口时就会开始ingress的处理,根据test-cloud-ingress的配置,所有testcenter开头的请求都会被去掉/testcenter并转发到12335端口的zuul中,由zuul进行再次路由。
2022-03-18更新:
如果用springcloud,网关应该选择gateway,k8s的ingress可以不用了,直接暴露gateway的端口就行。
部署eureka
先贴下eureka的配置
eureka:
server:
enable-self-preservation: false
instance:
prefer-ip-address: true
hostname: eureka
lease-expiration-duration-in-seconds: 30
lease-renewal-interval-in-seconds: 5
client:
# 表示是否注册自身到eureka服务器
register-with-eureka: false
# 是否从eureka上获取注册信息
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
port: 32316
spring:
application:
name: eureka
接下来创建eureka的镜像,编写Dockerfile
FROM openjdk:8u181
RUN mkdir /data
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo 'Asia/Shanghai' >/etc/timezone \
ARG villagecentercloud-eureka-0.0.1-SNAPSHOT.jar
COPY villagecentercloud-eureka-0.0.1-SNAPSHOT.jar eureka.jar
ENV JAVA_TOOL_OPTIONS ""
ENTRYPOINT ["java","-jar","/eureka.jar"]
EXPOSE 32316
镜像我使用的是openjdk:8u181,镜像内的时间设定为上海时区,JAVA_TOOL_OPTIONS用来在k8s的配置文件中写入环境变量,后面会贴。
需要打包镜像并且上传到私有仓库,我干脆写了个脚本
vim build.sh
docker rmi server-eureka-0.0.1:v1
docker build -t server-eureka-0.0.1:v1 .
docker tag server-eureka-0.0.1:v1 127.0.0.1:5000/server-eureka-0.0.1:v1
docker push 127.0.0.1:5000/server-eureka-0.0.1:v1
echo "success!"
chmod u+x build.sh
打包镜像,直接执行build.sh即可
上传完镜像以后开始在k8s中部署eureka,首先创建service和deployment
vim eureka-deployment.yaml
apiVersion: v1
kind: Namespace
metadata:
name: cifi-cloud
---
apiVersion: v1
kind: Service
metadata:
name: eureka
namespace: cifi-cloud
labels:
app: eureka
spec:
ports:
- port: 32316
targetPort: 32316
name: eureka
selector:
app: eureka
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: eureka
namespace: cifi-cloud
labels:
name: eureka
spec:
replicas: 1
selector:
matchLabels:
app: eureka
template:
metadata:
labels:
app: eureka
spec:
containers:
- name: eureka
image: 172.18.28.52:5000/server-eureka-0.0.1:v1
imagePullPolicy: Always
ports:
- containerPort: 32316
resources:
limits:
memory: 2048Mi
requests:
memory: 2048Mi
env:
- name: JAVA_TOOL_OPTIONS
value: "-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Djava.security.egd=file:/dev/./urandom "
resources是为了限制容器资源,因为jvm是按照宿主机的内存来设置的,如果你的宿主机是16G内存,那么一个java容器就可以占到1.3G左右,这样显然不行,因此在这里需要配置每个pod的最大资源;env这里通过JAVA_TOOL_OPTIONS来给容器中的jvm传递jvm启动参数:-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap这两个参数是让jvm感知到CGroup并且根据其大小来自动调整;replicas是指部署几份pod,其他的看看文档就知道了,没什么太难的。image要填私有仓库的地址,接下来部署
kubectl apply -f eureka-deployment.yaml
不出意外很快就部署好了,如果出错可能就要具体原因具体改,接下来部署zuul,打包镜像跟上面一样,就只贴springcloud配置文件和k8s部署文件
server:
port: 32335
#服务的名称
spring:
application:
name: zuul
#指定注册中心地址
eureka:
client:
service-url:
defaultZone: http://eureka:32316/eureka/
instance:
prefer-ip-address: true
lease-renewal-interval-in-seconds: 5
lease-expiration-duration-in-seconds: 30
#自定义路由映射
zuul:
routes:
es:
path: /es/**
eureka:
path: /test-eureka/**
serviceId: eureka
stripPrefix: true
custom-sensitive-headers: true
eureka-static-32316:
path: /eureka/**
serviceId: eureka
stripPrefix: false
custom-sensitive-headers: true
filter:
allowPaths: /es/test/razer#不想被zuul拦截的url
auth:
accessTokenTime: 360000
logging:
level:
root: debug
apiVersion: v1
kind: Service
metadata:
name: zuul
namespace: test-cloud
labels:
app: zuul
spec:
ports:
- port: 12335
targetPort: 12335
name: zuul
selector:
app: zuul
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: zuul
namespace: test-cloud
labels:
name: zuul
spec:
replicas: 1
selector:
matchLabels:
app: zuul
template:
metadata:
labels:
app: zuul
spec:
containers:
- name: zuul
image: 120.78.151.255:5000/service-zuul-0.0.1:v1
imagePullPolicy: Always
ports:
- containerPort: 12335
initContainers:
- name: eureka
image: busybox:1.31
command: ['sh', '-c', 'until nslookup eureka; do echo waiting for eureka; sleep 1; done;']
最后部署一个普通的生产者即可,此处我使用一个es项目,也是只放配置文件应用即可
spring配置文件
server:
port: 12333
# servlet:
# context-path: /es
eureka:
instance:
prefer-ip-address: true
lease-renewal-interval-in-seconds: 5
lease-expiration-duration-in-seconds: 30
hostname: es
client:
service-url:
defaultZone: http://eureka:32316/eureka/
spring:
application:
name: es
es:
host: 10.10.2.5,10.10.2.6,10.10.2.7
port: 9200
schema: http #协议
connectTimeOut: 1000 #连接超时时间
socketTimeOut: 30000 #连接超时时间
connectionRequestTimeOut: 500 #获取连接的超时时间
maxConnectNum: 100 #最大连接数
maxConnectPerRoute: 100 #最大路由数
k8s配置文件
apiVersion: v1
kind: Service
metadata:
name: elasticsearch
namespace: test-cloud
labels:
app: elasticsearch
spec:
ports:
- port: 12333
targetPort: 12333
name: elasticsearch
selector:
app: elasticsearch
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: elasticsearch
namespace: test-cloud
labels:
name: elasticsearch
spec:
replicas: 1
selector:
matchLabels:
app: elasticsearch
template:
metadata:
labels:
app: elasticsearch
spec:
containers:
- name: elasticsearch
image: 120.78.151.255:5000/service-elasticsearch-0.0.1:v1
imagePullPolicy: Always
ports:
- containerPort: 12333
initContainers:
- name: eureka
image: busybox:1.31
command: ['sh', '-c', 'until nslookup eureka; do echo waiting for eureka; sleep 2; done;']
应用即可,这些都部署完成以后通过外部/其他机器的nginx转发到我们的k8s集群,贴下我的nginx部分配置
location /test-eureka/ {
proxy_pass http://172.18.28.51:32700/test-eureka/;
}
location ^~ /eureka/ {
proxy_pass http://127.18.28.51:32700/eureka-static/eureka/;
}
location ^~ /testcenter/ {
proxy_pass http://127.0.0.1:32700/testcenter/;
}
文件挂载
文件挂载是个必须的配置,方案有很多,简单点用nfs挂载到物理机。
首先是挂载文件的服务器,我这里使用master节点:
yum -y install nfs-utils rpcbind
systemctl enable rpcbind
systemctl enable nfs-server
systemctl start rpcbind
systemctl start nfs-server
//给要共享的文件夹权限
chmod -R go+w /usr/local/data
//编辑exports文件
vim /etc/exports
/usr/local/data 172.155.155.34(rw,sync,root_squash) 172.155.155.23(rw,sync,root_squash)
//其中172.155.155.34和172.155.155.23是需要共享目录的服务器,本文中为两个从节点
//修改完后生效
systemctl restart nfs
systemctl reload
然后配置两个需要挂载的从节点:
yum -y install nfs-utils
systemctl enable rpcbind
systemctl start rpcbind
这样就搞定了,没什么事早点下班嗷铁汁。
2022-03-18更新:
建议直接用oss,不要搞这些nfs啥的了。
结语
至此kubernetes部署springcloud全部结束,还有很多东西要学,有空会把二进制部署的贴上来。中间踩了很多坑,惨。
如果没事可以装个rancher(真香),一行命令搞定:
docker run -d --restart=unless-stopped -p 9000:80 -p 3443:443 -v /usr/local/rancher:/var/lib/rancher rancher/rancher:v2.4.5
网页端通过3443端口访问,务必要挂载配置文件出来。
更多推荐
所有评论(0)