记一次Gitlab-CI集成K8S实录

in DevOps with 0 comment

2019年号称云原生元年,企业全面上云,上云就上云原生。各大云厂商云原生事业如火如荼的进行着。Gitlab也不甘人后,很好的支持和构建云原生项目。部署环境的搭建和配置向来繁杂,云原生之前的年代,搭建和配置部署环境还存在大量人工而且重复地劳动,浪费了大量时间和精力在环境部署上,而且环境难以移植,微服务的兴起更是加剧了环境搭建和配置的难度,对运维也是一大挑战。容器及其编排技术因此而孕育而生,宿主环境的无感知,极易地扩缩容,容器技术存在巨大优势。但容器及其编排环境搭建本身也不是一件容易的事情,各种套件你方唱罢我登场。Iass、Pass层领域容器云环境搭建和维护成本问题都摆在那里,各大云厂商云原生事业才有了广阔的市场前景,都想在这一领域独占鳌头。Docker、Kubernetes、Harbor、Prometheus等集群环境不是本文关注的重点,这里只是记录Gitlab-CI集成K8S的试验,依赖现成的K8S集群环境,但曾经被还原过一次,导致一些配置丢失。CI集成K8S跟集成其他环境步骤相同,同样需要两步,第一步,安装Gitlab-Runner及注册授权,需要注意的是,需要选择Kubernetes执行器;第二步是还是编写.gitlab-ci.yaml文件,只是需要Docker等容器命令的相关知识。此外,由于Kubernetes是基于RBAC角色权限设计,需要有Kubernetes Service Account具有操纵K8S集群的权限。

Gitlab-ci绑定k8s集群

我们可以先手动一个K8S集群的集成,预置好具有对K8S集群有操纵权限的账号,供后续使用。

image-20200803105705828

然后在K8S环境里准备好集群环境配置参数

API,URL 指向k8s集群地址

kubectl cluster-info | grep 'Kubernetes master' | awk '/http/ {print $NF}'

CA certificate, 需要k8s认证

[root@wenqy gitlab]# kubectl get secrets
NAME                  TYPE                                  DATA   AGE
default-token-xxlhq   kubernetes.io/service-account-token   3      47d
[root@wenqy gitlab]# kubectl get secret default-token-xxlhq -o jsonpath="{['data']['ca\.crt']}" | base64 --decode
-----BEGIN CERTIFICATE-----
MIICyDCCAbCgAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl
	......
gINmxCg80ZwsEXEUo8UE2ybYVd/GmhPShuW/UriJcj6Ncx9viX2EsyoviVU=
-----END CERTIFICATE-----
[root@wenqy gitlab]# 

Token, K8S授予具有cluster-admin账号权限的token

K8S集群环境创建至少有container.clusterRoleBindings.create权限的账号

[root@wenqy gitlab]# cat gitlab-admin-service-account.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: gitlab-admin
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: gitlab-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: gitlab-admin
  namespace: kube-system

[root@wenqy gitlab]# kubectl apply -f gitlab-admin-service-account.yaml
serviceaccount/gitlab-admin created
clusterrolebinding.rbac.authorization.k8s.io/gitlab-admin created

K8S集群环境获取Token

[root@wenqy gitlab]# kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep gitlab-admin | awk '{print $1}')
Name:         gitlab-admin-token-xsknq
Namespace:    kube-system
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: gitlab-admin
              kubernetes.io/service-account.uid: d67285d1-d538-11ea-ba67-000c29b409ba

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1025 bytes
namespace:  11 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWN
	......
5qcaEOsXRuVrmG0hAHqVHpAvryuQ3CA
[root@wenqy gitlab]# 

如果出现is blocked: Requests to the local network are not allowed错误,需要用管理员账号开启配置,允许访问本地网络

clip_image001

填入上述参数后,创建成功

image-20200803113646082

这一步可能不是必须的,需要注意是对哪个名称空间创建服务账号,需要部署在哪个名称空间下,否则可能导致部署失败

操作页面本身有链接参考

