云原生架构系列之NodeJS自动CI/CD

本文以NodeJS开发框架为例,讲解如何组合Kubernetes、GitLab、Docker、Docker Registry等技术,实现CI/CD的自动化。

NodeJS 示例

本文假设开发机器已经安装nodejs、express、express generator、docker

通过以下命令产生一个基本框架

express --no-view --git

然后运行nodejs,在浏览器中访问http://localhost:3000/即可看到express的页面。

npm start

在Kubernetes集群中创建Gitlab账户

创建gitlab-service-account.yaml文件

该文件中创建了一个gitlab-service-account账户,并做了角色绑定。

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: gitlab-service-account
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: gitlab-service-account-role-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: gitlab-service-account
    namespace: default

Kubernetes中创建账户和角色绑定

kubectl apply -f gitlab-service-account.yaml

部署Docker Registry

本示例选择在CentOS 7上安装VMware Harbor,如何部署请参阅网上其他文章,或看稍后的文章。

GitLab 配置

GitLab的部署在本篇中也不详述,请参与其他部分-。

为了使用CI/CD,我们需要在GitLab中设置环境变量。

位置:项目设置->CI/CD->环境变量,展开后即可设置。

注意:为了安全,REGISTRY_PASSWORD, K8S_USER_TOKEN, K8S_CA_PEM 应该予以保护。

REGISTRY_SERVER: Docker Registry的URL,!!!如果是Docker Hub,则需要修改本文件

REGISTRY_USER: 登录Docker Registry的用户名

REGISTRY_PASSWORD: 登录Docker Registry的密码

K8S_SERVER: Kubernetes API Server

K8S_USER_TOKEN: 链接Kubernetes集群的用户令牌。

获取用户TOKEN的方式:

kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep gitlab-admin | awk '{print $1}')

K8S_CA_PEM : Kubernetes集群的CA证书

获取方式:

kubectl get secret <secret name> -o jsonpath="{['data']['ca\.crt']}"

通过 GitLab 构建 Docker

接下来,我们在看在GitLab中如何构建Docker

创建.gitlab-ci.yml文件

image: docker:latest
services:
  - docker:dind

stages:
  - build
  - deploy

variables:
  CONTAINER_IMAGE: testapp:${CI_COMMIT_SHORT_SHA}
  DOCKER_HOST: tcp://localhost:2375/
  DOCKER_DRIVER: overlay2
  REGISTRY_IMAGE: ${REGISTRY_SERVER}/library/testapp:${CI_COMMIT_SHORT_SHA}

build:
  stage: build
  script: 
    - docker login -u ${REGISTRY_USER} -p ${REGISTRY_PASSWORD} ${REGISTRY_SERVER}
    - docker build -t ${CONTAINER_IMAGE} .
    - docker tag ${CONTAINER_IMAGE} ${REGISTRY_IMAGE}
    - docker push ${REGISTRY_IMAGE}
    - docker tag ${CONTAINER_IMAGE} testapp:latest

其中docker:latest是来自于Docker Hub的镜像,并使用Docker-in-Docker(dind)技术。

${CI_COMMIT_SHORT_SHA}:GitLab在提交代码时会生成一个简短的SHA码,这是该环境变量;

DOCKER_HOSTDOCKER_DRIVER必须如此设置,否则将会出现无法打开socket的错误提示。

REGISTRY_IMAGE 是组合后的本地Registry的URL

其中的Build脚本对应几个步骤:

  1. 登录本地Registry;
  2. 构建Docker
  3. 标记Docker为本地Registry
  4. 推送Docker到本地Registry
  5. 标记本地Docker为最新版本。这条实际上没有用。

创建 Dockerfile

FROM node:10

WORKDIR /usr/src/app

COPY package*.json ./
RUN npm install --registry <LOCAL NPM REGISTRY URL>
RUN npm ci --only=production

# Bundle app source
COPY . .

EXPOSE 3000
CMD ["npm", "start"]

部署到Kubernetes集群中

创建deployment.yaml文件

apiVersion: apps/v1
kind: Deployment
metadata:
  name: testapp
  labels:
    app: testapp
spec:
  replicas: 2
  selector:
    matchLabels:
      app: testapp
      tier: frontend
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app: testapp
        tier: frontend
    spec:
      containers:
        - name: testapp
          image: docker.shmtu.edu.cn/library/testapp:<VERSION>
          ports:
            - containerPort: 3000
          livenessProbe:
            httpGet:
              path: /
              port: 3000
            initialDelaySeconds: 2
            periodSeconds: 2
          readinessProbe:
            httpGet:
              path: /
              port: 3000
            initialDelaySeconds: 2
            periodSeconds: 2
      imagePullSecrets:
        - name: local-registry    

其中有几个需要说明的地方:

1、因为需要选用本地Registry的镜像,所以需要先创建secret:

kubectl create secret docker-registry local-registry \
--docker-server=docker.shmtu.edu.cn \
--docker-username=<REGISTRY_USER> \
--docker-password=<REGISTRY_PASSWORD>

创建完成后,可以查看是否正确:

kubectl get secret local-registry --output="jsonpath={.data.\.dockerconfigjson}" | base64 -d

2、作为App监控的livenessProbe和readinessProbe最好也配置上。

其余参数不做讲解。

部署Service

由于deployment.yaml每次都会执行,其中的pod都会创建,这样就需要我们把service部署文件放在外面,第一次部署之前执行一次即可。

apiVersion: v1
kind: Service
metadata:
  name: testapps-svc
  namespace: gitlab-managed-apps
  labels:
    app: testapp-svc
spec:
  type: NodePort
  ports:
  - port: 3000
    nodePort: 30300
  selector:
    app: testapp
    tier: frontend

修改 .gitlab-ci.yml 文件

在 .gitlab-ci.yml 文件中,添加deploy阶段的内容

deploy:
  stage: deploy
  image: docker.shmtu.edu.cn/library/helm-kubectl:1.14.1
  script:
    - kubectl version
    - kubectl config set-cluster k8s --server="${K8S_SERVER}"
    - kubectl config set clusters.k8s.certificate-authority-data "${K8S_CA_PEM}"
    - kubectl config set-credentials gitlab --token="${K8S_USER_TOKEN}"
    - kubectl config set-context default --cluster=k8s --user=gitlab
    - kubectl config use-context default
    - sed -i "s/<VERSION>/${CI_COMMIT_SHORT_SHA}/g" deployment.yaml
    - cat deployment.yaml
    - kubectl apply -f deployment.yaml

注意:

1、目前dtzar/helm-kubectl Docker镜像支持到kubectl v1.13.4,而我们的集群是v1.14.0,所以我们自行Build了这个Docker,并推送到本地的Docker Registry中。

2、其中的cat deployment.yaml并不必要,仅仅是为了排错使用,可以去掉该命令。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355

推荐阅读更多精彩内容