devops學習-流水線發布的演示


經過網上視頻的學習整理如下: 

環境規划

10.211.55.11  k8s-master1,nfs

10.211.55.12  k8s-master2,k8s-node1

10.211.55.13  k8s-master3,k8s-node2

10.211.55.14  Harbor倉庫,git倉庫,其他公共的服務

上面設計到的服務,可以查看我前面寫過的文章

項目下載地址

https://github.com/erlonglong/k8s-test/tree/master/devops

https://www.daocloud.io/mirror 鏡像加速
[root@wan src]# cat  /etc/docker/daemon.json
{
  "insecure-registries":["hub.k8s.com","10.211.55.14"],
  "registry-mirrors": ["http://f1361db2.m.daocloud.io"]
}

各節點docker的加速和私有倉庫的配置,域名需要綁定

hub.k8s.com  10.211.55.14

使用K8S 部署jenkins 

采用jenkins-master + jenkins-slave 的模式來實現CI&CD

https://github.com/jenkinsci/kubernetes-plugin/tree/master/src/main/kubernetes 

wget https://raw.githubusercontent.com/jenkinsci/kubernetes-plugin/master/src/main/kubernetes/jenkins.yml

這里面我們用不到ingress 可以把相關的資源去掉

vim  jenkins-master.yaml  

 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: jenkins
rules:
- 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/v1beta1
kind: RoleBinding
metadata:
  name: jenkins
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: jenkins
subjects:
- kind: ServiceAccount
  name: jenkins
---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: jenkins
  labels:
    name: jenkins
spec:
  serviceName: jenkins
  replicas: 1
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      name: jenkins
      labels:
        name: jenkins
    spec:
      terminationGracePeriodSeconds: 10
      serviceAccountName: jenkins
      containers:
        - name: jenkins
          image: jenkins/jenkins:lts-alpine

          imagePullPolicy: Always 

          ports:
            - containerPort: 8080
            - containerPort: 50000
          resources:
            limits:
              cpu: 1
              memory: 1Gi
            requests:
              cpu: 0.5
              memory: 500Mi
          env:
            - name: LIMITS_MEMORY
              valueFrom:
                resourceFieldRef:
                  resource: limits.memory
                  divisor: 1Mi
            - name: JAVA_OPTS
              value: -Xmx$(LIMITS_MEMORY)m -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85
          volumeMounts:
            - name: jenkins-home
              mountPath: /var/jenkins_home
          livenessProbe:
            httpGet:
              path: /login
              port: 8080
            initialDelaySeconds: 60
            timeoutSeconds: 5
            failureThreshold: 12 # ~2 minutes
          readinessProbe:
            httpGet:
              path: /login
              port: 8080
            initialDelaySeconds: 60
            timeoutSeconds: 5
            failureThreshold: 12 # ~2 minutes
  volumeClaimTemplates:
  - metadata:
      name: jenkins-home
    spec:
      storageClassName: "managed-nfs-storage"
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
  name: jenkins
spec:
  type: NodePort
  selector:
    name: jenkins
  ports:
    -
      name: http
      port: 80
      targetPort: 8080
      protocol: TCP
      nodePort: 30008
    -
      name: agent
      port: 50000
      protocol: TCP

配置文件關鍵點是上面標注的位置:

PV 的問題,需要動態創建PV ,所以需要創建一個NFS 動態分配的PV 資源,當然也可以創建靜態的PV,這塊內容不多介紹了

關鍵看一下動態PV 的創建

nfs-server 

vim /etc/exports

/data/volumes/   10.0.0.0/8(rw,no_root_squash) 

vim nfs-pv.yaml
kind: ServiceAccount
apiVersion: v1
metadata:
  name: nfs-client-provisioner
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
  archiveOnDelete: "true"
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nfs-client-provisioner
spec:
  replicas: 1
  selector:
    matchLabels:
     app: nfs-client-provisioner
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          image: doudou007/nfs-pv:latest
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: fuseim.pri/ifs
            - name: NFS_SERVER
              value: 10.211.55.11
            - name: NFS_PATH
              value: /data/volumes
      volumes:
        - name: nfs-client-root
          nfs:
            server: 10.211.55.11
            path: /data/volumes            

 還有一點需要注意,給node節點需要安裝支持NFS掛載 客戶端的軟件包

yum install nfs-utils -y  

kubectl apply -f nfs-pv.yaml

kubectl apply -f jenkins-master.yaml

