k8s之容器迁移 [jenkins为例]

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了k8s之容器迁移 [jenkins为例]相关的知识,希望对你有一定的参考价值。

参考技术A 一、数据备份
1.找到需要迁移的容器名称

2.找到迁移容器的数据目录

二、修改yaml配置文件

3.svc.yaml 主要修改点:namespace

4.ingress 的修改点:namespace、host

三、创建一个新的容器
1.创建并查看状态

四、登录到容器中清空数据文件

五、拷贝备份的数据文件到容器中

六、重启容器

七、根据实际情况修改容器中目录权限等问题

在 Jenkins 中使用 docker Container 链接

【中文标题】在 Jenkins 中使用 docker Container 链接【英文标题】:Using docker Container links in Jenkins 【发布时间】:2021-06-27 18:42:25 【问题描述】:

我正在尝试运行适用于数据库迁移脚本的 CI 系统。因此,这可能会阻止我们运行由于语法错误而在迁移时无法运行的 sql 脚本。对于我们的本地设置,我们使用 docker-compose 并一次运行多个容器。不幸的是,这不是我们在 Jenkins 管道中的选择

我使用以下策略创建了这个 Jenkinsfile。

    postgres 容器使用或多或少的默认参数运行 另一个 postgres 容器链接到第一个容器,仅使用 pg_isready 命令行等待数据库准备好进行连接 使用 flyway 容器针对第 1 步中的数据库设置运行数据库迁移。最终计划使用 Web 应用程序运行 E2E 测试

我的实现基于documentation here(运行 docker sidecar)。但是,这不起作用,第一个容器(步骤 1)似乎正在停止。我添加了一些额外的调试(try catch)来查看这个容器的日志

我的 Jenkinsfile

的内容
def docker_repository = '<CUSTOM-REGISTRY>'
def docker_user_credentialsId = '<DOCKER-USER>'

pipeline 
   agent  label 'docker && linux && nonprod' 

options 
    buildDiscarder(logRotator(daysToKeepStr: '90', numToKeepStr: '20', artifactDaysToKeepStr: '90', artifactNumToKeepStr: '20'))
    timeout(time: 20, unit: 'MINUTES') 

stages 
    stage('build & test') 
        environment 
            POSTGRES_DB = 'mydb'
            POSTGRES_USER = 'postgres'
            POSTGRES_PASSWORD = 'postgres'                
            FLYWAY_URL = 'jdbc:postgresql://localhost:5432/mydb'
            // FLYWAY_URL = 'jdbc:postgresql://db-container:5432/mydb'
            FLYWAY_USER = 'postgres'
            FLYWAY_PASSWORD = 'postgres'
        
        steps 
            checkout scm
            withCredentials([ usernamePassword(credentialsId: docker_user_credentialsId, passwordVariable: 'ARTIFACTORY_API_TOKEN', usernameVariable: 'ARTIFACTORY_API_USER'),])                                 
            script 
                docker.withRegistry(docker_repository, docker_user_credentialsId) 
                    docker.image('<REGISTRY>/postgres').withRun("--name=db-container -e POSTGRES_PASSWORD=postgres")  c ->
                        try 
                            docker.image('<REGISTRY>/postgres').inside("--link $c.id:db")                                 
                                sh '''
                                    while ! pg_isready -h db -p 5432
                                    do
                                         echo $
                                         echo "$(date) - waiting for database to start"
                                         sleep 10
                                    done
                                '''
                            
                            docker.image('<REGISTRY>/flyway/flyway').inside("--link $c.id:db") 
                                sh 'info'
                                // sh 'migrate'
                            
                         catch (exc) 
                            sh "docker logs $c.id"
                            throw exc
                        
                    
                
                            
        
    

post 
    always 
        cleanWs()
    

第 2 步被暂时删除以获取此日志,因为第 2 步在循环中等待并且 docker 日志

