接前一篇文章 kubernetes Jenkins gitlab搭建CI/CD环境–(一),本文介绍在Kubernetes上安装Jenkins。
Jenkins的安装有多种,可以在独立的服务器安装,结合K8S的话可以使用helm,参考:https://github.com/kubernetes/charts/tree/master/stable/jenkins
chart中使用的Jenkins基础镜像 jenkins/jenkins:lts,也可以通过Dockerfile自己定制。
下面是我基于jenkins/jenkins:lts定制的Dockerfile,增加了docker,docker-compose,kubectl和maven,然后使用yaml文件手动部署的。
Jenkins Master的 Dockerfile 如下:
FROM jenkins/jenkins:lts MAINTAINER Fisher.yu <yu2hei@gmail.com> EXPOSE 8080 50000 ENV DOCKER_VERSION=17.04.0-ce DOCKER_COMPOSE_VERSION=1.21.2 KUBECTL_VERSION=v1.10.1 # Use Root to setup kubectl, docker-ce, docker-compose USER root WORKDIR /usr/local/bin ############ # change debian source to 163 ############ RUN sed -i 's/deb.debian.org/mirrors.163.com/g' /etc/apt/sources.list RUN sed -i 's/security.debian.org/mirrors.163.com\/debian-security/g' /etc/apt/sources.list ############ # Update packages ############ RUN apt-get update && apt-get install -y --no-install-recommends \ make \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* ####### # docker-ce ####### #RUN curl -fsSLO https://get.docker.com/builds/Linux/x86_64/docker-${DOCKER_VERSION}.tgz \ RUN curl -fsSLO http://sudops.com/docker-${DOCKER_VERSION}.tgz \ && tar --strip-components=1 -xvzf docker-${DOCKER_VERSION}.tgz -C /usr/local/bin \ && chmod -R +x /usr/local/bin/docker ####### # docker-compose ####### #RUN curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-Linux-x86_64 -o /usr/local/bin/docker-compose \ RUN curl -L http://sudops.com/docker-compose-Linux-x86_64 -o /usr/local/bin/docker-compose \ && chmod +x /usr/local/bin/docker-compose ####### # kubectl ####### RUN curl -L http://sudops.com/kubectl-${KUBECTL_VERSION} -o /usr/local/bin/kubectl \ && chmod +x /usr/local/bin/kubectl ####### # Maven ####### # Preparation ENV MAVEN_VERSION 3.5.3 ENV MAVEN_HOME /etc/maven-${MAVEN_VERSION} # Installation RUN cd /tmp RUN wget http://archive.apache.org/dist/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz RUN mkdir maven-${MAVEN_VERSION} RUN tar -zxvf apache-maven-${MAVEN_VERSION}-bin.tar.gz --directory maven-${MAVEN_VERSION} --strip-components=1 RUN mv maven-${MAVEN_VERSION} ${MAVEN_HOME} ENV PATH ${PATH}:${MAVEN_HOME}/bin # Cleanup RUN rm apache-maven-${MAVEN_VERSION}-bin.tar.gz RUN unset MAVEN_VERSION ####### # Back to Jenkins home ####### USER jenkins WORKDIR $JENKINS_HOME
#build docker 镜像
docker build -t repo.ky.in/webcola/jenkins-docker-kubectl:v0.0.1 --no-cache .
#将build好的docker镜像push到私有docker-harbor中
docker push repo.ky.in/webcola/jenkins-docker-kubectl:v0.0.1
创建Jenkins部署文件
*** 本文中kubernetes使用namespace均为devns
创建jenkins PersistentVolumeClaim yaml文件
# cat jenkins-pvc.yaml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: jenkins-pvc namespace: devns spec: accessModes: - ReadWriteOnce resources: requests: storage: 60Gi storageClassName: kyglustersc ** 说明,这里指定了之前创建的storageclass: kyglustersc
创建jenkins deployment文件
# cat jenkins-deployment.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: kyjenkins namespace: devns labels: app: kyjenkins spec: strategy: type: Recreate template: metadata: labels: app: kyjenkins tier: kyjenkins spec: containers: - image: repo.ky.in/webcola/jenkins-docker-kubectl:v0.0.1 name: kyjenkins securityContext: privileged: true ports: - containerPort: 8080 name: kyjenkins - containerPort: 50000 name: agent protocol: TCP volumeMounts: - name: docker mountPath: /var/run/docker.sock - name: jenkins-persistent-storage mountPath: /var/jenkins_home - name: kube-config mountPath: /root/.kube/config volumes: - name: docker hostPath: path: /var/run/docker.sock - name: jenkins-persistent-storage persistentVolumeClaim: claimName: jenkins-pvc - name: kube-config hostPath: path: /root/.kube/config
创建jenkins-service
# cat jenkins-service.yaml apiVersion: v1 kind: Service metadata: name: kyjenkins namespace: devns labels: app: kyjenkins spec: ports: - port: 8080 targetPort: 8080 name: kyjenkins - port: 50000 targetPort: 50000 name: agent selector: app: kyjenkins tier: kyjenkins
然后执行
kubectl create -f .
待jenkisn pods running后,describe查看pods情况:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 2d (x5 over 2d) default-scheduler pod has unbound PersistentVolumeClaims (repeated 9 times) Normal Scheduled 2d default-scheduler Successfully assigned kyjenkins-8685458884-j8qjg to node_178 Normal SuccessfulMountVolume 2d kubelet, node_178 MountVolume.SetUp succeeded for volume "docker" Normal SuccessfulMountVolume 2d kubelet, node_178 MountVolume.SetUp succeeded for volume "kube-config" Normal SuccessfulMountVolume 2d kubelet, node_178 MountVolume.SetUp succeeded for volume "default-token-fxgsp" Normal SuccessfulMountVolume 2d kubelet, node_178 MountVolume.SetUp succeeded for volume "pvc-d7ad4f36-5d73-11e8-bcc6-5254006a334a" Normal Pulled 2d kubelet, node_178 Container image "repo.ky.in/webcola/jenkins-docker-kubectl:v0.0.1" already present on machine Normal Created 2d kubelet, node_178 Created container Normal Started 2d kubelet, node_178 Started container
Jenkins Master运行没问题,然后配置Ingress,并reload配置。
- host: jenkins.kydev.in http: paths: - backend: serviceName: kyjenkins servicePort: 8080
访问 http://jenkins.kydev.in
解锁密钥可以在kubernetes上执行 kubectl logs kyjenkins-8685458884-j8qjg -f 查看,也可以exec 进入到pods内部查看文件。
可以安装下社区推荐的插件:
Jenkins一些常用的插件,可以根据自己的实际情况安装:
locale php-jenkins-plugins checkstyle cloverphp dry htmlpublisher jdepend plot pmd violations xunit php git phing build-pipeline-plugin bouncycastle API PHP Built-in Web Server ElasticBox Jenkins Kubernetes CI/CD Javadoc Maven Integration OWASP Markup Formatter Static Analysis Utilities DRY GitLab Logo Kubernetes :: Pipeline :: Arquillian Steps Gitlab Merge Request Builder Kubernetes Cli Kubernetes :: Pipeline :: DevOps Steps Kubernetes :: Pipeline :: Kubernetes Steps Kubernetes :: Pipeline :: Aggregator Windows Slaves Matrix Authorization Strategy Phing Plot Gitlab Authentication Violation Comments to GitLab Token Macro Ant PAM Authentication LDAP External Monitor Job Type Run Condition Conditional BuildStep Parameterized Trigger jQuery Build Pipeline ruby-runtime Gitlab Hook xUnit Pipeline Aggregator GitHub API GitHub GitHub Branch Source Pipeline: GitHub Clover PHP JDepend Dashboard View Delivery Pipeline HTML Publisher PMD Checkstyle Violations php Checkstyle Azure Commons Kubernetes Continuous Deploy Kubernetes Credentials Provider GitLab Kubernetes :: Pipeline :: Kubernetes Steps Kubernetes :: Pipeline :: DevOps Steps
如果使用默认源比较慢,可以多试试其他几个源:
https://updates.jenkins.io/update-center.json (默认:) http://updates.jenkins-ci.org/update-center.json https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json http://mirror.xmission.com/jenkins/updates/current/update-center.json
接下来可以验证Master的工作情况:
创建一个freestyle的job kube-test。
可以看到任务执行成功,kubectl get pods -n devns 可以打印出结果。
接下来配置Jenkins slave
同样Jenkins slave也是采用自定义Dockerfile的方式
# cat Dockerfile FROM jenkins/jnlp-slave MAINTAINER Fisher.yu <yu2hei@gmail.com> ENV KUBECTL_VERSION=v1.10.1 DOCKER_VERSION=17.04.0-ce USER root ########## # Maven-3.5.3 ########## COPY maven /usr/share/maven/ RUN chmod +x /usr/share/maven/bin/mvn && ln -s /usr/share/maven/bin/mvn /usr/local/bin/mvn ########## # kubectl-1.10.1 ########## COPY kubectl /usr/local/bin/ RUN chmod +x /usr/local/bin/kubectl ########## # 预配置 kubectl ########## ########## # 在运行时由 ConfigMap 挂载Volume ########## ENV CERT_DIR /etc/kubernetes/conf ARG DOCKER_SOCK_DIR=/var/run/docker.sock RUN mkdir -p ${CERT_DIR} \ mkidr -p /root/.kube \ touch ${CERT_DIR}/k8s-root-ca.pem \ touch ${CERT_DIR}/admin.pem \ touch ${CERT_DIR}/admin-key.pem COPY config /usr/local/bin/ RUN export KUBECONFIG=/usr/local/bin/config && kubectl config view ########## # docker-ce ########## #------------------------------------------------# copy docker /usr/bin/docker RUN apt-get -y update && apt-get install -y apt-utils iptables libdevmapper1.02.1 libltdl7 libseccomp2 && apt-get -y autoremove && chmod +x /usr/bin/docker ########## # 挂载volume ########## VOLUME ${CERT_DIR} VOLUME ${DOCKER_SOCK_DIR}
## 当前目录结果 # tree . . ├── config ├── docker ├── docker-compose ├── Dockerfile ├── kubectl └── maven ├── bin ├── conf ├── lib └── README.txt
# cat config apiVersion: v1 clusters: - cluster: certificate-authority: /etc/kubernetes/conf/k8s-root-ca.pem server: http://k8sapi.kydev.in name: kubernetes contexts: - context: cluster: kubernetes namespace: kube-system user: admin name: kubernetes current-context: kubernetes kind: Config preferences: {} users: - name: admin user: client-certificate: /etc/kubernetes/conf/admin.pem client-key: /etc/kubernetes/conf/admin-key.pem
将build的镜像push到私有repo中。
docker build -t repo.ky.in/webcola/jnlp-slave-docker-kubectl-ky:v0.0.1 --no-cache . docker push repo.ky.in/webcola/jnlp-slave-docker-kubectl-ky:v0.0.1
# (1). 创建 kubectl-cert-cm 资源对象 kubectl create configmap kubectl-cert-cm --from-file=/etc/kubernetes/ssl -n=devns # (2). 查看所创建的 kubectl-cert-cm 资源对象 kubectl describe configmap kubectl-cert-cm -n=devns
下面继续配置Jenkins的Slave节点。
Kubernetes Pod Template 中配置,详见截图
好了,现在Jenkins的jnlp-slave已经配置完毕
下面开始测试:
创建pipeline任务
pipeline script
def label = "mypod-${UUID.randomUUID().toString()}" podTemplate(label: label, containers: [ containerTemplate(name: 'maven', image: 'repo.ky.in/webcola/jdk-maven-ant:v1.0.0', ttyEnabled: true, command: 'cat') ]) { node(label) { stage('Get a Maven project') { container('maven') { stage('wait for exec check'){ sh 'sleep 10' } stage('get maven env') { sh 'cat /etc/resolv.conf' sh 'cat /etc/issue' sh 'uname -a' sh 'env' sh 'echo "$(sed \'s/options ndots:5/#options ndots:5/g\' /etc/resolv.conf)" > /etc/resolv.conf' } stage('code checkout') { git url: 'http://gitlab.ky.in/devops/tomcatwartest.git', credentialsId: '29efa3cc-4fe7-42e2-95a4-a03c18d56603', branch: 'master' sh 'mvn clean package' sh 'sleep 300' } } } } }
任务运行成功。
在配置Jenkins-slave是有几个地方需要注意:
(1)Jenkins slave使用自定义镜像调用kubectl时freestyle的任务可以在构建环境中指定『setup kubernetes CLI』,但是在pipeline中就需要在镜像里面做文章了,可以参考jenkins-slave的Dockerfile,需要将三个证书文件和config文件传入到镜像中,创建kubectl-cert-cm的configmap。
(2)pipeline中的podTemplate指定了自定义的image,但是实际启动中还是会默认再启动一个jenkins/jnlp-slave:alpine的镜像。然而这个alpine本身就有很多”坑”,比如dns解析的问题,在slave的镜像里面git代码会报Can’t resolve git server host。解决方式就是注释掉/etc/resolv.conf里面的”options ndots:5″ 这行,具体见我之前的文章:kubernetes 使用基于 alpine 镜像无法正常解析外网DNS
好了,接下来的文章会介绍kubernetes上安装gitlab,配置钩子自动出发流程,以及本文涉及的一个简单的tomcat-maven测试环境。