[root@k8s-master1 jenkins-new]# kubectl get pods |egrep jenkins

jenkins-0   1/1     Running   0          2m52s

 

這倆說明一下,需要安裝的插件

重點是需要安裝

pipe  插件  git 插件  kubernetes插件   kubernetes deploy 這幾個插件:

 

 

 

 

 

接下來配置jenkins-slave 

通過k8s 來動態創建jenkins-slave ,所以需要提供jenkins-slave 相關的鏡像

FROM centos:7
LABEL maintainer doudou
RUN yum install -y java-1.8.0-openjdk maven curl git libtool-ltdl-devel && \
    yum clean all && \
    rm -rf /var/cache/yum/* && \
    mkdir -p /usr/share/jenkins
COPY slave.jar /usr/share/jenkins/slave.jar
COPY jenkins-slave /usr/bin/jenkins-slave
COPY settings.xml /etc/maven/settings.xml
RUN chmod +x /usr/bin/jenkins-slave
ENTRYPOINT ["jenkins-slave"]

這個鏡像制作涉及到的幾個文件

jenkins-slave:  wget https://github.com/jenkinsci/docker-jnlp-slave/blob/master/jenkins-slave

slave.jar :通過master 獲取wget  http://10.211.55.13:30008/jnlpJars/slave.jar

maven:settings.xml:

 

文件沒什么變化關鍵是加入了一個阿里雲的倉庫,提高下載包的速度: 

  <mirror>
      <id>central</id>
      <mirrorOf>central</mirrorOf>
      <name>aliyun maven</name>
      <url>https://maven.aliyun.com/repository/public</url>
    </mirror>
  </mirrors>
[root@k8s-master1 jenkins-slave]# ls

Dockerfile  jenkins-slave  settings.xml  slave.jar

docker build -t hub.k8s.com/dev/jenkins-slave-jdk:1.8 ./

說明一下,這個是打包成Harbor推送的tag

hub.k8s.com  訪問路徑

dev 倉庫名

jenkins-slave-jdk:1.8  鏡像名和版本

docker login -u admin -p'Harbor12345' 

docker push  hub.k8s.com/dev/jenkins-slave-jdk:1.8

登陸Harbor可以看到相關的鏡像

下面通過jenkins來實現CI 和CD  

 

配置參數化構建:默認master用於多分支發布

 

 

 

下面是pipe 的語法:

https://jenkins.io/zh/doc/book/pipeline/syntax/

http://10.211.55.13:30008/me/my-views/view/all/job/demo/pipeline-syntax/ 

官方鏈接:

https://jenkins.io/zh/doc/book/pipeline/syntax/

 

 

涉及到幾個認證的ID,需要我們提前生成

下面認證用的ID 是需要在jenkins上面增加相關憑據才能生成ID,這樣做是為了保護隱私的密碼和用戶名
def docker_registry_auth = "898bbf50-9f94-480e-861d-187f5633f26c" 
def git_auth = "71bd0d12-3b2b-4acb-94cb-38f7aa9c6817"   
def k8s_auth = "f3b86b4f-68a7-4913-8f2d-c7683ecaa235" 

可以通過選項生成自己需要的語法,下面是配置好K8S ,在系統配置里面,增加一個雲,配置即可

 

 因為我們jenkins 是通過POD 安裝的,所以我們用內部提供的cluster 連接就可以,默認POD 都有權限訪問的

如果需要配置外部的

cat /root/.kube/config
echo certificate-authority-data | base64 -d > ca.crt
echo client-certificate-data | base64 -d > client.crt
echo client-key-data | base64 -d > client.key
openssl pkcs12 -export -out cert.pfx -inkey client.key -in client.crt -certfile ca.crt
key 拷貝ca.crt
cert.pfx 上傳上去
查看文章:https://blog.csdn.net/diantun00/article/details/81180694

k8s-deploy的配置

提取出核心的代碼

kubernetesDeploy configs: 'deploy.yml', kubeconfigId: "${k8s_auth}" 

deploy.yml 這個文件是在當前的倉庫里面查找,所有我們需要把這個文件也git 提交到倉庫

同樣,我們可以吧Jenkinsfile 的文件也提交到GIT 倉庫

 

[root@k8s-master1 java-demo]# ls
db deploy.yml  Jenkinsfile  LICENSE pom.xml README.md src

還有一點需要注意,因為是在POD 里面構建鏡像,所以需要通過secret來認證拉取鏡像的信息

def secret_name = "registry-pull-secret"

kubectl create secret docker-registry registry-pull-secret \
--docker-username=admin --docker-password=Harbor12345 \
--docker-email=doudou@k8s.com --docker-server=hub.k8s.com 

下面是具體的流水線代碼

def registry = "hub.k8s.com"
def project = "dev"
def app_name = "demo"
def image_name = "${registry}/${project}/${app_name}:${BUILD_NUMBER}"
def git_address = "git@10.211.55.14:/home/git/java-demo.git"
def secret_name = "registry-pull-secret"
def docker_registry_auth = "898bbf50-9f94-480e-861d-187f5633f26c"
def git_auth = "71bd0d12-3b2b-4acb-94cb-38f7aa9c6817"
def k8s_auth = "f3b86b4f-68a7-4913-8f2d-c7683ecaa235"
podTemplate(label: 'jenkins-slave', cloud: 'kubernetes', containers: [
    containerTemplate(
        name: 'jnlp',
        image: "${registry}/dev/jenkins-slave-jdk:1.8"
    ),
  ],
  volumes: [
    hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'),
    hostPathVolume(mountPath: '/usr/bin/docker', hostPath: '/usr/bin/docker')
  ],
)
{
  node("jenkins-slave"){
      // 第一步
      stage('拉取代碼'){
         checkout([$class: 'GitSCM', branches: [[name: '${Branch}']], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]])
      }
      // 第二步
      stage('代碼編譯'){
          sh "mvn clean package -Dmaven.test.skip=true"
      }
      // 第三步
      stage('構建鏡像'){
          withCredentials([usernamePassword(credentialsId: "${docker_registry_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
            sh """
              echo '
                FROM doudou007/tomcat
                RUN rm -rf /usr/local/tomcat/webapps/*
                ADD target/*.war /usr/local/tomcat/webapps/ROOT.war
              ' > Dockerfile
              ls
              ls target
              docker build -t ${image_name} .
              echo "${password}"|docker login -u ${username} --password-stdin ${registry}
              docker push ${image_name}
            """
            }
      }
      // 第四步
      stage('部署到K8S平台'){
          sh """
          sed -i 's#\$IMAGE_NAME#${image_name}#' deploy.yml
          sed -i 's#\$SECRET_NAME#${secret_name}#' deploy.yml
          """
          kubernetesDeploy configs: 'deploy.yml', kubeconfigId: "${k8s_auth}"
      }
  }
}

部署的yaml文件

vim deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: java-demo
  template:
    metadata:
      labels:
        app: java-demo
    spec:
      imagePullSecrets:
      - name: $SECRET_NAME
      containers:
      - name: tomcat
        image: $IMAGE_NAME
        ports:
        - containerPort: 8080
          name: web
        livenessProbe:
          httpGet:
            path: /
            port: 8080
          initialDelaySeconds: 60
          timeoutSeconds: 5
          failureThreshold: 12
        readinessProbe:
          httpGet:
            path: /
            port: 8080
          initialDelaySeconds: 60
          timeoutSeconds: 5
          failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  type: NodePort
  selector:
    app: java-demo
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080  

 

查看控制台日志輸出:

 

推送上的鏡像

[root@k8s-master1 demo]# kubectl get pods|egrep web
web-5b7c77d664-ddwbp 1/1      Running 1 3h2m
web-5b7c77d664-rd7lr    1/1      Running 1 3h2m

然后通過節點訪問,就可以看到訪問的程序了

說明整個流程是完成了,這塊需要加強學習的地方是jenkins 流水線發布的學習

核心就是jenkins的配置,這里方便演示,只用到GIT,后續可以擴展成gitlab 

下面是通過gitlab自動構建的文章:

https://www.cnblogs.com/yinzhengjie/p/9613270.html

 

 

還有一種方式應用k8s 的

kubernetes cli插件

這個插件功能只要在pod里面執行kubectl

提前把kubectl  打包編譯到jenkins 的鏡像里面

然后生成需要的憑據

jenkins添加kubernetes憑證

找一個有集群管理員角色的的secrets

kubectl describe secrets -n kube-system kubernetes-dashboard-token-fr9cz |egrep token:

或者

kubectl -n kube-system   get secrets  kubernetes-dashboard-token-fr9cz  -o go-template --template '{{index .data "token"}}' | base64 -d

 

 

然后在jenkins界面添加憑證

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM