草庐IT

持续集成与部署(一)

JJNile 2023-10-19 原文

查看 K8s 版本,Kubeadm 初始化

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.4", GitCommit:"e6c093d87ea4cbb530a7b2ae91e54c0842d8308a", GitTreeState:"clean", BuildDate:"2022-02-16T12:38:05Z", GoVersion:"go1.17.7", Compiler:"gc", Platform:"linux/amd64"}

可以看到上面的版本是 1.23.4,因此下面的 kubernetes-version 需要修改为对应版本,而且 apiserver-advertise-address 修改为主机的 IP

$ kubeadm init \
--apiserver-advertise-address=106.55.37.123 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.23.4 \
--service-cidr=10.1.0.0/16 \
--pod-network-cidr=10.244.0.0/16 \
--ignore-preflight-errors=all  \
--v=6

环境

K8s 集群

Jenkins

Gitlab

Dockerhub

Helm

搭建 K8s 集群

K8s 集群部署在远程服务器部署或者使用阿里云等云平台的 K8s 集群,这里使用一台远程服务器安装的是 k3s,也可以用 kubeadm。

安装 kubesphere

在集群的主节点,执行以下命令开始安装:

$ kubectl apply -f https://github.com/kubesphere/ks-installer/releases/download/v3.2.1/kubesphere-installer.yaml
   
$ kubectl apply -f https://github.com/kubesphere/ks-installer/releases/download/v3.2.1/cluster-configuration.yaml

检查安装日志:

kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l app=ks-install -o jsonpath='{.items[0].metadata.name}') -f

等待安装完成后,通过 30880 端口和并使用默认帐户和密码 (admin/P@88w0rd) 访问 Web 控制台

image.png

PS:期间改了密码后面忘记了。。这里插入一个忘记密码的操作,具体也可以参考官方文档

# <USERNAME> 和 <YOURPASSWORD> 修改为实际用户名和想要修改的密码
$ kubectl patch users <USERNAME> -p '{"spec":{"password":"<YOURPASSWORD>"}}' --type='merge' && kubectl annotate users <USERNAME> iam.kubesphere.io/password-encrypted-

下载镜像 Jenkins

由于 Jenkins 在 dockerHub 上的官方镜像是已经废弃的,所以需要下载最新版,在本机安装

$ docker pull jenkins/jenkins:latest

创建 Jenkins 容器并启用

$ docker run -d -p 8080:8080 --name jenkins jenkins/jenkins:latest

Jenkins 安装和配置

启动后访问 8080 端口,进入到 Jenkins 需要初始化

  • 根据提示去对应目录查看密码并复制进去,
  • 选择推荐安装插件即可,等待安装完成后
  • 创建后台账号密码
  • 地址默认

初始化完成后,安装本地化插件

image.png

由于 Jenkins 重启比较慢,可以通过访问 http://localhost:8080/restart 后点击确认,手动重启服务

之后进入 Jenkins 容器,生成密钥

$ docker exec -it jenkins /bin/bash

# 生成密钥,一路回车即可
$ ssh-keygen

需要将公钥传到 K8s 集群的 master 节点所在服务器

# 将公钥传入 K8s 集群 Master 节点所在的服务器
$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@106.55.37.187

# 测试
$ ssh root@106.55.37.187

创建项目

由于个人电脑装 GitLab 比较消耗资源,因此这里直接用官方的 GitLab 仓库作为测试,在 GitLab 中创建一个私有项目,也可以用 GitHub 或者 Gitee 代替,有条件可以自己搭建 GitLab 或者购买多一个服务器。

代码仓库添加公钥

在 GitLab 中添加【本地】和 【Jenkins 容器】的 SSH 公钥

$ cat ~/.ssh/id_rsa.pub 
image.png

之后测试宿主机下、Jenkins 容器下、K8s 集群是否能够正常克隆,拉取以及推送:

以下为项目所属目录,不存在则创建

  • 宿主机:任意目录

  • Jenkins:/var/jenkins_home/workspace/

  • K8s 集群:/usr/local/k8s/

$ git clone git@gitlab.com:JeaNile/test.git

测试完成后保留项目不进行删除,避免后续上传不了

