代码之家  ›  专栏  ›  技术社区  ›  Adam Comerford

作为Jenkins构建过程的一部分,如何跨多个集群创建和修改Kubernetes资源?

  •  0
  • Adam Comerford  · 技术社区  · 5 年前

    具体来说,有几个资源(当前定义为 YAML )在现有的Kubernetes集群中,我想作为构建过程的一部分进行修改,还有一些我想从头开始创建的集群。在每种情况下,我都希望在多个区域中这样做,以保持所有区域的同步。

    所涉及的资源是 Agones fleets ,如下所示(实际值已删除,但具有代表性):

    apiVersion: agones.dev/v1
    kind: Fleet
    metadata:
      annotations:
        agones.dev/sdk-version: 1.11.0
      name: test
      namespace: game-servers
      resourceVersion: "12324578"
      selfLink: /apis/agones.dev/v1/namespaces/game-servers/fleets/test
    spec:
      replicas: 1
      scheduling: Packed
      strategy:
        rollingUpdate:
          maxSurge: 25%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          creationTimestamp: null
          labels:
            branch: test
            git_commit: 1b12371827fdea31231230901876ffe
        spec:
          health:
            disabled: false
            failureThreshold: 5
            initialDelaySeconds: 10
            periodSeconds: 5
          ports:
          - containerPort: 1234
            name: default
            portPolicy: Dynamic
            protocol: UDP
          sdkServer:
            logLevel: Info
          template:
            metadata:
              creationTimestamp: null
              labels:
                role: game-servers
            spec:
              containers:
              - image: registry.example.com/gameserver:1b12371827fdea31231230901876ffe
                name: agones
                resources:
                  limits:
                    cpu: 500m
                    memory: 512m
                  requests:
                    cpu: 100m
                    memory: 256Mi
              nodeSelector:
                role: game-servers
    

    如果存在 fleet ,我想注射最新的 git commit 输入标签,以及要使用的图像(假设它将在注册表上进行适当标记)。

    如果没有现有的 舰队 ,对于某些值,我希望从头开始循环并创建新的车队,具有与上述类似的特征。我尝试了几种不同的方法,但都失败了——从集群上的权限问题到尝试直接使用时出现的奇怪错误 for Jenkins/Groovy中的循环。

    1 回复  |  直到 5 年前
        1
  •  0
  •   Adam Comerford    5 年前

    与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。

    推荐文章