阿里云 Serverless Kubernetes 讓您無需管理和維護集群與服務器,即可快速創(chuàng)建 Kuberentes 容器應用袖瞻,并且根據(jù)應用實際使用的 CPU 和內存資源量進行按需付費锅风。使用 Serverless Kubernetes兢卵,您可以專注于設計和構建應用程序蜈首,而不是管理運行應用程序的基礎設施岗憋。它基于阿里云彈性計算基礎架構肃晚,并且完全兼容 Kuberentes API 的解決方案,充分結合了虛擬化資源帶來的安全性仔戈、彈性和 Kubernetes 生態(tài)关串。
由此定位拧廊,這種集群是很適合用來跑CI流程場景的。CI觸發(fā)時創(chuàng)建對應資源晋修,CI結束后銷毀對應的資源吧碾。目前Serverless Kubernetes集群尚在公測當中,或多或少有一些不友好的體驗飞蚓,比如:
- 不支持
Role
滤港,RoleBinding
。 - 不能自定義
CoreDNS
/Kube-DNS
配置趴拧。 - 不能使用
docker-in-docker
方式構建鏡像溅漾。 - 不支持
PersistentVolume
和PersistentVolumeClaim
。
以上提及的四點就是本次部署Runner時需要解決的需求著榴。
不支持 Role添履,RoleBinding
在觸發(fā)CI流程時,Runner會在Kubenertes集群中創(chuàng)建對應的Pod進行CI脑又,在不支持自定義 Role
暮胧,RoleBinding
的情況下,也就只有使用阿里云提供的kubeconfig
文件了问麸,將對應值粘貼到對應字段創(chuàng)建Secret
往衷,這里不再累述。最后Runner會引用到這個Secret
严卖。
apiVersion: v1
kind: Secret
metadata:
name: kubernetes-admin-cert
type: kubernetes.io/tls
data:
ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUq......
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR......
tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQp......
不能自定義CoreDNS/Kube-DNS配置
自定義CoreDNS/Kube-DNS配置是為了讓集群內部應用不通過公網(wǎng)訪問同一VPC下的其他應用直接通過內網(wǎng)即可席舍,比如Gitlab,Harbor等哮笆。
解決方式一:
阿里云官方提供的解決方案是使用privateZone来颤。但本文不介紹這種方式,為什么呢稠肘?這是一個謎一樣的問題福铅,這里不做深入探討。
解決方式二:
??注意:該方法Serverless Kubernetes集群尚不支持项阴,未來將會支持滑黔,故現(xiàn)在解決此問題只能用方式一。
讓Runner所生成的Pod使用HostAliases环揽。但是官方提供的Runner并不支持這個功能拷沸,那就直接優(yōu)化源碼吧,優(yōu)化詳情參見此次提交薯演。
不能使用docker-in-docker方式構建鏡像
解決方式:
使用kaniko進行鏡像構建预明,這里我們將官方鏡像中的可執(zhí)行文件復制到自己的CI鏡像中即可使用兑牡。
FROM gcr.io/kaniko-project/executor:v0.9.0
FROM registry.cn-hangzhou.aliyuncs.com/choerodon-tools/cibase:0.7.0
COPY --from=0 /kaniko/executor /usr/local/bin/kaniko
這是我build好可直接食用的鏡像:
registry.cn-hangzhou.aliyuncs.com/setzero/gitlab-ci-slaver:0.1.0
待友好解決的問題:
- Harbor界面不顯示鏡像信息issues,但如果原本就有該鏡像的倉庫那么是可以正常顯示的携龟。疑是Harbor版本太低的問題,目前使用的是v1.4.0衡创。
- 執(zhí)行kaniko后會出現(xiàn)
Deleting filesystem...
操作帝嗡,導致執(zhí)行完kaniko后不能再執(zhí)行其他命令,在CI中可以再分出一個stage
來規(guī)避這個問題璃氢。
不支持 PV 和 PVC
在CI時我們需要緩存一些可復用的文件哟玷,或者上一job所產生的文件下個job會用到。
解決方式一:
先部署minio一也,minio通過nfs volume方式掛載nas巢寡,然后在.gitlab-ci.yml
文件中使用cache
和artifacts
關鍵字。但本文不介紹這種方式椰苟,為什么呢抑月?這是一個謎一樣的問題,這里不做深入探討舆蝴。
相關資料:
解決方式二:
讓Runner所生成的Pod使用nfs volume方式掛載nas谦絮,但是官方提供的Runner并不支持這個功能,那就直接優(yōu)化源碼吧洁仗,優(yōu)化詳情參見此次MR层皱,故將這次CI生成的二進制文件覆蓋官方原有的就行。
FROM gitlab/gitlab-runner:alpine-v11.8.0
ADD https://gitlab.com/TimeBye/gitlab-runner/-/jobs/174588999/artifacts/raw/out/binaries/gitlab-runner-linux-amd64 /usr/bin/gitlab-ci-multi-runner
RUN chmod +x /usr/bin/gitlab-ci-multi-runner
這是我build好可直接食用的鏡像:
registry.cn-hangzhou.aliyuncs.com/setzero/gitlab-runner:alpine-v11.8.1
后記
優(yōu)化Runner后的配置示例
concurrent = 3
check_interval = 0
[[runners]]
name = "runner"
url = "https://gitlab.com/"
token = "2b388a2636d35b9d141348e972706b"
executor = "kubernetes"
output_limit = 51200
environment = ["CHART_REPOSITORY=http://chart.com",
"SONAR_URL=http://sonarqube.com"]
[runners.kubernetes]
host = "https://abcde.serverless-1.kubernetes.cn-shanghai.aliyuncs.com:6443"
cert_file = "/etc/gitlab-runner/tls.crt"
key_file = "/etc/gitlab-runner/tls.crt"
ca_file = "/etc/gitlab-runner/ca.crt"
namespace = "default"
pull_policy = "always"
cpu_limit = "2"
cpu_request = "2"
memory_limit = "4Gi"
memory_request = "4Gi"
service_cpu_limit = "1"
service_cpu_request = "1"
service_memory_limit = "2Gi"
service_memory_request = "2Gi"
helper_cpu_limit = "250m"
helper_cpu_request = "250m"
helper_memory_limit = "512Mi"
helper_memory_request = "512Mi"
helper_image = "gitlab/gitlab-runner-helper:x86_64-3fff1dcf"
[runners.kubernetes.pod_annotations]
# "k8s.aliyun.com/enable-eip" = "true"
[runners.kubernetes.host_aliases]
"127.0.0.1" = [ "foo.local", "bar.local" ]
"127.0.0.2" = [ "oof.local", "rab.local" ]
[runners.kubernetes.volumes]
[[runners.kubernetes.volumes.nfs]]
name = "runner-cache"
mount_path = "/cache"
server = "abcde-map64.cn-shanghai.nas.aliyuncs.com"
nfs_path = "/runner/cache-pv"
[[runners.kubernetes.volumes.nfs]]
name = "runner-maven"
mount_path = "/root/.m2"
server = "abcde-map64.cn-shanghai.nas.aliyuncs.com"
nfs_path = "/runner/maven-pv"
[[runners.kubernetes.volumes.secret]]
name = "docker-registry-secret"
mount_path = "/root/.docker"
read_only = false
[runners.kubernetes.volumes.secret.items]
"config.json" = "config.json"