首先說一下我的環境,首先准備一台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直接安裝到虛擬機上。
jenkins安裝
go項目
為了省事我們把必要腳本都放到項目里面,項目結構如下:
我們的Dockerfile文件如下:
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
buildtest.sh是在jenkins上直接運行docker實例
在jenkins上創建一個 自由風的項目 gavintest, 調用shell腳本:
cd /var/lib/jenkins/workspace/gavintest chmod 777 buildtest.sh ./buildtest.sh
jenkins構建結果:
訪問結果:
修改配置
重啟docker restart gavintest然后訪問
k8s部署
准備【手動部署一次】
這里需要用到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 mypvc.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
配置域名host 然后訪問:
手動部署結果成功:
修改配置文件 然后手動重啟 以下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
推送到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 root@10.0.0.41 # 驗證 ssh 'root@10.0.0.41'
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 <pod_name> kubectl logs -f <pod_name> #類似tail -f的方式查看(tail -f 實時查看日志文件 tail -f 日志文件log) # 查看指定pod中指定容器的日志 kubectl logs <pod_name> -c <container_name> kubectl logs pod_name -c container_name -n namespace (一次性查看) kubectl logs -f <pod_name> -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() }