http://gitlab.wenqy.com/help/user/project/clusters/add_remove_clusters.md#add-existing-cluster

K8S安装Gitlab-Runner

安装Gitlab-Runner可以有多种形式,或者使用不同的执行器等等。这里采用Helm+Tiller的形式,直接将Gitlab-Runner部署到K8S集群中。

安装Helm

Helm是K8S的应用包管理器,主要用于 Kubernetes 应用程序 Chart 的创建、打包、发布以及创建和管理本地和远程的 Chart 仓库。Helm官方提供一键安装脚本

curl https://raw.githubusercontent.com/helm/helm/master/scripts/get > get_helm.sh
$ chmod 700 get_helm.sh
$ ./get_helm.sh
安装Tiller

Tiller是 Helm 的服务端,部署在 Kubernetes 集群中。Tiller 用于接收 Helm 的请求,并根据 Chart 生成 Kubernetes 的部署文件(Helm 称为 Release),然后提交给 Kubernetes 创建应用。官方Tiller镜像被墙,利用dockerhub第三方镜像打tag成官方镜像,可以推送到私有镜像仓库,或者找国内的源

docker pull fishead/gcr.io.kubernetes-helm.tiller:v2.12.3
docker tag fishead/gcr.io.kubernetes-helm.tiller:v2.12.3 gcr.io/kubernetes-helm/tiller:v2.12.3

helm部署Tiller

helm init --service-account tiller --tiller-image gcr.io/kubernetes-helm/tiller:v2.12.3 --skip-refresh

使用国内源

helm init --service-account tiller --upgrade -i registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.12.3  --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts

查看Tiller是否部署成功

kubectl get pods -n kube-system|grep tiller

如果出现ImagePullBackOff

[root@wenqy gitlab]# kubectl get pods -n kube-system|grep tiller
tiller-deploy-85d786df69-l6ch4            0/1     ImagePullBackOff   0          12d

可以先拉取tiller镜像到本地,编辑配置文件,把拉取策略改为imagePullPolicy:Never,只从本地拉取

#使用命令编辑配置,IfNotPresent :如果本地存在镜像就优先使用本地镜像
kubectl edit deployment tiller-deploy -n kube-system

重启Tiller pod

kubectl get pods -n kube-system|grep tiller
kubectl get pod tiller-deploy-d87494c4-qnr7t -n kube-system -o yaml | kubectl replace --force -f -

给Tiller授权

创建 Kubernetes 的服务帐号和绑定角色

kubectl create serviceaccount --namespace kube-system tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller

使用 kubectl patch 更新 API 对象

kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'

查看是否授权成功

kubectl get deploy --namespace kube-system   tiller-deploy  --output yaml|grep  serviceAccount

查看是否安装成功

