k8s与CICD--借助scp插件实现非容器项目的部署

前言

最近连续996加班,一直没有时间完成drone系列文章。drone-wechat插件实现了一半,由于企业微信token申请比较麻烦,所以也没有进展。今天抽出时间,研究了一下scp插件,主要目的是实现非容器项目的部署。其实就是借助scp插件,将构建好的go项目可执行文件和配置文件发布到指定主机上。本项目依旧基于baa-cicd项目。

.drone.yml

直接上.drone.yml 文件

workspace:
  base: /go
  path: src/gogs.xxx.com/baa-cicd
pipeline:
  build:
    image: golang:latest
    commands:
      - go build -o baa-cicd
  # publish:
  #   image: plugins/docker
  #   registry: registry.xxx.com
  #   repo: registry.xxx.com/test/baa-cicd
  #   tags: latest
  #   secrets: [ docker_username, docker_password ]
  #   insecure: true
  scp:
    image: appleboy/drone-scp
    host: 10.xx.xx.170
    username: root
    key_path: deploy_rsa
    rm: true
    target:
     - /rc/local
    source:
     - baa-cicd 
  ssh:
    image: appleboy/drone-ssh
    host:10.xx.xx.170
    username: root
    key_path: deploy_rsa
    script:
      - supervisorctl -c /rc/conf/supervisord.conf reload
  notify:
    image: plugins/slack
    webhook: https://hooks.slack.com/services/xxx/xxx/xxx
    channel: dev
    template: >
      {{#success build.status}}
        build {{build.number}} succeeded. Good job.
      {{else}}
        build {{build.number}} failed. Fix me please.
      {{/success}}
  • scp 插件基于ssh实现。所以关键是ssh的相关设置比较重要。比如允许root用户ssh登录,以及密码和rsa秘钥几种登录方式的配置。我们这边基本上都是openssh,所以可以先了解一下openssh的设置。这边我主要允许root登录,编辑 /etc/ssh/sshd_config,注意:PermitRootLogin yes。
  • 关于rsa秘钥登录,这边就不做更多介绍了。
  • 此处deploy_rsa是放置了ssh登录秘钥的文件。
  • 当然光是拷贝了文件,并不能完成部署。所以此处引用了另外一个插件ssh,简单假设项目是用supervisior管理进程,那么ssh执行supervisorctl -c /rc/conf/supervisord.conf reload命令。完成新项目的部署。
  • 其实此处再引入一个插件并不是特别合适,感觉有点麻烦,其实个人感觉scp引入一个script参数,比较好,执行一些拷贝完成以后的操作指令。

scp 插件介绍

配置简介:

scp插件通过ssh拷贝文件到目标主机,下面是如何在drone中使用的sample

pipeline:
  scp:
    image: appleboy/drone-scp
    host: example.com
    target: /home/deploy/web
    source: release.tar.gz

自定义用户名和密码以及端口的配置示例:

pipeline:
  scp:
    image: appleboy/drone-scp
    host: example.com
+   username: appleboy
+   password: 12345678
+   port: 4430
    target: /home/deploy/web
    source: release.tar.gz

项目需要从多个文件拷贝到目的主机多个文件的配置示例:

pipeline:
  scp:
    image: appleboy/drone-scp
    host: example.com
    target:
+     - /home/deploy/web1
+     - /home/deploy/web2
    source:
+     - release_1.tar.gz
+     - release_2.tar.gz

此处注意的就是一一对应关系。我理解的场景是,在项目中配置文件和可执行文件处于不同的文件夹下,或多个配置文件。

一般项目部署为了高可用,会将项目部署在多台主机上,所以下面是一个多目标主机的配置示例:

pipeline:
  scp:
    image: appleboy/drone-scp
-   host: example.com
+   host:
+     - example1.com
+     - example2.com
    target: /home/deploy/web
    source: release.tar.gz

当然文件比较多的时候,如果一一写出就过于麻烦了,该scp支持模式匹配:

pipeline:
  scp:
    image: appleboy/drone-scp
    host:
      - example1.com
      - example2.com
    target: /home/deploy/web
    source:
-     - release/backend.tar.gz
-     - release/images.tar.gz
+     - release/*.tar.gz

当然依旧可以定义触发条件:

pipeline:
  scp:
    image: appleboy/drone-scp
    host: example.com
    target: /home/deploy/web
    source: release.tar.gz
+   when:
+     status: success
+     event: tag

参数简介:

host
目的主机的域名或是ip

port
目标主机的ssh端口

username
目的主机ssh用户名

password
目的主机ssh密码

key
访问主机的秘钥

target
目的主机目的文件路径

source
想要拷贝的文件列表

rm
在拷贝之前删除原文件的开关

timeout
建立tcp连接的最大超时时间

插件源码

该插件作者貌似是一个台湾同胞。贡献了其他很多的drone插件,比如k8s 和telegram。这里源码地址,大致可以看看,主要是了解drone插件的编写思路。等不忙的时候,继续完成我的drone-wechat。

<think> 我们面对的错误信息是:在创建 'deploy/cicd-demo-dev.yaml' 文件时出现 'namespaces "k8s-cicd-dev" not found'。这意味着我们尝试在一个不存在的命名空间(namespace)中创建资源。 解决步骤: 1. 确认命名空间是否存在:使用命令 `kubectl get namespace` 或 `kubectl get ns` 查看当前集群中存在的命名空间。 2. 如果命名空间不存在,则需要创建它。创建命名空间的YAML文件示例(如k8s-cicd-dev-ns.yaml): ```yaml apiVersion: v1 kind: Namespace metadata: name: k8s-cicd-dev ``` 然后使用 `kubectl apply -f k8s-cicd-dev-ns.yaml` 来创建。 3. 如果命名空间已经存在,但错误仍然出现,请检查YAML文件中的命名空间拼写是否正确(注意大小写,命名空间名称是大小写敏感的)。 4. 在创建资源(如deployment)的YAML文件(即deploy/cicd-demo-dev.yaml)中,确保在metadata部分正确指定了命名空间: ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: cicd-demo namespace: k8s-cicd-dev # 这里指定命名空间 ... ``` 5. 如果是在CI/CD流程中(例如Jenkins)执行,请确保执行kubectl命令的上下文(context)正确,并且有权限访问该命名空间。 注意:在引用[2]中,用户遇到了连接问题(The connection to the server localhost:8080 was refused),这通常意味着kubectl没有正确配置。因此,请确保在运行命令的环境中正确配置了kubeconfig文件(通常位于~/.kube/config),或者通过环境变量KUBECONFIG指定。 针对用户提到的引用[1]中的Jenkins流水线脚本,他们使用了SSH到远程主机(k8s master)然后执行脚本。因此,请确保在远程主机上(k8s master)已经正确配置了kubectl,并且有权限操作命名空间。 总结解决方案: - 创建命名空间(如果不存在) - 检查YAML文件中的命名空间名称 - 确保kubectl配置正确并且有权限 下面,我们将按照上述步骤详细说明。 步骤1:检查命名空间是否存在 在远程主机(k8s master)上执行: ```bash kubectl get namespace k8s-cicd-dev ``` 如果返回找不到,则创建。 步骤2:创建命名空间 编写一个YAML文件,比如`k8s-cicd-dev-ns.yaml`,内容如上所示,然后运行: ```bash kubectl apply -f k8s-cicd-dev-ns.yaml ``` 步骤3:验证命名空间已创建 ```bash kubectl get ns ``` 确认列表中出现了k8s-cicd-dev。 步骤4:检查部署文件 确保`deploy/cicd-demo-dev.yaml`文件中指定了正确的命名空间(即`namespace: k8s-cicd-dev`),并且没有拼写错误。 步骤5:在CI/CD脚本中应用部署 在Jenkins的SSH步骤中,执行脚本应该包含应用部署文件的命令: ```bash kubectl apply -f deploy/cicd-demo-dev.yaml ``` 注意:这个命令需要在kubectl配置正确的环境下运行。 如果之前是因为命名空间不存在而失败,创建命名空间后再次运行部署即可。 另外,引用[2]中的错误提示连接被拒绝,这可能是由于没有配置kubectl的上下文(context)或者kubeconfig文件没有正确设置。在Jenkins的远程脚本中,需要确保kubectl可以访问集群,可以通过以下命令检查: ```bash kubectl cluster-info ``` 如果出现问题,需要配置kubeconfig。通常,在master节点上,kubeconfig位于/etc/kubernetes/admin.conf,我们可以将其复制到Jenkins用户的家目录下(比如~/.kube/config),或者设置环境变量: ```bash export KUBECONFIG=/etc/kubernetes/admin.conf ``` 然后再执行kubectl命令。 因此,在Jenkins的流水线中,可能需要添加配置kubeconfig的步骤,例如: ```groovy stage('Remote SSH') { writeFile file: '/opt/project/k8s-deploy-springboot-demo.sh', text: ''' export KUBECONFIG=/etc/kubernetes/admin.conf # 确保kubectl使用正确的配置文件 kubectl get ns # 检查命名空间 kubectl apply -f deploy/cicd-demo-dev.yaml # 部署 ''' sshScript remote: remote, script: "/opt/project/k8s-deploy-springboot-demo.sh" } ``` 注意:上面的脚本中,我们假设在远程主机上(k8s master)的/etc/kubernetes/admin.conf文件存在并且配置正确。 如果问题仍然存在,请检查远程主机上的kubectl配置,以及用户是否有权限在命名空间k8s-cicd-dev中创建资源。 综上所述,解决该错误的重点是确保命名空间存在,并且kubectl配置正确。 </think> ### 解决 "namespaces k8s-cicd-dev not found" 错误 这个错误表明 Kubernetes 集群中不存在名为 `k8s-cicd-dev` 的命名空间(Namespace)。以下是完整的解决步骤: #### 步骤 1:验证命名空间是否存在 在 Kubernetes 主节点执行: ```bash kubectl get namespaces | grep k8s-cicd-dev ``` 如果无输出,说明命名空间不存在。 #### 步骤 2:创建缺失的命名空间 创建命名空间定义文件 `k8s-cicd-dev-ns.yaml`: ```yaml apiVersion: v1 kind: Namespace metadata: name: k8s-cicd-dev labels: env: development ``` 应用配置: ```bash kubectl apply -f k8s-cicd-dev-ns.yaml ``` 或者在 CI/CD 流水线中直接创建(如 Jenkinsfile): ```groovy stage('Create Namespace') { sshScript remote: remote, script: """ kubectl create namespace k8s-cicd-dev """ } ``` #### 步骤 3:检查部署文件的命名空间配置 确保 `deploy/cicd-demo-dev.yaml` 文件中明确指定命名空间: ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: cicd-demo namespace: k8s-cicd-dev # 必须存在此行 spec: ... ``` #### 步骤 4:验证 RBAC 权限 检查服务账户是否具有操作该命名空间的权限: ```bash kubectl auth can-i create deployments --namespace=k8s-cicd-dev ``` 如果返回 `no`,需添加 RBAC 规则: ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: cicd-access namespace: k8s-cicd-dev subjects: - kind: ServiceAccount name: cicd-service-account roleRef: kind: ClusterRole name: edit apiGroup: rbac.authorization.k8s.io ``` #### 步骤 5:解决上下文配置问题(引用 [2] 的延伸) 如果出现连接错误(如引用 [2] 的 `connection refused`): ```bash mkdir -p $HOME/.kube sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config export KUBECONFIG=$HOME/.kube/config ``` #### 常见原因总结 1. **命名空间未创建**:这是最直接的原因(占 90% 案例) 2. **YAML 文件未指定命名空间**:metadata 部分缺少 `namespace` 字段 3. **权限问题**:服务账户无权操作目标命名空间 4. **上下文配置错误**:kubectl 未正确配置(如引用 [2]) > **注意**:命名空间名称需严格匹配,包括大小写(Kubernetes 区分大小写)。 --- ### 相关问题 1. 如何在 Kubernetes 中批量管理多个命名空间? 2. 命名空间和 RBAC 权限如何配合实现最小权限原则? 3. 在 CI/CD 流水线中如何动态创建 Kubernetes 资源? 4. 如何诊断和解决 `kubectl` 的 `connection refused` 错误? 5. Kubernetes 命名空间 Docker 命名空间有何本质区别?[^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值