安装 rsync

由于 scp 无法上传隐藏文件,需要指定才行,因此使用 rsync 代替,进入 Jenkins 容器进行安装

$ apt-get update
$ apt-get install rsync

安装完成后,进程测试

$ mkdir .a
$ rsync -r ./* root@106.55.37.187:/usr/local/k8s/hyperf-learn

保证 .a 目录能上传成功即可

Jenkins 配置项目

之后配置 Jenkins 项目,选择创建自由风格的项目

image.png

配置 Git 仓库

image.png

构建完成执行 shell 查看结果

image.png

点击构建并进入任务中

image.png

查看构建的 Console,可以看到构建完成后输出的 shell 脚本内容

image.png

测试完成后,进行说明大体流程跑通了,接下来讲项目正式构建。

安装 nerdctl 和 buildkit

由于使用的是 K3s,底层使用的是 containerd,不像 docker 那么方便,因此需要通过 nerdctl+buildkitd 来实现镜像构建和镜像管理,如果使用的是 docker,或者觉得麻烦的可以安装 docker 跳过此步骤。

安装 nerdctl

$ wget https://github.com/containerd/nerdctl/releases/download/v0.18.0/nerdctl-0.18.0-linux-amd64.tar.gz
tar -zxvf nerdctl-0.18.0-linux-amd64.tar.gz -C /usr/local/containerd/bin/
ln -s /usr/local/containerd/bin/nerdctl /usr/local/bin/nerdctl

安装完成后查看版本,如果正常输出代表没有问题。

$ nerdctl version

安装 buildkitd

$ wget https://github.com/moby/buildkit/releases/download/v0.10.1/buildkit-v0.10.1.linux-amd64.tar.gz
$ tar -zxvf buildkit-v0.10.1.linux-amd64.tar.gz -C /usr/local/containerd/
$ ln -s /usr/local/containerd/bin/buildkitd /usr/local/bin/buildkitd
$ ln -s /usr/local/containerd/bin/buildctl /usr/local/bin/buildctl

编辑保存 buildkit.socket

$ vim /etc/systemd/system/buildkit.socket

[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit

[Socket]
ListenStream=%t/buildkit/buildkitd.sock

[Install]
WantedBy=sockets.target

编辑保存 buildkit.service

$ vim /etc/systemd/system/buildkit.service

[Unit]
Description=BuildKit
Requires=buildkit.socket
After=buildkit.socketDocumentation=https://github.com/moby/buildkit

[Service]
ExecStart=/usr/local/bin/buildkitd --oci-worker=false --containerd-worker=true

[Install]
WantedBy=multi-user.target
$ systemctl daemon-reload
$ systemctl enable buildkit
$ systemctl start buildkit

如果报 FATA[0000] cannot access containerd socket "/run/containerd/containerd.sock": no such file or directory

将 k3s 的 containerd.sock 软连接到该目录

$ ln -s /run/k3s/containerd/containerd.sock /run/containerd/containerd.sock

登录 dockerhub,并尝试拉取,之后就可以查看到对应的镜像了

$ nerdctl login -u jeanile
..
..
$ nerdctl pull jeanile/php:test
docker.io/jeanile/php:test:                                                       resolved       |++++++++++++++++++++++++++++++++++++++|
manifest-sha256:236613658a40c126080b5a2c0d71564
..
..
$ nerdctl images
REPOSITORY     TAG       IMAGE ID        CREATED        PLATFORM       SIZE         BLOB SIZE
jeanile/php    test      236613658a40    2 weeks ago    linux/amd64    565.4 MiB    166.6 MiB

nerdctl 和 docker 命令差不都,删除测试的镜像,然后准备下一步操作。

helm

在宿主机和 K8s 集群的 master 节点安装

宿主机下进入项目中,执行创建 helm 目录

$ mkdir .helm && cd .helm
$ helm create hyperf-learn # hyperf-learn 为项目名称

执行完成后查看目录结构

$ tree .helm
.helm/
└── hyperf-learn
    ├── Chart.yaml
    ├── templates
    │   ├── deployment.yaml
    │   ├── _helpers.tpl
    │   ├── hpa.yaml
    │   ├── ingress.yaml
    │   ├── NOTES.txt
    │   ├── serviceaccount.yaml
    │   ├── service.yaml
    │   └── tests
    │       └── test-connection.yaml
    └── values.yaml

其中 templates 目录下的是一些常用的 K8s 资源 yaml 模版,values.yaml 则是填写一些镜像、configMap、端口等值,values.yaml 的值会需要覆盖到 templates 目录各个 yaml 下,并且 values.yaml 可以有多个,区分不同环境。

更改 helm 中的 yaml

values.yaml

replicaCount: 1

image:
- repository: 
+ repository: jeanile/hyperf-learn
  pullPolicy: Always
  # Overrides the image tag whose default is the chart appVersion.
- tag: ""
+ tag: "8.1-alpine-sw4.8.8"
..
..

将构建结果输出到 log 查看:

$ helm upgrade --install --debug --dry-run hyperf-learn .helm/hyperf-learn > helm.log 

处理集群报错

当提示:「Error: Kubernetes cluster unreachable: Get "http://localhost:8080/version?timeout=32s": dial tcp [::1]:8080: connect: connection refused」

原因是因为 helm v3 版本不再需要 Tiller,而是直接访问 ApiServer 来与 k8s 交互,通过环境变量 KUBECONFIG 来读取存有 ApiServre 的地址与 token 的配置文件地址,默认地址为 ~/.kube/config,因此需要进行更改 KUBECONFIG 环境变量

$ vim/etc/profile
# 最后一行加入
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml

$ source /etc/profile

创建命名空间

进入集群内部创建项目的命名空间

$ kubectl create namespace hyperf-learn

构建自动化脚本

echo "开始部署"
projectName="hyperf-learn" # 项目名称
branchName="main" # 分支名称
env="release" # 发布环境
k8sHost="106.55.37.187"  #k8s集群的master节点ip 
k8sUser="root" # k8s集群的master节点的登录账号
k8sDeployPath="/usr/local/k8s/" # k8s集群的部署目录
latestCommitID=$(git rev-parse --short HEAD)  # 最近一次提交id
workDir="${k8sDeployPath}${projectName}" # 发布操作的工作目录
imageName="jeanile/${projectName}:${branchName}-${latestCommitID}" # 进行名
k8sNamespace="hyperf-learn"
helmValues="values.yaml"

# 上传文件到k8s服务器
rsync -r ./* ${k8sUser}@${k8sHost}:${workDir}

ssh ${k8sUser}@${k8sHost} <<eof
# 跳转到工作目录
cd ${workDir}
# 构建镜像
nerdctl build -t ${imageName} .
# 登录镜像并推送进行
cat /usr/local/password/dockerhub | nerdctl login -u jeanile --password-stdin 
#推送进行
nerdctl push ${imageName}
# 删除本地镜像
nerdctl rmi ${imageName}
# 退出登录镜像服务器
nerdctl logout

# 构建部署文件并部署
helm upgrade --install --set image.tag=${branchName}-${latestCommitID} -n ${k8sNamespace} ${projectName} .helm/${projectName}/ --values=.helm/${projectName}/${helmValues}

# 清空当前目录下的所有文件
rm -rf *
# 退出
exit
eof
echo "部署完成"

其中主要使用 helm 部署,参数解释:

  • --kube-context:

  • --set image.tag:需要部署的镜像名称

  • -n:选择命名空间

  • --values:指定部署的 values,可以有多个 values 区分环境

部署完成后,查看对应命名空间下的资源:

$ kubectl get all -n hyperf-learn
NAME                                READY   STATUS    RESTARTS   AGE
pod/hyperf-learn-67894b5886-bctjw   1/1     Running   0          9m48s

NAME                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/hyperf-learn   ClusterIP   10.43.92.237   <none>        9501/TCP   9m48s

NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/hyperf-learn   1/1     1            1           9m48s

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/hyperf-learn-67894b5886   1         1         1       9m48s

如果都是 READY 为 1/1 说明没问题了,之前演示为了简单,没有设置对外暴漏的端口,此处可以手动暴漏端口:

$ kubectl expose pod -n hyperf-learn hyperf-learn-67894b5886-bctjw --type=LoadBalancer --port=9501
service/hyperf-learn-67894b5886-bctjw exposed

之后通过浏览器访问:

有关持续集成与部署(一)的更多相关文章

  1. ruby-on-rails - 如何使辅助方法在 Rails 集成测试中可用? - 2

    我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel

  2. ruby-on-rails - 每次我尝试部署时,我都会得到 - (gcloud.preview.app.deploy) 错误响应 : [4] DEADLINE_EXCEEDED - 2

    我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie

  3. ruby-on-rails - 我如何将 Hoptoad 与 DelayedJob 和 DaemonSpawn 集成? - 2

    我一直很高兴地使用DelayedJob习惯用法:foo.send_later(:bar)这会调用DelayedJob进程中对象foo的方法bar。我一直在使用DaemonSpawn在我的服务器上启动DelayedJob进程。但是...如果foo抛出异常,Hoptoad不会捕获它。这是任何这些包中的错误...还是我需要更改某些配置...或者我是否需要在DS或DJ中插入一些异常处理来调用Hoptoad通知程序?回应下面的第一条评论。classDelayedJobWorker 最佳答案 尝试monkeypatchingDelayed::W

  4. ruby-on-rails - Ruby on Rails 可以部署在 Azure 网站上吗? - 2

    我可以在Azure网站上部署RubyonRails吗? 最佳答案 还没有。目前仅支持.NET和PHP。 关于ruby-on-rails-RubyonRails可以部署在Azure网站上吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/12964010/

  5. jenkins部署1--jenkins+gitee持续集成 - 2

    前置步骤我们都操作完了,这篇开始介绍jenkins的集成。话不多说,看操作1、登录进入jenkins后会让你选择安装插件,选择第一个默认的就行。安装完成后设置账号密码,重新登录。2、配置JDK和Git都需要执行路径,所以需要先把执行路径找到,先进入服务器的docker容器,2.1JDK的路径root@69eef9ee86cf:/usr/bin#echo$JAVA_HOME/usr/local/openjdk-82.2Git的路径root@69eef9ee86cf:/#whichgit/usr/bin/git3、先配置JDK和Git。点击:ManageJenkins>>GlobalToolCon

  6. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  7. Ruby,使用包含 TK GUI 的 ocra 部署一个 exe - 2

    Ocra无法处理需要“tk”的应用程序require'tk'puts'nope'用奥克拉http://github.com/larsch/ocra不起作用(如链接中的一个问题所述)问题:https://github.com/larsch/ocra/issues/29(Ocra是1.9的"new"rubyscript2exe,本质上它用于将rb脚本部署为可执行文件)唯一的问题似乎是缺少tcl的DLL文件我不认为这是一个问题据我所知,问题是缺少tk的DLL文件如果它们是已知的,则可以在执行ocra时将它们包括在内有没有办法知道tk工作所需的DLL依赖项? 最佳答

  8. ruby-on-rails - NameError(未初始化常量 Unzipper::Zip)但仅在 Heroku 部署(Rails)上 - 2

    我有一个类unzipper.rb,它使用Rubyzip解压文件。在我的本地环境中,我可以成功解压缩文件,而无需使用require'zip'明确包含依赖项但是在Heroku上,我得到一个NameError(uninitializedconstantUnzipper::Zip)我只能通过使用明确的require来解决问题:为什么这在H​​eroku环境中是必需的,但在本地主机上却不是?我的印象是Rails自动需要所有gem。app/services/unzipper.rbrequire'zip'#OnlyrequiredforHeroku.Workslocallywithout!class

  9. ruby - Sinatra session 未按预期持续 - 2

    我正在尝试使用Sinatra中的重定向和session在网站周围传递一些数据。这是一个简化的示例,使用PrettyPrint进行调试:require'pp'require'rubygems'require'sinatra'enable:sessionsget'/'dosession[:foo]='12345'puts'session1'ppsessionredirectto('/redir')endget'/redir'doputs'session2'ppsession'helloworld'end查看Thin的输出,我看到:>>Listeningon0.0.0.0:4567,CTRL

  10. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

    出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

随机推荐