[root@wenqy gitlab]# helm version
Client: &version.Version{SemVer:"v2.16.1", GitCommit:"bbdfe5e7803a12bbdf97e94cd847859890cf4050", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.16.1", GitCommit:"bbdfe5e7803a12bbdf97e94cd847859890cf4050", GitTreeState:"clean"}
安装Gitlab-Runner

准备url、token等信息

image-20200803160710387

准备Helm values.yaml配置,注意填写gitlabUrl、token、tag、harbor secret和hostAliases等信息或者限制资源

imagePullPolicy: IfNotPresent
gitlabUrl: http://gitlab.wenqy.com/
runnerRegistrationToken: "aYT_P3W8qddRy6hpFf7a"
terminationGracePeriodSeconds: 3600
concurrent: 10
checkInterval: 30
rbac:
  create: false
  clusterWideAccess: false
  # serviceAccountName: default
  podSecurityPolicy:     
    enabled: false
    resourceNames:      
      - gitlab-runner
metrics:                                                                                                       enabled: true
runners:
  image: ubuntu:18.04
  tags: "k8s-runner"
  privileged: true
  pollTimeout: 180
  outputLimit: 4096
  cache: {}
  builds: {}
  services: {}
  helpers: {}
securityContext:
  fsGroup: 65533
  runAsUser: 100
resources: {}
affinity: {}
nodeSelector: {}
tolerations: []
hostAliases:                                                                                               
  - ip: "192.168.1.106"
    hostnames: ["dockerhub.wenqy.com"]                                                                       podAnnotations: {}
podLabels: {}

由于K8S集群环境没有配置VPC,这里没有开启缓存,需要注意的是,使用docker in docker构建镜像 时privileged必须为true,开启特权模式,即privileged: true,否则会报无法连接docker daemon的错误,开启特权意味着Pod对docker的资源限制可能失效

参考

https://gitlab.com/gitlab-org/charts/gitlab-runner/-/blob/master/values.yaml

这里总是按照最新的Gitlab-runner版本,利用Helm安装Gitlab-runner

helm repo add gitlab https://charts.gitlab.io
helm install --namespace gitlab --name gitlab-runner -f  values.yaml gitlab/gitlab-runner

如果提示报错:

[root@wenqy gitlab]# helm install --namespace gitlab --name gitlab-runner -f values.yaml gitlab/gitlab-runner
Error: Could not get apiVersions from Kubernetes: unable to retrieve the complete list of server APIs: metrics.k8s.io/v1beta1: the server is currently unable to handle the request

删除无用api,再次安装Gitlab-Runner

[root@wenqy gitlab]# kubectl get apiservice
NAME                                   SERVICE                      AVAILABLE                  AGE
v1beta1.extensions                     Local                        True                       47d
v1beta1.metrics.k8s.io                 kube-system/metrics-server   False (MissingEndpoints)   47d
v2beta2.autoscaling                    Local                        True                       47d
[root@wenqy gitlab]# kubectl delete apiservice v1beta1.metrics.k8s.io
apiservice.apiregistration.k8s.io "v1beta1.metrics.k8s.io" deleted

查看Gitlab-Runner pod状态

kubectl describe pod gitlab-runner-gitlab-runner-9ffb46694-d62rc -n gitlab

校验Gitlab-Runner是否成功

[root@wenqy gitlab]# kubectl get pod -n gitlab
NAME                                          READY   STATUS    RESTARTS   AGE
gitlab-runner-gitlab-runner-9ffb46694-d62rc   1/1     Running   0          27m

回到gitlab,gitlab-runner出现绿色实心圈,说明注册成功了

image-20200803153119363

CI流水线

变量定义

编写.gitlab-ci.yaml文件前,可以先定义一些变量,保存kubeConfig或者私有镜像仓库的账号信息等等

image-20200803154739696

获取kube_config编码串,定义到变量中,利用kube_config访问集群,在deploy阶段可有用

echo $(cat ~/.kube/config | base64) | tr -d " "

gitlab-ci部署阶段,将编码串解码写入配置

variables:
  KUBECONFIG: /etc/deploy/config
  ....
deploy_k8s_job:
  image: dockerhub.wenqy.com/gitlab/kubectl:1.0.0
  stage: deploy_k8s
  tags:
    - k8s-runner
  before_script:
    - mkdir -p /etc/deploy
    - echo $kube_config |base64 -d > $KUBECONFIG

如果Gitlab-ci绑定k8s集群使用的Service Account对指定的namespace拥有create权限的话,是可以跳过这步kube_config配置的。

重新分配Service Account

由于k8s环境被人还原过一次,很多配置都丢失了,gitlab-ci绑定的Service Account不一致,gitlab-ci报错:

ERROR: Job failed (system failure): pods is forbidden: User "system:serviceaccount:gitlab:default" cannot create resource "pods" in API group "" in the namespace "gitlab"

新增namespace为gitlab,name为default的Service Account

# Source: gitlab-runner/templates/service-account.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: default
  namespace: gitlab
---
# Source: gitlab-runner/templates/role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: "ClusterRole"
metadata:
  name: default
  namespace: gitlab
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["*"]
---
# Source: gitlab-runner/templates/role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: "ClusterRoleBinding"
metadata:
  name: default
  namespace: gitlab
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: "ClusterRole"
  name: default
subjects:
- kind: ServiceAccount
  name: default
  namespace: gitlab

删除原有gitlab-runner

[root@wenqy gitlab]# helm ls
NAME            REVISION        UPDATED                         STATUS          CHART                   APP VERSION     NAMESPACE
gitlab-runner   1               Mon Aug  3 18:11:11 2020        DEPLOYED        gitlab-runner-0.19.1    13.2.1          gitlab   
[root@wenqy gitlab]# helm del --purge gitlab-runner

可以修改values.yaml,添加serviceAccountName属性,指定gitlab-runner使用Service Account账号角色权限操纵

runners:
  serviceAccountName: default

参考

https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3841

重建Gitlab-Runner,可以指定Gitlab-Runner版本

helm install --namespace gitlab --name gitlab-runner -f  values.yaml gitlab/gitlab-runner --version 0.14.0
分配imagePullSecrets

重新注册Gitlab-Runner后,gitlab-ci报错,无法拉取自定义镜像

 ERROR: Job failed (system failure): prepare environment: image pull failed: rpc error: code = Unknown desc = Error response from daemon: pull access denied for xxxxxxx/gitlab/maven_deps, repository does not exist or may require 'docker login'. Check https://docs.gitlab.com/runner/shells/index.html#shell-profile-loading for more information

可以暂时先在K8S集群宿主机里手动拉取私服上的自定义镜像,默认拉取策略是IfNotPresent,优先从本地拉取,而出现问题原因没有配置拉取镜像的秘钥,指向docker registry的域名映射,在values.yaml分配秘钥,重新安装Gitlab-Runner

runners:                                                                                                     	imagePullSecrets:	["harbor-secret"]
hostAliases:                                                                                               
  - ip: "192.168.181.106"
    hostnames: ["dockerhub.wenqy.com"]
开启特权模式

继续执行gitlab-ci流水线,问题来到了下面:

68 $ docker login -u $REGISTRY_USERNAME -p $REGISTRY_PASSWORD dockerhub.wenqy.com
69 WARNING! Using --password via the CLI is insecure. Use --password-stdin.
70 time="2020-08-03T10:47:18Z" level=info msg="Error logging in to v2 endpoint, trying next endpoint: Get https://dockerhub.wenqy.com/v2/: dial tcp xx.xx.xx.xx:443: connect: connection refused"
71 Get https://dockerhub.wenqy.com/v2/: dial tcp xx.xx.xx.xx:443: connect: connection refused
72 ERROR: Job failed: command terminated with exit code 1

这次在k8s集群环境还原之前,出现过类似问题,当时是docker in docker版本问题所导致,采用版本降级处理。那现在为什么不行了呢?因为使用的docker image是stable,稳定版可能升级了,我把矛头还是指向了docker版本问题,使用具体的低版本,还在docker login之前使用docker info,还是出现问题:

docker: Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?.

太多人碰到了这个问题,官方文档为此都出了故障排除集锦。问题虽已解决过,还是纠结于其中。基础环境已经一致,应当刹车才对。查看官方文档,docker-dind需要开启特权模式。由于k8s环境还原,helm values.xml文件也丢失了,凭借印象,还特地把privileged改为false,不知其所以然,实在是尴尬。按照说法,docker需要挂载/var/run/docker.sock与docker daemon通信,docker容器内默认是普通用户权限,这时需要提升到root权限。

# values.yaml
runners:             
  privileged: true 

特权模式也可能带来相应的安全隐患,据官网说法还可能带来一定的性能损失,docker-dind应该不是一个值得推荐的build方式。另外一种是使用google的kaniko,但由于众所周知的The Great Firewall of China,kaniko是被屏蔽的。知识终究是有国界的,因为知识最终是以人为载体的。可以考虑第三方kaniko,这里不做尝试。

参考

https://docs.gitlab.com/runner/executors/kubernetes.html#configuring-executor-service-account

https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#use-docker-in-docker-workflow-with-docker-executor

kube_config配置

因为使用了自定义变量kube_config配置,k8s环境还原后,配置已然不对,导致报错:

unable to recognize "deployment.yaml": Get https://192.168.1.141:6443/api?timeout=32s: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")

在k8s宿主机上重新获取配置,定义变量值,解决问题

sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
echo $(cat ~/.kube/config | base64) | tr -d " "
自定义镜像

由于没有启动缓存,项目每次构建时需要从阿里云私服下载依赖都非常慢,先迫不得已做个妥协,做一个黑盒镜像,先把依赖缓存到镜像,在推送到镜像私服上去,加快构建步骤,这步并不是必须的。

docker run it maven:3.6.2-jdk-14 sh
# 容器内创建maven工程,跑pom
mvn -s ci_settings.xml --batch-mode package -B -DskipTests
# 退出容器后提交一个新的镜像
docker ps
docker commit 065b4f9d20ac maven_deps:3.6.2-jdk-14
docker tag  maven_deps:3.6.2-jdk-14 dockerhub.wenqy.com/gitlab/maven_deps:3.6.2-jdk-14
docker:dind版本问题

因为之前说过docker in docker 版本问题,在构建应用镜像的阶段也会导致下面错误:

docker: Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?.

问题的原因在于docker:dind的19.03版本以后,默认会开启TLS通信,由于k8s集群环境没有开启TLS,需要关闭TLS,或者降级dind版本到18.09。

关闭TLS

将TLS证书目录路径设空DOCKER_TLS_CERTDIR: ''

docker_build_job:
  #image: docker:stable
  image: docker:19.03.0
  stage: docker_build
  variables:
    DOCKER_DRIVER: overlay2
    DOCKER_TLS_CERTDIR: ''
    #CI_DEBUG_TRACE: "true"
  services:
    - name: docker:19.03.0-dind

降级版本

将docker:dind版本降级到18.09

docker_build_job:
  image: docker:18.09.7
  stage: docker_build
  variables:
    DOCKER_DRIVER: overlay2
    DOCKER_HOST: tcp://localhost:2375
    #CI_DEBUG_TRACE: "true"
  services:
    - name: docker:18.09.7-dind
      entrypoint: ["dockerd-entrypoint.sh"]
      command: ["--insecure-registry", "dockerhub.wenqy.com"]

因为Harbor Registry服务器是开启Https的,需要设置insecure-registry参数,在Https不可用的情况下,docker可以回退到http。否则可能会出现x509等类似的问题。

WARNING! Using --password via the CLI is insecure. Use --password-stdin.
 time="2020-04-02T04:09:23Z" level=info msg="Error logging in to v2 endpoint, trying next endpoint: Get https://dockerhub.wenqy.com/v2/: x509: certificate is valid for www.wenqy.com, wenqy.com, not dockerhub.wenqy.com"
 Get https://dockerhub.wenqy.com/v2/: x509: certificate is valid for www.wenqy.com, wenqy.com, not dockerhub.wenqy.com
指定node运行

因为k8s环境是别人的,只是挂了一个节点到k8s环境,k8s环境还原后,node节点label信息也丢失了,匹配不到node节点运行pod

Events:
  Type     Reason            Age                From               Message
  ----     ------            ----               ----               -------
  Warning  FailedScheduling  13m (x3 over 13m)  default-scheduler  0/3 nodes are available: 3 node(s) didn't match node selector.

k8s利用label标签来绑定到特定node运行pod

[root@wenqy .kube]# 
[root@wenqy .kube]# kubectl get nodes --show-labels
NAME              STATUS   ROLES    AGE   VERSION   LABELS
wenqy   Ready    master   49d   v1.13.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=wenqy,node-role.kubernetes.io/master=
harbornode01         Ready    <none>   49d   v1.13.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=harbornode01,vsftp=ftp
harbornode03         Ready    <none>   49d   v1.13.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=harbornode03
[root@wenqy .kube]#  
[root@wenqy .kube]# kubectl label nodes harbornode03 disktype=ssd
node/harbornode03 labeled
[root@wenqy .kube]# kubectl get nodes --show-labels
NAME              STATUS   ROLES    AGE   VERSION   LABELS
wenqy   Ready    master   49d   v1.13.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=wenqy,node-role.kubernetes.io/master=
harbornode01         Ready    <none>   49d   v1.13.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=harbornode01,vsftp=ftp
harbornode03         Ready    <none>   49d   v1.13.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/hostname=harbornode03

指定node运行pod

#deployment.yaml
spec:
  ...
  template:
    ...
    spec:
      nodeSelector:
        disktype: ssd # lable 指定node节点跑
K8s生成Secrets

CI流水线成功部署,pod启动出现ImagePullBackOff,报错详情提示需要docker login

k8s还原,secret也丢失了,创建secret,指定名称空间

[root@wenqy .kube]# kubectl create secret docker-registry harbor-secret --docker-server=dockerhub.wenqy.com --docker-username=gitlab --docker-password=Gitlab123456 -n gitlab
secret/harbor-secret created
[root@wenqy .kube]# kubectl  get secret
NAME                  TYPE                                  DATA   AGE
default-token-xxlhq   kubernetes.io/service-account-token   3      49d
harbor-secret         kubernetes.io/dockerconfigjson        1      7s
[root@wenqy .kube]# 
资源限制

k8s环境资源有限,还是借挂节点,需要对CPU、memory等资源进行限制,防止对集群的崩溃

spec:
  ...
  template:
    ...
    spec:
      ...
      containers:
      - name: springboot-hsf-test
        image: dockerhub.wenqy.com/gitlab/springboot-hsf-test:IMAGE_TAG
        imagePullPolicy: Always
        resources: #资源管理
          requests: #容器运行时,最低资源需求,也就是说最少需要多少资源容器才能正常运行
            cpu: 0.1 #CPU资源(核数),两种方式,浮点数或者是整数+m,0.1=100m,最少值为0.001核(1m)
            memory: 1024Mi #内存使用量
          limits: #资源限制
            cpu: 0.5
            memory: 2048Mi
查看logs

继续,还是出现CrashLoopBackOff,项目启动失败,查看日志

kubectl logs springboot-hsf-test-89775f989-tt65l -n gitlab

java启动报错,出现打开jar zip流报错,判断依赖jar包损坏,项目采用阿里云hsf框架jar形式构建,项目启动需要指定Pandora容器的位置,构建docker镜像时,需要从Nginx服务器中拉取Pandora sar包,域名和Nginx转发规则有被人改过,无法下载sar包,到此,发现原因,将sar包传至正确的域名指向位置

配置ingress

流水线执行成功,成功部署至k8s,直接访问内网IP健康检查地址,说明项目启动成功

[root@wenqy ~]# kubectl get pod -n gitlab -o wide
NAME                                          READY   STATUS    RESTARTS   AGE     IP           NODE        NOMINATED NODE   READINESS GATES
gitlab-runner-gitlab-runner-df75bf48d-wg644   1/1     Running   0          16h     10.96.1.55   harbornode01   <none>           <none>
springboot-hsf-test-54cd4ff877-7n8sp          1/1     Running   0          9m50s   10.96.2.56   harbornode03   <none>           <none>
[root@wenqy ~]# 
[root@wenqy ~]# curl 10.96.2.56:18081/health
ok[root@wenqy ~]# 

配置项目K8S Service类型为ClusterIP,通过集群的内部 IP 暴露服务,服务只能够在集群内部可以访问,这也是默认的 ServiceType

#deployment.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: springboot-hsf-test
spec:
  ports:
  - port: 18081
    targetPort: 18081
    name: springboot-hsf-test
  selector:
    app: springboot-hsf-test
  type: ClusterIP

利用Ingress暴露服务给外部,相当于外部负载均衡器,配置网址映射规则和路径匹配会路由到一个或多个后端服务。

[root@wenqy gitlab]# cat ingress.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: gitlab-ingress
  namespace: gitlab
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
 rules:
 - host: busi.com
   http:
     paths:
     - path: /springboot-hsf-test
       backend:
         serviceName: springboot-hsf-test
         servicePort: 18081

[root@wenqy gitlab]# kubectl apply -f ingress.yaml 

host配置为域名,不能配置为IP,会报错

[root@wenqy gitlab]# kubectl get ingress -n gitlab
NAME             HOSTS      ADDRESS   PORTS   AGE
gitlab-ingress   busi.com             80      25m
[root@wenqy gitlab]# kubectl describe ingress gitlab-ingress -n gitlab
Name:             gitlab-ingress
Namespace:        gitlab
Address:          
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host      Path  Backends
  ----      ----  --------
  busi.com  
            /springboot-hsf-test   springboot-hsf-test:18081 (<none>)
Annotations:
  kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"nginx.ingress.kubernetes.io/rewrite-target":"/"},"name":"gitlab-ingress","namespace":"gitlab"},"spec":{"rules":[{"host":"busi.com","http":{"paths":[{"backend":{"serviceName":"springboot-hsf-test","servicePort":18081},"path":"/springboot-hsf-test"}]}}]}}

  nginx.ingress.kubernetes.io/rewrite-target:  /
