Jenkins在kubernetes上的初体验

2020-06-15 14:52:15 浏览数 (1)

在 kubernetes 上部署 Jenkins

在k8s上运行jenkins之前,我们需要知道几件事情:

  1. 可以通过image修改 jenkins 镜像的版本
  2. 可以通过nodeSelector选择 jenkins pod 运行在哪个 Node(cpu/mem 充足)节点上
  3. 我们对 Jenkins 的运行做了资源限制,如果不够,可以按需修改,limitsrequests中的 CPU 单位通常是指 CPU 的千分之一为最小单位,所以 1000m 就表示 1 个 CPU,200m 表示 0.2 个
  4. 我们对 jenkins 的数据做了持久化配置,通过 nfs 提供 pv,如果你有 ceph,glusterfs,可以按需修改
  5. jenkins 在 k8s 上被指定到了kube-ops命令空间下,如果没有,请提前创建kubectl create ns kube-ops
  6. 使用 jenkins 最头疼的事就是插件下载不下来,无法正常运行,因此有两个办法就是,第一,你把基础插件提前拷贝到存储卷上,第二就是通过把插件打到 jenkins docker 镜像内,其实都一样。

准备配置清单

配置清单的文件名称,使用者按需自己创建。

准备 pv 和 pvc 的清单配置文件

代码语言:javascript复制
apiVersion: v1
kind: PersistentVolume
metadata:
  name: jenkinspv
spec:
  capacity:
    storage: 15Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Delete
  nfs:
    server: 172.16.132.231
    path: /data/k8s
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: jenkinspvc
  namespace: kube-ops
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 15G

创建 pv/pvc 对象,这里我们要注意 nfs 提供给 jenkins 的存储目录的权限问题,否则服务因为权限无法写入数据:

在 nfs 服务主机上:

代码语言:javascript复制
chown -R 1000 /data/k8s/jenkins2

然后,我们就可以配置 pv 了:

代码语言:javascript复制
kubectl apply -f jenkins-storage.yaml

准备 ServiceAccount 资源对象

代码语言:javascript复制
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins2
  namespace: kube-ops
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: jenkins2
  namespace: kube-ops
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: jenkins2
  namespace: kube-ops
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: jenkins2
subjects:
  - kind: ServiceAccount
    name: jenkins2
    namespace: kube-ops

创建 sa 对象

代码语言:javascript复制
kubectl apply -f jenkins-sa.yaml

准备 jenkins deployment 配置清单

在准备好 sa 和存储之后,我们就可以运行 jenkins 了,这里我们通过ClusterIP访问 Jenkins pod,因此我们还会准备一个 jenkins service 资源对象在 deployment 下方

代码语言:javascript复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins2
  namespace: kube-ops
spec:
  selector:
    matchLabels:
      app: jenkins2
  template:
    metadata:
      labels:
        app: jenkins2
    spec:
      nodeSelector:
        kubernetes.io/hostname: dev-k8s-02.kubemaster.top
      terminationGracePeriodSeconds: 10
      serviceAccountName: jenkins2
      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: 2000m
              memory: 4Gi
            requests:
              cpu: 1000m
              memory: 2Gi
          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: jenkins2
              mountPath: /var/jenkins_home
          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 -Duser.timezone=Asia/Shanghai
      securityContext:
        fsGroup: 1000
      volumes:
        - name: jenkinshome
          persistentVolumeClaim:
            claimName: jenkinspvc

---
apiVersion: v1
kind: Service
metadata:
  name: jenkins2
  namespace: kube-ops
  labels:
    app: jenkins2
spec:
  selector:
    app: jenkins2
  ports:
    - name: web
      port: 8080
      targetPort: web
    - name: agent
      port: 50000
      targetPort: agent

此时我们就可以应用apply这个 deployment 了,在应用之后,如果你的nodeSelector服务器上没有这个 jenkins 的镜像,可能需要一段时间拉取

代码语言:javascript复制
kubectl apply -f jenkins-deployment-with-svc.yaml

当 jenkins 运行成功之后,我们应该如何访问呢,此处我们通过 traefik 的ingressroute增加一个路由,用于在(k8s 集群外)外部访问 jenkins,如果你还没有 Traefik,想要安装的话,可以查看 Traefik 在 k8s 的使用文章

准备 jenkins ingressroute 配置清单

代码语言:javascript复制
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: jenkinsingress
  namespace: kube-ops
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`jenkins.kubemaster.top`)
      kind: Rule
      services:
        - name: jenkins2
          port: 8080

将配置应用到 k8s 环境中

代码语言:javascript复制
kubectl apply -f jenkins-ingressroute.yaml

准备域名以及 DNS 解析

准备一个域名,将域名解析到 Traefik 运行的主机上,通过 web 端口既可以访问 jenkins 了

代码语言:javascript复制
☸️  devcluster? tracing  ~/api   master  ? ? curl -I jenkins.kubemaster.top
HTTP/1.1 403 Forbidden
Content-Length: 793
Content-Type: text/html;charset=utf-8
Date: Tue, 21 Apr 2020 09:32:36 GMT
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Server: Jetty(9.4.25.v20191220)
Set-Cookie: JSESSIONID.b1161c1c=node07msgdvrmibs59emvt3tn25pp433368.node0; Path=/; HttpOnly
X-Content-Type-Options: nosniff
X-Hudson: 1.395
X-Hudson-Cli-Port: 50000
X-Jenkins: 2.204.3
X-Jenkins-Cli-Port: 50000
X-Jenkins-Cli2-Port: 50000
X-Jenkins-Session: d1c63459
X-Permission-Implied-By: hudson.security.Permission.GenericRead
X-Permission-Implied-By: hudson.model.Hudson.Administer
X-Required-Permission: hudson.model.Hudson.Read
X-You-Are-Authenticated-As: anonymous
X-You-Are-In-Group-Disabled: JENKINS-39402: use -Dhudson.security.AccessDeniedException2.REPORT_GROUP_HEADERS=true or use /whoAmI to diagnose

0 人点赞