“所爱隔山海,山海不可平,海有舟可渡,山有路可行,此爱翻山海,山海皆可平。”
作为一个想搞开发的,最近似乎都在干运维,不知道有没有跑偏。。。
网上关于CI/CD的文章一大堆,刚开始听着好像好高大尚的感觉,持续集成CI(Continuous Integration),持续交付(Continuous Delivery),持续部署CD(Continuous Deployment),个人认为就是有错尽早发现,添加一点东西就测一下,部一下(部到整体,而不是自己所写的那么一点,因为自己写的肯定没毛病啊。。),看看有无毛病,而不是等着都干完了一起测,哪的多费劲。其实平时好像也是这么开发的啊,但CI/CD还强调自动化部署,这点挺重要的。
花了一个星期搞了搞k8s,感觉有点复杂,虽然搭建起来了,虽然只学到了皮毛,但是学习过程中找到了很多不错的资源,希望对你们有所帮助。
为什么要用k8s,我现在接触的感觉k8s比较强的一点是,如果你服务有两个副本,其中一个挂了,那么他会帮你自动帮你新建一个副本,保证一直有两个正常的服务在运行,如果挂的服务正常了,多余的将会被删除,个人感觉这个功能非常强悍(匹夫之见)
自己按照网上五花八门的教程,搭了几遍都失败了,不是这个错就是那个错,有的还要,国内要求科学上网,所以只能解决一时的问题,最后找到了大佬搭建的脚本,只需几步便搭建成功了。
搭建之前,如果需要dns,可以先配置一下dns,省的后面麻烦,因为k8s部署后他里面内置的coredns,配置是从宿主机copy过去的,如果你需要用dns先配置一下(云服务器应该不用配,华为云dns是在控制台配置的,自己视情况而定)
教程是使用ansible搭建的k8s
https://github.com/easzlab/kubeasz
首先下载脚本,下载完成执行完命令后,在/etc/ansible下面有个host文件,需要配置一下
对ansible不了解的可以先去了解一下,了解一下就ok,知道配置的意义,已经怎么配。
这是我的配置,仅供参考,ip啥的改成自己的,我是在103机器装的ansible,108为master节点,111和148位node节点,听说k8s后面将不会区分master和node,具体是不是就不得而知了。配置完成后继续执行后面的命令完成安装。
# 'etcd' cluster should have odd member(s) (1,3,5,...)
# variable 'NODE_NAME' is the distinct name of a member in 'etcd' cluster
[etcd]
192.168.1.103 NODE_NAME=etcd1
192.168.1.108 NODE_NAME=etcd2
192.168.1.111 NODE_NAME=etcd3
192.168.1.148 NODE_NAME=etcd4
# master node(s)
[kube-master]
192.168.1.108
# work node(s)
[kube-node]
192.168.1.111
192.168.1.148
# [optional] harbor server, a private docker registry
# 'NEW_INSTALL': 'yes' to install a harbor server; 'no' to integrate with existed one
[harbor]
#192.168.1.8 HARBOR_DOMAIN="harbor.yourdomain.com" NEW_INSTALL=no
# [optional] loadbalance for accessing k8s from outside
[ex-lb]
#192.168.1.6 LB_ROLE=backup EX_APISERVER_VIP=192.168.1.250 EX_APISERVER_PORT=8443
#192.168.1.7 LB_ROLE=master EX_APISERVER_VIP=192.168.1.250 EX_APISERVER_PORT=8443
# [optional] ntp server for the cluster
[chrony]
#192.168.1.1
[all:vars]
# --------- Main Variables ---------------
# Cluster container-runtime supported: docker, containerd
CONTAINER_RUNTIME="docker"
# Network plugins supported: calico, flannel, kube-router, cilium, kube-ovn
CLUSTER_NETWORK="flannel"
# Service proxy mode of kube-proxy: 'iptables' or 'ipvs'
PROXY_MODE="ipvs"
# K8S Service CIDR, not overlap with node(host) networking
SERVICE_CIDR="10.68.0.0/16"
# Cluster CIDR (Pod CIDR), not overlap with node(host) networking
CLUSTER_CIDR="172.20.0.0/16"
# NodePort Range
NODE_PORT_RANGE="20000-40000"
# Cluster DNS Domain
CLUSTER_DNS_DOMAIN="cluster.local."
# -------- Additional Variables (don't change the default value right now) ---
# Binaries Directory
bin_dir="/opt/kube/bin"
# CA and other components cert/key Directory
ca_dir="/etc/kubernetes/ssl"
# Deploy Directory (kubeasz workspace)
base_dir="/etc/ansible"
其他步骤很完善,我这里不在复述,沟通交流那里可以加群,里面大佬挺多的,有问题可以在里面问,也可以留言,我尽量解答。
我是搭建没有问题。。
使用kubectl的一串命令验证一下集群有没有毛病,然后就是搭建可视化界面,
找了一个Kuboard
kubectl apply -f https://kuboard.cn/install-script/kuboard.yaml
执行命令获取token
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep kuboard-user | awk '{print $1}')
访问任意节点的IP:32567即可访问界面,附上大佬的k8s教程,
https://www.kuboard.cn/learning/
k8s就搭建成功了
你可以在k8s外搭建jenkins,也可以在k8s上搭建jenkins,搭建在k8s中可以保证其高可用,
外面搭建jenkins很简单,就下载war包java命令运行就行,或者使用docker运行,不在复苏,感兴趣可以去百度,我这里介绍在k8s中搭建jenkins
参考:https://www.jianshu.com/p/0aef1cc27d3d
-首先创建pv用于数剧挂载,pvc.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: opspv
spec:
capacity:
storage: 20Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Delete
nfs:
server: 192.168.1.108
path: /opt/nfs/jenkins
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: opspvc
namespace: kube-ops
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 20Gi
注意修改server,其他自己视情况修改。
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins
namespace: kube-ops
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: jenkins
rules:
- apiGroups: ["extensions", "apps"]
resources: ["deployments"]
verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
- apiGroups: [""]
resources: ["services"]
verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get","list","watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: jenkins
namespace: kube-ops
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: jenkins
subjects:
- kind: ServiceAccount
name: jenkins
namespace: kube-ops
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins
namespace: kube-ops
spec:
template:
metadata:
labels:
app: jenkins
spec:
terminationGracePeriodSeconds: 10
serviceAccount: jenkins
containers:
- name: jenkins
image: jenkins/jenkins:lts
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: web
protocol: TCP
- containerPort: 50000
name: agent
protocol: TCP
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
failureThreshold: 12
readinessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
failureThreshold: 12
volumeMounts:
- name: jenkinshome
subPath: jenkins
mountPath: /var/jenkins_home
securityContext:
fsGroup: 1000
volumes:
- name: jenkinshome
persistentVolumeClaim:
claimName: opspvc
selector:
matchLabels:
app: jenkins
---
apiVersion: v1
kind: Service
metadata:
name: jenkins
namespace: kube-ops
labels:
app: jenkins
spec:
selector:
app: jenkins
type: NodePort
ports:
- name: web
port: 8080
targetPort: web
nodePort: 30003
- name: agent
port: 50000
targetPort: agent
对于配置的含义,大部分教程里面都有。
然后就是部署
kubectl create -f pvc.yaml
kubectl create -f jenkins-rbac.yaml
kubectl create -f jenkins-deployment.yaml
然后查看状态
kubectl get pods -n kube-ops
kubectl describe pod jenkins-86d6987987-c9m2t -n kube-ops
查看日志
kubectl logs jenkins-86d6987987-c9m2t -n kube-ops
如果报错
touch: cannot touch '/var/jenkins_home/copy_reference_file.log': Permission denied
Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?
很明显是nfs挂载文件没有权限,加权限就行
chown -R 1000 /opt/nfs/jenkins
然后新建一个
# 删除原来的
kubectl delete -f jenkins.yaml
# 新建
kubectl create -f jenkins.yaml
# 再查看状态是否正常,不正常继续排查
kubectl get pods -n kube-ops
然后访问任意节点的ip:30003即可访问jenkins
第一次登陆的密码在日志里面可以看见,然后就是安装他推荐的插件,安装完成后就是配置jenkins,在jenkins配置里面配置好你所需的配置,根据自己情况而定,比如我们项目使用grade我就要配置gradle等等。。
到这里你已经搭建好k8s集群,配置好jenkins(太费劲了,曾经的我一度想放弃,这什么玩意儿。。。),然后就是新建一个项目
讲一下你们的心路历程(没错就是你们的),你提交代码到仓库,如果是getlab,使用webhook自动触发拉取,不是的话就配置cron表达式定时构建,jenkins拉取到代码后,需要进行构建,测试,打包,一系列操作,这是最基本的,姑且认为这是持续集成,然后需要将镜像push到镜像仓库,然后执行k8s的命令,从镜像仓库拉取镜像,部署服务,这可以叫持续交付,整个过程你干嘛了?你就提交了代码,啥也没干,看能不能部署成功就完事,整体自动化,这可以算是持续部署,整体思路就是这样
理想很丰满,现实很骨感,k8s感觉性能上还有待提升吧,我直接使用docker,可以自行好几个微服务,但使用k8s部署几个既感觉不太行了,而且我们的项目是saas平台的,如果每一套都要搭建一套的话,不太现实,直接使用jenkins+docker也可以实现CI/CD只是没有k8s的诸多优点,视情况而定吧
我举例部署一个eureka
如果用的仓库是getlab的建议使用流水线,直接使用管道Pipeline实现CI/CD,而且有webhook插件可以提供自动触发构建,非常的方便,说实话Pipeline我也不是很会。。群里有人用这个,需要的话可以在群里问,或者@me,我虽然不太会,但我知道有人会啊。。(怎样@me,请看头像),使用Pipeline的话相比比较容易实现,但你的学点Pipeline的知识,反正我是不会。
我们公司用的是华为云的仓库,目前流水线只能使用getlab的仓库,没办法建一个自由项目吧,
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: admin-regist
namespace: kube-spring-cloud
labels:
app: regist
spec:
replicas: 1
selector:
matchLabels:
app: regist
template:
metadata:
labels:
app: regist
namespace: kube-spring-cloud
spec:
containers:
- name: regist
image: registry.cn-beijing.aliyuncs.com/byb-docker/regist:001
imagePullPolicy: Always
imagePullSecrets:
- name: aliyun-secret
---
apiVersion: v1
kind: Service
metadata:
name: admin-regist
namespace: kube-spring-cloud
spec:
type: NodePort
ports:
- name: web
port: 38001
targetPort: 38001
nodePort: 38001
selector:
app: regist
可以通过参数化构建,将名称和镜像以参数传入配置文件,这样所有的服务用一个配置即可,我是用的是nodeport建立与外网的联系,也可以使用ingerss。
如果k8s里面搭建的jenkins直接执行脚本就行,我是在外面不得jenkins所以使用了ssh
echo "---------------delete old deployment-----------------------"
kubectl delete deployment admin-regist -n kube-spring-cloud
echo "---------------delete old service-----------------------"
kubectl delete service admin-regist -n kube-spring-cloud
echo "---------------delete old ingress-----------------------"
kubectl get ingress admin-regist -n kube-spring-cloud
echo "---------------deploy-----------------------"
kubectl create -f /root/k8s/k8s-deployment.yaml -n kube-spring-cloud
在kube-spring-cloud便可以看见部署的微服务
访问任意节点的ip:380011都可以访问注册中心
至此部署完毕!!!