欢迎光临
我们一直在努力

KubernetesCI/CD实践

12-Kubernetes-CI/CD实践

  • Docker与Kubernetes基础
  • 基于Kubectl CI/CD实践
  • 基于Helm CI/CD实践
  • 基于ArgoCD 实践
  • 01-Docker基础

    02-Kubernetes基础

    03-K8SCI-基本配置

    04-K8SCI-添加构建镜像步骤

    05-K8SCD-手动部署应用

    06-K8SCD-自动化部署应用

    07-K8SCD-添加应用回滚

    08-K8SCD-GitOps流水线优化

    09-HELM-手动发布Chart

    10-HELM-CI流水线配置

    11-HELM-添加上传Chart步骤

    12-HELM-CD发布Chart

    13-ArgoCD-发布manifest

    14-ArgoCD-发布Helm Chart

    必修

    一、Kubectl 发布流水线

    我用夸克网盘给你分享了 链接:https://pan.quark.cn/s/ce015bdb3f78

    CI流水线:

    • 下载代码
    • 构建单元测试
    • 代码扫描
    • 构建镜像
    • 更新发布文件

    CD流水线:

    • 输入版本,从git下载部署文件;
    • 使用kubectl发布;
    • 使用kubectl回滚;

    1.1 CI流水线

    此次项目我们使用了jenkins共享库来完成最佳实践。  jenkinsfile第一行就是要导入我们的共享库。@Library("devops5") _

    我们在共享库中编写了一些特定的处理类。在Jenkinsfile中导入这些类

    @Library("devops5") _

    //Lib
    def build = new org.devops.Build()
    def myTool = new org.devops.Tools()
    def sonar = new org.devops.Sonar()
    def art = new org.devops.Artifact()
    def gitlabTool = new org.devops.Gitlab()

    有些参数需要用户在Jenkins页面构建前填写的:

    • 用户需要在jenkins作业中配置好要构建的代码仓库的地址。(一般不需要改, 可以使用选项参数)
    • 每次构建需要输入此代码库要构建的代码分支。 (字符串参数)
    • 选择本次构建要使用的构建工具(选项参数maven、ant、gradle、npm)

    流水线运行

    此条流水线运行在标签为"build"的节点上, 跳过默认的checkout步骤。

    agent { label "build01"}
    options{
    skipDefaultCheckout true
    }

    阶段与节点

    下载代码

    stage("CheckOut"){
    steps{
    script{
    //下载代码
    currentBuild.description = "branch: ${env.branchName}"
    myTool.GetCode("${env.branchName}", "${env.srcUrl}")
    }
    }
    }

    构建代码和单元测试

    stage("Build"){
    steps{
    script{
    // 构建阶段
    build.Build()
    }
    }
    }

    stage("UnitTest"){
    when {
    environment name: 'skipUnitTest' , value: 'false'
    }
    steps{
    script{
    // 单元测试
    build.UnitTest()
    }
    }
    }

    代码扫描

    stage("CodeScan"){
    steps{
    script{
    // 代码扫描
    env.commitID = myTool.GetCommitID()
    sonar.CodeScan()
    }
    }
    }

    构建上传镜像

    • 需要将docker镜像仓库的用户认证信息,以用户名和密码类型的凭据在Jenkins中存储;
    • docker仓库:192.168.1.200:8088/${repoName}/${projectName};
    • 镜像标签: ${env.branchName} 即 版本分支名称;
    • 步骤: 登录镜像仓库> 构建镜像 > 上传镜像 > 删除本地镜像(节省空间);

    stage("DockerImage"){
    steps{
    script{
    //生成Docker镜像
    repoName = "${JOB_NAME}".split("/")[0] //devops5
    projectName = "${JOB_NAME}".split("/")[-1].split("_")[0] //devops5-npm-web
    env.registry = "192.168.1.200:8088" //harbor
    env.imageName = "${env.registry}/${repoName}/${projectName}:${env.branchName}"

    withCredentials([usernamePassword(credentialsId: 'd12269dd-2439-4d3e-8917-915e8404e97a',
    passwordVariable: 'DOCKER_PASSWD',
    usernameVariable: 'DOCKER_USER')]) {
    sh """
    # 构建镜像
    docker build -t ${env.imageName} .

    #登录镜像仓库
    docker login -u ${DOCKER_USER} -p ${DOCKER_PASSWD} ${env.registry}

    # 上传镜像
    docker push ${env.imageName}

    # 删除镜像
    sleep 2
    docker rmi ${env.imageName}

    """
    }
    }
    }
    }

    【GitOps最重要的一个特性: 自动更新部署文件】

    更新生成版本文件

    • 步骤: 拿到 env仓库中的deployments.yaml模板文件, 然后替换内容,更新到版本库。

    更新对象:

    __RELEASE_VERSION__(镜像TAG)

    stage("UpdateEnvFile"){
    steps{
    script {
    // 更新部署文件

    //下载发布文件
    projectId = 12
    filePath = "devops5-npm-web-deployment.yaml"
    branchName = "main"
    fileData = gitlabTool.GetRepoFile(projectId,filePath, branchName )
    sh "rm -fr ${filePath}"
    writeFile file: filePath , text: fileData
    env.deployFile = filePath
    sh "sed -i 's#__RELEASE_VERSION__#${env.branchName}#g' ${env.deployFile} "
    sh "ls -l ; cat ${filePath}"

    //创建/更新发布文件
    newYaml = sh returnStdout: true, script: "cat ${env.deployFile}"
    println(newYaml)
    //更新gitlab文件内容
    base64Content = newYaml.bytes.encodeBase64().toString()

    env.groupName = "${JOB_NAME}".split("/")[0] //devops5
    env.projectName = "${JOB_NAME}".split("/")[-1].split("_")[0] //devops5-npm-web

    // 会有并行问题,同时更新报错
    try {
    gitlabTool.UpdateRepoFile(projectId,"${env.projectName}%2f${env.branchName}.yaml",base64Content, "main")
    } catch(e){
    gitlabTool.CreateRepoFile(projectId,"${env.projectName}%2f${env.branchName}.yaml",base64Content, "main")
    }
    }
    }
    }

    更新后的版本文件

    1.2 CD流水线

    jenkinsfile第一行就是要导入我们的共享库。@Library("devops5@main") _

    我们在共享库中编写了一些特定的处理类:

    • src/org/devops/Gitlab.groovy         版本控制系统接口操作工具

    在Jenkinsfile中导入这些类

    @Library("devops5") _

    //Lib
    def gitlabTool = new org.devops.Gitlab()

    只有一个参数需要用户在Jenkins页面构建前填写的:

    • 用户在页面输入发布版本: branchName, 例如 RELEASE-1.1.0

    我们在流水线中定义一些全局变量:

    • 通过作业名称拿到业务简称(devops03)
    • 通过作业名称拿到应用名称(devops03-devops-ui)

    env.groupName = "${JOB_NAME}".split("/")[0]
    env.projectName = "${JOB_NAME}".split("/")[-1].split("_")[0]

    流水线运行

    此条流水线运行在标签为"k8s"的节点上, 跳过默认的checkout步骤。(课程中是在k8s的master节点启动了一个jnlp的Jenkins Slave)

    agent { label "build01"}
    options{
    skipDefaultCheckout true
    }

    阶段与节点

    获取发布文件

    • 下载CI流水线生成的版本文件到本地;

    stage("GetDeployFile"){
    steps{
    script{
    //下载发布文件
    projectId = 12
    env.deployFile = "${env.releaseVersion}.yaml"
    filePath = "${env.projectName}%2f${env.deployFile}"

    branchName = "main"
    fileData = gitlabTool.GetRepoFile(projectId,filePath, branchName )
    sh "rm -fr ${env.deployFile}"
    writeFile file: env.deployFile , text: fileData
    sh "ls -l ; cat ${env.deployFile}"

    //sh "sed -i 's#__RELEASE_VERSION__#${env.releaseVersion}#g' ${env.deployFile} "
    //sh "ls -l ; cat ${filePath}"
    }
    }
    }

    应用发布

    • 创建名称空间,更新应用

    stage("DeployAPP"){
    steps{
    script{
    env.namespace = "${env.groupName}"

    sh """
    ## 发布应用
    kubectl apply -f ${env.deployFile} -n ${env.namespace}

    """

    // 获取应用状态
    5.times{
    sh "sleep 2; kubectl -n ${env.namespace} get pod | grep ${env.projectName}"
    }
    }
    }
    }

    回滚步骤(交互)

    • 给用户提供两个选项 :yes执行回滚,no跳过;
    • 使用kubectl rollout undo 默认回滚上个版本;

    stage("RollOut"){
    input {
    message "是否进行回滚"
    ok "提交"
    submitter ""
    parameters {
    choice(choices: ['yes', 'no'], name: 'opts')
    }
    }

    steps{
    script{

    switch("${opts}") {
    case "yes":
    sh "kubectl rollout undo deployment/${env.projectName} -n ${env.namespace} "
    break

    case "no":
    break
    }
    }
    }
    }

    二、Helm CI/CD流水线

    我用夸克网盘 链接:https://pan.quark.cn/s/c19bbf182e2c

    基于Helm CI/CD

    2.1 CI流水线

    此部分可以参考上面“基于kubectl发布”阶段, 相同的阶段代码。

    阶段与节点

    此部分可以参考上面“基于kubectl发布”阶段, 相同的阶段代码。

    更新生成版本文件

    此处的版本文件不再是一个文件了, 而是一个chart包。如何生成:

    helm create "${appName}"
    cd "${appName}"
    git push 到版本库

    • 步骤: 拿到 helm chart仓库中的values.yaml模板文件, 然后替换镜像,更新到版本库。
    • 更新对象:
      • image.tag (镜像标签)

    stage("UpdateEnvFile"){
    steps{
    script {
    // 更新部署文件
    env.groupName = "${JOB_NAME}".split("/")[0] //devops5
    env.projectName = "${JOB_NAME}".split("/")[-1].split("_")[0] //devops5-npm-web

    //下载发布文件
    projectId = 13
    env.deployFile = "values.yaml"
    filePath = "${env.projectName}%2f${env.deployFile}"
    branchName = "master"
    fileData = gitlabTool.GetRepoFile(projectId,filePath, branchName )
    sh "rm -fr ${env.deployFile}"

    yamlData = readYaml text: fileData
    yamlData.image.tag = "${env.branchName}"

    writeYaml file: "${env.deployFile}" , data: yamlData

    //创建/更新发布文件
    newYaml = sh returnStdout: true, script: "cat ${env.deployFile}"
    println(newYaml)
    //更新gitlab文件内容
    base64Content = newYaml.bytes.encodeBase64().toString()

    // 会有并行问题,同时更新报错
    try {
    gitlabTool.UpdateRepoFile(projectId,"${env.projectName}%2fvalues.yaml",base64Content, "master")
    } catch(e){
    gitlabTool.CreateRepoFile(projectId,"${env.projectName}%2fvalues.yaml",base64Content, "master")
    }
    }
    }
    }

    Helm 打包阶段:

    stage("HelmPackage"){
    steps{
    script{
    // helm pakcage & push harbor

    //download helm git repo
    myTool.GetCode("master", "http://192.168.1.200:8076/devops5/devops5-helm-charts.git")

    //helm package
    chartVersion = "${env.branchName}".split("-")[-1]
    sh "helm package ${env.projectName} –version ${chartVersion}"

    //push package
    sh "helm cm-push ${env.projectName}-${chartVersion}.tgz harborrepo"

    }
    }
    }

    2.2 CD流水线设计与实现

    下载chart仓库

    stage("GetHelmChart"){
    steps{
    script{
    //下载helm chart
    env.chartVersion = "${env.releaseVersion}".split("-")[-1]
    sh """
    helm repo update
    helm pull harborrepo/${env.projectName} –version ${env.chartVersion}
    """
    }
    }
    }

    helm发布应用

    • 创建名称空间,打包,获取REVISION历史(便于回滚)

    stage("DeployAPP"){
    steps{
    script{
    env.namespace = "${env.groupName}"

    sh """
    ## 发布应用
    helm upgrade –install –create-namespace "${env.projectName}" ./"${env.projectName}"-${env.chartVersion}.tgz -n ${env.namespace}
    helm history "${env.projectName}" -n ${env.namespace}
    """

    // 获取应用状态
    5.times{
    sh "sleep 2; kubectl -n ${env.namespace} get pod | grep ${env.projectName}"
    }

    //收集history
    env.revision = sh returnStdout: true,
    script: """helm history ${env.projectName} -n ${env.namespace} | grep -v 'REVISION' | awk '{print \\$1}' """
    println("${env.revision}")
    println("${env.revision.split('\\n').toString()}")
    env.REVISION = "${env.revision.split('\\n').toString()}"
    println("${env.REVISION}")
    }
    }
    }

    回滚步骤

    • 交互式用户选择REVISION, 触发Helm rollback;

    stage("CheckHealth"){
    steps{
    script{
    result = sh returnStdout: true, script: """ curl "http://${env.domainName}/health" """
    if (result == "ok\\n"){
    println("success!")
    }
    }
    }
    }

    stage("RollOut"){
    input {
    message "是否进行回滚"
    ok "提交"
    submitter ""
    parameters {
    choice(choices: ['yes', 'no'], name: 'opts')
    }
    }

    steps{
    script{

    switch("${opts}") {
    case "yes":
    def result = input message: "选择回滚版本?",
    parameters: [choice(choices: env.REVISION, name: 'rversion')]

    println("${result}")
    sh "helm rollback ${env.projectName} ${result} -n ${env.namespace} "
    break

    case "no":
    break
    }
    }
    }
    }

    三、ArgoCD实践

    安装部署

    ## apply
    kubectl create namespace argocd
    kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

    ## 查看部署状态
    [root@master ~]# kubectl get pod -n argocd
    NAME READY STATUS RESTARTS AGE
    argocd-application-controller-0 1/1 Running 0 64m
    argocd-dex-server-77dd4b844b-tkpxh 1/1 Running 0 64m
    argocd-redis-74d8c6db65-b9dl9 1/1 Running 0 64m
    argocd-repo-server-5674b858d5-255cc 1/1 Running 0 64m
    argocd-server-59964ffc7d-szg4c 1/1 Running 0 64m

    ## 使用nodePort
    kubectl patch svc argocd-server -p '{"spec": {"type": "NodePort"}}' -n argocd

    ## 默认情况下 admin 帐号的初始密码是自动生成的,会以明文的形式存储在 Argo CD 安装的命名空间中名为 password 的 Secret 对象下的 argocd-initial-admin-secret 字段下,我们可以用下面的命令来获取

    kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo

    连接K8s集群

    Argo CD 支持部署应用到多集群,所以如果你要将应用部署到外部集群的时候,需要先将外部集群的认证信息注册到 Argo CD 中,如果是在内部部署(运行 Argo CD 的同一个集群,默认不需要配置),应该使用 https://kubernetes.default.svc 作为应用的 K8S APIServer 地址。

    ## 下载客户端工具
    curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
    chmod +x /usr/local/bin/argocd

    ## 添加集群
    [root@master ~]# argocd-linux-amd64 login 192.168.1.230:30248
    WARNING: server is not configured with TLS. Proceed (y/n)? y
    Username: admin
    Password:
    'admin:login' logged in successfully
    Context '192.168.1.230:30248' updated

    ## 列出当前 kubeconfig 中的所有集群上下文:
    [root@master ~]# kubectl config get-contexts -o name
    kubernetes-admin@kubernetes

    ## 注册集群
    [root@master ~]# argocd-linux-amd64 cluster add kubernetes-admin@kubernetes
    WARNING: This will create a service account `argocd-manager` on the cluster referenced by context `kubernetes-admin@kubernetes` with full cluster level admin privileges. Do you want to continue [y/N]? y
    INFO[0002] ServiceAccount "argocd-manager" already exists in namespace "kube-system"
    INFO[0002] ClusterRole "argocd-manager-role" updated
    INFO[0002] ClusterRoleBinding "argocd-manager-role-binding" updated
    Cluster 'https://192.168.10.100:6443' added

    添加Git Repo

    创建APP

    四、发布策略(扩展)

    滚动更新

    apiVersion: apps/v1beta2
    kind: Deployment
    metadata:
    name: nginx
    labels:
    app: nginx
    spec:
    replicas: 1
    selector:
    matchLabels:
    app: nginx
    strategy:
    type: RollingUpdate
    rollingUpdate:
    maxUnavailable: 1 ## 最多1个pod处于不可工作状态
    maxSurge: 2 ## 升级时可以比预期多出2个pod
    minReadySeconds: 5 ## 容器启动后等待5秒

    蓝绿发布

    创建新的部署,然后修改service的标签来将流量指向新的部署。

    [root@master b-g]# kubectl get pod
    NAME READY STATUS RESTARTS AGE
    nginxapp-1.19-bdb8dc6c4-2jfsw 1/1 Running 0 12m
    nginxapp-1.19-bdb8dc6c4-79qrh 1/1 Running 0 12m
    nginxapp-1.19-bdb8dc6c4-hbwkx 1/1 Running 0 12m
    nginxapp-1.20-786464458-4zh5t 1/1 Running 0 91s
    nginxapp-1.20-786464458-5bfwq 1/1 Running 0 91s
    nginxapp-1.20-786464458-fwgxb 1/1 Running 0 91s

    v1.1.4-blue.yaml

    kind: Deployment
    apiVersion: apps/v1
    metadata:
    labels:
    k8s-app: devops4-ops-service
    version: "1.1.4"
    name: devops4-ops-service-blue
    namespace: devops4
    spec:
    replicas: 3
    revisionHistoryLimit: 10
    selector:
    matchLabels:
    k8s-app: devops4-ops-service
    version: "1.1.4"
    template:
    metadata:
    labels:
    k8s-app: devops4-ops-service
    version: "1.1.4"
    namespace: devops4
    name: devops4-ops-service
    spec:
    containers:
    – name: devops4-ops-service
    image: 192.168.1.200:8088/devops4/devops4-ops-service:RELEASE-1.1.4-c6b176ad
    imagePullPolicy: IfNotPresent
    ports:
    – containerPort: 8080
    name: web
    protocol: TCP
    serviceAccountName: devops4-ops-service
    —
    apiVersion: v1
    kind: ServiceAccount
    metadata:
    labels:
    k8s-app: devops4-ops-service
    name: devops4-ops-service

    service.yaml

    apiVersion: v1
    kind: Namespace
    metadata:
    name: devops4
    —
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: example-ingress
    namespace: devops4
    spec:
    rules:
    – host: devops4.ops.service
    http:
    paths:
    – pathType: Prefix
    path: "/"
    backend:
    service:
    name: devops4-ops-service
    port:
    number: 8080
    —
    kind: Service
    apiVersion: v1
    metadata:
    labels:
    k8s-app: devops4-ops-service
    name: devops4-ops-service
    namespace: devops4
    spec:
    type: ClusterIP
    ports:
    – name: web
    port: 8080
    targetPort: 8080
    selector:
    k8s-app: devops4-ops-service
    version: "1.1.4"

    v1.1.5-green.yaml

    kind: Deployment
    apiVersion: apps/v1
    metadata:
    labels:
    k8s-app: devops4-ops-service
    version: "1.1.5"
    name: devops4-ops-service-green
    namespace: devops4
    spec:
    replicas: 3
    revisionHistoryLimit: 10
    selector:
    matchLabels:
    k8s-app: devops4-ops-service
    version: "1.1.5"
    template:
    metadata:
    labels:
    k8s-app: devops4-ops-service
    version: "1.1.5"
    namespace: devops4
    name: devops4-ops-service
    spec:
    containers:
    – name: devops4-ops-service
    image: 192.168.1.200:8088/devops4/devops4-ops-service:RELEASE-1.1.5-bc630338
    imagePullPolicy: IfNotPresent
    ports:
    – containerPort: 8080
    name: web
    protocol: TCP
    serviceAccountName: devops4-ops-service
    —
    apiVersion: v1
    kind: ServiceAccount
    metadata:
    labels:
    k8s-app: devops4-ops-service
    name: devops4-ops-service

    启动busybox容器调试(废弃)

    kubectl run –restart=Never -it –image \\
    infoblox/dnstools dnstools

    修改流量(service)

    kubectl patch svc devops4-ops-service -p '{"spec":{"selector":{"version": "1.1.5"}}}' -n devops4

    测试验证

    curl http://devops4.ops.service/hello

    灰度发布

    https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#canary

    1.1.4

    apiVersion: v1
    kind: Namespace
    metadata:
    name: devops4
    —
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: example-ingress-1-4
    namespace: devops4
    spec:
    rules:
    – host: devops4.ops.service
    http:
    paths:
    – pathType: Prefix
    path: "/"
    backend:
    service:
    name: devops4-ops-service-1-4
    port:
    number: 8080
    —
    kind: Deployment
    apiVersion: apps/v1
    metadata:
    labels:
    k8s-app: devops4-ops-service
    name: devops4-ops-service-1-4
    namespace: devops4
    spec:
    replicas: 1
    revisionHistoryLimit: 10
    selector:
    matchLabels:
    k8s-app: devops4-ops-service
    template:
    metadata:
    labels:
    k8s-app: devops4-ops-service
    namespace: devops4
    name: devops4-ops-service
    spec:
    containers:
    – name: devops4-ops-service
    image: 192.168.1.200:8088/devops4/devops4-ops-service:RELEASE-1.1.4-c6b176ad
    imagePullPolicy: IfNotPresent
    ports:
    – containerPort: 8080
    name: web
    protocol: TCP
    serviceAccountName: devops4-ops-service
    —
    apiVersion: v1
    kind: ServiceAccount
    metadata:
    labels:
    k8s-app: devops4-ops-service
    name: devops4-ops-service
    namespace: devops4
    —
    kind: Service
    apiVersion: v1
    metadata:
    labels:
    k8s-app: devops4-ops-service
    name: devops4-ops-service-1-4
    namespace: devops4
    spec:
    type: ClusterIP
    ports:
    – name: web
    port: 8080
    targetPort: 8080
    selector:
    k8s-app: devops4-ops-service

    1.1.5

    apiVersion: v1
    kind: Namespace
    metadata:
    name: devops5
    —
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: example-ingress
    namespace: devops5
    annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-cookie: "from"
    spec:
    rules:
    – host: devops4.ops.service
    http:
    paths:
    – pathType: Prefix
    path: "/"
    backend:
    service:
    name: devops4-ops-service-1-5
    port:
    number: 8080
    —
    kind: Deployment
    apiVersion: apps/v1
    metadata:
    labels:
    k8s-app: devops4-ops-service
    name: devops4-ops-service
    namespace: devops5
    spec:
    replicas: 1
    revisionHistoryLimit: 10
    selector:
    matchLabels:
    k8s-app: devops4-ops-service
    template:
    metadata:
    labels:
    k8s-app: devops4-ops-service
    namespace: devops5
    name: devops4-ops-service
    spec:
    containers:
    – name: devops4-ops-service
    image: 192.168.1.200:8088/devops4/devops4-ops-service:RELEASE-1.1.5-bc630338
    imagePullPolicy: IfNotPresent
    ports:
    – containerPort: 8080
    name: web
    protocol: TCP
    serviceAccountName: devops4-ops-service
    —
    apiVersion: v1
    kind: ServiceAccount
    metadata:
    labels:
    k8s-app: devops4-ops-service
    name: devops4-ops-service
    namespace: devops5
    —
    kind: Service
    apiVersion: v1
    metadata:
    labels:
    k8s-app: devops4-ops-service
    name: devops4-ops-service-1-5
    namespace: devops5
    spec:
    type: ClusterIP
    ports:
    – name: web
    port: 8080
    targetPort: 8080
    selector:
    k8s-app: devops4-ops-service

    创建资源:

    [root@zeyang-nuc-service canary]# kubectl get all -n devops4
    NAME READY STATUS RESTARTS AGE
    pod/devops4-ops-service-1-4-7f97cb665c-vcntl 1/1 Running 0 16m

    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    service/devops4-ops-service-1-4 ClusterIP 10.96.65.65 <none> 8080/TCP 16m

    NAME READY UP-TO-DATE AVAILABLE AGE
    deployment.apps/devops4-ops-service-1-4 1/1 1 1 16m

    NAME DESIRED CURRENT READY AGE
    replicaset.apps/devops4-ops-service-1-4-7f97cb665c 1 1 1 16m

    [root@zeyang-nuc-service canary]# kubectl get all -n devops5
    NAME READY STATUS RESTARTS AGE
    pod/devops4-ops-service-5fbfb57777-6hc62 1/1 Running 0 15m

    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    service/devops4-ops-service-1-5 ClusterIP 10.96.64.251 <none> 8080/TCP 15m

    NAME READY UP-TO-DATE AVAILABLE AGE
    deployment.apps/devops4-ops-service 1/1 1 1 15m

    NAME DESIRED CURRENT READY AGE
    replicaset.apps/devops4-ops-service-5fbfb57777 1 1 1 15m

    测试:

    ## 编辑hosts文件
    192.168.10.100 devops4.ops.service

    for i in {1..10};do curl devops4.ops.service/hello ;done

    基于权重的发布

    <1.19.0

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    name: example-ingress
    namespace: devops4
    annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
    spec:
    rules:
    – host: devops4.ops.service
    http:
    paths:
    – path: /
    backend:
    serviceName: devops4-ops-service
    servicePort: 8080

    Header报头流量分发

    <1.19.0

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    name: example-ingress
    namespace: devops4
    annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "Region"
    nginx.ingress.kubernetes.io/canary-by-header-value: "bj"
    spec:
    rules:
    – host: devops4.ops.service
    http:
    paths:
    – path: /
    backend:
    serviceName: devops4-ops-service
    servicePort: 8080

    >1.19.0

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: example-ingress
    namespace: devops4
    annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "Region"
    nginx.ingress.kubernetes.io/canary-by-header-value: "bj"
    spec:
    rules:
    – host: devops4.ops.service
    http:
    paths:
    – pathType: Prefix
    path: "/"
    backend:
    service:
    name: devops4-ops-service
    port:
    number: 8080
    for i in {1..10};do curl -H "region: bj" devops4.ops.service/hello;done

    根据cookie流量分发

    <1.19.0

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    name: example-ingress
    namespace: devops4
    annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-cookie: "from"
    spec:
    rules:
    – host: devops4.ops.service
    http:
    paths:
    – path: /
    backend:
    serviceName: devops4-ops-service
    servicePort: 8080

    >1.19.0

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: example-ingress
    namespace: devops4
    annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-cookie: "from"
    spec:
    rules:
    – host: devops4.ops.service
    http:
    paths:
    – pathType: Prefix
    path: "/"
    backend:
    service:
    name: devops4-ops-service
    port:
    number: 8080
    [root@master ingress-gray]# curl devops4.ops.service/hello –cookie "from=always"
    1.1.5
    [root@master ingress-gray]# curl devops4.ops.service/hello –cookie "from=a"
    1.1.4
    [root@master ingress-gray]# curl devops4.ops.service/hello –cookie "from=a"
    1.1.4

    赞(0)
    未经允许不得转载:171主机测评 » KubernetesCI/CD实践
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址