Events:
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  CREATE  25m   nginx-ingress-controller  Ingress gitlab/gitlab-ingress

本机配置DNS,修改/etc/hosts配置

192.168.1.142 busi.com

用域名访问健康检查URL,成功

[root@wenqy gitlab]# curl busi.com/springboot-hsf-test/health
ok[root@wenqy gitlab]#

如果有部署类似360开源的wayne这种devops部署平台或者Kubernetes 的DashBoard,可以在管理平台直接创建ingress,进行路由

运行结果

流水线最终运行效果

image-20200806140733583

Pineline执行完后,构建镜像推送到私有仓库,登录Harbor查看

image-20200814143851535

访问健康检查URL也返回正确结果,项目已经在k8s集群环境中启动成功。

我们可以自建Maven私服、镜像私服等减少网络带来的延迟进行优化等等。测试环境暂且告一段落了,这里也可以推送部署到阿里云容器服务等第三方云服务厂商

总结

Gitlab CI将应用自动化部署到K8S集群环境步骤还是简单的,但与K8S环境的对接过程还是有点曲折,基础镜像被还原,由于问题和数据没有及时的记录、备份、整理和理解,让人措手不及,凭借对当时的印象和模糊经验,可能反而让你记忆混淆,南辕北辙。英语烂,不解其意,知识储备和理解不够也是问题出现的根源。需要及时总结出现的问题和解决方案,好记性不如烂笔头,需要形成自己的知识库,一知半解的东西更需要记录和备忘,以待备查。Gitlab-Runner版本、docker版本间可能存在较大的差异,需要甄别版本特性,不要使用latest或stable版本,防止自动升级导致意外。提醒我们版本应保持向后兼容,实在重大版本无法兼容,应提供升级方案或者版本回退方案。虽然历史不是简单的重复,但是人总是踏入同一条错误的河流,不然,错误为什么无法避免,战争为何无法避免。

测试项目和资料:https://github.com/wenqy/springboot-hsf-test

参考

https://help.aliyun.com/document_detail/99943.html?spm=a2c4g.11186623.6.618.69556f171qQLGo

https://docs.docker.com/registry/insecure/#deploy-a-plain-http-registry

https://gitlab.com/gitlab-org/gitlab-runner/-/tree/master/

https://help.aliyun.com/document_detail/106968.html?spm=5176.11065259.1996646101.searchclickresult.15237c2bLJVndo 使用GitLab CI在Kubernetes服务上运行GitLab Runner并执行Pipeline

https://about.gitlab.com/releases/2019/07/31/docker-in-docker-with-docker-19-dot-03/ Update: Changes to GitLab CI/CD and Docker in Docker with Docker 19.03

https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#docker-cannot-connect-to-the-docker-daemon-at-tcpdocker2375-is-the-docker-daemon-running

https://kubernetes.io/zh/docs/concepts/services-networking/ingress/

https://kubernetes.io/zh/docs/concepts/services-networking/service/

http://360yun.org/wayne/

https://github.com/cnych/gitlab-ci-k8s-demo

https://gitee.com/linlion/gitlab-docker-k8s