+ docker logs 9d9e8699b57430e288520c485c8333a0261f9283f749aec2832cfb0e5f19ef9e
 The files belonging to this database system will be owned by user "postgres".
 This user must also own the server process.
 The database cluster will be initialized with locale "en_US.utf8".
 The default database encoding has accordingly been set to "UTF8".
 The default text search configuration will be set to "english".

 Data page checksums are disabled.
 fixing permissions on existing directory /var/lib/postgresql/data ... ok
  creating subdirectories ... ok
  selecting dynamic shared memory implementation ... posix
  selecting default max_connections ... 100
  selecting default shared_buffers ... 128MB 
  selecting default time zone ... Etc/UTC
  creating configuration files ... ok
  running bootstrap script ... ok
  performing post-bootstrap initialization ... ok
  syncing data to disk ... ok
  Success. You can now start the database server using:
  pg_ctl -D /var/lib/postgresql/data -l logfile start
  initdb: warning: enabling "trust" authentication for local connections
  You can change this by editing pg_hba.conf or using the option -A, or
   --auth-local and --auth-host, the next time you run initdb.
  waiting for server to start....2021-03-31 15:21:29.923 UTC [48] LOG:  starting PostgreSQL 13.2 
  (Debian 13.2-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
  2021-03-31 15:21:29.929 UTC [48] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
  2021-03-31 15:21:29.946 UTC [49] LOG:  database system was shut down at 2021-03-31 15:21:29 UTC
  2021-03-31 15:21:29.951 UTC [48] LOG:  database system is ready to accept connections
  done

  server started

   /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
   2021-03-31 15:21:30.062 UTC [48] LOG:  received fast shutdown request
   waiting for server to shut down....2021-03-31 15:21:30.064 UTC [48] LOG:  aborting any active transactions

   2021-03-31 15:21:30.065 UTC [48] LOG:  background worker "logical replication launcher" (PID 55) 
     exited with exit code 1

    2021-03-31 15:21:30.071 UTC [50] LOG:  shutting down
    2021-03-31 15:21:30.099 UTC [48] LOG:  database system is shut down
    done

    server stopped
    PostgreSQL init process complete; ready for start up.

    2021-03-31 15:21:30.188 UTC [1] LOG:  starting PostgreSQL 13.2 (Debian 13.2-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit

    2021-03-31 15:21:30.190 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
    2021-03-31 15:21:30.190 UTC [1] LOG:  listening on IPv6 address "::", port 5432
    2021-03-31 15:21:30.196 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
    2021-03-31 15:21:30.203 UTC [67] LOG:  database system was shut down at 2021-03-31 15:21:30 UTC
    2021-03-31 15:21:30.208 UTC [1] LOG:  database system is ready to accept connections

postgres 和 flyway 版本在这里不应该发挥重要作用,但从日志中可以看出,默认标签提供的 Postgres 版本是 13.2。

这里有什么建议吗?

【问题讨论】:

【参考方案1】:

假设您使用的是official postgres docker image,一个可能的根本原因是容器的entrypoint 的脚本失败。

来自图像的 Docker 页面:

警告:/docker-entrypoint-initdb.d 中的脚本仅在使用空数据目录启动容器时运行; [...] 一个常见问题是如果您的 /docker-entrypoint-initdb.d 脚本之一失败(这将导致入口点脚本退出)并且您的协调器使用已初始化的数据目录重新启动容器,它将不会继续使用您的脚本

解决方案

假设入口点进程确实失败了(可能是因为它看到了一个不属于自己的数据库,并且由entrypoint 设计来覆盖它,因为它链接到另一个 postgres 容器),你可以通过设置自己的来克服这个问题entrypointcmd,从而防止图像尝试创建一个您无论如何都不会使用的数据库,即:

FROM postgres

#Switch back to default entrypoint
ENTRYPOINT ["/bin/sh"]

#Let the container start and do nothing until the pipeline kicks in
CMD ["-c","sleep infinity"]

根据上面的 Dockerfile 创建一个新的镜像,推送它,并在 Jenkins 的管道中定义它而不是当前的(仅适用于 sidecar)。然后你应该有一个稳定的容器,链接到实际的数据库容器,管道可以跳转到。

最后,关于在sidecar中启动的命令,我建议使用localhost而不是db作为目标主机,在命令问题的pg_isready -h db -p 5432上,结果为:pg_isready -h localhost -p 5432

【讨论】:

不幸的是,这也不起作用。第一个 postgres 容器在 sidecar 连接到它之前仍在停止【参考方案2】:

经过一些试验和错误,这对我们有用。虽然它与初始设置非常相似,但关键变化在于选择使用insidewithRun。最终的 Jenkinsfile 如下所示。

// credentials
def docker_user_credentialsId = '<DOCKER-USER>'
def docker_repository = '<CUSTOM-REGISTRY>'

// docker images
def pg = docker.image('postgres:12-alpine')
def flyway = docker.image('flyway/flyway:7-alpine')

pipeline 
    agent none

    options 
        buildDiscarder(logRotator(daysToKeepStr: '90', numToKeepStr: '20', artifactDaysToKeepStr: '90', artifactNumToKeepStr: '20'))
        timeout(time: 120, unit: 'MINUTES') 
    

    stages 
        stage('db migration test') 
            agent  
                label 'docker && linux'
            

            environment 
                PGHOST = 'db'
                PGPORT = '5432'
                PGDATABASE = 'postgres'
                PGUSER = 'postgres'
                PGPASSWORD = 'postgres'
            

            steps 
                script 
                    docker.withRegistry(docker_repository, docker_user_credentialsId) 
                        def db = pg.withRun(
                            "-v $WORKSPACE/docker/init-user-db.sh:/docker-entrypoint-initdb.d/init-user-db.sh -e POSTGRES_USER=$env.PGUSER -e POSTGRES_PASSWORD=$env.PGPASSWORD -e POSTGRES_DB=$env.PGDATABASE"
                        )  db ->
                            pg.inside("--link $db.id:$env.PGHOST")                                 
                                sh '''
                                    echo "$(date) - waiting for database to start"
                                    while ! pg_isready
                                    do
                                        sleep 10
                                    done
                                '''
                            
                            flyway.withRun("-e FLYWAY_LOCATIONS=filesystem:/tmp/database/server,filesystem:/tmp/database/local -e FLYWAY_URL=jdbc:postgresql://$PGHOST:$env.PGPORT/$env.PGDATABASE -e FLYWAY_USER=$env.PGUSER -e FLYWAY_PASSWORD=$env.PGPASSWORD -v $WORKSPACE/database/local:/tmp/database/local -v $WORKSPACE/database/server:/tmp/database/server --link $db.id:db", "migrate")  f ->
                                sh "docker logs -f $f.id"
                                def output = sh script: "docker inspect $f.id --format='.State.ExitCode'", returnStdout: true
                                sh "exit $output"
                            
                        
                    
                
            
        
    
 

【讨论】:

以上是关于k8s之容器迁移 [jenkins为例]的主要内容,如果未能解决你的问题,请参考以下文章

k8s中mongo容器数据迁移之内存小坑

linux12Devops -->10Jenkins流水线容器化+Harbor私有仓库

k8s实战课程笔记

docker+jenkins

使用k8s容器化布署jenkins

更改Jenkins的主目录