草庐IT

基于 Sealos 的镜像构建能力,快速部署自定义 k8s 集群

运维技术帮 2023-03-28 原文

Sealos 是一个快速构建高可用 k8s 集群的命令行工具,该工具部署时会在第一个 k8s master 节点部署 registry 服务(sealos.hub),该域名通过 hosts 解析到第一个 k8s master 节点 ip;基于内核 ipvs 对 apiserver 进行负载均衡,其默认虚拟 ip 地址为 10.103.97.2(apiserver.cluster.local),所有 k8s Worker 节点通过该虚拟 ip 访问 kube-apiserver

建议通过 PC 端访问本文章,以获取更好阅读体验,由于精力有限,该文章的后续更新、完善仅限于站点 运维技术帮 (https://ywjsbang.com) 望理解 !!

环境配置

# 各组件版本
CenOS7.9 Min(Kernel 5.4.220)
Sealos:v4.1.3
flannel:v0.20.0
kubernetes:v1.25.3
kubernetes-dashboard:v2.7.0

# 设置各节点主机名与 IP 地址映射关系
cat >> /etc/hosts << EOF
192.168.31.51 t1
192.168.31.52 t2
192.168.31.53 t3
192.168.31.54 t4
192.168.31.55 t5
EOF

# 安装依赖
yum install socat conntrack-tools -y

flanneld 默认容器

flanneld 默认配置清单 kube-flannel.yml 中的容器配置,简要说明如下

initContainers:
  docker.io/rancher/mirrored-flannelcni-flannel-cni-plugin:v1.1.0   # 通过卷挂载方式,将 CNI 插件 /opt/cni/bin/flannel 挂载到宿主机对应位置
  docker.io/rancher/mirrored-flannelcni-flannel:v0.20.0             # 通过卷挂载方式,将配置目录 /etc/cni/net.d 和 /etc/kube-flannel/ 挂载到宿主机对应位置
containers
  docker.io/rancher/mirrored-flannelcni-flannel:v0.20.0             # flanneld 守护进程

自定义 kube-flannel.yml

修改 pod 网段

修改 kube-flannel.yml 配置,其默认 pod 网段为 10.244.0.0/16,可按需修改
wget https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml -C ./manifests/

kind: ConfigMap
apiVersion: v1
metadata:
  name: kube-flannel-cfg
  namespace: kube-flannel
  labels:
    tier: node
    app: flannel
data:
  ...
  ...
  net-conf.json: |
    {
      "Network": "10.15.0.0/16",     # pod 网段, 该网段必须与 kube-controller-manager 配置参数 --cluster-cidr 值匹配
      "Backend": {
        "Type": "vxlan"
      }
    }

添加 init 容器

修改 kube-flannel.yml 添加 Init 容器 install-cni-plugin-sealos,其作用是通过卷挂载,将宿主机目录 /opt/cni/bin 挂载到容器目录 /opt/cni/bin

initContainers:
- name: install-cni-plugin-sealos
  image: docker.io/labring/docker-cni-plugins:v1.1.0
  command: ["/bin/sh"]
  args: ["-c", "cp -f /cni-plugins/* /opt/cni/bin/"]
  volumeMounts:
  - name: cni-plugin-sealos
    mountPath: /opt/cni/bin
# 定义卷 cni-plugin-sealos
volumes:
- name: cni-plugin-sealos
  hostPath:
    path: /opt/cni/bin

部署 Sealos

wget  https://github.com/labring/sealos/releases/download/v4.1.3/sealos_4.1.3_linux_amd64.tar.gz  && \
tar -zxvf sealos_4.1.3_linux_amd64.tar.gz sealos &&  \
chmod +x sealos && mv sealos /usr/bin

创建 Dockerfile

1、创建镜像构建配置文件,目录 registry 构建时会自动生成,用于存放构建该镜像时依赖的其它镜像信息 !!

cat > Dockerfile << EOF
FROM scratch
COPY manifests ./manifests
COPY registry ./registry
CMD ["kubectl apply -f manifests/kube-flannel.yml"]
EOF

2、使用 sealos 打包构建镜像

# 执行自定义镜像构建
sealos build -f Dockerfile -t it123.me/flannel:v0.20.0 .
# 查看本地镜像
sealos images
# > REPOSITORY                     TAG       IMAGE ID       CREATED          SIZE
# > it123.me/flannel               v0.20.0   6f0563e3df50   19 minutes ago   72.9 MB
# > docker.io/labring/kubernetes   v1.25.3   6f1de58f84c4   8 days ago       589 MB
# > docker.io/labring/calico       v3.24.1   e2122fc58fd3   8 weeks ago      354 MB
# > docker.io/labring/helm         v3.8.2    1123e8b4b455   3 months ago     45.1 MB
# > docker.io/labring/calico       v3.22.1   29516dc98b4b   4 months ago     546 MB

生成 Clusterfile

1、生成集群配置文件

sealos gen labring/kubernetes:v1.25.3 it123.me/flannel:v0.20.0 --masters 192.168.31.51 --nodes 192.168.31.54 -p rootroot > Clusterfile
# 参数解析
--masters    # 集群 master 节点,可逗号分隔指定多个
--nodes      # 集群 worker 节点,可逗号分隔指定多个
-p rootroot  # 部署时的 ssh 密码,默认 ssh 用户 root,可通过 -u 参数修改
# 创建集群时需要的镜像
it123.me/flannel:v0.20.0
labring/kubernetes:v1.25.3

2、配置文件 Clusterfile 内容如下

apiVersion: apps.sealos.io/v1beta1
kind: Cluster
metadata:
  creationTimestamp: null
  name: default
spec:
  hosts:
  - ips:
    - 192.168.31.51:22
    roles:
    - master
    - amd64
  - ips:
    - 192.168.31.54:22
    roles:
    - node
    - amd64
  image:
  - labring/kubernetes:v1.25.3
  - it123.me/flannel:v0.20.0
  ssh:
    passwd: rootroot
    pk: /root/.ssh/id_rsa
    port: 22
status: {}

3、向 Clusterfile 文件尾行添加如下内容,以自定义集群的 pod 和 service 网段,将会分别用于设置组件 kube-controller-manager 启动参数 --cluster-cidr 和 --service-cluster-ip-range 的值

---
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
networking:
  podSubnet: 10.15.0.0/16               # 该值必须与 flanneld 配置清单 kube-flannel.yaml 中的配置一致,
  serviceSubnet: 10.16.0.0/16

创建集群

1、基于如上配置创建集群

# 创建集群, 并验证节点状态
sealos apply -f Clusterfile
kubectl get node -o wide
# > NAME   STATUS   ROLES           AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION                CONTAINER-RUNTIME
# > t1     Ready    control-plane   41m   v1.25.3   192.168.31.51   <none>        CentOS Linux 7 (Core)   5.4.220-1.el7.elrepo.x86_64   containerd://1.6.2
# > t4     Ready    <none>          41m   v1.25.3   192.168.31.54   <none>        CentOS Linux 7 (Core)   5.4.220-1.el7.elrepo.x86_64   containerd://1.6.2

2、在需要执行集群管理的节点添加 kubeconfig 配置

mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

集群维护

添加 Work 节点

1、添加工作节点 192.168.31.55

sealos add --nodes 192.168.31.55        # 执行 sealos delete --nodes 192.168.31.50 删除节点
kubectl get node -o wide
# > NAME   STATUS   ROLES           AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION                CONTAINER-RUNTIME
# > t1     Ready    control-plane   41m   v1.25.3   192.168.31.51   <none>        CentOS Linux 7 (Core)   5.4.220-1.el7.elrepo.x86_64   containerd://1.6.2
# > t4     Ready    <none>          41m   v1.25.3   192.168.31.54   <none>        CentOS Linux 7 (Core)   5.4.220-1.el7.elrepo.x86_64   containerd://1.6.2
# > t5     Ready    <none>          38s   v1.25.3   192.168.31.55   <none>        CentOS Linux 7 (Core)   5.4.221-1.el7.elrepo.x86_64   containerd://1.6.2

2、验证 pod 、service 网段

kubectl get pod,svc -o wide -A
# > NAMESPACE      NAME                             READY   STATUS    RESTARTS   AGE     IP              NODE   NOMINATED NODE   READINESS GATES
# > kube-system    pod/coredns-565d847f94-4lr8z     1/1     Running   0          44m     10.15.0.5       t8     <none>           <none>
# > kube-system    pod/coredns-565d847f94-65v47     1/1     Running   0          44m     10.15.0.4       t8     <none>           <none>

# > NAMESPACE     NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE   SELECTOR
# > default       service/kubernetes   ClusterIP   10.16.0.1    <none>        443/TCP                  44m   <none>
# > kube-system   service/kube-dns     ClusterIP   10.16.0.10   <none>        53/UDP,53/TCP,9153/TCP   44m   k8s-app=kube-dns

添加 Master 节点

1、添加控制器节点 192.168.31.52 和 192.168.31.53

sealos add --masters 192.168.31.52,192.168.31.53

执行该操作时,sealos 会自动在对应 master 节点添加 etcd 服务,但是集群 kube-apiserver 配置项 --etcd-servers 并未更新,因此、还需到各 master 节点更新配置文件 /etc/kubernetes/manifests/kube-apiserver.yaml,设置配置项--etcd-servers=https://192.168.31.51:2379,https://192.168.31.52:2379,https://192.168.31.53:2379 实现 etcd 服务的高可用
备注: 该配置项修改后会自动生效,因为 k8s 会自动监视这些配置文件,当被修改时,k8s 会自动重建对应节点 kube-apiserver 的 pod 实例

2、验证节点

kubectl get node -o wide
# > NAME   STATUS   ROLES           AGE     VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION                CONTAINER-RUNTIME
# > t1     Ready    control-plane   54m     v1.25.3   192.168.31.51   <none>        CentOS Linux 7 (Core)   5.4.220-1.el7.elrepo.x86_64   containerd://1.6.2
# > t2     Ready    control-plane   2m      v1.25.3   192.168.31.52   <none>        CentOS Linux 7 (Core)   5.4.220-1.el7.elrepo.x86_64   containerd://1.6.2
# > t3     Ready    control-plane   2m      v1.25.3   192.168.31.53   <none>        CentOS Linux 7 (Core)   5.4.220-1.el7.elrepo.x86_64   containerd://1.6.2
# > t4     Ready    <none>          54m     v1.25.3   192.168.31.54   <none>        CentOS Linux 7 (Core)   5.4.220-1.el7.elrepo.x86_64   containerd://1.6.2
# > t5     Ready    <none>          13m     v1.25.3   192.168.31.55   <none>        CentOS Linux 7 (Core)   5.4.220-1.el7.elrepo.x86_64   containerd://1.6.2

部署 dashboard

sealos run --cluster demo01 labring/kubernetes-dashboard:v2.7.0

清理集群

sealos reset

Q&A

1、error execution phase control-plane-prepare/certs: error creating PKI assets: failed to write or validate certificate "apiserver": certificate apiserver is invalid: x509: certificate is valid for 192.168.31.53, 10.96.0.1, 10.103.97.2, 127.0.0.1, 192.168.31.51, 192.168.31.52, not 10.16.0.1 (生成的 apiserver.cert 证书不包含 10.16.0.1)
使用 sealos apply -f Clusterfile 创建集群时,并未将 Clusterfile 中 kubeadm 的自定义集群配置 ClusterConfiguration 添加至 .sealos/demo01/Clusterfile 文件,因此当使用如下命令添加 master 节点时报错提示,生成的 apiserver.cert 证书中不包含自定义的 service 网段 ip

# 使用默认配置文件 .sealos/demo01/Clusterfile
sealos add --cluster demo01 --masters 192.168.31.52,192.168.31.53

解决方案:在文件 .sealos/demo01/Clusterfile 尾行添加如下配置, 再执行 master 节点添加命令:

---
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
networking:
  podSubnet: 10.15.0.0/16
  serviceSubnet: 10.16.0.0/16

2、若执行 sealos apply -f Clusterfile 操作时,提示 no change apps | nodes, 则需要用 Clusterfile 覆盖 /root/.sealos/default/Clusterfile 文件
cp Clusterfile /root/.sealos/default/Clusterfile 或删除 /root/.sealos/default/Clusterfile 状态部分 status:{} 或 sealos reset

3、socat not found in system path !!
集群所有节点安装 yum install socat -y

4、ERROR [2022-11-02 20:11:43] >> Port: 10249 occupied. Please turn off port service.
本次安装受到环境残留干扰,需清理节点环境

5、error execution phase preflight: couldn't validate the identity of the API Server: could not find a JWS signature in the cluster-info ConfigMap for token ID "fk63j7"
新建 default 集群时,执行 sealos reset --cluster default 清除之前创建的集群证书及其它信息

重 要 提 醒: 由于笔者时间、视野、认知有限,本文难免出现错误、疏漏等问题,期待各位读者朋友、业界大佬指正交流, 共同进步 !!

有关基于 Sealos 的镜像构建能力,快速部署自定义 k8s 集群的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  3. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  4. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  5. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  6. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  7. ruby - 如何在 Grape 中定义哈希数组? - 2

    我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>

  8. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  9. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  10. ruby-on-rails - 如何生成传递一些自定义参数的 `link_to` URL? - 2

    我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些

随机推荐