首先说一下我的环境,首先准备一台ubuntu18.4虚拟机,安装docker, 然后用docker 安装gitlab[大家可以参考 Ubuntu Docker搭建GitLab以及常规配置使用] 和harbor【大家可以参考 Ubuntu18 安装搭建Harbor】,关于k8s的安装大家 可以参考 Ubuntu 18 Kubernetes集群的安装和部署 以及Helm的安装 和 Centos 使用kubeadm安装Kubernetes 1.15.3 关于harbor 程序手动更新到k8s 参考 Windows docker k8s asp.net core.我尝试过通过docker来安装jenkins,jenkins容器里面在安装docker和harbor通信,但是后面还是遇到很多问题 不好解决, docker默认是无状态的 需要保存的数据都要挂在的虚拟机上, 比如jenkins里面下载的golang镜像,jenkins重启就丢失了, 所以后面彩用jenkins直接安装到虚拟机上。
#准备工作
#存储库密钥添加到系统
wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add -
#将Debian包存储库地址附加到服务器的sources.list
echo deb http://pkg.jenkins.io/debian-stable binary/ | sudo tee /etc/apt/sources.list.d/jenkins.list
apt-get update
sudo apt-get install -y openjdk-8-jdk
sudo apt-get install -y jenkins
#如果你的端口8080被占用
#编辑`/etc/default/jenkins`, 修改 ----HTTP_PORT=8080----`为----HTTP_PORT=8081----` 在这里,“8081”也可被换为其他可用端口
#启动Jenkins
sudo systemctl start jenkins
sudo systemctl status jenkins
jenkins的配置我们就省略了, 部署项目我们时 在开发测试环境可以直接在jenkins上直接运行docker实例,也可以把docker推到harbor上,至于harbor到k8s上后面在写一篇文章。
为了省事我们把必要脚本都放到项目里面,项目结构如下:
我们的Dockerfile文件如下:
FROM golang:1.15.6
RUN mkdir -p /app
RUN mkdir -p /app/conf
RUN mkdir -p /app/logs
WORKDIR /app
ADD main /app/main
EXPOSE 8080
CMD ["./main"]
buildtest.sh是在jenkins上直接运行docker实例
#!/bin/bash
#cd $WORKSPACE
export GOPROXY=https://goproxy.io
#根据 go.mod 文件来处理依赖关系。
go mod tidy
# linux环境编译
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main
#删除docker
docker stop gavintest
docker rm gavintest
docker rmi gavintest
# 构建docker镜像,项目中需要在当前目录下有dockerfile,否则构建失败
docker build -t gavintest .
mkdir logs
mkdir conf2
#挂载资源文件夹 运行docker
docker run -d --name gavintest -p 9999:8080 -v $(pwd)/conf:/app/conf -v $(pwd)/logs:/app/logs gavintest
在jenkins上创建一个 自由风的项目 gavintest, 调用shell脚本:
cd /var/lib/jenkins/workspace/gavintest
chmod 777 buildtest.sh
./buildtest.sh
jenkins构建 结果
访问结果:
修改配置:
重启docker restart gavintest 然后访问:
这里需要用到pvc,关于pvc的搭建我就省略了, 大家可以参考 ubuntu kubernetes中使用NFS创建pv_pvc ,以下都是在k8s master上执行[我为了方便把 端口改为80了而不在是8080]
命令空间1.准备namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: go
labels:
name: go
kubectl apply -f namespace.yaml
#因为是私有的harbor所以需要创建regsecret认证,然后在deploy文件引用它
kubectl create secret docker-registry regsecret --docker-server=192.168.100.30:8080 --docker-username=admin --docker-password=123456 -n=go
#kubectl delete secret regsecret -n=go
创建mypv.yaml (kubectl apply -f mypv.yaml)
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
spec:
capacity:
storage: 100M
accessModes:
- ReadWriteMany
nfs:
path: /data/k8s/
server: 192.168.100.11
和mypvc.yaml (kubectl apply -f mypvc.yaml)
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: myclaim
namespace: go
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10M
和deploy.yaml (kubectl apply -f deploy.yaml)
apiVersion: apps/v1
kind: Deployment
metadata:
name: gavintest
namespace: go
spec:
replicas: 5
minReadySeconds: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
selector:
matchLabels:
name: gavintest
template:
metadata:
labels:
name: gavintest
spec:
imagePullSecrets:
- name: regsecret
containers:
- name: gavintest
image: 192.168.100.30:8080/go/gavintest:20210301
ports:
- containerPort: 80
imagePullPolicy: Always
volumeMounts:
- mountPath: "/app/conf"
name: httpd-volume
volumes:
- name: httpd-volume
persistentVolumeClaim:
claimName: myclaim
我们可以用kubectl exec -it podnamexxx -n gobash 进入pod验证以下
或者 kubectl get pod -o wide -n go 查看ip直接访问
service.ymal (kubectl apply -f service.ymal)
apiVersion: v1
kind: Service
metadata:
name: gavintest
namespace: go
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: gavintest
ingress.yaml (kubectl apply -f ingress.yaml ) 可以参考 https://www.cnblogs.com/fanqisoft/p/11609172.html
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: gavintest
namespace: go
spec:
rules:
- host: k8s.go.com
http:
paths:
- path: /
backend:
serviceName: gavintest
servicePort: 80
配置域名 然后访问:
手动部署结果成功:
修改配置文件 然后手动重启 以下pod 看看配置是否更新
#pod 重启方法1
kubectl scale deployment XXXX --replicas=0 -n {namespace}
kubectl scale deployment XXXX --replicas=1 -n {namespace}
#方法2
kubectl delete pod {podname} -n {namespace}
#方法3
kubectl get pod {podname} -n {namespace} -o yaml | kubectl replace --force -f -
#方法4Kubernetes 1.15开始才有
#kubectl rollout restart deploy {your_deployment_name}
kubectl rollout restart deploy gavintest -n go
build.sh文件是把docker镜像推到harbor上的【已经测试通过】
#!/bin/bash
#cd $WORKSPACE
export GOPROXY=https://goproxy.io
#根据 go.mod 文件来处理依赖关系。
go mod tidy
# linux环境编译
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main
# 构建docker镜像,项目中需要在当前目录下有dockerfile,否则构建失败
docker build -t gavintest .
docker tag gavintest 192.168.100.30:8080/go/gavintest:${BUILD_NUMBER}
docker push 192.168.100.30:8080/go/gavintest
docker rmi gavintest
docker rmi 192.168.100.30:8080/go/gavintest:${BUILD_NUMBER}
cd ..
#删除项目文件夹
#rm -rf gavintest
这里镜像push到harbor了,
现在我们搞一个rollout.sh文件【需要和gavintest_dm.yaml同级目录】, 就是根据现有的deploy.yaml文件来生成新的部署文件,然后调用/data/k8s/rollout.sh 38 [38是harbor里面镜像版本号,如果有权限问题 chmod 777 /data/k8s/rollout.sh]
#!/bin/bash
workdir="/data/k8s"
project="gavintest"
job_number=$(date +%s)
cd ${workdir}
oldversion=$(cat ${project}_dm.yaml | grep "image:" | awk -F ':' '{print $NF}')
newversion=$1
echo "old version is: "${oldversion}
echo "new version is: "${newversion}
sed -i.bak${job_number} 's/'"${oldversion}"'/'"${newversion}"'/g' ${project}_dm.yaml
kubectl apply -f ${project}_dm.yaml --record=true
那么jenkins就可以用过ssh 192.168.100.11 "cd /data/k8s && sh rollout.sh ${BUILD_NUMBER}" 来调用shell了
错误Host key verification failed 的解决办法:
a.jenkins普通用户无法执行某些系统命令;
b.我们并没有为jenkins生成过密钥对,也没有将他的公钥拷到目标服务器上.
在安装jenkins后,系统生成了jenkins这个普通用户,但是在/etc/passwd中,他的shell是/bin/false,所以他不能登录系统,也没有家目录;
首先我们修改他的登录权限,将/bin/false改为/bin/bash,切换到jenkins用户,su - jenkins,他的终端显示为-bash-4.2$,修改终端显示.
终端修改完之后长这个样子
生成密钥对
具体步骤
vim ~/.bash_profile
export PS1='[\u@\h \W]\$'
source ~/.bash_profile
# 给jenkins生成密钥对
ssh-keygen -t rsa
ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]
# 验证
ssh '[email protected]'
3.使用sudo提升普通用户权限
此时是完成了第二步,但还没有操作第一步,在文件末尾添加一行,就这么一行就有很多要注意的地方,首先修改文件权限为600,然后用viduso去修改文件,中间的空隙不是空格,而是tab,命令和命令之间要用逗号,保存退出后,将权限改为440,而不是400,最后用visudo -c检查语法是否出错.
jenkins ALL=(ALL) NOPASSWD: /usr/bin/ssh, /usr/bin/rsync
jenkins ALL=(ALL) NOPASSWD: ALL
这两行内容任意选一个都行.
需要确保k8s master 的vi /etc/ssh/sshd_config 配置
重启 sudo systemctl restart jenkins,至于如何带哦用远程的sh我这里比较偷懒 直接用插件SSH remote hosts
1.jenkins账号运行docker 没有权限提示 :dial unix /var/run/docker.sock: connect: permission denied 解决办法
sudo groupadd docker #添加docker用户组
sudo gpasswd -a $USER docker #将登陆用户加入到docker用户组中
docker ps #测试当前用户是否可以正常使用docker命令
#把jenkins添加到docker的group里就可以了。
sudo usermod -a -G docker jenkins
#重启jenkins。
systemctl restart jenkins
2.jenkins在王harbor上推送失败,提示push: unauthorized to access repository,解决办法
#首先登陆harbor
docker login 192.168.100.30:8080
查看.docker/config.json 文件
root@server:~# cat .docker/config.json
{
"auths": {
"192.168.100.30:8080": {
"auth": "Z2F2aW46R2F2aW4xMjM="
}
},
"HttpHeaders": {
"User-Agent": "Docker-Client/19.03.6 (linux)"
}
}
#把.docker复制到/var/lib/jenkins目录下
cp -r .docker/ /var/lib/jenkins/
修改文件夹权限 chown -R jenkins.jenkins .docker
cd /var/lib/jenkins/
chown -R jenkins.jenkins .docker
systemctl restart jenkins
3.
1.pod若处于运行状态,则通过kubectl logs 即可
# 查看指定pod的日志
kubectl logs
kubectl logs -f #类似tail -f的方式查看(tail -f 实时查看日志文件 tail -f 日志文件log)
# 查看指定pod中指定容器的日志
kubectl logs -c
kubectl logs pod_name -c container_name -n namespace (一次性查看)
kubectl logs -f -n namespace (tail -f方式实时查看)
2.若pod处于init状态,则需要通过docker ps查看
#获取对应的pod name
kubectl get pods -n namespace -o wide (STATUS是init的pod_name)
#通过docker ps 获取该pod的中的CONTAINER ID
docker ps | grep pod_name
#通过docker log获取对应的日志信息
docker logs CONTAINER_ID
main.go
package main
import (
_ "demo/routers"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
)
func main() {
_ = logs.SetLogger(logs.AdapterFile, `{"filename":"logs/gavintest.log", "level":7, "daily":true, "maxdays":10}`)
logs.Debug("website=%v", beego.AppConfig.String("website"))
beego.Run()
}
default.go
package controllers
import (
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
)
type MainController struct {
beego.Controller
}
type responseData struct {
Data interface{}
Code int
Msg string
}
func (c *MainController) Get() {
website := beego.AppConfig.String("website")
logs.Info("/get:website=%v", website)
ret := &responseData{
Data: website,
Code: 200,
Msg: "OK",
}
c.Data["json"] = ret
c.ServeJSON()
c.StopRun()
}