与Jenkins的许多相关内容一样,要使这项工作正常进行,需要几个插件,特别是:
假设:
-
这些操作将在为执行Jenkins构建而正确配置的基于Linux的容器上运行
-
将从本地文件系统读取几个必需的“变量”——这些可能是管道中早期的构建工件,或者
ENV
变量,具体取决于设置
-
群集上已存在Kubernetes服务帐户,具有执行任务的足够权限
-
这些帐户的凭据已在Jenkins中配置
-
fleetconfig.yaml
在本地文件系统上可用,并且是一个完整的舰队配置,类似于问题中提出的配置
为了区别对待不同的车队,需要根据车队本身的名称应用一些选择标准,然后需要通过每个区域等进行循环。
为了保持这一简单,将有一个基本的
if
语句在类型之间进行选择(这很容易扩展),然后使用2个元素的循环遍历多个区域(也很容易扩展到多个)。
这是一篇完整的文章
Stage
用詹金斯的话来说,但很明显,它本身并不是完全可执行的。它尽可能接近一个已经运行了相当长一段时间的现有、经过测试的工作配置。
尽管这仍然适用于示例资源,但没有理由不能使用它来修改、创建Kubernetes中的其他资源。
stage('DeployFleets') {
agent {
node {
label 'k8s-node-linux'
}
}
steps {
script {
// assume we can read the Fleet name in from a file
FLEET_NAME = readFile("/path/to/FLEET_NAME")
// let's assume that test is one of the fleets that is being modified, not created, deal with that first
container('jenkins-worker'){
if (FLEET_NAME != 'test') {
script {
// again, assume we can read the commit from a file
def GIT_COMMIT_TAG = readFile("/path/to/GIT_COMMIT")
// create a map of 2 fictional regions with an account to use and an cluster adddress for that region
def DEPLOY_REGIONS = [
"us-east-1": ["jenkins_service_acct_use1", 'https://useast1-cluster.example.com'],
"us-east-2": ["jenkins_service_acct_use2", 'https://useast2-cluster.example.com'],
]
// this each construction is needed in order to get around https://issues.jenkins-ci.org/browse/JENKINS-49732 which prevents using a for(element in DEPLOY_REGIONS)
DEPLOY_REGIONS.each { element ->
withKubeCredentials([[credentialsId: element.value[0], serverUrl: element.value[1]]]) {
sh """
kubectl patch fleet ${FLEET_NAME} -n game-servers --type=json -p='[{"op": "replace", "path": "/spec/template/spec/template/spec/containers/0/image", "value":"registry.example.com/gameserver/${FLEET_NAME}:${GIT_COMMIT_TAG}"}]'
kubectl patch fleet ${FLEET_NAME} -n game-servers --type=json -p='[{"op": "replace", "path": "/spec/template/metadata/labels/git_commit", "value":"${GIT_COMMIT_TAG}"}]'
"""
}
}
}
} else {
// rather than patching here, create a fleet from scratch using a source YAML file as a template
script {
def GIT_COMMIT_TAG = readFile("/path/to/GIT_COMMIT")
def NUM_REPLICAS = 1
def DEPLOY_REGIONS = [
"us-east-1": ["jenkins_service_acct_use1", 'https://useast1-cluster.example.com'],
"us-east-2": ["jenkins_service_acct_use2", 'https://useast2-cluster.example.com'],
]
// see note above about each construct
DEPLOY_REGIONS.each { element ->
// assume template available on file system
def FLEET_CONFIG = readYaml file: "/path/to/fleetconfig.yaml"
FLEET_CONFIG.metadata.name = env.SOME_SANE_NAME
FLEET_CONFIG.spec.template.metadata.labels.git_commit = GIT_COMMIT_TAG
FLEET_CONFIG.spec.replicas = NUM_REPLICAS
FLEET_CONFIG.spec.template.spec.template.spec.containers[0].image = "registry.example.com/gameserver/${FLEET_NAME}:${GIT_COMMIT_TAG}"
writeYaml file: "${env.SOME_SANE_NAME}_fleet.yaml", data: FLEET_CONFIG, overwrite: true
withKubeCredentials([[credentialsId: element.value[0], serverUrl: element.value[1]]]) {
sh """
kubectl -n game-servers apply -f "${env.SOME_SANE_NAME}_fleet.yaml"
"""
}
}
}
}
}
}
}
}
考虑到环境因素,这并不特别困难
YAML
Jenkins通过插件提供给我们的操作实用程序,但找到一种从端到端都有效的方法可能是一个挑战。在中使用patch命令
kubectl
使补丁对Jenkins来说不那么“原生”,但它的便利性是值得的(例如,另一种方法是使用RESTAPI)。这个
foreach
结构看起来很奇怪,但需要避免Jenkins中长期存在的bug。